Merge branch 'jk/guess-repo-name-regression-fix'
authorJunio C Hamano <gitster@pobox.com>
Wed, 19 Aug 2015 21:48:54 +0000 (14:48 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 19 Aug 2015 21:48:54 +0000 (14:48 -0700)
"git clone $URL" in recent releases of Git contains a regression in
the code that invents a new repository name incorrectly based on
the $URL.  This has been corrected.

* jk/guess-repo-name-regression-fix:
  clone: use computed length in guess_dir_name
  clone: add tests for output directory

353 files changed:
.gitignore
Documentation/RelNotes/2.4.6.txt [new file with mode: 0644]
Documentation/RelNotes/2.4.7.txt [new file with mode: 0644]
Documentation/RelNotes/2.4.8.txt [new file with mode: 0644]
Documentation/RelNotes/2.5.0.txt [new file with mode: 0644]
Documentation/RelNotes/2.6.0.txt [new file with mode: 0644]
Documentation/cmd-list.perl
Documentation/config.txt
Documentation/diff-options.txt
Documentation/git-am.txt
Documentation/git-bisect.txt
Documentation/git-blame.txt
Documentation/git-branch.txt
Documentation/git-cat-file.txt
Documentation/git-check-ref-format.txt
Documentation/git-checkout.txt
Documentation/git-describe.txt
Documentation/git-fast-import.txt
Documentation/git-for-each-ref.txt
Documentation/git-format-patch.txt
Documentation/git-fsck.txt
Documentation/git-log.txt
Documentation/git-merge.txt
Documentation/git-p4.txt
Documentation/git-pull.txt
Documentation/git-rebase.txt
Documentation/git-reflog.txt
Documentation/git-rev-list.txt
Documentation/git-rev-parse.txt
Documentation/git-send-email.txt
Documentation/git-status.txt
Documentation/git-tag.txt
Documentation/git-tools.txt
Documentation/git-update-index.txt
Documentation/git-update-ref.txt
Documentation/git-verify-commit.txt
Documentation/git-verify-tag.txt
Documentation/git-worktree.txt [new file with mode: 0644]
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/gitrepository-layout.txt
Documentation/gitweb.conf.txt
Documentation/howto/new-command.txt
Documentation/i18n.txt
Documentation/pretty-options.txt
Documentation/rev-list-options.txt
Documentation/revisions.txt
Documentation/technical/api-argv-array.txt
Documentation/technical/api-parse-options.txt
Documentation/technical/api-ref-iteration.txt
Documentation/technical/api-remote.txt
Documentation/technical/http-protocol.txt
Documentation/technical/index-format.txt
Documentation/technical/protocol-capabilities.txt
Documentation/technical/racy-git.txt
GIT-VERSION-GEN
Makefile
RelNotes
advice.c
advice.h
archive-zip.c
archive.c
argv-array.c
argv-array.h
bisect.c
bisect.h
branch.c
branch.h
builtin.h
builtin/add.c
builtin/am.c [new file with mode: 0644]
builtin/apply.c
builtin/blame.c
builtin/branch.c
builtin/cat-file.c
builtin/checkout-index.c
builtin/checkout.c
builtin/clean.c
builtin/clone.c
builtin/commit.c
builtin/config.c
builtin/count-objects.c
builtin/describe.c
builtin/fast-export.c
builtin/fetch.c
builtin/fmt-merge-msg.c
builtin/for-each-ref.c
builtin/fsck.c
builtin/gc.c
builtin/index-pack.c
builtin/init-db.c
builtin/log.c
builtin/merge.c
builtin/name-rev.c
builtin/pack-objects.c
builtin/patch-id.c
builtin/prune.c
builtin/pull.c [new file with mode: 0644]
builtin/receive-pack.c
builtin/reflog.c
builtin/remote.c
builtin/repack.c
builtin/replace.c
builtin/rev-list.c
builtin/rev-parse.c
builtin/send-pack.c
builtin/shortlog.c
builtin/show-branch.c
builtin/show-ref.c
builtin/tag.c
builtin/unpack-objects.c
builtin/update-index.c
builtin/update-ref.c
builtin/verify-commit.c
builtin/verify-tag.c
builtin/worktree.c [new file with mode: 0644]
bulk-checkin.c
cache-tree.c
cache-tree.h
cache.h
combine-diff.c
command-list.txt
commit-slab.h
commit.c
commit.h
compat/mingw.c
compat/mingw.h
config.c
config.mak.uname
configure.ac
contrib/completion/git-completion.bash
contrib/completion/git-completion.tcsh
contrib/completion/git-prompt.sh
contrib/examples/git-am.sh [moved from git-am.sh with 93% similarity]
contrib/examples/git-pull.sh [moved from git-pull.sh with 68% similarity]
contrib/hooks/multimail/CHANGES
contrib/hooks/multimail/README
contrib/hooks/multimail/README.Git
contrib/hooks/multimail/git_multimail.py
contrib/hooks/multimail/migrate-mailhook-config
contrib/hooks/multimail/post-receive.example [moved from contrib/hooks/multimail/post-receive with 74% similarity]
contrib/hooks/pre-auto-gc-battery
contrib/subtree/git-subtree.sh
contrib/subtree/git-subtree.txt
contrib/subtree/t/t7900-subtree.sh
convert.c
copy.c
daemon.c
date.c
diff-lib.c
diff.c
diff.h
dir.c
dir.h
environment.c
ewah/bitmap.c
ewah/ewah_bitmap.c
ewah/ewah_io.c
ewah/ewok.h
fast-import.c
fetch-pack.c
fsck.c
fsck.h
generate-cmdlist.perl [new file with mode: 0755]
generate-cmdlist.sh [deleted file]
gettext.c
git-bisect.sh
git-compat-util.h
git-cvsimport.perl
git-mergetool--lib.sh
git-mergetool.sh
git-p4.py
git-rebase--am.sh
git-rebase--interactive.sh
git-rebase--merge.sh
git-rebase.sh
git-send-email.perl
git-sh-setup.sh
git-stash.sh
git.c
gpg-interface.c
gpg-interface.h
help.c
hex.c
http-backend.c
http.c
ll-merge.c
lockfile.c
lockfile.h
log-tree.c
mergetools/winmerge [new file with mode: 0644]
notes-merge.c
notes.c
pack-bitmap.c
pager.c
parse-options-cb.c
parse-options.c
parse-options.h
path.c
perl/Git.pm
pkt-line.c
po/bg.po
po/ca.po
po/de.po
po/fr.po
po/git.pot
po/ru.po
po/sv.po
po/vi.po
po/zh_CN.po
pretty.c
progress.c
reachable.c
read-cache.c
ref-filter.c [new file with mode: 0644]
ref-filter.h [new file with mode: 0644]
reflog-walk.c
reflog-walk.h
refs.c
refs.h
remote-testsvn.c
remote.c
remote.h
replace_object.c
revision.c
revision.h
run-command.c
run-command.h
send-pack.c
server-info.c
setup.c
sha1_file.c
sha1_name.c
shallow.c
split-index.c
strbuf.c
strbuf.h
submodule.c
t/lib-git-p4.sh
t/lib-rebase.sh
t/perf/p5310-pack-bitmaps.sh
t/perf/p7300-clean.sh [new file with mode: 0755]
t/t0002-gitfile.sh
t/t0021-conversion.sh
t/t0027-auto-crlf.sh
t/t0040-parse-options.sh
t/t0060-path-utils.sh
t/t0090-cache-tree.sh
t/t0302-credential-store.sh
t/t1006-cat-file.sh
t/t1090-sparse-checkout-scope.sh [new file with mode: 0755]
t/t1400-update-ref.sh
t/t1402-check-ref-format.sh
t/t1410-reflog.sh
t/t1411-reflog-show.sh
t/t1430-bad-ref-name.sh
t/t1450-fsck.sh
t/t1501-worktree.sh
t/t1502-rev-parse-parseopt.sh
t/t1503-rev-parse-verify.sh
t/t1507-rev-parse-upstream.sh
t/t1509-root-worktree.sh
t/t1510-repo-setup.sh
t/t1514-rev-parse-push.sh [new file with mode: 0755]
t/t2019-checkout-ambiguous-ref.sh
t/t2025-worktree-add.sh [new file with mode: 0755]
t/t2026-prune-linked-checkouts.sh [new file with mode: 0755]
t/t3033-merge-toplevel.sh [new file with mode: 0755]
t/t3200-branch.sh
t/t3210-pack-refs.sh
t/t3402-rebase-merge.sh
t/t3404-rebase-interactive.sh
t/t3415-rebase-autosquash.sh
t/t3418-rebase-continue.sh
t/t3701-add-interactive.sh
t/t3901-i18n-patch.sh
t/t3903-stash.sh
t/t3904-stash-patch.sh
t/t4014-format-patch.sh
t/t4015-diff-whitespace.sh
t/t4018-diff-funcname.sh
t/t4018/fountain-scene [new file with mode: 0644]
t/t4136-apply-check.sh
t/t4150-am.sh
t/t4151-am-abort.sh
t/t4202-log.sh
t/t5302-pack-index.sh
t/t5304-prune.sh
t/t5310-pack-bitmaps.sh
t/t5312-prune-corruption.sh
t/t5504-fetch-receive-strict.sh
t/t5511-refspec.sh
t/t5512-ls-remote.sh
t/t5516-fetch-push.sh
t/t5520-pull.sh
t/t5521-pull-options.sh
t/t5601-clone.sh
t/t6020-merge-df.sh
t/t6021-merge-criss-cross.sh
t/t6026-merge-attr.sh
t/t6030-bisect-porcelain.sh
t/t6300-for-each-ref.sh
t/t6301-for-each-ref-errors.sh [new file with mode: 0755]
t/t6501-freshen-objects.sh
t/t7004-tag.sh
t/t7030-verify-tag.sh [new file with mode: 0755]
t/t7063-status-untracked-cache.sh [new file with mode: 0755]
t/t7300-clean.sh
t/t7410-submodule-checkout-to.sh [new file with mode: 0755]
t/t7502-commit.sh
t/t7509-commit.sh
t/t7510-signed-commit.sh
t/t7512-status-help.sh
t/t8002-blame.sh
t/t9000-addresses.sh [new file with mode: 0755]
t/t9000/test.pl [new file with mode: 0755]
t/t9001-send-email.sh
t/t9300-fast-import.sh
t/t9402-git-cvsserver-refs.sh
t/t9800-git-p4-basic.sh
t/t9801-git-p4-branch.sh
t/t9803-git-p4-shell-metachars.sh
t/t9805-git-p4-skip-submit-edit.sh
t/t9813-git-p4-preserve-users.sh
t/t9814-git-p4-rename.sh
t/t9816-git-p4-locked.sh
t/t9818-git-p4-block.sh [new file with mode: 0755]
t/t9819-git-p4-case-folding.sh [new file with mode: 0755]
t/t9820-git-p4-editor-handling.sh [new file with mode: 0755]
t/t9902-completion.sh
t/t9903-bash-prompt.sh
t/test-lib-functions.sh
t/test-lib.sh
templates/hooks--applypatch-msg.sample
templates/hooks--pre-applypatch.sample
test-date.c
test-dump-untracked-cache.c [new file with mode: 0644]
test-parse-options.c
test-revision-walking.c
trace.c
trace.h
transport-helper.c
transport.c
tree-diff.c
tree-walk.c
tree-walk.h
unpack-trees.c
upload-pack.c
userdiff.c
utf8.h
walker.c
wrapper.c
wt-status.c

index a052419..a685ec1 100644 (file)
 /git-verify-tag
 /git-web--browse
 /git-whatchanged
+/git-worktree
 /git-write-tree
 /git-core-*/?*
 /gitweb/GITWEB-BUILD-OPTIONS
 /test-delta
 /test-dump-cache-tree
 /test-dump-split-index
+/test-dump-untracked-cache
 /test-scrap-cache-tree
 /test-genrandom
 /test-hashmap
diff --git a/Documentation/RelNotes/2.4.6.txt b/Documentation/RelNotes/2.4.6.txt
new file mode 100644 (file)
index 0000000..b53f353
--- /dev/null
@@ -0,0 +1,23 @@
+Git v2.4.6 Release Notes
+========================
+
+Fixes since v2.4.5
+------------------
+
+ * "git fetch --depth=<depth>" and "git clone --depth=<depth>" issued
+   a shallow transfer request even to an upload-pack that does not
+   support the capability.
+
+ * "git fsck" used to ignore missing or invalid objects recorded in reflog.
+
+ * The tcsh completion writes a bash scriptlet but that would have
+   failed for users with noclobber set.
+
+ * Recent Mac OS X updates breaks the logic to detect that the machine
+   is on the AC power in the sample pre-auto-gc script.
+
+ * "git format-patch --ignore-if-upstream A..B" did not like to be fed
+   tags as boundary commits.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
diff --git a/Documentation/RelNotes/2.4.7.txt b/Documentation/RelNotes/2.4.7.txt
new file mode 100644 (file)
index 0000000..b3ac412
--- /dev/null
@@ -0,0 +1,53 @@
+Git v2.4.7 Release Notes
+========================
+
+Fixes since v2.4.6
+------------------
+
+ * A minor regression to "git fsck" in v2.2 era was fixed; it
+   complained about a body-less tag object when it lacked a
+   separator empty line after its header to separate it with a
+   non-existent body.
+
+ * We used to ask libCURL to use the most secure authentication method
+   available when talking to an HTTP proxy only when we were told to
+   talk to one via configuration variables.  We now ask libCURL to
+   always use the most secure authentication method, because the user
+   can tell libCURL to use an HTTP proxy via an environment variable
+   without using configuration variables.
+
+ * When you say "!<ENTER>" while running say "git log", you'd confuse
+   yourself in the resulting shell, that may look as if you took
+   control back to the original shell you spawned "git log" from but
+   that isn't what is happening.  To that new shell, we leaked
+   GIT_PAGER_IN_USE environment variable that was meant as a local
+   communication between the original "Git" and subprocesses that was
+   spawned by it after we launched the pager, which caused many
+   "interesting" things to happen, e.g. "git diff | cat" still paints
+   its output in color by default.
+
+   Stop leaking that environment variable to the pager's half of the
+   fork; we only need it on "Git" side when we spawn the pager.
+
+ * Avoid possible ssize_t to int truncation.
+
+ * "git config" failed to update the configuration file when the
+   underlying filesystem is incapable of renaming a file that is still
+   open.
+
+ * A minor bugfix when pack bitmap is used with "rev-list --count".
+
+ * An ancient test framework enhancement to allow color was not
+   entirely correct; this makes it work even when tput needs to read
+   from the ~/.terminfo under the user's real HOME directory.
+
+ * Fix a small bug in our use of umask() return value.
+
+ * "git rebase" did not exit with failure when format-patch it invoked
+   failed for whatever reason.
+
+ * Disable "have we lost a race with competing repack?" check while
+   receiving a huge object transfer that runs index-pack.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
diff --git a/Documentation/RelNotes/2.4.8.txt b/Documentation/RelNotes/2.4.8.txt
new file mode 100644 (file)
index 0000000..ad946b2
--- /dev/null
@@ -0,0 +1,21 @@
+Git v2.4.8 Release Notes
+========================
+
+Fixes since v2.4.7
+------------------
+
+ * Abandoning an already applied change in "git rebase -i" with
+   "--continue" left CHERRY_PICK_HEAD and confused later steps.
+
+ * Various fixes around "git am" that applies a patch to a history
+   that is not there yet.
+
+ * "git for-each-ref" reported "missing object" for 0{40} when it
+   encounters a broken ref.  The lack of object whose name is 0{40} is
+   not the problem; the ref being broken is.
+
+ * "git commit --cleanup=scissors" was not careful enough to protect
+   against getting fooled by a line that looked like scissors.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
diff --git a/Documentation/RelNotes/2.5.0.txt b/Documentation/RelNotes/2.5.0.txt
new file mode 100644 (file)
index 0000000..8704450
--- /dev/null
@@ -0,0 +1,563 @@
+Git 2.5 Release Notes
+=====================
+
+Updates since v2.4
+------------------
+
+UI, Workflows & Features
+
+ * The bash completion script (in contrib/) learned a few options that
+   "git revert" takes.
+
+ * Whitespace breakages in deleted and context lines can also be
+   painted in the output of "git diff" and friends with the new
+   --ws-error-highlight option.
+
+ * List of commands shown by "git help" are grouped along the workflow
+   elements to help early learners.
+
+ * "git p4" now detects the filetype (e.g. binary) correctly even when
+   the files are opened exclusively.
+
+ * git p4 attempts to better handle branches in Perforce.
+
+ * "git p4" learned "--changes-block-size <n>" to read the changes in
+   chunks from Perforce, instead of making one call to "p4 changes"
+   that may trigger "too many rows scanned" error from Perforce.
+
+ * More workaround for Perforce's row number limit in "git p4".
+
+ * Unlike "$EDITOR" and "$GIT_EDITOR" that can hold the path to the
+   command and initial options (e.g. "/path/to/emacs -nw"), 'git p4'
+   did not let the shell interpolate the contents of the environment
+   variable that name the editor "$P4EDITOR" (and "$EDITOR", too).
+   This release makes it in line with the rest of Git, as well as with
+   Perforce.
+
+ * A new short-hand <branch>@{push} denotes the remote-tracking branch
+   that tracks the branch at the remote the <branch> would be pushed
+   to.
+
+ * "git show-branch --topics HEAD" (with no other arguments) did not
+   do anything interesting.  Instead, contrast the given revision
+   against all the local branches by default.
+
+ * A replacement for contrib/workdir/git-new-workdir that does not
+   rely on symbolic links and make sharing of objects and refs safer
+   by making the borrowee and borrowers aware of each other.
+
+   Consider this as still an experimental feature; its UI is still
+   likely to change.
+
+ * Tweak the sample "store" backend of the credential helper to honor
+   XDG configuration file locations when specified.
+
+ * A heuristic we use to catch mistyped paths on the command line
+   "git <cmd> <revs> <pathspec>" is to make sure that all the non-rev
+   parameters in the later part of the command line are names of the
+   files in the working tree, but that means "git grep $str -- \*.c"
+   must always be disambiguated with "--", because nobody sane will
+   create a file whose name literally is asterisk-dot-see.  Loosen the
+   heuristic to declare that with a wildcard string the user likely
+   meant to give us a pathspec.
+
+ * "git merge FETCH_HEAD" learned that the previous "git fetch" could
+   be to create an Octopus merge, i.e. recording multiple branches
+   that are not marked as "not-for-merge"; this allows us to lose an
+   old style invocation "git merge <msg> HEAD $commits..." in the
+   implementation of "git pull" script; the old style syntax can now
+   be deprecated (but not removed yet).
+
+ * Filter scripts were run with SIGPIPE disabled on the Git side,
+   expecting that they may not read what Git feeds them to filter.
+   We however treated a filter that does not read its input fully
+   before exiting as an error.  We no longer do and ignore EPIPE
+   when writing to feed the filter scripts.
+
+   This changes semantics, but arguably in a good way.  If a filter
+   can produce its output without fully consuming its input using
+   whatever magic, we now let it do so, instead of diagnosing it
+   as a programming error.
+
+ * Instead of dying immediately upon failing to obtain a lock, the
+   locking (of refs etc) retries after a short while with backoff.
+
+ * Introduce http.<url>.SSLCipherList configuration variable to tweak
+   the list of cipher suite to be used with libcURL when talking with
+   https:// sites.
+
+ * "git subtree" script (in contrib/) used "echo -n" to produce
+   progress messages in a non-portable way.
+
+ * "git subtree" script (in contrib/) does not have --squash option
+   when pushing, but the documentation and help text pretended as if
+   it did.
+
+ * The Git subcommand completion (in contrib/) no longer lists credential
+   helpers among candidates; they are not something the end user would
+   invoke interactively.
+
+ * The index file can be taught with "update-index --untracked-cache"
+   to optionally remember already seen untracked files, in order to
+   speed up "git status" in a working tree with tons of cruft.
+
+ * "git mergetool" learned to drive WinMerge as a backend.
+
+ * "git upload-pack" that serves "git fetch" can be told to serve
+   commits that are not at the tip of any ref, as long as they are
+   reachable from a ref, with uploadpack.allowReachableSHA1InWant
+   configuration variable.
+
+ * "git cat-file --batch(-check)" learned the "--follow-symlinks"
+   option that follows an in-tree symbolic link when asked about an
+   object via extended SHA-1 syntax, e.g. HEAD:RelNotes that points at
+   Documentation/RelNotes/2.5.0.txt.  With the new option, the command
+   behaves as if HEAD:Documentation/RelNotes/2.5.0.txt was given as
+   input instead.
+
+   Consider this as still an experimental and incomplete feature:
+
+    - We may want to do the same for in-index objects, e.g.
+      asking for :RelNotes with this option should give
+      :Documentation/RelNotes/2.5.0.txt, too
+
+    - "git cat-file --follow-symlinks blob HEAD:RelNotes"
+      may also be something we want to allow in the future.
+
+ * "git send-email" learned the alias file format used by the sendmail
+   program (in a simplified form; we obviously do not feed pipes).
+
+ * Traditionally, external low-level 3-way merge drivers are expected
+   to produce their results based solely on the contents of the three
+   variants given in temporary files named by %O, %A and %B on their
+   command line.  Additionally allow them to look at the final path
+   (given by %P).
+
+ * "git blame" learned blame.showEmail configuration variable.
+
+ * "git apply" cannot diagnose a patch corruption when the breakage is
+   to mark the length of the hunk shorter than it really is on the
+   hunk header line "@@ -l,k +m,n @@"; one special case it could is
+   when the hunk becomes no-op (e.g. k == n == 2 for two-line context
+   patch output), and it learned to do so in this special case.
+
+ * Add the "--allow-unknown-type" option to "cat-file" to allow
+   inspecting loose objects of an experimental or a broken type.
+
+ * Many long-running operations show progress eye-candy, even when
+   they are later backgrounded.  Hide the eye-candy when the process
+   is sent to the background instead.
+   (merge a4fb76c lm/squelch-bg-progress later to maint).
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * "unsigned char [20]" used throughout the code to represent object
+   names are being converted into a semi-opaque "struct object_id".
+   This effort is expected to interfere with other topics in flight,
+   but hopefully will give us one extra level of abstraction in the
+   end, when completed.
+
+ * for_each_ref() callback functions were taught to name the objects
+   not with "unsigned char sha1[20]" but with "struct object_id".
+
+ * Catch a programmer mistake to feed a pointer not an array to
+   ARRAY_SIZE() macro, by using a couple of GCC extensions.
+
+ * Some error messages in "git config" were emitted without calling
+   the usual error() facility.
+
+ * When "add--interactive" splits a hunk into two overlapping hunks
+   and then let the user choose only one, it sometimes feeds an
+   incorrect patch text to "git apply".  Add tests to demonstrate
+   this.
+
+   I have a slight suspicion that this may be $gmane/87202 coming back
+   and biting us (I seem to have said "let's run with this and see
+   what happens" back then).
+
+ * More line-ending tests.
+
+ * An earlier rewrite to use strbuf_getwholeline() instead of fgets(3)
+   to read packed-refs file revealed that the former is unacceptably
+   inefficient.  It has been optimized by using getdelim(3) when
+   available.
+
+ * The refs API uses ref_lock struct which had its own "int fd", even
+   though the same file descriptor was in the lock struct it contains.
+   Clean-up the code to lose this redundant field.
+
+ * There was a dead code that used to handle "git pull --tags" and
+   show special-cased error message, which was made irrelevant when
+   the semantics of the option changed back in Git 1.9 days.
+   (merge 19d122b pt/pull-tags-error-diag later to maint).
+
+ * Help us to find broken test script that splits the body part of the
+   test by mistaken use of wrong kind of quotes.
+   (merge d93d5d5 jc/test-prereq-validate later to maint).
+
+ * Developer support to automatically detect broken &&-chain in the
+   test scripts is now turned on by default.
+   (merge 92b269f jk/test-chain-lint later to maint).
+
+ * Error reporting mechanism used in "refs" API has been made more
+   consistent.
+
+ * "git pull" has more test coverage now.
+
+ * "git pull" has become more aware of the options meant for
+   underlying "git fetch" and then learned to use parse-options
+   parser.
+
+ * Clarify in the Makefile a guideline to decide use of USE_NSEC.
+
+Also contains various documentation updates and code clean-ups.
+
+
+Fixes since v2.4
+----------------
+
+Unless otherwise noted, all the fixes since v2.4 in the maintenance
+track are contained in this release (see the maintenance releases'
+notes for details).
+
+ * Git 2.4 broke setting verbosity and progress levels on "git clone"
+   with native transports.
+   (merge 822f0c4 mh/clone-verbosity-fix later to maint).
+
+ * "git add -e" did not allow the user to abort the operation by
+   killing the editor.
+   (merge cb64800 jk/add-e-kill-editor later to maint).
+
+ * Memory usage of "git index-pack" has been trimmed by tens of
+   per-cent.
+   (merge f0e7f11 nd/slim-index-pack-memory-usage later to maint).
+
+ * "git rev-list --objects $old --not --all" to see if everything that
+   is reachable from $old is already connected to the existing refs
+   was very inefficient.
+   (merge b6e8a3b jk/still-interesting later to maint).
+
+ * "hash-object --literally" introduced in v2.2 was not prepared to
+   take a really long object type name.
+   (merge 1427a7f jc/hash-object later to maint).
+
+ * "git rebase --quiet" was not quite quiet when there is nothing to
+   do.
+   (merge 22946a9 jk/rebase-quiet-noop later to maint).
+
+ * The completion for "log --decorate=" parameter value was incorrect.
+   (merge af16bda sg/complete-decorate-full-not-long later to maint).
+
+ * "filter-branch" corrupted commit log message that ends with an
+   incomplete line on platforms with some "sed" implementations that
+   munge such a line.  Work it around by avoiding to use "sed".
+   (merge df06201 jk/filter-branch-use-of-sed-on-incomplete-line later to maint).
+
+ * "git daemon" fails to build from the source under NO_IPV6
+   configuration (regression in 2.4).
+   (merge d358f77 jc/daemon-no-ipv6-for-2.4.1 later to maint).
+
+ * Some time ago, "git blame" (incorrectly) lost the convert_to_git()
+   call when synthesizing a fake "tip" commit that represents the
+   state in the working tree, which broke folks who record the history
+   with LF line ending to make their project portable across platforms
+   while terminating lines in their working tree files with CRLF for
+   their platform.
+   (merge 4bf256d tb/blame-resurrect-convert-to-git later to maint).
+
+ * We avoid setting core.worktree when the repository location is the
+   ".git" directory directly at the top level of the working tree, but
+   the code misdetected the case in which the working tree is at the
+   root level of the filesystem (which arguably is a silly thing to
+   do, but still valid).
+   (merge 84ccad8 jk/init-core-worktree-at-root later to maint).
+
+ * "git commit --date=now" or anything that relies on approxidate lost
+   the daylight-saving-time offset.
+   (merge f6e6362 jc/epochtime-wo-tz later to maint).
+
+ * Access to objects in repositories that borrow from another one on a
+   slow NFS server unnecessarily got more expensive due to recent code
+   becoming more cautious in a naive way not to lose objects to pruning.
+   (merge ee1c6c3 jk/prune-mtime later to maint).
+
+ * The codepaths that read .gitignore and .gitattributes files have been
+   taught that these files encoded in UTF-8 may have UTF-8 BOM marker at
+   the beginning; this makes it in line with what we do for configuration
+   files already.
+   (merge 27547e5 cn/bom-in-gitignore later to maint).
+
+ * a few helper scripts in the test suite did not report errors
+   correctly.
+   (merge de248e9 ep/fix-test-lib-functions-report later to maint).
+
+ * The default $HOME/.gitconfig file created upon "git config --global"
+   that edits it had incorrectly spelled user.name and user.email
+   entries in it.
+   (merge 7e11052 oh/fix-config-default-user-name-section later to maint).
+
+ * "git cat-file bl $blob" failed to barf even though there is no
+   object type that is "bl".
+   (merge b7994af jk/type-from-string-gently later to maint).
+
+ * The usual "git diff" when seeing a file turning into a directory
+   showed a patchset to remove the file and create all files in the
+   directory, but "git diff --no-index" simply refused to work.  Also,
+   when asked to compare a file and a directory, imitate POSIX "diff"
+   and compare the file with the file with the same name in the
+   directory, instead of refusing to run.
+   (merge 0615173 jc/diff-no-index-d-f later to maint).
+
+ * "git rebase -i" moved the "current" command from "todo" to "done" a
+   bit too prematurely, losing a step when a "pick" did not even start.
+   (merge 8cbc57c ph/rebase-i-redo later to maint).
+
+ * The connection initiation code for "ssh" transport tried to absorb
+   differences between the stock "ssh" and Putty-supplied "plink" and
+   its derivatives, but the logic to tell that we are using "plink"
+   variants were too loose and falsely triggered when "plink" appeared
+   anywhere in the path (e.g. "/home/me/bin/uplink/ssh").
+   (merge baaf233 bc/connect-plink later to maint).
+
+ * We have prepended $GIT_EXEC_PATH and the path "git" is installed in
+   (typically "/usr/bin") to $PATH when invoking subprograms and hooks
+   for almost eternity, but the original use case the latter tried to
+   support was semi-bogus (i.e. install git to /opt/foo/git and run it
+   without having /opt/foo on $PATH), and more importantly it has
+   become less and less relevant as Git grew more mainstream (i.e. the
+   users would _want_ to have it on their $PATH).  Stop prepending the
+   path in which "git" is installed to users' $PATH, as that would
+   interfere the command search order people depend on (e.g. they may
+   not like versions of programs that are unrelated to Git in /usr/bin
+   and want to override them by having different ones in /usr/local/bin
+   and have the latter directory earlier in their $PATH).
+   (merge a0b4507 jk/git-no-more-argv0-path-munging later to maint).
+
+ * core.excludesfile (defaulting to $XDG_HOME/git/ignore) is supposed
+   to be overridden by repository-specific .git/info/exclude file, but
+   the order was swapped from the beginning. This belatedly fixes it.
+   (merge 099d2d8 jc/gitignore-precedence later to maint).
+
+ * There was a commented-out (instead of being marked to expect
+   failure) test that documented a breakage that was fixed since the
+   test was written; turn it into a proper test.
+   (merge 66d2e04 sb/t1020-cleanup later to maint).
+
+ * The "log --decorate" enhancement in Git 2.4 that shows the commit
+   at the tip of the current branch e.g. "HEAD -> master", did not
+   work with --decorate=full.
+   (merge 429ad20 mg/log-decorate-HEAD later to maint).
+
+ * The ref API did not handle cases where 'refs/heads/xyzzy/frotz' is
+   removed at the same time as 'refs/heads/xyzzy' is added (or vice
+   versa) very well.
+   (merge c628edf mh/ref-directory-file later to maint).
+
+ * Multi-ref transaction support we merged a few releases ago
+   unnecessarily kept many file descriptors open, risking to fail with
+   resource exhaustion.  This is for 2.4.x track.
+   (merge 185ce3a mh/write-refs-sooner-2.4 later to maint).
+
+ * "git bundle verify" did not diagnose extra parameters on the
+   command line.
+   (merge 7886cfa ps/bundle-verify-arg later to maint).
+
+ * Various documentation mark-up fixes to make the output more
+   consistent in general and also make AsciiDoctor (an alternative
+   formatter) happier.
+   (merge d0258b9 jk/asciidoc-markup-fix later to maint).
+   (merge ad3967a jk/stripspace-asciidoctor-fix later to maint).
+   (merge 975e382 ja/tutorial-asciidoctor-fix later to maint).
+
+ * The code to read pack-bitmap wanted to allocate a few hundred
+   pointers to a structure, but by mistake allocated and leaked memory
+   enough to hold that many actual structures.  Correct the allocation
+   size and also have it on stack, as it is small enough.
+   (merge 599dc76 rs/plug-leak-in-pack-bitmaps later to maint).
+
+ * The pull.ff configuration was supposed to override the merge.ff
+   configuration, but it didn't.
+   (merge db9bb28 pt/pull-ff-vs-merge-ff later to maint).
+
+ * "git pull --log" and "git pull --no-log" worked as expected, but
+   "git pull --log=20" did not.
+   (merge 5061a44 pt/pull-log-n later to maint).
+
+ * "git rerere forget" in a repository without rerere enabled gave a
+   cryptic error message; it should be a silent no-op instead.
+   (merge 0544574 jk/rerere-forget-check-enabled later to maint).
+
+ * "git rebase -i" fired post-rewrite hook when it shouldn't (namely,
+   when it was told to stop sequencing with 'exec' insn).
+   (merge 141ff8f mm/rebase-i-post-rewrite-exec later to maint).
+
+ * Clarify that "log --raw" and "log --format=raw" are unrelated
+   concepts.
+   (merge 92de921 mm/log-format-raw-doc later to maint).
+
+ * Make "git stash something --help" error out, so that users can
+   safely say "git stash drop --help".
+   (merge 5ba2831 jk/stash-options later to maint).
+
+ * The clean/smudge interface did not work well when filtering an
+   empty contents (failed and then passed the empty input through).
+   It can be argued that a filter that produces anything but empty for
+   an empty input is nonsense, but if the user wants to do strange
+   things, then why not?
+   (merge f6a1e1e jh/filter-empty-contents later to maint).
+
+ * Communication between the HTTP server and http_backend process can
+   lead to a dead-lock when relaying a large ref negotiation request.
+   Diagnose the situation better, and mitigate it by reading such a
+   request first into core (to a reasonable limit).
+   (merge 636614f jk/http-backend-deadlock later to maint).
+
+ * "git clean pathspec..." tried to lstat(2) and complain even for
+   paths outside the given pathspec.
+   (merge 838d6a9 dt/clean-pathspec-filter-then-lstat later to maint).
+
+ * Recent "git prune" traverses young unreachable objects to safekeep
+   old objects in the reachability chain from them, which sometimes
+   caused error messages that are unnecessarily alarming.
+   (merge ce4e7b2 jk/squelch-missing-link-warning-for-unreachable later to maint).
+
+ * The configuration reader/writer uses mmap(2) interface to access
+   the files; when we find a directory, it barfed with "Out of memory?".
+   (merge 9ca0aaf jk/diagnose-config-mmap-failure later to maint).
+
+ * "color.diff.plain" was a misnomer; give it 'color.diff.context' as
+   a more logical synonym.
+   (merge 8dbf3eb jk/color-diff-plain-is-context later to maint).
+
+ * The setup code used to die when core.bare and core.worktree are set
+   inconsistently, even for commands that do not need working tree.
+   (merge fada767 jk/die-on-bogus-worktree-late later to maint).
+
+ * Recent Mac OS X updates breaks the logic to detect that the machine
+   is on the AC power in the sample pre-auto-gc script.
+   (merge c54c7b3 pa/auto-gc-mac-osx later to maint).
+
+ * "git commit --cleanup=scissors" was not careful enough to protect
+   against getting fooled by a line that looked like scissors.
+   (merge fbfa097 sg/commit-cleanup-scissors later to maint).
+
+ * "Have we lost a race with competing repack?" check was too
+   expensive, especially while receiving a huge object transfer
+   that runs index-pack (e.g. "clone" or "fetch").
+   (merge 0eeb077 jk/index-pack-reduce-recheck later to maint).
+
+ * The tcsh completion writes a bash scriptlet but that would have
+   failed for users with noclobber set.
+   (merge 0b1f688 af/tcsh-completion-noclobber later to maint).
+
+ * "git for-each-ref" reported "missing object" for 0{40} when it
+   encounters a broken ref.  The lack of object whose name is 0{40} is
+   not the problem; the ref being broken is.
+   (merge 501cf47 mh/reporting-broken-refs-from-for-each-ref later to maint).
+
+ * Various fixes around "git am" that applies a patch to a history
+   that is not there yet.
+   (merge 6ea3b67 pt/am-abort-fix later to maint).
+
+ * "git fsck" used to ignore missing or invalid objects recorded in reflog.
+   (merge 19bf6c9 mh/fsck-reflog-entries later to maint).
+
+ * "git format-patch --ignore-if-upstream A..B" did not like to be fed
+   tags as boundary commits.
+   (merge 9b7a61d jc/do-not-feed-tags-to-clear-commit-marks later to maint).
+
+ * "git fetch --depth=<depth>" and "git clone --depth=<depth>" issued
+   a shallow transfer request even to an upload-pack that does not
+   support the capability.
+   (merge eb86a50 me/fetch-into-shallow-safety later to maint).
+
+ * "git rebase" did not exit with failure when format-patch it invoked
+   failed for whatever reason.
+   (merge 60d708b cb/rebase-am-exit-code later to maint).
+
+ * Fix a small bug in our use of umask() return value.
+   (merge 3096b2e jk/fix-refresh-utime later to maint).
+
+ * An ancient test framework enhancement to allow color was not
+   entirely correct; this makes it work even when tput needs to read
+   from the ~/.terminfo under the user's real HOME directory.
+   (merge d5c1b7c rh/test-color-avoid-terminfo-in-original-home later to maint).
+
+ * A minor bugfix when pack bitmap is used with "rev-list --count".
+   (merge c8a70d3 jk/rev-list-no-bitmap-while-pruning later to maint).
+
+ * "git config" failed to update the configuration file when the
+   underlying filesystem is incapable of renaming a file that is still
+   open.
+   (merge 7a64592 kb/config-unmap-before-renaming later to maint).
+
+ * Avoid possible ssize_t to int truncation.
+   (merge 6c8afe4 mh/strbuf-read-file-returns-ssize-t later to maint).
+
+ * When you say "!<ENTER>" while running say "git log", you'd confuse
+   yourself in the resulting shell, that may look as if you took
+   control back to the original shell you spawned "git log" from but
+   that isn't what is happening.  To that new shell, we leaked
+   GIT_PAGER_IN_USE environment variable that was meant as a local
+   communication between the original "Git" and subprocesses that was
+   spawned by it after we launched the pager, which caused many
+   "interesting" things to happen, e.g. "git diff | cat" still paints
+   its output in color by default.
+
+   Stop leaking that environment variable to the pager's half of the
+   fork; we only need it on "Git" side when we spawn the pager.
+   (merge 124b519 jc/unexport-git-pager-in-use-in-pager later to maint).
+
+ * Abandoning an already applied change in "git rebase -i" with
+   "--continue" left CHERRY_PICK_HEAD and confused later steps.
+   (merge 0e0aff4 js/rebase-i-clean-up-upon-continue-to-skip later to maint).
+
+ * We used to ask libCURL to use the most secure authentication method
+   available when talking to an HTTP proxy only when we were told to
+   talk to one via configuration variables.  We now ask libCURL to
+   always use the most secure authentication method, because the user
+   can tell libCURL to use an HTTP proxy via an environment variable
+   without using configuration variables.
+   (merge 5841520 et/http-proxyauth later to maint).
+
+ * A fix to a minor regression to "git fsck" in v2.2 era that started
+   complaining about a body-less tag object when it lacks a separator
+   empty line after its header to separate it with a non-existent body.
+   (merge 84d18c0 jc/fsck-retire-require-eoh later to maint).
+
+ * Code cleanups and documentation updates.
+   (merge 0269f96 mm/usage-log-l-can-take-regex later to maint).
+   (merge 64f2589 nd/t1509-chroot-test later to maint).
+   (merge d201a1e sb/test-bitmap-free-at-end later to maint).
+   (merge 05bfc7d sb/line-log-plug-pairdiff-leak later to maint).
+   (merge 846e5df pt/xdg-config-path later to maint).
+   (merge 1154aa4 jc/plug-fmt-merge-msg-leak later to maint).
+   (merge 319b678 jk/sha1-file-reduce-useless-warnings later to maint).
+   (merge 9a35c14 fg/document-commit-message-stripping later to maint).
+   (merge bbf431c ps/doc-packfile-vs-pack-file later to maint).
+   (merge 309a9e3 jk/skip-http-tests-under-no-curl later to maint).
+   (merge ccd593c dl/branch-error-message later to maint).
+   (merge 22570b6 rs/janitorial later to maint).
+   (merge 5c2a581 mc/commit-doc-grammofix later to maint).
+   (merge ce41720 ah/usage-strings later to maint).
+   (merge e6a268c sb/glossary-submodule later to maint).
+   (merge ec48a76 sb/submodule-doc-intro later to maint).
+   (merge 14f8b9b jk/clone-dissociate later to maint).
+   (merge 055c7e9 sb/pack-protocol-mention-smart-http later to maint).
+   (merge 7c37a5d jk/make-fix-dependencies later to maint).
+   (merge fc0aa39 sg/merge-summary-config later to maint).
+   (merge 329af6c pt/t0302-needs-sanity later to maint).
+   (merge d614f07 fk/doc-format-patch-vn later to maint).
+   (merge 72dbb36 sg/completion-commit-cleanup later to maint).
+   (merge e654eb2 es/utf8-stupid-compiler-workaround later to maint).
+   (merge 34b935c es/osx-header-pollutes-mask-macro later to maint).
+   (merge ab7fade jc/prompt-document-ps1-state-separator later to maint).
+   (merge 25f600e mm/describe-doc later to maint).
+   (merge 83fe167 mm/branch-doc-updates later to maint).
+   (merge 75d2e5a ls/hint-rev-list-count later to maint).
+   (merge edc8f71 cb/subtree-tests-update later to maint).
+   (merge 5330e6e sb/p5310-and-chain later to maint).
+   (merge c4ac525 tb/checkout-doc later to maint).
+   (merge e479c5f jk/pretty-encoding-doc later to maint).
+   (merge 7e837c6 ss/clone-guess-dir-name-simplify later to maint).
diff --git a/Documentation/RelNotes/2.6.0.txt b/Documentation/RelNotes/2.6.0.txt
new file mode 100644 (file)
index 0000000..4a0a589
--- /dev/null
@@ -0,0 +1,190 @@
+Git 2.6 Release Notes
+=====================
+
+Updates since v2.5
+------------------
+
+UI, Workflows & Features
+
+ * An asterisk as a substring (as opposed to the entirety) of a path
+   component for both side of a refspec, e.g.
+   "refs/heads/o*:refs/remotes/heads/i*", is now allowed.
+
+ * New userdiff pattern definition for fountain screenwriting markup
+   format has been added.
+
+ * "git log" and friends learned a new "--date=format:..." option to
+   format timestamps using system's strftime(3).
+
+ * "git fast-import" learned to respond to the get-mark command via
+   its cat-blob-fd interface.
+
+ * "git rebase -i" learned "drop commit-object-name subject" command
+   as another way to skip replaying of a commit.
+
+ * A new configuration variable can enable "--follow" automatically
+   when "git log" is run with one pathspec argument.
+
+ * "git status" learned to show a more detailed information regarding
+   the "rebase -i" session in progress.
+
+ * "git cat-file" learned "--batch-all-objects" option to enumerate all
+   available objects in the repository more quickly than "rev-list
+   --all --objects" (the output includes unreachable objects, though).
+
+ * "git fsck" learned to ignore errors on a set of known-to-be-bad
+   objects, and also allows the warning levels of various kinds of
+   non-critical breakages to be tweaked.
+
+ * "git rebase -i"'s list of todo is made configurable.
+
+ * "git send-email" now performs alias-expansion on names that are
+   given via --cccmd, etc.
+
+ * An environment variable GIT_REPLACE_REF_BASE tells Git to look into
+   refs hierarchy other than refs/replace/ for the object replacement
+   data.
+
+ * Allow untracked cache (experimental) to be used when sparse
+   checkout (experimental) is also in use.
+
+ * "git pull --rebase" has been taught to pay attention to
+   rebase.autostash configuration.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * In preparation for allowing different "backends" to store the refs
+   in a way different from the traditional "one ref per file in
+   $GIT_DIR or in a $GIT_DIR/packed-refs file" filesystem storage,
+   direct filesystem access to ref-like things like CHERRY_PICK_HEAD
+   from scripts and programs has been reduced.
+
+ * Computation of untracked status indicator by bash prompt
+   script (in contrib/) has been optimized.
+
+ * Memory use reduction when commit-slab facility is used to annotate
+   sparsely (which is not recommended in the first place).
+
+ * Clean up refs API and make "git clone" less intimate with the
+   implementation detail.
+
+ * "git pull" was reimplemented in C.
+
+ * The packet tracing machinery allows to capture an incoming pack
+   data to a file for debugging.
+
+ * Move machinery to parse human-readable scaled numbers like 1k, 4M,
+   and 2G as an option parameter's value from pack-objects to
+   parse-options API, to make it available to other codepaths.
+
+ * "git verify-tag" and "git verify-commit" have been taught to share
+   more code, and then learned to optionally show the verification
+   message from the underlying GPG implementation.
+
+ * Various enhancements around "git am" reading patches generated by
+   foreign SCM have been made.
+
+ * Ref listing by "git branch -l" and "git tag -l" commands has
+   started to be rebuilt, based on the for-each-ref machinery.
+
+ * The code to perform multi-tree merges has been taught to repopulate
+   the cache-tree upon a successful merge into the index, so that
+   subsequent "diff-index --cached" (hence "status") and "write-tree"
+   (hence "commit") will go faster.
+
+   The same logic in "git checkout" may now be removed, but that is a
+   separate issue.
+
+ * Tests that assume how reflogs are represented on the filesystem too
+   much have been corrected.
+
+ * "git am" has been rewritten in "C".
+
+
+Also contains various documentation updates and code clean-ups.
+
+
+Fixes since v2.5
+----------------
+
+Unless otherwise noted, all the fixes since v2.5 in the maintenance
+track are contained in this release (see the maintenance releases'
+notes for details).
+
+ * "git subtree" (in contrib/) depended on "git log" output to be
+   stable, which was a no-no.  Apply a workaround to force a
+   particular date format.
+   (merge e7aac44 da/subtree-date-confusion later to maint).
+
+ * An attempt to delete a ref by pushing into a repositorywhose HEAD
+   symbolic reference points at an unborn branch that cannot be
+   created due to ref D/F conflict (e.g. refs/heads/a/b exists, HEAD
+   points at refs/heads/a) failed.
+   (merge b112b14 jx/do-not-crash-receive-pack-wo-head later to maint).
+
+ * The low-level "git send-pack" did not honor 'user.signingkey'
+   configuration variable when sending a signed-push.
+   (merge d830d39 db/send-pack-user-signingkey later to maint).
+
+ * "sparse checkout" misbehaved for a path that is excluded from the
+   checkout when switching between branches that differ at the path.
+   (merge 7d78241 as/sparse-checkout-removal later to maint).
+
+ * An experimental "untracked cache" feature used uname(2) in a
+   slightly unportable way.
+   (merge 100e433 cb/uname-in-untracked later to maint).
+
+ * A "rebase" replays changes of the local branch on top of something
+   else, as such they are placed in stage #3 and referred to as
+   "theirs", while the changes in the new base, typically a foreign
+   work, are placed in stage #2 and referred to as "ours".  Clarify
+   the "checkout --ours/--theirs".
+   (merge f303016 se/doc-checkout-ours-theirs later to maint).
+
+ * The "rev-parse --parseopt" mode parsed the option specification
+   and the argument hint in a strange way to allow '=' and other
+   special characters in the option name while forbidding them from
+   the argument hint.  This made it impossible to define an option
+   like "--pair <key>=<value>" with "pair=key=value" specification,
+   which instead would have defined a "--pair=key <value>" option.
+   (merge 2d893df ib/scripted-parse-opt-better-hint-string later to maint).
+
+ * Often a fast-import stream builds a new commit on top of the
+   previous commit it built, and it often unconditionally emits a
+   "from" command to specify the first parent, which can be omitted in
+   such a case.  This caused fast-import to forget the tree of the
+   previous commit and then re-read it from scratch, which was
+   inefficient.  Optimize for this common case.
+   (merge 0df3245 mh/fast-import-optimize-current-from later to maint).
+
+ * Running an aliased command from a subdirectory when the .git thing
+   in the working tree is a gitfile pointing elsewhere did not work.
+   (merge d95138e nd/export-worktree later to maint).
+
+ * "Is this subdirectory a separate repository that should not be
+   touched?" check "git clean" was inefficient.  This was replaced
+   with a more optimized check.
+   (merge 38ae878 ee/clean-remove-dirs later to maint).
+
+ * The "new-worktree-mode" hack in "checkout" that was added in
+   nd/multiple-work-trees topic has been removed by updating the
+   implementation of new "worktree add".
+   (merge 65f9b75 es/worktree-add-cleanup later to maint).
+
+ * Remove remaining cruft from  "git checkout --to", which
+   transitioned to "git worktree add".
+   (merge 114ff88 es/worktree-add later to maint).
+
+ * An off-by-one error made "git remote" to mishandle a remote with a
+   single letter nickname.
+   (merge bc598c3 mh/get-remote-group-fix later to maint).
+
+ * Code cleanups and documentation updates.
+   (merge 1c601af es/doc-clean-outdated-tools later to maint).
+   (merge 3581304 kn/tag-doc-fix later to maint).
+   (merge 3a59e59 kb/i18n-doc later to maint).
+   (merge 45abdee sb/remove-unused-var-from-builtin-add later to maint).
+   (merge 14691e3 sb/parse-options-codeformat later to maint).
+   (merge 4a6ada3 ad/bisect-cleanup later to maint).
+   (merge da4c5ad ta/docfix-index-format-tech later to maint).
index 04f9977..5aa73cf 100755 (executable)
@@ -38,6 +38,10 @@ sub format_one {
        }
 }
 
+while (<>) {
+       last if /^### command list/;
+}
+
 my %cmds = ();
 for (sort <>) {
        next if /^#/;
index 2e919f0..75ec02e 100644 (file)
@@ -453,6 +453,8 @@ false), while all other repositories are assumed to be bare (bare
 
 core.worktree::
        Set the path to the root of the working tree.
+       If GIT_COMMON_DIR environment variable is set, core.worktree
+       is ignored and not used for determining the root of working tree.
        This can be overridden by the GIT_WORK_TREE environment
        variable and the '--work-tree' command-line option.
        The value can be an absolute path or relative to the path to
@@ -622,6 +624,12 @@ core.commentChar::
 If set to "auto", `git-commit` would select a character that is not
 the beginning character of any line in existing commit messages.
 
+core.packedRefsTimeout::
+       The length of time, in milliseconds, to retry when trying to
+       lock the `packed-refs` file. Value 0 means not to retry at
+       all; -1 means to try indefinitely. Default is 1000 (i.e.,
+       retry for 1 second).
+
 sequence.editor::
        Text editor used by `git rebase -i` for editing the rebase instruction file.
        The value is meant to be interpreted by the shell when it is used.
@@ -761,6 +769,14 @@ am.keepcr::
        by giving '--no-keep-cr' from the command line.
        See linkgit:git-am[1], linkgit:git-mailsplit[1].
 
+am.threeWay::
+       By default, `git am` will fail if the patch does not apply cleanly. When
+       set to true, this setting tells `git am` to fall back on 3-way merge if
+       the patch records the identity of blobs it is supposed to apply to and
+       we have those blobs available locally (equivalent to giving the `--3way`
+       option from the command line). Defaults to `false`.
+       See linkgit:git-am[1].
+
 apply.ignoreWhitespace::
        When set to 'change', tells 'git apply' to ignore changes in
        whitespace, in the same way as the '--ignore-space-change'
@@ -1234,6 +1250,25 @@ filter.<driver>.smudge::
        object to a worktree file upon checkout.  See
        linkgit:gitattributes[5] for details.
 
+fsck.<msg-id>::
+       Allows overriding the message type (error, warn or ignore) of a
+       specific message ID such as `missingEmail`.
++
+For convenience, fsck prefixes the error/warning with the message ID,
+e.g.  "missingEmail: invalid author/committer line - missing email" means
+that setting `fsck.missingEmail = ignore` will hide that issue.
++
+This feature is intended to support working with legacy repositories
+which cannot be repaired without disruptive changes.
+
+fsck.skipList::
+       The path to a sorted list of object names (i.e. one SHA-1 per
+       line) that are known to be broken in a non-fatal way and should
+       be ignored. This feature is useful when an established project
+       should be accepted despite early commits containing errors that
+       can be safely ignored such as invalid committer email addresses.
+       Note: corrupt objects cannot be skipped with this setting.
+
 gc.aggressiveDepth::
        The depth parameter used in the delta compression
        algorithm used by 'git gc --aggressive'.  This defaults
@@ -1272,13 +1307,24 @@ gc.packRefs::
 gc.pruneExpire::
        When 'git gc' is run, it will call 'prune --expire 2.weeks.ago'.
        Override the grace period with this config variable.  The value
-       "now" may be used to disable this  grace period and always prune
-       unreachable objects immediately.
+       "now" may be used to disable this grace period and always prune
+       unreachable objects immediately, or "never" may be used to
+       suppress pruning.
+
+gc.worktreePruneExpire::
+       When 'git gc' is run, it calls
+       'git worktree prune --expire 3.months.ago'.
+       This config variable can be used to set a different grace
+       period. The value "now" may be used to disable the grace
+       period and prune $GIT_DIR/worktrees immediately, or "never"
+       may be used to suppress pruning.
 
 gc.reflogExpire::
 gc.<pattern>.reflogExpire::
        'git reflog expire' removes reflog entries older than
-       this time; defaults to 90 days.  With "<pattern>" (e.g.
+       this time; defaults to 90 days. The value "now" expires all
+       entries immediately, and "never" suppresses expiration
+       altogether. With "<pattern>" (e.g.
        "refs/stash") in the middle the setting applies only to
        the refs that match the <pattern>.
 
@@ -1286,7 +1332,9 @@ gc.reflogExpireUnreachable::
 gc.<ref>.reflogExpireUnreachable::
        'git reflog expire' removes reflog entries older than
        this time and are not reachable from the current tip;
-       defaults to 30 days.  With "<pattern>" (e.g. "refs/stash")
+       defaults to 30 days. The value "now" expires all entries
+       immediately, and "never" suppresses expiration altogether.
+       With "<pattern>" (e.g. "refs/stash")
        in the middle, the setting applies only to the refs that
        match the <pattern>.
 
@@ -1561,6 +1609,19 @@ http.saveCookies::
        If set, store cookies received during requests to the file specified by
        http.cookieFile. Has no effect if http.cookieFile is unset.
 
+http.sslCipherList::
+  A list of SSL ciphers to use when negotiating an SSL connection.
+  The available ciphers depend on whether libcurl was built against
+  NSS or OpenSSL and the particular configuration of the crypto
+  library in use.  Internally this sets the 'CURLOPT_SSL_CIPHER_LIST'
+  option; see the libcurl documentation for more details on the format
+  of this list.
++
+Can be overridden by the 'GIT_SSL_CIPHER_LIST' environment variable.
+To force git to use libcurl's default cipher list and ignore any
+explicit http.sslCipherList option, set 'GIT_SSL_CIPHER_LIST' to the
+empty string.
+
 http.sslVerify::
        Whether to verify the SSL certificate when fetching or pushing
        over HTTPS. Can be overridden by the 'GIT_SSL_NO_VERIFY' environment
@@ -2133,6 +2194,22 @@ rebase.autoStash::
        successful rebase might result in non-trivial conflicts.
        Defaults to false.
 
+rebase.missingCommitsCheck::
+       If set to "warn", git rebase -i will print a warning if some
+       commits are removed (e.g. a line was deleted), however the
+       rebase will still proceed. If set to "error", it will print
+       the previous warning and stop the rebase, 'git rebase
+       --edit-todo' can then be used to correct the error. If set to
+       "ignore", no checking is done.
+       To drop a commit without warning or error, use the `drop`
+       command in the todo-list.
+       Defaults to "ignore".
+
+rebase.instructionFormat
+       A format string, as specified in linkgit:git-log[1], to be used for
+       the instruction list during an interactive rebase.  The format will automatically
+       have the long commit hash prepended to the format.
+
 receive.advertiseAtomic::
        By default, git-receive-pack will advertise the atomic push
        capability to its clients. If you don't want to this capability
@@ -2169,6 +2246,28 @@ receive.fsckObjects::
        Defaults to false. If not set, the value of `transfer.fsckObjects`
        is used instead.
 
+receive.fsck.<msg-id>::
+       When `receive.fsckObjects` is set to true, errors can be switched
+       to warnings and vice versa by configuring the `receive.fsck.<msg-id>`
+       setting where the `<msg-id>` is the fsck message ID and the value
+       is one of `error`, `warn` or `ignore`. For convenience, fsck prefixes
+       the error/warning with the message ID, e.g. "missingEmail: invalid
+       author/committer line - missing email" means that setting
+       `receive.fsck.missingEmail = ignore` will hide that issue.
++
+This feature is intended to support working with legacy repositories
+which would not pass pushing when `receive.fsckObjects = true`, allowing
+the host to accept repositories with certain known issues but still catch
+other issues.
+
+receive.fsck.skipList::
+       The path to a sorted list of object names (i.e. one SHA-1 per
+       line) that are known to be broken in a non-fatal way and should
+       be ignored. This feature is useful when an established project
+       should be accepted despite early commits containing errors that
+       can be safely ignored such as invalid committer email addresses.
+       Note: corrupt objects cannot be skipped with this setting.
+
 receive.unpackLimit::
        If the number of objects received in a push is below this
        limit then the objects will be unpacked into loose object
@@ -2214,13 +2313,10 @@ receive.denyNonFastForwards::
        set when initializing a shared repository.
 
 receive.hideRefs::
-       String(s) `receive-pack` uses to decide which refs to omit
-       from its initial advertisement.  Use more than one
-       definitions to specify multiple prefix strings. A ref that
-       are under the hierarchies listed on the value of this
-       variable is excluded, and is hidden when responding to `git
-       push`, and an attempt to update or delete a hidden ref by
-       `git push` is rejected.
+       This variable is the same as `transfer.hideRefs`, but applies
+       only to `receive-pack` (and so affects pushes, but not fetches).
+       An attempt to update or delete a hidden ref by `git push` is
+       rejected.
 
 receive.updateServerInfo::
        If set to true, git-receive-pack will run git-update-server-info
@@ -2508,9 +2604,18 @@ transfer.fsckObjects::
        Defaults to false.
 
 transfer.hideRefs::
-       This variable can be used to set both `receive.hideRefs`
-       and `uploadpack.hideRefs` at the same time to the same
-       values.  See entries for these other variables.
+       String(s) `receive-pack` and `upload-pack` use to decide which
+       refs to omit from their initial advertisements.  Use more than
+       one definition to specify multiple prefix strings. A ref that is
+       under the hierarchies listed in the value of this variable is
+       excluded, and is hidden when responding to `git push` or `git
+       fetch`.  See `receive.hideRefs` and `uploadpack.hideRefs` for
+       program-specific versions of this config.
++
+You may also include a `!` in front of the ref name to negate the entry,
+explicitly exposing it, even if an earlier entry marked it as hidden.
+If you have multiple hideRefs values, later entries override earlier ones
+(and entries in more-specific config files override less-specific ones).
 
 transfer.unpackLimit::
        When `fetch.unpackLimit` or `receive.unpackLimit` are
@@ -2525,20 +2630,23 @@ uploadarchive.allowUnreachable::
        `false`.
 
 uploadpack.hideRefs::
-       String(s) `upload-pack` uses to decide which refs to omit
-       from its initial advertisement.  Use more than one
-       definitions to specify multiple prefix strings. A ref that
-       are under the hierarchies listed on the value of this
-       variable is excluded, and is hidden from `git ls-remote`,
-       `git fetch`, etc.  An attempt to fetch a hidden ref by `git
-       fetch` will fail.  See also `uploadpack.allowtipsha1inwant`.
-
-uploadpack.allowtipsha1inwant::
+       This variable is the same as `transfer.hideRefs`, but applies
+       only to `upload-pack` (and so affects only fetches, not pushes).
+       An attempt to fetch a hidden ref by `git fetch` will fail.  See
+       also `uploadpack.allowTipSHA1InWant`.
+
+uploadpack.allowTipSHA1InWant::
        When `uploadpack.hideRefs` is in effect, allow `upload-pack`
        to accept a fetch request that asks for an object at the tip
        of a hidden ref (by default, such a request is rejected).
        see also `uploadpack.hideRefs`.
 
+uploadpack.allowReachableSHA1InWant::
+       Allow `upload-pack` to accept a fetch request that asks for an
+       object that is reachable from any ref tip. However, note that
+       calculating object reachability is computationally expensive.
+       Defaults to `false`.
+
 uploadpack.keepAlive::
        When `upload-pack` has started `pack-objects`, there may be a
        quiet period while `pack-objects` prepares the pack. Normally
index 3ad6404..d56ca90 100644 (file)
@@ -291,6 +291,16 @@ ifndef::git-format-patch[]
        initial indent of the line are considered whitespace errors.
        Exits with non-zero status if problems are found. Not compatible
        with --exit-code.
+
+--ws-error-highlight=<kind>::
+       Highlight whitespace errors on lines specified by <kind>
+       in the color specified by `color.diff.whitespace`.  <kind>
+       is a comma separated list of `old`, `new`, `context`.  When
+       this option is not given, only whitespace errors in `new`
+       lines are highlighted.  E.g. `--ws-error-highlight=new,old`
+       highlights whitespace errors on both deleted and added lines.
+       `all` can be used as a short-hand for `old,new,context`.
+
 endif::git-format-patch[]
 
 --full-index::
index 0d8ba48..dbea6e7 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git am' [--signoff] [--keep] [--[no-]keep-cr] [--[no-]utf8]
-        [--3way] [--interactive] [--committer-date-is-author-date]
+        [--[no-]3way] [--interactive] [--committer-date-is-author-date]
         [--ignore-date] [--ignore-space-change | --ignore-whitespace]
         [--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
         [--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
@@ -90,10 +90,13 @@ default.   You can use `--no-utf8` to override this.
 
 -3::
 --3way::
+--no-3way::
        When the patch does not apply cleanly, fall back on
        3-way merge if the patch records the identity of blobs
        it is supposed to apply to and we have those blobs
-       available locally.
+       available locally. `--no-3way` can be used to override
+       am.threeWay configuration variable. For more information,
+       see am.threeWay in linkgit:git-config[1].
 
 --ignore-space-change::
 --ignore-whitespace::
index 4cb52a7..e97f2de 100644 (file)
@@ -3,7 +3,7 @@ git-bisect(1)
 
 NAME
 ----
-git-bisect - Find by binary search the change that introduced a bug
+git-bisect - Use binary search to find the commit that introduced a bug
 
 
 SYNOPSIS
@@ -16,7 +16,6 @@ DESCRIPTION
 The command takes various subcommands, and different options depending
 on the subcommand:
 
- git bisect help
  git bisect start [--no-checkout] [<bad> [<good>...]] [--] [<paths>...]
  git bisect bad [<rev>]
  git bisect good [<rev>...]
@@ -26,64 +25,71 @@ on the subcommand:
  git bisect replay <logfile>
  git bisect log
  git bisect run <cmd>...
+ git bisect help
 
-This command uses 'git rev-list --bisect' to help drive the
-binary search process to find which change introduced a bug, given an
-old "good" commit object name and a later "bad" commit object name.
-
-Getting help
-~~~~~~~~~~~~
-
-Use "git bisect" to get a short usage description, and "git bisect
-help" or "git bisect -h" to get a long usage description.
+This command uses a binary search algorithm to find which commit in
+your project's history introduced a bug. You use it by first telling
+it a "bad" commit that is known to contain the bug, and a "good"
+commit that is known to be before the bug was introduced. Then `git
+bisect` picks a commit between those two endpoints and asks you
+whether the selected commit is "good" or "bad". It continues narrowing
+down the range until it finds the exact commit that introduced the
+change.
 
 Basic bisect commands: start, bad, good
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Using the Linux kernel tree as an example, basic use of the bisect
-command is as follows:
+As an example, suppose you are trying to find the commit that broke a
+feature that was known to work in version `v2.6.13-rc2` of your
+project. You start a bisect session as follows:
 
 ------------------------------------------------
 $ git bisect start
 $ git bisect bad                 # Current version is bad
-$ git bisect good v2.6.13-rc2    # v2.6.13-rc2 was the last version
-                                 # tested that was good
+$ git bisect good v2.6.13-rc2    # v2.6.13-rc2 is known to be good
 ------------------------------------------------
 
-When you have specified at least one bad and one good version, the
-command bisects the revision tree and outputs something similar to
-the following:
+Once you have specified at least one bad and one good commit, `git
+bisect` selects a commit in the middle of that range of history,
+checks it out, and outputs something similar to the following:
 
 ------------------------------------------------
-Bisecting: 675 revisions left to test after this
+Bisecting: 675 revisions left to test after this (roughly 10 steps)
 ------------------------------------------------
 
-The state in the middle of the set of revisions is then checked out.
-You would now compile that kernel and boot it. If the booted kernel
-works correctly, you would then issue the following command:
+You should now compile the checked-out version and test it. If that
+version works correctly, type
 
 ------------------------------------------------
-$ git bisect good                      # this one is good
+$ git bisect good
 ------------------------------------------------
 
-The output of this command would be something similar to the following:
+If that version is broken, type
 
 ------------------------------------------------
-Bisecting: 337 revisions left to test after this
+$ git bisect bad
 ------------------------------------------------
 
-You keep repeating this process, compiling the tree, testing it, and
-depending on whether it is good or bad issuing the command "git bisect good"
-or "git bisect bad" to ask for the next bisection.
+Then `git bisect` will respond with something like
+
+------------------------------------------------
+Bisecting: 337 revisions left to test after this (roughly 9 steps)
+------------------------------------------------
+
+Keep repeating the process: compile the tree, test it, and depending
+on whether it is good or bad run `git bisect good` or `git bisect bad`
+to ask for the next commit that needs testing.
+
+Eventually there will be no more revisions left to inspect, and the
+command will print out a description of the first bad commit. The
+reference `refs/bisect/bad` will be left pointing at that commit.
 
-Eventually there will be no more revisions left to bisect, and you
-will have been left with the first bad kernel revision in "refs/bisect/bad".
 
 Bisect reset
 ~~~~~~~~~~~~
 
 After a bisect session, to clean up the bisection state and return to
-the original HEAD (i.e., to quit bisecting), issue the following command:
+the original HEAD, issue the following command:
 
 ------------------------------------------------
 $ git bisect reset
@@ -100,9 +106,10 @@ instead:
 $ git bisect reset <commit>
 ------------------------------------------------
 
-For example, `git bisect reset HEAD` will leave you on the current
-bisection commit and avoid switching commits at all, while `git bisect
-reset bisect/bad` will check out the first bad revision.
+For example, `git bisect reset bisect/bad` will check out the first
+bad revision, while `git bisect reset HEAD` will leave you on the
+current bisection commit and avoid switching commits at all.
+
 
 Bisect visualize
 ~~~~~~~~~~~~~~~~
@@ -147,17 +154,17 @@ $ git bisect replay that-file
 Avoiding testing a commit
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
-If, in the middle of a bisect session, you know that the next suggested
-revision is not a good one to test (e.g. the change the commit
-introduces is known not to work in your environment and you know it
-does not have anything to do with the bug you are chasing), you may
-want to find a nearby commit and try that instead.
+If, in the middle of a bisect session, you know that the suggested
+revision is not a good one to test (e.g. it fails to build and you
+know that the failure does not have anything to do with the bug you
+are chasing), you can manually select a nearby commit and test that
+one instead.
 
 For example:
 
 ------------
 $ git bisect good/bad                  # previous round was good or bad.
-Bisecting: 337 revisions left to test after this
+Bisecting: 337 revisions left to test after this (roughly 9 steps)
 $ git bisect visualize                 # oops, that is uninteresting.
 $ git reset --hard HEAD~3              # try 3 revisions before what
                                        # was suggested
@@ -169,18 +176,19 @@ the revision as good or bad in the usual manner.
 Bisect skip
 ~~~~~~~~~~~~
 
-Instead of choosing by yourself a nearby commit, you can ask Git
-to do it for you by issuing the command:
+Instead of choosing a nearby commit by yourself, you can ask Git to do
+it for you by issuing the command:
 
 ------------
 $ git bisect skip                 # Current version cannot be tested
 ------------
 
-But Git may eventually be unable to tell the first bad commit among
-a bad commit and one or more skipped commits.
+However, if you skip a commit adjacent to the one you are looking for,
+Git will be unable to tell exactly which of those commits was the
+first bad one.
 
-You can even skip a range of commits, instead of just one commit,
-using the "'<commit1>'..'<commit2>'" notation. For example:
+You can also skip a range of commits, instead of just one commit,
+using range notation. For example:
 
 ------------
 $ git bisect skip v2.5..v2.6
@@ -196,8 +204,8 @@ would issue the command:
 $ git bisect skip v2.5 v2.5..v2.6
 ------------
 
-This tells the bisect process that the commits between `v2.5` included
-and `v2.6` included should be skipped.
+This tells the bisect process that the commits between `v2.5` and
+`v2.6` (inclusive) should be skipped.
 
 
 Cutting down bisection by giving more parameters to bisect start
@@ -231,14 +239,14 @@ or bad, you can bisect by issuing the command:
 $ git bisect run my_script arguments
 ------------
 
-Note that the script (`my_script` in the above example) should
-exit with code 0 if the current source code is good, and exit with a
-code between 1 and 127 (inclusive), except 125, if the current
-source code is bad.
+Note that the script (`my_script` in the above example) should exit
+with code 0 if the current source code is good/old, and exit with a
+code between 1 and 127 (inclusive), except 125, if the current source
+code is bad/new.
 
 Any other exit code will abort the bisect process. It should be noted
-that a program that terminates via "exit(-1)" leaves $? = 255, (see the
-exit(3) manual page), as the value is chopped with "& 0377".
+that a program that terminates via `exit(-1)` leaves $? = 255, (see the
+exit(3) manual page), as the value is chopped with `& 0377`.
 
 The special exit code 125 should be used when the current source code
 cannot be tested. If the script exits with this code, the current
@@ -247,7 +255,7 @@ as the highest sensible value to use for this purpose, because 126 and 127
 are used by POSIX shells to signal specific error status (127 is for
 command not found, 126 is for command found but not executable---these
 details do not matter, as they are normal errors in the script, as far as
-"bisect run" is concerned).
+`bisect run` is concerned).
 
 You may often find that during a bisect session you want to have
 temporary modifications (e.g. s/#define DEBUG 0/#define DEBUG 1/ in a
@@ -260,7 +268,7 @@ next revision to test, the script can apply the patch
 before compiling, run the real test, and afterwards decide if the
 revision (possibly with the needed patch) passed the test and then
 rewind the tree to the pristine state.  Finally the script should exit
-with the status of the real test to let the "git bisect run" command loop
+with the status of the real test to let the `git bisect run` command loop
 determine the eventual outcome of the bisect session.
 
 OPTIONS
@@ -307,12 +315,12 @@ $ git bisect run ~/test.sh
 $ git bisect reset                   # quit the bisect session
 ------------
 +
-Here we use a "test.sh" custom script. In this script, if "make"
+Here we use a `test.sh` custom script. In this script, if `make`
 fails, we skip the current commit.
-"check_test_case.sh" should "exit 0" if the test case passes,
-and "exit 1" otherwise.
+`check_test_case.sh` should `exit 0` if the test case passes,
+and `exit 1` otherwise.
 +
-It is safer if both "test.sh" and "check_test_case.sh" are
+It is safer if both `test.sh` and `check_test_case.sh` are
 outside the repository to prevent interactions between the bisect,
 make and test processes and the scripts.
 
@@ -379,6 +387,11 @@ In this case, when 'git bisect run' finishes, bisect/bad will refer to a commit
 has at least one parent whose reachable graph is fully traversable in the sense
 required by 'git pack objects'.
 
+Getting help
+~~~~~~~~~~~~
+
+Use `git bisect` to get a short usage description, and `git bisect
+help` or `git bisect -h` to get a long usage description.
 
 SEE ALSO
 --------
index 9f23a86..e6e947c 100644 (file)
@@ -76,6 +76,8 @@ include::blame-options.txt[]
 -e::
 --show-email::
        Show the author email instead of author name (Default: off).
+       This can also be controlled via the `blame.showEmail` config
+       option.
 
 -w::
        Ignore whitespace when comparing the parent's version and
index 359619b..a67138a 100644 (file)
@@ -81,7 +81,7 @@ OPTIONS
        `--track` or `--set-upstream`.
 
 -D::
-       Delete a branch irrespective of its merged status.
+       Shortcut for `--delete --force`.
 
 -l::
 --create-reflog::
@@ -95,13 +95,17 @@ OPTIONS
 --force::
        Reset <branchname> to <startpoint> if <branchname> exists
        already. Without `-f` 'git branch' refuses to change an existing branch.
+       In combination with `-d` (or `--delete`), allow deleting the
+       branch irrespective of its merged status. In combination with
+       `-m` (or `--move`), allow renaming the branch even if the new
+       branch name already exists.
 
 -m::
 --move::
        Move/rename a branch and the corresponding reflog.
 
 -M::
-       Move/rename a branch even if the new branch name already exists.
+       Shortcut for `--move --force`.
 
 --color[=<when>]::
        Color branches to highlight current, local, and
index f6a16f4..3105fc0 100644 (file)
@@ -9,8 +9,8 @@ git-cat-file - Provide content or type and size information for repository objec
 SYNOPSIS
 --------
 [verse]
-'git cat-file' (-t | -s | -e | -p | <type> | --textconv ) <object>
-'git cat-file' (--batch | --batch-check) < <list-of-objects>
+'git cat-file' (-t [--allow-unknown-type]| -s [--allow-unknown-type]| -e | -p | <type> | --textconv ) <object>
+'git cat-file' (--batch | --batch-check) [--follow-symlinks] < <list-of-objects>
 
 DESCRIPTION
 -----------
@@ -69,6 +69,79 @@ OPTIONS
        not be combined with any other options or arguments.  See the
        section `BATCH OUTPUT` below for details.
 
+--batch-all-objects::
+       Instead of reading a list of objects on stdin, perform the
+       requested batch operation on all objects in the repository and
+       any alternate object stores (not just reachable objects).
+       Requires `--batch` or `--batch-check` be specified. Note that
+       the objects are visited in order sorted by their hashes.
+
+--buffer::
+       Normally batch output is flushed after each object is output, so
+       that a process can interactively read and write from
+       `cat-file`. With this option, the output uses normal stdio
+       buffering; this is much more efficient when invoking
+       `--batch-check` on a large number of objects.
+
+--allow-unknown-type::
+       Allow -s or -t to query broken/corrupt objects of unknown type.
+
+--follow-symlinks::
+       With --batch or --batch-check, follow symlinks inside the
+       repository when requesting objects with extended SHA-1
+       expressions of the form tree-ish:path-in-tree.  Instead of
+       providing output about the link itself, provide output about
+       the linked-to object.  If a symlink points outside the
+       tree-ish (e.g. a link to /foo or a root-level link to ../foo),
+       the portion of the link which is outside the tree will be
+       printed.
++
+This option does not (currently) work correctly when an object in the
+index is specified (e.g. `:link` instead of `HEAD:link`) rather than
+one in the tree.
++
+This option cannot (currently) be used unless `--batch` or
+`--batch-check` is used.
++
+For example, consider a git repository containing:
++
+--
+       f: a file containing "hello\n"
+       link: a symlink to f
+       dir/link: a symlink to ../f
+       plink: a symlink to ../f
+       alink: a symlink to /etc/passwd
+--
++
+For a regular file `f`, `echo HEAD:f | git cat-file --batch` would print
++
+--
+       ce013625030ba8dba906f756967f9e9ca394464a blob 6
+--
++
+And `echo HEAD:link | git cat-file --batch --follow-symlinks` would
+print the same thing, as would `HEAD:dir/link`, as they both point at
+`HEAD:f`.
++
+Without `--follow-symlinks`, these would print data about the symlink
+itself.  In the case of `HEAD:link`, you would see
++
+--
+       4d1ae35ba2c8ec712fa2a379db44ad639ca277bd blob 1
+--
++
+Both `plink` and `alink` point outside the tree, so they would
+respectively print:
++
+--
+       symlink 4
+       ../f
+
+       symlink 11
+       /etc/passwd
+--
+
+
 OUTPUT
 ------
 If '-t' is specified, one of the <type>.
@@ -148,6 +221,47 @@ the repository, then `cat-file` will ignore any custom format and print:
 <object> SP missing LF
 ------------
 
+If --follow-symlinks is used, and a symlink in the repository points
+outside the repository, then `cat-file` will ignore any custom format
+and print:
+
+------------
+symlink SP <size> LF
+<symlink> LF
+------------
+
+The symlink will either be absolute (beginning with a /), or relative
+to the tree root.  For instance, if dir/link points to ../../foo, then
+<symlink> will be ../foo.  <size> is the size of the symlink in bytes.
+
+If --follow-symlinks is used, the following error messages will be
+displayed:
+
+------------
+<object> SP missing LF
+------------
+is printed when the initial symlink requested does not exist.
+
+------------
+dangling SP <size> LF
+<object> LF
+------------
+is printed when the initial symlink exists, but something that
+it (transitive-of) points to does not.
+
+------------
+loop SP <size> LF
+<object> LF
+------------
+is printed for symlink loops (or any symlinks that
+require more than 40 link resolutions to resolve).
+
+------------
+notdir SP <size> LF
+<object> LF
+------------
+is printed when, during symlink resolution, a file is used as a
+directory name.
 
 CAVEATS
 -------
index fc02959..9044dfa 100644 (file)
@@ -94,8 +94,8 @@ OPTIONS
        Interpret <refname> as a reference name pattern for a refspec
        (as used with remote repositories).  If this option is
        enabled, <refname> is allowed to contain a single `*`
-       in place of a one full pathname component (e.g.,
-       `foo/*/bar` but not `foo/bar*`).
+       in the refspec (e.g., `foo/bar*/baz` or `foo/bar*baz/`
+       but not `foo/bar*/baz*`).
 
 --normalize::
        Normalize 'refname' by removing any leading slash (`/`)
index d504108..e269fb1 100644 (file)
@@ -3,7 +3,7 @@ git-checkout(1)
 
 NAME
 ----
-git-checkout - Checkout a branch or paths to the working tree
+git-checkout - Switch branches or restore working tree files
 
 SYNOPSIS
 --------
@@ -89,6 +89,10 @@ Omitting <branch> detaches HEAD at the tip of the current branch.
        (i.e.  commit, tag or tree) to update the index for the given
        paths before updating the working tree.
 +
+'git checkout' with <paths> or `--patch` is used to restore modified or
+deleted paths to their original contents from the index or replace paths
+with the contents from a named <tree-ish> (most often a commit-ish).
++
 The index may contain unmerged entries because of a previous failed merge.
 By default, if you try to check out such an entry from the index, the
 checkout operation will fail and nothing will be checked out.
@@ -116,6 +120,21 @@ entries; instead, unmerged entries are ignored.
 --theirs::
        When checking out paths from the index, check out stage #2
        ('ours') or #3 ('theirs') for unmerged paths.
++
+Note that during `git rebase` and `git pull --rebase`, 'ours' and
+'theirs' may appear swapped; `--ours` gives the version from the
+branch the changes are rebased onto, while `--theirs` gives the
+version from the branch that holds your work that is being rebased.
++
+This is because `rebase` is used in a workflow that treats the
+history at the remote as the shared canonical one, and treats the
+work done on the branch you are rebasing as the third-party work to
+be integrated, and you are temporarily assuming the role of the
+keeper of the canonical history during the rebase.  As the keeper of
+the canonical history, you need to view the history from the remote
+as `ours` (i.e. "our shared canonical history"), while what you did
+on your side branch as `theirs` (i.e. "one contributor's work on top
+of it").
 
 -b <new_branch>::
        Create a new branch named <new_branch> and start it at
@@ -225,6 +244,12 @@ This means that you can use `git checkout -p` to selectively discard
 edits from your current working tree. See the ``Interactive Mode''
 section of linkgit:git-add[1] to learn how to operate the `--patch` mode.
 
+--ignore-other-worktrees::
+       `git checkout` refuses when the wanted ref is already checked
+       out by another worktree. This option makes it check the ref
+       out anyway. In other words, the ref can be held by more than one
+       worktree.
+
 <branch>::
        Branch to checkout; if it refers to a branch (i.e., a name that,
        when prepended with "refs/heads/", is a valid ref), then that
index d20ca40..e045fc7 100644 (file)
@@ -3,7 +3,7 @@ git-describe(1)
 
 NAME
 ----
-git-describe - Show the most recent tag that is reachable from a commit
+git-describe - Describe a commit using the most recent tag reachable from it
 
 
 SYNOPSIS
index fd32895..66910aa 100644 (file)
@@ -54,7 +54,7 @@ Options for Frontends
 ~~~~~~~~~~~~~~~~~~~~~
 
 --cat-blob-fd=<fd>::
-       Write responses to `cat-blob` and `ls` queries to the
+       Write responses to `get-mark`, `cat-blob`, and `ls` queries to the
        file descriptor <fd> instead of `stdout`.  Allows `progress`
        output intended for the end-user to be separated from other
        output.
@@ -350,6 +350,11 @@ and control the current import process.  More detailed discussion
        unless the `done` feature was requested using the
        `--done` command-line option or `feature done` command.
 
+`get-mark`::
+       Causes fast-import to print the SHA-1 corresponding to a mark
+       to the file descriptor set with `--cat-blob-fd`, or `stdout` if
+       unspecified.
+
 `cat-blob`::
        Causes fast-import to print a blob in 'cat-file --batch'
        format to the file descriptor set with `--cat-blob-fd` or
@@ -930,6 +935,25 @@ Placing a `progress` command immediately after a `checkpoint` will
 inform the reader when the `checkpoint` has been completed and it
 can safely access the refs that fast-import updated.
 
+`get-mark`
+~~~~~~~~~~
+Causes fast-import to print the SHA-1 corresponding to a mark to
+stdout or to the file descriptor previously arranged with the
+`--cat-blob-fd` argument. The command otherwise has no impact on the
+current import; its purpose is to retrieve SHA-1s that later commits
+might want to refer to in their commit messages.
+
+....
+       'get-mark' SP ':' <idnum> LF
+....
+
+This command can be used anywhere in the stream that comments are
+accepted.  In particular, the `get-mark` command can be used in the
+middle of a commit but not in the middle of a `data` command.
+
+See ``Responses To Commands'' below for details about how to read
+this output safely.
+
 `cat-blob`
 ~~~~~~~~~~
 Causes fast-import to print a blob to a file descriptor previously
@@ -1000,7 +1024,8 @@ Output uses the same format as `git ls-tree <tree> -- <path>`:
 ====
 
 The <dataref> represents the blob, tree, or commit object at <path>
-and can be used in later 'cat-blob', 'filemodify', or 'ls' commands.
+and can be used in later 'get-mark', 'cat-blob', 'filemodify', or
+'ls' commands.
 
 If there is no file or subtree at that path, 'git fast-import' will
 instead report
@@ -1042,9 +1067,11 @@ import-marks-if-exists::
        "feature import-marks-if-exists" like a corresponding
        command-line option silently skips a nonexistent file.
 
+get-mark::
 cat-blob::
 ls::
-       Require that the backend support the 'cat-blob' or 'ls' command.
+       Require that the backend support the 'get-mark', 'cat-blob',
+       or 'ls' command respectively.
        Versions of fast-import not supporting the specified command
        will exit with a message indicating so.
        This lets the import error out early with a clear message,
@@ -1124,11 +1151,11 @@ bidirectional pipes:
        git fast-import >fast-import-output
 ====
 
-A frontend set up this way can use `progress`, `ls`, and `cat-blob`
-commands to read information from the import in progress.
+A frontend set up this way can use `progress`, `get-mark`, `ls`, and
+`cat-blob` commands to read information from the import in progress.
 
 To avoid deadlock, such frontends must completely consume any
-pending output from `progress`, `ls`, and `cat-blob` before
+pending output from `progress`, `ls`, `get-mark`, and `cat-blob` before
 performing writes to fast-import that might block.
 
 Crash Reports
index 4240875..7f8d9a5 100644 (file)
@@ -97,6 +97,12 @@ upstream::
        or "=" (in sync).  Has no effect if the ref does not have
        tracking information associated with it.
 
+push::
+       The name of a local ref which represents the `@{push}` location
+       for the displayed ref. Respects `:short`, `:track`, and
+       `:trackshort` options as `upstream` does. Produces an empty
+       string if no `@{push}` ref is configured.
+
 HEAD::
        '*' if HEAD matches current ref (the checked out branch), ' '
        otherwise.
index bb3ea93..0dac4e9 100644 (file)
@@ -170,7 +170,7 @@ will want to ensure that threading is disabled for `git send-email`.
 -v <n>::
 --reroll-count=<n>::
        Mark the series as the <n>-th iteration of the topic. The
-       output filenames have `v<n>` pretended to them, and the
+       output filenames have `v<n>` prepended to them, and the
        subject prefix ("PATCH" by default, but configurable via the
        `--subject-prefix` option) has ` v<n>` appended to it.  E.g.
        `--reroll-count=4` may produce `v4-0001-add-makefile.patch`
index 25c431d..84ee92e 100644 (file)
@@ -11,7 +11,7 @@ SYNOPSIS
 [verse]
 'git fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
         [--[no-]full] [--strict] [--verbose] [--lost-found]
-        [--[no-]dangling] [--[no-]progress] [<object>*]
+        [--[no-]dangling] [--[no-]progress] [--connectivity-only] [<object>*]
 
 DESCRIPTION
 -----------
@@ -60,6 +60,11 @@ index file, all SHA-1 references in `refs` namespace, and all reflogs
        object pools.  This is now default; you can turn it off
        with --no-full.
 
+--connectivity-only::
+       Check only the connectivity of tags, commits and tree objects. By
+       avoiding to unpack blobs, this speeds up the operation, at the
+       expense of missing corrupt objects or other problematic issues.
+
 --strict::
        Enable more strict checking, namely to catch a file mode
        recorded with g+w bit set, which was created by older
index 5692945..97b9993 100644 (file)
@@ -184,6 +184,12 @@ log.date::
        `--date` option.)  Defaults to "default", which means to write
        dates like `Sat May 8 19:35:34 2010 -0500`.
 
+log.follow::
+       If a single <path> is given to git log, it will act as
+       if the `--follow` option was also used.  This has the same
+       limitations as `--follow`, i.e. it cannot be used to follow
+       multiple files and does not work well on non-linear history.
+
 log.showRoot::
        If `false`, `git log` and related commands will not treat the
        initial commit as a big creation event.  Any root commits in
index 1f94908..273a100 100644 (file)
@@ -104,6 +104,10 @@ commit or stash your changes before running 'git merge'.
 If no commit is given from the command line, merge the remote-tracking
 branches that the current branch is configured to use as its upstream.
 See also the configuration section of this manual page.
++
+When `FETCH_HEAD` (and no other commit) is specified, the branches
+recorded in the `.git/FETCH_HEAD` file by the previous invocation
+of `git fetch` for merging are merged to the current branch.
 
 
 PRE-MERGE CHECKS
index a1664b9..82aa5d6 100644 (file)
@@ -225,9 +225,20 @@ Git repository:
        they can find the p4 branches in refs/heads.
 
 --max-changes <n>::
-       Limit the number of imported changes to 'n'.  Useful to
-       limit the amount of history when using the '@all' p4 revision
-       specifier.
+       Import at most 'n' changes, rather than the entire range of
+       changes included in the given revision specifier. A typical
+       usage would be use '@all' as the revision specifier, but then
+       to use '--max-changes 1000' to import only the last 1000
+       revisions rather than the entire revision history.
+
+--changes-block-size <n>::
+       The internal block size to use when converting a revision
+       specifier such as '@all' into a list of specific change
+       numbers. Instead of using a single call to 'p4 changes' to
+       find the full list of changes for the conversion, there are a
+       sequence of calls to 'p4 changes -m', each of which requests
+       one block of changes of the given size. The default block size
+       is 500, which should usually be suitable.
 
 --keep-path::
        The mapping of file names from the p4 depot path to Git, by
index 712ab4b..93c72a2 100644 (file)
@@ -74,9 +74,6 @@ pulling or stash them away with linkgit:git-stash[1].
 OPTIONS
 -------
 
-Options meant for 'git pull' itself and the underlying 'git merge'
-must be given before the options meant for 'git fetch'.
-
 -q::
 --quiet::
        This is passed to both underlying git-fetch to squelch reporting of
index 1d01baa..ca03954 100644 (file)
@@ -213,6 +213,15 @@ rebase.autoSquash::
 rebase.autoStash::
        If set to true enable '--autostash' option by default.
 
+rebase.missingCommitsCheck::
+       If set to "warn", print warnings about removed commits in
+       interactive mode. If set to "error", print the warnings and
+       stop the rebase. If set to "ignore", no checking is
+       done. "ignore" by default.
+
+rebase.instructionFormat::
+       Custom commit list format to use during an '--interactive' rebase.
+
 OPTIONS
 -------
 --onto <newbase>::
@@ -359,6 +368,10 @@ default is `--no-fork-point`, otherwise the default is `--fork-point`.
        Make a list of the commits which are about to be rebased.  Let the
        user edit that list before rebasing.  This mode can also be used to
        split commits (see SPLITTING COMMITS below).
++
+The commit list format can be changed by setting the configuration option
+rebase.instructionFormat.  A customized instruction format will automatically
+have the long commit hash prepended to the format.
 
 -p::
 --preserve-merges::
@@ -514,6 +527,9 @@ rebasing.
 If you just want to edit the commit message for a commit, replace the
 command "pick" with the command "reword".
 
+To drop a commit, replace the command "pick" with "drop", or just
+delete the matching line.
+
 If you want to fold two or more commits into one, replace the command
 "pick" for the second and subsequent commits with "squash" or "fixup".
 If the commits had different authors, the folded commit will be
index 5e7908e..44c736f 100644 (file)
@@ -23,6 +23,7 @@ depending on the subcommand:
        [--dry-run] [--verbose] [--all | <refs>...]
 'git reflog delete' [--rewrite] [--updateref]
        [--dry-run] [--verbose] ref@\{specifier\}...
+'git reflog exists' <ref>
 
 Reference logs, or "reflogs", record when the tips of branches and
 other references were updated in the local repository. Reflogs are
@@ -52,6 +53,9 @@ argument must be an _exact_ entry (e.g. "`git reflog delete
 master@{2}`"). This subcommand is also typically not used directly by
 end users.
 
+The "exists" subcommand checks whether a ref has a reflog.  It exits
+with zero status if the reflog exists, and non-zero status if it does
+not.
 
 OPTIONS
 -------
index b10ea60..7b49c85 100644 (file)
@@ -56,6 +56,7 @@ SYNOPSIS
             [ --reverse ]
             [ --walk-reflogs ]
             [ --no-walk ] [ --do-walk ]
+            [ --count ]
             [ --use-bitmap-index ]
             <commit>... [ \-- <paths>... ]
 
index bf81b97..b6c6326 100644 (file)
@@ -216,6 +216,9 @@ If `$GIT_DIR` is not defined and the current directory
 is not detected to lie in a Git repository or work tree
 print a message to stderr and exit with nonzero status.
 
+--git-common-dir::
+       Show `$GIT_COMMON_DIR` if defined, else `$GIT_DIR`.
+
 --is-inside-git-dir::
        When the current working directory is below the repository
        directory print "true", otherwise "false".
@@ -233,6 +236,13 @@ print a message to stderr and exit with nonzero status.
        repository.  If <path> is a gitfile then the resolved path
        to the real repository is printed.
 
+--git-path <path>::
+       Resolve "$GIT_DIR/<path>" and takes other path relocation
+       variables such as $GIT_OBJECT_DIRECTORY,
+       $GIT_INDEX_FILE... into account. For example, if
+       $GIT_OBJECT_DIRECTORY is set to /foo/bar then "git rev-parse
+       --git-path objects/abc" returns /foo/bar/abc.
+
 --show-cdup::
        When the command is invoked from a subdirectory, show the
        path of the top-level directory relative to the current
@@ -301,8 +311,8 @@ Each line of options has this format:
 `<opt-spec>`::
        its format is the short option character, then the long option name
        separated by a comma. Both parts are not required, though at least one
-       is necessary. `h,help`, `dry-run` and `f` are all three correct
-       `<opt-spec>`.
+       is necessary. May not contain any of the `<flags>` characters.
+       `h,help`, `dry-run` and `f` are examples of correct `<opt-spec>`.
 
 `<flags>`::
        `<flags>` are of `*`, `=`, `?` or `!`.
index 8045546..f14705e 100644 (file)
@@ -49,17 +49,17 @@ Composing
        of 'sendemail.annotate'. See the CONFIGURATION section for
        'sendemail.multiEdit'.
 
---bcc=<address>::
+--bcc=<address>,...::
        Specify a "Bcc:" value for each email. Default is the value of
        'sendemail.bcc'.
 +
-The --bcc option must be repeated for each user you want on the bcc list.
+This option may be specified multiple times.
 
---cc=<address>::
+--cc=<address>,...::
        Specify a starting "Cc:" value for each email.
        Default is the value of 'sendemail.cc'.
 +
-The --cc option must be repeated for each user you want on the cc list.
+This option may be specified multiple times.
 
 --compose::
        Invoke a text editor (see GIT_EDITOR in linkgit:git-var[1])
@@ -110,13 +110,13 @@ is not set, this will be prompted for.
        Only necessary if --compose is also set.  If --compose
        is not set, this will be prompted for.
 
---to=<address>::
+--to=<address>,...::
        Specify the primary recipient of the emails generated. Generally, this
        will be the upstream maintainer of the project involved. Default is the
        value of the 'sendemail.to' configuration value; if that is unspecified,
        and --to-cmd is not specified, this will be prompted for.
 +
-The --to option must be repeated for each user you want on the to list.
+This option may be specified multiple times.
 
 --8bit-encoding=<encoding>::
        When encountering a non-ASCII message or subject that does not
@@ -383,7 +383,24 @@ sendemail.aliasesFile::
 
 sendemail.aliasFileType::
        Format of the file(s) specified in sendemail.aliasesFile. Must be
-       one of 'mutt', 'mailrc', 'pine', 'elm', or 'gnus'.
+       one of 'mutt', 'mailrc', 'pine', 'elm', or 'gnus', or 'sendmail'.
++
+What an alias file in each format looks like can be found in
+the documentation of the email program of the same name. The
+differences and limitations from the standard formats are
+described below:
++
+--
+sendmail;;
+*      Quoted aliases and quoted addresses are not supported: lines that
+       contain a `"` symbol are ignored.
+*      Redirection to a file (`/path/name`) or pipe (`|command`) is not
+       supported.
+*      File inclusion (`:include: /path/name`) is not supported.
+*      Warnings are printed on the standard error output for any
+       explicitly unsupported constructs, and any other lines that are not
+       recognized by the parser.
+--
 
 sendemail.multiEdit::
        If true (default), a single editor instance will be spawned to edit
index 5221f95..335f312 100644 (file)
@@ -66,7 +66,10 @@ When `-u` option is not used, untracked files and directories are
 shown (i.e. the same as specifying `normal`), to help you avoid
 forgetting to add newly created files.  Because it takes extra work
 to find untracked files in the filesystem, this mode may take some
-time in a large working tree.  You can use `no` to have `git status`
+time in a large working tree.
+Consider enabling untracked cache and split index if supported (see
+`git update-index --untracked-cache` and `git update-index
+--split-index`), Otherwise you can use `no` to have `git status`
 return more quickly without showing untracked files.
 +
 The default can be changed using the status.showUntrackedFiles
index 034d10d..84f6496 100644 (file)
@@ -13,8 +13,7 @@ SYNOPSIS
        <tagname> [<commit> | <object>]
 'git tag' -d <tagname>...
 'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>]
-       [--column[=<options>] | --no-column] [<pattern>...]
-       [<pattern>...]
+       [--column[=<options>] | --no-column] [--create-reflog] [<pattern>...]
 'git tag' -v <tagname>...
 
 DESCRIPTION
@@ -143,6 +142,9 @@ This option is only applicable when listing tags without annotation lines.
        all, 'whitespace' removes just leading/trailing whitespace lines and
        'strip' removes both whitespace and commentary.
 
+--create-reflog::
+       Create a reflog for the tag.
+
 <tagname>::
        The name of the tag to create, delete, or describe.
        The new tag name must pass all checks defined by
index 78a0d95..2f4ff50 100644 (file)
-A short Git tools survey
-========================
+Git Tools
+=========
 
+When Git was young, people looking for third-party Git-related tools came
+to the Git project itself to find them, thus a list of such tools was
+maintained here. These days, however, search engines fill that role much
+more efficiently, so this manually-maintained list has been retired.
 
-Introduction
-------------
-
-Apart from Git contrib/ area there are some others third-party tools
-you may want to look.
-
-This document presents a brief summary of each tool and the corresponding
-link.
-
-
-Alternative/Augmentative Porcelains
------------------------------------
-
-   - *Cogito* (http://www.kernel.org/pub/software/scm/cogito/)
-
-   Cogito is a version control system layered on top of the Git tree history
-   storage system. It aims at seamless user interface and ease of use,
-   providing generally smoother user experience than the "raw" Core Git
-   itself and indeed many other version control systems.
-
-   Cogito is no longer maintained as most of its functionality
-   is now in core Git.
-
-
-   - *pg* (http://www.spearce.org/category/projects/scm/pg/)
-
-   pg is a shell script wrapper around Git to help the user manage a set of
-   patches to files. pg is somewhat like quilt or StGit, but it does have a
-   slightly different feature set.
-
-
-   - *StGit* (http://www.procode.org/stgit/)
-
-   Stacked Git provides a quilt-like patch management functionality in the
-   Git environment. You can easily manage your patches in the scope of Git
-   until they get merged upstream.
-
-
-History Viewers
----------------
-
-   - *gitk* (shipped with git-core)
-
-   gitk is a simple Tk GUI for browsing history of Git repositories easily.
-
-
-   - *gitview*  (contrib/)
-
-   gitview is a GTK based repository browser for Git
-
-
-   - *gitweb* (shipped with git-core)
-
-   Gitweb provides full-fledged web interface for Git repositories.
-
-
-   - *qgit* (http://digilander.libero.it/mcostalba/)
-
-   QGit is a git/StGit GUI viewer built on Qt/C++. QGit could be used
-   to browse history and directory tree, view annotated files, commit
-   changes cherry picking single files or applying patches.
-   Currently it is the fastest and most feature rich among the Git
-   viewers and commit tools.
-
-   - *tig* (http://jonas.nitro.dk/tig/)
-
-   tig by Jonas Fonseca is a simple Git repository browser
-   written using ncurses. Basically, it just acts as a front-end
-   for git-log and git-show/git-diff. Additionally, you can also
-   use it as a pager for Git commands.
-
-
-Foreign SCM interface
----------------------
-
-   - *git-svn* (shipped with git-core)
-
-   git-svn is a simple conduit for changesets between a single Subversion
-   branch and Git.
-
-
-   - *quilt2git / git2quilt* (http://home-tj.org/wiki/index.php/Misc)
-
-   These utilities convert patch series in a quilt repository and commit
-   series in Git back and forth.
-
-
-   - *hg-to-git* (contrib/)
-
-   hg-to-git converts a Mercurial repository into a Git one, and
-   preserves the full branch history in the process. hg-to-git can
-   also be used in an incremental way to keep the Git repository
-   in sync with the master Mercurial repository.
-
-
-Others
-------
-
-   - *(h)gct* (http://www.cyd.liu.se/users/~freku045/gct/)
-
-   Commit Tool or (h)gct is a GUI enabled commit tool for Git and
-   Mercurial (hg). It allows the user to view diffs, select which files
-   to committed (or ignored / reverted) write commit messages and
-   perform the commit itself.
-
-   - *git.el* (contrib/)
-
-   This is an Emacs interface for Git. The user interface is modelled on
-   pcl-cvs. It has been developed on Emacs 21 and will probably need some
-   tweaking to work on XEmacs.
-
-
-http://git.or.cz/gitwiki/InterfacesFrontendsAndTools has more
-comprehensive list.
+See also the `contrib/` area, and the Git wiki:
+http://git.or.cz/gitwiki/InterfacesFrontendsAndTools
index aff0179..1a296bc 100644 (file)
@@ -170,6 +170,20 @@ may not support it yet.
        the shared index file. This mode is designed for very large
        indexes that take a significant amount of time to read or write.
 
+--untracked-cache::
+--no-untracked-cache::
+       Enable or disable untracked cache extension. This could speed
+       up for commands that involve determining untracked files such
+       as `git status`. The underlying operating system and file
+       system must change `st_mtime` field of a directory if files
+       are added or deleted in that directory.
+
+--force-untracked-cache::
+       For safety, `--untracked-cache` performs tests on the working
+       directory to make sure untracked cache can be used. These
+       tests can take a few seconds. `--force-untracked-cache` can be
+       used to skip the tests.
+
 \--::
        Do not interpret any more arguments as options.
 
index c8f5ae5..969bfab 100644 (file)
@@ -8,7 +8,7 @@ git-update-ref - Update the object name stored in a ref safely
 SYNOPSIS
 --------
 [verse]
-'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>] | --stdin [-z])
+'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] [--create-reflog] <ref> <newvalue> [<oldvalue>] | --stdin [-z])
 
 DESCRIPTION
 -----------
@@ -67,6 +67,9 @@ performs all modifications together.  Specify commands of the form:
        verify SP <ref> [SP <oldvalue>] LF
        option SP <opt> LF
 
+With `--create-reflog`, update-ref will create a reflog for each ref
+even if one would not ordinarily be created.
+
 Quote fields containing whitespace as if they were strings in C source
 code; i.e., surrounded by double-quotes and with backslash escapes.
 Use 40 "0" characters or the empty string to specify a zero value.  To
index 9413e28..ecf4da1 100644 (file)
@@ -16,6 +16,10 @@ Validates the gpg signature created by 'git commit -S'.
 
 OPTIONS
 -------
+--raw::
+       Print the raw gpg status output to standard error instead of the normal
+       human-readable output.
+
 -v::
 --verbose::
        Print the contents of the commit object before validating it.
index f88ba96..d590edc 100644 (file)
@@ -16,6 +16,10 @@ Validates the gpg signature created by 'git tag'.
 
 OPTIONS
 -------
+--raw::
+       Print the raw gpg status output to standard error instead of the normal
+       human-readable output.
+
 -v::
 --verbose::
        Print the contents of the tag object before validating it.
diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt
new file mode 100644 (file)
index 0000000..fb68156
--- /dev/null
@@ -0,0 +1,176 @@
+git-worktree(1)
+===============
+
+NAME
+----
+git-worktree - Manage multiple working trees
+
+
+SYNOPSIS
+--------
+[verse]
+'git worktree add' [-f] [--detach] [-b <new-branch>] <path> [<branch>]
+'git worktree prune' [-n] [-v] [--expire <expire>]
+
+DESCRIPTION
+-----------
+
+Manage multiple working trees attached to the same repository.
+
+A git repository can support multiple working trees, allowing you to check
+out more than one branch at a time.  With `git worktree add` a new working
+tree is associated with the repository.  This new working tree is called a
+"linked working tree" as opposed to the "main working tree" prepared by "git
+init" or "git clone".  A repository has one main working tree (if it's not a
+bare repository) and zero or more linked working trees.
+
+When you are done with a linked working tree you can simply delete it.
+The working tree's administrative files in the repository (see
+"DETAILS" below) will eventually be removed automatically (see
+`gc.worktreePruneExpire` in linkgit:git-config[1]), or you can run
+`git worktree prune` in the main or any linked working tree to
+clean up any stale administrative files.
+
+If you move a linked working tree to another file system, or
+within a file system that does not support hard links, you need to run
+at least one git command inside the linked working tree
+(e.g. `git status`) in order to update its administrative files in the
+repository so that they do not get automatically pruned.
+
+If a linked working tree is stored on a portable device or network share
+which is not always mounted, you can prevent its administrative files from
+being pruned by creating a file named 'locked' alongside the other
+administrative files, optionally containing a plain text reason that
+pruning should be suppressed. See section "DETAILS" for more information.
+
+COMMANDS
+--------
+add <path> [<branch>]::
+
+Create `<path>` and checkout `<branch>` into it. The new working directory
+is linked to the current repository, sharing everything except working
+directory specific files such as HEAD, index, etc.
++
+If `<branch>` is omitted and neither `-b` nor `-B` nor `--detached` used,
+then, as a convenience, a new branch based at HEAD is created automatically,
+as if `-b $(basename <path>)` was specified.
+
+prune::
+
+Prune working tree information in $GIT_DIR/worktrees.
+
+OPTIONS
+-------
+
+-f::
+--force::
+       By default, `add` refuses to create a new working tree when `<branch>`
+       is already checked out by another working tree. This option overrides
+       that safeguard.
+
+-b <new-branch>::
+-B <new-branch>::
+       With `add`, create a new branch named `<new-branch>` starting at
+       `<branch>`, and check out `<new-branch>` into the new working tree.
+       If `<branch>` is omitted, it defaults to HEAD.
+       By default, `-b` refuses to create a new branch if it already
+       exists. `-B` overrides this safeguard, resetting `<new-branch>` to
+       `<branch>`.
+
+--detach::
+       With `add`, detach HEAD in the new working tree. See "DETACHED HEAD"
+       in linkgit:git-checkout[1].
+
+-n::
+--dry-run::
+       With `prune`, do not remove anything; just report what it would
+       remove.
+
+-v::
+--verbose::
+       With `prune`, report all removals.
+
+--expire <time>::
+       With `prune`, only expire unused working trees older than <time>.
+
+DETAILS
+-------
+Each linked working tree has a private sub-directory in the repository's
+$GIT_DIR/worktrees directory.  The private sub-directory's name is usually
+the base name of the linked working tree's path, possibly appended with a
+number to make it unique.  For example, when `$GIT_DIR=/path/main/.git` the
+command `git worktree add /path/other/test-next next` creates the linked
+working tree in `/path/other/test-next` and also creates a
+`$GIT_DIR/worktrees/test-next` directory (or `$GIT_DIR/worktrees/test-next1`
+if `test-next` is already taken).
+
+Within a linked working tree, $GIT_DIR is set to point to this private
+directory (e.g. `/path/main/.git/worktrees/test-next` in the example) and
+$GIT_COMMON_DIR is set to point back to the main working tree's $GIT_DIR
+(e.g. `/path/main/.git`). These settings are made in a `.git` file located at
+the top directory of the linked working tree.
+
+Path resolution via `git rev-parse --git-path` uses either
+$GIT_DIR or $GIT_COMMON_DIR depending on the path. For example, in the
+linked working tree `git rev-parse --git-path HEAD` returns
+`/path/main/.git/worktrees/test-next/HEAD` (not
+`/path/other/test-next/.git/HEAD` or `/path/main/.git/HEAD`) while `git
+rev-parse --git-path refs/heads/master` uses
+$GIT_COMMON_DIR and returns `/path/main/.git/refs/heads/master`,
+since refs are shared across all working trees.
+
+See linkgit:gitrepository-layout[5] for more information. The rule of
+thumb is do not make any assumption about whether a path belongs to
+$GIT_DIR or $GIT_COMMON_DIR when you need to directly access something
+inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path.
+
+To prevent a $GIT_DIR/worktrees entry from being pruned (which
+can be useful in some situations, such as when the
+entry's working tree is stored on a portable device), add a file named
+'locked' to the entry's directory. The file contains the reason in
+plain text. For example, if a linked working tree's `.git` file points
+to `/path/main/.git/worktrees/test-next` then a file named
+`/path/main/.git/worktrees/test-next/locked` will prevent the
+`test-next` entry from being pruned.  See
+linkgit:gitrepository-layout[5] for details.
+
+EXAMPLES
+--------
+You are in the middle of a refactoring session and your boss comes in and
+demands that you fix something immediately. You might typically use
+linkgit:git-stash[1] to store your changes away temporarily, however, your
+working tree is in such a state of disarray (with new, moved, and removed
+files, and other bits and pieces strewn around) that you don't want to risk
+disturbing any of it. Instead, you create a temporary linked working tree to
+make the emergency fix, remove it when done, and then resume your earlier
+refactoring session.
+
+------------
+$ git worktree add -b emergency-fix ../temp master
+$ pushd ../temp
+# ... hack hack hack ...
+$ git commit -a -m 'emergency fix for boss'
+$ popd
+$ rm -rf ../temp
+$ git worktree prune
+------------
+
+BUGS
+----
+Multiple checkout in general is still experimental, and the support
+for submodules is incomplete. It is NOT recommended to make multiple
+checkouts of a superproject.
+
+git-worktree could provide more automation for tasks currently
+performed manually, such as:
+
+- `remove` to remove a linked working tree and its administrative files (and
+  warn if the working tree is dirty)
+- `mv` to move or rename a working tree and update its administrative files
+- `list` to list linked working trees
+- `lock` to prevent automatic pruning of administrative files (for instance,
+  for a working tree on a portable device)
+
+GIT
+---
+Part of the linkgit:git[1] suite
index a4a4cf3..2795340 100644 (file)
@@ -43,9 +43,17 @@ unreleased) version of Git, that is available from the 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v2.4.5/git.html[documentation for release 2.4.5]
+* link:v2.5.0/git.html[documentation for release 2.5]
 
 * release notes for
+  link:RelNotes/2.5.0.txt[2.5].
+
+* link:v2.4.8/git.html[documentation for release 2.4.8]
+
+* release notes for
+  link:RelNotes/2.4.8.txt[2.4.8],
+  link:RelNotes/2.4.7.txt[2.4.7],
+  link:RelNotes/2.4.6.txt[2.4.6],
   link:RelNotes/2.4.5.txt[2.4.5],
   link:RelNotes/2.4.4.txt[2.4.4],
   link:RelNotes/2.4.3.txt[2.4.3],
@@ -773,7 +781,7 @@ The Git Repository
 ~~~~~~~~~~~~~~~~~~
 These environment variables apply to 'all' core Git commands. Nb: it
 is worth noting that they may be used/overridden by SCMS sitting above
-Git so take care if using Cogito etc.
+Git so take care if using a foreign front-end.
 
 'GIT_INDEX_FILE'::
        This environment allows the specification of an alternate
@@ -839,6 +847,15 @@ Git so take care if using Cogito etc.
        an explicit repository directory set via 'GIT_DIR' or on the
        command line.
 
+'GIT_COMMON_DIR'::
+       If this variable is set to a path, non-worktree files that are
+       normally in $GIT_DIR will be taken from this path
+       instead. Worktree-specific files such as HEAD or index are
+       taken from $GIT_DIR. See linkgit:gitrepository-layout[5] and
+       linkgit:git-worktree[1] for
+       details. This variable has lower precedence than other path
+       variables such as GIT_INDEX_FILE, GIT_OBJECT_DIRECTORY...
+
 Git Commits
 ~~~~~~~~~~~
 'GIT_AUTHOR_NAME'::
@@ -993,9 +1010,20 @@ Unsetting the variable, or setting it to empty, "0" or
        Enables trace messages for all packets coming in or out of a
        given program. This can help with debugging object negotiation
        or other protocol issues. Tracing is turned off at a packet
-       starting with "PACK".
+       starting with "PACK" (but see 'GIT_TRACE_PACKFILE' below).
        See 'GIT_TRACE' for available trace output options.
 
+'GIT_TRACE_PACKFILE'::
+       Enables tracing of packfiles sent or received by a
+       given program. Unlike other trace output, this trace is
+       verbatim: no headers, and no quoting of binary data. You almost
+       certainly want to direct into a file (e.g.,
+       `GIT_TRACE_PACKFILE=/tmp/my.pack`) rather than displaying it on
+       the terminal or mixing it with other trace output.
++
+Note that this is currently only implemented for the client side
+of clones and fetches.
+
 'GIT_TRACE_PERFORMANCE'::
        Enables performance related trace messages, e.g. total execution
        time of each Git command.
index 70899b3..e3b1de8 100644 (file)
@@ -527,6 +527,8 @@ patterns are available:
 
 - `fortran` suitable for source code in the Fortran language.
 
+- `fountain` suitable for Fountain documents.
+
 - `html` suitable for HTML/XHTML documents.
 
 - `java` suitable for source code in the Java language.
@@ -774,7 +776,7 @@ To define a custom merge driver `filfre`, add a section to your
 ----------------------------------------------------------------
 [merge "filfre"]
        name = feel-free merge driver
-       driver = filfre %O %A %B
+       driver = filfre %O %A %B %L %P
        recursive = binary
 ----------------------------------------------------------------
 
@@ -800,6 +802,9 @@ merge between common ancestors, when there are more than one.
 When left unspecified, the driver itself is used for both
 internal merge and the final merge.
 
+The merge driver can learn the pathname in which the merged result
+will be stored via placeholder `%P`.
+
 
 `conflict-marker-size`
 ^^^^^^^^^^^^^^^^^^^^^^
index 79653f3..577ee84 100644 (file)
@@ -46,6 +46,9 @@ of incomplete object store is not suitable to be published for
 use with dumb transports but otherwise is OK as long as
 `objects/info/alternates` points at the object stores it
 borrows from.
++
+This directory is ignored if $GIT_COMMON_DIR is set and
+"$GIT_COMMON_DIR/objects" will be used instead.
 
 objects/[0-9a-f][0-9a-f]::
        A newly created object is stored in its own file.
@@ -92,7 +95,8 @@ refs::
        References are stored in subdirectories of this
        directory.  The 'git prune' command knows to preserve
        objects reachable from refs found in this directory and
-       its subdirectories.
+       its subdirectories. This directory is ignored if $GIT_COMMON_DIR
+       is set and "$GIT_COMMON_DIR/refs" will be used instead.
 
 refs/heads/`name`::
        records tip-of-the-tree commit objects of branch `name`
@@ -114,7 +118,8 @@ refs/replace/`<obj-sha1>`::
 packed-refs::
        records the same information as refs/heads/, refs/tags/,
        and friends record in a more efficient way.  See
-       linkgit:git-pack-refs[1].
+       linkgit:git-pack-refs[1]. This file is ignored if $GIT_COMMON_DIR
+       is set and "$GIT_COMMON_DIR/packed-refs" will be used instead.
 
 HEAD::
        A symref (see glossary) to the `refs/heads/` namespace
@@ -133,6 +138,11 @@ being a symref to point at the current branch.  Such a state
 is often called 'detached HEAD.'  See linkgit:git-checkout[1]
 for details.
 
+config::
+       Repository specific configuration file. This file is ignored
+       if $GIT_COMMON_DIR is set and "$GIT_COMMON_DIR/config" will be
+       used instead.
+
 branches::
        A slightly deprecated way to store shorthands to be used
        to specify a URL to 'git fetch', 'git pull' and 'git push'.
@@ -140,7 +150,10 @@ branches::
        'name' can be given to these commands in place of
        'repository' argument.  See the REMOTES section in
        linkgit:git-fetch[1] for details.  This mechanism is legacy
-       and not likely to be found in modern repositories.
+       and not likely to be found in modern repositories. This
+       directory is ignored if $GIT_COMMON_DIR is set and
+       "$GIT_COMMON_DIR/branches" will be used instead.
+
 
 hooks::
        Hooks are customization scripts used by various Git
@@ -149,7 +162,9 @@ hooks::
        default.  To enable, the `.sample` suffix has to be
        removed from the filename by renaming.
        Read linkgit:githooks[5] for more details about
-       each hook.
+       each hook. This directory is ignored if $GIT_COMMON_DIR is set
+       and "$GIT_COMMON_DIR/hooks" will be used instead.
+
 
 index::
        The current index file for the repository.  It is
@@ -161,7 +176,8 @@ sharedindex.<SHA-1>::
 
 info::
        Additional information about the repository is recorded
-       in this directory.
+       in this directory. This directory is ignored if $GIT_COMMON_DIR
+       is set and "$GIT_COMMON_DIR/index" will be used instead.
 
 info/refs::
        This file helps dumb transports discover what refs are
@@ -201,12 +217,15 @@ remotes::
        when interacting with remote repositories via 'git fetch',
        'git pull' and 'git push' commands.  See the REMOTES section
        in linkgit:git-fetch[1] for details.  This mechanism is legacy
-       and not likely to be found in modern repositories.
+       and not likely to be found in modern repositories. This
+       directory is ignored if $GIT_COMMON_DIR is set and
+       "$GIT_COMMON_DIR/remotes" will be used instead.
 
 logs::
-       Records of changes made to refs are stored in this
-       directory.  See linkgit:git-update-ref[1]
-       for more information.
+       Records of changes made to refs are stored in this directory.
+       See linkgit:git-update-ref[1] for more information. This
+       directory is ignored if $GIT_COMMON_DIR is set and
+       "$GIT_COMMON_DIR/logs" will be used instead.
 
 logs/refs/heads/`name`::
        Records all changes made to the branch tip named `name`.
@@ -217,11 +236,46 @@ logs/refs/tags/`name`::
 shallow::
        This is similar to `info/grafts` but is internally used
        and maintained by shallow clone mechanism.  See `--depth`
-       option to linkgit:git-clone[1] and linkgit:git-fetch[1].
+       option to linkgit:git-clone[1] and linkgit:git-fetch[1]. This
+       file is ignored if $GIT_COMMON_DIR is set and
+       "$GIT_COMMON_DIR/shallow" will be used instead.
+
+commondir::
+       If this file exists, $GIT_COMMON_DIR (see linkgit:git[1]) will
+       be set to the path specified in this file if it is not
+       explicitly set. If the specified path is relative, it is
+       relative to $GIT_DIR. The repository with commondir is
+       incomplete without the repository pointed by "commondir".
 
 modules::
        Contains the git-repositories of the submodules.
 
+worktrees::
+       Contains administrative data for linked
+       working trees. Each subdirectory contains the working tree-related
+       part of a linked working tree. This directory is ignored if
+       $GIT_COMMON_DIR is set, in which case
+       "$GIT_COMMON_DIR/worktrees" will be used instead.
+
+worktrees/<id>/gitdir::
+       A text file containing the absolute path back to the .git file
+       that points to here. This is used to check if the linked
+       repository has been manually removed and there is no need to
+       keep this directory any more. The mtime of this file should be
+       updated every time the linked repository is accessed.
+
+worktrees/<id>/locked::
+       If this file exists, the linked working tree may be on a
+       portable device and not available. The presence of this file
+       prevents `worktrees/<id>` from being pruned either automatically
+       or manually by `git worktree prune`. The file may contain a string
+       explaining why the repository is locked.
+
+worktrees/<id>/link::
+       If this file exists, it is a hard link to the linked .git
+       file. It is used to detect if the linked repository is
+       manually removed.
+
 SEE ALSO
 --------
 linkgit:git-init[1],
index a096e7d..8a42270 100644 (file)
@@ -487,7 +487,7 @@ By default it is set to (), i.e. an empty list.  This means that gitweb
 would not try to create project URL (to fetch) from project name.
 
 $projects_list_group_categories::
-       Whether to enables the grouping of projects by category on the project
+       Whether to enable the grouping of projects by category on the project
        list page. The category of a project is determined by the
        `$GIT_DIR/category` file or the `gitweb.category` variable in each
        repository's configuration.  Disabled by default (set to 0).
index d7de5a3..6d772bd 100644 (file)
@@ -95,7 +95,9 @@ your language, document it in the INSTALL file.
 that categorizes commands by type, so they can be listed in appropriate
 subsections in the documentation's summary command list.  Add an entry
 for yours.  To understand the categories, look at git-commands.txt
-in the main directory.
+in the main directory.  If the new command is part of the typical Git
+workflow and you believe it common enough to be mentioned in 'git help',
+map this command to a common group in the column [common].
 
 7. Give the maintainer one paragraph to include in the RelNotes file
 to describe the new feature; a good place to do so is in the cover
index e9a1d5d..2dd79db 100644 (file)
@@ -1,18 +1,31 @@
-At the core level, Git is character encoding agnostic.
-
- - The pathnames recorded in the index and in the tree objects
-   are treated as uninterpreted sequences of non-NUL bytes.
-   What readdir(2) returns are what are recorded and compared
-   with the data Git keeps track of, which in turn are expected
-   to be what lstat(2) and creat(2) accepts.  There is no such
-   thing as pathname encoding translation.
+Git is to some extent character encoding agnostic.
 
  - The contents of the blob objects are uninterpreted sequences
    of bytes.  There is no encoding translation at the core
    level.
 
- - The commit log messages are uninterpreted sequences of non-NUL
-   bytes.
+ - Path names are encoded in UTF-8 normalization form C. This
+   applies to tree objects, the index file, ref names, as well as
+   path names in command line arguments, environment variables
+   and config files (`.git/config` (see linkgit:git-config[1]),
+   linkgit:gitignore[5], linkgit:gitattributes[5] and
+   linkgit:gitmodules[5]).
++
+Note that Git at the core level treats path names simply as
+sequences of non-NUL bytes, there are no path name encoding
+conversions (except on Mac and Windows). Therefore, using
+non-ASCII path names will mostly work even on platforms and file
+systems that use legacy extended ASCII encodings. However,
+repositories created on such systems will not work properly on
+UTF-8-based systems (e.g. Linux, Mac, Windows) and vice versa.
+Additionally, many Git-based tools simply assume path names to
+be UTF-8 and will fail to display other encodings correctly.
+
+ - Commit log messages are typically encoded in UTF-8, but other
+   extended ASCII encodings are also supported. This includes
+   ISO-8859-x, CP125x and many others, but _not_ UTF-16/32,
+   EBCDIC and CJK multi-byte encodings (GBK, Shift-JIS, Big5,
+   EUC-x, CP9xx etc.).
 
 Although we encourage that the commit log messages are encoded
 in UTF-8, both the core and Git Porcelain are designed not to
index 74aa01a..642af6e 100644 (file)
@@ -37,7 +37,10 @@ people using 80-column terminals.
        in their encoding header; this option can be used to tell the
        command to re-code the commit log message in the encoding
        preferred by the user.  For non plumbing commands this
-       defaults to UTF-8.
+       defaults to UTF-8. Note that if an object claims to be encoded
+       in `X` and we are outputting in `X`, we will output the object
+       verbatim; this means that invalid sequences in the original
+       commit may be copied to the output.
 
 --notes[=<ref>]::
        Show the notes (see linkgit:git-notes[1]) that annotate the
index 77ac439..a9b808f 100644 (file)
@@ -727,6 +727,11 @@ format, often found in email messages.
 +
 `--date=raw` shows the date in the internal raw Git format `%s %z` format.
 +
+`--date=format:...` feeds the format `...` to your system `strftime`.
+Use `--date=format:%c` to show the date in your system locale's
+preferred format.  See the `strftime` manual for a complete list of
+format placeholders.
++
 `--date=default` shows timestamps in the original time zone
 (either committer's or author's).
 
index 0796118..d85e303 100644 (file)
@@ -98,6 +98,31 @@ some output processing may assume ref names in UTF-8.
   `branch.<name>.merge`).  A missing branchname defaults to the
   current one.
 
+'<branchname>@\{push\}', e.g. 'master@\{push\}', '@\{push\}'::
+  The suffix '@\{push}' reports the branch "where we would push to" if
+  `git push` were run while `branchname` was checked out (or the current
+  'HEAD' if no branchname is specified). Since our push destination is
+  in a remote repository, of course, we report the local tracking branch
+  that corresponds to that branch (i.e., something in 'refs/remotes/').
++
+Here's an example to make it more clear:
++
+------------------------------
+$ git config push.default current
+$ git config remote.pushdefault myfork
+$ git checkout -b mybranch origin/master
+
+$ git rev-parse --symbolic-full-name @{upstream}
+refs/remotes/origin/master
+
+$ git rev-parse --symbolic-full-name @{push}
+refs/remotes/myfork/mybranch
+------------------------------
++
+Note in the example that we set up a triangular workflow, where we pull
+from one location and push to another. In a non-triangular workflow,
+'@\{push}' is the same as '@\{upstream}', and there is no need for it.
+
 '<rev>{caret}', e.g. 'HEAD{caret}, v1.5.1{caret}0'::
   A suffix '{caret}' to a revision parameter means the first parent of
   that commit object.  '{caret}<n>' means the <n>th parent (i.e.
index 1a79781..8076172 100644 (file)
@@ -46,6 +46,9 @@ Functions
        Format a string and push it onto the end of the array. This is a
        convenience wrapper combining `strbuf_addf` and `argv_array_push`.
 
+`argv_array_pushv`::
+       Push a null-terminated array of strings onto the end of the array.
+
 `argv_array_pop`::
        Remove the final element from the array. If there are no
        elements in the array, do nothing.
index 1f2db31..5f0757d 100644 (file)
@@ -168,6 +168,12 @@ There are some macros to easily define options:
        Introduce an option with integer argument.
        The integer is put into `int_var`.
 
+`OPT_MAGNITUDE(short, long, &unsigned_long_var, description)`::
+       Introduce an option with a size argument. The argument must be a
+       non-negative integer and may include a suffix of 'k', 'm' or 'g' to
+       scale the provided value by 1024, 1024^2 or 1024^3 respectively.
+       The scaled value is put into `unsigned_long_var`.
+
 `OPT_DATE(short, long, &int_var, description)`::
        Introduce an option with date argument, see `approxidate()`.
        The timestamp is put into `int_var`.
@@ -212,6 +218,19 @@ There are some macros to easily define options:
        Use it to hide deprecated options that are still to be recognized
        and ignored silently.
 
+`OPT_PASSTHRU(short, long, &char_var, arg_str, description, flags)`::
+       Introduce an option that will be reconstructed into a char* string,
+       which must be initialized to NULL. This is useful when you need to
+       pass the command-line option to another command. Any previous value
+       will be overwritten, so this should only be used for options where
+       the last one specified on the command line wins.
+
+`OPT_PASSTHRU_ARGV(short, long, &argv_array_var, arg_str, description, flags)`::
+       Introduce an option where all instances of it on the command-line will
+       be reconstructed into an argv_array. This is useful when you need to
+       pass the command-line option, which can be specified multiple times,
+       to another command.
+
 
 The last element of the array must be `OPT_END()`.
 
index 02adfd4..37379d8 100644 (file)
@@ -6,7 +6,7 @@ Iteration of refs is done by using an iterate function which will call a
 callback function for every ref. The callback function has this
 signature:
 
-       int handle_one_ref(const char *refname, const unsigned char *sha1,
+       int handle_one_ref(const char *refname, const struct object_id *oid,
                           int flags, void *cb_data);
 
 There are different kinds of iterate functions which all take a
index 5d245aa..2cfdd22 100644 (file)
@@ -97,10 +97,6 @@ It contains:
 
        The name of the remote listed in the configuration.
 
-`remote`::
-
-       The struct remote for that remote.
-
 `merge_name`::
 
        An array of the "merge" lines in the configuration.
index 229f845..1c561bd 100644 (file)
@@ -319,7 +319,8 @@ Servers SHOULD support all capabilities defined here.
 Clients MUST send at least one "want" command in the request body.
 Clients MUST NOT reference an id in a "want" command which did not
 appear in the response obtained through ref discovery unless the
-server advertises capability `allow-tip-sha1-in-want`.
+server advertises capability `allow-tip-sha1-in-want` or
+`allow-reachable-sha1-in-want`.
 
   compute_request   =  want_list
                       have_list
index 35112e4..7392ff6 100644 (file)
@@ -233,3 +233,65 @@ Git index format
   The remaining index entries after replaced ones will be added to the
   final index. These added entries are also sorted by entry name then
   stage.
+
+== Untracked cache
+
+  Untracked cache saves the untracked file list and necessary data to
+  verify the cache. The signature for this extension is { 'U', 'N',
+  'T', 'R' }.
+
+  The extension starts with
+
+  - A sequence of NUL-terminated strings, preceded by the size of the
+    sequence in variable width encoding. Each string describes the
+    environment where the cache can be used.
+
+  - Stat data of $GIT_DIR/info/exclude. See "Index entry" section from
+    ctime field until "file size".
+
+  - Stat data of core.excludesfile
+
+  - 32-bit dir_flags (see struct dir_struct)
+
+  - 160-bit SHA-1 of $GIT_DIR/info/exclude. Null SHA-1 means the file
+    does not exist.
+
+  - 160-bit SHA-1 of core.excludesfile. Null SHA-1 means the file does
+    not exist.
+
+  - NUL-terminated string of per-dir exclude file name. This usually
+    is ".gitignore".
+
+  - The number of following directory blocks, variable width
+    encoding. If this number is zero, the extension ends here with a
+    following NUL.
+
+  - A number of directory blocks in depth-first-search order, each
+    consists of
+
+    - The number of untracked entries, variable width encoding.
+
+    - The number of sub-directory blocks, variable width encoding.
+
+    - The directory name terminated by NUL.
+
+    - A number of untracked file/dir names terminated by NUL.
+
+The remaining data of each directory block is grouped by type:
+
+  - An ewah bitmap, the n-th bit marks whether the n-th directory has
+    valid untracked cache entries.
+
+  - An ewah bitmap, the n-th bit records "check-only" bit of
+    read_directory_recursive() for the n-th directory.
+
+  - An ewah bitmap, the n-th bit indicates whether SHA-1 and stat data
+    is valid for the n-th directory and exists in the next data.
+
+  - An array of stat data. The n-th data corresponds with the n-th
+    "one" bit in the previous ewah bitmap.
+
+  - An array of SHA-1. The n-th SHA-1 corresponds with the n-th "one" bit
+    in the previous ewah bitmap.
+
+  - One NUL.
index 4f8a7bf..eaab6b4 100644 (file)
@@ -260,6 +260,13 @@ If the upload-pack server advertises this capability, fetch-pack may
 send "want" lines with SHA-1s that exist at the server but are not
 advertised by upload-pack.
 
+allow-reachable-sha1-in-want
+----------------------------
+
+If the upload-pack server advertises this capability, fetch-pack may
+send "want" lines with SHA-1s that exist at the server but are not
+advertised by upload-pack.
+
 push-cert=<nonce>
 -----------------
 
index 242a044..4a8be4d 100644 (file)
@@ -41,13 +41,17 @@ With a `USE_STDEV` compile-time option, `st_dev` is also
 compared, but this is not enabled by default because this member
 is not stable on network filesystems.  With `USE_NSEC`
 compile-time option, `st_mtim.tv_nsec` and `st_ctim.tv_nsec`
-members are also compared, but this is not enabled by default
+members are also compared. On Linux, this is not enabled by default
 because in-core timestamps can have finer granularity than
 on-disk timestamps, resulting in meaningless changes when an
 inode is evicted from the inode cache.  See commit 8ce13b0
 of git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
 ([PATCH] Sync in core time granularity with filesystems,
-2005-01-04).
+2005-01-04). This patch is included in kernel 2.6.11 and newer, but
+only fixes the issue for file systems with exactly 1 ns or 1 s
+resolution. Other file systems are still broken in current Linux
+kernels (e.g. CEPH, CIFS, NTFS, UDF), see
+https://lkml.org/lkml/2015/6/9/714
 
 Racy Git
 --------
index 159d526..fc45283 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.4.5
+DEF_VER=v2.5.0.GIT
 
 LF='
 '
@@ -38,5 +38,3 @@ test "$VN" = "$VC" || {
        echo >&2 "GIT_VERSION = $VN"
        echo "GIT_VERSION = $VN" >$GVF
 }
-
-
index 8700db8..e39ca6c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -217,10 +217,11 @@ all::
 # as the compiler can crash (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49299)
 #
 # Define USE_NSEC below if you want git to care about sub-second file mtimes
-# and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and
-# it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely
-# randomly break unless your underlying filesystem supports those sub-second
-# times (my ext3 doesn't).
+# and ctimes. Note that you need recent glibc (at least 2.2.4) for this. On
+# Linux, kernel 2.6.11 or newer is required for reliable sub-second file times
+# on file systems with exactly 1 ns or 1 s resolution. If you intend to use Git
+# on other file systems (e.g. CEPH, CIFS, NTFS, UDF), don't enable USE_NSEC. See
+# Documentation/technical/racy-git.txt for details.
 #
 # Define USE_ST_TIMESPEC if your "struct stat" uses "st_ctimespec" instead of
 # "st_ctim"
@@ -359,6 +360,8 @@ all::
 # compiler is detected to support it.
 #
 # Define HAVE_BSD_SYSCTL if your platform has a BSD-compatible sysctl function.
+#
+# Define HAVE_GETDELIM if your system has the getdelim() function.
 
 GIT-VERSION-FILE: FORCE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -464,7 +467,6 @@ TEST_PROGRAMS_NEED_X =
 # interactive shell sessions without exporting it.
 unexport CDPATH
 
-SCRIPT_SH += git-am.sh
 SCRIPT_SH += git-bisect.sh
 SCRIPT_SH += git-difftool--helper.sh
 SCRIPT_SH += git-filter-branch.sh
@@ -472,7 +474,6 @@ SCRIPT_SH += git-merge-octopus.sh
 SCRIPT_SH += git-merge-one-file.sh
 SCRIPT_SH += git-merge-resolve.sh
 SCRIPT_SH += git-mergetool.sh
-SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
@@ -572,6 +573,7 @@ TEST_PROGRAMS_NEED_X += test-date
 TEST_PROGRAMS_NEED_X += test-delta
 TEST_PROGRAMS_NEED_X += test-dump-cache-tree
 TEST_PROGRAMS_NEED_X += test-dump-split-index
+TEST_PROGRAMS_NEED_X += test-dump-untracked-cache
 TEST_PROGRAMS_NEED_X += test-genrandom
 TEST_PROGRAMS_NEED_X += test-hashmap
 TEST_PROGRAMS_NEED_X += test-index-version
@@ -759,6 +761,7 @@ LIB_OBJS += reachable.o
 LIB_OBJS += read-cache.o
 LIB_OBJS += reflog-walk.o
 LIB_OBJS += refs.o
+LIB_OBJS += ref-filter.o
 LIB_OBJS += remote.o
 LIB_OBJS += replace_object.o
 LIB_OBJS += rerere.o
@@ -809,6 +812,7 @@ LIB_OBJS += xdiff-interface.o
 LIB_OBJS += zlib.o
 
 BUILTIN_OBJS += builtin/add.o
+BUILTIN_OBJS += builtin/am.o
 BUILTIN_OBJS += builtin/annotate.o
 BUILTIN_OBJS += builtin/apply.o
 BUILTIN_OBJS += builtin/archive.o
@@ -874,6 +878,7 @@ BUILTIN_OBJS += builtin/pack-refs.o
 BUILTIN_OBJS += builtin/patch-id.o
 BUILTIN_OBJS += builtin/prune-packed.o
 BUILTIN_OBJS += builtin/prune.o
+BUILTIN_OBJS += builtin/pull.o
 BUILTIN_OBJS += builtin/push.o
 BUILTIN_OBJS += builtin/read-tree.o
 BUILTIN_OBJS += builtin/receive-pack.o
@@ -906,6 +911,7 @@ BUILTIN_OBJS += builtin/var.o
 BUILTIN_OBJS += builtin/verify-commit.o
 BUILTIN_OBJS += builtin/verify-pack.o
 BUILTIN_OBJS += builtin/verify-tag.o
+BUILTIN_OBJS += builtin/worktree.o
 BUILTIN_OBJS += builtin/write-tree.o
 
 GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
@@ -1437,6 +1443,10 @@ ifdef HAVE_BSD_SYSCTL
        BASIC_CFLAGS += -DHAVE_BSD_SYSCTL
 endif
 
+ifdef HAVE_GETDELIM
+       BASIC_CFLAGS += -DHAVE_GETDELIM
+endif
+
 ifeq ($(TCLTK_PATH),)
 NO_TCLTK = NoThanks
 endif
@@ -1687,10 +1697,10 @@ $(BUILT_INS): git$X
        ln -s $< $@ 2>/dev/null || \
        cp $< $@
 
-common-cmds.h: ./generate-cmdlist.sh command-list.txt
+common-cmds.h: generate-cmdlist.perl command-list.txt
 
 common-cmds.h: $(wildcard Documentation/git-*.txt)
-       $(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@
+       $(QUIET_GEN)$(PERL_PATH) generate-cmdlist.perl command-list.txt > $@+ && mv $@+ $@
 
 SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
        $(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
@@ -2449,7 +2459,7 @@ check-docs::
                esac ; \
                test -f "Documentation/$$v.txt" || \
                echo "no doc: $$v"; \
-               sed -e '/^#/d' command-list.txt | \
+               sed -e '1,/^### command list/d' -e '/^#/d' command-list.txt | \
                grep -q "^$$v[  ]" || \
                case "$$v" in \
                git) ;; \
@@ -2457,7 +2467,8 @@ check-docs::
                esac ; \
        done; \
        ( \
-               sed -e '/^#/d' \
+               sed -e '1,/^### command list/d' \
+                   -e '/^#/d' \
                    -e 's/[     ].*//' \
                    -e 's/^/listed /' command-list.txt; \
                $(MAKE) -C Documentation print-man1 | \
index 7b5f2ec..84a20c8 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.4.5.txt
\ No newline at end of file
+Documentation/RelNotes/2.6.0.txt
\ No newline at end of file
index 575bec2..4965686 100644 (file)
--- a/advice.c
+++ b/advice.c
@@ -96,6 +96,14 @@ void NORETURN die_resolve_conflict(const char *me)
        die("Exiting because of an unresolved conflict.");
 }
 
+void NORETURN die_conclude_merge(void)
+{
+       error(_("You have not concluded your merge (MERGE_HEAD exists)."));
+       if (advice_resolve_conflict)
+               advise(_("Please, commit your changes before you can merge."));
+       die(_("Exiting because of unfinished merge."));
+}
+
 void detach_advice(const char *new_name)
 {
        const char fmt[] =
index 5ecc6c1..b341a55 100644 (file)
--- a/advice.h
+++ b/advice.h
@@ -24,6 +24,7 @@ __attribute__((format (printf, 1, 2)))
 void advise(const char *advice, ...);
 int error_resolve_conflict(const char *me);
 extern void NORETURN die_resolve_conflict(const char *me);
+void NORETURN die_conclude_merge(void);
 void detach_advice(const char *new_name);
 
 #endif /* ADVICE_H */
index ffb3535..ae3d67f 100644 (file)
@@ -448,12 +448,12 @@ static void write_zip_trailer(const unsigned char *sha1)
        copy_le16(trailer.entries, zip_dir_entries);
        copy_le32(trailer.size, zip_dir_offset);
        copy_le32(trailer.offset, zip_offset);
-       copy_le16(trailer.comment_length, sha1 ? 40 : 0);
+       copy_le16(trailer.comment_length, sha1 ? GIT_SHA1_HEXSZ : 0);
 
        write_or_die(1, zip_dir, zip_dir_offset);
        write_or_die(1, &trailer, ZIP_DIR_TRAILER_SIZE);
        if (sha1)
-               write_or_die(1, sha1_to_hex(sha1), 40);
+               write_or_die(1, sha1_to_hex(sha1), GIT_SHA1_HEXSZ);
 }
 
 static void dos_time(time_t *time, int *dos_date, int *dos_time)
index 96057ed..01b0899 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "refs.h"
 #include "commit.h"
 #include "tree-walk.h"
 #include "attr.h"
@@ -33,7 +34,7 @@ static void format_subst(const struct commit *commit,
        char *to_free = NULL;
        struct strbuf fmt = STRBUF_INIT;
        struct pretty_print_context ctx = {0};
-       ctx.date_mode = DATE_NORMAL;
+       ctx.date_mode.type = DATE_NORMAL;
        ctx.abbrev = DEFAULT_ABBREV;
 
        if (src == buf->buf)
@@ -101,7 +102,7 @@ static void setup_archive_check(struct git_attr_check *check)
 
 struct directory {
        struct directory *up;
-       unsigned char sha1[20];
+       struct object_id oid;
        int baselen, len;
        unsigned mode;
        int stage;
@@ -177,7 +178,7 @@ static void queue_directory(const unsigned char *sha1,
        d->stage   = stage;
        c->bottom  = d;
        d->len = sprintf(d->path, "%.*s%s/", (int)base->len, base->buf, filename);
-       hashcpy(d->sha1, sha1);
+       hashcpy(d->oid.hash, sha1);
 }
 
 static int write_directory(struct archiver_context *c)
@@ -191,7 +192,7 @@ static int write_directory(struct archiver_context *c)
        d->path[d->len - 1] = '\0'; /* no trailing slash */
        ret =
                write_directory(c) ||
-               write_archive_entry(d->sha1, d->path, d->baselen,
+               write_archive_entry(d->oid.hash, d->path, d->baselen,
                                    d->path + d->baselen, d->mode,
                                    d->stage, c) != READ_TREE_RECURSIVE;
        free(d);
@@ -354,7 +355,7 @@ static void parse_treeish_arg(const char **argv,
        time_t archive_time;
        struct tree *tree;
        const struct commit *commit;
-       unsigned char sha1[20];
+       struct object_id oid;
 
        /* Remotes are only allowed to fetch actual refs */
        if (remote && !remote_allow_unreachable) {
@@ -362,15 +363,15 @@ static void parse_treeish_arg(const char **argv,
                const char *colon = strchrnul(name, ':');
                int refnamelen = colon - name;
 
-               if (!dwim_ref(name, refnamelen, sha1, &ref))
+               if (!dwim_ref(name, refnamelen, oid.hash, &ref))
                        die("no such ref: %.*s", refnamelen, name);
                free(ref);
        }
 
-       if (get_sha1(name, sha1))
+       if (get_sha1(name, oid.hash))
                die("Not a valid object name");
 
-       commit = lookup_commit_reference_gently(sha1, 1);
+       commit = lookup_commit_reference_gently(oid.hash, 1);
        if (commit) {
                commit_sha1 = commit->object.sha1;
                archive_time = commit->date;
@@ -379,21 +380,21 @@ static void parse_treeish_arg(const char **argv,
                archive_time = time(NULL);
        }
 
-       tree = parse_tree_indirect(sha1);
+       tree = parse_tree_indirect(oid.hash);
        if (tree == NULL)
                die("not a tree object");
 
        if (prefix) {
-               unsigned char tree_sha1[20];
+               struct object_id tree_oid;
                unsigned int mode;
                int err;
 
                err = get_tree_entry(tree->object.sha1, prefix,
-                                    tree_sha1, &mode);
+                                    tree_oid.hash, &mode);
                if (err || !S_ISDIR(mode))
                        die("current working directory is untracked");
 
-               tree = parse_tree_indirect(tree_sha1);
+               tree = parse_tree_indirect(tree_oid.hash);
        }
        ar_args->tree = tree;
        ar_args->commit_sha1 = commit_sha1;
index 256741d..eaed477 100644 (file)
@@ -49,6 +49,12 @@ void argv_array_pushl(struct argv_array *array, ...)
        va_end(ap);
 }
 
+void argv_array_pushv(struct argv_array *array, const char **argv)
+{
+       for (; *argv; argv++)
+               argv_array_push(array, *argv);
+}
+
 void argv_array_pop(struct argv_array *array)
 {
        if (!array->argc)
index c65e6e8..a2fa0aa 100644 (file)
@@ -17,6 +17,7 @@ __attribute__((format (printf,2,3)))
 void argv_array_pushf(struct argv_array *, const char *fmt, ...);
 LAST_ARG_MUST_BE_NULL
 void argv_array_pushl(struct argv_array *, ...);
+void argv_array_pushv(struct argv_array *, const char **);
 void argv_array_pop(struct argv_array *);
 void argv_array_clear(struct argv_array *);
 
index 8c6d843..857cf59 100644 (file)
--- a/bisect.c
+++ b/bisect.c
 static struct sha1_array good_revs;
 static struct sha1_array skipped_revs;
 
-static unsigned char *current_bad_sha1;
+static struct object_id *current_bad_oid;
 
 static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
 static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
 static const char *argv_update_ref[] = {"update-ref", "--no-deref", "BISECT_HEAD", NULL, NULL};
 
+static const char *term_bad;
+static const char *term_good;
+
 /* Remember to update object flag allocation in object.h */
 #define COUNTED                (1u<<16)
 
@@ -400,18 +403,24 @@ struct commit_list *find_bisection(struct commit_list *list,
        return best;
 }
 
-static int register_ref(const char *refname, const unsigned char *sha1,
+static int register_ref(const char *refname, const struct object_id *oid,
                        int flags, void *cb_data)
 {
-       if (!strcmp(refname, "bad")) {
-               current_bad_sha1 = xmalloc(20);
-               hashcpy(current_bad_sha1, sha1);
-       } else if (starts_with(refname, "good-")) {
-               sha1_array_append(&good_revs, sha1);
+       struct strbuf good_prefix = STRBUF_INIT;
+       strbuf_addstr(&good_prefix, term_good);
+       strbuf_addstr(&good_prefix, "-");
+
+       if (!strcmp(refname, term_bad)) {
+               current_bad_oid = xmalloc(sizeof(*current_bad_oid));
+               oidcpy(current_bad_oid, oid);
+       } else if (starts_with(refname, good_prefix.buf)) {
+               sha1_array_append(&good_revs, oid->hash);
        } else if (starts_with(refname, "skip-")) {
-               sha1_array_append(&skipped_revs, sha1);
+               sha1_array_append(&skipped_revs, oid->hash);
        }
 
+       strbuf_release(&good_prefix);
+
        return 0;
 }
 
@@ -564,7 +573,7 @@ static struct commit_list *skip_away(struct commit_list *list, int count)
 
        for (i = 0; cur; cur = cur->next, i++) {
                if (i == index) {
-                       if (hashcmp(cur->item->object.sha1, current_bad_sha1))
+                       if (hashcmp(cur->item->object.sha1, current_bad_oid->hash))
                                return cur;
                        if (previous)
                                return previous;
@@ -607,7 +616,7 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix,
 
        /* rev_argv.argv[0] will be ignored by setup_revisions */
        argv_array_push(&rev_argv, "bisect_rev_setup");
-       argv_array_pushf(&rev_argv, bad_format, sha1_to_hex(current_bad_sha1));
+       argv_array_pushf(&rev_argv, bad_format, oid_to_hex(current_bad_oid));
        for (i = 0; i < good_revs.nr; i++)
                argv_array_pushf(&rev_argv, good_format,
                                 sha1_to_hex(good_revs.sha1[i]));
@@ -628,21 +637,21 @@ static void bisect_common(struct rev_info *revs)
 }
 
 static void exit_if_skipped_commits(struct commit_list *tried,
-                                   const unsigned char *bad)
+                                   const struct object_id *bad)
 {
        if (!tried)
                return;
 
        printf("There are only 'skip'ped commits left to test.\n"
-              "The first bad commit could be any of:\n");
+              "The first %s commit could be any of:\n", term_bad);
        print_commit_list(tried, "%s\n", "%s\n");
        if (bad)
-               printf("%s\n", sha1_to_hex(bad));
+               printf("%s\n", oid_to_hex(bad));
        printf("We cannot bisect more!\n");
        exit(2);
 }
 
-static int is_expected_rev(const unsigned char *sha1)
+static int is_expected_rev(const struct object_id *oid)
 {
        const char *filename = git_path("BISECT_EXPECTED_REV");
        struct stat st;
@@ -658,7 +667,7 @@ static int is_expected_rev(const unsigned char *sha1)
                return 0;
 
        if (strbuf_getline(&str, fp, '\n') != EOF)
-               res = !strcmp(str.buf, sha1_to_hex(sha1));
+               res = !strcmp(str.buf, oid_to_hex(oid));
 
        strbuf_release(&str);
        fclose(fp);
@@ -719,7 +728,7 @@ static struct commit **get_bad_and_good_commits(int *rev_nr)
        struct commit **rev = xmalloc(len * sizeof(*rev));
        int i, n = 0;
 
-       rev[n++] = get_commit_reference(current_bad_sha1);
+       rev[n++] = get_commit_reference(current_bad_oid->hash);
        for (i = 0; i < good_revs.nr; i++)
                rev[n++] = get_commit_reference(good_revs.sha1[i]);
        *rev_nr = n;
@@ -729,36 +738,42 @@ static struct commit **get_bad_and_good_commits(int *rev_nr)
 
 static void handle_bad_merge_base(void)
 {
-       if (is_expected_rev(current_bad_sha1)) {
-               char *bad_hex = sha1_to_hex(current_bad_sha1);
+       if (is_expected_rev(current_bad_oid)) {
+               char *bad_hex = oid_to_hex(current_bad_oid);
                char *good_hex = join_sha1_array_hex(&good_revs, ' ');
-
-               fprintf(stderr, "The merge base %s is bad.\n"
-                       "This means the bug has been fixed "
-                       "between %s and [%s].\n",
-                       bad_hex, bad_hex, good_hex);
-
+               if (!strcmp(term_bad, "bad") && !strcmp(term_good, "good")) {
+                       fprintf(stderr, "The merge base %s is bad.\n"
+                               "This means the bug has been fixed "
+                               "between %s and [%s].\n",
+                               bad_hex, bad_hex, good_hex);
+               } else {
+                       fprintf(stderr, "The merge base %s is %s.\n"
+                               "This means the first '%s' commit is "
+                               "between %s and [%s].\n",
+                               bad_hex, term_bad, term_good, bad_hex, good_hex);
+               }
                exit(3);
        }
 
-       fprintf(stderr, "Some good revs are not ancestor of the bad rev.\n"
+       fprintf(stderr, "Some %s revs are not ancestor of the %s rev.\n"
                "git bisect cannot work properly in this case.\n"
-               "Maybe you mistake good and bad revs?\n");
+               "Maybe you mistook %s and %s revs?\n",
+               term_good, term_bad, term_good, term_bad);
        exit(1);
 }
 
 static void handle_skipped_merge_base(const unsigned char *mb)
 {
        char *mb_hex = sha1_to_hex(mb);
-       char *bad_hex = sha1_to_hex(current_bad_sha1);
+       char *bad_hex = sha1_to_hex(current_bad_oid->hash);
        char *good_hex = join_sha1_array_hex(&good_revs, ' ');
 
        warning("the merge base between %s and [%s] "
                "must be skipped.\n"
-               "So we cannot be sure the first bad commit is "
+               "So we cannot be sure the first %s commit is "
                "between %s and %s.\n"
                "We continue anyway.",
-               bad_hex, good_hex, mb_hex, bad_hex);
+               bad_hex, good_hex, term_bad, mb_hex, bad_hex);
        free(good_hex);
 }
 
@@ -781,7 +796,7 @@ static void check_merge_bases(int no_checkout)
 
        for (; result; result = result->next) {
                const unsigned char *mb = result->item->object.sha1;
-               if (!hashcmp(mb, current_bad_sha1)) {
+               if (!hashcmp(mb, current_bad_oid->hash)) {
                        handle_bad_merge_base();
                } else if (0 <= sha1_array_lookup(&good_revs, mb)) {
                        continue;
@@ -838,8 +853,8 @@ static void check_good_are_ancestors_of_bad(const char *prefix, int no_checkout)
        struct stat st;
        int fd;
 
-       if (!current_bad_sha1)
-               die("a bad revision is needed");
+       if (!current_bad_oid)
+               die("a %s revision is needed", term_bad);
 
        /* Check if file BISECT_ANCESTORS_OK exists. */
        if (!stat(filename, &st) && S_ISREG(st.st_mode))
@@ -889,6 +904,36 @@ static void show_diff_tree(const char *prefix, struct commit *commit)
        log_tree_commit(&opt, commit);
 }
 
+/*
+ * The terms used for this bisect session are stored in BISECT_TERMS.
+ * We read them and store them to adapt the messages accordingly.
+ * Default is bad/good.
+ */
+void read_bisect_terms(const char **read_bad, const char **read_good)
+{
+       struct strbuf str = STRBUF_INIT;
+       const char *filename = git_path("BISECT_TERMS");
+       FILE *fp = fopen(filename, "r");
+
+       if (!fp) {
+               if (errno == ENOENT) {
+                       *read_bad = "bad";
+                       *read_good = "good";
+                       return;
+               } else {
+                       die("could not read file '%s': %s", filename,
+                               strerror(errno));
+               }
+       } else {
+               strbuf_getline(&str, fp, '\n');
+               *read_bad = strbuf_detach(&str, NULL);
+               strbuf_getline(&str, fp, '\n');
+               *read_good = strbuf_detach(&str, NULL);
+       }
+       strbuf_release(&str);
+       fclose(fp);
+}
+
 /*
  * We use the convention that exiting with an exit code 10 means that
  * the bisection process finished successfully.
@@ -903,8 +948,9 @@ int bisect_next_all(const char *prefix, int no_checkout)
        struct commit_list *tried;
        int reaches = 0, all = 0, nr, steps;
        const unsigned char *bisect_rev;
-       char bisect_rev_hex[41];
+       char bisect_rev_hex[GIT_SHA1_HEXSZ + 1];
 
+       read_bisect_terms(&term_bad, &term_good);
        if (read_bisect_refs())
                die("reading bisect refs failed");
 
@@ -926,8 +972,10 @@ int bisect_next_all(const char *prefix, int no_checkout)
                 */
                exit_if_skipped_commits(tried, NULL);
 
-               printf("%s was both good and bad\n",
-                      sha1_to_hex(current_bad_sha1));
+               printf("%s was both %s and %s\n",
+                      oid_to_hex(current_bad_oid),
+                      term_good,
+                      term_bad);
                exit(1);
        }
 
@@ -938,11 +986,12 @@ int bisect_next_all(const char *prefix, int no_checkout)
        }
 
        bisect_rev = revs.commits->item->object.sha1;
-       memcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), 41);
+       memcpy(bisect_rev_hex, sha1_to_hex(bisect_rev), GIT_SHA1_HEXSZ + 1);
 
-       if (!hashcmp(bisect_rev, current_bad_sha1)) {
-               exit_if_skipped_commits(tried, current_bad_sha1);
-               printf("%s is the first bad commit\n", bisect_rev_hex);
+       if (!hashcmp(bisect_rev, current_bad_oid->hash)) {
+               exit_if_skipped_commits(tried, current_bad_oid);
+               printf("%s is the first %s commit\n", bisect_rev_hex,
+                       term_bad);
                show_diff_tree(prefix, revs.commits->item);
                /* This means the bisection process succeeded. */
                exit(10);
index 2a6c831..acd12ef 100644 (file)
--- a/bisect.h
+++ b/bisect.h
@@ -26,4 +26,6 @@ extern int bisect_next_all(const char *prefix, int no_checkout);
 
 extern int estimate_bisect_steps(int all);
 
+extern void read_bisect_terms(const char **bad, const char **good);
+
 #endif
index b002435..c85be07 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -310,3 +310,70 @@ void remove_branch_state(void)
        unlink(git_path("MERGE_MODE"));
        unlink(git_path("SQUASH_MSG"));
 }
+
+static void check_linked_checkout(const char *branch, const char *id)
+{
+       struct strbuf sb = STRBUF_INIT;
+       struct strbuf path = STRBUF_INIT;
+       struct strbuf gitdir = STRBUF_INIT;
+
+       /*
+        * $GIT_COMMON_DIR/HEAD is practically outside
+        * $GIT_DIR so resolve_ref_unsafe() won't work (it
+        * uses git_path). Parse the ref ourselves.
+        */
+       if (id)
+               strbuf_addf(&path, "%s/worktrees/%s/HEAD", get_git_common_dir(), id);
+       else
+               strbuf_addf(&path, "%s/HEAD", get_git_common_dir());
+
+       if (!strbuf_readlink(&sb, path.buf, 0)) {
+               if (!starts_with(sb.buf, "refs/") ||
+                   check_refname_format(sb.buf, 0))
+                       goto done;
+       } else if (strbuf_read_file(&sb, path.buf, 0) >= 0 &&
+           starts_with(sb.buf, "ref:")) {
+               strbuf_remove(&sb, 0, strlen("ref:"));
+               strbuf_trim(&sb);
+       } else
+               goto done;
+       if (strcmp(sb.buf, branch))
+               goto done;
+       if (id) {
+               strbuf_reset(&path);
+               strbuf_addf(&path, "%s/worktrees/%s/gitdir", get_git_common_dir(), id);
+               if (strbuf_read_file(&gitdir, path.buf, 0) <= 0)
+                       goto done;
+               strbuf_rtrim(&gitdir);
+       } else
+               strbuf_addstr(&gitdir, get_git_common_dir());
+       skip_prefix(branch, "refs/heads/", &branch);
+       strbuf_strip_suffix(&gitdir, ".git");
+       die(_("'%s' is already checked out at '%s'"), branch, gitdir.buf);
+done:
+       strbuf_release(&path);
+       strbuf_release(&sb);
+       strbuf_release(&gitdir);
+}
+
+void die_if_checked_out(const char *branch)
+{
+       struct strbuf path = STRBUF_INIT;
+       DIR *dir;
+       struct dirent *d;
+
+       check_linked_checkout(branch, NULL);
+
+       strbuf_addf(&path, "%s/worktrees", get_git_common_dir());
+       dir = opendir(path.buf);
+       strbuf_release(&path);
+       if (!dir)
+               return;
+
+       while ((d = readdir(dir)) != NULL) {
+               if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+                       continue;
+               check_linked_checkout(branch, d->d_name);
+       }
+       closedir(dir);
+}
index 64173ab..58aa45f 100644 (file)
--- a/branch.h
+++ b/branch.h
@@ -52,4 +52,11 @@ extern void install_branch_config(int flag, const char *local, const char *origi
  */
 extern int read_branch_desc(struct strbuf *, const char *branch_name);
 
+/*
+ * Check if a branch is checked out in the main worktree or any linked
+ * worktree and die (with a message describing its checkout location) if
+ * it is.
+ */
+extern void die_if_checked_out(const char *branch);
+
 #endif
index b87df70..79aaf0a 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -30,6 +30,7 @@ extern int textconv_object(const char *path, unsigned mode, const unsigned char
 extern int is_builtin(const char *s);
 
 extern int cmd_add(int argc, const char **argv, const char *prefix);
+extern int cmd_am(int argc, const char **argv, const char *prefix);
 extern int cmd_annotate(int argc, const char **argv, const char *prefix);
 extern int cmd_apply(int argc, const char **argv, const char *prefix);
 extern int cmd_archive(int argc, const char **argv, const char *prefix);
@@ -98,6 +99,7 @@ extern int cmd_pack_redundant(int argc, const char **argv, const char *prefix);
 extern int cmd_patch_id(int argc, const char **argv, const char *prefix);
 extern int cmd_prune(int argc, const char **argv, const char *prefix);
 extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);
+extern int cmd_pull(int argc, const char **argv, const char *prefix);
 extern int cmd_push(int argc, const char **argv, const char *prefix);
 extern int cmd_read_tree(int argc, const char **argv, const char *prefix);
 extern int cmd_receive_pack(int argc, const char **argv, const char *prefix);
@@ -133,6 +135,7 @@ extern int cmd_verify_commit(int argc, const char **argv, const char *prefix);
 extern int cmd_verify_tag(int argc, const char **argv, const char *prefix);
 extern int cmd_version(int argc, const char **argv, const char *prefix);
 extern int cmd_whatchanged(int argc, const char **argv, const char *prefix);
+extern int cmd_worktree(int argc, const char **argv, const char *prefix);
 extern int cmd_write_tree(int argc, const char **argv, const char *prefix);
 extern int cmd_verify_pack(int argc, const char **argv, const char *prefix);
 extern int cmd_show_ref(int argc, const char **argv, const char *prefix);
index 4bd98b7..b2a5c57 100644 (file)
@@ -375,7 +375,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
        if (add_new_files) {
                int baselen;
-               struct pathspec empty_pathspec;
 
                /* Set up the default git porcelain excludes */
                memset(&dir, 0, sizeof(dir));
@@ -384,7 +383,6 @@ int cmd_add(int argc, const char **argv, const char *prefix)
                        setup_standard_excludes(&dir);
                }
 
-               memset(&empty_pathspec, 0, sizeof(empty_pathspec));
                /* This picks up the paths that are not tracked */
                baselen = fill_directory(&dir, &pathspec);
                if (pathspec.nr)
diff --git a/builtin/am.c b/builtin/am.c
new file mode 100644 (file)
index 0000000..1399c8d
--- /dev/null
@@ -0,0 +1,2321 @@
+/*
+ * Builtin "git am"
+ *
+ * Based on git-am.sh by Junio C Hamano.
+ */
+#include "cache.h"
+#include "builtin.h"
+#include "exec_cmd.h"
+#include "parse-options.h"
+#include "dir.h"
+#include "run-command.h"
+#include "quote.h"
+#include "lockfile.h"
+#include "cache-tree.h"
+#include "refs.h"
+#include "commit.h"
+#include "diff.h"
+#include "diffcore.h"
+#include "unpack-trees.h"
+#include "branch.h"
+#include "sequencer.h"
+#include "revision.h"
+#include "merge-recursive.h"
+#include "revision.h"
+#include "log-tree.h"
+#include "notes-utils.h"
+#include "rerere.h"
+#include "prompt.h"
+
+/**
+ * Returns 1 if the file is empty or does not exist, 0 otherwise.
+ */
+static int is_empty_file(const char *filename)
+{
+       struct stat st;
+
+       if (stat(filename, &st) < 0) {
+               if (errno == ENOENT)
+                       return 1;
+               die_errno(_("could not stat %s"), filename);
+       }
+
+       return !st.st_size;
+}
+
+/**
+ * Like strbuf_getline(), but treats both '\n' and "\r\n" as line terminators.
+ */
+static int strbuf_getline_crlf(struct strbuf *sb, FILE *fp)
+{
+       if (strbuf_getwholeline(sb, fp, '\n'))
+               return EOF;
+       if (sb->buf[sb->len - 1] == '\n') {
+               strbuf_setlen(sb, sb->len - 1);
+               if (sb->len > 0 && sb->buf[sb->len - 1] == '\r')
+                       strbuf_setlen(sb, sb->len - 1);
+       }
+       return 0;
+}
+
+/**
+ * Returns the length of the first line of msg.
+ */
+static int linelen(const char *msg)
+{
+       return strchrnul(msg, '\n') - msg;
+}
+
+/**
+ * Returns true if `str` consists of only whitespace, false otherwise.
+ */
+static int str_isspace(const char *str)
+{
+       for (; *str; str++)
+               if (!isspace(*str))
+                       return 0;
+
+       return 1;
+}
+
+enum patch_format {
+       PATCH_FORMAT_UNKNOWN = 0,
+       PATCH_FORMAT_MBOX,
+       PATCH_FORMAT_STGIT,
+       PATCH_FORMAT_STGIT_SERIES,
+       PATCH_FORMAT_HG
+};
+
+enum keep_type {
+       KEEP_FALSE = 0,
+       KEEP_TRUE,      /* pass -k flag to git-mailinfo */
+       KEEP_NON_PATCH  /* pass -b flag to git-mailinfo */
+};
+
+enum scissors_type {
+       SCISSORS_UNSET = -1,
+       SCISSORS_FALSE = 0,  /* pass --no-scissors to git-mailinfo */
+       SCISSORS_TRUE        /* pass --scissors to git-mailinfo */
+};
+
+struct am_state {
+       /* state directory path */
+       char *dir;
+
+       /* current and last patch numbers, 1-indexed */
+       int cur;
+       int last;
+
+       /* commit metadata and message */
+       char *author_name;
+       char *author_email;
+       char *author_date;
+       char *msg;
+       size_t msg_len;
+
+       /* when --rebasing, records the original commit the patch came from */
+       unsigned char orig_commit[GIT_SHA1_RAWSZ];
+
+       /* number of digits in patch filename */
+       int prec;
+
+       /* various operating modes and command line options */
+       int interactive;
+       int threeway;
+       int quiet;
+       int signoff;
+       int utf8;
+       int keep; /* enum keep_type */
+       int message_id;
+       int scissors; /* enum scissors_type */
+       struct argv_array git_apply_opts;
+       const char *resolvemsg;
+       int committer_date_is_author_date;
+       int ignore_date;
+       int allow_rerere_autoupdate;
+       const char *sign_commit;
+       int rebasing;
+};
+
+/**
+ * Initializes am_state with the default values. The state directory is set to
+ * dir.
+ */
+static void am_state_init(struct am_state *state, const char *dir)
+{
+       int gpgsign;
+
+       memset(state, 0, sizeof(*state));
+
+       assert(dir);
+       state->dir = xstrdup(dir);
+
+       state->prec = 4;
+
+       git_config_get_bool("am.threeway", &state->threeway);
+
+       state->utf8 = 1;
+
+       git_config_get_bool("am.messageid", &state->message_id);
+
+       state->scissors = SCISSORS_UNSET;
+
+       argv_array_init(&state->git_apply_opts);
+
+       if (!git_config_get_bool("commit.gpgsign", &gpgsign))
+               state->sign_commit = gpgsign ? "" : NULL;
+}
+
+/**
+ * Releases memory allocated by an am_state.
+ */
+static void am_state_release(struct am_state *state)
+{
+       free(state->dir);
+       free(state->author_name);
+       free(state->author_email);
+       free(state->author_date);
+       free(state->msg);
+       argv_array_clear(&state->git_apply_opts);
+}
+
+/**
+ * Returns path relative to the am_state directory.
+ */
+static inline const char *am_path(const struct am_state *state, const char *path)
+{
+       return mkpath("%s/%s", state->dir, path);
+}
+
+/**
+ * If state->quiet is false, calls fprintf(fp, fmt, ...), and appends a newline
+ * at the end.
+ */
+static void say(const struct am_state *state, FILE *fp, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       if (!state->quiet) {
+               vfprintf(fp, fmt, ap);
+               putc('\n', fp);
+       }
+       va_end(ap);
+}
+
+/**
+ * Returns 1 if there is an am session in progress, 0 otherwise.
+ */
+static int am_in_progress(const struct am_state *state)
+{
+       struct stat st;
+
+       if (lstat(state->dir, &st) < 0 || !S_ISDIR(st.st_mode))
+               return 0;
+       if (lstat(am_path(state, "last"), &st) || !S_ISREG(st.st_mode))
+               return 0;
+       if (lstat(am_path(state, "next"), &st) || !S_ISREG(st.st_mode))
+               return 0;
+       return 1;
+}
+
+/**
+ * Reads the contents of `file` in the `state` directory into `sb`. Returns the
+ * number of bytes read on success, -1 if the file does not exist. If `trim` is
+ * set, trailing whitespace will be removed.
+ */
+static int read_state_file(struct strbuf *sb, const struct am_state *state,
+                       const char *file, int trim)
+{
+       strbuf_reset(sb);
+
+       if (strbuf_read_file(sb, am_path(state, file), 0) >= 0) {
+               if (trim)
+                       strbuf_trim(sb);
+
+               return sb->len;
+       }
+
+       if (errno == ENOENT)
+               return -1;
+
+       die_errno(_("could not read '%s'"), am_path(state, file));
+}
+
+/**
+ * Reads a KEY=VALUE shell variable assignment from `fp`, returning the VALUE
+ * as a newly-allocated string. VALUE must be a quoted string, and the KEY must
+ * match `key`. Returns NULL on failure.
+ *
+ * This is used by read_author_script() to read the GIT_AUTHOR_* variables from
+ * the author-script.
+ */
+static char *read_shell_var(FILE *fp, const char *key)
+{
+       struct strbuf sb = STRBUF_INIT;
+       const char *str;
+
+       if (strbuf_getline(&sb, fp, '\n'))
+               goto fail;
+
+       if (!skip_prefix(sb.buf, key, &str))
+               goto fail;
+
+       if (!skip_prefix(str, "=", &str))
+               goto fail;
+
+       strbuf_remove(&sb, 0, str - sb.buf);
+
+       str = sq_dequote(sb.buf);
+       if (!str)
+               goto fail;
+
+       return strbuf_detach(&sb, NULL);
+
+fail:
+       strbuf_release(&sb);
+       return NULL;
+}
+
+/**
+ * Reads and parses the state directory's "author-script" file, and sets
+ * state->author_name, state->author_email and state->author_date accordingly.
+ * Returns 0 on success, -1 if the file could not be parsed.
+ *
+ * The author script is of the format:
+ *
+ *     GIT_AUTHOR_NAME='$author_name'
+ *     GIT_AUTHOR_EMAIL='$author_email'
+ *     GIT_AUTHOR_DATE='$author_date'
+ *
+ * where $author_name, $author_email and $author_date are quoted. We are strict
+ * with our parsing, as the file was meant to be eval'd in the old git-am.sh
+ * script, and thus if the file differs from what this function expects, it is
+ * better to bail out than to do something that the user does not expect.
+ */
+static int read_author_script(struct am_state *state)
+{
+       const char *filename = am_path(state, "author-script");
+       FILE *fp;
+
+       assert(!state->author_name);
+       assert(!state->author_email);
+       assert(!state->author_date);
+
+       fp = fopen(filename, "r");
+       if (!fp) {
+               if (errno == ENOENT)
+                       return 0;
+               die_errno(_("could not open '%s' for reading"), filename);
+       }
+
+       state->author_name = read_shell_var(fp, "GIT_AUTHOR_NAME");
+       if (!state->author_name) {
+               fclose(fp);
+               return -1;
+       }
+
+       state->author_email = read_shell_var(fp, "GIT_AUTHOR_EMAIL");
+       if (!state->author_email) {
+               fclose(fp);
+               return -1;
+       }
+
+       state->author_date = read_shell_var(fp, "GIT_AUTHOR_DATE");
+       if (!state->author_date) {
+               fclose(fp);
+               return -1;
+       }
+
+       if (fgetc(fp) != EOF) {
+               fclose(fp);
+               return -1;
+       }
+
+       fclose(fp);
+       return 0;
+}
+
+/**
+ * Saves state->author_name, state->author_email and state->author_date in the
+ * state directory's "author-script" file.
+ */
+static void write_author_script(const struct am_state *state)
+{
+       struct strbuf sb = STRBUF_INIT;
+
+       strbuf_addstr(&sb, "GIT_AUTHOR_NAME=");
+       sq_quote_buf(&sb, state->author_name);
+       strbuf_addch(&sb, '\n');
+
+       strbuf_addstr(&sb, "GIT_AUTHOR_EMAIL=");
+       sq_quote_buf(&sb, state->author_email);
+       strbuf_addch(&sb, '\n');
+
+       strbuf_addstr(&sb, "GIT_AUTHOR_DATE=");
+       sq_quote_buf(&sb, state->author_date);
+       strbuf_addch(&sb, '\n');
+
+       write_file(am_path(state, "author-script"), 1, "%s", sb.buf);
+
+       strbuf_release(&sb);
+}
+
+/**
+ * Reads the commit message from the state directory's "final-commit" file,
+ * setting state->msg to its contents and state->msg_len to the length of its
+ * contents in bytes.
+ *
+ * Returns 0 on success, -1 if the file does not exist.
+ */
+static int read_commit_msg(struct am_state *state)
+{
+       struct strbuf sb = STRBUF_INIT;
+
+       assert(!state->msg);
+
+       if (read_state_file(&sb, state, "final-commit", 0) < 0) {
+               strbuf_release(&sb);
+               return -1;
+       }
+
+       state->msg = strbuf_detach(&sb, &state->msg_len);
+       return 0;
+}
+
+/**
+ * Saves state->msg in the state directory's "final-commit" file.
+ */
+static void write_commit_msg(const struct am_state *state)
+{
+       int fd;
+       const char *filename = am_path(state, "final-commit");
+
+       fd = xopen(filename, O_WRONLY | O_CREAT, 0666);
+       if (write_in_full(fd, state->msg, state->msg_len) < 0)
+               die_errno(_("could not write to %s"), filename);
+       close(fd);
+}
+
+/**
+ * Loads state from disk.
+ */
+static void am_load(struct am_state *state)
+{
+       struct strbuf sb = STRBUF_INIT;
+
+       if (read_state_file(&sb, state, "next", 1) < 0)
+               die("BUG: state file 'next' does not exist");
+       state->cur = strtol(sb.buf, NULL, 10);
+
+       if (read_state_file(&sb, state, "last", 1) < 0)
+               die("BUG: state file 'last' does not exist");
+       state->last = strtol(sb.buf, NULL, 10);
+
+       if (read_author_script(state) < 0)
+               die(_("could not parse author script"));
+
+       read_commit_msg(state);
+
+       if (read_state_file(&sb, state, "original-commit", 1) < 0)
+               hashclr(state->orig_commit);
+       else if (get_sha1_hex(sb.buf, state->orig_commit) < 0)
+               die(_("could not parse %s"), am_path(state, "original-commit"));
+
+       read_state_file(&sb, state, "threeway", 1);
+       state->threeway = !strcmp(sb.buf, "t");
+
+       read_state_file(&sb, state, "quiet", 1);
+       state->quiet = !strcmp(sb.buf, "t");
+
+       read_state_file(&sb, state, "sign", 1);
+       state->signoff = !strcmp(sb.buf, "t");
+
+       read_state_file(&sb, state, "utf8", 1);
+       state->utf8 = !strcmp(sb.buf, "t");
+
+       read_state_file(&sb, state, "keep", 1);
+       if (!strcmp(sb.buf, "t"))
+               state->keep = KEEP_TRUE;
+       else if (!strcmp(sb.buf, "b"))
+               state->keep = KEEP_NON_PATCH;
+       else
+               state->keep = KEEP_FALSE;
+
+       read_state_file(&sb, state, "messageid", 1);
+       state->message_id = !strcmp(sb.buf, "t");
+
+       read_state_file(&sb, state, "scissors", 1);
+       if (!strcmp(sb.buf, "t"))
+               state->scissors = SCISSORS_TRUE;
+       else if (!strcmp(sb.buf, "f"))
+               state->scissors = SCISSORS_FALSE;
+       else
+               state->scissors = SCISSORS_UNSET;
+
+       read_state_file(&sb, state, "apply-opt", 1);
+       argv_array_clear(&state->git_apply_opts);
+       if (sq_dequote_to_argv_array(sb.buf, &state->git_apply_opts) < 0)
+               die(_("could not parse %s"), am_path(state, "apply-opt"));
+
+       state->rebasing = !!file_exists(am_path(state, "rebasing"));
+
+       strbuf_release(&sb);
+}
+
+/**
+ * Removes the am_state directory, forcefully terminating the current am
+ * session.
+ */
+static void am_destroy(const struct am_state *state)
+{
+       struct strbuf sb = STRBUF_INIT;
+
+       strbuf_addstr(&sb, state->dir);
+       remove_dir_recursively(&sb, 0);
+       strbuf_release(&sb);
+}
+
+/**
+ * Runs applypatch-msg hook. Returns its exit code.
+ */
+static int run_applypatch_msg_hook(struct am_state *state)
+{
+       int ret;
+
+       assert(state->msg);
+       ret = run_hook_le(NULL, "applypatch-msg", am_path(state, "final-commit"), NULL);
+
+       if (!ret) {
+               free(state->msg);
+               state->msg = NULL;
+               if (read_commit_msg(state) < 0)
+                       die(_("'%s' was deleted by the applypatch-msg hook"),
+                               am_path(state, "final-commit"));
+       }
+
+       return ret;
+}
+
+/**
+ * Runs post-rewrite hook. Returns it exit code.
+ */
+static int run_post_rewrite_hook(const struct am_state *state)
+{
+       struct child_process cp = CHILD_PROCESS_INIT;
+       const char *hook = find_hook("post-rewrite");
+       int ret;
+
+       if (!hook)
+               return 0;
+
+       argv_array_push(&cp.args, hook);
+       argv_array_push(&cp.args, "rebase");
+
+       cp.in = xopen(am_path(state, "rewritten"), O_RDONLY);
+       cp.stdout_to_stderr = 1;
+
+       ret = run_command(&cp);
+
+       close(cp.in);
+       return ret;
+}
+
+/**
+ * Reads the state directory's "rewritten" file, and copies notes from the old
+ * commits listed in the file to their rewritten commits.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int copy_notes_for_rebase(const struct am_state *state)
+{
+       struct notes_rewrite_cfg *c;
+       struct strbuf sb = STRBUF_INIT;
+       const char *invalid_line = _("Malformed input line: '%s'.");
+       const char *msg = "Notes added by 'git rebase'";
+       FILE *fp;
+       int ret = 0;
+
+       assert(state->rebasing);
+
+       c = init_copy_notes_for_rewrite("rebase");
+       if (!c)
+               return 0;
+
+       fp = xfopen(am_path(state, "rewritten"), "r");
+
+       while (!strbuf_getline(&sb, fp, '\n')) {
+               unsigned char from_obj[GIT_SHA1_RAWSZ], to_obj[GIT_SHA1_RAWSZ];
+
+               if (sb.len != GIT_SHA1_HEXSZ * 2 + 1) {
+                       ret = error(invalid_line, sb.buf);
+                       goto finish;
+               }
+
+               if (get_sha1_hex(sb.buf, from_obj)) {
+                       ret = error(invalid_line, sb.buf);
+                       goto finish;
+               }
+
+               if (sb.buf[GIT_SHA1_HEXSZ] != ' ') {
+                       ret = error(invalid_line, sb.buf);
+                       goto finish;
+               }
+
+               if (get_sha1_hex(sb.buf + GIT_SHA1_HEXSZ + 1, to_obj)) {
+                       ret = error(invalid_line, sb.buf);
+                       goto finish;
+               }
+
+               if (copy_note_for_rewrite(c, from_obj, to_obj))
+                       ret = error(_("Failed to copy notes from '%s' to '%s'"),
+                                       sha1_to_hex(from_obj), sha1_to_hex(to_obj));
+       }
+
+finish:
+       finish_copy_notes_for_rewrite(c, msg);
+       fclose(fp);
+       strbuf_release(&sb);
+       return ret;
+}
+
+/**
+ * Determines if the file looks like a piece of RFC2822 mail by grabbing all
+ * non-indented lines and checking if they look like they begin with valid
+ * header field names.
+ *
+ * Returns 1 if the file looks like a piece of mail, 0 otherwise.
+ */
+static int is_mail(FILE *fp)
+{
+       const char *header_regex = "^[!-9;-~]+:";
+       struct strbuf sb = STRBUF_INIT;
+       regex_t regex;
+       int ret = 1;
+
+       if (fseek(fp, 0L, SEEK_SET))
+               die_errno(_("fseek failed"));
+
+       if (regcomp(&regex, header_regex, REG_NOSUB | REG_EXTENDED))
+               die("invalid pattern: %s", header_regex);
+
+       while (!strbuf_getline_crlf(&sb, fp)) {
+               if (!sb.len)
+                       break; /* End of header */
+
+               /* Ignore indented folded lines */
+               if (*sb.buf == '\t' || *sb.buf == ' ')
+                       continue;
+
+               /* It's a header if it matches header_regex */
+               if (regexec(&regex, sb.buf, 0, NULL, 0)) {
+                       ret = 0;
+                       goto done;
+               }
+       }
+
+done:
+       regfree(&regex);
+       strbuf_release(&sb);
+       return ret;
+}
+
+/**
+ * Attempts to detect the patch_format of the patches contained in `paths`,
+ * returning the PATCH_FORMAT_* enum value. Returns PATCH_FORMAT_UNKNOWN if
+ * detection fails.
+ */
+static int detect_patch_format(const char **paths)
+{
+       enum patch_format ret = PATCH_FORMAT_UNKNOWN;
+       struct strbuf l1 = STRBUF_INIT;
+       struct strbuf l2 = STRBUF_INIT;
+       struct strbuf l3 = STRBUF_INIT;
+       FILE *fp;
+
+       /*
+        * We default to mbox format if input is from stdin and for directories
+        */
+       if (!*paths || !strcmp(*paths, "-") || is_directory(*paths))
+               return PATCH_FORMAT_MBOX;
+
+       /*
+        * Otherwise, check the first few lines of the first patch, starting
+        * from the first non-blank line, to try to detect its format.
+        */
+
+       fp = xfopen(*paths, "r");
+
+       while (!strbuf_getline_crlf(&l1, fp)) {
+               if (l1.len)
+                       break;
+       }
+
+       if (starts_with(l1.buf, "From ") || starts_with(l1.buf, "From: ")) {
+               ret = PATCH_FORMAT_MBOX;
+               goto done;
+       }
+
+       if (starts_with(l1.buf, "# This series applies on GIT commit")) {
+               ret = PATCH_FORMAT_STGIT_SERIES;
+               goto done;
+       }
+
+       if (!strcmp(l1.buf, "# HG changeset patch")) {
+               ret = PATCH_FORMAT_HG;
+               goto done;
+       }
+
+       strbuf_reset(&l2);
+       strbuf_getline_crlf(&l2, fp);
+       strbuf_reset(&l3);
+       strbuf_getline_crlf(&l3, fp);
+
+       /*
+        * If the second line is empty and the third is a From, Author or Date
+        * entry, this is likely an StGit patch.
+        */
+       if (l1.len && !l2.len &&
+               (starts_with(l3.buf, "From:") ||
+                starts_with(l3.buf, "Author:") ||
+                starts_with(l3.buf, "Date:"))) {
+               ret = PATCH_FORMAT_STGIT;
+               goto done;
+       }
+
+       if (l1.len && is_mail(fp)) {
+               ret = PATCH_FORMAT_MBOX;
+               goto done;
+       }
+
+done:
+       fclose(fp);
+       strbuf_release(&l1);
+       return ret;
+}
+
+/**
+ * Splits out individual email patches from `paths`, where each path is either
+ * a mbox file or a Maildir. Returns 0 on success, -1 on failure.
+ */
+static int split_mail_mbox(struct am_state *state, const char **paths, int keep_cr)
+{
+       struct child_process cp = CHILD_PROCESS_INIT;
+       struct strbuf last = STRBUF_INIT;
+
+       cp.git_cmd = 1;
+       argv_array_push(&cp.args, "mailsplit");
+       argv_array_pushf(&cp.args, "-d%d", state->prec);
+       argv_array_pushf(&cp.args, "-o%s", state->dir);
+       argv_array_push(&cp.args, "-b");
+       if (keep_cr)
+               argv_array_push(&cp.args, "--keep-cr");
+       argv_array_push(&cp.args, "--");
+       argv_array_pushv(&cp.args, paths);
+
+       if (capture_command(&cp, &last, 8))
+               return -1;
+
+       state->cur = 1;
+       state->last = strtol(last.buf, NULL, 10);
+
+       return 0;
+}
+
+/**
+ * Callback signature for split_mail_conv(). The foreign patch should be
+ * read from `in`, and the converted patch (in RFC2822 mail format) should be
+ * written to `out`. Return 0 on success, or -1 on failure.
+ */
+typedef int (*mail_conv_fn)(FILE *out, FILE *in, int keep_cr);
+
+/**
+ * Calls `fn` for each file in `paths` to convert the foreign patch to the
+ * RFC2822 mail format suitable for parsing with git-mailinfo.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int split_mail_conv(mail_conv_fn fn, struct am_state *state,
+                       const char **paths, int keep_cr)
+{
+       static const char *stdin_only[] = {"-", NULL};
+       int i;
+
+       if (!*paths)
+               paths = stdin_only;
+
+       for (i = 0; *paths; paths++, i++) {
+               FILE *in, *out;
+               const char *mail;
+               int ret;
+
+               if (!strcmp(*paths, "-"))
+                       in = stdin;
+               else
+                       in = fopen(*paths, "r");
+
+               if (!in)
+                       return error(_("could not open '%s' for reading: %s"),
+                                       *paths, strerror(errno));
+
+               mail = mkpath("%s/%0*d", state->dir, state->prec, i + 1);
+
+               out = fopen(mail, "w");
+               if (!out)
+                       return error(_("could not open '%s' for writing: %s"),
+                                       mail, strerror(errno));
+
+               ret = fn(out, in, keep_cr);
+
+               fclose(out);
+               fclose(in);
+
+               if (ret)
+                       return error(_("could not parse patch '%s'"), *paths);
+       }
+
+       state->cur = 1;
+       state->last = i;
+       return 0;
+}
+
+/**
+ * A split_mail_conv() callback that converts an StGit patch to an RFC2822
+ * message suitable for parsing with git-mailinfo.
+ */
+static int stgit_patch_to_mail(FILE *out, FILE *in, int keep_cr)
+{
+       struct strbuf sb = STRBUF_INIT;
+       int subject_printed = 0;
+
+       while (!strbuf_getline(&sb, in, '\n')) {
+               const char *str;
+
+               if (str_isspace(sb.buf))
+                       continue;
+               else if (skip_prefix(sb.buf, "Author:", &str))
+                       fprintf(out, "From:%s\n", str);
+               else if (starts_with(sb.buf, "From") || starts_with(sb.buf, "Date"))
+                       fprintf(out, "%s\n", sb.buf);
+               else if (!subject_printed) {
+                       fprintf(out, "Subject: %s\n", sb.buf);
+                       subject_printed = 1;
+               } else {
+                       fprintf(out, "\n%s\n", sb.buf);
+                       break;
+               }
+       }
+
+       strbuf_reset(&sb);
+       while (strbuf_fread(&sb, 8192, in) > 0) {
+               fwrite(sb.buf, 1, sb.len, out);
+               strbuf_reset(&sb);
+       }
+
+       strbuf_release(&sb);
+       return 0;
+}
+
+/**
+ * This function only supports a single StGit series file in `paths`.
+ *
+ * Given an StGit series file, converts the StGit patches in the series into
+ * RFC2822 messages suitable for parsing with git-mailinfo, and queues them in
+ * the state directory.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int split_mail_stgit_series(struct am_state *state, const char **paths,
+                                       int keep_cr)
+{
+       const char *series_dir;
+       char *series_dir_buf;
+       FILE *fp;
+       struct argv_array patches = ARGV_ARRAY_INIT;
+       struct strbuf sb = STRBUF_INIT;
+       int ret;
+
+       if (!paths[0] || paths[1])
+               return error(_("Only one StGIT patch series can be applied at once"));
+
+       series_dir_buf = xstrdup(*paths);
+       series_dir = dirname(series_dir_buf);
+
+       fp = fopen(*paths, "r");
+       if (!fp)
+               return error(_("could not open '%s' for reading: %s"), *paths,
+                               strerror(errno));
+
+       while (!strbuf_getline(&sb, fp, '\n')) {
+               if (*sb.buf == '#')
+                       continue; /* skip comment lines */
+
+               argv_array_push(&patches, mkpath("%s/%s", series_dir, sb.buf));
+       }
+
+       fclose(fp);
+       strbuf_release(&sb);
+       free(series_dir_buf);
+
+       ret = split_mail_conv(stgit_patch_to_mail, state, patches.argv, keep_cr);
+
+       argv_array_clear(&patches);
+       return ret;
+}
+
+/**
+ * A split_patches_conv() callback that converts a mercurial patch to a RFC2822
+ * message suitable for parsing with git-mailinfo.
+ */
+static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
+{
+       struct strbuf sb = STRBUF_INIT;
+
+       while (!strbuf_getline(&sb, in, '\n')) {
+               const char *str;
+
+               if (skip_prefix(sb.buf, "# User ", &str))
+                       fprintf(out, "From: %s\n", str);
+               else if (skip_prefix(sb.buf, "# Date ", &str)) {
+                       unsigned long timestamp;
+                       long tz, tz2;
+                       char *end;
+
+                       errno = 0;
+                       timestamp = strtoul(str, &end, 10);
+                       if (errno)
+                               return error(_("invalid timestamp"));
+
+                       if (!skip_prefix(end, " ", &str))
+                               return error(_("invalid Date line"));
+
+                       errno = 0;
+                       tz = strtol(str, &end, 10);
+                       if (errno)
+                               return error(_("invalid timezone offset"));
+
+                       if (*end)
+                               return error(_("invalid Date line"));
+
+                       /*
+                        * mercurial's timezone is in seconds west of UTC,
+                        * however git's timezone is in hours + minutes east of
+                        * UTC. Convert it.
+                        */
+                       tz2 = labs(tz) / 3600 * 100 + labs(tz) % 3600 / 60;
+                       if (tz > 0)
+                               tz2 = -tz2;
+
+                       fprintf(out, "Date: %s\n", show_date(timestamp, tz2, DATE_MODE(RFC2822)));
+               } else if (starts_with(sb.buf, "# ")) {
+                       continue;
+               } else {
+                       fprintf(out, "\n%s\n", sb.buf);
+                       break;
+               }
+       }
+
+       strbuf_reset(&sb);
+       while (strbuf_fread(&sb, 8192, in) > 0) {
+               fwrite(sb.buf, 1, sb.len, out);
+               strbuf_reset(&sb);
+       }
+
+       strbuf_release(&sb);
+       return 0;
+}
+
+/**
+ * Splits a list of files/directories into individual email patches. Each path
+ * in `paths` must be a file/directory that is formatted according to
+ * `patch_format`.
+ *
+ * Once split out, the individual email patches will be stored in the state
+ * directory, with each patch's filename being its index, padded to state->prec
+ * digits.
+ *
+ * state->cur will be set to the index of the first mail, and state->last will
+ * be set to the index of the last mail.
+ *
+ * Set keep_cr to 0 to convert all lines ending with \r\n to end with \n, 1
+ * to disable this behavior, -1 to use the default configured setting.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+static int split_mail(struct am_state *state, enum patch_format patch_format,
+                       const char **paths, int keep_cr)
+{
+       if (keep_cr < 0) {
+               keep_cr = 0;
+               git_config_get_bool("am.keepcr", &keep_cr);
+       }
+
+       switch (patch_format) {
+       case PATCH_FORMAT_MBOX:
+               return split_mail_mbox(state, paths, keep_cr);
+       case PATCH_FORMAT_STGIT:
+               return split_mail_conv(stgit_patch_to_mail, state, paths, keep_cr);
+       case PATCH_FORMAT_STGIT_SERIES:
+               return split_mail_stgit_series(state, paths, keep_cr);
+       case PATCH_FORMAT_HG:
+               return split_mail_conv(hg_patch_to_mail, state, paths, keep_cr);
+       default:
+               die("BUG: invalid patch_format");
+       }
+       return -1;
+}
+
+/**
+ * Setup a new am session for applying patches
+ */
+static void am_setup(struct am_state *state, enum patch_format patch_format,
+                       const char **paths, int keep_cr)
+{
+       unsigned char curr_head[GIT_SHA1_RAWSZ];
+       const char *str;
+       struct strbuf sb = STRBUF_INIT;
+
+       if (!patch_format)
+               patch_format = detect_patch_format(paths);
+
+       if (!patch_format) {
+               fprintf_ln(stderr, _("Patch format detection failed."));
+               exit(128);
+       }
+
+       if (mkdir(state->dir, 0777) < 0 && errno != EEXIST)
+               die_errno(_("failed to create directory '%s'"), state->dir);
+
+       if (split_mail(state, patch_format, paths, keep_cr) < 0) {
+               am_destroy(state);
+               die(_("Failed to split patches."));
+       }
+
+       if (state->rebasing)
+               state->threeway = 1;
+
+       write_file(am_path(state, "threeway"), 1, state->threeway ? "t" : "f");
+
+       write_file(am_path(state, "quiet"), 1, state->quiet ? "t" : "f");
+
+       write_file(am_path(state, "sign"), 1, state->signoff ? "t" : "f");
+
+       write_file(am_path(state, "utf8"), 1, state->utf8 ? "t" : "f");
+
+       switch (state->keep) {
+       case KEEP_FALSE:
+               str = "f";
+               break;
+       case KEEP_TRUE:
+               str = "t";
+               break;
+       case KEEP_NON_PATCH:
+               str = "b";
+               break;
+       default:
+               die("BUG: invalid value for state->keep");
+       }
+
+       write_file(am_path(state, "keep"), 1, "%s", str);
+
+       write_file(am_path(state, "messageid"), 1, state->message_id ? "t" : "f");
+
+       switch (state->scissors) {
+       case SCISSORS_UNSET:
+               str = "";
+               break;
+       case SCISSORS_FALSE:
+               str = "f";
+               break;
+       case SCISSORS_TRUE:
+               str = "t";
+               break;
+       default:
+               die("BUG: invalid value for state->scissors");
+       }
+
+       write_file(am_path(state, "scissors"), 1, "%s", str);
+
+       sq_quote_argv(&sb, state->git_apply_opts.argv, 0);
+       write_file(am_path(state, "apply-opt"), 1, "%s", sb.buf);
+
+       if (state->rebasing)
+               write_file(am_path(state, "rebasing"), 1, "%s", "");
+       else
+               write_file(am_path(state, "applying"), 1, "%s", "");
+
+       if (!get_sha1("HEAD", curr_head)) {
+               write_file(am_path(state, "abort-safety"), 1, "%s", sha1_to_hex(curr_head));
+               if (!state->rebasing)
+                       update_ref("am", "ORIG_HEAD", curr_head, NULL, 0,
+                                       UPDATE_REFS_DIE_ON_ERR);
+       } else {
+               write_file(am_path(state, "abort-safety"), 1, "%s", "");
+               if (!state->rebasing)
+                       delete_ref("ORIG_HEAD", NULL, 0);
+       }
+
+       /*
+        * NOTE: Since the "next" and "last" files determine if an am_state
+        * session is in progress, they should be written last.
+        */
+
+       write_file(am_path(state, "next"), 1, "%d", state->cur);
+
+       write_file(am_path(state, "last"), 1, "%d", state->last);
+
+       strbuf_release(&sb);
+}
+
+/**
+ * Increments the patch pointer, and cleans am_state for the application of the
+ * next patch.
+ */
+static void am_next(struct am_state *state)
+{
+       unsigned char head[GIT_SHA1_RAWSZ];
+
+       free(state->author_name);
+       state->author_name = NULL;
+
+       free(state->author_email);
+       state->author_email = NULL;
+
+       free(state->author_date);
+       state->author_date = NULL;
+
+       free(state->msg);
+       state->msg = NULL;
+       state->msg_len = 0;
+
+       unlink(am_path(state, "author-script"));
+       unlink(am_path(state, "final-commit"));
+
+       hashclr(state->orig_commit);
+       unlink(am_path(state, "original-commit"));
+
+       if (!get_sha1("HEAD", head))
+               write_file(am_path(state, "abort-safety"), 1, "%s", sha1_to_hex(head));
+       else
+               write_file(am_path(state, "abort-safety"), 1, "%s", "");
+
+       state->cur++;
+       write_file(am_path(state, "next"), 1, "%d", state->cur);
+}
+
+/**
+ * Returns the filename of the current patch email.
+ */
+static const char *msgnum(const struct am_state *state)
+{
+       static struct strbuf sb = STRBUF_INIT;
+
+       strbuf_reset(&sb);
+       strbuf_addf(&sb, "%0*d", state->prec, state->cur);
+
+       return sb.buf;
+}
+
+/**
+ * Refresh and write index.
+ */
+static void refresh_and_write_cache(void)
+{
+       struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
+
+       hold_locked_index(lock_file, 1);
+       refresh_cache(REFRESH_QUIET);
+       if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+               die(_("unable to write index file"));
+}
+
+/**
+ * Returns 1 if the index differs from HEAD, 0 otherwise. When on an unborn
+ * branch, returns 1 if there are entries in the index, 0 otherwise. If an
+ * strbuf is provided, the space-separated list of files that differ will be
+ * appended to it.
+ */
+static int index_has_changes(struct strbuf *sb)
+{
+       unsigned char head[GIT_SHA1_RAWSZ];
+       int i;
+
+       if (!get_sha1_tree("HEAD", head)) {
+               struct diff_options opt;
+
+               diff_setup(&opt);
+               DIFF_OPT_SET(&opt, EXIT_WITH_STATUS);
+               if (!sb)
+                       DIFF_OPT_SET(&opt, QUICK);
+               do_diff_cache(head, &opt);
+               diffcore_std(&opt);
+               for (i = 0; sb && i < diff_queued_diff.nr; i++) {
+                       if (i)
+                               strbuf_addch(sb, ' ');
+                       strbuf_addstr(sb, diff_queued_diff.queue[i]->two->path);
+               }
+               diff_flush(&opt);
+               return DIFF_OPT_TST(&opt, HAS_CHANGES) != 0;
+       } else {
+               for (i = 0; sb && i < active_nr; i++) {
+                       if (i)
+                               strbuf_addch(sb, ' ');
+                       strbuf_addstr(sb, active_cache[i]->name);
+               }
+               return !!active_nr;
+       }
+}
+
+/**
+ * Dies with a user-friendly message on how to proceed after resolving the
+ * problem. This message can be overridden with state->resolvemsg.
+ */
+static void NORETURN die_user_resolve(const struct am_state *state)
+{
+       if (state->resolvemsg) {
+               printf_ln("%s", state->resolvemsg);
+       } else {
+               const char *cmdline = state->interactive ? "git am -i" : "git am";
+
+               printf_ln(_("When you have resolved this problem, run \"%s --continue\"."), cmdline);
+               printf_ln(_("If you prefer to skip this patch, run \"%s --skip\" instead."), cmdline);
+               printf_ln(_("To restore the original branch and stop patching, run \"%s --abort\"."), cmdline);
+       }
+
+       exit(128);
+}
+
+/**
+ * Parses `mail` using git-mailinfo, extracting its patch and authorship info.
+ * state->msg will be set to the patch message. state->author_name,
+ * state->author_email and state->author_date will be set to the patch author's
+ * name, email and date respectively. The patch body will be written to the
+ * state directory's "patch" file.
+ *
+ * Returns 1 if the patch should be skipped, 0 otherwise.
+ */
+static int parse_mail(struct am_state *state, const char *mail)
+{
+       FILE *fp;
+       struct child_process cp = CHILD_PROCESS_INIT;
+       struct strbuf sb = STRBUF_INIT;
+       struct strbuf msg = STRBUF_INIT;
+       struct strbuf author_name = STRBUF_INIT;
+       struct strbuf author_date = STRBUF_INIT;
+       struct strbuf author_email = STRBUF_INIT;
+       int ret = 0;
+
+       cp.git_cmd = 1;
+       cp.in = xopen(mail, O_RDONLY, 0);
+       cp.out = xopen(am_path(state, "info"), O_WRONLY | O_CREAT, 0777);
+
+       argv_array_push(&cp.args, "mailinfo");
+       argv_array_push(&cp.args, state->utf8 ? "-u" : "-n");
+
+       switch (state->keep) {
+       case KEEP_FALSE:
+               break;
+       case KEEP_TRUE:
+               argv_array_push(&cp.args, "-k");
+               break;
+       case KEEP_NON_PATCH:
+               argv_array_push(&cp.args, "-b");
+               break;
+       default:
+               die("BUG: invalid value for state->keep");
+       }
+
+       if (state->message_id)
+               argv_array_push(&cp.args, "-m");
+
+       switch (state->scissors) {
+       case SCISSORS_UNSET:
+               break;
+       case SCISSORS_FALSE:
+               argv_array_push(&cp.args, "--no-scissors");
+               break;
+       case SCISSORS_TRUE:
+               argv_array_push(&cp.args, "--scissors");
+               break;
+       default:
+               die("BUG: invalid value for state->scissors");
+       }
+
+       argv_array_push(&cp.args, am_path(state, "msg"));
+       argv_array_push(&cp.args, am_path(state, "patch"));
+
+       if (run_command(&cp) < 0)
+               die("could not parse patch");
+
+       close(cp.in);
+       close(cp.out);
+
+       /* Extract message and author information */
+       fp = xfopen(am_path(state, "info"), "r");
+       while (!strbuf_getline(&sb, fp, '\n')) {
+               const char *x;
+
+               if (skip_prefix(sb.buf, "Subject: ", &x)) {
+                       if (msg.len)
+                               strbuf_addch(&msg, '\n');
+                       strbuf_addstr(&msg, x);
+               } else if (skip_prefix(sb.buf, "Author: ", &x))
+                       strbuf_addstr(&author_name, x);
+               else if (skip_prefix(sb.buf, "Email: ", &x))
+                       strbuf_addstr(&author_email, x);
+               else if (skip_prefix(sb.buf, "Date: ", &x))
+                       strbuf_addstr(&author_date, x);
+       }
+       fclose(fp);
+
+       /* Skip pine's internal folder data */
+       if (!strcmp(author_name.buf, "Mail System Internal Data")) {
+               ret = 1;
+               goto finish;
+       }
+
+       if (is_empty_file(am_path(state, "patch"))) {
+               printf_ln(_("Patch is empty. Was it split wrong?"));
+               die_user_resolve(state);
+       }
+
+       strbuf_addstr(&msg, "\n\n");
+       if (strbuf_read_file(&msg, am_path(state, "msg"), 0) < 0)
+               die_errno(_("could not read '%s'"), am_path(state, "msg"));
+       stripspace(&msg, 0);
+
+       if (state->signoff)
+               append_signoff(&msg, 0, 0);
+
+       assert(!state->author_name);
+       state->author_name = strbuf_detach(&author_name, NULL);
+
+       assert(!state->author_email);
+       state->author_email = strbuf_detach(&author_email, NULL);
+
+       assert(!state->author_date);
+       state->author_date = strbuf_detach(&author_date, NULL);
+
+       assert(!state->msg);
+       state->msg = strbuf_detach(&msg, &state->msg_len);
+
+finish:
+       strbuf_release(&msg);
+       strbuf_release(&author_date);
+       strbuf_release(&author_email);
+       strbuf_release(&author_name);
+       strbuf_release(&sb);
+       return ret;
+}
+
+/**
+ * Sets commit_id to the commit hash where the mail was generated from.
+ * Returns 0 on success, -1 on failure.
+ */
+static int get_mail_commit_sha1(unsigned char *commit_id, const char *mail)
+{
+       struct strbuf sb = STRBUF_INIT;
+       FILE *fp = xfopen(mail, "r");
+       const char *x;
+
+       if (strbuf_getline(&sb, fp, '\n'))
+               return -1;
+
+       if (!skip_prefix(sb.buf, "From ", &x))
+               return -1;
+
+       if (get_sha1_hex(x, commit_id) < 0)
+               return -1;
+
+       strbuf_release(&sb);
+       fclose(fp);
+       return 0;
+}
+
+/**
+ * Sets state->msg, state->author_name, state->author_email, state->author_date
+ * to the commit's respective info.
+ */
+static void get_commit_info(struct am_state *state, struct commit *commit)
+{
+       const char *buffer, *ident_line, *author_date, *msg;
+       size_t ident_len;
+       struct ident_split ident_split;
+       struct strbuf sb = STRBUF_INIT;
+
+       buffer = logmsg_reencode(commit, NULL, get_commit_output_encoding());
+
+       ident_line = find_commit_header(buffer, "author", &ident_len);
+
+       if (split_ident_line(&ident_split, ident_line, ident_len) < 0) {
+               strbuf_add(&sb, ident_line, ident_len);
+               die(_("invalid ident line: %s"), sb.buf);
+       }
+
+       assert(!state->author_name);
+       if (ident_split.name_begin) {
+               strbuf_add(&sb, ident_split.name_begin,
+                       ident_split.name_end - ident_split.name_begin);
+               state->author_name = strbuf_detach(&sb, NULL);
+       } else
+               state->author_name = xstrdup("");
+
+       assert(!state->author_email);
+       if (ident_split.mail_begin) {
+               strbuf_add(&sb, ident_split.mail_begin,
+                       ident_split.mail_end - ident_split.mail_begin);
+               state->author_email = strbuf_detach(&sb, NULL);
+       } else
+               state->author_email = xstrdup("");
+
+       author_date = show_ident_date(&ident_split, DATE_MODE(NORMAL));
+       strbuf_addstr(&sb, author_date);
+       assert(!state->author_date);
+       state->author_date = strbuf_detach(&sb, NULL);
+
+       assert(!state->msg);
+       msg = strstr(buffer, "\n\n");
+       if (!msg)
+               die(_("unable to parse commit %s"), sha1_to_hex(commit->object.sha1));
+       state->msg = xstrdup(msg + 2);
+       state->msg_len = strlen(state->msg);
+}
+
+/**
+ * Writes `commit` as a patch to the state directory's "patch" file.
+ */
+static void write_commit_patch(const struct am_state *state, struct commit *commit)
+{
+       struct rev_info rev_info;
+       FILE *fp;
+
+       fp = xfopen(am_path(state, "patch"), "w");
+       init_revisions(&rev_info, NULL);
+       rev_info.diff = 1;
+       rev_info.abbrev = 0;
+       rev_info.disable_stdin = 1;
+       rev_info.show_root_diff = 1;
+       rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;
+       rev_info.no_commit_id = 1;
+       DIFF_OPT_SET(&rev_info.diffopt, BINARY);
+       DIFF_OPT_SET(&rev_info.diffopt, FULL_INDEX);
+       rev_info.diffopt.use_color = 0;
+       rev_info.diffopt.file = fp;
+       rev_info.diffopt.close_file = 1;
+       add_pending_object(&rev_info, &commit->object, "");
+       diff_setup_done(&rev_info.diffopt);
+       log_tree_commit(&rev_info, commit);
+}
+
+/**
+ * Writes the diff of the index against HEAD as a patch to the state
+ * directory's "patch" file.
+ */
+static void write_index_patch(const struct am_state *state)
+{
+       struct tree *tree;
+       unsigned char head[GIT_SHA1_RAWSZ];
+       struct rev_info rev_info;
+       FILE *fp;
+
+       if (!get_sha1_tree("HEAD", head))
+               tree = lookup_tree(head);
+       else
+               tree = lookup_tree(EMPTY_TREE_SHA1_BIN);
+
+       fp = xfopen(am_path(state, "patch"), "w");
+       init_revisions(&rev_info, NULL);
+       rev_info.diff = 1;
+       rev_info.disable_stdin = 1;
+       rev_info.no_commit_id = 1;
+       rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;
+       rev_info.diffopt.use_color = 0;
+       rev_info.diffopt.file = fp;
+       rev_info.diffopt.close_file = 1;
+       add_pending_object(&rev_info, &tree->object, "");
+       diff_setup_done(&rev_info.diffopt);
+       run_diff_index(&rev_info, 1);
+}
+
+/**
+ * Like parse_mail(), but parses the mail by looking up its commit ID
+ * directly. This is used in --rebasing mode to bypass git-mailinfo's munging
+ * of patches.
+ *
+ * state->orig_commit will be set to the original commit ID.
+ *
+ * Will always return 0 as the patch should never be skipped.
+ */
+static int parse_mail_rebase(struct am_state *state, const char *mail)
+{
+       struct commit *commit;
+       unsigned char commit_sha1[GIT_SHA1_RAWSZ];
+
+       if (get_mail_commit_sha1(commit_sha1, mail) < 0)
+               die(_("could not parse %s"), mail);
+
+       commit = lookup_commit_or_die(commit_sha1, mail);
+
+       get_commit_info(state, commit);
+
+       write_commit_patch(state, commit);
+
+       hashcpy(state->orig_commit, commit_sha1);
+       write_file(am_path(state, "original-commit"), 1, "%s",
+                       sha1_to_hex(commit_sha1));
+
+       return 0;
+}
+
+/**
+ * Applies current patch with git-apply. Returns 0 on success, -1 otherwise. If
+ * `index_file` is not NULL, the patch will be applied to that index.
+ */
+static int run_apply(const struct am_state *state, const char *index_file)
+{
+       struct child_process cp = CHILD_PROCESS_INIT;
+
+       cp.git_cmd = 1;
+
+       if (index_file)
+               argv_array_pushf(&cp.env_array, "GIT_INDEX_FILE=%s", index_file);
+
+       /*
+        * If we are allowed to fall back on 3-way merge, don't give false
+        * errors during the initial attempt.
+        */
+       if (state->threeway && !index_file) {
+               cp.no_stdout = 1;
+               cp.no_stderr = 1;
+       }
+
+       argv_array_push(&cp.args, "apply");
+
+       argv_array_pushv(&cp.args, state->git_apply_opts.argv);
+
+       if (index_file)
+               argv_array_push(&cp.args, "--cached");
+       else
+               argv_array_push(&cp.args, "--index");
+
+       argv_array_push(&cp.args, am_path(state, "patch"));
+
+       if (run_command(&cp))
+               return -1;
+
+       /* Reload index as git-apply will have modified it. */
+       discard_cache();
+       read_cache_from(index_file ? index_file : get_index_file());
+
+       return 0;
+}
+
+/**
+ * Builds an index that contains just the blobs needed for a 3way merge.
+ */
+static int build_fake_ancestor(const struct am_state *state, const char *index_file)
+{
+       struct child_process cp = CHILD_PROCESS_INIT;
+
+       cp.git_cmd = 1;
+       argv_array_push(&cp.args, "apply");
+       argv_array_pushv(&cp.args, state->git_apply_opts.argv);
+       argv_array_pushf(&cp.args, "--build-fake-ancestor=%s", index_file);
+       argv_array_push(&cp.args, am_path(state, "patch"));
+
+       if (run_command(&cp))
+               return -1;
+
+       return 0;
+}
+
+/**
+ * Attempt a threeway merge, using index_path as the temporary index.
+ */
+static int fall_back_threeway(const struct am_state *state, const char *index_path)
+{
+       unsigned char orig_tree[GIT_SHA1_RAWSZ], his_tree[GIT_SHA1_RAWSZ],
+                     our_tree[GIT_SHA1_RAWSZ];
+       const unsigned char *bases[1] = {orig_tree};
+       struct merge_options o;
+       struct commit *result;
+       char *his_tree_name;
+
+       if (get_sha1("HEAD", our_tree) < 0)
+               hashcpy(our_tree, EMPTY_TREE_SHA1_BIN);
+
+       if (build_fake_ancestor(state, index_path))
+               return error("could not build fake ancestor");
+
+       discard_cache();
+       read_cache_from(index_path);
+
+       if (write_index_as_tree(orig_tree, &the_index, index_path, 0, NULL))
+               return error(_("Repository lacks necessary blobs to fall back on 3-way merge."));
+
+       say(state, stdout, _("Using index info to reconstruct a base tree..."));
+
+       if (!state->quiet) {
+               /*
+                * List paths that needed 3-way fallback, so that the user can
+                * review them with extra care to spot mismerges.
+                */
+               struct rev_info rev_info;
+               const char *diff_filter_str = "--diff-filter=AM";
+
+               init_revisions(&rev_info, NULL);
+               rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;
+               diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1);
+               add_pending_sha1(&rev_info, "HEAD", our_tree, 0);
+               diff_setup_done(&rev_info.diffopt);
+               run_diff_index(&rev_info, 1);
+       }
+
+       if (run_apply(state, index_path))
+               return error(_("Did you hand edit your patch?\n"
+                               "It does not apply to blobs recorded in its index."));
+
+       if (write_index_as_tree(his_tree, &the_index, index_path, 0, NULL))
+               return error("could not write tree");
+
+       say(state, stdout, _("Falling back to patching base and 3-way merge..."));
+
+       discard_cache();
+       read_cache();
+
+       /*
+        * This is not so wrong. Depending on which base we picked, orig_tree
+        * may be wildly different from ours, but his_tree has the same set of
+        * wildly different changes in parts the patch did not touch, so
+        * recursive ends up canceling them, saying that we reverted all those
+        * changes.
+        */
+
+       init_merge_options(&o);
+
+       o.branch1 = "HEAD";
+       his_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
+       o.branch2 = his_tree_name;
+
+       if (state->quiet)
+               o.verbosity = 0;
+
+       if (merge_recursive_generic(&o, our_tree, his_tree, 1, bases, &result)) {
+               rerere(state->allow_rerere_autoupdate);
+               free(his_tree_name);
+               return error(_("Failed to merge in the changes."));
+       }
+
+       free(his_tree_name);
+       return 0;
+}
+
+/**
+ * Commits the current index with state->msg as the commit message and
+ * state->author_name, state->author_email and state->author_date as the author
+ * information.
+ */
+static void do_commit(const struct am_state *state)
+{
+       unsigned char tree[GIT_SHA1_RAWSZ], parent[GIT_SHA1_RAWSZ],
+                     commit[GIT_SHA1_RAWSZ];
+       unsigned char *ptr;
+       struct commit_list *parents = NULL;
+       const char *reflog_msg, *author;
+       struct strbuf sb = STRBUF_INIT;
+
+       if (run_hook_le(NULL, "pre-applypatch", NULL))
+               exit(1);
+
+       if (write_cache_as_tree(tree, 0, NULL))
+               die(_("git write-tree failed to write a tree"));
+
+       if (!get_sha1_commit("HEAD", parent)) {
+               ptr = parent;
+               commit_list_insert(lookup_commit(parent), &parents);
+       } else {
+               ptr = NULL;
+               say(state, stderr, _("applying to an empty history"));
+       }
+
+       author = fmt_ident(state->author_name, state->author_email,
+                       state->ignore_date ? NULL : state->author_date,
+                       IDENT_STRICT);
+
+       if (state->committer_date_is_author_date)
+               setenv("GIT_COMMITTER_DATE",
+                       state->ignore_date ? "" : state->author_date, 1);
+
+       if (commit_tree(state->msg, state->msg_len, tree, parents, commit,
+                               author, state->sign_commit))
+               die(_("failed to write commit object"));
+
+       reflog_msg = getenv("GIT_REFLOG_ACTION");
+       if (!reflog_msg)
+               reflog_msg = "am";
+
+       strbuf_addf(&sb, "%s: %.*s", reflog_msg, linelen(state->msg),
+                       state->msg);
+
+       update_ref(sb.buf, "HEAD", commit, ptr, 0, UPDATE_REFS_DIE_ON_ERR);
+
+       if (state->rebasing) {
+               FILE *fp = xfopen(am_path(state, "rewritten"), "a");
+
+               assert(!is_null_sha1(state->orig_commit));
+               fprintf(fp, "%s ", sha1_to_hex(state->orig_commit));
+               fprintf(fp, "%s\n", sha1_to_hex(commit));
+               fclose(fp);
+       }
+
+       run_hook_le(NULL, "post-applypatch", NULL);
+
+       strbuf_release(&sb);
+}
+
+/**
+ * Validates the am_state for resuming -- the "msg" and authorship fields must
+ * be filled up.
+ */
+static void validate_resume_state(const struct am_state *state)
+{
+       if (!state->msg)
+               die(_("cannot resume: %s does not exist."),
+                       am_path(state, "final-commit"));
+
+       if (!state->author_name || !state->author_email || !state->author_date)
+               die(_("cannot resume: %s does not exist."),
+                       am_path(state, "author-script"));
+}
+
+/**
+ * Interactively prompt the user on whether the current patch should be
+ * applied.
+ *
+ * Returns 0 if the user chooses to apply the patch, 1 if the user chooses to
+ * skip it.
+ */
+static int do_interactive(struct am_state *state)
+{
+       assert(state->msg);
+
+       if (!isatty(0))
+               die(_("cannot be interactive without stdin connected to a terminal."));
+
+       for (;;) {
+               const char *reply;
+
+               puts(_("Commit Body is:"));
+               puts("--------------------------");
+               printf("%s", state->msg);
+               puts("--------------------------");
+
+               /*
+                * TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
+                * in your translation. The program will only accept English
+                * input at this point.
+                */
+               reply = git_prompt(_("Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: "), PROMPT_ECHO);
+
+               if (!reply) {
+                       continue;
+               } else if (*reply == 'y' || *reply == 'Y') {
+                       return 0;
+               } else if (*reply == 'a' || *reply == 'A') {
+                       state->interactive = 0;
+                       return 0;
+               } else if (*reply == 'n' || *reply == 'N') {
+                       return 1;
+               } else if (*reply == 'e' || *reply == 'E') {
+                       struct strbuf msg = STRBUF_INIT;
+
+                       if (!launch_editor(am_path(state, "final-commit"), &msg, NULL)) {
+                               free(state->msg);
+                               state->msg = strbuf_detach(&msg, &state->msg_len);
+                       }
+                       strbuf_release(&msg);
+               } else if (*reply == 'v' || *reply == 'V') {
+                       const char *pager = git_pager(1);
+                       struct child_process cp = CHILD_PROCESS_INIT;
+
+                       if (!pager)
+                               pager = "cat";
+                       argv_array_push(&cp.args, pager);
+                       argv_array_push(&cp.args, am_path(state, "patch"));
+                       run_command(&cp);
+               }
+       }
+}
+
+/**
+ * Applies all queued mail.
+ *
+ * If `resume` is true, we are "resuming". The "msg" and authorship fields, as
+ * well as the state directory's "patch" file is used as-is for applying the
+ * patch and committing it.
+ */
+static void am_run(struct am_state *state, int resume)
+{
+       const char *argv_gc_auto[] = {"gc", "--auto", NULL};
+       struct strbuf sb = STRBUF_INIT;
+
+       unlink(am_path(state, "dirtyindex"));
+
+       refresh_and_write_cache();
+
+       if (index_has_changes(&sb)) {
+               write_file(am_path(state, "dirtyindex"), 1, "t");
+               die(_("Dirty index: cannot apply patches (dirty: %s)"), sb.buf);
+       }
+
+       strbuf_release(&sb);
+
+       while (state->cur <= state->last) {
+               const char *mail = am_path(state, msgnum(state));
+               int apply_status;
+
+               if (!file_exists(mail))
+                       goto next;
+
+               if (resume) {
+                       validate_resume_state(state);
+                       resume = 0;
+               } else {
+                       int skip;
+
+                       if (state->rebasing)
+                               skip = parse_mail_rebase(state, mail);
+                       else
+                               skip = parse_mail(state, mail);
+
+                       if (skip)
+                               goto next; /* mail should be skipped */
+
+                       write_author_script(state);
+                       write_commit_msg(state);
+               }
+
+               if (state->interactive && do_interactive(state))
+                       goto next;
+
+               if (run_applypatch_msg_hook(state))
+                       exit(1);
+
+               say(state, stdout, _("Applying: %.*s"), linelen(state->msg), state->msg);
+
+               apply_status = run_apply(state, NULL);
+
+               if (apply_status && state->threeway) {
+                       struct strbuf sb = STRBUF_INIT;
+
+                       strbuf_addstr(&sb, am_path(state, "patch-merge-index"));
+                       apply_status = fall_back_threeway(state, sb.buf);
+                       strbuf_release(&sb);
+
+                       /*
+                        * Applying the patch to an earlier tree and merging
+                        * the result may have produced the same tree as ours.
+                        */
+                       if (!apply_status && !index_has_changes(NULL)) {
+                               say(state, stdout, _("No changes -- Patch already applied."));
+                               goto next;
+                       }
+               }
+
+               if (apply_status) {
+                       int advice_amworkdir = 1;
+
+                       printf_ln(_("Patch failed at %s %.*s"), msgnum(state),
+                               linelen(state->msg), state->msg);
+
+                       git_config_get_bool("advice.amworkdir", &advice_amworkdir);
+
+                       if (advice_amworkdir)
+                               printf_ln(_("The copy of the patch that failed is found in: %s"),
+                                               am_path(state, "patch"));
+
+                       die_user_resolve(state);
+               }
+
+               do_commit(state);
+
+next:
+               am_next(state);
+       }
+
+       if (!is_empty_file(am_path(state, "rewritten"))) {
+               assert(state->rebasing);
+               copy_notes_for_rebase(state);
+               run_post_rewrite_hook(state);
+       }
+
+       /*
+        * In rebasing mode, it's up to the caller to take care of
+        * housekeeping.
+        */
+       if (!state->rebasing) {
+               am_destroy(state);
+               run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+       }
+}
+
+/**
+ * Resume the current am session after patch application failure. The user did
+ * all the hard work, and we do not have to do any patch application. Just
+ * trust and commit what the user has in the index and working tree.
+ */
+static void am_resolve(struct am_state *state)
+{
+       validate_resume_state(state);
+
+       say(state, stdout, _("Applying: %.*s"), linelen(state->msg), state->msg);
+
+       if (!index_has_changes(NULL)) {
+               printf_ln(_("No changes - did you forget to use 'git add'?\n"
+                       "If there is nothing left to stage, chances are that something else\n"
+                       "already introduced the same changes; you might want to skip this patch."));
+               die_user_resolve(state);
+       }
+
+       if (unmerged_cache()) {
+               printf_ln(_("You still have unmerged paths in your index.\n"
+                       "Did you forget to use 'git add'?"));
+               die_user_resolve(state);
+       }
+
+       if (state->interactive) {
+               write_index_patch(state);
+               if (do_interactive(state))
+                       goto next;
+       }
+
+       rerere(0);
+
+       do_commit(state);
+
+next:
+       am_next(state);
+       am_run(state, 0);
+}
+
+/**
+ * Performs a checkout fast-forward from `head` to `remote`. If `reset` is
+ * true, any unmerged entries will be discarded. Returns 0 on success, -1 on
+ * failure.
+ */
+static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
+{
+       struct lock_file *lock_file;
+       struct unpack_trees_options opts;
+       struct tree_desc t[2];
+
+       if (parse_tree(head) || parse_tree(remote))
+               return -1;
+
+       lock_file = xcalloc(1, sizeof(struct lock_file));
+       hold_locked_index(lock_file, 1);
+
+       refresh_cache(REFRESH_QUIET);
+
+       memset(&opts, 0, sizeof(opts));
+       opts.head_idx = 1;
+       opts.src_index = &the_index;
+       opts.dst_index = &the_index;
+       opts.update = 1;
+       opts.merge = 1;
+       opts.reset = reset;
+       opts.fn = twoway_merge;
+       init_tree_desc(&t[0], head->buffer, head->size);
+       init_tree_desc(&t[1], remote->buffer, remote->size);
+
+       if (unpack_trees(2, t, &opts)) {
+               rollback_lock_file(lock_file);
+               return -1;
+       }
+
+       if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+               die(_("unable to write new index file"));
+
+       return 0;
+}
+
+/**
+ * Clean the index without touching entries that are not modified between
+ * `head` and `remote`.
+ */
+static int clean_index(const unsigned char *head, const unsigned char *remote)
+{
+       struct lock_file *lock_file;
+       struct tree *head_tree, *remote_tree, *index_tree;
+       unsigned char index[GIT_SHA1_RAWSZ];
+       struct pathspec pathspec;
+
+       head_tree = parse_tree_indirect(head);
+       if (!head_tree)
+               return error(_("Could not parse object '%s'."), sha1_to_hex(head));
+
+       remote_tree = parse_tree_indirect(remote);
+       if (!remote_tree)
+               return error(_("Could not parse object '%s'."), sha1_to_hex(remote));
+
+       read_cache_unmerged();
+
+       if (fast_forward_to(head_tree, head_tree, 1))
+               return -1;
+
+       if (write_cache_as_tree(index, 0, NULL))
+               return -1;
+
+       index_tree = parse_tree_indirect(index);
+       if (!index_tree)
+               return error(_("Could not parse object '%s'."), sha1_to_hex(index));
+
+       if (fast_forward_to(index_tree, remote_tree, 0))
+               return -1;
+
+       memset(&pathspec, 0, sizeof(pathspec));
+
+       lock_file = xcalloc(1, sizeof(struct lock_file));
+       hold_locked_index(lock_file, 1);
+
+       if (read_tree(remote_tree, 0, &pathspec)) {
+               rollback_lock_file(lock_file);
+               return -1;
+       }
+
+       if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
+               die(_("unable to write new index file"));
+
+       remove_branch_state();
+
+       return 0;
+}
+
+/**
+ * Resets rerere's merge resolution metadata.
+ */
+static void am_rerere_clear(void)
+{
+       struct string_list merge_rr = STRING_LIST_INIT_DUP;
+       int fd = setup_rerere(&merge_rr, 0);
+
+       if (fd < 0)
+               return;
+
+       rerere_clear(&merge_rr);
+       string_list_clear(&merge_rr, 1);
+}
+
+/**
+ * Resume the current am session by skipping the current patch.
+ */
+static void am_skip(struct am_state *state)
+{
+       unsigned char head[GIT_SHA1_RAWSZ];
+
+       am_rerere_clear();
+
+       if (get_sha1("HEAD", head))
+               hashcpy(head, EMPTY_TREE_SHA1_BIN);
+
+       if (clean_index(head, head))
+               die(_("failed to clean index"));
+
+       am_next(state);
+       am_run(state, 0);
+}
+
+/**
+ * Returns true if it is safe to reset HEAD to the ORIG_HEAD, false otherwise.
+ *
+ * It is not safe to reset HEAD when:
+ * 1. git-am previously failed because the index was dirty.
+ * 2. HEAD has moved since git-am previously failed.
+ */
+static int safe_to_abort(const struct am_state *state)
+{
+       struct strbuf sb = STRBUF_INIT;
+       unsigned char abort_safety[GIT_SHA1_RAWSZ], head[GIT_SHA1_RAWSZ];
+
+       if (file_exists(am_path(state, "dirtyindex")))
+               return 0;
+
+       if (read_state_file(&sb, state, "abort-safety", 1) > 0) {
+               if (get_sha1_hex(sb.buf, abort_safety))
+                       die(_("could not parse %s"), am_path(state, "abort_safety"));
+       } else
+               hashclr(abort_safety);
+
+       if (get_sha1("HEAD", head))
+               hashclr(head);
+
+       if (!hashcmp(head, abort_safety))
+               return 1;
+
+       error(_("You seem to have moved HEAD since the last 'am' failure.\n"
+               "Not rewinding to ORIG_HEAD"));
+
+       return 0;
+}
+
+/**
+ * Aborts the current am session if it is safe to do so.
+ */
+static void am_abort(struct am_state *state)
+{
+       unsigned char curr_head[GIT_SHA1_RAWSZ], orig_head[GIT_SHA1_RAWSZ];
+       int has_curr_head, has_orig_head;
+       char *curr_branch;
+
+       if (!safe_to_abort(state)) {
+               am_destroy(state);
+               return;
+       }
+
+       am_rerere_clear();
+
+       curr_branch = resolve_refdup("HEAD", 0, curr_head, NULL);
+       has_curr_head = !is_null_sha1(curr_head);
+       if (!has_curr_head)
+               hashcpy(curr_head, EMPTY_TREE_SHA1_BIN);
+
+       has_orig_head = !get_sha1("ORIG_HEAD", orig_head);
+       if (!has_orig_head)
+               hashcpy(orig_head, EMPTY_TREE_SHA1_BIN);
+
+       clean_index(curr_head, orig_head);
+
+       if (has_orig_head)
+               update_ref("am --abort", "HEAD", orig_head,
+                               has_curr_head ? curr_head : NULL, 0,
+                               UPDATE_REFS_DIE_ON_ERR);
+       else if (curr_branch)
+               delete_ref(curr_branch, NULL, REF_NODEREF);
+
+       free(curr_branch);
+       am_destroy(state);
+}
+
+/**
+ * parse_options() callback that validates and sets opt->value to the
+ * PATCH_FORMAT_* enum value corresponding to `arg`.
+ */
+static int parse_opt_patchformat(const struct option *opt, const char *arg, int unset)
+{
+       int *opt_value = opt->value;
+
+       if (!strcmp(arg, "mbox"))
+               *opt_value = PATCH_FORMAT_MBOX;
+       else if (!strcmp(arg, "stgit"))
+               *opt_value = PATCH_FORMAT_STGIT;
+       else if (!strcmp(arg, "stgit-series"))
+               *opt_value = PATCH_FORMAT_STGIT_SERIES;
+       else if (!strcmp(arg, "hg"))
+               *opt_value = PATCH_FORMAT_HG;
+       else
+               return error(_("Invalid value for --patch-format: %s"), arg);
+       return 0;
+}
+
+enum resume_mode {
+       RESUME_FALSE = 0,
+       RESUME_APPLY,
+       RESUME_RESOLVED,
+       RESUME_SKIP,
+       RESUME_ABORT
+};
+
+int cmd_am(int argc, const char **argv, const char *prefix)
+{
+       struct am_state state;
+       int binary = -1;
+       int keep_cr = -1;
+       int patch_format = PATCH_FORMAT_UNKNOWN;
+       enum resume_mode resume = RESUME_FALSE;
+
+       const char * const usage[] = {
+               N_("git am [options] [(<mbox>|<Maildir>)...]"),
+               N_("git am [options] (--continue | --skip | --abort)"),
+               NULL
+       };
+
+       struct option options[] = {
+               OPT_BOOL('i', "interactive", &state.interactive,
+                       N_("run interactively")),
+               OPT_HIDDEN_BOOL('b', "binary", &binary,
+                       N_("(historical option -- no-op")),
+               OPT_BOOL('3', "3way", &state.threeway,
+                       N_("allow fall back on 3way merging if needed")),
+               OPT__QUIET(&state.quiet, N_("be quiet")),
+               OPT_BOOL('s', "signoff", &state.signoff,
+                       N_("add a Signed-off-by line to the commit message")),
+               OPT_BOOL('u', "utf8", &state.utf8,
+                       N_("recode into utf8 (default)")),
+               OPT_SET_INT('k', "keep", &state.keep,
+                       N_("pass -k flag to git-mailinfo"), KEEP_TRUE),
+               OPT_SET_INT(0, "keep-non-patch", &state.keep,
+                       N_("pass -b flag to git-mailinfo"), KEEP_NON_PATCH),
+               OPT_BOOL('m', "message-id", &state.message_id,
+                       N_("pass -m flag to git-mailinfo")),
+               { OPTION_SET_INT, 0, "keep-cr", &keep_cr, NULL,
+                 N_("pass --keep-cr flag to git-mailsplit for mbox format"),
+                 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1},
+               { OPTION_SET_INT, 0, "no-keep-cr", &keep_cr, NULL,
+                 N_("do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"),
+                 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 0},
+               OPT_BOOL('c', "scissors", &state.scissors,
+                       N_("strip everything before a scissors line")),
+               OPT_PASSTHRU_ARGV(0, "whitespace", &state.git_apply_opts, N_("action"),
+                       N_("pass it through git-apply"),
+                       0),
+               OPT_PASSTHRU_ARGV(0, "ignore-space-change", &state.git_apply_opts, NULL,
+                       N_("pass it through git-apply"),
+                       PARSE_OPT_NOARG),
+               OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &state.git_apply_opts, NULL,
+                       N_("pass it through git-apply"),
+                       PARSE_OPT_NOARG),
+               OPT_PASSTHRU_ARGV(0, "directory", &state.git_apply_opts, N_("root"),
+                       N_("pass it through git-apply"),
+                       0),
+               OPT_PASSTHRU_ARGV(0, "exclude", &state.git_apply_opts, N_("path"),
+                       N_("pass it through git-apply"),
+                       0),
+               OPT_PASSTHRU_ARGV(0, "include", &state.git_apply_opts, N_("path"),
+                       N_("pass it through git-apply"),
+                       0),
+               OPT_PASSTHRU_ARGV('C', NULL, &state.git_apply_opts, N_("n"),
+                       N_("pass it through git-apply"),
+                       0),
+               OPT_PASSTHRU_ARGV('p', NULL, &state.git_apply_opts, N_("num"),
+                       N_("pass it through git-apply"),
+                       0),
+               OPT_CALLBACK(0, "patch-format", &patch_format, N_("format"),
+                       N_("format the patch(es) are in"),
+                       parse_opt_patchformat),
+               OPT_PASSTHRU_ARGV(0, "reject", &state.git_apply_opts, NULL,
+                       N_("pass it through git-apply"),
+                       PARSE_OPT_NOARG),
+               OPT_STRING(0, "resolvemsg", &state.resolvemsg, NULL,
+                       N_("override error message when patch failure occurs")),
+               OPT_CMDMODE(0, "continue", &resume,
+                       N_("continue applying patches after resolving a conflict"),
+                       RESUME_RESOLVED),
+               OPT_CMDMODE('r', "resolved", &resume,
+                       N_("synonyms for --continue"),
+                       RESUME_RESOLVED),
+               OPT_CMDMODE(0, "skip", &resume,
+                       N_("skip the current patch"),
+                       RESUME_SKIP),
+               OPT_CMDMODE(0, "abort", &resume,
+                       N_("restore the original branch and abort the patching operation."),
+                       RESUME_ABORT),
+               OPT_BOOL(0, "committer-date-is-author-date",
+                       &state.committer_date_is_author_date,
+                       N_("lie about committer date")),
+               OPT_BOOL(0, "ignore-date", &state.ignore_date,
+                       N_("use current timestamp for author date")),
+               OPT_RERERE_AUTOUPDATE(&state.allow_rerere_autoupdate),
+               { OPTION_STRING, 'S', "gpg-sign", &state.sign_commit, N_("key-id"),
+                 N_("GPG-sign commits"),
+                 PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+               OPT_HIDDEN_BOOL(0, "rebasing", &state.rebasing,
+                       N_("(internal use for git-rebase)")),
+               OPT_END()
+       };
+
+       git_config(git_default_config, NULL);
+
+       am_state_init(&state, git_path("rebase-apply"));
+
+       argc = parse_options(argc, argv, prefix, options, usage, 0);
+
+       if (binary >= 0)
+               fprintf_ln(stderr, _("The -b/--binary option has been a no-op for long time, and\n"
+                               "it will be removed. Please do not use it anymore."));
+
+       /* Ensure a valid committer ident can be constructed */
+       git_committer_info(IDENT_STRICT);
+
+       if (read_index_preload(&the_index, NULL) < 0)
+               die(_("failed to read the index"));
+
+       if (am_in_progress(&state)) {
+               /*
+                * Catch user error to feed us patches when there is a session
+                * in progress:
+                *
+                * 1. mbox path(s) are provided on the command-line.
+                * 2. stdin is not a tty: the user is trying to feed us a patch
+                *    from standard input. This is somewhat unreliable -- stdin
+                *    could be /dev/null for example and the caller did not
+                *    intend to feed us a patch but wanted to continue
+                *    unattended.
+                */
+               if (argc || (resume == RESUME_FALSE && !isatty(0)))
+                       die(_("previous rebase directory %s still exists but mbox given."),
+                               state.dir);
+
+               if (resume == RESUME_FALSE)
+                       resume = RESUME_APPLY;
+
+               am_load(&state);
+       } else {
+               struct argv_array paths = ARGV_ARRAY_INIT;
+               int i;
+
+               /*
+                * Handle stray state directory in the independent-run case. In
+                * the --rebasing case, it is up to the caller to take care of
+                * stray directories.
+                */
+               if (file_exists(state.dir) && !state.rebasing) {
+                       if (resume == RESUME_ABORT) {
+                               am_destroy(&state);
+                               am_state_release(&state);
+                               return 0;
+                       }
+
+                       die(_("Stray %s directory found.\n"
+                               "Use \"git am --abort\" to remove it."),
+                               state.dir);
+               }
+
+               if (resume)
+                       die(_("Resolve operation not in progress, we are not resuming."));
+
+               for (i = 0; i < argc; i++) {
+                       if (is_absolute_path(argv[i]) || !prefix)
+                               argv_array_push(&paths, argv[i]);
+                       else
+                               argv_array_push(&paths, mkpath("%s/%s", prefix, argv[i]));
+               }
+
+               am_setup(&state, patch_format, paths.argv, keep_cr);
+
+               argv_array_clear(&paths);
+       }
+
+       switch (resume) {
+       case RESUME_FALSE:
+               am_run(&state, 0);
+               break;
+       case RESUME_APPLY:
+               am_run(&state, 1);
+               break;
+       case RESUME_RESOLVED:
+               am_resolve(&state);
+               break;
+       case RESUME_SKIP:
+               am_skip(&state);
+               break;
+       case RESUME_ABORT:
+               am_abort(&state);
+               break;
+       default:
+               die("BUG: invalid resume value");
+       }
+
+       am_state_release(&state);
+
+       return 0;
+}
index 0769b09..54aba4e 100644 (file)
@@ -208,7 +208,7 @@ struct patch {
        struct patch *next;
 
        /* three-way fallback result */
-       unsigned char threeway_stage[3][20];
+       struct object_id threeway_stage[3];
 };
 
 static void free_fragment_list(struct fragment *list)
@@ -1638,6 +1638,9 @@ static int parse_fragment(const char *line, unsigned long size,
        }
        if (oldlines || newlines)
                return -1;
+       if (!deleted && !added)
+               return -1;
+
        fragment->leading = leading;
        fragment->trailing = trailing;
 
@@ -3426,11 +3429,11 @@ static int try_threeway(struct image *image, struct patch *patch,
        if (status) {
                patch->conflicted_threeway = 1;
                if (patch->is_new)
-                       hashclr(patch->threeway_stage[0]);
+                       oidclr(&patch->threeway_stage[0]);
                else
-                       hashcpy(patch->threeway_stage[0], pre_sha1);
-               hashcpy(patch->threeway_stage[1], our_sha1);
-               hashcpy(patch->threeway_stage[2], post_sha1);
+                       hashcpy(patch->threeway_stage[0].hash, pre_sha1);
+               hashcpy(patch->threeway_stage[1].hash, our_sha1);
+               hashcpy(patch->threeway_stage[2].hash, post_sha1);
                fprintf(stderr, "Applied patch to '%s' with conflicts.\n", patch->new_name);
        } else {
                fprintf(stderr, "Applied patch to '%s' cleanly.\n", patch->new_name);
@@ -4186,14 +4189,14 @@ static void add_conflicted_stages_file(struct patch *patch)
 
        remove_file_from_cache(patch->new_name);
        for (stage = 1; stage < 4; stage++) {
-               if (is_null_sha1(patch->threeway_stage[stage - 1]))
+               if (is_null_oid(&patch->threeway_stage[stage - 1]))
                        continue;
                ce = xcalloc(1, ce_size);
                memcpy(ce->name, patch->new_name, namelen);
                ce->ce_mode = create_ce_mode(mode);
                ce->ce_flags = create_ce_flags(stage);
                ce->ce_namelen = namelen;
-               hashcpy(ce->sha1, patch->threeway_stage[stage - 1]);
+               hashcpy(ce->sha1, patch->threeway_stage[stage - 1].hash);
                if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0)
                        die(_("unable to add cache entry for %s"), patch->new_name);
        }
index b3e948e..04e4864 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "cache.h"
+#include "refs.h"
 #include "builtin.h"
 #include "blob.h"
 #include "commit.h"
@@ -50,7 +51,7 @@ static int xdl_opts;
 static int abbrev = -1;
 static int no_whole_file_rename;
 
-static enum date_mode blame_date_mode = DATE_ISO8601;
+static struct date_mode blame_date_mode = { DATE_ISO8601 };
 static size_t blame_date_width;
 
 static struct string_list mailmap;