summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes-1.6.5.8.txt28
-rw-r--r--Documentation/RelNotes-1.6.6.1.txt19
-rw-r--r--Documentation/RelNotes-1.7.0.txt46
-rw-r--r--Documentation/config.txt94
-rw-r--r--Documentation/fetch-options.txt10
-rw-r--r--Documentation/git-add.txt2
-rw-r--r--Documentation/git-am.txt10
-rw-r--r--Documentation/git-apply.txt10
-rw-r--r--Documentation/git-archimport.txt12
-rw-r--r--Documentation/git-archive.txt4
-rw-r--r--Documentation/git-blame.txt8
-rw-r--r--Documentation/git-branch.txt6
-rw-r--r--Documentation/git-bundle.txt26
-rw-r--r--Documentation/git-check-ref-format.txt2
-rw-r--r--Documentation/git-checkout-index.txt8
-rw-r--r--Documentation/git-cherry-pick.txt2
-rw-r--r--Documentation/git-cherry.txt6
-rw-r--r--Documentation/git-citool.txt4
-rw-r--r--Documentation/git-clean.txt4
-rw-r--r--Documentation/git-commit-tree.txt2
-rw-r--r--Documentation/git-commit.txt20
-rw-r--r--Documentation/git-config.txt14
-rw-r--r--Documentation/git-cvsexportcommit.txt2
-rw-r--r--Documentation/git-cvsimport.txt18
-rw-r--r--Documentation/git-cvsserver.txt6
-rw-r--r--Documentation/git-daemon.txt42
-rw-r--r--Documentation/git-describe.txt6
-rw-r--r--Documentation/git-diff-files.txt2
-rw-r--r--Documentation/git-diff-index.txt20
-rw-r--r--Documentation/git-diff-tree.txt10
-rw-r--r--Documentation/git-diff.txt4
-rw-r--r--Documentation/git-difftool.txt33
-rw-r--r--Documentation/git-fast-export.txt12
-rw-r--r--Documentation/git-fast-import.txt20
-rw-r--r--Documentation/git-fetch-pack.txt6
-rw-r--r--Documentation/git-fetch.txt2
-rw-r--r--Documentation/git-filter-branch.txt24
-rw-r--r--Documentation/git-fmt-merge-msg.txt2
-rw-r--r--Documentation/git-for-each-ref.txt2
-rw-r--r--Documentation/git-format-patch.txt4
-rw-r--r--Documentation/git-fsck.txt4
-rw-r--r--Documentation/git-gc.txt20
-rw-r--r--Documentation/git-get-tar-commit-id.txt6
-rw-r--r--Documentation/git-grep.txt2
-rw-r--r--Documentation/git-gui.txt20
-rw-r--r--Documentation/git-hash-object.txt2
-rw-r--r--Documentation/git-help.txt8
-rw-r--r--Documentation/git-http-backend.txt22
-rw-r--r--Documentation/git-http-fetch.txt2
-rw-r--r--Documentation/git-imap-send.txt2
-rw-r--r--Documentation/git-index-pack.txt8
-rw-r--r--Documentation/git-init.txt6
-rw-r--r--Documentation/git-instaweb.txt2
-rw-r--r--Documentation/git-log.txt4
-rw-r--r--Documentation/git-ls-files.txt6
-rw-r--r--Documentation/git-ls-tree.txt4
-rw-r--r--Documentation/git-mailinfo.txt4
-rw-r--r--Documentation/git-merge-file.txt22
-rw-r--r--Documentation/git-merge-index.txt8
-rw-r--r--Documentation/git-merge-one-file.txt6
-rw-r--r--Documentation/git-merge.txt54
-rw-r--r--Documentation/git-mergetool.txt16
-rw-r--r--Documentation/git-name-rev.txt4
-rw-r--r--Documentation/git-notes.txt91
-rw-r--r--Documentation/git-pack-objects.txt6
-rw-r--r--Documentation/git-pack-redundant.txt2
-rw-r--r--Documentation/git-patch-id.txt2
-rw-r--r--Documentation/git-peek-remote.txt2
-rw-r--r--Documentation/git-prune.txt16
-rw-r--r--Documentation/git-pull.txt14
-rw-r--r--Documentation/git-push.txt15
-rw-r--r--Documentation/git-read-tree.txt42
-rw-r--r--Documentation/git-rebase.txt63
-rw-r--r--Documentation/git-receive-pack.txt6
-rw-r--r--Documentation/git-reflog.txt2
-rw-r--r--Documentation/git-remote.txt2
-rw-r--r--Documentation/git-repack.txt12
-rw-r--r--Documentation/git-replace.txt2
-rw-r--r--Documentation/git-rerere.txt28
-rw-r--r--Documentation/git-reset.txt2
-rw-r--r--Documentation/git-rev-list.txt6
-rw-r--r--Documentation/git-rev-parse.txt37
-rw-r--r--Documentation/git-revert.txt8
-rw-r--r--Documentation/git-send-pack.txt4
-rw-r--r--Documentation/git-sh-setup.txt2
-rw-r--r--Documentation/git-shortlog.txt4
-rw-r--r--Documentation/git-show-index.txt4
-rw-r--r--Documentation/git-show-ref.txt4
-rw-r--r--Documentation/git-show.txt6
-rw-r--r--Documentation/git-stash.txt8
-rw-r--r--Documentation/git-status.txt2
-rw-r--r--Documentation/git-submodule.txt8
-rw-r--r--Documentation/git-symbolic-ref.txt2
-rw-r--r--Documentation/git-tag.txt8
-rw-r--r--Documentation/git-tar-tree.txt6
-rw-r--r--Documentation/git-update-index.txt22
-rw-r--r--Documentation/git-upload-archive.txt4
-rw-r--r--Documentation/git-upload-pack.txt8
-rw-r--r--Documentation/git-var.txt2
-rw-r--r--Documentation/git-verify-pack.txt2
-rw-r--r--Documentation/git-verify-tag.txt2
-rw-r--r--Documentation/git-web--browse.txt6
-rw-r--r--Documentation/git-whatchanged.txt4
-rw-r--r--Documentation/git-write-tree.txt8
-rw-r--r--Documentation/git.txt14
-rw-r--r--Documentation/gitattributes.txt29
-rw-r--r--Documentation/gitcore-tutorial.txt168
-rw-r--r--Documentation/gitcvs-migration.txt10
-rw-r--r--Documentation/gitdiffcore.txt26
-rw-r--r--Documentation/githooks.txt64
-rw-r--r--Documentation/gitignore.txt4
-rw-r--r--Documentation/gitk.txt2
-rw-r--r--Documentation/gitrepository-layout.txt18
-rw-r--r--Documentation/gittutorial-2.txt16
-rw-r--r--Documentation/gittutorial.txt42
-rw-r--r--Documentation/gitworkflows.txt6
-rw-r--r--Documentation/i18n.txt4
-rw-r--r--Documentation/merge-options.txt9
-rw-r--r--Documentation/merge-strategies.txt29
-rw-r--r--Documentation/pretty-formats.txt1
-rw-r--r--Documentation/pretty-options.txt8
-rw-r--r--Documentation/pull-fetch-param.txt8
-rw-r--r--Documentation/technical/api-strbuf.txt11
-rw-r--r--Documentation/urls-remotes.txt4
-rw-r--r--Makefile34
-rw-r--r--advice.c18
-rw-r--r--advice.h6
-rw-r--r--archive.c4
-rw-r--r--attr.c11
-rw-r--r--attr.h2
-rw-r--r--bisect.c2
-rw-r--r--bisect.h2
-rw-r--r--blob.c21
-rw-r--r--blob.h9
-rw-r--r--builtin-add.c76
-rw-r--r--builtin-apply.c13
-rw-r--r--builtin-check-attr.c2
-rw-r--r--builtin-checkout.c12
-rw-r--r--builtin-commit.c60
-rw-r--r--builtin-grep.c357
-rw-r--r--builtin-hash-object.c (renamed from hash-object.c)5
-rw-r--r--builtin-index-pack.c (renamed from index-pack.c)16
-rw-r--r--builtin-log.c3
-rw-r--r--builtin-ls-files.c43
-rw-r--r--builtin-merge-file.c17
-rw-r--r--builtin-merge-index.c (renamed from merge-index.c)7
-rw-r--r--builtin-merge-recursive.c27
-rw-r--r--builtin-merge-tree.c (renamed from merge-tree.c)10
-rw-r--r--builtin-merge.c69
-rw-r--r--builtin-mktag.c (renamed from mktag.c)6
-rw-r--r--builtin-mv.c11
-rw-r--r--builtin-notes.c459
-rw-r--r--builtin-pack-objects.c7
-rw-r--r--builtin-pack-redundant.c (renamed from pack-redundant.c)8
-rw-r--r--builtin-patch-id.c (renamed from patch-id.c)4
-rw-r--r--builtin-push.c2
-rw-r--r--builtin-read-tree.c2
-rw-r--r--builtin-rerere.c5
-rw-r--r--builtin-rev-list.c2
-rw-r--r--builtin-rev-parse.c6
-rw-r--r--builtin-revert.c15
-rw-r--r--builtin-rm.c3
-rw-r--r--builtin-send-pack.c51
-rw-r--r--builtin-unpack-file.c (renamed from unpack-file.c)5
-rw-r--r--builtin-update-index.c18
-rw-r--r--builtin-var.c (renamed from var.c)4
-rw-r--r--builtin.h12
-rw-r--r--cache.h17
-rw-r--r--commit.h2
-rw-r--r--config.c6
-rw-r--r--contrib/buildsystems/engine.pl8
-rwxr-xr-xcontrib/examples/git-merge.sh3
-rwxr-xr-xcontrib/examples/git-notes.sh (renamed from git-notes.sh)0
-rwxr-xr-xcontrib/fast-import/git-p42
-rw-r--r--convert.c6
-rw-r--r--daemon.c1
-rw-r--r--date.c2
-rw-r--r--dir.c215
-rw-r--r--entry.c2
-rw-r--r--fast-import.c134
-rw-r--r--git-compat-util.h2
-rwxr-xr-xgit-cvsimport.perl70
-rwxr-xr-xgit-difftool--helper.sh38
-rwxr-xr-xgit-difftool.perl26
-rwxr-xr-xgit-pull.sh55
-rwxr-xr-xgit-rebase--interactive.sh284
-rwxr-xr-xgit-sh-setup.sh19
-rw-r--r--git.c14
-rw-r--r--grep.c84
-rw-r--r--grep.h1
-rw-r--r--hex.c67
-rw-r--r--http.c10
-rw-r--r--http.h9
-rw-r--r--ident.c25
-rw-r--r--ll-merge.c88
-rw-r--r--ll-merge.h4
-rw-r--r--log-tree.c1
-rw-r--r--mailmap.c5
-rw-r--r--mailmap.h1
-rw-r--r--match-trees.c69
-rw-r--r--merge-file.c16
-rw-r--r--merge-recursive.c47
-rw-r--r--merge-recursive.h7
-rw-r--r--notes.c843
-rw-r--r--notes.h196
-rw-r--r--object.c21
-rw-r--r--object.h5
-rw-r--r--pack-write.c4
-rw-r--r--pack.h2
-rw-r--r--parse-options.c7
-rw-r--r--parse-options.h3
-rw-r--r--pretty.c13
-rw-r--r--quote.c2
-rw-r--r--quote.h1
-rw-r--r--read-cache.c102
-rw-r--r--remote-curl.c20
-rw-r--r--remote.c50
-rw-r--r--remote.h2
-rw-r--r--rerere.c299
-rw-r--r--rerere.h1
-rw-r--r--resolve-undo.c176
-rw-r--r--resolve-undo.h16
-rw-r--r--revision.c9
-rw-r--r--revision.h3
-rw-r--r--run-command.c177
-rw-r--r--setup.c22
-rw-r--r--sha1_file.c74
-rw-r--r--show-index.c2
-rw-r--r--strbuf.c33
-rw-r--r--strbuf.h3
-rw-r--r--submodule.c2
-rw-r--r--symlinks.c31
-rw-r--r--t/lib-rebase.sh33
-rwxr-xr-xt/t0061-run-command.sh14
-rwxr-xr-xt/t2030-unresolve-info.sh170
-rwxr-xr-xt/t2105-update-index-gitfile.sh38
-rwxr-xr-xt/t3001-ls-files-others-exclude.sh39
-rwxr-xr-xt/t3030-merge-recursive.sh6
-rwxr-xr-xt/t3301-notes.sh543
-rwxr-xr-xt/t3303-notes-subtrees.sh28
-rwxr-xr-xt/t3304-notes-mixed.sh36
-rwxr-xr-xt/t3305-notes-fanout.sh95
-rwxr-xr-xt/t3306-notes-prune.sh94
-rwxr-xr-xt/t3404-rebase-interactive.sh205
-rwxr-xr-xt/t3415-rebase-autosquash.sh73
-rwxr-xr-xt/t3416-rebase-onto-threedots.sh (renamed from t/t3415-rebase-onto-threedots.sh)0
-rwxr-xr-xt/t3501-revert-cherry-pick.sh2
-rwxr-xr-xt/t4120-apply-popt.sh5
-rwxr-xr-xt/t4133-apply-filenames.sh38
-rwxr-xr-xt/t5523-push-upstream.sh69
-rwxr-xr-xt/t5541-http-push.sh44
-rwxr-xr-xt/t6006-rev-list-format.sh7
-rwxr-xr-xt/t6026-merge-attr.sh12
-rwxr-xr-xt/t6029-merge-subtree.sh47
-rwxr-xr-xt/t6037-merge-ours-theirs.sh64
-rwxr-xr-xt/t7001-mv.sh12
-rwxr-xr-xt/t7002-grep.sh74
-rwxr-xr-xt/t7501-commit.sh6
-rwxr-xr-xt/t7800-difftool.sh63
-rwxr-xr-xt/t9300-fast-import.sh156
-rwxr-xr-xt/t9301-fast-import-notes.sh623
-rwxr-xr-xt/t9350-fast-export.sh (renamed from t/t9301-fast-export.sh)0
-rw-r--r--test-run-command.c35
-rw-r--r--transport-helper.c42
-rw-r--r--transport.c67
-rw-r--r--transport.h1
-rw-r--r--userdiff.c2
-rw-r--r--utf8.c2
-rw-r--r--utf8.h1
-rw-r--r--ws.c2
-rw-r--r--wt-status.c2
-rw-r--r--xdiff/xdiff.h15
-rw-r--r--xdiff/xmerge.c33
273 files changed, 7205 insertions, 2229 deletions
diff --git a/Documentation/RelNotes-1.6.5.8.txt b/Documentation/RelNotes-1.6.5.8.txt
new file mode 100644
index 0000000..8b24beb
--- /dev/null
+++ b/Documentation/RelNotes-1.6.5.8.txt
@@ -0,0 +1,28 @@
+Git v1.6.5.8 Release Notes
+==========================
+
+Fixes since v1.6.5.7
+--------------------
+
+* "git count-objects" did not handle packfiles that are bigger than 4G on
+ platforms with 32-bit off_t.
+
+* "git rebase -i" did not abort cleanly if it failed to launch the editor.
+
+* "git blame" did not work well when commit lacked the author name.
+
+* "git fast-import" choked when handling a tag that points at an object
+ that is not a commit.
+
+* "git reset --hard" did not work correctly when GIT_WORK_TREE environment
+ variable is used to point at the root of the true work tree.
+
+* "git grep" fed a buffer that is not NUL-terminated to underlying
+ regexec().
+
+* "git checkout -m other" while on a branch that does not have any commit
+ segfaulted, instead of failing.
+
+* "git branch -a other" should have diagnosed the command as an error.
+
+Other minor documentation updates are also included.
diff --git a/Documentation/RelNotes-1.6.6.1.txt b/Documentation/RelNotes-1.6.6.1.txt
index 406fbc4..f1d0a4a 100644
--- a/Documentation/RelNotes-1.6.6.1.txt
+++ b/Documentation/RelNotes-1.6.6.1.txt
@@ -4,8 +4,16 @@ Git v1.6.6.1 Release Notes
Fixes since v1.6.6
------------------
+ * "git blame" did not work well when commit lacked the author name.
+
* "git branch -a name" wasn't diagnosed as an error.
+ * "git count-objects" did not handle packfiles that are bigger than 4G on
+ platforms with 32-bit off_t.
+
+ * "git checkout -m other" while on a branch that does not have any commit
+ segfaulted, instead of failing.
+
* "git fast-import" choked when fed a tag that do not point at a
commit.
@@ -15,6 +23,11 @@ Fixes since v1.6.6
* "git grep -L" didn't show empty files (they should never match, and
they should always appear in -L output as unmatching).
+ * "git rebase -i" did not abort cleanly if it failed to launch the editor.
+
+ * "git reset --hard" did not work correctly when GIT_WORK_TREE environment
+ variable is used to point at the root of the true work tree.
+
* http-backend was not listed in the command list in the documentation.
* Building on FreeBSD (both 7 and 8) needs OLD_ICONV set in the Makefile
@@ -22,9 +35,3 @@ Fixes since v1.6.6
* "git checkout -m some-branch" while on an unborn branch crashed.
Other minor documentation updates are included.
-
---
-exec >/var/tmp/1
-O=v1.6.6-39-g6304c40
-echo O=$(git describe maint)
-git shortlog --no-merges $O..maint
diff --git a/Documentation/RelNotes-1.7.0.txt b/Documentation/RelNotes-1.7.0.txt
index 7a49b47..a3d0395 100644
--- a/Documentation/RelNotes-1.7.0.txt
+++ b/Documentation/RelNotes-1.7.0.txt
@@ -77,9 +77,18 @@ Updates since v1.6.6
the submodule directory when it should (namely, when you are not
interested in the submodule at all and didn't clone/checkout).
+ * A new attribute conflict-marker-size can be used to change the size of
+ the conflict markers from the default 7; this is useful when tracked
+ contents (e.g. git-merge documentation) have strings that resemble the
+ conflict markers.
+
* "git checkout A...B" is a way to detach HEAD at the merge base between
A and B.
+ * "git checkout -m path" to reset the work tree file back into the
+ conflicted state works even when you already ran "git add path" and
+ resolved the conflicts.
+
* "git commit --date='<date>'" can be used to override the author date
just like "git commit --author='<name> <email>'" can be used to
override the author identity.
@@ -87,14 +96,49 @@ Updates since v1.6.6
* "git commit --no-status" can be used to omit the listing of the index
and the work tree status in the editor used to prepare the log message.
+ * "git commit" warns a bit more aggressively until you configure user.email,
+ whose default value almost always is not (and fundamentally cannot be)
+ what you want.
+
+ * "git difftool" has been extended to make it easier to integrate it
+ with gitk.
+
* "git fetch --all" can now be used in place of "git remote update".
+ * "git grep" does not rely on external grep anymore.
+
+ * "git grep" learned "--no-index" option, to search inside contents that
+ are not managed by git.
+
+ * "git merge" learned to pass options specific to strategy-backends. E.g.
+
+ - "git merge -Xsubtree=path/to/directory" can be used to tell the subtree
+ strategy how much to shift the trees explicitly.
+
+ - "git merge -Xtheirs" can be used to auto-merge as much as possible,
+ while discarding your own changes and taking merged version in
+ conflicted regions.
+
* "git push" learned "git push origin --delete branch", a syntactic sugar
for "git push origin :branch".
+ * "git push" learned "git push --set-upstream origin forker:forkee" that
+ lets you configure your "forker" branch to later pull from "forkee"
+ branch at "origin".
+
* "git rebase --onto A...B" means the history is replayed on top of the
merge base between A and B.
+ * "git rebase -i" learned new action "fixup", that squashes the change
+ but does not affect existing log message.
+
+ * "git rebase -i" also learned --autosquash option, that is useful
+ together with the new "fixup" action.
+
+ * "git rerere" learned "forget path" subcommand. Together with "git
+ checkout -m path" it will be useful when you recorded a wrong
+ resolution.
+
* Use of "git reset --merge" has become easier when resetting away a
conflicted mess left in the work tree.
@@ -117,6 +161,6 @@ release, unless otherwise noted.
--
exec >/var/tmp/1
-O=v1.6.6-263-ge33fd3c
+O=v1.6.6.1-379-gd4556c4
echo O=$(git describe master)
git shortlog --no-merges $O..master ^maint
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 2d6775c..8dcb191 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -64,7 +64,7 @@ The values following the equals sign in variable assign are all either
a string, an integer, or a boolean. Boolean values may be given as yes/no,
0/1, true/false or on/off. Case is not significant in boolean values, when
converting value to the canonical form using '--bool' type specifier;
-'git-config' will ensure that the output is "true" or "false".
+'git config' will ensure that the output is "true" or "false".
String values may be entirely or partially enclosed in double quotes.
You need to enclose variable values in double quotes if you want to
@@ -130,6 +130,14 @@ advice.*::
Advice shown when linkgit:git-merge[1] refuses to
merge to avoid overwritting local changes.
Default: true.
+ resolveConflict::
+ Advices shown by various commands when conflicts
+ prevent the operation from being performed.
+ Default: true.
+ implicitIdentity::
+ Advice on how to set your identity configuration when
+ your information is guessed from the system username and
+ domain name. Default: true.
--
core.fileMode::
@@ -442,8 +450,8 @@ core.pager::
core.whitespace::
A comma separated list of common whitespace problems to
- notice. 'git-diff' will use `color.diff.whitespace` to
- highlight them, and 'git-apply --whitespace=error' will
+ notice. 'git diff' will use `color.diff.whitespace` to
+ highlight them, and 'git apply --whitespace=error' will
consider them as errors. You can prefix `-` to disable
any of them (e.g. `-trailing-space`):
+
@@ -507,7 +515,7 @@ core.sparseCheckout::
linkgit:git-read-tree[1] for more information.
add.ignore-errors::
- Tells 'git-add' to continue adding files when some files cannot be
+ Tells 'git add' to continue adding files when some files cannot be
added due to indexing errors. Equivalent to the '--ignore-errors'
option of linkgit:git-add[1].
@@ -529,19 +537,19 @@ executed from the top-level directory of a repository, which may
not necessarily be the current directory.
apply.ignorewhitespace::
- When set to 'change', tells 'git-apply' to ignore changes in
+ When set to 'change', tells 'git apply' to ignore changes in
whitespace, in the same way as the '--ignore-space-change'
option.
- When set to one of: no, none, never, false tells 'git-apply' to
+ When set to one of: no, none, never, false tells 'git apply' to
respect all whitespace differences.
See linkgit:git-apply[1].
apply.whitespace::
- Tells 'git-apply' how to handle whitespaces, in the same way
+ Tells 'git apply' how to handle whitespaces, in the same way
as the '--whitespace' option. See linkgit:git-apply[1].
branch.autosetupmerge::
- Tells 'git-branch' and 'git-checkout' to set up new branches
+ Tells 'git branch' and 'git checkout' to set up new branches
so that linkgit:git-pull[1] will appropriately merge from the
starting point branch. Note that even if this option is not set,
this behavior can be chosen per-branch using the `--track`
@@ -552,7 +560,7 @@ branch.autosetupmerge::
branch. This option defaults to true.
branch.autosetuprebase::
- When a new branch is created with 'git-branch' or 'git-checkout'
+ When a new branch is created with 'git branch' or 'git checkout'
that tracks another branch, this variable tells git to set
up pull to rebase instead of merge (see "branch.<name>.rebase").
When `never`, rebase is never automatically set to true.
@@ -567,24 +575,24 @@ branch.autosetuprebase::
This option defaults to never.
branch.<name>.remote::
- When in branch <name>, it tells 'git-fetch' and 'git-push' which
+ When in branch <name>, it tells 'git fetch' and 'git push' which
remote to fetch from/push to. It defaults to `origin` if no remote is
configured. `origin` is also used if you are not on any branch.
branch.<name>.merge::
Defines, together with branch.<name>.remote, the upstream branch
- for the given branch. It tells 'git-fetch'/'git-pull' which
- branch to merge and can also affect 'git-push' (see push.default).
- When in branch <name>, it tells 'git-fetch' the default
+ for the given branch. It tells 'git fetch'/'git pull' which
+ branch to merge and can also affect 'git push' (see push.default).
+ When in branch <name>, it tells 'git fetch' the default
refspec to be marked for merging in FETCH_HEAD. The value is
handled like the remote part of a refspec, and must match a
ref which is fetched from the remote given by
"branch.<name>.remote".
- The merge information is used by 'git-pull' (which at first calls
- 'git-fetch') to lookup the default branch for merging. Without
- this option, 'git-pull' defaults to merge the first refspec fetched.
+ The merge information is used by 'git pull' (which at first calls
+ 'git fetch') to lookup the default branch for merging. Without
+ this option, 'git pull' defaults to merge the first refspec fetched.
Specify multiple values to get an octopus merge.
- If you wish to setup 'git-pull' so that it merges into <name> from
+ If you wish to setup 'git pull' so that it merges into <name> from
another branch in the local repository, you can point
branch.<name>.merge to the desired branch, and use the special setting
`.` (a period) for branch.<name>.remote.
@@ -656,14 +664,6 @@ color.grep::
`never`), never. When set to `true` or `auto`, use color only
when the output is written to the terminal. Defaults to `false`.
-color.grep.external::
- The string value of this variable is passed to an external 'grep'
- command as a command line option if match highlighting is turned
- on. If set to an empty string, no option is passed at all,
- turning off coloring for external 'grep' calls; this is the default.
- For GNU grep, set it to `--color=always` to highlight matches even
- when a pager is used.
-
color.grep.match::
Use customized color for matches. The value of this variable
may be specified as in color.branch.<slot>. It is passed using
@@ -677,7 +677,7 @@ color.interactive::
colors only when the output is to the terminal. Defaults to false.
color.interactive.<slot>::
- Use customized color for 'git-add --interactive'
+ Use customized color for 'git add --interactive'
output. `<slot>` may be `prompt`, `header`, `help` or `error`, for
four distinct types of normal output from interactive
commands. The values of these variables may be specified as
@@ -727,14 +727,14 @@ commit.template::
specified user's home directory.
diff.autorefreshindex::
- When using 'git-diff' to compare with work tree
+ When using 'git diff' to compare with work tree
files, do not consider stat-only change as changed.
Instead, silently run `git update-index --refresh` to
update the cached stat information for paths whose
contents in the work tree match the contents in the
index. This option defaults to true. Note that this
- affects only 'git-diff' Porcelain, and not lower level
- 'diff' commands such as 'git-diff-files'.
+ affects only 'git diff' Porcelain, and not lower level
+ 'diff' commands such as 'git diff-files'.
diff.external::
If this config variable is set, diff generation is not
@@ -746,24 +746,24 @@ diff.external::
your files, you might want to use linkgit:gitattributes[5] instead.
diff.mnemonicprefix::
- If set, 'git-diff' uses a prefix pair that is different from the
+ If set, 'git diff' uses a prefix pair that is different from the
standard "a/" and "b/" depending on what is being compared. When
this configuration is in effect, reverse diff output also swaps
the order of the prefixes:
-'git-diff';;
+`git diff`;;
compares the (i)ndex and the (w)ork tree;
-'git-diff HEAD';;
+`git diff HEAD`;;
compares a (c)ommit and the (w)ork tree;
-'git diff --cached';;
+`git diff --cached`;;
compares a (c)ommit and the (i)ndex;
-'git-diff HEAD:file1 file2';;
+`git diff HEAD:file1 file2`;;
compares an (o)bject and a (w)ork tree entity;
-'git diff --no-index a b';;
+`git diff --no-index a b`;;
compares two non-git things (1) and (2).
diff.renameLimit::
The number of files to consider when performing the copy/rename
- detection; equivalent to the 'git-diff' option '-l'.
+ detection; equivalent to the 'git diff' option '-l'.
diff.renames::
Tells git to detect renames. If set to any boolean value, it
@@ -849,7 +849,7 @@ format.pretty::
linkgit:git-whatchanged[1].
format.thread::
- The default threading style for 'git-format-patch'. Can be
+ The default threading style for 'git format-patch'. Can be
a boolean value, or `shallow` or `deep`. `shallow` threading
makes every mail a reply to the head of the series,
where the head is chosen from the cover letter, the
@@ -867,7 +867,7 @@ format.signoff::
gc.aggressiveWindow::
The window size parameter used in the delta compression
- algorithm used by 'git-gc --aggressive'. This defaults
+ algorithm used by 'git gc --aggressive'. This defaults
to 10.
gc.auto::
@@ -887,33 +887,33 @@ gc.packrefs::
Running `git pack-refs` in a repository renders it
unclonable by Git versions prior to 1.5.1.2 over dumb
transports such as HTTP. This variable determines whether
- 'git gc' runs `git pack-refs`. This can be set to "nobare"
+ 'git gc' runs `git pack-refs`. This can be set to `nobare`
to enable it within all non-bare repos or it can be set to a
boolean value. The default is `true`.
gc.pruneexpire::
- When 'git-gc' is run, it will call 'prune --expire 2.weeks.ago'.
+ 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.
gc.reflogexpire::
- 'git-reflog expire' removes reflog entries older than
+ 'git reflog expire' removes reflog entries older than
this time; defaults to 90 days.
gc.reflogexpireunreachable::
- 'git-reflog expire' removes reflog entries older than
+ 'git reflog expire' removes reflog entries older than
this time and are not reachable from the current tip;
defaults to 30 days.
gc.rerereresolved::
Records of conflicted merge you resolved earlier are
- kept for this many days when 'git-rerere gc' is run.
+ kept for this many days when 'git rerere gc' is run.
The default is 60 days. See linkgit:git-rerere[1].
gc.rerereunresolved::
Records of conflicted merge you have not resolved are
- kept for this many days when 'git-rerere gc' is run.
+ kept for this many days when 'git rerere gc' is run.
The default is 15 days. See linkgit:git-rerere[1].
gitcvs.commitmsgannotation::
@@ -1021,7 +1021,7 @@ gui.spellingdictionary::
off.
gui.fastcopyblame::
- If true, 'git gui blame' uses '-C' instead of '-C -C' for original
+ If true, 'git gui blame' uses `-C` instead of `-C -C` for original
location detection. It makes blame significantly faster on huge
repositories at the expense of less thorough copy detection.
@@ -1180,7 +1180,7 @@ i18n.commitEncoding::
i18n.logOutputEncoding::
Character encoding the commit messages are converted to when
- running 'git-log' and friends.
+ running 'git log' and friends.
imap::
The configuration variables in the 'imap' section are described
@@ -1214,7 +1214,7 @@ interactive.singlekey::
log.date::
Set default date-time mode for the log command. Setting log.date
- value is similar to using 'git-log'\'s --date option. The value is one of the
+ value is similar to using 'git log'\'s --date option. The value is one of the
following alternatives: {relative,local,default,iso,rfc,short}.
See linkgit:git-log[1].
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index ab6419f..fe716b2 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -19,7 +19,7 @@ endif::git-pull[]
-f::
--force::
- When 'git-fetch' is used with `<rbranch>:<lbranch>`
+ When 'git fetch' is used with `<rbranch>:<lbranch>`
refspec, it refuses to update the local branch
`<lbranch>` unless the remote branch `<rbranch>` it
fetches is a descendant of `<lbranch>`. This option
@@ -61,16 +61,16 @@ endif::git-pull[]
-u::
--update-head-ok::
- By default 'git-fetch' refuses to update the head which
+ By default 'git fetch' refuses to update the head which
corresponds to the current branch. This flag disables the
- check. This is purely for the internal use for 'git-pull'
- to communicate with 'git-fetch', and unless you are
+ check. This is purely for the internal use for 'git pull'
+ to communicate with 'git fetch', and unless you are
implementing your own Porcelain you are not supposed to
use it.
--upload-pack <upload-pack>::
When given, and the repository to fetch from is handled
- by 'git-fetch-pack', '--exec=<upload-pack>' is passed to
+ by 'git fetch-pack', '--exec=<upload-pack>' is passed to
the command to specify non-default path for the command
run on the other end.
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 1f1b199..f74fcf3 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -39,7 +39,7 @@ The `git add` command will not add ignored files by default. If any
ignored files were explicitly specified on the command line, `git add`
will fail with a list of ignored files. Ignored files reached by
directory recursion or filename globbing performed by Git (quote your
-globs before the shell) will be silently ignored. The `add` command can
+globs before the shell) will be silently ignored. The 'git add' command can
be used to add ignored files with the `-f` (force) option.
Please see linkgit:git-commit[1] for alternative ways to add content to a
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 67ad5da..c3e4f12 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -37,7 +37,7 @@ OPTIONS
-k::
--keep::
- Pass `-k` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
+ Pass `-k` flag to 'git mailinfo' (see linkgit:git-mailinfo[1]).
-c::
--scissors::
@@ -53,7 +53,7 @@ OPTIONS
-u::
--utf8::
- Pass `-u` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
+ Pass `-u` flag to 'git mailinfo' (see linkgit:git-mailinfo[1]).
The proposed commit log message taken from the e-mail
is re-coded into UTF-8 encoding (configuration variable
`i18n.commitencoding` can be used to specify project's
@@ -63,7 +63,7 @@ This was optional in prior versions of git, but now it is the
default. You can use `--no-utf8` to override this.
--no-utf8::
- Pass `-n` flag to 'git-mailinfo' (see
+ Pass `-n` flag to 'git mailinfo' (see
linkgit:git-mailinfo[1]).
-3::
@@ -81,7 +81,7 @@ default. You can use `--no-utf8` to override this.
-p<n>::
--directory=<dir>::
--reject::
- These flags are passed to the 'git-apply' (see linkgit:git-apply[1])
+ These flags are passed to the 'git apply' (see linkgit:git-apply[1])
program that applies
the patch.
@@ -121,7 +121,7 @@ default. You can use `--no-utf8` to override this.
to the screen before exiting. This overrides the
standard message informing you to use `--resolved`
or `--skip` to handle the failure. This is solely
- for internal use between 'git-rebase' and 'git-am'.
+ for internal use between 'git rebase' and 'git am'.
--abort::
Restore the original branch and abort the patching operation.
diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index c2528a7..8463439 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -69,7 +69,7 @@ OPTIONS
without using the working tree. This implies `--index`.
--build-fake-ancestor=<file>::
- Newer 'git-diff' output has embedded 'index information'
+ Newer 'git diff' output has embedded 'index information'
for each blob to help identify the original version that
the patch applies to. When this flag is given, and if
the original versions of the blobs are available locally,
@@ -83,7 +83,7 @@ the information is read from the current index instead.
Apply the patch in reverse.
--reject::
- For atomicity, 'git-apply' by default fails the whole patch and
+ For atomicity, 'git apply' by default fails the whole patch and
does not touch the working tree when some of the hunks
do not apply. This option makes it apply
the parts of the patch that are applicable, and leave the
@@ -109,7 +109,7 @@ any of those replacements occurred.
ever ignored.
--unidiff-zero::
- By default, 'git-apply' expects that the patch being
+ By default, 'git apply' expects that the patch being
applied is a unified diff with at least one line of context.
This provides good safety measures, but breaks down when
applying a diff generated with `--unified=0`. To bypass these
@@ -120,7 +120,7 @@ discouraged.
--apply::
If you use any of the options marked "Turns off
- 'apply'" above, 'git-apply' reads and outputs the
+ 'apply'" above, 'git apply' reads and outputs the
requested information without actually applying the
patch. Give this flag after those flags to also apply
the patch.
@@ -229,7 +229,7 @@ apply.whitespace::
Submodules
----------
-If the patch contains any changes to submodules then 'git-apply'
+If the patch contains any changes to submodules then 'git apply'
treats these changes as follows.
If `--index` is specified (explicitly or implicitly), then the submodule
diff --git a/Documentation/git-archimport.txt b/Documentation/git-archimport.txt
index c7a6e3e..4d4325f 100644
--- a/Documentation/git-archimport.txt
+++ b/Documentation/git-archimport.txt
@@ -29,17 +29,17 @@ branches that have different roots, it will refuse to run. In that case,
edit your <archive/branch> parameters to define clearly the scope of the
import.
-'git-archimport' uses `tla` extensively in the background to access the
+'git archimport' uses `tla` extensively in the background to access the
Arch repository.
Make sure you have a recent version of `tla` available in the path. `tla` must
-know about the repositories you pass to 'git-archimport'.
+know about the repositories you pass to 'git archimport'.
-For the initial import, 'git-archimport' expects to find itself in an empty
+For the initial import, 'git archimport' expects to find itself in an empty
directory. To follow the development of a project that uses Arch, rerun
-'git-archimport' with the same parameters as the initial import to perform
+'git archimport' with the same parameters as the initial import to perform
incremental imports.
-While 'git-archimport' will try to create sensible branch names for the
+While 'git archimport' will try to create sensible branch names for the
archives that it imports, it is also possible to specify git branch names
manually. To do so, write a git branch name after each <archive/branch>
parameter, separated by a colon. This way, you can shorten the Arch
@@ -84,7 +84,7 @@ OPTIONS
-o::
Use this for compatibility with old-style branch names used by
- earlier versions of 'git-archimport'. Old-style branch names
+ earlier versions of 'git archimport'. Old-style branch names
were category--branch, whereas new-style branch names are
archive,category--branch--version. In both cases, names given
on the command-line will override the automatically-generated
diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
index e579791..799c8b6 100644
--- a/Documentation/git-archive.txt
+++ b/Documentation/git-archive.txt
@@ -21,13 +21,13 @@ structure for the named tree, and writes it out to the standard
output. If <prefix> is specified it is
prepended to the filenames in the archive.
-'git-archive' behaves differently when given a tree ID versus when
+'git archive' behaves differently when given a tree ID versus when
given a commit ID or tag ID. In the first case the current time is
used as the modification time of each file in the archive. In the latter
case the commit time as recorded in the referenced commit object is
used instead. Additionally the commit ID is stored in a global
extended pax header if the tar format is used; it can be extracted
-using 'git-get-tar-commit-id'. In ZIP files it is stored as a file
+using 'git get-tar-commit-id'. In ZIP files it is stored as a file
comment.
OPTIONS
diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt
index b786471..a27f439 100644
--- a/Documentation/git-blame.txt
+++ b/Documentation/git-blame.txt
@@ -21,7 +21,7 @@ last modified the line. Optionally, start annotating from the given revision.
The command can also limit the range of lines annotated.
The report does not tell you anything about lines which have been deleted or
-replaced; you need to use a tool such as 'git-diff' or the "pickaxe"
+replaced; you need to use a tool such as 'git diff' or the "pickaxe"
interface briefly mentioned in the following paragraph.
Apart from supporting file annotation, git also supports searching the
@@ -49,7 +49,7 @@ include::blame-options.txt[]
file (see `-M`). The first number listed is the score.
This is the number of alphanumeric characters detected
as having been moved between or within files. This must be above
- a certain threshold for 'git-blame' to consider those lines
+ a certain threshold for 'git blame' to consider those lines
of code to have been moved.
-f::
@@ -100,7 +100,7 @@ header elements later.
SPECIFYING RANGES
-----------------
-Unlike 'git-blame' and 'git-annotate' in older versions of git, the extent
+Unlike 'git blame' and 'git annotate' in older versions of git, the extent
of the annotation can be limited to both line ranges and revision
ranges. When you are interested in finding the origin for
lines 40-60 for file `foo`, you can use the `-L` option like so
@@ -118,7 +118,7 @@ which limits the annotation to the body of the `hello` subroutine.
When you are not interested in changes older than version
v2.6.18, or changes older than 3 weeks, you can use revision
-range specifiers similar to 'git-rev-list':
+range specifiers similar to 'git rev-list':
git blame v2.6.18.. -- foo
git blame --since=3.weeks -- foo
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index 0e83680..44144d5 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -38,7 +38,7 @@ working tree to it; use "git checkout <newbranch>" to switch to the
new branch.
When a local branch is started off a remote branch, git sets up the
-branch so that 'git-pull' will appropriately merge from
+branch so that 'git pull' will appropriately merge from
the remote branch. This behavior may be changed via the global
`branch.autosetupmerge` configuration flag. That setting can be
overridden by using the `--track` and `--no-track` options.
@@ -55,7 +55,7 @@ has a reflog then the reflog will also be deleted.
Use -r together with -d to delete remote-tracking branches. Note, that it
only makes sense to delete remote-tracking branches if they no longer exist
-in the remote repository or if 'git-fetch' was configured not to fetch
+in the remote repository or if 'git fetch' was configured not to fetch
them again. See also the 'prune' subcommand of linkgit:git-remote[1] for a
way to clean up all obsolete remote-tracking branches.
@@ -76,7 +76,7 @@ OPTIONS
-f::
--force::
Reset <branchname> to <startpoint> if <branchname> exists
- already. Without `-f` 'git-branch' refuses to change an existing branch.
+ already. Without `-f` 'git branch' refuses to change an existing branch.
-m::
Move/rename a branch and the corresponding reflog.
diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt
index c3a066e..a5ed8fb 100644
--- a/Documentation/git-bundle.txt
+++ b/Documentation/git-bundle.txt
@@ -21,9 +21,9 @@ Some workflows require that one or more branches of development on one
machine be replicated on another machine, but the two machines cannot
be directly connected, and therefore the interactive git protocols (git,
ssh, rsync, http) cannot be used. This command provides support for
-'git-fetch' and 'git-pull' to operate by packaging objects and references
+'git fetch' and 'git pull' to operate by packaging objects and references
in an archive at the originating machine, then importing those into
-another repository using 'git-fetch' and 'git-pull'
+another repository using 'git fetch' and 'git pull'
after moving the archive by some means (e.g., by sneakernet). As no
direct connection between the repositories exists, the user must specify a
basis for the bundle that is held by the destination repository: the
@@ -35,14 +35,14 @@ OPTIONS
create <file>::
Used to create a bundle named 'file'. This requires the
- 'git-rev-list' arguments to define the bundle contents.
+ 'git rev-list' arguments to define the bundle contents.
verify <file>::
Used to check that a bundle file is valid and will apply
cleanly to the current repository. This includes checks on the
bundle format itself as well as checking that the prerequisite
commits exist and are fully linked in the current repository.
- 'git-bundle' prints a list of missing commits, if any, and exits
+ 'git bundle' prints a list of missing commits, if any, and exits
with a non-zero status.
list-heads <file>::
@@ -51,15 +51,15 @@ list-heads <file>::
printed out.
unbundle <file>::
- Passes the objects in the bundle to 'git-index-pack'
+ Passes the objects in the bundle to 'git index-pack'
for storage in the repository, then prints the names of all
defined references. If a list of references is given, only
references matching those in the list are printed. This command is
- really plumbing, intended to be called only by 'git-fetch'.
+ really plumbing, intended to be called only by 'git fetch'.
[git-rev-list-args...]::
- A list of arguments, acceptable to 'git-rev-parse' and
- 'git-rev-list', that specifies the specific objects and references
+ A list of arguments, acceptable to 'git rev-parse' and
+ 'git rev-list', that specifies the specific objects and references
to transport. For example, `master\~10..master` causes the
current master reference to be packaged along with all objects
added since its 10th ancestor commit. There is no explicit
@@ -69,16 +69,16 @@ unbundle <file>::
[refname...]::
A list of references used to limit the references reported as
- available. This is principally of use to 'git-fetch', which
+ available. This is principally of use to 'git fetch', which
expects to receive only those references asked for and not
- necessarily everything in the pack (in this case, 'git-bundle' acts
- like 'git-fetch-pack').
+ necessarily everything in the pack (in this case, 'git bundle' acts
+ like 'git fetch-pack').
SPECIFYING REFERENCES
---------------------
-'git-bundle' will only package references that are shown by
-'git-show-ref': this includes heads, tags, and remote heads. References
+'git bundle' will only package references that are shown by
+'git show-ref': this includes heads, tags, and remote heads. References
such as `master\~1` cannot be packaged, but are perfectly suitable for
defining the basis. More than one reference may be packaged, and more
than one basis can be specified. The objects packaged are those not
diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt
index 0aeef24..d9a3326 100644
--- a/Documentation/git-check-ref-format.txt
+++ b/Documentation/git-check-ref-format.txt
@@ -60,7 +60,7 @@ reference name expressions (see linkgit:git-rev-parse[1]):
. A colon `:` is used as in `srcref:dstref` to mean "use srcref\'s
value and store it in dstref" in fetch and push operations.
It may also be used to select a specific object such as with
- 'git-cat-file': "git cat-file blob v1.3.3:refs.c".
+ 'git cat-file': "git cat-file blob v1.3.3:refs.c".
. at-open-brace `@{` is used as a notation to access a reflog entry.
diff --git a/Documentation/git-checkout-index.txt b/Documentation/git-checkout-index.txt
index 62d8483..d6aa6e1 100644
--- a/Documentation/git-checkout-index.txt
+++ b/Documentation/git-checkout-index.txt
@@ -88,7 +88,7 @@ $ find . -name '*.h' -print0 | xargs -0 git checkout-index -f --
which will force all existing `*.h` files to be replaced with their
cached copies. If an empty command line implied "all", then this would
force-refresh everything in the index, which was not the point. But
-since 'git-checkout-index' accepts --stdin it would be faster to use:
+since 'git checkout-index' accepts --stdin it would be faster to use:
----------------
$ find . -name '*.h' -print0 | git checkout-index -f -z --stdin
@@ -102,7 +102,7 @@ Using `--` is probably a good policy in scripts.
Using --temp or --stage=all
---------------------------
When `--temp` is used (or implied by `--stage=all`)
-'git-checkout-index' will create a temporary file for each index
+'git checkout-index' will create a temporary file for each index
entry being checked out. The index will not be updated with stat
information. These options can be useful if the caller needs all
stages of all unmerged entries so that the unmerged files can be
@@ -147,9 +147,9 @@ To update and refresh only the files already checked out::
$ git checkout-index -n -f -a && git update-index --ignore-missing --refresh
----------------
-Using 'git-checkout-index' to "export an entire tree"::
+Using 'git checkout-index' to "export an entire tree"::
The prefix ability basically makes it trivial to use
- 'git-checkout-index' as an "export as tree" function.
+ 'git checkout-index' as an "export as tree" function.
Just read the desired tree into the index, and do:
+
----------------
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index b764130..78f4714 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -24,7 +24,7 @@ OPTIONS
-e::
--edit::
- With this option, 'git-cherry-pick' will let you edit the commit
+ With this option, 'git cherry-pick' will let you edit the commit
message prior to committing.
-x::
diff --git a/Documentation/git-cherry.txt b/Documentation/git-cherry.txt
index 7deefda..fed115a 100644
--- a/Documentation/git-cherry.txt
+++ b/Documentation/git-cherry.txt
@@ -14,7 +14,7 @@ DESCRIPTION
The changeset (or "diff") of each commit between the fork-point and <head>
is compared against each commit between the fork-point and <upstream>.
The commits are compared with their 'patch id', obtained from
-the 'git-patch-id' program.
+the 'git patch-id' program.
Every commit that doesn't exist in the <upstream> branch
has its id (sha1) reported, prefixed by a symbol. The ones that have
@@ -37,8 +37,8 @@ to and including <limit> are not reported:
\__*__*__<limit>__-__+__> <head>
-Because 'git-cherry' compares the changeset rather than the commit id
-(sha1), you can use 'git-cherry' to find out if a commit you made locally
+Because 'git cherry' compares the changeset rather than the commit id
+(sha1), you can use 'git cherry' to find out if a commit you made locally
has been applied <upstream> under a different commit id. For example,
this will happen if you're feeding patches <upstream> via email rather
than pushing or pulling commits directly.
diff --git a/Documentation/git-citool.txt b/Documentation/git-citool.txt
index 670cb02..fb2753c 100644
--- a/Documentation/git-citool.txt
+++ b/Documentation/git-citool.txt
@@ -14,9 +14,9 @@ DESCRIPTION
A Tcl/Tk based graphical interface to review modified files, stage
them into the index, enter a commit message and record the new
commit onto the current branch. This interface is an alternative
-to the less interactive 'git-commit' program.
+to the less interactive 'git commit' program.
-'git-citool' is actually a standard alias for `git gui citool`.
+'git citool' is actually a standard alias for `git gui citool`.
See linkgit:git-gui[1] for more details.
Author
diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index 9d291bd..335c885 100644
--- a/Documentation/git-clean.txt
+++ b/Documentation/git-clean.txt
@@ -34,7 +34,7 @@ OPTIONS
-f::
--force::
If the git configuration specifies clean.requireForce as true,
- 'git-clean' will refuse to run unless given -f or -n.
+ 'git clean' will refuse to run unless given -f or -n.
-n::
--dry-run::
@@ -48,7 +48,7 @@ OPTIONS
-x::
Don't use the ignore rules. This allows removing all untracked
files, including build products. This can be used (possibly in
- conjunction with 'git-reset') to create a pristine
+ conjunction with 'git reset') to create a pristine
working directory to test a clean build.
-X::
diff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt
index 4fec5d5..6188854 100644
--- a/Documentation/git-commit-tree.txt
+++ b/Documentation/git-commit-tree.txt
@@ -70,7 +70,7 @@ is taken from the configuration items user.name and user.email, or, if not
present, system user name and fully qualified hostname.
A commit comment is read from stdin. If a changelog
-entry is not provided via "<" redirection, 'git-commit-tree' will just wait
+entry is not provided via "<" redirection, 'git commit-tree' will just wait
for one to be entered and terminated with ^D.
include::date-formats.txt[]
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index d3a2dec..e99bb14 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -21,11 +21,11 @@ with a log message from the user describing the changes.
The content to be added can be specified in several ways:
-1. by using 'git-add' to incrementally "add" changes to the
+1. by using 'git add' to incrementally "add" changes to the
index before using the 'commit' command (Note: even modified
files must be "added");
-2. by using 'git-rm' to remove files from the working tree
+2. by using 'git rm' to remove files from the working tree
and the index, again before using the 'commit' command;
3. by listing files as arguments to the 'commit' command, in which
@@ -41,14 +41,14 @@ The content to be added can be specified in several ways:
5. by using the --interactive switch with the 'commit' command to decide one
by one which files should be part of the commit, before finalizing the
- operation. Currently, this is done by invoking 'git-add --interactive'.
+ operation. Currently, this is done by invoking 'git add --interactive'.
The `--dry-run` option can be used to obtain a
summary of what is included by any of the above for the next
commit by giving the same set of parameters (options and paths).
If you make a commit and then find a mistake immediately after
-that, you can recover from it with 'git-reset'.
+that, you can recover from it with 'git reset'.
OPTIONS
@@ -185,7 +185,7 @@ FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].)
Make a commit only from the paths specified on the
command line, disregarding any contents that have been
staged so far. This is the default mode of operation of
- 'git-commit' if any paths are given on the command line,
+ 'git commit' if any paths are given on the command line,
in which case this option can be omitted.
If this option is specified together with '--amend', then
no paths need to be specified, which can be used to amend
@@ -253,10 +253,10 @@ EXAMPLES
--------
When recording your own work, the contents of modified files in
your working tree are temporarily stored to a staging area
-called the "index" with 'git-add'. A file can be
+called the "index" with 'git add'. A file can be
reverted back, only in the index but not in the working tree,
to that of the last commit with `git reset HEAD -- <file>`,
-which effectively reverts 'git-add' and prevents the changes to
+which effectively reverts 'git add' and prevents the changes to
this file from participating in the next commit. After building
the state to be committed incrementally with these commands,
`git commit` (without any pathname parameter) is used to record what
@@ -312,13 +312,13 @@ $ git commit
this second commit would record the changes to `hello.c` and
`hello.h` as expected.
-After a merge (initiated by 'git-merge' or 'git-pull') stops
+After a merge (initiated by 'git merge' or 'git pull') stops
because of conflicts, cleanly merged
paths are already staged to be committed for you, and paths that
conflicted are left in unmerged state. You would have to first
-check which paths are conflicting with 'git-status'
+check which paths are conflicting with 'git status'
and after fixing them manually in your working tree, you would
-stage the result as usual with 'git-add':
+stage the result as usual with 'git add':
------------
$ git status | grep unmerged
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 2632928..543dd64 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -38,7 +38,7 @@ you want to handle the lines that do *not* match the regex, just
prepend a single exclamation mark in front (see also <<EXAMPLES>>).
The type specifier can be either '--int' or '--bool', to make
-'git-config' ensure that the variable(s) are of the given type and
+'git config' ensure that the variable(s) are of the given type and
convert the value to the canonical form (simple decimal number for int,
a "true" or "false" string for bool), or '--path', which does some
path expansion (see '--path' below). If no type specifier is passed, no
@@ -125,16 +125,16 @@ See also <<FILES>>.
List all variables set in config file.
--bool::
- 'git-config' will ensure that the output is "true" or "false"
+ 'git config' will ensure that the output is "true" or "false"
--int::
- 'git-config' will ensure that the output is a simple
+ 'git config' will ensure that the output is a simple
decimal number. An optional value suffix of 'k', 'm', or 'g'
in the config file will cause the value to be multiplied
by 1024, 1048576, or 1073741824 prior to output.
--bool-or-int::
- 'git-config' will ensure that the output matches the format of
+ 'git config' will ensure that the output matches the format of
either --bool or --int, as described above.
--path::
@@ -181,7 +181,7 @@ FILES
-----
If not set explicitly with '--file', there are three files where
-'git-config' will search for configuration options:
+'git config' will search for configuration options:
$GIT_DIR/config::
Repository specific configuration file. (The filename is
@@ -198,12 +198,12 @@ $(prefix)/etc/gitconfig::
If no further options are given, all reading options will read all of these
files that are available. If the global or the system-wide configuration
file are not available they will be ignored. If the repository configuration
-file is not available or readable, 'git-config' will exit with a non-zero
+file is not available or readable, 'git config' will exit with a non-zero
error code. However, in neither case will an error message be issued.
All writing options will per default write to the repository specific
configuration file. Note that this also affects options like '--replace-all'
-and '--unset'. *'git-config' will only ever change one file at a time*.
+and '--unset'. *'git config' will only ever change one file at a time*.
You can override these rules either by command line options or by environment
variables. The '--global' and the '--system' options will limit the file used
diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt
index abaaf27..b2696ef 100644
--- a/Documentation/git-cvsexportcommit.txt
+++ b/Documentation/git-cvsexportcommit.txt
@@ -27,7 +27,7 @@ by default.
Supports file additions, removals, and commits that affect binary files.
-If the commit is a merge commit, you must tell 'git-cvsexportcommit' what
+If the commit is a merge commit, you must tell 'git cvsexportcommit' what
parent the changeset should be done against.
OPTIONS
diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt
index 614e769..ddfcb3d 100644
--- a/Documentation/git-cvsimport.txt
+++ b/Documentation/git-cvsimport.txt
@@ -28,9 +28,9 @@ At least version 2.1 is required.
Please see the section <<issues,ISSUES>> for further reference.
You should *never* do any work of your own on the branches that are
-created by 'git-cvsimport'. By default initial import will create and populate a
+created by 'git cvsimport'. By default initial import will create and populate a
"master" branch from the CVS repository's main branch which you're free
-to work with; after that, you need to 'git-merge' incremental imports, or
+to work with; after that, you need to 'git merge' incremental imports, or
any CVS branches, yourself. It is advisable to specify a named remote via
-r to separate and protect the incoming branches.
@@ -49,13 +49,13 @@ OPTIONS
-d <CVSROOT>::
The root of the CVS archive. May be local (a simple path) or remote;
currently, only the :local:, :ext: and :pserver: access methods
- are supported. If not given, 'git-cvsimport' will try to read it
+ are supported. If not given, 'git cvsimport' will try to read it
from `CVS/Root`. If no such file exists, it checks for the
`CVSROOT` environment variable.
<CVS_module>::
The CVS module you want to import. Relative to <CVSROOT>.
- If not given, 'git-cvsimport' tries to read it from
+ If not given, 'git cvsimport' tries to read it from
`CVS/Repository`.
-C <target-dir>::
@@ -65,14 +65,14 @@ OPTIONS
-r <remote>::
The git remote to import this CVS repository into.
Moves all CVS branches into remotes/<remote>/<branch>
- akin to the way 'git-clone' uses 'origin' by default.
+ akin to the way 'git clone' uses 'origin' by default.
-o <branch-for-HEAD>::
When no remote is specified (via -r) the 'HEAD' branch
from CVS is imported to the 'origin' branch within the git
repository, as 'HEAD' already has a special meaning for git.
When a remote is specified the 'HEAD' branch is named
- remotes/<remote>/master mirroring 'git-clone' behaviour.
+ remotes/<remote>/master mirroring 'git clone' behaviour.
Use this option if you want to import into a different
branch.
+
@@ -145,17 +145,17 @@ This option can be used several times to provide several detection regexes.
---------
+
-'git-cvsimport' will make it appear as those authors had
+'git cvsimport' will make it appear as those authors had
their GIT_AUTHOR_NAME and GIT_AUTHOR_EMAIL set properly
all along.
+
For convenience, this data is saved to `$GIT_DIR/cvs-authors`
each time the '-A' option is provided and read from that same
-file each time 'git-cvsimport' is run.
+file each time 'git cvsimport' is run.
+
It is not recommended to use this feature if you intend to
export changes back to CVS again later with
-'git-cvsexportcommit'.
+'git cvsexportcommit'.
-h::
Print a short usage message and exit.
diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index fbab295..dbb053e 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -22,7 +22,7 @@ cvspserver stream tcp nowait nobody /usr/bin/git-cvsserver git-cvsserver pserver
Usage:
[verse]
-'git cvsserver' [options] [pserver|server] [<directory> ...]
+'git-cvsserver' [options] [pserver|server] [<directory> ...]
OPTIONS
-------
@@ -206,7 +206,7 @@ them write access to the directory, too.
The database can not be reliably regenerated in a
consistent form after the branch it is tracking has changed.
Example: For merged branches, 'git-cvsserver' only tracks
-one branch of development, and after a 'git-merge' an
+one branch of development, and after a 'git merge' an
incrementally updated database may track a different branch
than a database regenerated from scratch, causing inconsistent
CVS revision numbers. `git-cvsserver` has no way of knowing which
@@ -309,7 +309,7 @@ To get a checkout with the Eclipse CVS client:
Protocol notes: If you are using anonymous access via pserver, just select that.
Those using SSH access should choose the 'ext' protocol, and configure 'ext'
access on the Preferences->Team->CVS->ExtConnection pane. Set CVS_SERVER to
-"'git cvsserver'". Note that password support is not good when using 'ext',
+"`git cvsserver`". Note that password support is not good when using 'ext',
you will definitely want to have SSH keys setup.
Alternatively, you can just use the non-standard extssh protocol that Eclipse
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index a85121c..01c9f8e 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -28,36 +28,36 @@ that service if it is enabled.
It verifies that the directory has the magic file "git-daemon-export-ok", and
it will refuse to export any git directory that hasn't explicitly been marked
for export this way (unless the '--export-all' parameter is specified). If you
-pass some directory paths as 'git-daemon' arguments, you can further restrict
+pass some directory paths as 'git daemon' arguments, you can further restrict
the offers to a whitelist comprising of those.
By default, only `upload-pack` service is enabled, which serves
-'git-fetch-pack' and 'git-ls-remote' clients, which are invoked
-from 'git-fetch', 'git-pull', and 'git-clone'.
+'git fetch-pack' and 'git ls-remote' clients, which are invoked
+from 'git fetch', 'git pull', and 'git clone'.
This is ideally suited for read-only updates, i.e., pulling from
git repositories.
-An `upload-archive` also exists to serve 'git-archive'.
+An `upload-archive` also exists to serve 'git archive'.
OPTIONS
-------
--strict-paths::
Match paths exactly (i.e. don't allow "/foo/repo" when the real path is
"/foo/repo.git" or "/foo/repo/.git") and don't do user-relative paths.
- 'git-daemon' will refuse to start when this option is enabled and no
+ 'git daemon' will refuse to start when this option is enabled and no
whitelist is specified.
--base-path=path::
Remap all the path requests as relative to the given path.
- This is sort of "GIT root" - if you run 'git-daemon' with
+ This is sort of "GIT root" - if you run 'git daemon' with
'--base-path=/srv/git' on example.com, then if you later try to pull
- 'git://example.com/hello.git', 'git-daemon' will interpret the path
+ 'git://example.com/hello.git', 'git daemon' will interpret the path
as '/srv/git/hello.git'.
--base-path-relaxed::
If --base-path is enabled and repo lookup fails, with this option
- 'git-daemon' will attempt to lookup without prefixing the base path.
+ 'git daemon' will attempt to lookup without prefixing the base path.
This is useful for switching to --base-path usage, while still
allowing the old paths.
@@ -143,7 +143,7 @@ OPTIONS
+
Giving these options is an error when used with `--inetd`; use
the facility of inet daemon to achieve the same before spawning
-'git-daemon' if needed.
+'git daemon' if needed.
--enable=service::
--disable=service::
@@ -169,24 +169,24 @@ SERVICES
These services can be globally enabled/disabled using the
command line options of this command. If a finer-grained
-control is desired (e.g. to allow 'git-archive' to be run
+control is desired (e.g. to allow 'git archive' to be run
against only in a few selected repositories the daemon serves),
the per-repository configuration file can be used to enable or
disable them.
upload-pack::
- This serves 'git-fetch-pack' and 'git-ls-remote'
+ This serves 'git fetch-pack' and 'git ls-remote'
clients. It is enabled by default, but a repository can
disable it by setting `daemon.uploadpack` configuration
item to `false`.
upload-archive::
- This serves 'git-archive --remote'. It is disabled by
+ This serves 'git archive --remote'. It is disabled by
default, but a repository can enable it by setting
`daemon.uploadarch` configuration item to `true`.
receive-pack::
- This serves 'git-send-pack' clients, allowing anonymous
+ This serves 'git send-pack' clients, allowing anonymous
push. It is disabled by default, as there is _no_
authentication in the protocol (in other words, anybody
can push anything into the repository, including removal
@@ -204,8 +204,8 @@ $ grep 9418 /etc/services
git 9418/tcp # Git Version Control System
------------
-'git-daemon' as inetd server::
- To set up 'git-daemon' as an inetd service that handles any
+'git daemon' as inetd server::
+ To set up 'git daemon' as an inetd service that handles any
repository under the whitelisted set of directories, /pub/foo
and /pub/bar, place an entry like the following into
/etc/inetd all on one line:
@@ -217,8 +217,8 @@ git 9418/tcp # Git Version Control System
------------------------------------------------
-'git-daemon' as inetd server for virtual hosts::
- To set up 'git-daemon' as an inetd service that handles
+'git daemon' as inetd server for virtual hosts::
+ To set up 'git daemon' as an inetd service that handles
repositories for different virtual hosts, `www.example.com`
and `www.example.org`, place an entry like the following into
`/etc/inetd` all on one line:
@@ -240,8 +240,8 @@ clients, a symlink from `/software` into the appropriate
default repository could be made as well.
-'git-daemon' as regular daemon for virtual hosts::
- To set up 'git-daemon' as a regular, non-inetd service that
+'git daemon' as regular daemon for virtual hosts::
+ To set up 'git daemon' as a regular, non-inetd service that
handles repositories for multiple virtual hosts based on
their IP addresses, start the daemon like this:
+
@@ -258,7 +258,7 @@ Repositories can still be accessed by hostname though, assuming
they correspond to these IP addresses.
selectively enable/disable services per repository::
- To enable 'git-archive --remote' and disable 'git-fetch' against
+ To enable 'git archive --remote' and disable 'git fetch' against
a repository, have the following in the configuration file in the
repository (that is the file 'config' next to 'HEAD', 'refs' and
'objects').
@@ -272,7 +272,7 @@ selectively enable/disable services per repository::
ENVIRONMENT
-----------
-'git-daemon' will set REMOTE_ADDR to the IP address of the client
+'git daemon' will set REMOTE_ADDR to the IP address of the client
that connected to it, if the IP address is available. REMOTE_ADDR will
be available in the environment of hooks called when
services are performed.
diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
index 78b9808..6fc5323 100644
--- a/Documentation/git-describe.txt
+++ b/Documentation/git-describe.txt
@@ -106,7 +106,7 @@ of commits which would be displayed by "git log v1.0.4..parent".
The hash suffix is "-g" + 7-char abbreviation for the tip commit
of parent (which was `2414721b194453f058079d897d13c4e377f92dc6`).
-Doing a 'git-describe' on a tag-name will just show the tag name:
+Doing a 'git describe' on a tag-name will just show the tag name:
[torvalds@g5 git]$ git describe v1.0.4
v1.0.4
@@ -136,13 +136,13 @@ be sufficient to disambiguate these commits.
SEARCH STRATEGY
---------------
-For each committish supplied, 'git-describe' will first look for
+For each committish supplied, 'git describe' will first look for
a tag which tags exactly that commit. Annotated tags will always
be preferred over lightweight tags, and tags with newer dates will
always be preferred over tags with older dates. If an exact match
is found, its name will be output and searching will stop.
-If an exact match was not found, 'git-describe' will walk back
+If an exact match was not found, 'git describe' will walk back
through the commit history to locate an ancestor commit which
has been tagged. The ancestor's tag will be output along with an
abbreviation of the input committish's SHA1.
diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.txt
index 4ef0357..9cd8cce 100644
--- a/Documentation/git-diff-files.txt
+++ b/Documentation/git-diff-files.txt
@@ -15,7 +15,7 @@ DESCRIPTION
Compares the files in the working tree and the index. When paths
are specified, compares only those named paths. Otherwise all
entries in the index are compared. The output format is the
-same as for 'git-diff-index' and 'git-diff-tree'.
+same as for 'git diff-index' and 'git diff-tree'.
OPTIONS
-------
diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.txt
index 8b9ed29..162cb74 100644
--- a/Documentation/git-diff-index.txt
+++ b/Documentation/git-diff-index.txt
@@ -31,7 +31,7 @@ include::diff-options.txt[]
-m::
By default, files recorded in the index but not checked
out are reported as deleted. This flag makes
- 'git-diff-index' say that all non-checked-out files are up
+ 'git diff-index' say that all non-checked-out files are up
to date.
include::diff-format.txt[]
@@ -48,7 +48,7 @@ Cached Mode
If '--cached' is specified, it allows you to ask:
show me the differences between HEAD and the current index
- contents (the ones I'd write using 'git-write-tree')
+ contents (the ones I'd write using 'git write-tree')
For example, let's say that you have worked on your working directory, updated
some files in the index and are ready to commit. You want to see exactly
@@ -60,7 +60,7 @@ object and compare it that way, and to do that, you just do
Example: let's say I had renamed `commit.c` to `git-commit.c`, and I had
done an `update-index` to make that effective in the index file.
`git diff-files` wouldn't show anything at all, since the index file
-matches my working directory. But doing a 'git-diff-index' does:
+matches my working directory. But doing a 'git diff-index' does:
torvalds@ppc970:~/git> git diff-index --cached HEAD
-100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 commit.c
@@ -69,10 +69,10 @@ matches my working directory. But doing a 'git-diff-index' does:
You can see easily that the above is a rename.
In fact, `git diff-index --cached` *should* always be entirely equivalent to
-actually doing a 'git-write-tree' and comparing that. Except this one is much
+actually doing a 'git write-tree' and comparing that. Except this one is much
nicer for the case where you just want to check where you are.
-So doing a 'git-diff-index --cached' is basically very useful when you are
+So doing a `git diff-index --cached` is basically very useful when you are
asking yourself "what have I already marked for being committed, and
what's the difference to a previous tree".
@@ -80,20 +80,20 @@ Non-cached Mode
---------------
The "non-cached" mode takes a different approach, and is potentially
the more useful of the two in that what it does can't be emulated with
-a 'git-write-tree' + 'git-diff-tree'. Thus that's the default mode.
+a 'git write-tree' + 'git diff-tree'. Thus that's the default mode.
The non-cached version asks the question:
show me the differences between HEAD and the currently checked out
tree - index contents _and_ files that aren't up-to-date
which is obviously a very useful question too, since that tells you what
-you *could* commit. Again, the output matches the 'git-diff-tree -r'
+you *could* commit. Again, the output matches the 'git diff-tree -r'
output to a tee, but with a twist.
The twist is that if some file doesn't match the index, we don't have
a backing store thing for it, and we use the magic "all-zero" sha1 to
show that. So let's say that you have edited `kernel/sched.c`, but
-have not actually done a 'git-update-index' on it yet - there is no
+have not actually done a 'git update-index' on it yet - there is no
"object" associated with the new state, and you get:
torvalds@ppc970:~/v2.6/linux> git diff-index HEAD
@@ -104,11 +104,11 @@ not up-to-date and may contain new stuff. The all-zero sha1 means that to
get the real diff, you need to look at the object in the working directory
directly rather than do an object-to-object diff.
-NOTE: As with other commands of this type, 'git-diff-index' does not
+NOTE: As with other commands of this type, 'git diff-index' does not
actually look at the contents of the file at all. So maybe
`kernel/sched.c` hasn't actually changed, and it's just that you
touched it. In either case, it's a note that you need to
-'git-update-index' it to make the index be in sync.
+'git update-index' it to make the index be in sync.
NOTE: You can have a mixture of files show up as "has been updated"
and "is still dirty in the working directory" together. You can always
diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
index f2cef12..a7e37b8 100644
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -20,7 +20,7 @@ Compares the content and mode of the blobs found via two tree objects.
If there is only one <tree-ish> given, the commit is compared with its parents
(see --stdin below).
-Note that 'git-diff-tree' can use the tree encapsulated in a commit object.
+Note that 'git diff-tree' can use the tree encapsulated in a commit object.
OPTIONS
-------
@@ -67,25 +67,25 @@ The following flags further affect the behavior when comparing
commits (but not trees).
-m::
- By default, 'git-diff-tree --stdin' does not show
+ By default, 'git diff-tree --stdin' does not show
differences for merge commits. With this flag, it shows
differences to that commit from all of its parents. See
also '-c'.
-s::
- By default, 'git-diff-tree --stdin' shows differences,
+ By default, 'git diff-tree --stdin' shows differences,
either in machine-readable form (without '-p') or in patch
form (with '-p'). This output can be suppressed. It is
only useful with '-v' flag.
-v::
- This flag causes 'git-diff-tree --stdin' to also show
+ This flag causes 'git diff-tree --stdin' to also show
the commit message before the differences.
include::pretty-options.txt[]
--no-commit-id::
- 'git-diff-tree' outputs a line with the commit ID when
+ 'git diff-tree' outputs a line with the commit ID when
applicable. This flag suppressed the commit ID output.
-c::
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index 0ac7112..723a648 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -157,6 +157,10 @@ $ git diff -R <2>
rewrites (very expensive).
<2> Output diff in reverse.
+SEE ALSO
+--------
+linkgit:git-difftool[1]::
+ Show changes using common diff tools
Author
------
diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt
index 8e9aed6..8250bad 100644
--- a/Documentation/git-difftool.txt
+++ b/Documentation/git-difftool.txt
@@ -7,13 +7,13 @@ git-difftool - Show changes using common diff tools
SYNOPSIS
--------
-'git difftool' [--tool=<tool>] [-y|--no-prompt|--prompt] [<'git diff' options>]
+'git difftool' [<options>] <commit>{0,2} [--] [<path>...]
DESCRIPTION
-----------
-'git-difftool' is a git command that allows you to compare and edit files
+'git difftool' is a git command that allows you to compare and edit files
between revisions using common diff tools. 'git difftool' is a frontend
-to 'git-diff' and accepts the same options and arguments.
+to 'git diff' and accepts the same options and arguments.
OPTIONS
-------
@@ -33,23 +33,23 @@ OPTIONS
kdiff3, kompare, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff,
ecmerge, diffuse, opendiff, p4merge and araxis.
+
-If a diff tool is not specified, 'git-difftool'
+If a diff tool is not specified, 'git difftool'
will use the configuration variable `diff.tool`. If the
-configuration variable `diff.tool` is not set, 'git-difftool'
+configuration variable `diff.tool` is not set, 'git difftool'
will pick a suitable default.
+
You can explicitly provide a full path to the tool by setting the
configuration variable `difftool.<tool>.path`. For example, you
can configure the absolute path to kdiff3 by setting
-`difftool.kdiff3.path`. Otherwise, 'git-difftool' assumes the
+`difftool.kdiff3.path`. Otherwise, 'git difftool' assumes the
tool is available in PATH.
+
Instead of running one of the known diff tools,
-'git-difftool' can be customized to run an alternative program
+'git difftool' can be customized to run an alternative program
by specifying the command line to invoke in a configuration
variable `difftool.<tool>.cmd`.
+
-When 'git-difftool' is invoked with this tool (either through the
+When 'git difftool' is invoked with this tool (either through the
`-t` or `--tool` option or the `diff.tool` configuration variable)
the configured command line will be invoked with the following
variables available: `$LOCAL` is set to the name of the temporary
@@ -58,16 +58,31 @@ is set to the name of the temporary file containing the contents
of the diff post-image. `$BASE` is provided for compatibility
with custom merge tool commands and has the same value as `$LOCAL`.
+-x <command>::
+--extcmd=<command>::
+ Specify a custom command for viewing diffs.
+ 'git-difftool' ignores the configured defaults and runs
+ `$command $LOCAL $REMOTE` when this option is specified.
+
+-g::
+--gui::
+ When 'git-difftool' is invoked with the `-g` or `--gui` option
+ the default diff tool will be read from the configured
+ `diff.guitool` variable instead of `diff.tool`.
+
See linkgit:git-diff[1] for the full list of supported options.
CONFIG VARIABLES
----------------
-'git-difftool' falls back to 'git-mergetool' config variables when the
+'git difftool' falls back to 'git mergetool' config variables when the
difftool equivalents have not been defined.
diff.tool::
The default diff tool to use.
+diff.guitool::
+ The default diff tool to use when `--gui` is specified.
+
difftool.<tool>.path::
Override the path for the given tool. This is useful in case
your tool is not in the PATH.
diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt
index 75b06f3..c24e14b 100644
--- a/Documentation/git-fast-export.txt
+++ b/Documentation/git-fast-export.txt
@@ -13,18 +13,18 @@ SYNOPSIS
DESCRIPTION
-----------
This program dumps the given revisions in a form suitable to be piped
-into 'git-fast-import'.
+into 'git fast-import'.
You can use it as a human-readable bundle replacement (see
linkgit:git-bundle[1]), or as a kind of an interactive
-'git-filter-branch'.
+'git filter-branch'.
OPTIONS
-------
--progress=<n>::
Insert 'progress' statements every <n> objects, to be shown by
- 'git-fast-import' during import.
+ 'git fast-import' during import.
--signed-tags=(verbatim|warn|strip|abort)::
Specify how to handle signed tags. Since any transformation
@@ -91,8 +91,8 @@ marks the same across runs.
already contains the necessary objects.
[git-rev-list-args...]::
- A list of arguments, acceptable to 'git-rev-parse' and
- 'git-rev-list', that specifies the specific objects and references
+ A list of arguments, acceptable to 'git rev-parse' and
+ 'git rev-list', that specifies the specific objects and references
to export. For example, `master\~10..master` causes the
current master reference to be exported along with all objects
added since its 10th ancestor commit.
@@ -125,7 +125,7 @@ referenced by that revision range contains the string
Limitations
-----------
-Since 'git-fast-import' cannot tag trees, you will not be
+Since 'git fast-import' cannot tag trees, you will not be
able to export the linux-2.6.git repository completely, as it contains
a tag referencing a tree instead of a commit.
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index ae87f09..ff4022c 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -15,7 +15,7 @@ DESCRIPTION
This program is usually not what the end user wants to run directly.
Most end users want to use one of the existing frontend programs,
which parses a specific type of foreign source and feeds the contents
-stored there to 'git-fast-import'.
+stored there to 'git fast-import'.
fast-import reads a mixed command/data stream from standard input and
writes one or more packfiles directly into the current repository.
@@ -24,7 +24,7 @@ updated branch and tag refs, fully updating the current repository
with the newly imported data.
The fast-import backend itself can import into an empty repository (one that
-has already been initialized by 'git-init') or incrementally
+has already been initialized by 'git init') or incrementally
update an existing populated repository. Whether or not incremental
imports are supported from a particular foreign source depends on
the frontend program in use.
@@ -96,7 +96,7 @@ OPTIONS
This information may be useful after importing projects
whose total object set exceeds the 4 GiB packfile limit,
as these commits can be used as edge points during calls
- to 'git-pack-objects'.
+ to 'git pack-objects'.
--quiet::
Disable all non-fatal output, making fast-import silent when it
@@ -138,9 +138,9 @@ an ideal situation, given that most conversion tools are throw-away
Parallel Operation
------------------
-Like 'git-push' or 'git-fetch', imports handled by fast-import are safe to
+Like 'git push' or 'git fetch', imports handled by fast-import are safe to
run alongside parallel `git repack -a -d` or `git gc` invocations,
-or any other Git operation (including 'git-prune', as loose objects
+or any other Git operation (including 'git prune', as loose objects
are never used by fast-import).
fast-import does not lock the branch or tag refs it is actively importing.
@@ -234,7 +234,7 @@ variation in formatting will cause fast-import to reject the value.
+
An example value is ``Tue Feb 6 11:22:18 2007 -0500''. The Git
parser is accurate, but a little on the lenient side. It is the
-same parser used by 'git-am' when applying patches
+same parser used by 'git am' when applying patches
received from email.
+
Some malformed strings may be accepted as valid dates. In some of
@@ -270,7 +270,7 @@ timezone.
This particular format is supplied as its short to implement and
may be useful to a process that wants to create a new commit
right now, without needing to use a working directory or
-'git-update-index'.
+'git update-index'.
+
If separate `author` and `committer` commands are used in a `commit`
the timestamps may not match, as the system clock will be polled
@@ -713,7 +713,7 @@ recommended, as the frontend does not (easily) have access to the
complete set of bytes which normally goes into such a signature.
If signing is required, create lightweight tags from within fast-import with
`reset`, then create the annotated versions of those tags offline
-with the standard 'git-tag' process.
+with the standard 'git tag' process.
`reset`
~~~~~~~
@@ -1070,7 +1070,7 @@ is not `refs/heads/TAG_FIXUP`).
When committing fixups, consider using `merge` to connect the
commit(s) which are supplying file revisions to the fixup branch.
-Doing so will allow tools such as 'git-blame' to track
+Doing so will allow tools such as 'git blame' to track
through the real commit history and properly annotate the source
files.
@@ -1099,7 +1099,7 @@ Repacking Historical Data
~~~~~~~~~~~~~~~~~~~~~~~~~
If you are repacking very old imported data (e.g. older than the
last year), consider expending some extra CPU time and supplying
-\--window=50 (or higher) when you run 'git-repack'.
+\--window=50 (or higher) when you run 'git repack'.
This will take longer, but will also produce a smaller packfile.
You only need to expend the effort once, and everyone using your
project will benefit from the smaller repository.
diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt
index 47448da..e9952e8 100644
--- a/Documentation/git-fetch-pack.txt
+++ b/Documentation/git-fetch-pack.txt
@@ -12,7 +12,7 @@ SYNOPSIS
DESCRIPTION
-----------
-Usually you would want to use 'git-fetch', which is a
+Usually you would want to use 'git fetch', which is a
higher level wrapper of this command, instead.
Invokes 'git-upload-pack' on a possibly remote repository
@@ -33,12 +33,12 @@ OPTIONS
-q::
--quiet::
- Pass '-q' flag to 'git-unpack-objects'; this makes the
+ Pass '-q' flag to 'git unpack-objects'; this makes the
cloning process less verbose.
-k::
--keep::
- Do not invoke 'git-unpack-objects' on received data, but
+ Do not invoke 'git unpack-objects' on received data, but
create a single packfile out of it instead, and store it
in the object database. If provided twice then the pack is
locked against repacking.
diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt
index 9b9e568..948ea26 100644
--- a/Documentation/git-fetch.txt
+++ b/Documentation/git-fetch.txt
@@ -24,7 +24,7 @@ along with the objects necessary to complete them.
The ref names and their object names of fetched refs are stored
in `.git/FETCH_HEAD`. This information is left for a later merge
-operation done by 'git-merge'.
+operation done by 'git merge'.
When <refspec> stores the fetched result in tracking branches,
the tags that point at these branches are automatically
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index 394a77a..cfaba2a 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -116,7 +116,7 @@ OPTIONS
--commit-filter <command>::
This is the filter for performing the commit.
If this filter is specified, it will be called instead of the
- 'git-commit-tree' command, with arguments of the form
+ 'git commit-tree' command, with arguments of the form
"<TREE_ID> [-p <PARENT_COMMIT_ID>]..." and the log message on
stdin. The commit id is expected on stdout.
+
@@ -127,10 +127,10 @@ have all of them as parents.
You can use the 'map' convenience function in this filter, and other
convenience functions, too. For example, calling 'skip_commit "$@"'
will leave out the current commit (but not its changes! If you want
-that, use 'git-rebase' instead).
+that, use 'git rebase' instead).
+
-You can also use the 'git_commit_non_empty_tree "$@"' instead of
-'git commit-tree "$@"' if you don't wish to keep commits with a single parent
+You can also use the `git_commit_non_empty_tree "$@"` instead of
+`git commit-tree "$@"` if you don't wish to keep commits with a single parent
and that makes no change to the tree.
--tag-name-filter <command>::
@@ -179,7 +179,7 @@ the nearest ancestor that was not excluded.
and only one parent, it will hence keep merges points. Also, this
option is not compatible with the use of '--commit-filter'. Though you
just need to use the function 'git_commit_non_empty_tree "$@"' instead
- of the 'git commit-tree "$@"' idiom in your commit filter to make that
+ of the `git commit-tree "$@"` idiom in your commit filter to make that
happen.
--original <namespace>::
@@ -196,15 +196,15 @@ the nearest ancestor that was not excluded.
-f::
--force::
- 'git-filter-branch' refuses to start with an existing temporary
+ 'git filter-branch' refuses to start with an existing temporary
directory or when there are already refs starting with
'refs/original/', unless forced.
<rev-list options>...::
- Arguments for 'git-rev-list'. All positive refs included by
+ Arguments for 'git rev-list'. All positive refs included by
these options are rewritten. You may also specify options
such as '--all', but you must use '--' to separate them from
- the 'git-filter-branch' options.
+ the 'git filter-branch' options.
Examples
@@ -221,7 +221,7 @@ However, if the file is absent from the tree of some commit,
a simple `rm filename` will fail for that tree and commit.
Thus you may instead want to use `rm -f filename` as the script.
-Using `\--index-filter` with 'git-rm' yields a significantly faster
+Using `\--index-filter` with 'git rm' yields a significantly faster
version. Like with using `rm filename`, `git rm --cached filename`
will fail if the file is absent from the tree of a commit. If you
want to "completely forget" a file, it does not matter when it entered
@@ -303,7 +303,7 @@ and all children of the merge will become merge commits with P1,P2
as their parents instead of the merge commit.
You can rewrite the commit log messages using `--msg-filter`. For
-example, 'git-svn-id' strings in a repository created by 'git-svn' can
+example, 'git svn-id' strings in a repository created by 'git svn' can
be removed this way:
-------------------------------------------------------
@@ -314,7 +314,7 @@ git filter-branch --msg-filter '
To restrict rewriting to only part of the history, specify a revision
range in addition to the new branch name. The new branch name will
-point to the top-most revision that a 'git-rev-list' of this range
+point to the top-most revision that a 'git rev-list' of this range
will print.
If you need to add 'Acked-by' lines to, say, the last 10 commits (none
@@ -330,7 +330,7 @@ git filter-branch --msg-filter '
*NOTE* the changes introduced by the commits, and which are not reverted
by subsequent commits, will still be in the rewritten branch. If you want
to throw out _changes_ together with the commits, you should use the
-interactive mode of 'git-rebase'.
+interactive mode of 'git rebase'.
Consider this history:
diff --git a/Documentation/git-fmt-merge-msg.txt b/Documentation/git-fmt-merge-msg.txt
index a586950..a585dbe 100644
--- a/Documentation/git-fmt-merge-msg.txt
+++ b/Documentation/git-fmt-merge-msg.txt
@@ -16,7 +16,7 @@ DESCRIPTION
-----------
Takes the list of merged objects on stdin and produces a suitable
commit message to be used for the merge commit, usually to be
-passed as the '<merge-message>' argument of 'git-merge'.
+passed as the '<merge-message>' argument of 'git merge'.
This command is intended mostly for internal use by scripts
automatically invoking 'git merge'.
diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt
index 8dc873f..7e83288 100644
--- a/Documentation/git-for-each-ref.txt
+++ b/Documentation/git-for-each-ref.txt
@@ -82,7 +82,7 @@ objecttype::
The type of the object (`blob`, `tree`, `commit`, `tag`).
objectsize::
- The size of the object (the same as 'git-cat-file -s' reports).
+ The size of the object (the same as 'git cat-file -s' reports).
objectname::
The object name (aka SHA-1).
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index f1fd0df..9674f9d 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -29,7 +29,7 @@ DESCRIPTION
Prepare each commit with its patch in
one file per commit, formatted to resemble UNIX mailbox format.
The output of this command is convenient for e-mail submission or
-for use with 'git-am'.
+for use with 'git am'.
There are two ways to specify which commits to operate on.
@@ -221,7 +221,7 @@ EXAMPLES
--------
* Extract commits between revisions R1 and R2, and apply them on top of
-the current branch using 'git-am' to cherry-pick them:
+the current branch using 'git am' to cherry-pick them:
+
------------
$ git format-patch -k --stdout R1..R2 | git am -3 -k
diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt
index 6fe9484..3ad48a6 100644
--- a/Documentation/git-fsck.txt
+++ b/Documentation/git-fsck.txt
@@ -21,7 +21,7 @@ OPTIONS
<object>::
An object to treat as the head of an unreachability trace.
+
-If no objects are given, 'git-fsck' defaults to using the
+If no objects are given, 'git fsck' defaults to using the
index file, all SHA1 references in .git/refs/*, and all reflogs (unless
--no-reflogs is given) as heads.
@@ -85,7 +85,7 @@ So for example
will do quite a _lot_ of verification on the tree. There are a few
extra validity tests to be added (make sure that tree objects are
-sorted properly etc), but on the whole if 'git-fsck' is happy, you
+sorted properly etc), but on the whole if 'git fsck' is happy, you
do have a valid tree.
Any corrupt objects you will have to find in backups or other archives
diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt
index 4cd9cdf..189573a 100644
--- a/Documentation/git-gc.txt
+++ b/Documentation/git-gc.txt
@@ -15,13 +15,13 @@ DESCRIPTION
Runs a number of housekeeping tasks within the current repository,
such as compressing file revisions (to reduce disk space and increase
performance) and removing unreachable objects which may have been
-created from prior invocations of 'git-add'.
+created from prior invocations of 'git add'.
Users are encouraged to run this task on a regular basis within
each repository to maintain good disk space utilization and good
operating performance.
-Some git commands may automatically run 'git-gc'; see the `--auto` flag
+Some git commands may automatically run 'git gc'; see the `--auto` flag
below for details. If you know what you're doing and all you want is to
disable this behavior permanently without further considerations, just do:
@@ -33,15 +33,15 @@ OPTIONS
-------
--aggressive::
- Usually 'git-gc' runs very quickly while providing good disk
+ Usually 'git gc' runs very quickly while providing good disk
space utilization and performance. This option will cause
- 'git-gc' to more aggressively optimize the repository at the expense
+ 'git gc' to more aggressively optimize the repository at the expense
of taking much more time. The effects of this optimization are
persistent, so this option only needs to be used occasionally; every
few hundred changesets or so.
--auto::
- With this option, 'git-gc' checks whether any housekeeping is
+ With this option, 'git gc' checks whether any housekeeping is
required; if not, it exits without performing any work.
Some git commands run `git gc --auto` after performing
operations that could create many loose objects.
@@ -50,13 +50,13 @@ Housekeeping is required if there are too many loose objects or
too many packs in the repository. If the number of loose objects
exceeds the value of the `gc.auto` configuration variable, then
all loose objects are combined into a single pack using
-'git-repack -d -l'. Setting the value of `gc.auto` to 0
+`git repack -d -l`. Setting the value of `gc.auto` to 0
disables automatic packing of loose objects.
+
If the number of packs exceeds the value of `gc.autopacklimit`,
then existing packs (except those marked with a `.keep` file)
are consolidated into a single pack by using the `-A` option of
-'git-repack'. Setting `gc.autopacklimit` to 0 disables
+'git repack'. Setting `gc.autopacklimit` to 0 disables
automatic consolidation of packs.
--prune=<date>::
@@ -97,7 +97,7 @@ how long records of conflicted merge you have not resolved are
kept. This defaults to 15 days.
The optional configuration variable 'gc.packrefs' determines if
-'git-gc' runs 'git-pack-refs'. This can be set to "nobare" to enable
+'git gc' runs 'git pack-refs'. This can be set to "nobare" to enable
it within all non-bare repos or it can be set to a boolean value.
This defaults to true.
@@ -116,10 +116,10 @@ default is "2 weeks ago".
Notes
-----
-'git-gc' tries very hard to be safe about the garbage it collects. In
+'git gc' tries very hard to be safe about the garbage it collects. In
particular, it will keep not only objects referenced by your current set
of branches and tags, but also objects referenced by the index, remote
-tracking branches, refs saved by 'git-filter-branch' in
+tracking branches, refs saved by 'git filter-branch' in
refs/original/, or reflogs (which may reference commits in branches
that were later amended or rewound).
diff --git a/Documentation/git-get-tar-commit-id.txt b/Documentation/git-get-tar-commit-id.txt
index 84f23ee..790af95 100644
--- a/Documentation/git-get-tar-commit-id.txt
+++ b/Documentation/git-get-tar-commit-id.txt
@@ -14,12 +14,12 @@ SYNOPSIS
DESCRIPTION
-----------
Acts as a filter, extracting the commit ID stored in archives created by
-'git-archive'. It reads only the first 1024 bytes of input, thus its
+'git archive'. It reads only the first 1024 bytes of input, thus its
runtime is not influenced by the size of <tarfile> very much.
-If no commit ID is found, 'git-get-tar-commit-id' quietly exists with a
+If no commit ID is found, 'git get-tar-commit-id' quietly exists with a
return code of 1. This can happen if <tarfile> had not been created
-using 'git-archive' or if the first parameter of 'git-archive' had been
+using 'git archive' or if the first parameter of 'git archive' had been
a tree ID instead of a commit ID or tag.
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index 8c70020..abb6735 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -98,7 +98,7 @@ OPTIONS
--files-without-match::
Instead of showing every matched line, show only the
names of files that contain (or do not contain) matches.
- For better compatibility with 'git-diff', --name-only is a
+ For better compatibility with 'git diff', --name-only is a
synonym for --files-with-matches.
-z::
diff --git a/Documentation/git-gui.txt b/Documentation/git-gui.txt
index d0bc98b..2563710 100644
--- a/Documentation/git-gui.txt
+++ b/Documentation/git-gui.txt
@@ -11,19 +11,19 @@ SYNOPSIS
DESCRIPTION
-----------
-A Tcl/Tk based graphical user interface to Git. 'git-gui' focuses
+A Tcl/Tk based graphical user interface to Git. 'git gui' focuses
on allowing users to make changes to their repository by making
new commits, amending existing ones, creating branches, performing
local merges, and fetching/pushing to remote repositories.
-Unlike 'gitk', 'git-gui' focuses on commit generation
+Unlike 'gitk', 'git gui' focuses on commit generation
and single file annotation and does not show project history.
It does however supply menu actions to start a 'gitk' session from
-within 'git-gui'.
+within 'git gui'.
-'git-gui' is known to work on all popular UNIX systems, Mac OS X,
+'git gui' is known to work on all popular UNIX systems, Mac OS X,
and Windows (under both Cygwin and MSYS). To the extent possible
-OS specific user interface guidelines are followed, making 'git-gui'
+OS specific user interface guidelines are followed, making 'git gui'
a fairly native interface for users.
COMMANDS
@@ -38,13 +38,13 @@ browser::
browser are opened in the blame viewer.
citool::
- Start 'git-gui' and arrange to make exactly one commit before
+ Start 'git gui' and arrange to make exactly one commit before
exiting and returning to the shell. The interface is limited
to only commit actions, slightly reducing the application's
startup time and simplifying the menubar.
version::
- Display the currently running version of 'git-gui'.
+ Display the currently running version of 'git gui'.
Examples
@@ -103,15 +103,15 @@ SEE ALSO
linkgit:gitk[1]::
The git repository browser. Shows branches, commit history
and file differences. gitk is the utility started by
- 'git-gui''s Repository Visualize actions.
+ 'git gui''s Repository Visualize actions.
Other
-----
-'git-gui' is actually maintained as an independent project, but stable
+'git gui' is actually maintained as an independent project, but stable
versions are distributed as part of the Git suite for the convenience
of end users.
-A 'git-gui' development repository can be obtained from:
+A 'git gui' development repository can be obtained from:
git clone git://repo.or.cz/git-gui.git
diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt
index 0af40cf..479fce4 100644
--- a/Documentation/git-hash-object.txt
+++ b/Documentation/git-hash-object.txt
@@ -18,7 +18,7 @@ Computes the object ID value for an object with specified type
with the contents of the named file (which can be outside of the
work tree), and optionally writes the resulting object into the
object database. Reports its object ID to its standard output.
-This is used by 'git-cvsimport' to update the index
+This is used by 'git cvsimport' to update the index
without modifying files in the work tree. When <type> is not
specified, it defaults to "blob".
diff --git a/Documentation/git-help.txt b/Documentation/git-help.txt
index d9b9c34..f8df109 100644
--- a/Documentation/git-help.txt
+++ b/Documentation/git-help.txt
@@ -55,8 +55,8 @@ other display programs (see below).
+
The web browser can be specified using the configuration variable
'help.browser', or 'web.browser' if the former is not set. If none of
-these config variables is set, the 'git-web--browse' helper script
-(called by 'git-help') will pick a suitable default. See
+these config variables is set, the 'git web--browse' helper script
+(called by 'git help') will pick a suitable default. See
linkgit:git-web--browse[1] for more information about this.
CONFIGURATION VARIABLES
@@ -67,7 +67,7 @@ help.format
If no command line option is passed, the 'help.format' configuration
variable will be checked. The following values are supported for this
-variable; they make 'git-help' behave as their corresponding command
+variable; they make 'git help' behave as their corresponding command
line option:
* "man" corresponds to '-m|--man',
@@ -122,7 +122,7 @@ man.<tool>.path
You can explicitly provide a full path to your preferred man viewer by
setting the configuration variable 'man.<tool>.path'. For example, you
can configure the absolute path to konqueror by setting
-'man.konqueror.path'. Otherwise, 'git-help' assumes the tool is
+'man.konqueror.path'. Otherwise, 'git help' assumes the tool is
available in PATH.
man.<tool>.cmd
diff --git a/Documentation/git-http-backend.txt b/Documentation/git-http-backend.txt
index c8fe08a..07931c6 100644
--- a/Documentation/git-http-backend.txt
+++ b/Documentation/git-http-backend.txt
@@ -8,7 +8,7 @@ git-http-backend - Server side implementation of Git over HTTP
SYNOPSIS
--------
[verse]
-'git-http-backend'
+'git http-backend'
DESCRIPTION
-----------
@@ -24,10 +24,10 @@ that hasn't explicitly been marked for export this way (unless the
GIT_HTTP_EXPORT_ALL environmental variable is set).
By default, only the `upload-pack` service is enabled, which serves
-'git-fetch-pack' and 'git-ls-remote' clients, which are invoked from
-'git-fetch', 'git-pull', and 'git-clone'. If the client is authenticated,
-the `receive-pack` service is enabled, which serves 'git-send-pack'
-clients, which is invoked from 'git-push'.
+'git fetch-pack' and 'git ls-remote' clients, which are invoked from
+'git fetch', 'git pull', and 'git clone'. If the client is authenticated,
+the `receive-pack` service is enabled, which serves 'git send-pack'
+clients, which is invoked from 'git push'.
SERVICES
--------
@@ -43,12 +43,12 @@ http.getanyfile::
by setting this configuration item to `false`.
http.uploadpack::
- This serves 'git-fetch-pack' and 'git-ls-remote' clients.
+ This serves 'git fetch-pack' and 'git ls-remote' clients.
It is enabled by default, but a repository can disable it
by setting this configuration item to `false`.
http.receivepack::
- This serves 'git-send-pack' clients, allowing push. It is
+ This serves 'git send-pack' clients, allowing push. It is
disabled by default for anonymous users, and enabled by
default for users authenticated by the web server. It can be
disabled by setting this item to `false`, or enabled for all
@@ -56,11 +56,11 @@ http.receivepack::
URL TRANSLATION
---------------
-To determine the location of the repository on disk, 'git-http-backend'
+To determine the location of the repository on disk, 'git http-backend'
concatenates the environment variables PATH_INFO, which is set
automatically by the web server, and GIT_PROJECT_ROOT, which must be set
manually in the web server configuration. If GIT_PROJECT_ROOT is not
-set, 'git-http-backend' reads PATH_TRANSLATED, which is also set
+set, 'git http-backend' reads PATH_TRANSLATED, which is also set
automatically by the web server.
EXAMPLES
@@ -104,7 +104,7 @@ directive around the repository, or one of its parent directories:
----------------------------------------------------------------
+
To serve gitweb at the same url, use a ScriptAliasMatch to only
-those URLs that 'git-http-backend' can handle, and forward the
+those URLs that 'git http-backend' can handle, and forward the
rest to gitweb:
+
----------------------------------------------------------------
@@ -153,7 +153,7 @@ ScriptAlias /git/ /var/www/cgi-bin/gitweb.cgi/
ENVIRONMENT
-----------
-'git-http-backend' relies upon the CGI environment variables set
+'git http-backend' relies upon the CGI environment variables set
by the invoking web server, including:
* PATH_INFO (if GIT_PROJECT_ROOT is set, otherwise PATH_TRANSLATED)
diff --git a/Documentation/git-http-fetch.txt b/Documentation/git-http-fetch.txt
index e7c7961..d91cb7f 100644
--- a/Documentation/git-http-fetch.txt
+++ b/Documentation/git-http-fetch.txt
@@ -35,7 +35,7 @@ commit-id::
--stdin::
Instead of a commit id on the command line (which is not expected in this
- case), 'git-http-fetch' expects lines on stdin in the format
+ case), 'git http-fetch' expects lines on stdin in the format
<commit-id>['\t'<filename-as-in--w>]
diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt
index d016daf..57db955 100644
--- a/Documentation/git-imap-send.txt
+++ b/Documentation/git-imap-send.txt
@@ -13,7 +13,7 @@ SYNOPSIS
DESCRIPTION
-----------
-This command uploads a mailbox generated with 'git-format-patch'
+This command uploads a mailbox generated with 'git format-patch'
into an IMAP drafts folder. This allows patches to be sent as
other email is when using mail clients that cannot read mailbox
files directly.
diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt
index 4b5c743..65a301b 100644
--- a/Documentation/git-index-pack.txt
+++ b/Documentation/git-index-pack.txt
@@ -43,10 +43,10 @@ OPTIONS
a default name determined from the pack content. If
<pack-file> is not specified consider using --keep to
prevent a race condition between this process and
- 'git-repack'.
+ 'git repack'.
--fix-thin::
- It is possible for 'git-pack-objects' to build
+ It is possible for 'git pack-objects' to build
"thin" pack, which records objects in deltified form based on
objects not included in the pack to reduce network traffic.
Those objects are expected to be present on the receiving end
@@ -59,7 +59,7 @@ OPTIONS
Before moving the index into its final destination
create an empty .keep file for the associated pack file.
This option is usually necessary with --stdin to prevent a
- simultaneous 'git-repack' process from deleting
+ simultaneous 'git repack' process from deleting
the newly constructed pack and index before refs can be
updated to use objects contained in the pack.
@@ -86,7 +86,7 @@ Once the index has been created, the list of object names is sorted
and the SHA1 hash of that list is printed to stdout. If --stdin was
also used then this is prefixed by either "pack\t", or "keep\t" if a
new .keep file was successfully created. This is useful to remove a
-.keep file used as a lock to prevent the race with 'git-repack'
+.keep file used as a lock to prevent the race with 'git repack'
mentioned above.
diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt
index f081b24..7ee102d 100644
--- a/Documentation/git-init.txt
+++ b/Documentation/git-init.txt
@@ -95,11 +95,11 @@ If the object storage directory is specified via the `$GIT_OBJECT_DIRECTORY`
environment variable then the sha1 directories are created underneath -
otherwise the default `$GIT_DIR/objects` directory is used.
-Running 'git-init' in an existing repository is safe. It will not overwrite
-things that are already there. The primary reason for rerunning 'git-init'
+Running 'git init' in an existing repository is safe. It will not overwrite
+things that are already there. The primary reason for rerunning 'git init'
is to pick up newly added templates.
-Note that 'git-init' is the same as 'git-init-db'. The command
+Note that 'git init' is the same as 'git init-db'. The command
was primarily meant to initialize the object database, but over
time it has become responsible for setting up the other aspects
of the repository, such as installing the default hooks and
diff --git a/Documentation/git-instaweb.txt b/Documentation/git-instaweb.txt
index 0771f25..a1f17df 100644
--- a/Documentation/git-instaweb.txt
+++ b/Documentation/git-instaweb.txt
@@ -44,7 +44,7 @@ OPTIONS
-b::
--browser::
The web browser that should be used to view the gitweb
- page. This will be passed to the 'git-web--browse' helper
+ page. This will be passed to the 'git web--browse' helper
script along with the URL of the gitweb instance. See
linkgit:git-web--browse[1] for more information about this. If
the script fails, the URL will be printed to stdout.
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 0acd526..0e39bb6 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -14,9 +14,9 @@ DESCRIPTION
-----------
Shows the commit logs.
-The command takes options applicable to the 'git-rev-list'
+The command takes options applicable to the 'git rev-list'
command to control what is shown and how, and options applicable to
-the 'git-diff-*' commands to control how the changes
+the 'git diff-*' commands to control how the changes
each commit introduces are shown.
diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 98f3b9e..af409bf 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -146,7 +146,7 @@ which case it outputs:
[<tag> ]<mode> <object> <stage> <file>
-'git-ls-files --unmerged' and 'git-ls-files --stage' can be used to examine
+'git ls-files --unmerged' and 'git ls-files --stage' can be used to examine
detailed information on unmerged paths.
For an unmerged path, instead of recording a single mode/SHA1 pair,
@@ -163,7 +163,7 @@ respectively.
Exclude Patterns
----------------
-'git-ls-files' can use a list of "exclude patterns" when
+'git ls-files' can use a list of "exclude patterns" when
traversing the directory tree and finding files to show when the
flags --others or --ignored are specified. linkgit:gitignore[5]
specifies the format of exclude patterns.
@@ -179,7 +179,7 @@ These exclude patterns come from these places, in order:
in the same order they appear in the file.
3. command line flag --exclude-per-directory=<name> specifies
- a name of the file in each directory 'git-ls-files'
+ a name of the file in each directory 'git ls-files'
examines, normally `.gitignore`. Files in deeper
directories take precedence. Patterns are ordered in the
same order they appear in the files.
diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt
index c3fdccb..1f89d36 100644
--- a/Documentation/git-ls-tree.txt
+++ b/Documentation/git-ls-tree.txt
@@ -28,7 +28,7 @@ in the current working directory. Note that:
in a directory 'sub' that has a directory 'dir', you can run 'git
ls-tree -r HEAD dir' to list the contents of the tree (that is
'sub/dir' in 'HEAD'). You don't want to give a tree that is not at the
- root level (e.g. 'git ls-tree -r HEAD:sub dir') in this case, as that
+ root level (e.g. `git ls-tree -r HEAD:sub dir`) in this case, as that
would result in asking for 'sub/sub/dir' in the 'HEAD' commit.
However, the current working directory can be ignored by passing
--full-tree option.
@@ -84,7 +84,7 @@ Output Format
Unless the `-z` option is used, TAB, LF, and backslash characters
in pathnames are represented as `\t`, `\n`, and `\\`, respectively.
-This output format is compatible with what '--index-info --stdin' of
+This output format is compatible with what `--index-info --stdin` of
'git update-index' expects.
When the `-l` option is used, format changes to
diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.txt
index b81ac98..e3d58cb 100644
--- a/Documentation/git-mailinfo.txt
+++ b/Documentation/git-mailinfo.txt
@@ -16,7 +16,7 @@ DESCRIPTION
Reads a single e-mail message from the standard input, and
writes the commit log message in <msg> file, and the patches in
<patch> file. The author name, e-mail and e-mail subject are
-written out to the standard output to be used by 'git-am'
+written out to the standard output to be used by 'git am'
to create a commit. It is usually not necessary to use this
command directly. See linkgit:git-am[1] instead.
@@ -30,7 +30,7 @@ OPTIONS
whitespaces, (3) '[' up to ']', typically '[PATCH]', and
then prepends "[PATCH] ". This flag forbids this
munging, and is most useful when used to read back
- 'git-format-patch -k' output.
+ 'git format-patch -k' output.
-b::
When -k is not in effect, all leading strings bracketed with '['
diff --git a/Documentation/git-merge-file.txt b/Documentation/git-merge-file.txt
index 3035373..234269a 100644
--- a/Documentation/git-merge-file.txt
+++ b/Documentation/git-merge-file.txt
@@ -10,20 +10,21 @@ SYNOPSIS
--------
[verse]
'git merge-file' [-L <current-name> [-L <base-name> [-L <other-name>]]]
- [-p|--stdout] [-q|--quiet] <current-file> <base-file> <other-file>
+ [--ours|--theirs] [-p|--stdout] [-q|--quiet]
+ <current-file> <base-file> <other-file>
DESCRIPTION
-----------
-'git-merge-file' incorporates all changes that lead from the `<base-file>`
+'git merge-file' incorporates all changes that lead from the `<base-file>`
to `<other-file>` into `<current-file>`. The result ordinarily goes into
-`<current-file>`. 'git-merge-file' is useful for combining separate changes
+`<current-file>`. 'git merge-file' is useful for combining separate changes
to an original. Suppose `<base-file>` is the original, and both
`<current-file>` and `<other-file>` are modifications of `<base-file>`,
-then 'git-merge-file' combines both changes.
+then 'git merge-file' combines both changes.
A conflict occurs if both `<current-file>` and `<other-file>` have changes
-in a common segment of lines. If a conflict is found, 'git-merge-file'
+in a common segment of lines. If a conflict is found, 'git merge-file'
normally outputs a warning and brackets the conflict with lines containing
<<<<<<< and >>>>>>> markers. A typical conflict will look like this:
@@ -34,12 +35,14 @@ normally outputs a warning and brackets the conflict with lines containing
>>>>>>> B
If there are conflicts, the user should edit the result and delete one of
-the alternatives.
+the alternatives. When `--ours` or `--theirs` option is in effect, however,
+these conflicts are resolved favouring lines from `<current-file>` or
+lines from `<other-file>` respectively.
The exit value of this program is negative on error, and the number of
conflicts otherwise. If the merge was clean, the exit value is 0.
-'git-merge-file' is designed to be a minimal clone of RCS 'merge'; that is, it
+'git merge-file' is designed to be a minimal clone of RCS 'merge'; that is, it
implements all of RCS 'merge''s functionality which is needed by
linkgit:git[1].
@@ -62,6 +65,11 @@ OPTIONS
-q::
Quiet; do not warn about conflicts.
+--ours::
+--theirs::
+ Instead of leaving conflicts in the file, resolve conflicts
+ favouring our (or their) side of the lines.
+
EXAMPLES
--------
diff --git a/Documentation/git-merge-index.txt b/Documentation/git-merge-index.txt
index 123e6d0..4d266de 100644
--- a/Documentation/git-merge-index.txt
+++ b/Documentation/git-merge-index.txt
@@ -36,14 +36,14 @@ OPTIONS
failure usually indicates conflicts during the merge). This is for
porcelains which might want to emit custom messages.
-If 'git-merge-index' is called with multiple <file>s (or -a) then it
+If 'git merge-index' is called with multiple <file>s (or -a) then it
processes them in turn only stopping if merge returns a non-zero exit
code.
Typically this is run with a script calling git's imitation of
the 'merge' command from the RCS package.
-A sample script called 'git-merge-one-file' is included in the
+A sample script called 'git merge-one-file' is included in the
distribution.
ALERT ALERT ALERT! The git "merge object order" is different from the
@@ -68,10 +68,10 @@ or
This is added AA in the branch B.
fatal: merge program failed
-where the latter example shows how 'git-merge-index' will stop trying to
+where the latter example shows how 'git merge-index' will stop trying to
merge once anything has returned an error (i.e., `cat` returned an error
for the AA file, because it didn't exist in the original, and thus
-'git-merge-index' didn't even try to merge the MM thing).
+'git merge-index' didn't even try to merge the MM thing).
Author
------
diff --git a/Documentation/git-merge-one-file.txt b/Documentation/git-merge-one-file.txt
index dc8a96a..a163cfc 100644
--- a/Documentation/git-merge-one-file.txt
+++ b/Documentation/git-merge-one-file.txt
@@ -8,12 +8,12 @@ git-merge-one-file - The standard helper program to use with git-merge-index
SYNOPSIS
--------
-'git-merge-one-file'
+'git merge-one-file'
DESCRIPTION
-----------
-This is the standard helper program to use with 'git-merge-index'
-to resolve a merge after the trivial merge done with 'git-read-tree -m'.
+This is the standard helper program to use with 'git merge-index'
+to resolve a merge after the trivial merge done with 'git read-tree -m'.
Author
------
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 6747031..d4ef0d0 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -10,17 +10,21 @@ SYNOPSIS
--------
[verse]
'git merge' [-n] [--stat] [--no-commit] [--squash] [-s <strategy>]...
- [--[no-]rerere-autoupdate] [-m <msg>] <remote>...
-'git merge' <msg> HEAD <remote>...
+ [--[no-]rerere-autoupdate] [-m <msg>] <commit>...
+'git merge' <msg> HEAD <commit>...
DESCRIPTION
-----------
-This is the top-level interface to the merge machinery
-which drives multiple merge strategy scripts.
+Merges the history specified by <commit> into HEAD, optionally using a
+specific merge strategy.
-The second syntax (<msg> `HEAD` <remote>) is supported for
+The second syntax (<msg> `HEAD` <commit>...) is supported for
historical reasons. Do not use it from the command line or in
-new scripts. It is the same as `git merge -m <msg> <remote>`.
+new scripts. It is the same as `git merge -m <msg> <commit>...`.
+
+*Warning*: Running 'git merge' with uncommitted changes is
+discouraged: while possible, it leaves you in a state that is hard to
+back out of in the case of a conflict.
OPTIONS
@@ -38,16 +42,16 @@ include::merge-options.txt[]
Allow the rerere mechanism to update the index with the
result of auto-conflict resolution if possible.
-<remote>...::
- Other branch heads to merge into our branch. You need at
- least one <remote>. Specifying more than one <remote>
- obviously means you are trying an Octopus.
+<commit>...::
+ Commits, usually other branch heads, to merge into our branch.
+ You need at least one <commit>. Specifying more than one
+ <commit> obviously means you are trying an Octopus.
include::merge-strategies.txt[]
If you tried a merge which resulted in complex conflicts and
-want to start over, you can recover with 'git-reset'.
+want to start over, you can recover with 'git reset'.
CONFIGURATION
-------------
@@ -101,8 +105,8 @@ file matches exactly the current `HEAD` commit; otherwise we
will write out your local changes already registered in your
index file along with the merge result, which is not good.
Because 1. involves only those paths differing between your
-branch and the remote branch you are pulling from during the
-merge (which is typically a fraction of the whole tree), you can
+branch and the branch you are merging
+(which is typically a fraction of the whole tree), you can
have local modifications in your working tree as long as they do
not overlap with what the merge updates.
@@ -115,7 +119,7 @@ When there are conflicts, the following happens:
3. For conflicting paths, the index file records up to three
versions; stage1 stores the version from the common ancestor,
- stage2 from `HEAD`, and stage3 from the remote branch (you
+ stage2 from `HEAD`, and stage3 from the other branch (you
can inspect the stages with `git ls-files -u`). The working
tree files contain the result of the "merge" program; i.e. 3-way
merge results with familiar conflict markers `<<< === >>>`.
@@ -194,28 +198,28 @@ After seeing a conflict, you can do two things:
* Decide not to merge. The only clean-ups you need are to reset
the index file to the `HEAD` commit to reverse 2. and to clean
- up working tree changes made by 2. and 3.; 'git-reset --hard' can
+ up working tree changes made by 2. and 3.; `git-reset --hard` can
be used for this.
* Resolve the conflicts. Git will mark the conflicts in
the working tree. Edit the files into shape and
- 'git-add' them to the index. Use 'git-commit' to seal the deal.
+ 'git add' them to the index. Use 'git commit' to seal the deal.
You can work through the conflict with a number of tools:
- * Use a mergetool. 'git mergetool' to launch a graphical
+ * Use a mergetool. `git mergetool` to launch a graphical
mergetool which will work you through the merge.
- * Look at the diffs. 'git diff' will show a three-way diff,
- highlighting changes from both the HEAD and remote versions.
+ * Look at the diffs. `git diff` will show a three-way diff,
+ highlighting changes from both the HEAD and their versions.
- * Look at the diffs on their own. 'git log --merge -p <path>'
- will show diffs first for the HEAD version and then the
- remote version.
+ * Look at the diffs on their own. `git log --merge -p <path>`
+ will show diffs first for the HEAD version and then
+ their version.
- * Look at the originals. 'git show :1:filename' shows the
- common ancestor, 'git show :2:filename' shows the HEAD
- version and 'git show :3:filename' shows the remote version.
+ * Look at the originals. `git show :1:filename` shows the
+ common ancestor, `git show :2:filename` shows the HEAD
+ version and `git show :3:filename` shows their version.
EXAMPLES
diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt
index 4a6f7f3..55735fa 100644
--- a/Documentation/git-mergetool.txt
+++ b/Documentation/git-mergetool.txt
@@ -13,11 +13,11 @@ DESCRIPTION
-----------
Use `git mergetool` to run one of several merge utilities to resolve
-merge conflicts. It is typically run after 'git-merge'.
+merge conflicts. It is typically run after 'git merge'.
If one or more <file> parameters are given, the merge tool program will
be run to resolve differences on each file. If no <file> names are
-specified, 'git-mergetool' will run the merge tool program on every file
+specified, 'git mergetool' will run the merge tool program on every file
with merge conflicts.
OPTIONS
@@ -29,23 +29,23 @@ OPTIONS
kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge,
diffuse, tortoisemerge, opendiff, p4merge and araxis.
+
-If a merge resolution program is not specified, 'git-mergetool'
+If a merge resolution program is not specified, 'git mergetool'
will use the configuration variable `merge.tool`. If the
-configuration variable `merge.tool` is not set, 'git-mergetool'
+configuration variable `merge.tool` is not set, 'git mergetool'
will pick a suitable default.
+
You can explicitly provide a full path to the tool by setting the
configuration variable `mergetool.<tool>.path`. For example, you
can configure the absolute path to kdiff3 by setting
-`mergetool.kdiff3.path`. Otherwise, 'git-mergetool' assumes the
+`mergetool.kdiff3.path`. Otherwise, 'git mergetool' assumes the
tool is available in PATH.
+
Instead of running one of the known merge tool programs,
-'git-mergetool' can be customized to run an alternative program
+'git mergetool' can be customized to run an alternative program
by specifying the command line to invoke in a configuration
variable `mergetool.<tool>.cmd`.
+
-When 'git-mergetool' is invoked with this tool (either through the
+When 'git mergetool' is invoked with this tool (either through the
`-t` or `--tool` option or the `merge.tool` configuration
variable) the configured command line will be invoked with `$BASE`
set to the name of a temporary file containing the common base for
@@ -59,7 +59,7 @@ merge resolution.
If the custom merge tool correctly indicates the success of a
merge resolution with its exit code, then the configuration
variable `mergetool.<tool>.trustExitCode` can be set to `true`.
-Otherwise, 'git-mergetool' will prompt the user to indicate the
+Otherwise, 'git mergetool' will prompt the user to indicate the
success of the resolution after the custom tool has exited.
-y::
diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt
index 7ca8a7b..2108237 100644
--- a/Documentation/git-name-rev.txt
+++ b/Documentation/git-name-rev.txt
@@ -15,7 +15,7 @@ SYNOPSIS
DESCRIPTION
-----------
Finds symbolic names suitable for human digestion for revisions given in any
-format parsable by 'git-rev-parse'.
+format parsable by 'git rev-parse'.
OPTIONS
@@ -55,7 +55,7 @@ wrote you about that fantastic commit 33db5f4d9027a10e477ccf054b2c1ab94f74c85a.
Of course, you look into the commit, but that only tells you what happened, but
not the context.
-Enter 'git-name-rev':
+Enter 'git name-rev':
------------
% git name-rev 33db5f4d9027a10e477ccf054b2c1ab94f74c85a
diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt
index 94cceb1..14f73b9 100644
--- a/Documentation/git-notes.txt
+++ b/Documentation/git-notes.txt
@@ -3,57 +3,112 @@ git-notes(1)
NAME
----
-git-notes - Add/inspect commit notes
+git-notes - Add/inspect object notes
SYNOPSIS
--------
[verse]
-'git-notes' (edit [-F <file> | -m <msg>] | show) [commit]
+'git notes' [list [<object>]]
+'git notes' add [-f] [-F <file> | -m <msg> | (-c | -C) <object>] [<object>]
+'git notes' copy [-f] <from-object> <to-object>
+'git notes' append [-F <file> | -m <msg> | (-c | -C) <object>] [<object>]
+'git notes' edit [<object>]
+'git notes' show [<object>]
+'git notes' remove [<object>]
+'git notes' prune
+
DESCRIPTION
-----------
-This command allows you to add notes to commit messages, without
-changing the commit. To discern these notes from the message stored
-in the commit object, the notes are indented like the message, after
-an unindented line saying "Notes:".
+This command allows you to add/remove notes to/from objects, without
+changing the objects themselves.
+
+A typical use of notes is to extend a commit message without having
+to change the commit itself. Such commit notes can be shown by `git log`
+along with the original commit message. To discern these notes from the
+message stored in the commit object, the notes are indented like the
+message, after an unindented line saying "Notes:".
-To disable commit notes, you have to set the config variable
-core.notesRef to the empty string. Alternatively, you can set it
-to a different ref, something like "refs/notes/bugzilla". This setting
-can be overridden by the environment variable "GIT_NOTES_REF".
+To disable notes, you have to set the config variable core.notesRef to
+the empty string. Alternatively, you can set it to a different ref,
+something like "refs/notes/bugzilla". This setting can be overridden
+by the environment variable "GIT_NOTES_REF".
SUBCOMMANDS
-----------
+list::
+ List the notes object for a given object. If no object is
+ given, show a list of all note objects and the objects they
+ annotate (in the format "<note object> <annotated object>").
+ This is the default subcommand if no subcommand is given.
+
+add::
+ Add notes for a given object (defaults to HEAD). Abort if the
+ object already has notes, abort. (use `-f` to overwrite an
+ existing note).
+
+copy::
+ Copy the notes for the first object onto the second object.
+ Abort if the second object already has notes, or if the first
+ objects has none. (use -f to overwrite existing notes to the
+ second object). This subcommand is equivalent to:
+ `git notes add [-f] -C $(git notes list <from-object>) <to-object>`
+
+append::
+ Append to the notes of an existing object (defaults to HEAD).
+ Creates a new notes object if needed.
+
edit::
- Edit the notes for a given commit (defaults to HEAD).
+ Edit the notes for a given object (defaults to HEAD).
show::
- Show the notes for a given commit (defaults to HEAD).
+ Show the notes for a given object (defaults to HEAD).
+
+remove::
+ Remove the notes for a given object (defaults to HEAD).
+ This is equivalent to specifying an empty note message to
+ the `edit` subcommand.
+prune::
+ Remove all notes for non-existing/unreachable objects.
OPTIONS
-------
+-f::
+--force::
+ When adding notes to an object that already has notes,
+ overwrite the existing notes (instead of aborting).
+
-m <msg>::
+--message=<msg>::
Use the given note message (instead of prompting).
- If multiple `-m` (or `-F`) options are given, their
- values are concatenated as separate paragraphs.
+ If multiple `-m` options are given, their values
+ are concatenated as separate paragraphs.
-F <file>::
+--file=<file>::
Take the note message from the given file. Use '-' to
read the note message from the standard input.
- If multiple `-F` (or `-m`) options are given, their
- values are concatenated as separate paragraphs.
+-C <object>::
+--reuse-message=<object>::
+ Reuse the note message from the given note object.
+
+-c <object>::
+--reedit-message=<object>::
+ Like '-C', but with '-c' the editor is invoked, so that
+ the user can further edit the note message.
Author
------
-Written by Johannes Schindelin <johannes.schindelin@gmx.de>
+Written by Johannes Schindelin <johannes.schindelin@gmx.de> and
+Johan Herland <johan@herland.net>
Documentation
-------------
-Documentation by Johannes Schindelin
+Documentation by Johannes Schindelin and Johan Herland
GIT
---
diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt
index f54d433..097a147 100644
--- a/Documentation/git-pack-objects.txt
+++ b/Documentation/git-pack-objects.txt
@@ -32,7 +32,7 @@ Placing both in the pack/ subdirectory of $GIT_OBJECT_DIRECTORY (or
any of the directories on $GIT_ALTERNATE_OBJECT_DIRECTORIES)
enables git to read from such an archive.
-The 'git-unpack-objects' command can read the packed archive and
+The 'git unpack-objects' command can read the packed archive and
expand the objects contained in the pack into "one-file
one-object" format; this is typically done by the smart-pull
commands when a pack is created on-the-fly for efficient network
@@ -61,7 +61,7 @@ base-name::
--revs::
Read the revision arguments from the standard input, instead of
individual object names. The revision arguments are processed
- the same way as 'git-rev-list' with the `--objects` flag
+ the same way as 'git rev-list' with the `--objects` flag
uses its `commit` arguments to build the list of objects it
outputs. The objects on the resulting list are packed.
@@ -182,7 +182,7 @@ base-name::
A packed archive can express base object of a delta as
either 20-byte object name or as an offset in the
stream, but older version of git does not understand the
- latter. By default, 'git-pack-objects' only uses the
+ latter. By default, 'git pack-objects' only uses the
former format for better compatibility. This option
allows the command to use the latter format for
compactness. Depending on the average delta chain
diff --git a/Documentation/git-pack-redundant.txt b/Documentation/git-pack-redundant.txt
index 5f9435e..d060787 100644
--- a/Documentation/git-pack-redundant.txt
+++ b/Documentation/git-pack-redundant.txt
@@ -16,7 +16,7 @@ This program computes which packs in your repository
are redundant. The output is suitable for piping to
`xargs rm` if you are in the root of the repository.
-'git-pack-redundant' accepts a list of objects on standard input. Any objects
+'git pack-redundant' accepts a list of objects on standard input. Any objects
given will be ignored when checking which packs are required. This makes the
following command useful when wanting to remove packs which contain unreachable
objects.
diff --git a/Documentation/git-patch-id.txt b/Documentation/git-patch-id.txt
index 253fc0f..4dae139 100644
--- a/Documentation/git-patch-id.txt
+++ b/Documentation/git-patch-id.txt
@@ -18,7 +18,7 @@ ID" are almost guaranteed to be the same thing.
IOW, you can use this thing to look for likely duplicate commits.
-When dealing with 'git-diff-tree' output, it takes advantage of
+When dealing with 'git diff-tree' output, it takes advantage of
the fact that the patch is prefixed with the object name of the
commit, and outputs two 40-byte hexadecimal strings. The first
string is the patch ID, and the second string is the commit ID.
diff --git a/Documentation/git-peek-remote.txt b/Documentation/git-peek-remote.txt
index 8282a5e..87dacd7 100644
--- a/Documentation/git-peek-remote.txt
+++ b/Documentation/git-peek-remote.txt
@@ -12,7 +12,7 @@ SYNOPSIS
DESCRIPTION
-----------
-This command is deprecated; use 'git-ls-remote' instead.
+This command is deprecated; use 'git ls-remote' instead.
OPTIONS
-------
diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt
index da6055d..3bb7304 100644
--- a/Documentation/git-prune.txt
+++ b/Documentation/git-prune.txt
@@ -8,21 +8,21 @@ git-prune - Prune all unreachable objects from the object database
SYNOPSIS
--------
-'git-prune' [-n] [-v] [--expire <expire>] [--] [<head>...]
+'git prune' [-n] [-v] [--expire <expire>] [--] [<head>...]
DESCRIPTION
-----------
-NOTE: In most cases, users should run 'git-gc', which calls
-'git-prune'. See the section "NOTES", below.
+NOTE: In most cases, users should run 'git gc', which calls
+'git prune'. See the section "NOTES", below.
-This runs 'git-fsck --unreachable' using all the refs
+This runs 'git fsck --unreachable' using all the refs
available in `$GIT_DIR/refs`, optionally with additional set of
objects specified on the command line, and prunes all unpacked
objects unreachable from any of these head objects from the object database.
In addition, it
prunes the unpacked objects that are also found in packs by
-running 'git-prune-packed'.
+running 'git prune-packed'.
Note that unreachable, packed objects will remain. If this is
not desired, see linkgit:git-repack[1].
@@ -62,12 +62,12 @@ $ git prune $(cd ../another && $(git rev-parse --all))
Notes
-----
-In most cases, users will not need to call 'git-prune' directly, but
-should instead call 'git-gc', which handles pruning along with
+In most cases, users will not need to call 'git prune' directly, but
+should instead call 'git gc', which handles pruning along with
many other housekeeping tasks.
For a description of which objects are considered for pruning, see
-'git-fsck''s --unreachable option.
+'git fsck''s --unreachable option.
SEE ALSO
--------
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index b932011..31f42ea 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -13,16 +13,20 @@ SYNOPSIS
DESCRIPTION
-----------
-Runs 'git-fetch' with the given parameters, and calls 'git-merge'
+Runs 'git fetch' with the given parameters, and calls 'git merge'
to merge the retrieved head(s) into the current branch.
-With `--rebase`, calls 'git-rebase' instead of 'git-merge'.
+With `--rebase`, calls 'git rebase' instead of 'git merge'.
Note that you can use `.` (current directory) as the
<repository> to pull from the local repository -- this is useful
when merging local branches into the current branch.
-Also note that options meant for 'git-pull' itself and underlying
-'git-merge' must be given before the options meant for 'git-fetch'.
+Also note that options meant for 'git pull' itself and underlying
+'git merge' must be given before the options meant for 'git fetch'.
+
+*Warning*: Running 'git pull' (actually, the underlying 'git merge')
+with uncommitted changes is discouraged: while possible, it leaves you
+in a state that is hard to back out of in the case of a conflict.
OPTIONS
-------
@@ -148,7 +152,7 @@ $ git merge origin/next
If you tried a pull which resulted in a complex conflicts and
-would want to start over, you can recover with 'git-reset'.
+would want to start over, you can recover with 'git reset'.
SEE ALSO
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index e3eb1e8..c63932b 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -10,7 +10,7 @@ SYNOPSIS
--------
[verse]
'git push' [--all | --mirror | --tags] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
- [--repo=<repository>] [-f | --force] [-v | --verbose]
+ [--repo=<repository>] [-f | --force] [-v | --verbose] [-u | --set-upstream]
[<repository> <refspec>...]
DESCRIPTION
@@ -116,12 +116,19 @@ nor in any Push line of the corresponding remotes file---see below).
--repo=<repository>::
This option is only relevant if no <repository> argument is
- passed in the invocation. In this case, 'git-push' derives the
+ passed in the invocation. In this case, 'git push' derives the
remote name from the current branch: If it tracks a remote
branch, then that remote repository is pushed to. Otherwise,
the name "origin" is used. For this latter case, this option
can be used to override the name "origin". In other words,
the difference between these two commands
+
+-u::
+--set-upstream::
+ For every branch that is up to date or successfully pushed, add
+ upstream (tracking) reference, used by argument-less
+ linkgit:git-pull[1] and other commands. For more information,
+ see 'branch.<name>.merge' in linkgit:git-config[1].
+
--------------------------
git push public #1
@@ -130,11 +137,11 @@ git push --repo=public #2
+
is that #1 always pushes to "public" whereas #2 pushes to "public"
only if the current branch does not track a remote branch. This is
-useful if you write an alias or script around 'git-push'.
+useful if you write an alias or script around 'git push'.
--thin::
--no-thin::
- These options are passed to 'git-send-pack'. Thin
+ These options are passed to 'git send-pack'. Thin
transfer spends extra cycles to minimize the number of
objects to be sent and meant to be used on slower connection.
diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt
index d6faa14..567671c 100644
--- a/Documentation/git-read-tree.txt
+++ b/Documentation/git-read-tree.txt
@@ -25,8 +25,8 @@ fast-forward (i.e. 2-way) merge, or a 3-way merge, with the `-m`
flag. When used with `-m`, the `-u` flag causes it to also update
the files in the work tree with the result of the merge.
-Trivial merges are done by 'git-read-tree' itself. Only conflicting paths
-will be in unmerged state when 'git-read-tree' returns.
+Trivial merges are done by 'git read-tree' itself. Only conflicting paths
+will be in unmerged state when 'git read-tree' returns.
OPTIONS
-------
@@ -57,13 +57,13 @@ OPTIONS
Show the progress of checking files out.
--trivial::
- Restrict three-way merge by 'git-read-tree' to happen
+ Restrict three-way merge by 'git read-tree' to happen
only if there is no file-level merging required, instead
of resolving merge for trivial cases and leaving
conflicting files unresolved in the index.
--aggressive::
- Usually a three-way merge by 'git-read-tree' resolves
+ Usually a three-way merge by 'git read-tree' resolves
the merge for really trivial cases and leaves other
cases unresolved in the index, so that Porcelains can
implement different merge policies. This flag makes the
@@ -120,7 +120,7 @@ OPTIONS
Merging
-------
-If `-m` is specified, 'git-read-tree' can perform 3 kinds of
+If `-m` is specified, 'git read-tree' can perform 3 kinds of
merge, a single tree merge if only 1 tree is given, a
fast-forward merge with 2 trees, or a 3-way merge if 3 trees are
provided.
@@ -128,18 +128,18 @@ provided.
Single Tree Merge
~~~~~~~~~~~~~~~~~
-If only 1 tree is specified, 'git-read-tree' operates as if the user did not
+If only 1 tree is specified, 'git read-tree' operates as if the user did not
specify `-m`, except that if the original index has an entry for a
given pathname, and the contents of the path matches with the tree
being read, the stat info from the index is used. (In other words, the
index's stat()s take precedence over the merged tree's).
That means that if you do a `git read-tree -m <newtree>` followed by a
-`git checkout-index -f -u -a`, the 'git-checkout-index' only checks out
+`git checkout-index -f -u -a`, the 'git checkout-index' only checks out
the stuff that really changed.
-This is used to avoid unnecessary false hits when 'git-diff-files' is
-run after 'git-read-tree'.
+This is used to avoid unnecessary false hits when 'git diff-files' is
+run after 'git read-tree'.
Two Tree Merge
@@ -150,7 +150,7 @@ is the head commit of the current repository, and $M is the head
of a foreign tree, which is simply ahead of $H (i.e. we are in a
fast-forward situation).
-When two trees are specified, the user is telling 'git-read-tree'
+When two trees are specified, the user is telling 'git read-tree'
the following:
1. The current index and work tree is derived from $H, but
@@ -203,10 +203,10 @@ Here are the "carry forward" rules:
In all "keep index" cases, the index entry stays as in the
original index file. If the entry were not up to date,
-'git-read-tree' keeps the copy in the work tree intact when
+'git read-tree' keeps the copy in the work tree intact when
operating under the -u flag.
-When this form of 'git-read-tree' returns successfully, you can
+When this form of 'git read-tree' returns successfully, you can
see what "local changes" you made are carried forward by running
`git diff-index --cached $M`. Note that this does not
necessarily match `git diff-index --cached $H` would have
@@ -229,7 +229,7 @@ of the path is kept as long as $H and $M are the same.
Each "index" entry has two bits worth of "stage" state. stage 0 is the
normal one, and is the only one you'd see in any kind of normal use.
-However, when you do 'git-read-tree' with three trees, the "stage"
+However, when you do 'git read-tree' with three trees, the "stage"
starts out at 1.
This means that you can do
@@ -245,7 +245,7 @@ branch into the current branch, we use the common ancestor tree
as <tree1>, the current branch head as <tree2>, and the other
branch head as <tree3>.
-Furthermore, 'git-read-tree' has special-case logic that says: if you see
+Furthermore, 'git read-tree' has special-case logic that says: if you see
a file that matches in all respects in the following states, it
"collapses" back to "stage0":
@@ -261,7 +261,7 @@ a file that matches in all respects in the following states, it
- stage 1 and stage 3 are the same and stage 2 is different take
stage 2 (we did something while they did nothing)
-The 'git-write-tree' command refuses to write a nonsensical tree, and it
+The 'git write-tree' command refuses to write a nonsensical tree, and it
will complain about unmerged entries if it sees a single entry that is not
stage 0.
@@ -277,7 +277,7 @@ start a 3-way merge with an index file that is already
populated. Here is an outline of how the algorithm works:
- if a file exists in identical format in all three trees, it will
- automatically collapse to "merged" state by 'git-read-tree'.
+ automatically collapse to "merged" state by 'git read-tree'.
- a file that has _any_ difference what-so-ever in the three trees
will stay as separate entries in the index. It's up to "porcelain
@@ -301,8 +301,8 @@ populated. Here is an outline of how the algorithm works:
matching "stage1" entry if it exists too. .. all the normal
trivial rules ..
-You would normally use 'git-merge-index' with supplied
-'git-merge-one-file' to do this last step. The script updates
+You would normally use 'git merge-index' with supplied
+'git merge-one-file' to do this last step. The script updates
the files in the working tree as it merges each path and at the
end of a successful merge.
@@ -324,7 +324,7 @@ $ JC=`git rev-parse --verify "HEAD^0"`
$ git checkout-index -f -u -a $JC
----------------
-You do random edits, without running 'git-update-index'. And then
+You do random edits, without running 'git update-index'. And then
you notice that the tip of your "upstream" tree has advanced
since you pulled from him:
@@ -350,14 +350,14 @@ your work-in-progress changes, and your work tree would be
updated to the result of the merge.
However, if you have local changes in the working tree that
-would be overwritten by this merge, 'git-read-tree' will refuse
+would be overwritten by this merge, 'git read-tree' will refuse
to run to prevent your changes from being lost.
In other words, there is no need to worry about what exists only
in the working tree. When you have local changes in a part of
the project that is not involved in the merge, your changes do
not interfere with the merge, and are kept intact. When they
-*do* interfere, the merge does not even start ('git-read-tree'
+*do* interfere, the merge does not even start ('git read-tree'
complains loudly and fails without modifying anything). In such
a case, you can simply continue doing what you were in the
middle of doing, and when your working tree is ready (i.e. you
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index ca5e1e8..823f2a4 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -17,7 +17,7 @@ SYNOPSIS
DESCRIPTION
-----------
-If <branch> is specified, 'git-rebase' will perform an automatic
+If <branch> is specified, 'git rebase' will perform an automatic
`git checkout <branch>` before doing anything else. Otherwise
it remains on the current branch.
@@ -170,8 +170,8 @@ This is useful if F and G were flawed in some way, or should not be
part of topicA. Note that the argument to --onto and the <upstream>
parameter can be any valid commit-ish.
-In case of conflict, 'git-rebase' will stop at the first problematic commit
-and leave conflict markers in the tree. You can use 'git-diff' to locate
+In case of conflict, 'git rebase' will stop at the first problematic commit
+and leave conflict markers in the tree. You can use 'git diff' to locate
the markers (<<<<<<) and make edits to resolve the conflict. For each
file you edit, you need to tell git that the conflict has been resolved,
typically this would be done with
@@ -187,7 +187,7 @@ desired resolution, you can continue the rebasing process with
git rebase --continue
-Alternatively, you can undo the 'git-rebase' with
+Alternatively, you can undo the 'git rebase' with
git rebase --abort
@@ -238,10 +238,10 @@ other words, the sides are swapped.
-s <strategy>::
--strategy=<strategy>::
Use the given merge strategy.
- If there is no `-s` option 'git-merge-recursive' is used
+ If there is no `-s` option 'git merge-recursive' is used
instead. This implies --merge.
+
-Because 'git-rebase' replays each commit from the working branch
+Because 'git rebase' replays each commit from the working branch
on top of the <upstream> branch using the given strategy, using
the 'ours' strategy simply discards all patches from the <branch>,
which makes little sense.
@@ -280,13 +280,13 @@ which makes little sense.
--ignore-whitespace::
--whitespace=<option>::
- These flag are passed to the 'git-apply' program
+ These flag are passed to the 'git apply' program
(see linkgit:git-apply[1]) that applies the patch.
Incompatible with the --interactive option.
--committer-date-is-author-date::
--ignore-date::
- These flags are passed to 'git-am' to easily change the dates
+ These flags are passed to 'git am' to easily change the dates
of the rebased commits (see linkgit:git-am[1]).
-i::
@@ -308,12 +308,22 @@ which makes little sense.
root commits will be rewritten to have <newbase> as parent
instead.
+--autosquash::
+ When the commit log message begins with "squash! ..." (or
+ "fixup! ..."), and there is a commit whose title begins with
+ the same ..., automatically modify the todo list of rebase -i
+ so that the commit marked for squashing comes right after the
+ commit to be modified, and change the action of the moved
+ commit from `pick` to `squash` (or `fixup`).
++
+This option is only valid when '--interactive' option is used.
+
include::merge-strategies.txt[]
NOTES
-----
-You should understand the implications of using 'git-rebase' on a
+You should understand the implications of using 'git rebase' on a
repository that you share. See also RECOVERING FROM UPSTREAM REBASE
below.
@@ -369,12 +379,12 @@ pick fa1afe1 The oneline of the next commit
...
-------------------------------------------
-The oneline descriptions are purely for your pleasure; 'git-rebase' will
+The oneline descriptions are purely for your pleasure; 'git rebase' will
not look at them but at the commit names ("deadbee" and "fa1afe1" in this
example), so do not delete or edit the names.
By replacing the command "pick" with the command "edit", you can tell
-'git-rebase' to stop after applying that commit, so that you can edit
+'git rebase' to stop after applying that commit, so that you can edit
the files and/or the commit message, amend the commit, and continue
rebasing.
@@ -382,17 +392,20 @@ If you just want to edit the commit message for a commit, replace the
command "pick" with the command "reword".
If you want to fold two or more commits into one, replace the command
-"pick" with "squash" for the second and subsequent commit. If the
-commits had different authors, it will attribute the squashed commit to
-the author of the first commit.
-
-'git-rebase' will stop when "pick" has been replaced with "edit" or
+"pick" for the second and subsequent commits with "squash" or "fixup".
+If the commits had different authors, the folded commit will be
+attributed to the author of the first commit. The suggested commit
+message for the folded commit is the concatenation of the commit
+messages of the first commit and of those with the "squash" command,
+but omits the commit messages of commits with the "fixup" command.
+
+'git rebase' will stop when "pick" has been replaced with "edit" or
when a command fails due to merge errors. When you are done editing
and/or resolving conflicts you can continue with `git rebase --continue`.
For example, if you want to reorder the last 5 commits, such that what
was HEAD~4 becomes the new HEAD. To achieve that, you would call
-'git-rebase' like this:
+'git rebase' like this:
----------------------
$ git rebase -i HEAD~5
@@ -422,7 +435,7 @@ SPLITTING COMMITS
-----------------
In interactive mode, you can mark commits with the action "edit". However,
-this does not necessarily mean that 'git-rebase' expects the result of this
+this does not necessarily mean that 'git rebase' expects the result of this
edit to be exactly one commit. Indeed, you can undo the commit, or you can
add other commits. This can be used to split a commit into two:
@@ -438,7 +451,7 @@ add other commits. This can be used to split a commit into two:
- Now add the changes to the index that you want to have in the first
commit. You can use `git add` (possibly interactively) or
- 'git-gui' (or both) to do that.
+ 'git gui' (or both) to do that.
- Commit the now-current index with whatever commit message is appropriate
now.
@@ -449,7 +462,7 @@ add other commits. This can be used to split a commit into two:
If you are not absolutely sure that the intermediate revisions are
consistent (they compile, pass the testsuite, etc.) you should use
-'git-stash' to stash away the not-yet-committed changes
+'git stash' to stash away the not-yet-committed changes
after each commit, test, and amend the commit if fixes are necessary.
@@ -512,8 +525,8 @@ Easy case: The changes are literally the same.::
Hard case: The changes are not the same.::
This happens if the 'subsystem' rebase had conflicts, or used
- `\--interactive` to omit, edit, or squash commits; or if the
- upstream used one of `commit \--amend`, `reset`, or
+ `\--interactive` to omit, edit, squash, or fixup commits; or
+ if the upstream used one of `commit \--amend`, `reset`, or
`filter-branch`.
@@ -524,7 +537,7 @@ Only works if the changes (patch IDs based on the diff contents) on
'subsystem' are literally the same before and after the rebase
'subsystem' did.
-In that case, the fix is easy because 'git-rebase' knows to skip
+In that case, the fix is easy because 'git rebase' knows to skip
changes that are already present in the new upstream. So if you say
(assuming you're on 'topic')
------------
@@ -551,12 +564,12 @@ NOTE: While an "easy case recovery" sometimes appears to be successful
example, a commit that was removed via `git rebase
\--interactive` will be **resurrected**!
-The idea is to manually tell 'git-rebase' "where the old 'subsystem'
+The idea is to manually tell 'git rebase' "where the old 'subsystem'
ended and your 'topic' began", that is, what the old merge-base
between them was. You will have to find a way to name the last commit
of the old 'subsystem', for example:
-* With the 'subsystem' reflog: after 'git-fetch', the old tip of
+* With the 'subsystem' reflog: after 'git fetch', the old tip of
'subsystem' is at `subsystem@\{1}`. Subsequent fetches will
increase the number. (See linkgit:git-reflog[1].)
diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt
index cb5f405..2790eeb 100644
--- a/Documentation/git-receive-pack.txt
+++ b/Documentation/git-receive-pack.txt
@@ -8,15 +8,15 @@ git-receive-pack - Receive what is pushed into the repository
SYNOPSIS
--------
-'git receive-pack' <directory>
+'git-receive-pack' <directory>
DESCRIPTION
-----------
-Invoked by 'git-send-pack' and updates the repository with the
+Invoked by 'git send-pack' and updates the repository with the
information fed from the remote end.
This command is usually not invoked directly by the end user.
-The UI for the protocol is on the 'git-send-pack' side, and the
+The UI for the protocol is on the 'git send-pack' side, and the
program pair is meant to be used to push updates to remote
repository. For pull operations, see linkgit:git-fetch-pack[1].
diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt
index 7f7a544..802bd57 100644
--- a/Documentation/git-reflog.txt
+++ b/Documentation/git-reflog.txt
@@ -60,7 +60,7 @@ OPTIONS
refs.
+
This computation involves traversing all the reachable objects, i.e. it
-has the same cost as 'git-prune'. Fortunately, once this is run, we
+has the same cost as 'git prune'. Fortunately, once this is run, we
should not have to ever worry about missing objects, because the current
prune and pack-objects know about reflogs and protect objects referred by
them.
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index c272c92..b03ccaa 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -161,7 +161,7 @@ $ git checkout -b nfs linux-nfs/master
...
------------
-* Imitate 'git-clone' but track only selected branches
+* Imitate 'git clone' but track only selected branches
+
------------
$ mkdir project.git
diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt
index c9257a1..538895c 100644
--- a/Documentation/git-repack.txt
+++ b/Documentation/git-repack.txt
@@ -49,16 +49,16 @@ other objects in that pack they already have locally.
deleted by way of being left in the old pack and then
removed. Instead, the loose unreachable objects
will be pruned according to normal expiry rules
- with the next 'git-gc' invocation. See linkgit:git-gc[1].
+ with the next 'git gc' invocation. See linkgit:git-gc[1].
-d::
After packing, if the newly created packs make some
existing packs redundant, remove the redundant packs.
- Also run 'git-prune-packed' to remove redundant
+ Also run 'git prune-packed' to remove redundant
loose object files.
-l::
- Pass the `--local` option to 'git-pack-objects'. See
+ Pass the `--local` option to 'git pack-objects'. See
linkgit:git-pack-objects[1].
-f::
@@ -66,12 +66,12 @@ other objects in that pack they already have locally.
linkgit:git-pack-objects[1].
-q::
- Pass the `-q` option to 'git-pack-objects'. See
+ Pass the `-q` option to 'git pack-objects'. See
linkgit:git-pack-objects[1].
-n::
Do not update the server information with
- 'git-update-server-info'. This option skips
+ 'git update-server-info'. This option skips
updating local catalog files needed to publish
this repository (or a direct copy of it)
over HTTP or FTP. See linkgit:git-update-server-info[1].
@@ -109,7 +109,7 @@ Configuration
When configuration variable `repack.UseDeltaBaseOffset` is set
for the repository, the command passes `--delta-base-offset`
-option to 'git-pack-objects'; this typically results in slightly
+option to 'git pack-objects'; this typically results in slightly
smaller packs, but the generated packs are incompatible with
versions of git older than (and including) v1.4.3; do not set
the variable in a repository that older version of git needs to
diff --git a/Documentation/git-replace.txt b/Documentation/git-replace.txt
index 65a0da5..fde2092 100644
--- a/Documentation/git-replace.txt
+++ b/Documentation/git-replace.txt
@@ -65,7 +65,7 @@ OPTIONS
BUGS
----
Comparing blobs or trees that have been replaced with those that
-replace them will not work properly. And using 'git reset --hard' to
+replace them will not work properly. And using `git reset --hard` to
go back to a replaced commit will move the branch to the replacement
commit instead of the replaced commit.
diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.txt
index 7dd515b..acc220a 100644
--- a/Documentation/git-rerere.txt
+++ b/Documentation/git-rerere.txt
@@ -30,14 +30,14 @@ enable this command.
COMMANDS
--------
-Normally, 'git-rerere' is run without arguments or user-intervention.
+Normally, 'git rerere' is run without arguments or user-intervention.
However, it has several commands that allow it to interact with
its working state.
'clear'::
This resets the metadata used by rerere if a merge resolution is to be
-aborted. Calling 'git-am [--skip|--abort]' or 'git-rebase [--skip|--abort]'
+aborted. Calling 'git am [--skip|--abort]' or 'git rebase [--skip|--abort]'
will automatically invoke this command.
'diff'::
@@ -142,32 +142,32 @@ finally ready and merged into the master branch. This merge
would require you to resolve the conflict, introduced by the
commits marked with `*`. However, this conflict is often the
same conflict you resolved when you created the test merge you
-blew away. 'git-rerere' helps you resolve this final
+blew away. 'git rerere' helps you resolve this final
conflicted merge using the information from your earlier hand
resolve.
-Running the 'git-rerere' command immediately after a conflicted
+Running the 'git rerere' command immediately after a conflicted
automerge records the conflicted working tree files, with the
usual conflict markers `<<<<<<<`, `=======`, and `>>>>>>>` in
them. Later, after you are done resolving the conflicts,
-running 'git-rerere' again will record the resolved state of these
+running 'git rerere' again will record the resolved state of these
files. Suppose you did this when you created the test merge of
master into the topic branch.
Next time, after seeing the same conflicted automerge,
-running 'git-rerere' will perform a three-way merge between the
+running 'git rerere' will perform a three-way merge between the
earlier conflicted automerge, the earlier manual resolution, and
the current conflicted automerge.
If this three-way merge resolves cleanly, the result is written
out to your working tree file, so you do not have to manually
-resolve it. Note that 'git-rerere' leaves the index file alone,
+resolve it. Note that 'git rerere' leaves the index file alone,
so you still need to do the final sanity checks with `git diff`
-(or `git diff -c`) and 'git-add' when you are satisfied.
+(or `git diff -c`) and 'git add' when you are satisfied.
-As a convenience measure, 'git-merge' automatically invokes
-'git-rerere' upon exiting with a failed automerge and 'git-rerere'
+As a convenience measure, 'git merge' automatically invokes
+'git rerere' upon exiting with a failed automerge and 'git rerere'
records the hand resolve when it is a new conflict, or reuses the earlier hand
-resolve when it is not. 'git-commit' also invokes 'git-rerere'
+resolve when it is not. 'git commit' also invokes 'git rerere'
when committing a merge result. What this means is that you do
not have to do anything special yourself (besides enabling
the rerere.enabled config variable).
@@ -177,8 +177,8 @@ resolution is recorded, and it will be reused when you do the
actual merge later with the updated master and topic branch, as long
as the recorded resolution is still applicable.
-The information 'git-rerere' records is also used when running
-'git-rebase'. After blowing away the test merge and continuing
+The information 'git rerere' records is also used when running
+'git rebase'. After blowing away the test merge and continuing
development on the topic branch:
------------
@@ -197,7 +197,7 @@ you could run `git rebase master topic`, to bring yourself
up-to-date before your topic is ready to be sent upstream.
This would result in falling back to a three-way merge, and it
would conflict the same way as the test merge you resolved earlier.
-'git-rerere' will be run by 'git-rebase' to help you resolve this
+'git rerere' will be run by 'git rebase' to help you resolve this
conflict.
diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt
index c7aa444..168db08 100644
--- a/Documentation/git-reset.txt
+++ b/Documentation/git-reset.txt
@@ -39,7 +39,7 @@ OPTIONS
--soft::
Does not touch the index file nor the working tree at all, but
requires them to be in a good order. This leaves all your changed
- files "Changes to be committed", as 'git-status' would
+ files "Changes to be committed", as 'git status' would
put it.
--hard::
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index f857116..ae17c8a 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -9,7 +9,7 @@ git-rev-list - Lists commit objects in reverse chronological order
SYNOPSIS
--------
[verse]
-'git-rev-list' [ \--max-count=number ]
+'git rev-list' [ \--max-count=number ]
[ \--skip=number ]
[ \--max-age=timestamp ]
[ \--min-age=timestamp ]
@@ -94,8 +94,8 @@ between the two operands. The following two commands are equivalent:
'rev-list' is a very essential git command, since it
provides the ability to build and traverse commit ancestry graphs. For
this reason, it has a lot of different options that enables it to be
-used by commands as different as 'git-bisect' and
-'git-repack'.
+used by commands as different as 'git bisect' and
+'git repack'.
OPTIONS
-------
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 61f4835..c9184fc 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -15,16 +15,16 @@ DESCRIPTION
Many git porcelainish commands take mixture of flags
(i.e. parameters that begin with a dash '-') and parameters
-meant for the underlying 'git-rev-list' command they use internally
+meant for the underlying 'git rev-list' command they use internally
and flags and parameters for the other commands they use
-downstream of 'git-rev-list'. This command is used to
+downstream of 'git rev-list'. This command is used to
distinguish between them.
OPTIONS
-------
--parseopt::
- Use 'git-rev-parse' in option parsing mode (see PARSEOPT section below).
+ Use 'git rev-parse' in option parsing mode (see PARSEOPT section below).
--keep-dashdash::
Only meaningful in `--parseopt` mode. Tells the option parser to echo
@@ -36,17 +36,17 @@ OPTIONS
that take options themself.
--sq-quote::
- Use 'git-rev-parse' in shell quoting mode (see SQ-QUOTE
+ Use 'git rev-parse' in shell quoting mode (see SQ-QUOTE
section below). In contrast to the `--sq` option below, this
mode does only quoting. Nothing else is done to command input.
--revs-only::
Do not output flags and parameters not meant for
- 'git-rev-list' command.
+ 'git rev-list' command.
--no-revs::
Do not output flags and parameters meant for
- 'git-rev-list' command.
+ 'git rev-list' command.
--flags::
Do not output non-flag parameters.
@@ -74,7 +74,7 @@ OPTIONS
properly quoted for consumption by shell. Useful when
you expect your parameter to contain whitespaces and
newlines (e.g. when using pickaxe `-S` with
- 'git-diff-\*'). In contrast to the `--sq-quote` option,
+ 'git diff-\*'). In contrast to the `--sq-quote` option,
the command input is still interpreted as usual.
--not::
@@ -122,6 +122,9 @@ shown. If the pattern does not contain a globbing character (`?`,
character (`?`, `\*`, or `[`), it is turned into a prefix
match by appending `/\*`.
+--show-toplevel::
+ Show the absolute path of the top-level directory.
+
--show-prefix::
When the command is invoked from a subdirectory, show the
path of the current directory relative to the top-level
@@ -155,12 +158,12 @@ shown. If the pattern does not contain a globbing character (`?`,
--since=datestring::
--after=datestring::
Parse the date string, and output the corresponding
- --max-age= parameter for 'git-rev-list'.
+ --max-age= parameter for 'git rev-list'.
--until=datestring::
--before=datestring::
Parse the date string, and output the corresponding
- --min-age= parameter for 'git-rev-list'.
+ --min-age= parameter for 'git rev-list'.
<args>...::
Flags and parameters to be parsed.
@@ -181,7 +184,7 @@ blobs contained in a commit.
name the same commit object if there are no other object in
your repository whose object name starts with dae86e.
-* An output from 'git-describe'; i.e. a closest tag, optionally
+* An output from 'git describe'; i.e. a closest tag, optionally
followed by a dash and a number of commits, followed by a dash, a
`g`, and an abbreviated object name.
@@ -207,13 +210,13 @@ blobs contained in a commit.
+
HEAD names the commit your changes in the working tree is based on.
FETCH_HEAD records the branch you fetched from a remote repository
-with your last 'git-fetch' invocation.
+with your last 'git fetch' invocation.
ORIG_HEAD is created by commands that moves your HEAD in a drastic
way, to record the position of the HEAD before their operation, so that
you can change the tip of the branch back to the state before you ran
them easily.
MERGE_HEAD records the commit(s) you are merging into your branch
-when you run 'git-merge'.
+when you run 'git merge'.
* A ref followed by the suffix '@' with a date specification
enclosed in a brace
@@ -318,7 +321,7 @@ G H I J
SPECIFYING RANGES
-----------------
-History traversing commands such as 'git-log' operate on a set
+History traversing commands such as 'git log' operate on a set
of commits, not just a single commit. To these commands,
specifying a single revision with the notation described in the
previous section means the set of commits reachable from that
@@ -359,7 +362,7 @@ Here are a handful of examples:
PARSEOPT
--------
-In `--parseopt` mode, 'git-rev-parse' helps massaging options to bring to shell
+In `--parseopt` mode, 'git rev-parse' helps massaging options to bring to shell
scripts the same facilities C builtins have. It works as an option normalizer
(e.g. splits single switches aggregate values), a bit like `getopt(1)` does.
@@ -371,7 +374,7 @@ usage on the standard error stream, and exits with code 129.
Input Format
~~~~~~~~~~~~
-'git-rev-parse --parseopt' input format is fully text based. It has two parts,
+'git rev-parse --parseopt' input format is fully text based. It has two parts,
separated by a line that contains only `--`. The lines before the separator
(should be more than one) are used for the usage.
The lines after the separator describe the options.
@@ -430,13 +433,13 @@ eval `echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?`
SQ-QUOTE
--------
-In `--sq-quote` mode, 'git-rev-parse' echoes on the standard output a
+In `--sq-quote` mode, 'git rev-parse' echoes on the standard output a
single line suitable for `sh(1)` `eval`. This line is made by
normalizing the arguments following `--sq-quote`. Nothing other than
quoting the arguments is done.
If you want command input to still be interpreted as usual by
-'git-rev-parse' before the output is shell quoted, see the `--sq`
+'git rev-parse' before the output is shell quoted, see the `--sq`
option.
Example
diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt
index 5e11758..c66bf80 100644
--- a/Documentation/git-revert.txt
+++ b/Documentation/git-revert.txt
@@ -20,8 +20,8 @@ effect of an earlier commit (often a faulty one). If you want to
throw away all uncommitted changes in your working directory, you
should see linkgit:git-reset[1], particularly the '--hard' option. If
you want to extract specific files as they were in another commit, you
-should see linkgit:git-checkout[1], specifically the 'git checkout
-<commit> -- <filename>' syntax. Take care with these alternatives as
+should see linkgit:git-checkout[1], specifically the `git checkout
+<commit> -- <filename>` syntax. Take care with these alternatives as
both will discard uncommitted changes in your working directory.
OPTIONS
@@ -33,7 +33,7 @@ OPTIONS
-e::
--edit::
- With this option, 'git-revert' will let you edit the commit
+ With this option, 'git revert' will let you edit the commit
message prior to committing the revert. This is the default if
you run the command from a terminal.
@@ -54,7 +54,7 @@ See the link:howto/revert-a-faulty-merge.txt[revert-a-faulty-merge How-To] for
more details.
--no-edit::
- With this option, 'git-revert' will not start the commit
+ With this option, 'git revert' will not start the commit
message editor.
-n::
diff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.txt
index 5a04c6e..8178d92 100644
--- a/Documentation/git-send-pack.txt
+++ b/Documentation/git-send-pack.txt
@@ -12,7 +12,7 @@ SYNOPSIS
DESCRIPTION
-----------
-Usually you would want to use 'git-push', which is a
+Usually you would want to use 'git push', which is a
higher-level wrapper of this command, instead. See linkgit:git-push[1].
Invokes 'git-receive-pack' on a possibly remote repository, and
@@ -86,7 +86,7 @@ and the destination side (after the colon). The ref to be
pushed is determined by finding a match that matches the source
side, and where it is pushed is determined by using the
destination side. The rules used to match a ref are the same
-rules used by 'git-rev-parse' to resolve a symbolic ref
+rules used by 'git rev-parse' to resolve a symbolic ref
name. See linkgit:git-rev-parse[1].
- It is an error if <src> does not match exactly one of the
diff --git a/Documentation/git-sh-setup.txt b/Documentation/git-sh-setup.txt
index 18f14b5..3da2413 100644
--- a/Documentation/git-sh-setup.txt
+++ b/Documentation/git-sh-setup.txt
@@ -16,7 +16,7 @@ This is not a command the end user would want to run. Ever.
This documentation is meant for people who are studying the
Porcelain-ish scripts and/or are writing new ones.
-The 'git-sh-setup' scriptlet is designed to be sourced (using
+The 'git sh-setup' scriptlet is designed to be sourced (using
`.`) by other shell scripts to set up some variables pointing at
the normal git directories and a few helper shell functions.
diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt
index 42463a9..ecf9e27 100644
--- a/Documentation/git-shortlog.txt
+++ b/Documentation/git-shortlog.txt
@@ -3,7 +3,7 @@ git-shortlog(1)
NAME
----
-git-shortlog - Summarize 'git-log' output
+git-shortlog - Summarize 'git log' output
SYNOPSIS
--------
@@ -13,7 +13,7 @@ git shortlog [-n|--numbered] [-s|--summary] [-e|--email] [-w[<width>[,<indent1>[
DESCRIPTION
-----------
-Summarizes 'git-log' output in a format suitable for inclusion
+Summarizes 'git log' output in a format suitable for inclusion
in release announcements. Each commit will be grouped by author and
the first line of the commit message will be shown.
diff --git a/Documentation/git-show-index.txt b/Documentation/git-show-index.txt
index e3285aa..8382fbe 100644
--- a/Documentation/git-show-index.txt
+++ b/Documentation/git-show-index.txt
@@ -14,10 +14,10 @@ SYNOPSIS
DESCRIPTION
-----------
Reads given idx file for packed git archive created with
-'git-pack-objects' command, and dumps its contents.
+'git pack-objects' command, and dumps its contents.
The information it outputs is subset of what you can get from
-'git-verify-pack -v'; this command only shows the packfile
+'git verify-pack -v'; this command only shows the packfile
offset and SHA1 of each object.
diff --git a/Documentation/git-show-ref.txt b/Documentation/git-show-ref.txt
index 70f400b..df17d49 100644
--- a/Documentation/git-show-ref.txt
+++ b/Documentation/git-show-ref.txt
@@ -72,7 +72,7 @@ OPTIONS
--exclude-existing[=<pattern>]::
- Make 'git-show-ref' act as a filter that reads refs from stdin of the
+ Make 'git show-ref' act as a filter that reads refs from stdin of the
form "^(?:<anything>\s)?<refname>(?:\^\{\})?$" and performs the
following actions on each:
(1) strip "^{}" at the end of line if any;
@@ -135,7 +135,7 @@ When using the '--verify' flag, the command requires an exact path:
will only match the exact branch called "master".
-If nothing matches, 'git-show-ref' will return an error code of 1,
+If nothing matches, 'git show-ref' will return an error code of 1,
and in the case of verification, it will show an error message.
For scripting, you can ask it to be quiet with the "--quiet" flag, which
diff --git a/Documentation/git-show.txt b/Documentation/git-show.txt
index 48b612e..55e687a 100644
--- a/Documentation/git-show.txt
+++ b/Documentation/git-show.txt
@@ -16,16 +16,16 @@ Shows one or more objects (blobs, trees, tags and commits).
For commits it shows the log message and textual diff. It also
presents the merge commit in a special format as produced by
-'git-diff-tree --cc'.
+'git diff-tree --cc'.
For tags, it shows the tag message and the referenced objects.
-For trees, it shows the names (equivalent to 'git-ls-tree'
+For trees, it shows the names (equivalent to 'git ls-tree'
with \--name-only).
For plain blobs, it shows the plain contents.
-The command takes options applicable to the 'git-diff-tree' command to
+The command takes options applicable to the 'git diff-tree' command to
control how the changes the commit introduces are shown.
This manual page describes only the most frequently used options.
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 3f14b72..84e555d 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -20,7 +20,7 @@ SYNOPSIS
DESCRIPTION
-----------
-Use 'git stash' when you want to record the current state of the
+Use `git stash` when you want to record the current state of the
working directory and the index, but want to go back to a clean
working directory. The command saves your local modifications away
and reverts the working directory to match the `HEAD` commit.
@@ -77,7 +77,7 @@ stash@{0}: WIP on submit: 6ebd0e2... Update git-stash documentation
stash@{1}: On master: 9cc0589... Add git-stash
----------------------------------------------------------------
+
-The command takes options applicable to the 'git-log'
+The command takes options applicable to the 'git log'
command to control what is shown and how. See linkgit:git-log[1].
show [<stash>]::
@@ -85,7 +85,7 @@ show [<stash>]::
Show the changes recorded in the stash as a diff between the
stashed state and its original parent. When no `<stash>` is given,
shows the latest one. By default, the command shows the diffstat, but
- it will accept any format known to 'git-diff' (e.g., `git stash show
+ it will accept any format known to 'git diff' (e.g., `git stash show
-p stash@\{1}` to view the second most recent stash in patch form).
pop [--index] [-q|--quiet] [<stash>]::
@@ -201,7 +201,7 @@ $ git reset --soft HEAD^
# ... continue hacking ...
----------------------------------------------------------------
+
-You can use 'git-stash' to simplify the above, like this:
+You can use 'git stash' to simplify the above, like this:
+
----------------------------------------------------------------
# ... hack hack hack ...
diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index b3dfa42..1cab91b 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -17,7 +17,7 @@ current HEAD commit, paths that have differences between the working
tree and the index file, and paths in the working tree that are not
tracked by git (and are not ignored by linkgit:gitignore[5]). The first
are what you _would_ commit by running `git commit`; the second and
-third are what you _could_ commit by running 'git-add' before running
+third are what you _could_ commit by running 'git add' before running
`git commit`.
OPTIONS
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 4ef70c4..63aa694 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -99,11 +99,11 @@ locate the submodule using the relative URL in .gitmodules.
status::
Show the status of the submodules. This will print the SHA-1 of the
currently checked out commit for each submodule, along with the
- submodule path and the output of 'git-describe' for the
+ submodule path and the output of 'git describe' for the
SHA-1. Each SHA-1 will be prefixed with `-` if the submodule is not
initialized and `+` if the currently checked out submodule commit
does not match the SHA-1 found in the index of the containing
- repository. This command is the default command for 'git-submodule'.
+ repository. This command is the default command for 'git submodule'.
+
If '--recursive' is specified, this command will recurse into nested
submodules, and show their status as well.
@@ -114,8 +114,8 @@ init::
The key used in .git/config is `submodule.$name.url`.
This command does not alter existing information in .git/config.
You can then customize the submodule clone URLs in .git/config
- for your local setup and proceed to 'git submodule update';
- you can also just use 'git submodule update --init' without
+ for your local setup and proceed to `git submodule update`;
+ you can also just use `git submodule update --init` without
the explicit 'init' step if you do not intend to customize
any submodule locations.
diff --git a/Documentation/git-symbolic-ref.txt b/Documentation/git-symbolic-ref.txt
index 6392538..33a1536 100644
--- a/Documentation/git-symbolic-ref.txt
+++ b/Documentation/git-symbolic-ref.txt
@@ -49,7 +49,7 @@ cumbersome. On some platforms, `ln -sf` does not even work as
advertised (horrors). Therefore symbolic links are now deprecated
and symbolic refs are used by default.
-'git-symbolic-ref' will exit with status 0 if the contents of the
+'git symbolic-ref' will exit with status 0 if the contents of the
symbolic ref were printed correctly, with status 1 if the requested
name is not a symbolic ref, or 128 if another error occurs.
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 299b04f..31c78a8 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -95,7 +95,7 @@ OPTIONS
CONFIGURATION
-------------
-By default, 'git-tag' in sign-with-default mode (-s) will use your
+By default, 'git tag' in sign-with-default mode (-s) will use your
committer identity (of the form "Your Name <your@email.address>") to
find a key. If you want to use a different default key, you can specify
it in the repository configuration as follows:
@@ -131,12 +131,12 @@ and be done with it.
. The insane thing.
You really want to call the new version "X" too, 'even though'
-others have already seen the old one. So just use 'git-tag -f'
+others have already seen the old one. So just use 'git tag -f'
again, as if you hadn't already published the old one.
However, Git does *not* (and it should not) change tags behind
users back. So if somebody already got the old tag, doing a
-'git-pull' on your tree shouldn't just make them overwrite the old
+'git pull' on your tree shouldn't just make them overwrite the old
one.
If somebody got a release tag from you, you cannot just change
@@ -190,7 +190,7 @@ private anchor point tags from the other person.
You would notice "please pull" messages on the mailing list says
repo URL and branch name alone. This is designed to be easily
-cut&pasted to a 'git-fetch' command line:
+cut&pasted to a 'git fetch' command line:
------------
Linus, please pull from
diff --git a/Documentation/git-tar-tree.txt b/Documentation/git-tar-tree.txt
index a5d9558..3c786bd 100644
--- a/Documentation/git-tar-tree.txt
+++ b/Documentation/git-tar-tree.txt
@@ -12,19 +12,19 @@ SYNOPSIS
DESCRIPTION
-----------
-THIS COMMAND IS DEPRECATED. Use 'git-archive' with `--format=tar`
+THIS COMMAND IS DEPRECATED. Use 'git archive' with `--format=tar`
option instead (and move the <base> argument to `--prefix=base/`).
Creates a tar archive containing the tree structure for the named tree.
When <base> is specified it is added as a leading path to the files in the
generated tar archive.
-'git-tar-tree' behaves differently when given a tree ID versus when given
+'git tar-tree' behaves differently when given a tree ID versus when given
a commit ID or tag ID. In the first case the current time is used as
modification time of each file in the archive. In the latter case the
commit time as recorded in the referenced commit object is used instead.
Additionally the commit ID is stored in a global extended pax header.
-It can be extracted using 'git-get-tar-commit-id'.
+It can be extracted using 'git get-tar-commit-id'.
OPTIONS
-------
diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
index 8d88018..68dc187 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -32,7 +32,7 @@ cleared.
See also linkgit:git-add[1] for a more user-friendly way to do some of
the most common operations on the index.
-The way 'git-update-index' handles files it is told about can be modified
+The way 'git update-index' handles files it is told about can be modified
using the various options:
OPTIONS
@@ -54,7 +54,7 @@ OPTIONS
-q::
Quiet. If --refresh finds that the index needs an update, the
default behavior is to error out. This option makes
- 'git-update-index' continue anyway.
+ 'git update-index' continue anyway.
--ignore-submodules::
Do not try to update submodules. This option is only respected
@@ -62,7 +62,7 @@ OPTIONS
--unmerged::
If --refresh finds unmerged changes in the index, the default
- behavior is to error out. This option makes 'git-update-index'
+ behavior is to error out. This option makes 'git update-index'
continue anyway.
--ignore-missing::
@@ -113,7 +113,7 @@ you will need to handle the situation manually.
-g::
--again::
- Runs 'git-update-index' itself on the paths whose index
+ Runs 'git update-index' itself on the paths whose index
entries are different from those from the `HEAD` commit.
--unresolve::
@@ -131,7 +131,7 @@ you will need to handle the situation manually.
--replace::
By default, when a file `path` exists in the index,
- 'git-update-index' refuses an attempt to add `path/file`.
+ 'git update-index' refuses an attempt to add `path/file`.
Similarly if a file `path/file` exists, a file `path`
cannot be added. With --replace flag, existing entries
that conflict with the entry being added are
@@ -167,7 +167,7 @@ up-to-date for mode/content changes. But what it *does* do is to
can refresh the index for a file that hasn't been changed but where
the stat entry is out of date.
-For example, you'd want to do this after doing a 'git-read-tree', to link
+For example, you'd want to do this after doing a 'git read-tree', to link
up the stat index details with the proper files.
Using --cacheinfo or --info-only
@@ -208,13 +208,13 @@ back on 3-way merge.
. mode SP type SP sha1 TAB path
+
-The second format is to stuff 'git-ls-tree' output
+The second format is to stuff 'git ls-tree' output
into the index file.
. mode SP sha1 SP stage TAB path
+
This format is to put higher order stages into the
-index file and matches 'git-ls-files --stage' output.
+index file and matches 'git ls-files --stage' output.
To place a higher stage entry to the index, the path should
first be removed by feeding a mode=0 entry for the path, and
@@ -271,8 +271,8 @@ option. To unset, use `--no-assume-unchanged`.
The command looks at `core.ignorestat` configuration variable. When
this is true, paths updated with `git update-index paths...` and
paths updated with other git commands that update both index and
-working tree (e.g. 'git-apply --index', 'git-checkout-index -u',
-and 'git-read-tree -u') are automatically marked as "assume
+working tree (e.g. 'git apply --index', 'git checkout-index -u',
+and 'git read-tree -u') are automatically marked as "assume
unchanged". Note that "assume unchanged" bit is *not* set if
`git update-index --refresh` finds the working tree file matches
the index (use `git update-index --really-refresh` if you want
@@ -346,7 +346,7 @@ unreliable, this should be set to 'false' (see linkgit:git-config[1]).
This causes the command to ignore differences in file modes recorded
in the index and the file mode on the filesystem if they differ only on
executable bit. On such an unfortunate filesystem, you may
-need to use 'git-update-index --chmod='.
+need to use 'git update-index --chmod='.
Quite similarly, if `core.symlinks` configuration variable is set
to 'false' (see linkgit:git-config[1]), symbolic links are checked out
diff --git a/Documentation/git-upload-archive.txt b/Documentation/git-upload-archive.txt
index bbd7617..f5f2b39 100644
--- a/Documentation/git-upload-archive.txt
+++ b/Documentation/git-upload-archive.txt
@@ -12,11 +12,11 @@ SYNOPSIS
DESCRIPTION
-----------
-Invoked by 'git-archive --remote' and sends a generated archive to the
+Invoked by 'git archive --remote' and sends a generated archive to the
other end over the git protocol.
This command is usually not invoked directly by the end user. The UI
-for the protocol is on the 'git-archive' side, and the program pair
+for the protocol is on the 'git archive' side, and the program pair
is meant to be used to get an archive from a remote repository.
OPTIONS
diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt
index b8e49dc..71ca4ef 100644
--- a/Documentation/git-upload-pack.txt
+++ b/Documentation/git-upload-pack.txt
@@ -8,17 +8,17 @@ git-upload-pack - Send objects packed back to git-fetch-pack
SYNOPSIS
--------
-'git upload-pack' [--strict] [--timeout=<n>] <directory>
+'git-upload-pack' [--strict] [--timeout=<n>] <directory>
DESCRIPTION
-----------
-Invoked by 'git-fetch-pack', learns what
+Invoked by 'git fetch-pack', learns what
objects the other side is missing, and sends them after packing.
This command is usually not invoked directly by the end user.
-The UI for the protocol is on the 'git-fetch-pack' side, and the
+The UI for the protocol is on the 'git fetch-pack' side, and the
program pair is meant to be used to pull updates from a remote
-repository. For push operations, see 'git-send-pack'.
+repository. For push operations, see 'git send-pack'.
OPTIONS
diff --git a/Documentation/git-var.txt b/Documentation/git-var.txt
index ef6aa81..bb98182 100644
--- a/Documentation/git-var.txt
+++ b/Documentation/git-var.txt
@@ -20,7 +20,7 @@ OPTIONS
Cause the logical variables to be listed. In addition, all the
variables of the git configuration file .git/config are listed
as well. (However, the configuration variables listing functionality
- is deprecated in favor of 'git config -l'.)
+ is deprecated in favor of `git config -l`.)
EXAMPLE
--------
diff --git a/Documentation/git-verify-pack.txt b/Documentation/git-verify-pack.txt
index 97f7f91..916a38a 100644
--- a/Documentation/git-verify-pack.txt
+++ b/Documentation/git-verify-pack.txt
@@ -14,7 +14,7 @@ SYNOPSIS
DESCRIPTION
-----------
Reads given idx file for packed git archive created with the
-'git-pack-objects' command and verifies idx file and the
+'git pack-objects' command and verifies idx file and the
corresponding pack file.
OPTIONS
diff --git a/Documentation/git-verify-tag.txt b/Documentation/git-verify-tag.txt
index 84e70a0..dada212 100644
--- a/Documentation/git-verify-tag.txt
+++ b/Documentation/git-verify-tag.txt
@@ -11,7 +11,7 @@ SYNOPSIS
DESCRIPTION
-----------
-Validates the gpg signature created by 'git-tag'.
+Validates the gpg signature created by 'git tag'.
OPTIONS
-------
diff --git a/Documentation/git-web--browse.txt b/Documentation/git-web--browse.txt
index 278cf73..7572049 100644
--- a/Documentation/git-web--browse.txt
+++ b/Documentation/git-web--browse.txt
@@ -62,7 +62,7 @@ browser.<tool>.path
You can explicitly provide a full path to your preferred browser by
setting the configuration variable 'browser.<tool>.path'. For example,
you can configure the absolute path to firefox by setting
-'browser.firefox.path'. Otherwise, 'git-web--browse' assumes the tool
+'browser.firefox.path'. Otherwise, 'git web--browse' assumes the tool
is available in PATH.
browser.<tool>.cmd
@@ -71,7 +71,7 @@ browser.<tool>.cmd
When the browser, specified by options or configuration variables, is
not among the supported ones, then the corresponding
'browser.<tool>.cmd' configuration variable will be looked up. If this
-variable exists then 'git-web--browse' will treat the specified tool
+variable exists then 'git web--browse' will treat the specified tool
as a custom command and will use a shell eval to run the command with
the URLs passed as arguments.
@@ -113,7 +113,7 @@ See linkgit:git-config[1] for more information about this.
Author
------
Written by Christian Couder <chriscool@tuxfamily.org> and the git-list
-<git@vger.kernel.org>, based on 'git-mergetool' by Theodore Y. Ts'o.
+<git@vger.kernel.org>, based on 'git mergetool' by Theodore Y. Ts'o.
Documentation
-------------
diff --git a/Documentation/git-whatchanged.txt b/Documentation/git-whatchanged.txt
index cadfbd9..ea753cd 100644
--- a/Documentation/git-whatchanged.txt
+++ b/Documentation/git-whatchanged.txt
@@ -13,8 +13,8 @@ SYNOPSIS
DESCRIPTION
-----------
Shows commit logs and diff output each commit introduces. The
-command internally invokes 'git-rev-list' piped to
-'git-diff-tree', and takes command line options for both of
+command internally invokes 'git rev-list' piped to
+'git diff-tree', and takes command line options for both of
these commands.
This manual page describes only the most frequently used options.
diff --git a/Documentation/git-write-tree.txt b/Documentation/git-write-tree.txt
index c8899d5..bfceaca 100644
--- a/Documentation/git-write-tree.txt
+++ b/Documentation/git-write-tree.txt
@@ -17,17 +17,17 @@ tree object is printed to standard output.
The index must be in a fully merged state.
-Conceptually, 'git-write-tree' sync()s the current index contents
+Conceptually, 'git write-tree' sync()s the current index contents
into a set of tree files.
In order to have that match what is actually in your directory right
-now, you need to have done a 'git-update-index' phase before you did the
-'git-write-tree'.
+now, you need to have done a 'git update-index' phase before you did the
+'git write-tree'.
OPTIONS
-------
--missing-ok::
- Normally 'git-write-tree' ensures that the objects referenced by the
+ Normally 'git write-tree' ensures that the objects referenced by the
directory exist in the object database. This option disables this
check.
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 352c230..8c5f5b0 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -43,14 +43,16 @@ unreleased) version of git, that is available from 'master'
branch of the `git.git` repository.
Documentation for older releases are available here:
-* link:v1.6.6/git.html[documentation for release 1.6.6]
+* link:v1.6.6.1/git.html[documentation for release 1.6.6.1]
* release notes for
+ link:RelNotes-1.6.6.1.txt[1.6.6.1],
link:RelNotes-1.6.6.txt[1.6.6].
-* link:v1.6.5.7/git.html[documentation for release 1.6.5.7]
+* link:v1.6.5.8/git.html[documentation for release 1.6.5.8]
* release notes for
+ link:RelNotes-1.6.5.8.txt[1.6.5.8],
link:RelNotes-1.6.5.7.txt[1.6.5.7],
link:RelNotes-1.6.5.6.txt[1.6.5.6],
link:RelNotes-1.6.5.5.txt[1.6.5.5],
@@ -573,8 +575,8 @@ other
linkgit:git-config[1].
'GIT_SSH'::
- If this environment variable is set then 'git-fetch'
- and 'git-push' will use this command instead
+ If this environment variable is set then 'git fetch'
+ and 'git push' will use this command instead
of 'ssh' when they need to connect to a remote system.
The '$GIT_SSH' command will be given exactly two arguments:
the 'username@host' (or just 'host') from the URL and the
@@ -590,8 +592,8 @@ for further details.
'GIT_FLUSH'::
If this environment variable is set to "1", then commands such
- as 'git-blame' (in incremental mode), 'git-rev-list', 'git-log',
- and 'git-whatchanged' will force a flush of the output stream
+ as 'git blame' (in incremental mode), 'git rev-list', 'git log',
+ and 'git whatchanged' will force a flush of the output stream
after each commit-oriented record have been flushed. If this
variable is set to "0", the output of these commands will be done
using completely buffered I/O. If this environment variable is
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index 5a45e51..b396a87 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -88,9 +88,9 @@ Checking-out and checking-in
These attributes affect how the contents stored in the
repository are copied to the working tree files when commands
-such as 'git-checkout' and 'git-merge' run. They also affect how
+such as 'git checkout' and 'git merge' run. They also affect how
git stores the contents you prepare in the working tree in the
-repository upon 'git-add' and 'git-commit'.
+repository upon 'git add' and 'git commit'.
`crlf`
^^^^^^
@@ -148,16 +148,16 @@ an irreversible conversion. The safety triggers to prevent such
a conversion done to the files in the work tree, but there are a
few exceptions. Even though...
-- 'git-add' itself does not touch the files in the work tree, the
+- 'git add' itself does not touch the files in the work tree, the
next checkout would, so the safety triggers;
-- 'git-apply' to update a text file with a patch does touch the files
+- 'git apply' to update a text file with a patch does touch the files
in the work tree, but the operation is about text files and CRLF
conversion is about fixing the line ending inconsistencies, so the
safety does not trigger;
-- 'git-diff' itself does not touch the files in the work tree, it is
- often run to inspect the changes you intend to next 'git-add'. To
+- 'git diff' itself does not touch the files in the work tree, it is
+ often run to inspect the changes you intend to next 'git add'. To
catch potential problems early, safety triggers.
@@ -525,6 +525,23 @@ When left unspecified, the driver itself is used for both
internal merge and the final merge.
+`conflict-marker-size`
+^^^^^^^^^^^^^^^^^^^^^^
+
+This attribute controls the length of conflict markers left in
+the work tree file during a conflicted merge. Only setting to
+the value to a positive integer has any meaningful effect.
+
+For example, this line in `.gitattributes` can be used to tell the merge
+machinery to leave much longer (instead of the usual 7-character-long)
+conflict markers when merging the file `Documentation/git-merge.txt`
+results in a conflict.
+
+------------------------
+Documentation/git-merge.txt conflict-marker-size=32
+------------------------
+
+
Checking whitespace errors
~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/gitcore-tutorial.txt b/Documentation/gitcore-tutorial.txt
index f762dca..f7815e9 100644
--- a/Documentation/gitcore-tutorial.txt
+++ b/Documentation/gitcore-tutorial.txt
@@ -27,6 +27,14 @@ interfaces on top of it called "porcelain". You may not want to use the
plumbing directly very often, but it can be good to know what the
plumbing does for when the porcelain isn't flushing.
+Back when this document was originally written, many porcelain
+commands were shell scripts. For simplicity, it still uses them as
+examples to illustrate how plumbing is fit together to form the
+porcelain commands. The source tree includes some of these scripts in
+contrib/examples/ for reference. Although these are not implemented as
+shell scripts anymore, the description of what the plumbing layer
+commands do is still valid.
+
[NOTE]
Deeper technical details are often marked as Notes, which you can
skip on your first reading.
@@ -44,7 +52,7 @@ to import into git.
For our first example, we're going to start a totally new repository from
scratch, with no pre-existing files, and we'll call it 'git-tutorial'.
To start up, create a subdirectory for it, change into that
-subdirectory, and initialize the git infrastructure with 'git-init':
+subdirectory, and initialize the git infrastructure with 'git init':
------------------------------------------------
$ mkdir git-tutorial
@@ -139,7 +147,7 @@ but to actually check in your hard work, you will have to go through two steps:
- commit that index file as an object.
The first step is trivial: when you want to tell git about any changes
-to your working tree, you use the 'git-update-index' program. That
+to your working tree, you use the 'git update-index' program. That
program normally just takes a list of filenames you want to update, but
to avoid trivial mistakes, it refuses to add new entries to the index
(or remove existing ones) unless you explicitly tell it that you're
@@ -173,14 +181,14 @@ and see two files:
which correspond with the objects with names of `557db...` and
`f24c7...` respectively.
-If you want to, you can use 'git-cat-file' to look at those objects, but
+If you want to, you can use 'git cat-file' to look at those objects, but
you'll have to use the object name, not the filename of the object:
----------------
$ git cat-file -t 557db03de997c86a4a028e1ebd3a1ceb225be238
----------------
-where the `-t` tells 'git-cat-file' to tell you what the "type" of the
+where the `-t` tells 'git cat-file' to tell you what the "type" of the
object is. git will tell you that you have a "blob" object (i.e., just a
regular file), and you can see the contents with
@@ -205,7 +213,7 @@ hexadecimal digits in most places.
Anyway, as we mentioned previously, you normally never actually take a
look at the objects themselves, and typing long 40-character hex
names is not something you'd normally want to do. The above digression
-was just to show that 'git-update-index' did something magical, and
+was just to show that 'git update-index' did something magical, and
actually saved away the contents of your files into the git object
database.
@@ -228,7 +236,7 @@ $ echo "It's a new day for git" >>hello
and you can now, since you told git about the previous state of `hello`, ask
git what has changed in the tree compared to your old index, using the
-'git-diff-files' command:
+'git diff-files' command:
------------
$ git diff-files
@@ -239,7 +247,7 @@ version of a 'diff', but that internal version really just tells you
that it has noticed that "hello" has been modified, and that the old object
contents it had have been replaced with something else.
-To make it readable, we can tell 'git-diff-files' to output the
+To make it readable, we can tell 'git diff-files' to output the
differences as a patch, using the `-p` flag:
------------
@@ -255,7 +263,7 @@ index 557db03..263414f 100644
i.e. the diff of the change we caused by adding another line to `hello`.
-In other words, 'git-diff-files' always shows us the difference between
+In other words, 'git diff-files' always shows us the difference between
what is recorded in the index, and what is currently in the working
tree. That's very useful.
@@ -283,7 +291,7 @@ that in two phases: creating a 'tree' object, and committing that 'tree'
object as a 'commit' object together with an explanation of what the
tree was all about, along with information of how we came to that state.
-Creating a tree object is trivial, and is done with 'git-write-tree'.
+Creating a tree object is trivial, and is done with 'git write-tree'.
There are no options or other input: `git write-tree` will take the
current index state, and write an object that describes that whole
index. In other words, we're now tying together all the different
@@ -307,23 +315,23 @@ is not a "blob" object, but a "tree" object (you can also use
`git cat-file` to actually output the raw object contents, but you'll see
mainly a binary mess, so that's less interesting).
-However -- normally you'd never use 'git-write-tree' on its own, because
+However -- normally you'd never use 'git write-tree' on its own, because
normally you always commit a tree into a commit object using the
-'git-commit-tree' command. In fact, it's easier to not actually use
-'git-write-tree' on its own at all, but to just pass its result in as an
-argument to 'git-commit-tree'.
+'git commit-tree' command. In fact, it's easier to not actually use
+'git write-tree' on its own at all, but to just pass its result in as an
+argument to 'git commit-tree'.
-'git-commit-tree' normally takes several arguments -- it wants to know
+'git commit-tree' normally takes several arguments -- it wants to know
what the 'parent' of a commit was, but since this is the first commit
ever in this new repository, and it has no parents, we only need to pass in
-the object name of the tree. However, 'git-commit-tree' also wants to get a
+the object name of the tree. However, 'git commit-tree' also wants to get a
commit message on its standard input, and it will write out the resulting
object name for the commit to its standard output.
And this is where we create the `.git/refs/heads/master` file
which is pointed at by `HEAD`. This file is supposed to contain
the reference to the top-of-tree of the master branch, and since
-that's exactly what 'git-commit-tree' spits out, we can do this
+that's exactly what 'git commit-tree' spits out, we can do this
all with a sequence of simple shell commands:
------------------------------------------------
@@ -345,11 +353,11 @@ instead, and it would have done the above magic scripting for you.
Making a change
---------------
-Remember how we did the 'git-update-index' on file `hello` and then we
+Remember how we did the 'git update-index' on file `hello` and then we
changed `hello` afterward, and could compare the new state of `hello` with the
state we saved in the index file?
-Further, remember how I said that 'git-write-tree' writes the contents
+Further, remember how I said that 'git write-tree' writes the contents
of the *index* file to the tree, and thus what we just committed was in
fact the *original* contents of the file `hello`, not the new ones. We did
that on purpose, to show the difference between the index state, and the
@@ -360,12 +368,12 @@ As before, if we do `git diff-files -p` in our git-tutorial project,
we'll still see the same difference we saw last time: the index file
hasn't changed by the act of committing anything. However, now that we
have committed something, we can also learn to use a new command:
-'git-diff-index'.
+'git diff-index'.
-Unlike 'git-diff-files', which showed the difference between the index
-file and the working tree, 'git-diff-index' shows the differences
+Unlike 'git diff-files', which showed the difference between the index
+file and the working tree, 'git diff-index' shows the differences
between a committed *tree* and either the index file or the working
-tree. In other words, 'git-diff-index' wants a tree to be diffed
+tree. In other words, 'git diff-index' wants a tree to be diffed
against, and before we did the commit, we couldn't do that, because we
didn't have anything to diff against.
@@ -375,7 +383,7 @@ But now we can do
$ git diff-index -p HEAD
----------------
-(where `-p` has the same meaning as it did in 'git-diff-files'), and it
+(where `-p` has the same meaning as it did in 'git diff-files'), and it
will show us the same difference, but for a totally different reason.
Now we're comparing the working tree not against the index file,
but against the tree we just wrote. It just so happens that those two
@@ -390,7 +398,7 @@ $ git diff HEAD
which ends up doing the above for you.
-In other words, 'git-diff-index' normally compares a tree against the
+In other words, 'git diff-index' normally compares a tree against the
working tree, but when given the `\--cached` flag, it is told to
instead compare against just the index cache contents, and ignore the
current working tree state entirely. Since we just wrote the index
@@ -399,7 +407,7 @@ an empty set of differences, and that's exactly what it does.
[NOTE]
================
-'git-diff-index' really always uses the index for its
+'git diff-index' really always uses the index for its
comparisons, and saying that it compares a tree against the working
tree is thus not strictly accurate. In particular, the list of
files to compare (the "meta-data") *always* comes from the index file,
@@ -428,11 +436,11 @@ $ git update-index hello
(note how we didn't need the `\--add` flag this time, since git knew
about the file already).
-Note what happens to the different 'git-diff-\*' versions here. After
+Note what happens to the different 'git diff-\*' versions here. After
we've updated `hello` in the index, `git diff-files -p` now shows no
differences, but `git diff-index -p HEAD` still *does* show that the
current state is different from the state we committed. In fact, now
-'git-diff-index' shows the same difference whether we use the `--cached`
+'git diff-index' shows the same difference whether we use the `--cached`
flag or not, since now the index is coherent with the working tree.
Now, since we've updated `hello` in the index, we can commit the new
@@ -460,7 +468,7 @@ You've now made your first real git commit. And if you're interested in
looking at what `git commit` really does, feel free to investigate:
it's a few very simple shell scripts to generate the helpful (?) commit
message headers, and a few one-liners that actually do the
-commit itself ('git-commit').
+commit itself ('git commit').
Inspecting Changes
@@ -468,9 +476,9 @@ Inspecting Changes
While creating changes is useful, it's even more useful if you can tell
later what changed. The most useful command for this is another of the
-'diff' family, namely 'git-diff-tree'.
+'diff' family, namely 'git diff-tree'.
-'git-diff-tree' can be given two arbitrary trees, and it will tell you the
+'git diff-tree' can be given two arbitrary trees, and it will tell you the
differences between them. Perhaps even more commonly, though, you can
give it just a single commit object, and it will figure out the parent
of that commit itself, and show the difference directly. Thus, to get
@@ -518,15 +526,15 @@ various diff-\* commands compare things.
+-----------+
============
-More interestingly, you can also give 'git-diff-tree' the `--pretty` flag,
+More interestingly, you can also give 'git diff-tree' the `--pretty` flag,
which tells it to also show the commit message and author and date of the
commit, and you can tell it to show a whole series of diffs.
Alternatively, you can tell it to be "silent", and not show the diffs at
all, but just show the actual commit message.
-In fact, together with the 'git-rev-list' program (which generates a
-list of revisions), 'git-diff-tree' ends up being a veritable fount of
-changes. A trivial (but very useful) script called 'git-whatchanged' is
+In fact, together with the 'git rev-list' program (which generates a
+list of revisions), 'git diff-tree' ends up being a veritable fount of
+changes. A trivial (but very useful) script called 'git whatchanged' is
included with git which does exactly this, and shows a log of recent
activities.
@@ -553,14 +561,14 @@ When using the above two commands, the initial commit will be shown.
If this is a problem because it is huge, you can hide it by setting
the log.showroot configuration variable to false. Having this, you
can still show it for each command just adding the `\--root` option,
-which is a flag for 'git-diff-tree' accepted by both commands.
+which is a flag for 'git diff-tree' accepted by both commands.
With that, you should now be having some inkling of what git does, and
can explore on your own.
[NOTE]
Most likely, you are not directly using the core
-git Plumbing commands, but using Porcelain such as 'git-add', `git-rm'
+git Plumbing commands, but using Porcelain such as 'git add', `git-rm'
and `git-commit'.
@@ -595,7 +603,7 @@ pointer to the state you want to tag, but also a small tag name and
message, along with optionally a PGP signature that says that yes,
you really did
that tag. You create these annotated tags with either the `-a` or
-`-s` flag to 'git-tag':
+`-s` flag to 'git tag':
----------------
$ git tag -s <tagname>
@@ -642,7 +650,7 @@ and it will be gone. There's no external repository, and there's no
history outside the project you created.
- if you want to move or duplicate a git repository, you can do so. There
- is 'git-clone' command, but if all you want to do is just to
+ is 'git clone' command, but if all you want to do is just to
create a copy of your repository (with all the full history that
went along with it), you can do so with a regular
`cp -a git-tutorial new-git-tutorial`.
@@ -666,7 +674,7 @@ When copying a remote repository, you'll want to at a minimum update the
index cache when you do this, and especially with other peoples'
repositories you often want to make sure that the index cache is in some
known state (you don't know *what* they've done and not yet checked in),
-so usually you'll precede the 'git-update-index' with a
+so usually you'll precede the 'git update-index' with a
----------------
$ git read-tree --reset HEAD
@@ -674,7 +682,7 @@ $ git update-index --refresh
----------------
which will force a total index re-build from the tree pointed to by `HEAD`.
-It resets the index contents to `HEAD`, and then the 'git-update-index'
+It resets the index contents to `HEAD`, and then the 'git update-index'
makes sure to match up all index entries with the checked-out files.
If the original repository had uncommitted changes in its
working tree, `git update-index --refresh` notices them and
@@ -689,8 +697,8 @@ $ git reset
and in fact a lot of the common git command combinations can be scripted
with the `git xyz` interfaces. You can learn things by just looking
at what the various git scripts do. For example, `git reset` used to be
-the above two lines implemented in 'git-reset', but some things like
-'git-status' and 'git-commit' are slightly more complex scripts around
+the above two lines implemented in 'git reset', but some things like
+'git status' and 'git commit' are slightly more complex scripts around
the basic git commands.
Many (most?) public remote repositories will not contain any of
@@ -729,7 +737,7 @@ where the `-u` flag means that you want the checkout to keep the index
up-to-date (so that you don't have to refresh it afterward), and the
`-a` flag means "check out all files" (if you have a stale copy or an
older version of a checked out tree you may also need to add the `-f`
-flag first, to tell 'git-checkout-index' to *force* overwriting of any old
+flag first, to tell 'git checkout-index' to *force* overwriting of any old
files).
Again, this can all be simplified with
@@ -776,7 +784,7 @@ to it.
================================================
If you make the decision to start your new branch at some
other point in the history than the current `HEAD`, you can do so by
-just telling 'git-checkout' what the base of the checkout would be.
+just telling 'git checkout' what the base of the checkout would be.
In other words, if you have an earlier tag or branch, you'd just do
------------
@@ -819,7 +827,7 @@ $ git branch <branchname> [startingpoint]
which will simply _create_ the branch, but will not do anything further.
You can then later -- once you decide that you want to actually develop
-on that branch -- switch to that branch with a regular 'git-checkout'
+on that branch -- switch to that branch with a regular 'git checkout'
with the branchname as the argument.
@@ -881,7 +889,7 @@ source.
Anyway, let's exit 'gitk' (`^Q` or the File menu), and decide that we want
to merge the work we did on the `mybranch` branch into the `master`
branch (which is currently our `HEAD` too). To do that, there's a nice
-script called 'git-merge', which wants to know which branches you want
+script called 'git merge', which wants to know which branches you want
to resolve and what the merge is all about:
------------
@@ -925,7 +933,7 @@ $ git commit -i hello
which will very loudly warn you that you're now committing a merge
(which is correct, so never mind), and you can write a small merge
-message about your adventures in 'git-merge'-land.
+message about your adventures in 'git merge'-land.
After you're done, start up `gitk \--all` to see graphically what the
history looks like. Notice that `mybranch` still exists, and you can
@@ -967,21 +975,21 @@ branch head. Please see linkgit:git-rev-parse[1] if you want to
see more complex cases.
[NOTE]
-Without the '--more=1' option, 'git-show-branch' would not output the
+Without the '--more=1' option, 'git show-branch' would not output the
'[master^]' commit, as '[mybranch]' commit is a common ancestor of
both 'master' and 'mybranch' tips. Please see linkgit:git-show-branch[1]
for details.
[NOTE]
If there were more commits on the 'master' branch after the merge, the
-merge commit itself would not be shown by 'git-show-branch' by
+merge commit itself would not be shown by 'git show-branch' by
default. You would need to provide '--sparse' option to make the
merge commit visible in this case.
Now, let's pretend you are the one who did all the work in
`mybranch`, and the fruit of your hard work has finally been merged
to the `master` branch. Let's go back to `mybranch`, and run
-'git-merge' to get the "upstream changes" back to your branch.
+'git merge' to get the "upstream changes" back to your branch.
------------
$ git checkout mybranch
@@ -1023,12 +1031,12 @@ Merging external work
It's usually much more common that you merge with somebody else than
merging with your own branches, so it's worth pointing out that git
makes that very easy too, and in fact, it's not that different from
-doing a 'git-merge'. In fact, a remote merge ends up being nothing
+doing a 'git merge'. In fact, a remote merge ends up being nothing
more than "fetch the work from a remote repository into a temporary tag"
-followed by a 'git-merge'.
+followed by a 'git merge'.
Fetching from a remote repository is done by, unsurprisingly,
-'git-fetch':
+'git fetch':
----------------
$ git fetch <remote-repository>
@@ -1095,7 +1103,7 @@ The 'commit walkers' are sometimes also called 'dumb
transports', because they do not require any git aware smart
server like git Native transport does. Any stock HTTP server
that does not even support directory index would suffice. But
-you must prepare your repository with 'git-update-server-info'
+you must prepare your repository with 'git update-server-info'
to help dumb transport downloaders.
Once you fetch from the remote repository, you `merge` that
@@ -1115,7 +1123,7 @@ argument.
[NOTE]
You could do without using any branches at all, by
keeping as many local repositories as you would like to have
-branches, and merging between them with 'git-pull', just like
+branches, and merging between them with 'git pull', just like
you merge between branches. The advantage of this approach is
that it lets you keep a set of files for each `branch` checked
out and you may find it easier to switch back and forth if you
@@ -1132,7 +1140,7 @@ like this:
$ git config remote.linus.url http://www.kernel.org/pub/scm/git/git.git/
------------------------------------------------
-and use the "linus" keyword with 'git-pull' instead of the full URL.
+and use the "linus" keyword with 'git pull' instead of the full URL.
Examples.
@@ -1168,7 +1176,7 @@ $ git show-branch --more=2 master mybranch
+* [master^] Some fun.
------------
-Remember, before running 'git-merge', our `master` head was at
+Remember, before running 'git merge', our `master` head was at
"Some fun." commit, while our `mybranch` head was at "Some
work." commit.
@@ -1195,7 +1203,7 @@ Now we are ready to experiment with the merge by hand.
`git merge` command, when merging two branches, uses 3-way merge
algorithm. First, it finds the common ancestor between them.
-The command it uses is 'git-merge-base':
+The command it uses is 'git merge-base':
------------
$ mb=$(git merge-base HEAD mybranch)
@@ -1219,7 +1227,7 @@ this:
$ git read-tree -m -u $mb HEAD mybranch
------------
-This is the same 'git-read-tree' command we have already seen,
+This is the same 'git read-tree' command we have already seen,
but it takes three trees, unlike previous examples. This reads
the contents of each tree into different 'stage' in the index
file (the first tree goes to stage 1, the second to stage 2,
@@ -1260,8 +1268,8 @@ $ git ls-files --unmerged
The next step of merging is to merge these three versions of the
file, using 3-way merge. This is done by giving
-'git-merge-one-file' command as one of the arguments to
-'git-merge-index' command:
+'git merge-one-file' command as one of the arguments to
+'git merge-index' command:
------------
$ git merge-index git-merge-one-file hello
@@ -1270,7 +1278,7 @@ ERROR: Merge conflict in hello
fatal: merge program failed
------------
-'git-merge-one-file' script is called with parameters to
+'git merge-one-file' script is called with parameters to
describe those three versions, and is responsible to leave the
merge results in the working tree.
It is a fairly straightforward shell script, and
@@ -1289,9 +1297,9 @@ $ git ls-files --stage
------------
This is the state of the index file and the working file after
-'git-merge' returns control back to you, leaving the conflicting
+'git merge' returns control back to you, leaving the conflicting
merge for you to resolve. Notice that the path `hello` is still
-unmerged, and what you see with 'git-diff' at this point is
+unmerged, and what you see with 'git diff' at this point is
differences since stage 2 (i.e. your version).
@@ -1328,8 +1336,8 @@ into it later. Obviously, this repository creation needs to be
done only once.
[NOTE]
-'git-push' uses a pair of commands,
-'git-send-pack' on your local machine, and 'git-receive-pack'
+'git push' uses a pair of commands,
+'git send-pack' on your local machine, and 'git-receive-pack'
on the remote machine. The communication between the two over
the network internally uses an SSH connection.
@@ -1344,7 +1352,7 @@ $ mkdir my-git.git
------------
Then, make that directory into a git repository by running
-'git-init', but this time, since its name is not the usual
+'git init', but this time, since its name is not the usual
`.git`, we do things slightly differently:
------------
@@ -1407,7 +1415,7 @@ $ git repack
will do it for you. If you followed the tutorial examples, you
would have accumulated about 17 objects in `.git/objects/??/`
-directories by now. 'git-repack' tells you how many objects it
+directories by now. 'git repack' tells you how many objects it
packed, and stores the packed file in `.git/objects/pack`
directory.
@@ -1420,7 +1428,7 @@ them together. The former holds all the data from the objects
in the pack, and the latter holds the index for random
access.
-If you are paranoid, running 'git-verify-pack' command would
+If you are paranoid, running 'git verify-pack' command would
detect if you have a corrupt pack, but do not worry too much.
Our programs are always perfect ;-).
@@ -1487,17 +1495,17 @@ If other people are pulling from your repository over dumb
transport protocols (HTTP), you need to keep this repository
'dumb transport friendly'. After `git init`,
`$GIT_DIR/hooks/post-update.sample` copied from the standard templates
-would contain a call to 'git-update-server-info'
+would contain a call to 'git update-server-info'
but you need to manually enable the hook with
`mv post-update.sample post-update`. This makes sure
-'git-update-server-info' keeps the necessary files up-to-date.
+'git update-server-info' keeps the necessary files up-to-date.
3. Push into the public repository from your primary
repository.
-4. 'git-repack' the public repository. This establishes a big
+4. 'git repack' the public repository. This establishes a big
pack that contains the initial set of objects as the
- baseline, and possibly 'git-prune' if the transport
+ baseline, and possibly 'git prune' if the transport
used for pulling from your repository supports packed
repositories.
@@ -1511,14 +1519,14 @@ You can repack this private repository whenever you feel like.
6. Push your changes to the public repository, and announce it
to the public.
-7. Every once in a while, 'git-repack' the public repository.
+7. Every once in a while, 'git repack' the public repository.
Go back to step 5. and continue working.
A recommended work cycle for a "subsystem maintainer" who works
on that project and has an own "public repository" goes like this:
-1. Prepare your work repository, by 'git-clone' the public
+1. Prepare your work repository, by 'git clone' the public
repository of the "project lead". The URL used for the
initial cloning is stored in the remote.origin.url
configuration variable.
@@ -1533,7 +1541,7 @@ on that project and has an own "public repository" goes like this:
point at the repository you are borrowing from.
4. Push into the public repository from your primary
- repository. Run 'git-repack', and possibly 'git-prune' if the
+ repository. Run 'git repack', and possibly 'git prune' if the
transport used for pulling from your repository supports
packed repositories.
@@ -1550,7 +1558,7 @@ like.
"project lead" and possibly your "sub-subsystem
maintainers" to pull from it.
-7. Every once in a while, 'git-repack' the public repository.
+7. Every once in a while, 'git repack' the public repository.
Go back to step 5. and continue working.
@@ -1558,7 +1566,7 @@ A recommended work cycle for an "individual developer" who does
not have a "public" repository is somewhat different. It goes
like this:
-1. Prepare your work repository, by 'git-clone' the public
+1. Prepare your work repository, by 'git clone' the public
repository of the "project lead" (or a "subsystem
maintainer", if you work on a subsystem). The URL used for
the initial cloning is stored in the remote.origin.url
@@ -1656,8 +1664,8 @@ $ git reset --hard master~2
------------
You can make sure `git show-branch` matches the state before
-those two 'git-merge' you just did. Then, instead of running
-two 'git-merge' commands in a row, you would merge these two
+those two 'git merge' you just did. Then, instead of running
+two 'git merge' commands in a row, you would merge these two
branch heads (this is known as 'making an Octopus'):
------------
diff --git a/Documentation/gitcvs-migration.txt b/Documentation/gitcvs-migration.txt
index 0e49c1c..d861ec4 100644
--- a/Documentation/gitcvs-migration.txt
+++ b/Documentation/gitcvs-migration.txt
@@ -47,25 +47,25 @@ them first before running git pull.
[NOTE]
================================
The 'pull' command knows where to get updates from because of certain
-configuration variables that were set by the first 'git-clone'
+configuration variables that were set by the first 'git clone'
command; see `git config -l` and the linkgit:git-config[1] man
page for details.
================================
You can update the shared repository with your changes by first committing
-your changes, and then using the 'git-push' command:
+your changes, and then using the 'git push' command:
------------------------------------------------
$ git push origin master
------------------------------------------------
to "push" those commits to the shared repository. If someone else has
-updated the repository more recently, 'git-push', like 'cvs commit', will
+updated the repository more recently, 'git push', like 'cvs commit', will
complain, in which case you must pull any changes before attempting the
push again.
-In the 'git-push' command above we specify the name of the remote branch
-to update (`master`). If we leave that out, 'git-push' tries to update
+In the 'git push' command above we specify the name of the remote branch
+to update (`master`). If we leave that out, 'git push' tries to update
any branches in the remote repository that have the same name as a branch
in the local repository. So the last 'push' can be done with either of:
diff --git a/Documentation/gitdiffcore.txt b/Documentation/gitdiffcore.txt
index e8041bc..dcdea54 100644
--- a/Documentation/gitdiffcore.txt
+++ b/Documentation/gitdiffcore.txt
@@ -12,7 +12,7 @@ SYNOPSIS
DESCRIPTION
-----------
-The diff commands 'git-diff-index', 'git-diff-files', and 'git-diff-tree'
+The diff commands 'git diff-index', 'git diff-files', and 'git diff-tree'
can be told to manipulate differences they find in
unconventional ways before showing 'diff' output. The manipulation
is collectively called "diffcore transformation". This short note
@@ -23,18 +23,18 @@ that is easier to understand than the conventional kind.
The chain of operation
----------------------
-The 'git-diff-{asterisk}' family works by first comparing two sets of
+The 'git diff-{asterisk}' family works by first comparing two sets of
files:
- - 'git-diff-index' compares contents of a "tree" object and the
+ - 'git diff-index' compares contents of a "tree" object and the
working directory (when '\--cached' flag is not used) or a
"tree" object and the index file (when '\--cached' flag is
used);
- - 'git-diff-files' compares contents of the index file and the
+ - 'git diff-files' compares contents of the index file and the
working directory;
- - 'git-diff-tree' compares contents of two "tree" objects;
+ - 'git diff-tree' compares contents of two "tree" objects;
In all of these cases, the commands themselves first optionally limit
the two sets of files by any pathspecs given on their command-lines,
@@ -74,12 +74,12 @@ into another list. There are currently 5 such transformations:
- diffcore-pickaxe
- diffcore-order
-These are applied in sequence. The set of filepairs 'git-diff-{asterisk}'
+These are applied in sequence. The set of filepairs 'git diff-{asterisk}'
commands find are used as the input to diffcore-break, and
the output from diffcore-break is used as the input to the
next transformation. The final result is then passed to the
output routine and generates either diff-raw format (see Output
-format sections of the manual for 'git-diff-{asterisk}' commands) or
+format sections of the manual for 'git diff-{asterisk}' commands) or
diff-patch format.
@@ -87,7 +87,7 @@ diffcore-break: For Splitting Up "Complete Rewrites"
----------------------------------------------------
The second transformation in the chain is diffcore-break, and is
-controlled by the -B option to the 'git-diff-{asterisk}' commands. This is
+controlled by the -B option to the 'git diff-{asterisk}' commands. This is
used to detect a filepair that represents "complete rewrite" and
break such filepair into two filepairs that represent delete and
create. E.g. If the input contained this filepair:
@@ -123,7 +123,7 @@ diffcore-rename: For Detection Renames and Copies
This transformation is used to detect renames and copies, and is
controlled by the -M option (to detect renames) and the -C option
-(to detect copies as well) to the 'git-diff-{asterisk}' commands. If the
+(to detect copies as well) to the 'git diff-{asterisk}' commands. If the
input contained these filepairs:
------------------------------------------------
@@ -168,11 +168,11 @@ number after the "-M" or "-C" option (e.g. "-M8" to tell it to use
8/10 = 80%).
Note. When the "-C" option is used with `\--find-copies-harder`
-option, 'git-diff-{asterisk}' commands feed unmodified filepairs to
+option, 'git diff-{asterisk}' commands feed unmodified filepairs to
diffcore mechanism as well as modified ones. This lets the copy
detector consider unmodified files as copy source candidates at
the expense of making it slower. Without `\--find-copies-harder`,
-'git-diff-{asterisk}' commands can detect copies only if the file that was
+'git diff-{asterisk}' commands can detect copies only if the file that was
copied happened to have been modified in the same changeset.
@@ -223,7 +223,7 @@ diffcore-pickaxe: For Detecting Addition/Deletion of Specified String
This transformation is used to find filepairs that represent
changes that touch a specified string, and is controlled by the
--S option and the `\--pickaxe-all` option to the 'git-diff-{asterisk}'
+-S option and the `\--pickaxe-all` option to the 'git diff-{asterisk}'
commands.
When diffcore-pickaxe is in use, it checks if there are
@@ -246,7 +246,7 @@ diffcore-order: For Sorting the Output Based on Filenames
This is used to reorder the filepairs according to the user's
(or project's) taste, and is controlled by the -O option to the
-'git-diff-{asterisk}' commands.
+'git diff-{asterisk}' commands.
This takes a text file each of whose lines is a shell glob
pattern. Filepairs that match a glob pattern on an earlier line
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 29eeae7..87e2c03 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -15,7 +15,7 @@ DESCRIPTION
Hooks are little scripts you can place in `$GIT_DIR/hooks`
directory to trigger action at certain points. When
-'git-init' is run, a handful of example hooks are copied into the
+'git init' is run, a handful of example hooks are copied into the
`hooks` directory of the new repository, but by default they are
all disabled. To enable a hook, rename it by removing its `.sample`
suffix.
@@ -32,10 +32,10 @@ HOOKS
applypatch-msg
~~~~~~~~~~~~~~
-This hook is invoked by 'git-am' script. It takes a single
+This hook is invoked by 'git am' script. It takes a single
parameter, the name of the file that holds the proposed commit
log message. Exiting with non-zero status causes
-'git-am' to abort before applying the patch.
+'git am' to abort before applying the patch.
The hook is allowed to edit the message file in place, and can
be used to normalize the message into some project standard
@@ -48,7 +48,7 @@ The default 'applypatch-msg' hook, when enabled, runs the
pre-applypatch
~~~~~~~~~~~~~~
-This hook is invoked by 'git-am'. It takes no parameter, and is
+This hook is invoked by 'git am'. It takes no parameter, and is
invoked after the patch is applied, but before a commit is made.
If it exits with non-zero status, then the working tree will not be
@@ -63,33 +63,33 @@ The default 'pre-applypatch' hook, when enabled, runs the
post-applypatch
~~~~~~~~~~~~~~~
-This hook is invoked by 'git-am'. It takes no parameter,
+This hook is invoked by 'git am'. It takes no parameter,
and is invoked after the patch is applied and a commit is made.
This hook is meant primarily for notification, and cannot affect
-the outcome of 'git-am'.
+the outcome of 'git am'.
pre-commit
~~~~~~~~~~
-This hook is invoked by 'git-commit', and can be bypassed
+This hook is invoked by 'git commit', and can be bypassed
with `\--no-verify` option. It takes no parameter, and is
invoked before obtaining the proposed commit log message and
making a commit. Exiting with non-zero status from this script
-causes the 'git-commit' to abort.
+causes the 'git commit' to abort.
The default 'pre-commit' hook, when enabled, catches introduction
of lines with trailing whitespaces and aborts the commit when
such a line is found.
-All the 'git-commit' hooks are invoked with the environment
+All the 'git commit' hooks are invoked with the environment
variable `GIT_EDITOR=:` if the command will not bring up an editor
to modify the commit message.
prepare-commit-msg
~~~~~~~~~~~~~~~~~~
-This hook is invoked by 'git-commit' right after preparing the
+This hook is invoked by 'git commit' right after preparing the
default log message, and before the editor is started.
It takes one to three parameters. The first is the name of the file
@@ -101,7 +101,7 @@ commit is a merge or a `.git/MERGE_MSG` file exists); `squash`
(if a `.git/SQUASH_MSG` file exists); or `commit`, followed by
a commit SHA1 (if a `-c`, `-C` or `\--amend` option was given).
-If the exit status is non-zero, 'git-commit' will abort.
+If the exit status is non-zero, 'git commit' will abort.
The purpose of the hook is to edit the message file in place, and
it is not suppressed by the `\--no-verify` option. A non-zero exit
@@ -114,10 +114,10 @@ out the `Conflicts:` part of a merge's commit message.
commit-msg
~~~~~~~~~~
-This hook is invoked by 'git-commit', and can be bypassed
+This hook is invoked by 'git commit', and can be bypassed
with `\--no-verify` option. It takes a single parameter, the
name of the file that holds the proposed commit log message.
-Exiting with non-zero status causes the 'git-commit' to
+Exiting with non-zero status causes the 'git commit' to
abort.
The hook is allowed to edit the message file in place, and can
@@ -131,30 +131,30 @@ The default 'commit-msg' hook, when enabled, detects duplicate
post-commit
~~~~~~~~~~~
-This hook is invoked by 'git-commit'. It takes no
+This hook is invoked by 'git commit'. It takes no
parameter, and is invoked after a commit is made.
This hook is meant primarily for notification, and cannot affect
-the outcome of 'git-commit'.
+the outcome of 'git commit'.
pre-rebase
~~~~~~~~~~
-This hook is called by 'git-rebase' and can be used to prevent a branch
+This hook is called by 'git rebase' and can be used to prevent a branch
from getting rebased.
post-checkout
~~~~~~~~~~~~~
-This hook is invoked when a 'git-checkout' is run after having updated the
+This hook is invoked when a 'git checkout' is run after having updated the
worktree. The hook is given three parameters: the ref of the previous HEAD,
the ref of the new HEAD (which may or may not have changed), and a flag
indicating whether the checkout was a branch checkout (changing branches,
flag=1) or a file checkout (retrieving a file from the index, flag=0).
-This hook cannot affect the outcome of 'git-checkout'.
+This hook cannot affect the outcome of 'git checkout'.
-It is also run after 'git-clone', unless the --no-checkout (-n) option is
+It is also run after 'git clone', unless the --no-checkout (-n) option is
used. The first parameter given to the hook is the null-ref, the second the
ref of the new HEAD and the flag is always 1.
@@ -165,10 +165,10 @@ properties.
post-merge
~~~~~~~~~~
-This hook is invoked by 'git-merge', which happens when a 'git-pull'
+This hook is invoked by 'git merge', which happens when a 'git pull'
is done on a local repository. The hook takes a single parameter, a status
flag specifying whether or not the merge being done was a squash merge.
-This hook cannot affect the outcome of 'git-merge' and is not executed,
+This hook cannot affect the outcome of 'git merge' and is not executed,
if the merge failed due to conflicts.
This hook can be used in conjunction with a corresponding pre-commit hook to
@@ -181,7 +181,7 @@ pre-receive
~~~~~~~~~~~
This hook is invoked by 'git-receive-pack' on the remote repository,
-which happens when a 'git-push' is done on a local repository.
+which happens when a 'git push' is done on a local repository.
Just before starting to update refs on the remote repository, the
pre-receive hook is invoked. Its exit status determines the success
or failure of the update.
@@ -202,7 +202,7 @@ updated. If the hook exits with zero, updating of individual refs can
still be prevented by the <<update,'update'>> hook.
Both standard output and standard error output are forwarded to
-'git-send-pack' on the other end, so you can simply `echo` messages
+'git send-pack' on the other end, so you can simply `echo` messages
for the user.
[[update]]
@@ -210,7 +210,7 @@ update
~~~~~~
This hook is invoked by 'git-receive-pack' on the remote repository,
-which happens when a 'git-push' is done on a local repository.
+which happens when a 'git push' is done on a local repository.
Just before updating the ref on the remote repository, the update hook
is invoked. Its exit status determines the success or failure of
the ref update.
@@ -241,7 +241,7 @@ implement access control which is finer grained than the one
based on filesystem group.
Both standard output and standard error output are forwarded to
-'git-send-pack' on the other end, so you can simply `echo` messages
+'git send-pack' on the other end, so you can simply `echo` messages
for the user.
The default 'update' hook, when enabled--and with
@@ -253,7 +253,7 @@ post-receive
~~~~~~~~~~~~
This hook is invoked by 'git-receive-pack' on the remote repository,
-which happens when a 'git-push' is done on a local repository.
+which happens when a 'git push' is done on a local repository.
It executes on the remote repository once after all the refs have
been updated.
@@ -270,7 +270,7 @@ both old and new values of all the refs in addition to their
names.
Both standard output and standard error output are forwarded to
-'git-send-pack' on the other end, so you can simply `echo` messages
+'git send-pack' on the other end, so you can simply `echo` messages
for the user.
The default 'post-receive' hook is empty, but there is
@@ -283,7 +283,7 @@ post-update
~~~~~~~~~~~
This hook is invoked by 'git-receive-pack' on the remote repository,
-which happens when a 'git-push' is done on a local repository.
+which happens when a 'git push' is done on a local repository.
It executes on the remote repository once after all the refs have
been updated.
@@ -301,20 +301,20 @@ updated values of the refs. You might consider it instead if you need
them.
When enabled, the default 'post-update' hook runs
-'git-update-server-info' to keep the information used by dumb
+'git update-server-info' to keep the information used by dumb
transports (e.g., HTTP) up-to-date. If you are publishing
a git repository that is accessible via HTTP, you should
probably enable this hook.
Both standard output and standard error output are forwarded to
-'git-send-pack' on the other end, so you can simply `echo` messages
+'git send-pack' on the other end, so you can simply `echo` messages
for the user.
pre-auto-gc
~~~~~~~~~~~
-This hook is invoked by 'git-gc --auto'. It takes no parameter, and
-exiting with non-zero status from this script causes the 'git-gc --auto'
+This hook is invoked by 'git gc --auto'. It takes no parameter, and
+exiting with non-zero status from this script causes the 'git gc --auto'
to abort.
GIT
diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt
index 7df3cef..98c459d 100644
--- a/Documentation/gitignore.txt
+++ b/Documentation/gitignore.txt
@@ -56,10 +56,10 @@ the user's editor of choice) generally go into a file specified by
`core.excludesfile` in the user's `~/.gitconfig`.
The underlying git plumbing tools, such as
-'git-ls-files' and 'git-read-tree', read
+'git ls-files' and 'git read-tree', read
`gitignore` patterns specified by command-line options, or from
files specified by command-line options. Higher-level git
-tools, such as 'git-status' and 'git-add',
+tools, such as 'git status' and 'git add',
use patterns from the sources specified above.
Patterns have the following format:
diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt
index cf465cb..99baa24 100644
--- a/Documentation/gitk.txt
+++ b/Documentation/gitk.txt
@@ -22,7 +22,7 @@ git repository.
OPTIONS
-------
To control which revisions to show, the command takes options applicable to
-the 'git-rev-list' command (see linkgit:git-rev-list[1]).
+the 'git rev-list' command (see linkgit:git-rev-list[1]).
This manual page describes only the most
frequently used options.
diff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt
index 1befca9..3cd32d6 100644
--- a/Documentation/gitrepository-layout.txt
+++ b/Documentation/gitrepository-layout.txt
@@ -64,7 +64,7 @@ objects/info/packs::
are available in this object store. Whenever a pack is
added or removed, `git update-server-info` should be run
to keep this file up-to-date if the repository is
- published for dumb transports. 'git-repack' does this
+ published for dumb transports. 'git repack' does this
by default.
objects/info/alternates::
@@ -85,7 +85,7 @@ objects/info/http-alternates::
refs::
References are stored in subdirectories of this
- directory. The 'git-prune' command knows to keep
+ directory. The 'git prune' command knows to keep
objects reachable from refs found in this directory and
its subdirectories.
@@ -125,7 +125,7 @@ details.
branches::
A slightly deprecated way to store shorthands to be used
- to specify URL to 'git-fetch', 'git-pull' and 'git-push'
+ to specify URL to 'git fetch', 'git pull' and 'git push'
commands is to store a file in `branches/<name>` and
give 'name' to these commands in place of 'repository'
argument.
@@ -133,7 +133,7 @@ branches::
hooks::
Hooks are customization scripts used by various git
commands. A handful of sample hooks are installed when
- 'git-init' is run, but all of them are disabled by
+ 'git init' is run, but all of them are disabled by
default. To enable, the `.sample` suffix has to be
removed from the filename by renaming.
Read linkgit:githooks[5] for more details about
@@ -151,10 +151,10 @@ info/refs::
This file helps dumb transports discover what refs are
available in this repository. If the repository is
published for dumb transports, this file should be
- regenerated by 'git-update-server-info' every time a tag
+ regenerated by 'git update-server-info' every time a tag
or branch is created or modified. This is normally done
from the `hooks/update` hook, which is run by the
- 'git-receive-pack' command when you 'git-push' into the
+ 'git-receive-pack' command when you 'git push' into the
repository.
info/grafts::
@@ -168,14 +168,14 @@ info/grafts::
info/exclude::
This file, by convention among Porcelains, stores the
exclude pattern list. `.gitignore` is the per-directory
- ignore file. 'git-status', 'git-add', 'git-rm' and
- 'git-clean' look at it but the core git commands do not look
+ ignore file. 'git status', 'git add', 'git rm' and
+ 'git clean' look at it but the core git commands do not look
at it. See also: linkgit:gitignore[5].
remotes::
Stores shorthands to be used to give URL and default
refnames to interact with remote repository to
- 'git-fetch', 'git-pull' and 'git-push' commands.
+ 'git fetch', 'git pull' and 'git push' commands.
logs::
Records of changes made to refs are stored in this
diff --git a/Documentation/gittutorial-2.txt b/Documentation/gittutorial-2.txt
index dc8fc3a..ecab0c0 100644
--- a/Documentation/gittutorial-2.txt
+++ b/Documentation/gittutorial-2.txt
@@ -260,7 +260,7 @@ index a042389..513feba 100644
+hello world, again
------------------------------------------------
-So 'git-diff' is comparing against something other than the head.
+So 'git diff' is comparing against something other than the head.
The thing that it's comparing against is actually the index file,
which is stored in .git/index in a binary format, but whose contents
we can examine with ls-files:
@@ -275,9 +275,9 @@ hello world!
hello world, again
------------------------------------------------
-So what our 'git-add' did was store a new blob and then put
+So what our 'git add' did was store a new blob and then put
a reference to it in the index file. If we modify the file again,
-we'll see that the new modifications are reflected in the 'git-diff'
+we'll see that the new modifications are reflected in the 'git diff'
output:
------------------------------------------------
@@ -292,7 +292,7 @@ index 513feba..ba3da7b 100644
+again?
------------------------------------------------
-With the right arguments, 'git-diff' can also show us the difference
+With the right arguments, 'git diff' can also show us the difference
between the working directory and the last commit, or between the
index and the last commit:
@@ -316,7 +316,7 @@ index a042389..513feba 100644
+hello world, again
------------------------------------------------
-At any time, we can create a new commit using 'git-commit' (without
+At any time, we can create a new commit using 'git commit' (without
the "-a" option), and verify that the state committed only includes the
changes stored in the index file, not the additional change that is
still only in our working tree:
@@ -334,11 +334,11 @@ index 513feba..ba3da7b 100644
+again?
------------------------------------------------
-So by default 'git-commit' uses the index to create the commit, not
+So by default 'git commit' uses the index to create the commit, not
the working tree; the "-a" option to commit tells it to first update
the index with all changes in the working tree.
-Finally, it's worth looking at the effect of 'git-add' on the index
+Finally, it's worth looking at the effect of 'git add' on the index
file:
------------------------------------------------
@@ -346,7 +346,7 @@ $ echo "goodbye, world" >closing.txt
$ git add closing.txt
------------------------------------------------
-The effect of the 'git-add' was to add one entry to the index file:
+The effect of the 'git add' was to add one entry to the index file:
------------------------------------------------
$ git ls-files --stage
diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt
index cf0689c..1c16066 100644
--- a/Documentation/gittutorial.txt
+++ b/Documentation/gittutorial.txt
@@ -67,7 +67,7 @@ You've now initialized the working directory--you may notice a new
directory created, named ".git".
Next, tell git to take a snapshot of the contents of all files under the
-current directory (note the '.'), with 'git-add':
+current directory (note the '.'), with 'git add':
------------------------------------------------
$ git add .
@@ -75,7 +75,7 @@ $ git add .
This snapshot is now stored in a temporary staging area which git calls
the "index". You can permanently store the contents of the index in the
-repository with 'git-commit':
+repository with 'git commit':
------------------------------------------------
$ git commit
@@ -94,15 +94,15 @@ $ git add file1 file2 file3
------------------------------------------------
You are now ready to commit. You can see what is about to be committed
-using 'git-diff' with the --cached option:
+using 'git diff' with the --cached option:
------------------------------------------------
$ git diff --cached
------------------------------------------------
-(Without --cached, 'git-diff' will show you any changes that
+(Without --cached, 'git diff' will show you any changes that
you've made but not yet added to the index.) You can also get a brief
-summary of the situation with 'git-status':
+summary of the situation with 'git status':
------------------------------------------------
$ git status
@@ -126,7 +126,7 @@ $ git commit
This will again prompt you for a message describing the change, and then
record a new version of the project.
-Alternatively, instead of running 'git-add' beforehand, you can use
+Alternatively, instead of running 'git add' beforehand, you can use
------------------------------------------------
$ git commit -a
@@ -147,7 +147,7 @@ Git tracks content not files
Many revision control systems provide an `add` command that tells the
system to start tracking changes to a new file. Git's `add` command
-does something simpler and more powerful: 'git-add' is used both for new
+does something simpler and more powerful: 'git add' is used both for new
and newly modified files, and in both cases it takes a snapshot of the
given files and stages that content in the index, ready for inclusion in
the next commit.
@@ -376,7 +376,7 @@ alice$ git remote add bob /home/bob/myrepo
------------------------------------------------
With this, Alice can perform the first part of the "pull" operation
-alone using the 'git-fetch' command without merging them with her own
+alone using the 'git fetch' command without merging them with her own
branch, using:
-------------------------------------
@@ -384,7 +384,7 @@ alice$ git fetch bob
-------------------------------------
Unlike the longhand form, when Alice fetches from Bob using a
-remote repository shorthand set up with 'git-remote', what was
+remote repository shorthand set up with 'git remote', what was
fetched is stored in a remote tracking branch, in this case
`bob/master`. So after this:
@@ -428,7 +428,7 @@ bob$ git config --get remote.origin.url
/home/alice/project
-------------------------------------
-(The complete configuration created by 'git-clone' is visible using
+(The complete configuration created by 'git clone' is visible using
`git config -l`, and the linkgit:git-config[1] man page
explains the meaning of each option.)
@@ -458,7 +458,7 @@ Exploring history
-----------------
Git history is represented as a series of interrelated commits. We
-have already seen that the 'git-log' command can list those commits.
+have already seen that the 'git log' command can list those commits.
Note that first line of each git log entry also gives a name for the
commit:
@@ -471,7 +471,7 @@ Date: Tue May 16 17:18:22 2006 -0700
merge-base: Clarify the comments on post processing.
-------------------------------------
-We can give this name to 'git-show' to see the details about this
+We can give this name to 'git show' to see the details about this
commit.
-------------------------------------
@@ -529,13 +529,13 @@ $ git reset --hard HEAD^ # reset your current branch and working
Be careful with that last command: in addition to losing any changes
in the working directory, it will also remove all later commits from
this branch. If this branch is the only branch containing those
-commits, they will be lost. Also, don't use 'git-reset' on a
+commits, they will be lost. Also, don't use 'git reset' on a
publicly-visible branch that other developers pull from, as it will
force needless merges on other developers to clean up the history.
-If you need to undo changes that you have pushed, use 'git-revert'
+If you need to undo changes that you have pushed, use 'git revert'
instead.
-The 'git-grep' command can search for strings in any version of your
+The 'git grep' command can search for strings in any version of your
project, so
-------------------------------------
@@ -544,7 +544,7 @@ $ git grep "hello" v2.5
searches for all occurrences of "hello" in v2.5.
-If you leave out the commit name, 'git-grep' will search any of the
+If you leave out the commit name, 'git grep' will search any of the
files it manages in your current directory. So
-------------------------------------
@@ -554,7 +554,7 @@ $ git grep "hello"
is a quick way to search just the files that are tracked by git.
Many git commands also take sets of commits, which can be specified
-in a number of ways. Here are some examples with 'git-log':
+in a number of ways. Here are some examples with 'git log':
-------------------------------------
$ git log v2.5..v2.6 # commits between v2.5 and v2.6
@@ -564,7 +564,7 @@ $ git log v2.5.. Makefile # commits since v2.5 which modify
# Makefile
-------------------------------------
-You can also give 'git-log' a "range" of commits where the first is not
+You can also give 'git log' a "range" of commits where the first is not
necessarily an ancestor of the second; for example, if the tips of
the branches "stable" and "master" diverged from a common
commit some time ago, then
@@ -583,9 +583,9 @@ $ git log master..stable
will show the list of commits made on the stable branch but not
the master branch.
-The 'git-log' command has a weakness: it must present commits in a
+The 'git log' command has a weakness: it must present commits in a
list. When the history has lines of development that diverged and
-then merged back together, the order in which 'git-log' presents
+then merged back together, the order in which 'git log' presents
those commits is meaningless.
Most projects with multiple contributors (such as the Linux kernel,
@@ -609,7 +609,7 @@ of the file:
$ git diff v2.5:Makefile HEAD:Makefile.in
-------------------------------------
-You can also use 'git-show' to see any such file:
+You can also use 'git show' to see any such file:
-------------------------------------
$ git show v2.5:Makefile
diff --git a/Documentation/gitworkflows.txt b/Documentation/gitworkflows.txt
index 065441d..1ef55ff 100644
--- a/Documentation/gitworkflows.txt
+++ b/Documentation/gitworkflows.txt
@@ -360,7 +360,7 @@ There are three main tools that can be used for this:
* linkgit:git-pull[1] that does fetch and merge in one go.
-Note the last point. Do 'not' use 'git-pull' unless you actually want
+Note the last point. Do 'not' use 'git pull' unless you actually want
to merge the remote branch.
Getting changes out is easy:
@@ -397,7 +397,7 @@ Please pull from
<url> <branch>
-------------------------------------
-In that case, 'git-pull' can do the fetch and merge in one go, as
+In that case, 'git pull' can do the fetch and merge in one go, as
follows.
.Push/pull: Merging remote topics
@@ -449,7 +449,7 @@ problem.
If you receive such a patch series (as maintainer, or perhaps as a
reader of the mailing list it was sent to), save the mails to files,
-create a new topic branch and use 'git-am' to import the commits:
+create a new topic branch and use 'git am' to import the commits:
.format-patch/am: Importing patches
[caption="Recipe: "]
diff --git a/Documentation/i18n.txt b/Documentation/i18n.txt
index 708da6c..625d315 100644
--- a/Documentation/i18n.txt
+++ b/Documentation/i18n.txt
@@ -21,7 +21,7 @@ project find it more convenient to use legacy encodings, git
does not forbid it. However, there are a few things to keep in
mind.
-. 'git-commit' and 'git-commit-tree' issues
+. 'git commit' and 'git commit-tree' issues
a warning if the commit log message given to it does not look
like a valid UTF-8 string, unless you explicitly say your
project uses a legacy encoding. The way to say this is to
@@ -37,7 +37,7 @@ of `i18n.commitencoding` in its `encoding` header. This is to
help other people who look at them later. Lack of this header
implies that the commit log message is encoded in UTF-8.
-. 'git-log', 'git-show', 'git-blame' and friends look at the
+. 'git log', 'git show', 'git blame' and friends look at the
`encoding` header of a commit object, and try to re-code the
log message into UTF-8 unless otherwise specified. You can
specify the desired output encoding with
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index fec3394..3b83dba 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -59,8 +59,8 @@ option can be used to override --squash.
Use the given merge strategy; can be supplied more than
once to specify them in the order they should be tried.
If there is no `-s` option, a built-in list of strategies
- is used instead ('git-merge-recursive' when merging a single
- head, 'git-merge-octopus' otherwise).
+ is used instead ('git merge-recursive' when merging a single
+ head, 'git merge-octopus' otherwise).
--summary::
--no-summary::
@@ -74,3 +74,8 @@ option can be used to override --squash.
-v::
--verbose::
Be verbose.
+
+-X <option>::
+--strategy-option=<option>::
+ Pass merge strategy specific option through to the merge
+ strategy.
diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt
index 42910a3..a5bc1db 100644
--- a/Documentation/merge-strategies.txt
+++ b/Documentation/merge-strategies.txt
@@ -1,6 +1,11 @@
MERGE STRATEGIES
----------------
+The merge mechanism ('git-merge' and 'git-pull' commands) allows the
+backend 'merge strategies' to be chosen with `-s` option. Some strategies
+can also take their own options, which can be passed by giving `-X<option>`
+arguments to 'git-merge' and/or 'git-pull'.
+
resolve::
This can only resolve two heads (i.e. the current branch
and another branch you pulled from) using a 3-way merge
@@ -20,6 +25,27 @@ recursive::
Additionally this can detect and handle merges involving
renames. This is the default merge strategy when
pulling or merging one branch.
++
+The 'recursive' strategy can take the following options:
+
+ours;;
+ This option forces conflicting hunks to be auto-resolved cleanly by
+ favoring 'our' version. Changes from the other tree that do not
+ conflict with our side are reflected to the merge result.
++
+This should not be confused with the 'ours' merge strategy, which does not
+even look at what the other tree contains at all. It discards everything
+the other tree did, declaring 'our' history contains all that happened in it.
+
+theirs;;
+ This is opposite of 'ours'.
+
+subtree[=path];;
+ This option is a more advanced form of 'subtree' strategy, where
+ the strategy makes a guess on how two trees must be shifted to
+ match with each other when merging. Instead, the specified path
+ is prefixed (or stripped from the beginning) to make the shape of
+ two trees to match.
octopus::
This resolves cases with more than two heads, but refuses to do
@@ -33,7 +59,8 @@ ours::
merge is always that of the current branch head, effectively
ignoring all changes from all other branches. It is meant to
be used to supersede old development history of side
- branches.
+ branches. Note that this is different from the -Xours option to
+ the 'recursive' merge strategy.
subtree::
This is a modified recursive strategy. When merging trees A and
diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 53a9168..1686a54 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -134,6 +134,7 @@ The placeholders are:
- '%C(...)': color specification, as described in color.branch.* config option
- '%m': left, right or boundary mark
- '%n': newline
+- '%%': a raw '%'
- '%x00': print a byte from a hex code
- '%w([<w>[,<i1>[,<i2>]]])': switch line wrapping, like the -w option of
linkgit:git-shortlog[1].
diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt
index bff9499..aa96cae 100644
--- a/Documentation/pretty-options.txt
+++ b/Documentation/pretty-options.txt
@@ -28,3 +28,11 @@ people using 80-column terminals.
command to re-code the commit log message in the encoding
preferred by the user. For non plumbing commands this
defaults to UTF-8.
+
+--no-notes::
+--show-notes::
+ Show the notes (see linkgit:git-notes[1]) that annotate the
+ commit, when showing the commit log message. This is the default
+ for `git log`, `git show` and `git whatchanged` commands when
+ there is no `--pretty`, `--format` nor `--oneline` option is
+ given on the command line.
diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt
index 0551ebd..5dd6e5a 100644
--- a/Documentation/pull-fetch-param.txt
+++ b/Documentation/pull-fetch-param.txt
@@ -38,7 +38,7 @@ must know this is the expected usage pattern for a branch.
[NOTE]
You never do your own development on branches that appear
on the right hand side of a <refspec> colon on `Pull:` lines;
-they are to be updated by 'git-fetch'. If you intend to do
+they are to be updated by 'git fetch'. If you intend to do
development derived from a remote branch `B`, have a `Pull:`
line to track it (i.e. `Pull: B:remote-B`), and have a separate
branch `my-B` to do your development on top of it. The latter
@@ -50,13 +50,13 @@ on the remote branch, merge it into your development branch with
+
[NOTE]
There is a difference between listing multiple <refspec>
-directly on 'git-pull' command line and having multiple
+directly on 'git pull' command line and having multiple
`Pull:` <refspec> lines for a <repository> and running
-'git-pull' command without any explicit <refspec> parameters.
+'git pull' command without any explicit <refspec> parameters.
<refspec> listed explicitly on the command line are always
merged into the current branch after fetching. In other words,
if you list more than one remote refs, you would be making
-an Octopus. While 'git-pull' run without any explicit <refspec>
+an Octopus. While 'git pull' run without any explicit <refspec>
parameter takes default <refspec>s from `Pull:` lines, it
merges only the first <refspec> found into the current branch,
after fetching all the remote refs. This is because making an
diff --git a/Documentation/technical/api-strbuf.txt b/Documentation/technical/api-strbuf.txt
index a0e0f85..afe2759 100644
--- a/Documentation/technical/api-strbuf.txt
+++ b/Documentation/technical/api-strbuf.txt
@@ -199,6 +199,10 @@ character if the letter `n` appears after a `%`. The function returns
the length of the placeholder recognized and `strbuf_expand()` skips
over it.
+
+The format `%%` is automatically expanded to a single `%` as a quoting
+mechanism; callers do not need to handle the `%` placeholder themselves,
+and the callback function will not be invoked for this placeholder.
++
All other characters (non-percent and not skipped ones) are copied
verbatim to the strbuf. If the callback returned zero, meaning that the
placeholder is unknown, then the percent sign is copied, too.
@@ -214,6 +218,13 @@ which can be used by the programmer of the callback as she sees fit.
placeholder and replacement string. The array needs to be
terminated by an entry with placeholder set to NULL.
+`strbuf_addbuf_percentquote`::
+
+ Append the contents of one strbuf to another, quoting any
+ percent signs ("%") into double-percents ("%%") in the
+ destination. This is useful for literal data to be fed to either
+ strbuf_expand or to the *printf family of functions.
+
`strbuf_addf`::
Add a formatted string to the buffer.
diff --git a/Documentation/urls-remotes.txt b/Documentation/urls-remotes.txt
index 2a0e7b8..00f7e79 100644
--- a/Documentation/urls-remotes.txt
+++ b/Documentation/urls-remotes.txt
@@ -52,8 +52,8 @@ following format:
------------
-`Push:` lines are used by 'git-push' and
-`Pull:` lines are used by 'git-pull' and 'git-fetch'.
+`Push:` lines are used by 'git push' and
+`Pull:` lines are used by 'git pull' and 'git fetch'.
Multiple `Push:` and `Pull:` lines may
be specified for additional branch mappings.
diff --git a/Makefile b/Makefile
index b7f56b7..1f95f93 100644
--- a/Makefile
+++ b/Makefile
@@ -187,10 +187,6 @@ all::
# is a simplified version of the merge sort used in glibc. This is
# recommended if Git triggers O(n^2) behavior in your platform's qsort().
#
-# Define NO_EXTERNAL_GREP if you don't want "git grep" to ever call
-# your external grep (e.g., if your system lacks grep, if its grep is
-# broken, or spawning external process is slower than built-in grep git has).
-#
# Define UNRELIABLE_FSTAT if your system's fstat does not return the same
# information on a not yet closed file that lstat would return for the same
# file after it was closed.
@@ -357,7 +353,6 @@ SCRIPT_SH += git-merge-one-file.sh
SCRIPT_SH += git-merge-resolve.sh
SCRIPT_SH += git-mergetool.sh
SCRIPT_SH += git-mergetool--lib.sh
-SCRIPT_SH += git-notes.sh
SCRIPT_SH += git-parse-remote.sh
SCRIPT_SH += git-pull.sh
SCRIPT_SH += git-quiltimport.sh
@@ -391,19 +386,10 @@ EXTRA_PROGRAMS =
# ... and all the rest that could be moved out of bindir to gitexecdir
PROGRAMS += $(EXTRA_PROGRAMS)
PROGRAMS += git-fast-import$X
-PROGRAMS += git-hash-object$X
PROGRAMS += git-imap-send$X
-PROGRAMS += git-index-pack$X
-PROGRAMS += git-merge-index$X
-PROGRAMS += git-merge-tree$X
-PROGRAMS += git-mktag$X
-PROGRAMS += git-pack-redundant$X
-PROGRAMS += git-patch-id$X
PROGRAMS += git-shell$X
PROGRAMS += git-show-index$X
-PROGRAMS += git-unpack-file$X
PROGRAMS += git-upload-pack$X
-PROGRAMS += git-var$X
PROGRAMS += git-http-backend$X
# List built-in command $C whose implementation cmd_$C() is not in
@@ -501,6 +487,7 @@ LIB_H += reflog-walk.h
LIB_H += refs.h
LIB_H += remote.h
LIB_H += rerere.h
+LIB_H += resolve-undo.h
LIB_H += revision.h
LIB_H += run-command.h
LIB_H += sha1-lookup.h
@@ -562,6 +549,7 @@ LIB_OBJS += graph.o
LIB_OBJS += grep.o
LIB_OBJS += hash.o
LIB_OBJS += help.o
+LIB_OBJS += hex.o
LIB_OBJS += ident.o
LIB_OBJS += levenshtein.o
LIB_OBJS += list-objects.o
@@ -596,6 +584,7 @@ LIB_OBJS += refs.o
LIB_OBJS += remote.o
LIB_OBJS += replace_object.o
LIB_OBJS += rerere.o
+LIB_OBJS += resolve-undo.o
LIB_OBJS += revision.o
LIB_OBJS += run-command.o
LIB_OBJS += server-info.o
@@ -660,7 +649,9 @@ BUILTIN_OBJS += builtin-for-each-ref.o
BUILTIN_OBJS += builtin-fsck.o
BUILTIN_OBJS += builtin-gc.o
BUILTIN_OBJS += builtin-grep.o
+BUILTIN_OBJS += builtin-hash-object.o
BUILTIN_OBJS += builtin-help.o
+BUILTIN_OBJS += builtin-index-pack.o
BUILTIN_OBJS += builtin-init-db.o
BUILTIN_OBJS += builtin-log.o
BUILTIN_OBJS += builtin-ls-files.o
@@ -671,13 +662,19 @@ BUILTIN_OBJS += builtin-mailsplit.o
BUILTIN_OBJS += builtin-merge.o
BUILTIN_OBJS += builtin-merge-base.o
BUILTIN_OBJS += builtin-merge-file.o
+BUILTIN_OBJS += builtin-merge-index.o
BUILTIN_OBJS += builtin-merge-ours.o
BUILTIN_OBJS += builtin-merge-recursive.o
+BUILTIN_OBJS += builtin-merge-tree.o
+BUILTIN_OBJS += builtin-mktag.o
BUILTIN_OBJS += builtin-mktree.o
BUILTIN_OBJS += builtin-mv.o
BUILTIN_OBJS += builtin-name-rev.o
+BUILTIN_OBJS += builtin-notes.o
BUILTIN_OBJS += builtin-pack-objects.o
+BUILTIN_OBJS += builtin-pack-redundant.o
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-push.o
@@ -700,11 +697,13 @@ BUILTIN_OBJS += builtin-stripspace.o
BUILTIN_OBJS += builtin-symbolic-ref.o
BUILTIN_OBJS += builtin-tag.o
BUILTIN_OBJS += builtin-tar-tree.o
+BUILTIN_OBJS += builtin-unpack-file.o
BUILTIN_OBJS += builtin-unpack-objects.o
BUILTIN_OBJS += builtin-update-index.o
BUILTIN_OBJS += builtin-update-ref.o
BUILTIN_OBJS += builtin-update-server-info.o
BUILTIN_OBJS += builtin-upload-archive.o
+BUILTIN_OBJS += builtin-var.o
BUILTIN_OBJS += builtin-verify-pack.o
BUILTIN_OBJS += builtin-verify-tag.o
BUILTIN_OBJS += builtin-write-tree.o
@@ -795,7 +794,6 @@ ifeq ($(uname_S),SunOS)
NO_MKDTEMP = YesPlease
NO_MKSTEMPS = YesPlease
NO_REGEX = YesPlease
- NO_EXTERNAL_GREP = YesPlease
THREADED_DELTA_SEARCH = YesPlease
ifeq ($(uname_R),5.7)
NEEDS_RESOLV = YesPlease
@@ -914,7 +912,6 @@ ifeq ($(uname_S),IRIX)
# NO_MMAP. If you suspect that your compiler is not affected by this
# issue, comment out the NO_MMAP statement.
NO_MMAP = YesPlease
- NO_EXTERNAL_GREP = UnfortunatelyYes
SNPRINTF_RETURNS_BOGUS = YesPlease
SHELL_PATH = /usr/gnu/bin/bash
NEEDS_LIBGEN = YesPlease
@@ -934,7 +931,6 @@ ifeq ($(uname_S),IRIX64)
# NO_MMAP. If you suspect that your compiler is not affected by this
# issue, comment out the NO_MMAP statement.
NO_MMAP = YesPlease
- NO_EXTERNAL_GREP = UnfortunatelyYes
SNPRINTF_RETURNS_BOGUS = YesPlease
SHELL_PATH=/usr/gnu/bin/bash
NEEDS_LIBGEN = YesPlease
@@ -1349,9 +1345,6 @@ endif
ifdef DIR_HAS_BSD_GROUP_SEMANTICS
COMPAT_CFLAGS += -DDIR_HAS_BSD_GROUP_SEMANTICS
endif
-ifdef NO_EXTERNAL_GREP
- BASIC_CFLAGS += -DNO_EXTERNAL_GREP
-endif
ifdef UNRELIABLE_FSTAT
BASIC_CFLAGS += -DUNRELIABLE_FSTAT
endif
@@ -1788,6 +1781,7 @@ TEST_PROGRAMS_NEED_X += test-genrandom
TEST_PROGRAMS_NEED_X += test-match-trees
TEST_PROGRAMS_NEED_X += test-parse-options
TEST_PROGRAMS_NEED_X += test-path-utils
+TEST_PROGRAMS_NEED_X += test-run-command
TEST_PROGRAMS_NEED_X += test-sha1
TEST_PROGRAMS_NEED_X += test-sigchain
TEST_PROGRAMS_NEED_X += test-index-version
diff --git a/advice.c b/advice.c
index cb666ac..936d98b 100644
--- a/advice.c
+++ b/advice.c
@@ -3,6 +3,8 @@
int advice_push_nonfastforward = 1;
int advice_status_hints = 1;
int advice_commit_before_merge = 1;
+int advice_resolve_conflict = 1;
+int advice_implicit_identity = 1;
static struct {
const char *name;
@@ -11,6 +13,8 @@ static struct {
{ "pushnonfastforward", &advice_push_nonfastforward },
{ "statushints", &advice_status_hints },
{ "commitbeforemerge", &advice_commit_before_merge },
+ { "resolveconflict", &advice_resolve_conflict },
+ { "implicitidentity", &advice_implicit_identity },
};
int git_default_advice_config(const char *var, const char *value)
@@ -27,3 +31,17 @@ int git_default_advice_config(const char *var, const char *value)
return 0;
}
+
+void NORETURN die_resolve_conflict(const char *me)
+{
+ if (advice_resolve_conflict)
+ /*
+ * Message used both when 'git commit' fails and when
+ * other commands doing a merge do.
+ */
+ die("'%s' is not possible because you have unmerged files.\n"
+ "Please, fix them up in the work tree, and then use 'git add/rm <file>' as\n"
+ "appropriate to mark resolution and make a commit, or use 'git commit -a'.", me);
+ else
+ die("'%s' is not possible because you have unmerged files.", me);
+}
diff --git a/advice.h b/advice.h
index 3de5000..9b7a3ad 100644
--- a/advice.h
+++ b/advice.h
@@ -1,10 +1,16 @@
#ifndef ADVICE_H
#define ADVICE_H
+#include "git-compat-util.h"
+
extern int advice_push_nonfastforward;
extern int advice_status_hints;
extern int advice_commit_before_merge;
+extern int advice_resolve_conflict;
+extern int advice_implicit_identity;
int git_default_advice_config(const char *var, const char *value);
+extern void NORETURN die_resolve_conflict(const char *me);
+
#endif /* ADVICE_H */
diff --git a/archive.c b/archive.c
index 5b88507..d700af3 100644
--- a/archive.c
+++ b/archive.c
@@ -87,8 +87,8 @@ static void setup_archive_check(struct git_attr_check *check)
static struct git_attr *attr_export_subst;
if (!attr_export_ignore) {
- attr_export_ignore = git_attr("export-ignore", 13);
- attr_export_subst = git_attr("export-subst", 12);
+ attr_export_ignore = git_attr("export-ignore");
+ attr_export_subst = git_attr("export-subst");
}
check[0].attr = attr_export_ignore;
check[1].attr = attr_export_subst;
diff --git a/attr.c b/attr.c
index 55bdb7c..f5346ed 100644
--- a/attr.c
+++ b/attr.c
@@ -65,7 +65,7 @@ static int invalid_attr_name(const char *name, int namelen)
return 0;
}
-struct git_attr *git_attr(const char *name, int len)
+static struct git_attr *git_attr_internal(const char *name, int len)
{
unsigned hval = hash_name(name, len);
unsigned pos = hval % HASHSIZE;
@@ -95,6 +95,11 @@ struct git_attr *git_attr(const char *name, int len)
return a;
}
+struct git_attr *git_attr(const char *name)
+{
+ return git_attr_internal(name, strlen(name));
+}
+
/*
* .gitattributes file is one line per record, each of which is
*
@@ -162,7 +167,7 @@ static const char *parse_attr(const char *src, int lineno, const char *cp,
else {
e->setto = xmemdupz(equals + 1, ep - equals - 1);
}
- e->attr = git_attr(cp, len);
+ e->attr = git_attr_internal(cp, len);
}
(*num_attr)++;
return ep + strspn(ep, blank);
@@ -221,7 +226,7 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
sizeof(struct attr_state) * num_attr +
(is_macro ? 0 : namelen + 1));
if (is_macro)
- res->u.attr = git_attr(name, namelen);
+ res->u.attr = git_attr_internal(name, namelen);
else {
res->u.pattern = (char *)&(res->state[num_attr]);
memcpy(res->u.pattern, name, namelen);
diff --git a/attr.h b/attr.h
index 69b5767..450f49d 100644
--- a/attr.h
+++ b/attr.h
@@ -8,7 +8,7 @@ struct git_attr;
* Given a string, return the gitattribute object that
* corresponds to it.
*/
-struct git_attr *git_attr(const char *, int);
+struct git_attr *git_attr(const char *);
/* Internal use */
extern const char git_attr__true[];
diff --git a/bisect.c b/bisect.c
index 3d04d2a..6dc27ee 100644
--- a/bisect.c
+++ b/bisect.c
@@ -593,7 +593,7 @@ struct commit_list *filter_skipped(struct commit_list *list,
* is increased by one between each call, but that should not matter
* for this application.
*/
-int get_prn(int count) {
+static int get_prn(int count) {
count = count * 1103515245 + 12345;
return ((unsigned)(count/65536) % PRN_MODULO);
}
diff --git a/bisect.h b/bisect.h
index 82f8fc1..0862ce5 100644
--- a/bisect.h
+++ b/bisect.h
@@ -27,8 +27,6 @@ struct rev_list_info {
const char *header_prefix;
};
-extern int show_bisect_vars(struct rev_list_info *info, int reaches, int all);
-
extern int bisect_next_all(const char *prefix);
extern int estimate_bisect_steps(int all);
diff --git a/blob.c b/blob.c
index bd7d078..ae320bd 100644
--- a/blob.c
+++ b/blob.c
@@ -23,24 +23,3 @@ int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size)
item->object.parsed = 1;
return 0;
}
-
-int parse_blob(struct blob *item)
-{
- enum object_type type;
- void *buffer;
- unsigned long size;
- int ret;
-
- if (item->object.parsed)
- return 0;
- buffer = read_sha1_file(item->object.sha1, &type, &size);
- if (!buffer)
- return error("Could not read %s",
- sha1_to_hex(item->object.sha1));
- if (type != OBJ_BLOB)
- return error("Object %s not a blob",
- sha1_to_hex(item->object.sha1));
- ret = parse_blob_buffer(item, buffer, size);
- free(buffer);
- return ret;
-}
diff --git a/blob.h b/blob.h
index ea5d9e9..59b394e 100644
--- a/blob.h
+++ b/blob.h
@@ -13,6 +13,13 @@ struct blob *lookup_blob(const unsigned char *sha1);
int parse_blob_buffer(struct blob *item, void *buffer, unsigned long size);
-int parse_blob(struct blob *item);
+/**
+ * Blobs do not contain references to other objects and do not have
+ * structured data that needs parsing. However, code may use the
+ * "parsed" bit in the struct object for a blob to determine whether
+ * its content has been found to actually be available, so
+ * parse_blob_buffer() is used (by object.c) to flag that the object
+ * has been read successfully from the database.
+ **/
#endif /* BLOB_H */
diff --git a/builtin-add.c b/builtin-add.c
index cb6e590..2705f8d 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -11,6 +11,7 @@
#include "run-command.h"
#include "parse-options.h"
#include "diff.h"
+#include "diffcore.h"
#include "revision.h"
static const char * const builtin_add_usage[] = {
@@ -20,6 +21,81 @@ static const char * const builtin_add_usage[] = {
static int patch_interactive, add_interactive, edit_interactive;
static int take_worktree_changes;
+struct update_callback_data
+{
+ int flags;
+ int add_errors;
+};
+
+static void update_callback(struct diff_queue_struct *q,
+ struct diff_options *opt, void *cbdata)
+{
+ int i;
+ struct update_callback_data *data = cbdata;
+
+ for (i = 0; i < q->nr; i++) {
+ struct diff_filepair *p = q->queue[i];
+ const char *path = p->one->path;
+ switch (p->status) {
+ default:
+ die("unexpected diff status %c", p->status);
+ case DIFF_STATUS_UNMERGED:
+ /*
+ * ADD_CACHE_IGNORE_REMOVAL is unset if "git
+ * add -u" is calling us, In such a case, a
+ * missing work tree file needs to be removed
+ * if there is an unmerged entry at stage #2,
+ * but such a diff record is followed by
+ * another with DIFF_STATUS_DELETED (and if
+ * there is no stage #2, we won't see DELETED
+ * nor MODIFIED). We can simply continue
+ * either way.
+ */
+ if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL))
+ continue;
+ /*
+ * Otherwise, it is "git add path" is asking
+ * to explicitly add it; we fall through. A
+ * missing work tree file is an error and is
+ * caught by add_file_to_index() in such a
+ * case.
+ */
+ case DIFF_STATUS_MODIFIED:
+ case DIFF_STATUS_TYPE_CHANGED:
+ if (add_file_to_index(&the_index, path, data->flags)) {
+ if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
+ die("updating files failed");
+ data->add_errors++;
+ }
+ break;
+ case DIFF_STATUS_DELETED:
+ if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
+ break;
+ if (!(data->flags & ADD_CACHE_PRETEND))
+ remove_file_from_index(&the_index, path);
+ if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
+ printf("remove '%s'\n", path);
+ break;
+ }
+ }
+}
+
+int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
+{
+ struct update_callback_data data;
+ struct rev_info rev;
+ init_revisions(&rev, prefix);
+ setup_revisions(0, NULL, &rev, NULL);
+ rev.prune_data = pathspec;
+ rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
+ rev.diffopt.format_callback = update_callback;
+ data.flags = flags;
+ data.add_errors = 0;
+ rev.diffopt.format_callback_data = &data;
+ run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
+ return !!data.add_errors;
+}
+
static void fill_pathspec_matches(const char **pathspec, char *seen, int specs)
{
int num_unmatched = 0, i;
diff --git a/builtin-apply.c b/builtin-apply.c
index 541493e..2a1004d 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -404,6 +404,9 @@ static char *squash_slash(char *name)
{
int i = 0, j = 0;
+ if (!name)
+ return NULL;
+
while (name[i]) {
if ((name[j++] = name[i++]) == '/')
while (name[i] == '/')
@@ -416,7 +419,10 @@ static char *squash_slash(char *name)
static char *find_name(const char *line, char *def, int p_value, int terminate)
{
int len;
- const char *start = line;
+ const char *start = NULL;
+
+ if (p_value == 0)
+ start = line;
if (*line == '"') {
struct strbuf name = STRBUF_INIT;
@@ -686,7 +692,7 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
if (isnull)
die("git apply: bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
another = find_name(line, NULL, p_value, TERM_TAB);
- if (!another || memcmp(another, name, len))
+ if (!another || memcmp(another, name, len + 1))
die("git apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
free(another);
return orig_name;
@@ -1199,7 +1205,8 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
continue;
if (!patch->old_name && !patch->new_name) {
if (!patch->def_name)
- die("git diff header lacks filename information (line %d)", linenr);
+ die("git diff header lacks filename information when removing "
+ "%d leading pathname components (line %d)" , p_value, linenr);
patch->old_name = patch->new_name = patch->def_name;
}
patch->is_toplevel_relative = 1;
diff --git a/builtin-check-attr.c b/builtin-check-attr.c
index 8bd0430..3016d29 100644
--- a/builtin-check-attr.c
+++ b/builtin-check-attr.c
@@ -106,7 +106,7 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
const char *name;
struct git_attr *a;
name = argv[i];
- a = git_attr(name, strlen(name));
+ a = git_attr(name);
if (!a)
return error("%s: not a valid attribute name", name);
check[i].attr = a;
diff --git a/builtin-checkout.c b/builtin-checkout.c
index e44e238..5277817 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -17,6 +17,7 @@
#include "blob.h"
#include "xdiff-interface.h"
#include "ll-merge.h"
+#include "resolve-undo.h"
static const char * const checkout_usage[] = {
"git checkout [options] <branch>",
@@ -234,6 +235,10 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec,
if (report_path_error(ps_matched, pathspec, 0))
return 1;
+ /* "checkout -m path" to recreate conflicted state */
+ if (opts->merge)
+ unmerge_cache(pathspec);
+
/* Any unmerged paths? */
for (pos = 0; pos < active_nr; pos++) {
struct cache_entry *ce = active_cache[pos];
@@ -370,6 +375,7 @@ static int merge_working_tree(struct checkout_opts *opts,
if (read_cache_preload(NULL) < 0)
return error("corrupt index file");
+ resolve_undo_clear();
if (opts->force) {
ret = reset_tree(new->commit->tree, opts, 1);
if (ret)
@@ -752,8 +758,10 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
new.name = arg;
if ((new.commit = lookup_commit_reference_gently(rev, 1))) {
setup_branch_path(&new);
- if (resolve_ref(new.path, rev, 1, NULL))
- new.commit = lookup_commit_reference(rev);
+
+ if ((check_ref_format(new.path) == CHECK_REF_FORMAT_OK) &&
+ resolve_ref(new.path, rev, 1, NULL))
+ ;
else
new.path = NULL;
parse_commit(new.commit);
diff --git a/builtin-commit.c b/builtin-commit.c
index 69241f8..55676fd 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -36,7 +36,20 @@ static const char * const builtin_status_usage[] = {
NULL
};
+static const char implicit_ident_advice[] =
+"Your name and email address were configured automatically based\n"
+"on your username and hostname. Please check that they are accurate.\n"
+"You can suppress this message by setting them explicitly:\n"
+"\n"
+" git config --global user.name Your Name\n"
+" git config --global user.email you@example.com\n"
+"\n"
+"If the identity used for this commit is wrong, you can fix it with:\n"
+"\n"
+" git commit --amend --author='Your Name <you@example.com>'\n";
+
static unsigned char head_sha1[20];
+
static char *use_message_buffer;
static const char commit_editmsg[] = "COMMIT_EDITMSG";
static struct lock_file index_lock; /* real index */
@@ -245,6 +258,16 @@ static void create_base_index(void)
exit(128); /* We've already reported the error, finish dying */
}
+static void refresh_cache_or_die(int refresh_flags)
+{
+ /*
+ * refresh_flags contains REFRESH_QUIET, so the only errors
+ * are for unmerged entries.
+ */
+ if (refresh_cache(refresh_flags | REFRESH_IN_PORCELAIN))
+ die_resolve_conflict("commit");
+}
+
static char *prepare_index(int argc, const char **argv, const char *prefix, int is_status)
{
int fd;
@@ -284,7 +307,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, int
if (all || (also && pathspec && *pathspec)) {
int fd = hold_locked_index(&index_lock, 1);
add_files_to_cache(also ? prefix : NULL, pathspec, 0);
- refresh_cache(refresh_flags);
+ refresh_cache_or_die(refresh_flags);
if (write_cache(fd, active_cache, active_nr) ||
close_lock_file(&index_lock))
die("unable to write new_index file");
@@ -303,7 +326,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix, int
*/
if (!pathspec || !*pathspec) {
fd = hold_locked_index(&index_lock, 1);
- refresh_cache(refresh_flags);
+ refresh_cache_or_die(refresh_flags);
if (write_cache(fd, active_cache, active_nr) ||
commit_locked_index(&index_lock))
die("unable to write new_index file");
@@ -633,7 +656,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
author_ident);
free(author_ident);
- if (!user_ident_explicitly_given)
+ if (!user_ident_sufficiently_given())
fprintf(fp,
"%s"
"# Committer: %s\n",
@@ -1024,7 +1047,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
s.pathspec = get_pathspec(prefix, argv);
read_cache();
- refresh_cache(REFRESH_QUIET|REFRESH_UNMERGED);
+ refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, s.pathspec, NULL, NULL);
s.is_initial = get_sha1(s.reference, sha1) ? 1 : 0;
s.in_merge = in_merge;
wt_status_collect(&s);
@@ -1055,9 +1078,12 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
{
struct rev_info rev;
struct commit *commit;
- static const char *format = "format:%h] %s";
+ struct strbuf format = STRBUF_INIT;
unsigned char junk_sha1[20];
const char *head = resolve_ref("HEAD", junk_sha1, 0, NULL);
+ struct pretty_print_context pctx = {0};
+ struct strbuf author_ident = STRBUF_INIT;
+ struct strbuf committer_ident = STRBUF_INIT;
commit = lookup_commit(sha1);
if (!commit)
@@ -1065,6 +1091,25 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
if (!commit || parse_commit(commit))
die("could not parse newly created commit");
+ strbuf_addstr(&format, "format:%h] %s");
+
+ format_commit_message(commit, "%an <%ae>", &author_ident, &pctx);
+ format_commit_message(commit, "%cn <%ce>", &committer_ident, &pctx);
+ if (strbuf_cmp(&author_ident, &committer_ident)) {
+ strbuf_addstr(&format, "\n Author: ");
+ strbuf_addbuf_percentquote(&format, &author_ident);
+ }
+ if (!user_ident_sufficiently_given()) {
+ strbuf_addstr(&format, "\n Committer: ");
+ strbuf_addbuf_percentquote(&format, &committer_ident);
+ if (advice_implicit_identity) {
+ strbuf_addch(&format, '\n');
+ strbuf_addstr(&format, implicit_ident_advice);
+ }
+ }
+ strbuf_release(&author_ident);
+ strbuf_release(&committer_ident);
+
init_revisions(&rev, prefix);
setup_revisions(0, NULL, &rev, NULL);
@@ -1075,7 +1120,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
rev.verbose_header = 1;
rev.show_root_diff = 1;
- get_commit_format(format, &rev);
+ get_commit_format(format.buf, &rev);
rev.always_show_header = 0;
rev.diffopt.detect_rename = 1;
rev.diffopt.rename_limit = 100;
@@ -1094,10 +1139,11 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
struct pretty_print_context ctx = {0};
struct strbuf buf = STRBUF_INIT;
ctx.date_mode = DATE_NORMAL;
- format_commit_message(commit, format + 7, &buf, &ctx);
+ format_commit_message(commit, format.buf + 7, &buf, &ctx);
printf("%s\n", buf.buf);
strbuf_release(&buf);
}
+ strbuf_release(&format);
}
static int git_commit_config(const char *k, const char *v, void *cb)
diff --git a/builtin-grep.c b/builtin-grep.c
index cea973b..da854fa 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -14,14 +14,7 @@
#include "userdiff.h"
#include "grep.h"
#include "quote.h"
-
-#ifndef NO_EXTERNAL_GREP
-#ifdef __unix__
-#define NO_EXTERNAL_GREP 0
-#else
-#define NO_EXTERNAL_GREP 1
-#endif
-#endif
+#include "dir.h"
static char const * const grep_usage[] = {
"git grep [options] [-e] <pattern> [<rev>...] [[--] path...]",
@@ -42,8 +35,6 @@ static int grep_config(const char *var, const char *value, void *cb)
opt->color = git_config_colorbool(var, value, -1);
return 0;
}
- if (!strcmp(var, "color.grep.external"))
- return git_config_string(&(opt->color_external), var, value);
if (!strcmp(var, "color.grep.match")) {
if (!value)
return config_error_nonbool(var);
@@ -214,309 +205,12 @@ static int grep_file(struct grep_opt *opt, const char *filename)
return i;
}
-#if !NO_EXTERNAL_GREP
-static int exec_grep(int argc, const char **argv)
-{
- pid_t pid;
- int status;
-
- argv[argc] = NULL;
- trace_argv_printf(argv, "trace: grep:");
- pid = fork();
- if (pid < 0)
- return pid;
- if (!pid) {
- execvp("grep", (char **) argv);
- exit(255);
- }
- while (waitpid(pid, &status, 0) < 0) {
- if (errno == EINTR)
- continue;
- return -1;
- }
- if (WIFEXITED(status)) {
- if (!WEXITSTATUS(status))
- return 1;
- return 0;
- }
- return -1;
-}
-
-#define MAXARGS 1000
-#define ARGBUF 4096
-#define push_arg(a) do { \
- if (nr < MAXARGS) argv[nr++] = (a); \
- else die("maximum number of args exceeded"); \
- } while (0)
-
-/*
- * If you send a singleton filename to grep, it does not give
- * the name of the file. GNU grep has "-H" but we would want
- * that behaviour in a portable way.
- *
- * So we keep two pathnames in argv buffer unsent to grep in
- * the main loop if we need to do more than one grep.
- */
-static int flush_grep(struct grep_opt *opt,
- int argc, int arg0, const char **argv, int *kept)
-{
- int status;
- int count = argc - arg0;
- const char *kept_0 = NULL;
-
- if (count <= 2) {
- /*
- * Because we keep at least 2 paths in the call from
- * the main loop (i.e. kept != NULL), and MAXARGS is
- * far greater than 2, this usually is a call to
- * conclude the grep. However, the user could attempt
- * to overflow the argv buffer by giving too many
- * options to leave very small number of real
- * arguments even for the call in the main loop.
- */
- if (kept)
- die("insanely many options to grep");
-
- /*
- * If we have two or more paths, we do not have to do
- * anything special, but we need to push /dev/null to
- * get "-H" behaviour of GNU grep portably but when we
- * are not doing "-l" nor "-L" nor "-c".
- */
- if (count == 1 &&
- !opt->name_only &&
- !opt->unmatch_name_only &&
- !opt->count) {
- argv[argc++] = "/dev/null";
- argv[argc] = NULL;
- }
- }
-
- else if (kept) {
- /*
- * Called because we found many paths and haven't finished
- * iterating over the cache yet. We keep two paths
- * for the concluding call. argv[argc-2] and argv[argc-1]
- * has the last two paths, so save the first one away,
- * replace it with NULL while sending the list to grep,
- * and recover them after we are done.
- */
- *kept = 2;
- kept_0 = argv[argc-2];
- argv[argc-2] = NULL;
- argc -= 2;
- }
-
- if (opt->pre_context || opt->post_context) {
- /*
- * grep handles hunk marks between files, but we need to
- * do that ourselves between multiple calls.
- */
- if (opt->show_hunk_mark)
- write_or_die(1, "--\n", 3);
- else
- opt->show_hunk_mark = 1;
- }
-
- status = exec_grep(argc, argv);
-
- if (kept_0) {
- /*
- * Then recover them. Now the last arg is beyond the
- * terminating NULL which is at argc, and the second
- * from the last is what we saved away in kept_0
- */
- argv[arg0++] = kept_0;
- argv[arg0] = argv[argc+1];
- }
- return status;
-}
-
-static void grep_add_color(struct strbuf *sb, const char *escape_seq)
-{
- size_t orig_len = sb->len;
-
- while (*escape_seq) {
- if (*escape_seq == 'm')
- strbuf_addch(sb, ';');
- else if (*escape_seq != '\033' && *escape_seq != '[')
- strbuf_addch(sb, *escape_seq);
- escape_seq++;
- }
- if (sb->len > orig_len && sb->buf[sb->len - 1] == ';')
- strbuf_setlen(sb, sb->len - 1);
-}
-
-static int has_skip_worktree_entry(struct grep_opt *opt, const char **paths)
-{
- int nr;
- for (nr = 0; nr < active_nr; nr++) {
- struct cache_entry *ce = active_cache[nr];
- if (!S_ISREG(ce->ce_mode))
- continue;
- if (!pathspec_matches(paths, ce->name, opt->max_depth))
- continue;
- if (ce_skip_worktree(ce))
- return 1;
- }
- return 0;
-}
-
-static int external_grep(struct grep_opt *opt, const char **paths, int cached)
-{
- int i, nr, argc, hit, len, status;
- const char *argv[MAXARGS+1];
- char randarg[ARGBUF];
- char *argptr = randarg;
- struct grep_pat *p;
-
- if (opt->extended || (opt->relative && opt->prefix_length)
- || has_skip_worktree_entry(opt, paths))
- return -1;
- len = nr = 0;
- push_arg("grep");
- if (opt->fixed)
- push_arg("-F");
- if (opt->linenum)
- push_arg("-n");
- if (!opt->pathname)
- push_arg("-h");
- if (opt->regflags & REG_EXTENDED)
- push_arg("-E");
- if (opt->ignore_case)
- push_arg("-i");
- if (opt->binary == GREP_BINARY_NOMATCH)
- push_arg("-I");
- if (opt->word_regexp)
- push_arg("-w");
- if (opt->name_only)
- push_arg("-l");
- if (opt->unmatch_name_only)
- push_arg("-L");
- if (opt->null_following_name)
- /* in GNU grep git's "-z" translates to "-Z" */
- push_arg("-Z");
- if (opt->count)
- push_arg("-c");
- if (opt->post_context || opt->pre_context) {
- if (opt->post_context != opt->pre_context) {
- if (opt->pre_context) {
- push_arg("-B");
- len += snprintf(argptr, sizeof(randarg)-len,
- "%u", opt->pre_context) + 1;
- if (sizeof(randarg) <= len)
- die("maximum length of args exceeded");
- push_arg(argptr);
- argptr += len;
- }
- if (opt->post_context) {
- push_arg("-A");
- len += snprintf(argptr, sizeof(randarg)-len,
- "%u", opt->post_context) + 1;
- if (sizeof(randarg) <= len)
- die("maximum length of args exceeded");
- push_arg(argptr);
- argptr += len;
- }
- }
- else {
- push_arg("-C");
- len += snprintf(argptr, sizeof(randarg)-len,
- "%u", opt->post_context) + 1;
- if (sizeof(randarg) <= len)
- die("maximum length of args exceeded");
- push_arg(argptr);
- argptr += len;
- }
- }
- for (p = opt->pattern_list; p; p = p->next) {
- push_arg("-e");
- push_arg(p->pattern);
- }
- if (opt->color) {
- struct strbuf sb = STRBUF_INIT;
-
- grep_add_color(&sb, opt->color_match);
- setenv("GREP_COLOR", sb.buf, 1);
-
- strbuf_reset(&sb);
- strbuf_addstr(&sb, "mt=");
- grep_add_color(&sb, opt->color_match);
- strbuf_addstr(&sb, ":sl=:cx=:fn=:ln=:bn=:se=");
- setenv("GREP_COLORS", sb.buf, 1);
-
- strbuf_release(&sb);
-
- if (opt->color_external && strlen(opt->color_external) > 0)
- push_arg(opt->color_external);
- } else {
- unsetenv("GREP_COLOR");
- unsetenv("GREP_COLORS");
- }
- unsetenv("GREP_OPTIONS");
-
- hit = 0;
- argc = nr;
- for (i = 0; i < active_nr; i++) {
- struct cache_entry *ce = active_cache[i];
- char *name;
- int kept;
- if (!S_ISREG(ce->ce_mode))
- continue;
- if (!pathspec_matches(paths, ce->name, opt->max_depth))
- continue;
- name = ce->name;
- if (name[0] == '-') {
- int len = ce_namelen(ce);
- name = xmalloc(len + 3);
- memcpy(name, "./", 2);
- memcpy(name + 2, ce->name, len + 1);
- }
- argv[argc++] = name;
- if (MAXARGS <= argc) {
- status = flush_grep(opt, argc, nr, argv, &kept);
- if (0 < status)
- hit = 1;
- argc = nr + kept;
- }
- if (ce_stage(ce)) {
- do {
- i++;
- } while (i < active_nr &&
- !strcmp(ce->name, active_cache[i]->name));
- i--; /* compensate for loop control */
- }
- }
- if (argc > nr) {
- status = flush_grep(opt, argc, nr, argv, NULL);
- if (0 < status)
- hit = 1;
- }
- return hit;
-}
-#endif
-
-static int grep_cache(struct grep_opt *opt, const char **paths, int cached,
- int external_grep_allowed)
+static int grep_cache(struct grep_opt *opt, const char **paths, int cached)
{
int hit = 0;
int nr;
read_cache();
-#if !NO_EXTERNAL_GREP
- /*
- * Use the external "grep" command for the case where
- * we grep through the checked-out files. It tends to
- * be a lot more optimized
- */
- if (!cached && external_grep_allowed) {
- hit = external_grep(opt, paths, cached);
- if (hit >= 0)
- return hit;
- hit = 0;
- }
-#endif
-
for (nr = 0; nr < active_nr; nr++) {
struct cache_entry *ce = active_cache[nr];
if (!S_ISREG(ce->ce_mode))
@@ -626,6 +320,21 @@ static int grep_object(struct grep_opt *opt, const char **paths,
die("unable to grep from object of type %s", typename(obj->type));
}
+static int grep_directory(struct grep_opt *opt, const char **paths)
+{
+ struct dir_struct dir;
+ int i, hit = 0;
+
+ memset(&dir, 0, sizeof(dir));
+ setup_standard_excludes(&dir);
+
+ fill_directory(&dir, paths);
+ for (i = 0; i < dir.nr; i++)
+ hit |= grep_file(opt, dir.entries[i]->name);
+ free_grep_patterns(opt);
+ return hit;
+}
+
static int context_callback(const struct option *opt, const char *arg,
int unset)
{
@@ -713,16 +422,19 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
{
int hit = 0;
int cached = 0;
- int external_grep_allowed = 1;
int seen_dashdash = 0;
+ int external_grep_allowed__ignored;
struct grep_opt opt;
struct object_array list = { 0, 0, NULL };
const char **paths = NULL;
int i;
int dummy;
+ int nongit = 0, use_index = 1;
struct option options[] = {
OPT_BOOLEAN(0, "cached", &cached,
"search in index instead of in the work tree"),
+ OPT_BOOLEAN(0, "index", &use_index,
+ "--no-index finds in contents not managed by git"),
OPT_GROUP(""),
OPT_BOOLEAN('v', "invert-match", &opt.invert,
"show non-matching lines"),
@@ -796,18 +508,15 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
OPT_BOOLEAN(0, "all-match", &opt.all_match,
"show only matches from files that match all patterns"),
OPT_GROUP(""),
-#if NO_EXTERNAL_GREP
- OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed,
- "allow calling of grep(1) (ignored by this build)"),
-#else
- OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed,
- "allow calling of grep(1) (default)"),
-#endif
+ OPT_BOOLEAN(0, "ext-grep", &external_grep_allowed__ignored,
+ "allow calling of grep(1) (ignored by this build)"),
{ OPTION_CALLBACK, 0, "help-all", &options, NULL, "show usage",
PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
OPT_END()
};
+ prefix = setup_git_directory_gently(&nongit);
+
/*
* 'git grep -h', unlike 'git grep -h <pattern>', is a request
* to show usage information and exit.
@@ -845,6 +554,10 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
PARSE_OPT_STOP_AT_NON_OPTION |
PARSE_OPT_NO_INTERNAL_HELP);
+ if (use_index && nongit)
+ /* die the same way as if we did it at the beginning */
+ setup_git_directory();
+
/* First unrecognized non-option token */
if (argc > 0 && !opt.pattern_list) {
append_grep_pattern(&opt, argv[0], "command line", 0,
@@ -853,8 +566,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
argc--;
}
- if ((opt.color && !opt.color_external) || opt.funcname)
- external_grep_allowed = 0;
if (!opt.pattern_list)
die("no pattern given.");
if (!opt.fixed && opt.ignore_case)
@@ -897,10 +608,18 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
paths[1] = NULL;
}
+ if (!use_index) {
+ if (cached)
+ die("--cached cannot be used with --no-index.");
+ if (list.nr)
+ die("--no-index cannot be used with revs.");
+ return !grep_directory(&opt, paths);
+ }
+
if (!list.nr) {
if (!cached)
setup_work_tree();
- return !grep_cache(&opt, paths, cached, external_grep_allowed);
+ return !grep_cache(&opt, paths, cached);
}
if (cached)
diff --git a/hash-object.c b/builtin-hash-object.c
index 9455dd0..6a5f5b5 100644
--- a/hash-object.c
+++ b/builtin-hash-object.c
@@ -73,17 +73,14 @@ static const struct option hash_object_options[] = {
OPT_END()
};
-int main(int argc, const char **argv)
+int cmd_hash_object(int argc, const char **argv, const char *prefix)
{
int i;
- const char *prefix = NULL;
int prefix_length = -1;
const char *errstr = NULL;
type = blob_type;
- git_extract_argv0_path(argv[0]);
-
argc = parse_options(argc, argv, NULL, hash_object_options,
hash_object_usage, 0);
diff --git a/index-pack.c b/builtin-index-pack.c
index 190f372..b4cf8c5 100644
--- a/index-pack.c
+++ b/builtin-index-pack.c
@@ -166,7 +166,7 @@ static void use(int bytes)
consumed_bytes += bytes;
}
-static char *open_pack_file(char *pack_name)
+static const char *open_pack_file(const char *pack_name)
{
if (from_stdin) {
input_fd = 0;
@@ -870,18 +870,16 @@ static int git_index_pack_config(const char *k, const char *v, void *cb)
return git_default_config(k, v, cb);
}
-int main(int argc, char **argv)
+int cmd_index_pack(int argc, const char **argv, const char *prefix)
{
int i, fix_thin_pack = 0;
- char *curr_pack, *pack_name = NULL;
- char *curr_index, *index_name = NULL;
+ const char *curr_pack, *curr_index;
+ const char *index_name = NULL, *pack_name = NULL;
const char *keep_name = NULL, *keep_msg = NULL;
char *index_name_buf = NULL, *keep_name_buf = NULL;
struct pack_idx_entry **idx_objects;
unsigned char pack_sha1[20];
- git_extract_argv0_path(argv[0]);
-
if (argc == 2 && !strcmp(argv[1], "-h"))
usage(index_pack_usage);
@@ -906,7 +904,7 @@ int main(int argc, char **argv)
}
for (i = 1; i < argc; i++) {
- char *arg = argv[i];
+ const char *arg = argv[i];
if (*arg == '-') {
if (!strcmp(arg, "--stdin")) {
@@ -1039,9 +1037,9 @@ int main(int argc, char **argv)
free(index_name_buf);
free(keep_name_buf);
if (pack_name == NULL)
- free(curr_pack);
+ free((void *) curr_pack);
if (index_name == NULL)
- free(curr_index);
+ free((void *) curr_index);
return 0;
}
diff --git a/builtin-log.c b/builtin-log.c
index 41b6df4..8d16832 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -58,6 +58,9 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
usage(builtin_log_usage);
argc = setup_revisions(argc, argv, rev, "HEAD");
+ if (!rev->show_notes_given && !rev->pretty_given)
+ rev->show_notes = 1;
+
if (rev->diffopt.pickaxe || rev->diffopt.filter)
rev->always_show_header = 0;
if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) {
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index 7382157..b065061 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -11,6 +11,8 @@
#include "builtin.h"
#include "tree.h"
#include "parse-options.h"
+#include "resolve-undo.h"
+#include "string-list.h"
static int abbrev;
static int show_deleted;
@@ -18,6 +20,7 @@ static int show_cached;
static int show_others;
static int show_stage;
static int show_unmerged;
+static int show_resolve_undo;
static int show_modified;
static int show_killed;
static int show_valid_bit;
@@ -38,6 +41,7 @@ static const char *tag_other = "";
static const char *tag_killed = "";
static const char *tag_modified = "";
static const char *tag_skip_worktree = "";
+static const char *tag_resolve_undo = "";
static void show_dir_entry(const char *tag, struct dir_entry *ent)
{
@@ -156,6 +160,38 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce)
write_name_quoted(ce->name + offset, stdout, line_terminator);
}
+static int show_one_ru(struct string_list_item *item, void *cbdata)
+{
+ int offset = prefix_offset;
+ const char *path = item->string;
+ struct resolve_undo_info *ui = item->util;
+ int i, len;
+
+ len = strlen(path);
+ if (len < prefix_len)
+ return 0; /* outside of the prefix */
+ if (!match_pathspec(pathspec, path, len, prefix_len, ps_matched))
+ return 0; /* uninterested */
+ for (i = 0; i < 3; i++) {
+ if (!ui->mode[i])
+ continue;
+ printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
+ abbrev
+ ? find_unique_abbrev(ui->sha1[i], abbrev)
+ : sha1_to_hex(ui->sha1[i]),
+ i + 1);
+ write_name_quoted(path + offset, stdout, line_terminator);
+ }
+ return 0;
+}
+
+static void show_ru_info(const char *prefix)
+{
+ if (!the_index.resolve_undo)
+ return;
+ for_each_string_list(show_one_ru, the_index.resolve_undo, NULL);
+}
+
static void show_files(struct dir_struct *dir, const char *prefix)
{
int i;
@@ -458,6 +494,8 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
DIR_HIDE_EMPTY_DIRECTORIES),
OPT_BOOLEAN('u', "unmerged", &show_unmerged,
"show unmerged files in the output"),
+ OPT_BOOLEAN(0, "resolve-undo", &show_resolve_undo,
+ "show resolve-undo information"),
{ OPTION_CALLBACK, 'x', "exclude", &dir.exclude_list[EXC_CMDL], "pattern",
"skip files matching pattern",
0, option_parse_exclude },
@@ -498,6 +536,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
tag_other = "? ";
tag_killed = "K ";
tag_skip_worktree = "S ";
+ tag_resolve_undo = "U ";
}
if (show_modified || show_others || show_deleted || (dir.flags & DIR_SHOW_IGNORED) || show_killed)
require_work_tree = 1;
@@ -536,7 +575,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
/* With no flags, we default to showing the cached files */
if (!(show_stage | show_deleted | show_others | show_unmerged |
- show_killed | show_modified))
+ show_killed | show_modified | show_resolve_undo))
show_cached = 1;
if (prefix)
@@ -551,6 +590,8 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
overlay_tree_on_cache(with_tree, prefix);
}
show_files(&dir, prefix);
+ if (show_resolve_undo)
+ show_ru_info(prefix);
if (ps_matched) {
int bad;
diff --git a/builtin-merge-file.c b/builtin-merge-file.c
index afd2ea7..1e70073 100644
--- a/builtin-merge-file.c
+++ b/builtin-merge-file.c
@@ -25,15 +25,20 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
const char *names[3] = { NULL, NULL, NULL };
mmfile_t mmfs[3];
mmbuffer_t result = {NULL, 0};
- xpparam_t xpp = {XDF_NEED_MINIMAL};
+ xmparam_t xmp = {{XDF_NEED_MINIMAL}};
int ret = 0, i = 0, to_stdout = 0;
- int merge_level = XDL_MERGE_ZEALOUS_ALNUM;
- int merge_style = 0, quiet = 0;
+ int level = XDL_MERGE_ZEALOUS_ALNUM;
+ int style = 0, quiet = 0;
+ int favor = 0;
int nongit;
struct option options[] = {
OPT_BOOLEAN('p', "stdout", &to_stdout, "send results to standard output"),
- OPT_SET_INT(0, "diff3", &merge_style, "use a diff3 based merge", XDL_MERGE_DIFF3),
+ OPT_SET_INT(0, "diff3", &style, "use a diff3 based merge", XDL_MERGE_DIFF3),
+ OPT_SET_INT(0, "ours", &favor, "for conflicts, use our version",
+ XDL_MERGE_FAVOR_OURS),
+ OPT_SET_INT(0, "theirs", &favor, "for conflicts, use their version",
+ XDL_MERGE_FAVOR_THEIRS),
OPT__QUIET(&quiet),
OPT_CALLBACK('L', NULL, names, "name",
"set labels for file1/orig_file/file2", &label_cb),
@@ -45,7 +50,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
/* Read the configuration file */
git_config(git_xmerge_config, NULL);
if (0 <= git_xmerge_style)
- merge_style = git_xmerge_style;
+ style = git_xmerge_style;
}
argc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);
@@ -68,7 +73,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
}
ret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2],
- &xpp, merge_level | merge_style, &result);
+ &xmp, XDL_MERGE_FLAGS(level, style, favor), &result);
for (i = 0; i < 3; i++)
free(mmfs[i].ptr);
diff --git a/merge-index.c b/builtin-merge-index.c
index 19ddd03..2c4cf5e 100644
--- a/merge-index.c
+++ b/builtin-merge-index.c
@@ -66,7 +66,7 @@ static void merge_all(void)
}
}
-int main(int argc, char **argv)
+int cmd_merge_index(int argc, const char **argv, const char *prefix)
{
int i, force_file = 0;
@@ -78,9 +78,6 @@ int main(int argc, char **argv)
if (argc < 3)
usage("git merge-index [-o] [-q] <merge-program> (-a | [--] <filename>*)");
- git_extract_argv0_path(argv[0]);
-
- setup_git_directory();
read_cache();
i = 1;
@@ -94,7 +91,7 @@ int main(int argc, char **argv)
}
pgm = argv[i++];
for (; i < argc; i++) {
- char *arg = argv[i];
+ const char *arg = argv[i];
if (!force_file && *arg == '-') {
if (!strcmp(arg, "--")) {
force_file = 1;
diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c
index 710674c..d8875d5 100644
--- a/builtin-merge-recursive.c
+++ b/builtin-merge-recursive.c
@@ -25,19 +25,30 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix)
struct commit *result;
init_merge_options(&o);
- if (argv[0]) {
- int namelen = strlen(argv[0]);
- if (8 < namelen &&
- !strcmp(argv[0] + namelen - 8, "-subtree"))
- o.subtree_merge = 1;
- }
+ if (argv[0] && !suffixcmp(argv[0], "-subtree"))
+ o.subtree_shift = "";
if (argc < 4)
usagef("%s <base>... -- <head> <remote> ...", argv[0]);
for (i = 1; i < argc; ++i) {
- if (!strcmp(argv[i], "--"))
- break;
+ const char *arg = argv[i];
+
+ if (!prefixcmp(arg, "--")) {
+ if (!arg[2])
+ break;
+ if (!strcmp(arg+2, "ours"))
+ o.recursive_variant = MERGE_RECURSIVE_OURS;
+ else if (!strcmp(arg+2, "theirs"))
+ o.recursive_variant = MERGE_RECURSIVE_THEIRS;
+ else if (!strcmp(arg+2, "subtree"))
+ o.subtree_shift = "";
+ else if (!prefixcmp(arg+2, "subtree="))
+ o.subtree_shift = arg + 10;
+ else
+ die("Unknown option %s", arg);
+ continue;
+ }
if (bases_count < ARRAY_SIZE(bases)-1) {
unsigned char *sha = xmalloc(20);
if (get_sha1(argv[i], sha))
diff --git a/merge-tree.c b/builtin-merge-tree.c
index f01e7c8..a4a4f2c 100644
--- a/merge-tree.c
+++ b/builtin-merge-tree.c
@@ -54,7 +54,7 @@ static const char *explanation(struct merge_list *entry)
return "removed in remote";
}
-extern void *merge_file(struct blob *, struct blob *, struct blob *, unsigned long *);
+extern void *merge_file(const char *, struct blob *, struct blob *, struct blob *, unsigned long *);
static void *result(struct merge_list *entry, unsigned long *size)
{
@@ -76,7 +76,7 @@ static void *result(struct merge_list *entry, unsigned long *size)
their = NULL;
if (entry)
their = entry->blob;
- return merge_file(base, our, their, size);
+ return merge_file(entry->path, base, our, their, size);
}
static void *origin(struct merge_list *entry, unsigned long *size)
@@ -337,7 +337,7 @@ static void *get_tree_descriptor(struct tree_desc *desc, const char *rev)
return buf;
}
-int main(int argc, char **argv)
+int cmd_merge_tree(int argc, const char **argv, const char *prefix)
{
struct tree_desc t[3];
void *buf1, *buf2, *buf3;
@@ -345,10 +345,6 @@ int main(int argc, char **argv)
if (argc != 4)
usage(merge_tree_usage);
- git_extract_argv0_path(argv[0]);
-
- setup_git_directory();
-
buf1 = get_tree_descriptor(t+0, argv[1]);
buf2 = get_tree_descriptor(t+1, argv[2]);
buf3 = get_tree_descriptor(t+2, argv[3]);
diff --git a/builtin-merge.c b/builtin-merge.c
index 82e2a04..3aaec7b 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -24,6 +24,7 @@
#include "rerere.h"
#include "help.h"
#include "merge-recursive.h"
+#include "resolve-undo.h"
#define DEFAULT_TWOHEAD (1<<0)
#define DEFAULT_OCTOPUS (1<<1)
@@ -50,6 +51,8 @@ static struct commit_list *remoteheads;
static unsigned char head[20], stash[20];
static struct strategy **use_strategies;
static size_t use_strategies_nr, use_strategies_alloc;
+static const char **xopts;
+static size_t xopts_nr, xopts_alloc;
static const char *branch;
static int verbosity;
static int allow_rerere_auto;
@@ -147,6 +150,17 @@ static int option_parse_strategy(const struct option *opt,
return 0;
}
+static int option_parse_x(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (unset)
+ return 0;
+
+ ALLOC_GROW(xopts, xopts_nr + 1, xopts_alloc);
+ xopts[xopts_nr++] = xstrdup(arg);
+ return 0;
+}
+
static int option_parse_n(const struct option *opt,
const char *arg, int unset)
{
@@ -174,6 +188,8 @@ static struct option builtin_merge_options[] = {
OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
OPT_CALLBACK('s', "strategy", &use_strategies, "strategy",
"merge strategy to use", option_parse_strategy),
+ OPT_CALLBACK('X', "strategy-option", &xopts, "option=value",
+ "option for selected merge strategy", option_parse_x),
OPT_CALLBACK('m', "message", &merge_msg, "message",
"message to be used for the merge commit (if any)",
option_parse_message),
@@ -536,7 +552,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
const char *head_arg)
{
const char **args;
- int i = 0, ret;
+ int i = 0, x = 0, ret;
struct commit_list *j;
struct strbuf buf = STRBUF_INIT;
int index_fd;
@@ -565,7 +581,20 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
init_merge_options(&o);
if (!strcmp(strategy, "subtree"))
- o.subtree_merge = 1;
+ o.subtree_shift = "";
+
+ for (x = 0; x < xopts_nr; x++) {
+ if (!strcmp(xopts[x], "ours"))
+ o.recursive_variant = MERGE_RECURSIVE_OURS;
+ else if (!strcmp(xopts[x], "theirs"))
+ o.recursive_variant = MERGE_RECURSIVE_THEIRS;
+ else if (!strcmp(xopts[x], "subtree"))
+ o.subtree_shift = "";
+ else if (!prefixcmp(xopts[x], "subtree="))
+ o.subtree_shift = xopts[x]+8;
+ else
+ die("Unknown option for merge-recursive: -X%s", xopts[x]);
+ }
o.branch1 = head_arg;
o.branch2 = remoteheads->item->util;
@@ -583,10 +612,16 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
rollback_lock_file(lock);
return clean ? 0 : 1;
} else {
- args = xmalloc((4 + commit_list_count(common) +
+ args = xmalloc((4 + xopts_nr + commit_list_count(common) +
commit_list_count(remoteheads)) * sizeof(char *));
strbuf_addf(&buf, "merge-%s", strategy);
args[i++] = buf.buf;
+ for (x = 0; x < xopts_nr; x++) {
+ char *s = xmalloc(strlen(xopts[x])+2+1);
+ strcpy(s, "--");
+ strcpy(s+2, xopts[x]);
+ args[i++] = s;
+ }
for (j = common; j; j = j->next)
args[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));
args[i++] = "--";
@@ -597,6 +632,8 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
ret = run_command_v_opt(args, RUN_GIT_CMD);
strbuf_release(&buf);
i = 1;
+ for (x = 0; x < xopts_nr; x++)
+ free((void *)args[i++]);
for (j = common; j; j = j->next)
free((void *)args[i++]);
i += 2;
@@ -606,6 +643,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
discard_cache();
if (read_cache() < 0)
die("failed to read the cache");
+ resolve_undo_clear();
return ret;
}
}
@@ -620,11 +658,10 @@ static void count_diff_files(struct diff_queue_struct *q,
static int count_unmerged_entries(void)
{
- const struct index_state *state = &the_index;
int i, ret = 0;
- for (i = 0; i < state->cache_nr; i++)
- if (ce_stage(state->cache[i]))
+ for (i = 0; i < active_nr; i++)
+ if (ce_stage(active_cache[i]))
ret++;
return ret;
@@ -849,12 +886,22 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
const char *best_strategy = NULL, *wt_strategy = NULL;
struct commit_list **remotes = &remoteheads;
- if (file_exists(git_path("MERGE_HEAD")))
- die("You have not concluded your merge. (MERGE_HEAD exists)");
- if (read_cache_unmerged())
- die("You are in the middle of a conflicted merge."
- " (index unmerged)");
+ if (read_cache_unmerged()) {
+ die_resolve_conflict("merge");
+ }
+ if (file_exists(git_path("MERGE_HEAD"))) {
+ /*
+ * There is no unmerged entry, don't advise 'git
+ * add/rm <file>', just 'git commit'.
+ */
+ if (advice_resolve_conflict)
+ die("You have not concluded your merge (MERGE_HEAD exists).\n"
+ "Please, commit your changes before you can merge.");
+ else
+ die("You have not concluded your merge (MERGE_HEAD exists).");
+ }
+ resolve_undo_clear();
/*
* Check if we are _not_ on a detached HEAD, i.e. if there is a
* current branch.
diff --git a/mktag.c b/builtin-mktag.c
index a3b4270..1cb0f3f 100644
--- a/mktag.c
+++ b/builtin-mktag.c
@@ -153,7 +153,7 @@ static int verify_tag(char *buffer, unsigned long size)
#undef PD_FMT
-int main(int argc, char **argv)
+int cmd_mktag(int argc, const char **argv, const char *prefix)
{
struct strbuf buf = STRBUF_INIT;
unsigned char result_sha1[20];
@@ -161,10 +161,6 @@ int main(int argc, char **argv)
if (argc != 1)
usage("git mktag < signaturefile");
- git_extract_argv0_path(argv[0]);
-
- setup_git_directory();
-
if (strbuf_read(&buf, 0, 4096) < 0) {
die_errno("could not read from stdin");
}
diff --git a/builtin-mv.c b/builtin-mv.c
index 8247186..c07f53b 100644
--- a/builtin-mv.c
+++ b/builtin-mv.c
@@ -24,10 +24,13 @@ static const char **copy_pathspec(const char *prefix, const char **pathspec,
result[count] = NULL;
for (i = 0; i < count; i++) {
int length = strlen(result[i]);
- if (length > 0 && is_dir_sep(result[i][length - 1]))
- result[i] = xmemdupz(result[i], length - 1);
- if (base_name)
- result[i] = basename((char *)result[i]);
+ int to_copy = length;
+ while (to_copy > 0 && is_dir_sep(result[i][to_copy - 1]))
+ to_copy--;
+ if (to_copy != length || base_name) {
+ char *it = xmemdupz(result[i], to_copy);
+ result[i] = base_name ? strdup(basename(it)) : it;
+ }
}
return get_pathspec(prefix, result);
}
diff --git a/builtin-notes.c b/builtin-notes.c
new file mode 100644
index 0000000..123ecad
--- /dev/null
+++ b/builtin-notes.c
@@ -0,0 +1,459 @@
+/*
+ * Builtin "git notes"
+ *
+ * Copyright (c) 2010 Johan Herland <johan@herland.net>
+ *
+ * Based on git-notes.sh by Johannes Schindelin,
+ * and builtin-tag.c by Kristian Høgsberg and Carlos Rica.
+ */
+
+#include "cache.h"
+#include "builtin.h"
+#include "notes.h"
+#include "blob.h"
+#include "commit.h"
+#include "refs.h"
+#include "exec_cmd.h"
+#include "run-command.h"
+#include "parse-options.h"
+
+static const char * const git_notes_usage[] = {
+ "git notes [list [<object>]]",
+ "git notes add [-f] [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]",
+ "git notes copy [-f] <from-object> <to-object>",
+ "git notes append [-m <msg> | -F <file> | (-c | -C) <object>] [<object>]",
+ "git notes edit [<object>]",
+ "git notes show [<object>]",
+ "git notes remove [<object>]",
+ "git notes prune",
+ NULL
+};
+
+static const char note_template[] =
+ "\n"
+ "#\n"
+ "# Write/edit the notes for the following object:\n"
+ "#\n";
+
+struct msg_arg {
+ int given;
+ int use_editor;
+ struct strbuf buf;
+};
+
+static int list_each_note(const unsigned char *object_sha1,
+ const unsigned char *note_sha1, char *note_path,
+ void *cb_data)
+{
+ printf("%s %s\n", sha1_to_hex(note_sha1), sha1_to_hex(object_sha1));
+ return 0;
+}
+
+static void write_note_data(int fd, const unsigned char *sha1)
+{
+ unsigned long size;
+ enum object_type type;
+ char *buf = read_sha1_file(sha1, &type, &size);
+ if (buf) {
+ if (size)
+ write_or_die(fd, buf, size);
+ free(buf);
+ }
+}
+
+static void write_commented_object(int fd, const unsigned char *object)
+{
+ const char *show_args[5] =
+ {"show", "--stat", "--no-notes", sha1_to_hex(object), NULL};
+ struct child_process show;
+ struct strbuf buf = STRBUF_INIT;
+ FILE *show_out;
+
+ /* Invoke "git show --stat --no-notes $object" */
+ memset(&show, 0, sizeof(show));
+ show.argv = show_args;
+ show.no_stdin = 1;
+ show.out = -1;
+ show.err = 0;
+ show.git_cmd = 1;
+ if (start_command(&show))
+ die("unable to start 'show' for object '%s'",
+ sha1_to_hex(object));
+
+ /* Open the output as FILE* so strbuf_getline() can be used. */
+ show_out = xfdopen(show.out, "r");
+ if (show_out == NULL)
+ die_errno("can't fdopen 'show' output fd");
+
+ /* Prepend "# " to each output line and write result to 'fd' */
+ while (strbuf_getline(&buf, show_out, '\n') != EOF) {
+ write_or_die(fd, "# ", 2);
+ write_or_die(fd, buf.buf, buf.len);
+ write_or_die(fd, "\n", 1);
+ }
+ strbuf_release(&buf);
+ if (fclose(show_out))
+ die_errno("failed to close pipe to 'show' for object '%s'",
+ sha1_to_hex(object));
+ if (finish_command(&show))
+ die("failed to finish 'show' for object '%s'",
+ sha1_to_hex(object));
+}
+
+static void create_note(const unsigned char *object, struct msg_arg *msg,
+ int append_only, const unsigned char *prev,
+ unsigned char *result)
+{
+ char *path = NULL;
+
+ if (msg->use_editor || !msg->given) {
+ int fd;
+
+ /* write the template message before editing: */
+ path = git_pathdup("NOTES_EDITMSG");
+ fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
+ if (fd < 0)
+ die_errno("could not create file '%s'", path);
+
+ if (msg->given)
+ write_or_die(fd, msg->buf.buf, msg->buf.len);
+ else if (prev && !append_only)
+ write_note_data(fd, prev);
+ write_or_die(fd, note_template, strlen(note_template));
+
+ write_commented_object(fd, object);
+
+ close(fd);
+ strbuf_reset(&(msg->buf));
+
+ if (launch_editor(path, &(msg->buf), NULL)) {
+ die("Please supply the note contents using either -m" \
+ " or -F option");
+ }
+ stripspace(&(msg->buf), 1);
+ }
+
+ if (prev && append_only) {
+ /* Append buf to previous note contents */
+ unsigned long size;
+ enum object_type type;
+ char *prev_buf = read_sha1_file(prev, &type, &size);
+
+ strbuf_grow(&(msg->buf), size + 1);
+ if (msg->buf.len && prev_buf && size)
+ strbuf_insert(&(msg->buf), 0, "\n", 1);
+ if (prev_buf && size)
+ strbuf_insert(&(msg->buf), 0, prev_buf, size);
+ free(prev_buf);
+ }
+
+ if (!msg->buf.len) {
+ fprintf(stderr, "Removing note for object %s\n",
+ sha1_to_hex(object));
+ hashclr(result);
+ } else {
+ if (write_sha1_file(msg->buf.buf, msg->buf.len, blob_type, result)) {
+ error("unable to write note object");
+ if (path)
+ error("The note contents has been left in %s",
+ path);
+ exit(128);
+ }
+ }
+
+ if (path) {
+ unlink_or_warn(path);
+ free(path);
+ }
+}
+
+static int parse_msg_arg(const struct option *opt, const char *arg, int unset)
+{
+ struct msg_arg *msg = opt->value;
+
+ if (!arg)
+ return -1;
+
+ strbuf_grow(&(msg->buf), strlen(arg) + 2);
+ if (msg->buf.len)
+ strbuf_addstr(&(msg->buf), "\n");
+ strbuf_addstr(&(msg->buf), arg);
+ stripspace(&(msg->buf), 0);
+
+ msg->given = 1;
+ return 0;
+}
+
+static int parse_file_arg(const struct option *opt, const char *arg, int unset)
+{
+ struct msg_arg *msg = opt->value;
+
+ if (!arg)
+ return -1;
+
+ if (msg->buf.len)
+ strbuf_addstr(&(msg->buf), "\n");
+ if (!strcmp(arg, "-")) {
+ if (strbuf_read(&(msg->buf), 0, 1024) < 0)
+ die_errno("cannot read '%s'", arg);
+ } else if (strbuf_read_file(&(msg->buf), arg, 1024) < 0)
+ die_errno("could not open or read '%s'", arg);
+ stripspace(&(msg->buf), 0);
+
+ msg->given = 1;
+ return 0;
+}
+
+static int parse_reuse_arg(const struct option *opt, const char *arg, int unset)
+{
+ struct msg_arg *msg = opt->value;
+ char *buf;
+ unsigned char object[20];
+ enum object_type type;
+ unsigned long len;
+
+ if (!arg)
+ return -1;
+
+ if (msg->buf.len)
+ strbuf_addstr(&(msg->buf), "\n");
+
+ if (get_sha1(arg, object))
+ die("Failed to resolve '%s' as a valid ref.", arg);
+ if (!(buf = read_sha1_file(object, &type, &len)) || !len) {
+ free(buf);
+ die("Failed to read object '%s'.", arg);;
+ }
+ strbuf_add(&(msg->buf), buf, len);
+ free(buf);
+
+ msg->given = 1;
+ return 0;
+}
+
+static int parse_reedit_arg(const struct option *opt, const char *arg, int unset)
+{
+ struct msg_arg *msg = opt->value;
+ msg->use_editor = 1;
+ return parse_reuse_arg(opt, arg, unset);
+}
+
+int commit_notes(struct notes_tree *t, const char *msg)
+{
+ struct commit_list *parent;
+ unsigned char tree_sha1[20], prev_commit[20], new_commit[20];
+ struct strbuf buf = STRBUF_INIT;
+
+ if (!t)
+ t = &default_notes_tree;
+ if (!t->initialized || !t->ref || !*t->ref)
+ die("Cannot commit uninitialized/unreferenced notes tree");
+
+ /* Prepare commit message and reflog message */
+ strbuf_addstr(&buf, "notes: "); /* commit message starts at index 7 */
+ strbuf_addstr(&buf, msg);
+ if (buf.buf[buf.len - 1] != '\n')
+ strbuf_addch(&buf, '\n'); /* Make sure msg ends with newline */
+
+ /* Convert notes tree to tree object */
+ if (write_notes_tree(t, tree_sha1))
+ die("Failed to write current notes tree to database");
+
+ /* Create new commit for the tree object */
+ if (!read_ref(t->ref, prev_commit)) { /* retrieve parent commit */
+ parent = xmalloc(sizeof(*parent));
+ parent->item = lookup_commit(prev_commit);
+ parent->next = NULL;
+ } else {
+ hashclr(prev_commit);
+ parent = NULL;
+ }
+ if (commit_tree(buf.buf + 7, tree_sha1, parent, new_commit, NULL))
+ die("Failed to commit notes tree to database");
+
+ /* Update notes ref with new commit */
+ update_ref(buf.buf, t->ref, new_commit, prev_commit, 0, DIE_ON_ERR);
+
+ strbuf_release(&buf);
+ return 0;
+}
+
+int cmd_notes(int argc, const char **argv, const char *prefix)
+{
+ struct notes_tree *t;
+ unsigned char object[20], from_obj[20], new_note[20];
+ const unsigned char *note;
+ const char *object_ref;
+ char logmsg[100];
+
+ int list = 0, add = 0, copy = 0, append = 0, edit = 0, show = 0,
+ remove = 0, prune = 0, force = 0;
+ int given_object = 0, i = 1, retval = 0;
+ struct msg_arg msg = { 0, 0, STRBUF_INIT };
+ struct option options[] = {
+ OPT_GROUP("Notes options"),
+ OPT_CALLBACK('m', "message", &msg, "MSG",
+ "note contents as a string", parse_msg_arg),
+ OPT_CALLBACK('F', "file", &msg, "FILE",
+ "note contents in a file", parse_file_arg),
+ OPT_CALLBACK('c', "reedit-message", &msg, "OBJECT",
+ "reuse and edit specified note object", parse_reedit_arg),
+ OPT_CALLBACK('C', "reuse-message", &msg, "OBJECT",
+ "reuse specified note object", parse_reuse_arg),
+ OPT_BOOLEAN('f', "force", &force, "replace existing notes"),
+ OPT_END()
+ };
+
+ git_config(git_default_config, NULL);
+
+ argc = parse_options(argc, argv, prefix, options, git_notes_usage, 0);
+
+ if (argc && !strcmp(argv[0], "list"))
+ list = 1;
+ else if (argc && !strcmp(argv[0], "add"))
+ add = 1;
+ else if (argc && !strcmp(argv[0], "copy"))
+ copy = 1;
+ else if (argc && !strcmp(argv[0], "append"))
+ append = 1;
+ else if (argc && !strcmp(argv[0], "edit"))
+ edit = 1;
+ else if (argc && !strcmp(argv[0], "show"))
+ show = 1;
+ else if (argc && !strcmp(argv[0], "remove"))
+ remove = 1;
+ else if (argc && !strcmp(argv[0], "prune"))
+ prune = 1;
+ else if (!argc) {
+ list = 1; /* Default to 'list' if no other subcommand given */
+ i = 0;
+ }
+
+ if (list + add + copy + append + edit + show + remove + prune != 1)
+ usage_with_options(git_notes_usage, options);
+
+ if (msg.given && !(add || append || edit)) {
+ error("cannot use -m/-F/-c/-C options with %s subcommand.",
+ argv[0]);
+ usage_with_options(git_notes_usage, options);
+ }
+
+ if (msg.given && edit) {
+ fprintf(stderr, "The -m/-F/-c/-C options have been deprecated "
+ "for the 'edit' subcommand.\n"
+ "Please use 'git notes add -f -m/-F/-c/-C' instead.\n");
+ }
+
+ if (force && !(add || copy)) {
+ error("cannot use -f option with %s subcommand.", argv[0]);
+ usage_with_options(git_notes_usage, options);
+ }
+
+ if (copy) {
+ const char *from_ref;
+ if (argc < 3) {
+ error("too few parameters");
+ usage_with_options(git_notes_usage, options);
+ }
+ from_ref = argv[i++];
+ if (get_sha1(from_ref, from_obj))
+ die("Failed to resolve '%s' as a valid ref.", from_ref);
+ }
+
+ given_object = argc > i;
+ object_ref = given_object ? argv[i++] : "HEAD";
+
+ if (argc > i || (prune && given_object)) {
+ error("too many parameters");
+ usage_with_options(git_notes_usage, options);
+ }
+
+ if (get_sha1(object_ref, object))
+ die("Failed to resolve '%s' as a valid ref.", object_ref);
+
+ init_notes(NULL, NULL, NULL, 0);
+ t = &default_notes_tree;
+
+ if (prefixcmp(t->ref, "refs/notes/"))
+ die("Refusing to %s notes in %s (outside of refs/notes/)",
+ argv[0], t->ref);
+
+ note = get_note(t, object);
+
+ /* list command */
+
+ if (list) {
+ if (given_object) {
+ if (note) {
+ puts(sha1_to_hex(note));
+ goto end;
+ }
+ } else {
+ retval = for_each_note(t, 0, list_each_note, NULL);
+ goto end;
+ }
+ }
+
+ /* show command */
+
+ if ((list || show) && !note) {
+ error("No note found for object %s.", sha1_to_hex(object));
+ retval = 1;
+ goto end;
+ } else if (show) {
+ const char *show_args[3] = {"show", sha1_to_hex(note), NULL};
+ retval = execv_git_cmd(show_args);
+ goto end;
+ }
+
+ /* add/append/edit/remove/prune command */
+
+ if ((add || copy) && note) {
+ if (!force) {
+ error("Cannot %s notes. Found existing notes for object"
+ " %s. Use '-f' to overwrite existing notes",
+ argv[0], sha1_to_hex(object));
+ retval = 1;
+ goto end;
+ }
+ fprintf(stderr, "Overwriting existing notes for object %s\n",
+ sha1_to_hex(object));
+ }
+
+ if (remove) {
+ msg.given = 1;
+ msg.use_editor = 0;
+ strbuf_reset(&(msg.buf));
+ }
+
+ if (prune) {
+ hashclr(new_note);
+ prune_notes(t);
+ goto commit;
+ } else if (copy) {
+ const unsigned char *from_note = get_note(t, from_obj);
+ if (!from_note) {
+ error("Missing notes on source object %s. Cannot copy.",
+ sha1_to_hex(from_obj));
+ retval = 1;
+ goto end;
+ }
+ hashcpy(new_note, from_note);
+ } else
+ create_note(object, &msg, append, note, new_note);
+
+ if (is_null_sha1(new_note))
+ remove_note(t, object);
+ else
+ add_note(t, object, new_note, combine_notes_overwrite);
+
+commit:
+ snprintf(logmsg, sizeof(logmsg), "Notes %s by 'git notes %s'",
+ is_null_sha1(new_note) ? "removed" : "added", argv[0]);
+ commit_notes(t, logmsg);
+
+end:
+ free_notes(t);
+ strbuf_release(&(msg.buf));
+ return retval;
+}
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 890f45c..b0887d7 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -525,7 +525,8 @@ static void write_pack_file(void)
if (!pack_to_stdout) {
mode_t mode = umask(0);
struct stat st;
- char *idx_tmp_name, tmpname[PATH_MAX];
+ const char *idx_tmp_name;
+ char tmpname[PATH_MAX];
umask(mode);
mode = 0444 & ~mode;
@@ -569,7 +570,7 @@ static void write_pack_file(void)
if (rename(idx_tmp_name, tmpname))
die_errno("unable to rename temporary index file");
- free(idx_tmp_name);
+ free((void *) idx_tmp_name);
free(pack_tmp_name);
puts(sha1_to_hex(sha1));
}
@@ -673,7 +674,7 @@ static void setup_delta_attr_check(struct git_attr_check *check)
static struct git_attr *attr_delta;
if (!attr_delta)
- attr_delta = git_attr("delta", 5);
+ attr_delta = git_attr("delta");
check[0].attr = attr_delta;
}
diff --git a/pack-redundant.c b/builtin-pack-redundant.c
index 21c61db..41e1615 100644
--- a/pack-redundant.c
+++ b/builtin-pack-redundant.c
@@ -568,7 +568,7 @@ static struct pack_list * add_pack(struct packed_git *p)
return pack_list_insert(&altodb_packs, &l);
}
-static struct pack_list * add_pack_file(char *filename)
+static struct pack_list * add_pack_file(const char *filename)
{
struct packed_git *p = packed_git;
@@ -593,7 +593,7 @@ static void load_all(void)
}
}
-int main(int argc, char **argv)
+int cmd_pack_redundant(int argc, const char **argv, const char *prefix)
{
int i;
struct pack_list *min, *red, *pl;
@@ -601,13 +601,9 @@ int main(int argc, char **argv)
unsigned char *sha1;
char buf[42]; /* 40 byte sha1 + \n + \0 */
- git_extract_argv0_path(argv[0]);
-
if (argc == 2 && !strcmp(argv[1], "-h"))
usage(pack_redundant_usage);
- setup_git_directory();
-
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strcmp(arg, "--")) {
diff --git a/patch-id.c b/builtin-patch-id.c
index 0df4cb0..af0911e 100644
--- a/patch-id.c
+++ b/builtin-patch-id.c
@@ -75,13 +75,11 @@ static void generate_id_list(void)
static const char patch_id_usage[] = "git patch-id < patch";
-int main(int argc, char **argv)
+int cmd_patch_id(int argc, const char **argv, const char *prefix)
{
if (argc != 1)
usage(patch_id_usage);
- git_extract_argv0_path(argv[0]);
-
generate_id_list();
return 0;
}
diff --git a/builtin-push.c b/builtin-push.c
index 28a26e7..5df6608 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -218,6 +218,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)
OPT_BOOLEAN( 0 , "thin", &thin, "use thin pack"),
OPT_STRING( 0 , "receive-pack", &receivepack, "receive-pack", "receive pack program"),
OPT_STRING( 0 , "exec", &receivepack, "receive-pack", "receive pack program"),
+ OPT_BIT('u', "set-upstream", &flags, "set upstream for git pull/status",
+ TRANSPORT_PUSH_SET_UPSTREAM),
OPT_END()
};
diff --git a/builtin-read-tree.c b/builtin-read-tree.c
index 50413ca..5fda990 100644
--- a/builtin-read-tree.c
+++ b/builtin-read-tree.c
@@ -13,6 +13,7 @@
#include "dir.h"
#include "builtin.h"
#include "parse-options.h"
+#include "resolve-undo.h"
static int nr_trees;
static struct tree *trees[MAX_UNPACK_TREES];
@@ -124,6 +125,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)
die("You need to resolve your current index first");
stage = opts.merge = 1;
}
+ resolve_undo_clear();
for (i = 0; i < argc; i++) {
const char *arg = argv[i];
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 5028138..34f9ace 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -120,6 +120,11 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
if (argc < 2)
return rerere(flags);
+ if (!strcmp(argv[1], "forget")) {
+ const char **pathspec = get_pathspec(prefix, argv + 2);
+ return rerere_forget(pathspec);
+ }
+
fd = setup_rerere(&merge_rr, flags);
if (fd < 0)
return 0;
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index cd97ded..c924b3a 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -253,7 +253,7 @@ static void print_var_int(const char *var, int val)
printf("%s=%d\n", var, val);
}
-int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
+static int show_bisect_vars(struct rev_list_info *info, int reaches, int all)
{
int cnt, flags = info->bisect_show_flags;
char hex[41] = "";
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index d14fe20..a8c5043 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -604,6 +604,12 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
for_each_remote_ref(show_reference, NULL);
continue;
}
+ if (!strcmp(arg, "--show-toplevel")) {
+ const char *work_tree = get_git_work_tree();
+ if (work_tree)
+ puts(work_tree);
+ continue;
+ }
if (!strcmp(arg, "--show-prefix")) {
if (prefix)
puts(prefix);
diff --git a/builtin-revert.c b/builtin-revert.c
index 857ca2e..8ac86f0 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -235,6 +235,19 @@ static struct tree *empty_tree(void)
return tree;
}
+static NORETURN void die_dirty_index(const char *me)
+{
+ if (read_cache_unmerged()) {
+ die_resolve_conflict(me);
+ } else {
+ if (advice_commit_before_merge)
+ die("Your local changes would be overwritten by %s.\n"
+ "Please, commit your changes or stash them to proceed.", me);
+ else
+ die("Your local changes would be overwritten by %s.\n", me);
+ }
+}
+
static int revert_or_cherry_pick(int argc, const char **argv)
{
unsigned char head[20];
@@ -271,7 +284,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
if (get_sha1("HEAD", head))
die ("You do not have a valid HEAD");
if (index_differs_from("HEAD", 0))
- die ("Dirty index: cannot %s", me);
+ die_dirty_index(me);
}
discard_cache();
diff --git a/builtin-rm.c b/builtin-rm.c
index 57975db..f3772c8 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -169,9 +169,10 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
if (read_cache() < 0)
die("index file corrupt");
- refresh_cache(REFRESH_QUIET);
pathspec = get_pathspec(prefix, argv);
+ refresh_index(&the_index, REFRESH_QUIET, pathspec, NULL, NULL);
+
seen = NULL;
for (i = 0; pathspec[i] ; i++)
/* nothing */;
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index 8fffdbf..76c7206 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -406,50 +406,20 @@ int send_pack(struct send_pack_args *args,
*/
new_refs = 0;
for (ref = remote_refs; ref; ref = ref->next) {
-
- if (ref->peer_ref)
- hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
- else if (!args->send_mirror)
+ if (!ref->peer_ref && !args->send_mirror)
continue;
- ref->deletion = is_null_sha1(ref->new_sha1);
- if (ref->deletion && !allow_deleting_refs) {
- ref->status = REF_STATUS_REJECT_NODELETE;
- continue;
- }
- if (!ref->deletion &&
- !hashcmp(ref->old_sha1, ref->new_sha1)) {
- ref->status = REF_STATUS_UPTODATE;
+ /* Check for statuses set by set_ref_status_for_push() */
+ switch (ref->status) {
+ case REF_STATUS_REJECT_NONFASTFORWARD:
+ case REF_STATUS_UPTODATE:
continue;
+ default:
+ ; /* do nothing */
}
- /* This part determines what can overwrite what.
- * The rules are:
- *
- * (0) you can always use --force or +A:B notation to
- * selectively force individual ref pairs.
- *
- * (1) if the old thing does not exist, it is OK.
- *
- * (2) if you do not have the old thing, you are not allowed
- * to overwrite it; you would not know what you are losing
- * otherwise.
- *
- * (3) if both new and old are commit-ish, and new is a
- * descendant of old, it is OK.
- *
- * (4) regardless of all of the above, removing :B is
- * always allowed.
- */
-
- ref->nonfastforward =
- !ref->deletion &&
- !is_null_sha1(ref->old_sha1) &&
- (!has_sha1_file(ref->old_sha1)
- || !ref_newer(ref->new_sha1, ref->old_sha1));
-
- if (ref->nonfastforward && !ref->force && !args->force_update) {
- ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
+ if (ref->deletion && !allow_deleting_refs) {
+ ref->status = REF_STATUS_REJECT_NODELETE;
continue;
}
@@ -673,6 +643,9 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
if (match_refs(local_refs, &remote_refs, nr_refspecs, refspecs, flags))
return -1;
+ set_ref_status_for_push(remote_refs, args.send_mirror,
+ args.force_update);
+
ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
if (helper_status)
diff --git a/unpack-file.c b/builtin-unpack-file.c
index e9d8934..608590a 100644
--- a/unpack-file.c
+++ b/builtin-unpack-file.c
@@ -22,18 +22,15 @@ static char *create_temp_file(unsigned char *sha1)
return path;
}
-int main(int argc, char **argv)
+int cmd_unpack_file(int argc, const char **argv, const char *prefix)
{
unsigned char sha1[20];
- git_extract_argv0_path(argv[0]);
-
if (argc != 2 || !strcmp(argv[1], "-h"))
usage("git unpack-file <sha1>");
if (get_sha1(argv[1], sha1))
die("Not a valid object name %s", argv[1]);
- setup_git_directory();
git_config(git_default_config, NULL);
puts(create_temp_file(sha1));
diff --git a/builtin-update-index.c b/builtin-update-index.c
index a64a752..3ab214d 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -9,6 +9,7 @@
#include "tree-walk.h"
#include "builtin.h"
#include "refs.h"
+#include "resolve-undo.h"
/*
* Default to not allowing changes to the list of files. The
@@ -440,7 +441,18 @@ static int unresolve_one(const char *path)
/* See if there is such entry in the index. */
pos = cache_name_pos(path, namelen);
- if (pos < 0) {
+ if (0 <= pos) {
+ /* already merged */
+ pos = unmerge_cache_entry_at(pos);
+ if (pos < active_nr) {
+ struct cache_entry *ce = active_cache[pos];
+ if (ce_stage(ce) &&
+ ce_namelen(ce) == namelen &&
+ !memcmp(ce->name, path, namelen))
+ return 0;
+ }
+ /* no resolve-undo information; fall back */
+ } else {
/* If there isn't, either it is unmerged, or
* resolved as "removed" by mistake. We do not
* want to do anything in the former case.
@@ -719,6 +731,10 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
verbose = 1;
continue;
}
+ if (!strcmp(path, "--clear-resolve-undo")) {
+ resolve_undo_clear();
+ continue;
+ }
if (!strcmp(path, "-h") || !strcmp(path, "--help"))
usage(update_index_usage);
die("unknown option %s", path);
diff --git a/var.c b/builtin-var.c
index d9892f8..2280518 100644
--- a/var.c
+++ b/builtin-var.c
@@ -72,7 +72,7 @@ static int show_config(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb);
}
-int main(int argc, char **argv)
+int cmd_var(int argc, const char **argv, const char *prefix)
{
const char *val;
int nongit;
@@ -80,8 +80,6 @@ int main(int argc, char **argv)
usage(var_usage);
}
- git_extract_argv0_path(argv[0]);
-
setup_git_directory_gently(&nongit);
val = NULL;
diff --git a/builtin.h b/builtin.h
index c3f83c0..cdf9847 100644
--- a/builtin.h
+++ b/builtin.h
@@ -5,6 +5,7 @@
#include "strbuf.h"
#include "cache.h"
#include "commit.h"
+#include "notes.h"
extern const char git_version_string[];
extern const char git_usage_string[];
@@ -18,6 +19,7 @@ extern int fmt_merge_msg(int merge_summary, struct strbuf *in,
extern int commit_tree(const char *msg, unsigned char *tree,
struct commit_list *parents, unsigned char *ret,
const char *author);
+extern int commit_notes(struct notes_tree *t, const char *msg);
extern int check_pager_config(const char *cmd);
extern int cmd_add(int argc, const char **argv, const char *prefix);
@@ -55,8 +57,10 @@ extern int cmd_fsck(int argc, const char **argv, const char *prefix);
extern int cmd_gc(int argc, const char **argv, const char *prefix);
extern int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix);
extern int cmd_grep(int argc, const char **argv, const char *prefix);
+extern int cmd_hash_object(int argc, const char **argv, const char *prefix);
extern int cmd_help(int argc, const char **argv, const char *prefix);
extern int cmd_http_fetch(int argc, const char **argv, const char *prefix);
+extern int cmd_index_pack(int argc, const char **argv, const char *prefix);
extern int cmd_init_db(int argc, const char **argv, const char *prefix);
extern int cmd_log(int argc, const char **argv, const char *prefix);
extern int cmd_log_reflog(int argc, const char **argv, const char *prefix);
@@ -67,13 +71,19 @@ extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);
extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);
extern int cmd_merge(int argc, const char **argv, const char *prefix);
extern int cmd_merge_base(int argc, const char **argv, const char *prefix);
+extern int cmd_merge_index(int argc, const char **argv, const char *prefix);
extern int cmd_merge_ours(int argc, const char **argv, const char *prefix);
extern int cmd_merge_file(int argc, const char **argv, const char *prefix);
extern int cmd_merge_recursive(int argc, const char **argv, const char *prefix);
+extern int cmd_merge_tree(int argc, const char **argv, const char *prefix);
+extern int cmd_mktag(int argc, const char **argv, const char *prefix);
extern int cmd_mktree(int argc, const char **argv, const char *prefix);
extern int cmd_mv(int argc, const char **argv, const char *prefix);
extern int cmd_name_rev(int argc, const char **argv, const char *prefix);
+extern int cmd_notes(int argc, const char **argv, const char *prefix);
extern int cmd_pack_objects(int argc, const char **argv, const char *prefix);
+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_pickaxe(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);
@@ -98,12 +108,14 @@ extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);
extern int cmd_tag(int argc, const char **argv, const char *prefix);
extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
+extern int cmd_unpack_file(int argc, const char **argv, const char *prefix);
extern int cmd_unpack_objects(int argc, const char **argv, const char *prefix);
extern int cmd_update_index(int argc, const char **argv, const char *prefix);
extern int cmd_update_ref(int argc, const char **argv, const char *prefix);
extern int cmd_update_server_info(int argc, const char **argv, const char *prefix);
extern int cmd_upload_archive(int argc, const char **argv, const char *prefix);
extern int cmd_upload_tar(int argc, const char **argv, const char *prefix);
+extern int cmd_var(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);
diff --git a/cache.h b/cache.h
index cf36c81..4b15042 100644
--- a/cache.h
+++ b/cache.h
@@ -288,6 +288,7 @@ static inline int ce_to_dtype(const struct cache_entry *ce)
struct index_state {
struct cache_entry **cache;
unsigned int cache_nr, cache_alloc, cache_changed;
+ struct string_list *resolve_undo;
struct cache_tree *cache_tree;
struct cache_time timestamp;
void *alloc;
@@ -342,6 +343,9 @@ static inline void remove_name_hash(struct cache_entry *ce)
#define ce_modified(ce, st, options) ie_modified(&the_index, (ce), (st), (options))
#define cache_name_exists(name, namelen, igncase) index_name_exists(&the_index, (name), (namelen), (igncase))
#define cache_name_is_other(name, namelen) index_name_is_other(&the_index, (name), (namelen))
+#define resolve_undo_clear() resolve_undo_clear_index(&the_index)
+#define unmerge_cache_entry_at(at) unmerge_index_entry_at(&the_index, at)
+#define unmerge_cache(pathspec) unmerge_index(&the_index, pathspec)
#endif
enum object_type {
@@ -451,7 +455,6 @@ extern int index_name_pos(const struct index_state *, const char *name, int name
#define ADD_CACHE_JUST_APPEND 8 /* Append only; tree.c::read_tree() */
#define ADD_CACHE_NEW_ONLY 16 /* Do not replace existing ones */
extern int add_index_entry(struct index_state *, struct cache_entry *ce, int option);
-extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
extern int remove_index_entry_at(struct index_state *, int pos);
extern void remove_marked_cache_entries(struct index_state *istate);
@@ -481,9 +484,6 @@ extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_obje
extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
-/* "careful lstat()" */
-extern int check_path(const char *path, int len, struct stat *st, int skiplen);
-
#define REFRESH_REALLY 0x0001 /* ignore_valid */
#define REFRESH_UNMERGED 0x0002 /* allow unmerged */
#define REFRESH_QUIET 0x0004 /* be quiet about it */
@@ -627,7 +627,6 @@ static inline void hashclr(unsigned char *hash)
{
memset(hash, 0, 20);
}
-extern int is_empty_blob_sha1(const unsigned char *sha1);
#define EMPTY_TREE_SHA1_HEX \
"4b825dc642cb6eb9a060e54bf8d69288fbee4904"
@@ -697,7 +696,6 @@ extern int has_sha1_pack(const unsigned char *sha1);
extern int has_sha1_file(const unsigned char *sha1);
extern int has_loose_object_nonlocal(const unsigned char *sha1);
-extern int has_pack_file(const unsigned char *sha1);
extern int has_pack_index(const unsigned char *sha1);
extern const signed char hexval_table[256];
@@ -798,8 +796,6 @@ extern int has_symlink_leading_path(const char *name, int len);
extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
extern int has_symlink_or_noent_leading_path(const char *name, int len);
extern int has_dirs_only_path(const char *name, int len, int prefix_len);
-extern void invalidate_lstat_cache(const char *name, int len);
-extern void clear_lstat_cache(void);
extern void schedule_dir_for_removal(const char *name, int len);
extern void remove_scheduled_dirs(void);
@@ -939,7 +935,11 @@ extern const char *config_exclusive_filename;
#define MAX_GITNAME (1000)
extern char git_default_email[MAX_GITNAME];
extern char git_default_name[MAX_GITNAME];
+#define IDENT_NAME_GIVEN 01
+#define IDENT_MAIL_GIVEN 02
+#define IDENT_ALL_GIVEN (IDENT_NAME_GIVEN|IDENT_MAIL_GIVEN)
extern int user_ident_explicitly_given;
+extern int user_ident_sufficiently_given(void);
extern const char *git_commit_encoding;
extern const char *git_log_output_encoding;
@@ -1007,6 +1007,7 @@ extern int diff_auto_refresh_index;
/* match-trees.c */
void shift_tree(const unsigned char *, const unsigned char *, unsigned char *, int);
+void shift_tree_by(const unsigned char *, const unsigned char *, unsigned char *, const char *);
/*
* whitespace rules.
diff --git a/commit.h b/commit.h
index e5332ef..3cf5166 100644
--- a/commit.h
+++ b/commit.h
@@ -70,10 +70,10 @@ struct pretty_print_context
const char *after_subject;
enum date_mode date_mode;
int need_8bit_cte;
+ int show_notes;
struct reflog_walk_info *reflog_info;
};
-extern int non_ascii(int);
extern int has_non_ascii(const char *text);
struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
extern char *reencode_commit_message(const struct commit *commit,
diff --git a/config.c b/config.c
index f4f2c59..6963fbe 100644
--- a/config.c
+++ b/config.c
@@ -533,8 +533,7 @@ static int git_default_user_config(const char *var, const char *value)
if (!value)
return config_error_nonbool(var);
strlcpy(git_default_name, value, sizeof(git_default_name));
- if (git_default_email[0])
- user_ident_explicitly_given = 1;
+ user_ident_explicitly_given |= IDENT_NAME_GIVEN;
return 0;
}
@@ -542,8 +541,7 @@ static int git_default_user_config(const char *var, const char *value)
if (!value)
return config_error_nonbool(var);
strlcpy(git_default_email, value, sizeof(git_default_email));
- if (git_default_name[0])
- user_ident_explicitly_given = 1;
+ user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
return 0;
}
diff --git a/contrib/buildsystems/engine.pl b/contrib/buildsystems/engine.pl
index d506717..8f890fb 100644
--- a/contrib/buildsystems/engine.pl
+++ b/contrib/buildsystems/engine.pl
@@ -135,6 +135,11 @@ sub parseMakeOutput
}
} while($ate_next);
+ if ($text =~ /^test /) {
+ # options to test (eg -o) may be mistaken for linker options
+ next;
+ }
+
if($text =~ / -c /) {
# compilation
handleCompileLine($text, $line);
@@ -180,9 +185,6 @@ sub parseMakeOutput
# } elsif ($text =~ /generate-cmdlist\.sh/) {
# # command for generating list of commands
#
-# } elsif ($text =~ /^test / && $text =~ /|| rm -f /) {
-# # commands removing executables, if they exist
-#
# } elsif ($text =~ /new locations or Tcl/) {
# # command for detecting Tcl/Tk changes
#
diff --git a/contrib/examples/git-merge.sh b/contrib/examples/git-merge.sh
index 500635f..8f617fc 100755
--- a/contrib/examples/git-merge.sh
+++ b/contrib/examples/git-merge.sh
@@ -31,10 +31,11 @@ LF='
'
all_strategies='recur recursive octopus resolve stupid ours subtree'
+all_strategies="$all_strategies recursive-ours recursive-theirs"
default_twohead_strategies='recursive'
default_octopus_strategies='octopus'
no_fast_forward_strategies='subtree ours'
-no_trivial_strategies='recursive recur subtree ours'
+no_trivial_strategies='recursive recur subtree ours recursive-ours recursive-theirs'
use_strategies=
allow_fast_forward=t
diff --git a/git-notes.sh b/contrib/examples/git-notes.sh
index e642e47..e642e47 100755
--- a/git-notes.sh
+++ b/contrib/examples/git-notes.sh
diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index 48059d0..d1512e0 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -732,7 +732,7 @@ class P4Submit(Command):
if os.environ.has_key("P4EDITOR"):
editor = os.environ.get("P4EDITOR")
else:
- editor = read_pipe("git var GIT_EDITOR")
+ editor = read_pipe("git var GIT_EDITOR").strip()
system(editor + " " + fileName)
response = "y"
diff --git a/convert.c b/convert.c
index 950b1f9..27acce5 100644
--- a/convert.c
+++ b/convert.c
@@ -378,9 +378,9 @@ static void setup_convert_check(struct git_attr_check *check)
static struct git_attr *attr_filter;
if (!attr_crlf) {
- attr_crlf = git_attr("crlf", 4);
- attr_ident = git_attr("ident", 5);
- attr_filter = git_attr("filter", 6);
+ attr_crlf = git_attr("crlf");
+ attr_ident = git_attr("ident");
+ attr_filter = git_attr("filter");
user_convert_tail = &user_convert;
git_config(read_convert_config, NULL);
}
diff --git a/daemon.c b/daemon.c
index 918e560..360635e 100644
--- a/daemon.c
+++ b/daemon.c
@@ -147,7 +147,6 @@ static char *path_ok(char *directory)
{ "IP", ip_address },
{ "P", tcp_port },
{ "D", directory },
- { "%", "%" },
{ NULL }
};
diff --git a/date.c b/date.c
index 5d05ef6..45f3684 100644
--- a/date.c
+++ b/date.c
@@ -9,7 +9,7 @@
/*
* This is like mktime, but without normalization of tm_wday and tm_yday.
*/
-time_t tm_to_time_t(const struct tm *tm)
+static time_t tm_to_time_t(const struct tm *tm)
{
static const int mdays[] = {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
diff --git a/dir.c b/dir.c
index 3a8d3e6..67c3af6 100644
--- a/dir.c
+++ b/dir.c
@@ -242,6 +242,14 @@ int add_excludes_from_file_to_list(const char *fname,
if (!check_index ||
(buf = read_skip_worktree_file_from_index(fname, &size)) == NULL)
return -1;
+ if (size == 0) {
+ free(buf);
+ return 0;
+ }
+ if (buf[size-1] != '\n') {
+ buf = xrealloc(buf, size+1);
+ buf[size++] = '\n';
+ }
}
else {
size = xsize_t(st.st_size);
@@ -249,19 +257,21 @@ int add_excludes_from_file_to_list(const char *fname,
close(fd);
return 0;
}
- buf = xmalloc(size);
+ buf = xmalloc(size+1);
if (read_in_full(fd, buf, size) != size) {
+ free(buf);
close(fd);
return -1;
}
+ buf[size++] = '\n';
close(fd);
}
if (buf_p)
*buf_p = buf;
entry = buf;
- for (i = 0; i <= size; i++) {
- if (i == size || buf[i] == '\n') {
+ for (i = 0; i < size; i++) {
+ if (buf[i] == '\n') {
if (entry != buf + i && entry[0] != '#') {
buf[i - (i && buf[i-1] == '\r')] = 0;
add_exclude(entry, base, baselen, which);
@@ -655,6 +665,92 @@ static int get_dtype(struct dirent *de, const char *path, int len)
return dtype;
}
+enum path_treatment {
+ path_ignored,
+ path_handled,
+ path_recurse,
+};
+
+static enum path_treatment treat_one_path(struct dir_struct *dir,
+ char *path, int *len,
+ const struct path_simplify *simplify,
+ int dtype, struct dirent *de)
+{
+ int exclude = excluded(dir, path, &dtype);
+ if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
+ && in_pathspec(path, *len, simplify))
+ dir_add_ignored(dir, path, *len);
+
+ /*
+ * Excluded? If we don't explicitly want to show
+ * ignored files, ignore it
+ */
+ if (exclude && !(dir->flags & DIR_SHOW_IGNORED))
+ return path_ignored;
+
+ if (dtype == DT_UNKNOWN)
+ dtype = get_dtype(de, path, *len);
+
+ /*
+ * Do we want to see just the ignored files?
+ * We still need to recurse into directories,
+ * even if we don't ignore them, since the
+ * directory may contain files that we do..
+ */
+ if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
+ if (dtype != DT_DIR)
+ return path_ignored;
+ }
+
+ switch (dtype) {
+ default:
+ return path_ignored;
+ case DT_DIR:
+ memcpy(path + *len, "/", 2);
+ (*len)++;
+ switch (treat_directory(dir, path, *len, simplify)) {
+ case show_directory:
+ if (exclude != !!(dir->flags
+ & DIR_SHOW_IGNORED))
+ return path_ignored;
+ break;
+ case recurse_into_directory:
+ return path_recurse;
+ case ignore_directory:
+ return path_ignored;
+ }
+ break;
+ case DT_REG:
+ case DT_LNK:
+ break;
+ }
+ return path_handled;
+}
+
+static enum path_treatment treat_path(struct dir_struct *dir,
+ struct dirent *de,
+ char *path, int path_max,
+ int baselen,
+ const struct path_simplify *simplify,
+ int *len)
+{
+ int dtype;
+
+ if (is_dot_or_dotdot(de->d_name) || !strcmp(de->d_name, ".git"))
+ return path_ignored;
+ *len = strlen(de->d_name);
+ /* Ignore overly long pathnames! */
+ if (*len + baselen + 8 > path_max)
+ return path_ignored;
+ memcpy(path + baselen, de->d_name, *len + 1);
+ *len += baselen;
+ if (simplify_away(path, *len, simplify))
+ return path_ignored;
+
+ dtype = DTYPE(de);
+ return treat_one_path(dir, path, len, simplify, dtype, de);
+}
+
/*
* Read a directory tree. We currently ignore anything but
* directories, regular files and symlinks. That's because git
@@ -664,7 +760,10 @@ static int get_dtype(struct dirent *de, const char *path, int len)
* Also, we ignore the name ".git" (even if it is not a directory).
* That likely will not change.
*/
-static int read_directory_recursive(struct dir_struct *dir, const char *base, int baselen, int check_only, const struct path_simplify *simplify)
+static int read_directory_recursive(struct dir_struct *dir,
+ const char *base, int baselen,
+ int check_only,
+ const struct path_simplify *simplify)
{
DIR *fdir = opendir(*base ? base : ".");
int contents = 0;
@@ -675,70 +774,16 @@ static int read_directory_recursive(struct dir_struct *dir, const char *base, in
memcpy(path, base, baselen);
while ((de = readdir(fdir)) != NULL) {
- int len, dtype;
- int exclude;
-
- if (is_dot_or_dotdot(de->d_name) ||
- !strcmp(de->d_name, ".git"))
- continue;
- len = strlen(de->d_name);
- /* Ignore overly long pathnames! */
- if (len + baselen + 8 > sizeof(path))
- continue;
- memcpy(path + baselen, de->d_name, len+1);
- len = baselen + len;
- if (simplify_away(path, len, simplify))
- continue;
-
- dtype = DTYPE(de);
- exclude = excluded(dir, path, &dtype);
- if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
- && in_pathspec(path, len, simplify))
- dir_add_ignored(dir, path,len);
-
- /*
- * Excluded? If we don't explicitly want to show
- * ignored files, ignore it
- */
- if (exclude && !(dir->flags & DIR_SHOW_IGNORED))
+ int len;
+ switch (treat_path(dir, de, path, sizeof(path),
+ baselen, simplify, &len)) {
+ case path_recurse:
+ contents += read_directory_recursive
+ (dir, path, len, 0, simplify);
continue;
-
- if (dtype == DT_UNKNOWN)
- dtype = get_dtype(de, path, len);
-
- /*
- * Do we want to see just the ignored files?
- * We still need to recurse into directories,
- * even if we don't ignore them, since the
- * directory may contain files that we do..
- */
- if (!exclude && (dir->flags & DIR_SHOW_IGNORED)) {
- if (dtype != DT_DIR)
- continue;
- }
-
- switch (dtype) {
- default:
+ case path_ignored:
continue;
- case DT_DIR:
- memcpy(path + len, "/", 2);
- len++;
- switch (treat_directory(dir, path, len, simplify)) {
- case show_directory:
- if (exclude != !!(dir->flags
- & DIR_SHOW_IGNORED))
- continue;
- break;
- case recurse_into_directory:
- contents += read_directory_recursive(dir,
- path, len, 0, simplify);
- continue;
- case ignore_directory:
- continue;
- }
- break;
- case DT_REG:
- case DT_LNK:
+ case path_handled:
break;
}
contents++;
@@ -808,6 +853,41 @@ static void free_simplify(struct path_simplify *simplify)
free(simplify);
}
+static int treat_leading_path(struct dir_struct *dir,
+ const char *path, int len,
+ const struct path_simplify *simplify)
+{
+ char pathbuf[PATH_MAX];
+ int baselen, blen;
+ const char *cp;
+
+ while (len && path[len - 1] == '/')
+ len--;
+ if (!len)
+ return 1;
+ baselen = 0;
+ while (1) {
+ cp = path + baselen + !!baselen;
+ cp = memchr(cp, '/', path + len - cp);
+ if (!cp)
+ baselen = len;
+ else
+ baselen = cp - path;
+ memcpy(pathbuf, path, baselen);
+ pathbuf[baselen] = '\0';
+ if (!is_directory(pathbuf))
+ return 0;
+ if (simplify_away(pathbuf, baselen, simplify))
+ return 0;
+ blen = baselen;
+ if (treat_one_path(dir, pathbuf, &blen, simplify,
+ DT_DIR, NULL) == path_ignored)
+ return 0; /* do not recurse into it */
+ if (len <= baselen)
+ return 1; /* finished checking */
+ }
+}
+
int read_directory(struct dir_struct *dir, const char *path, int len, const char **pathspec)
{
struct path_simplify *simplify;
@@ -816,7 +896,8 @@ int read_directory(struct dir_struct *dir, const char *path, int len, const char
return dir->nr;
simplify = create_simplify(pathspec);
- read_directory_recursive(dir, path, len, 0, simplify);
+ if (!len || treat_leading_path(dir, path, len, simplify))
+ read_directory_recursive(dir, path, len, 0, simplify);
free_simplify(simplify);
qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name);
qsort(dir->ignored, dir->ignored_nr, sizeof(struct dir_entry *), cmp_name);
diff --git a/entry.c b/entry.c
index 9d5b232..004182c 100644
--- a/entry.c
+++ b/entry.c
@@ -179,7 +179,7 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
* This is like 'lstat()', except it refuses to follow symlinks
* in the path, after skipping "skiplen".
*/
-int check_path(const char *path, int len, struct stat *st, int skiplen)
+static int check_path(const char *path, int len, struct stat *st, int skiplen)
{
const char *slash = path + len;
diff --git a/fast-import.c b/fast-import.c
index 25c3588..901784f 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -245,6 +245,7 @@ struct branch
const char *name;
struct tree_entry branch_tree;
uintmax_t last_commit;
+ uintmax_t num_notes;
unsigned active : 1;
unsigned pack_id : PACK_ID_BITS;
unsigned char sha1[20];
@@ -702,6 +703,7 @@ static struct branch *new_branch(const char *name)
b->table_next_branch = branch_table[hc];
b->branch_tree.versions[0].mode = S_IFDIR;
b->branch_tree.versions[1].mode = S_IFDIR;
+ b->num_notes = 0;
b->active = 0;
b->pack_id = MAX_PACK_ID;
branch_table[hc] = b;
@@ -1911,6 +1913,109 @@ static void load_branch(struct branch *b)
}
}
+static unsigned char convert_num_notes_to_fanout(uintmax_t num_notes)
+{
+ unsigned char fanout = 0;
+ while ((num_notes >>= 8))
+ fanout++;
+ return fanout;
+}
+
+static void construct_path_with_fanout(const char *hex_sha1,
+ unsigned char fanout, char *path)
+{
+ unsigned int i = 0, j = 0;
+ if (fanout >= 20)
+ die("Too large fanout (%u)", fanout);
+ while (fanout) {
+ path[i++] = hex_sha1[j++];
+ path[i++] = hex_sha1[j++];
+ path[i++] = '/';
+ fanout--;
+ }
+ memcpy(path + i, hex_sha1 + j, 40 - j);
+ path[i + 40 - j] = '\0';
+}
+
+static uintmax_t do_change_note_fanout(
+ struct tree_entry *orig_root, struct tree_entry *root,
+ char *hex_sha1, unsigned int hex_sha1_len,
+ char *fullpath, unsigned int fullpath_len,
+ unsigned char fanout)
+{
+ struct tree_content *t = root->tree;
+ struct tree_entry *e, leaf;
+ unsigned int i, tmp_hex_sha1_len, tmp_fullpath_len;
+ uintmax_t num_notes = 0;
+ unsigned char sha1[20];
+ char realpath[60];
+
+ for (i = 0; t && i < t->entry_count; i++) {
+ e = t->entries[i];
+ tmp_hex_sha1_len = hex_sha1_len + e->name->str_len;
+ tmp_fullpath_len = fullpath_len;
+
+ /*
+ * We're interested in EITHER existing note entries (entries
+ * with exactly 40 hex chars in path, not including directory
+ * separators), OR directory entries that may contain note
+ * entries (with < 40 hex chars in path).
+ * Also, each path component in a note entry must be a multiple
+ * of 2 chars.
+ */
+ if (!e->versions[1].mode ||
+ tmp_hex_sha1_len > 40 ||
+ e->name->str_len % 2)
+ continue;
+
+ /* This _may_ be a note entry, or a subdir containing notes */
+ memcpy(hex_sha1 + hex_sha1_len, e->name->str_dat,
+ e->name->str_len);
+ if (tmp_fullpath_len)
+ fullpath[tmp_fullpath_len++] = '/';
+ memcpy(fullpath + tmp_fullpath_len, e->name->str_dat,
+ e->name->str_len);
+ tmp_fullpath_len += e->name->str_len;
+ fullpath[tmp_fullpath_len] = '\0';
+
+ if (tmp_hex_sha1_len == 40 && !get_sha1_hex(hex_sha1, sha1)) {
+ /* This is a note entry */
+ construct_path_with_fanout(hex_sha1, fanout, realpath);
+ if (!strcmp(fullpath, realpath)) {
+ /* Note entry is in correct location */
+ num_notes++;
+ continue;
+ }
+
+ /* Rename fullpath to realpath */
+ if (!tree_content_remove(orig_root, fullpath, &leaf))
+ die("Failed to remove path %s", fullpath);
+ tree_content_set(orig_root, realpath,
+ leaf.versions[1].sha1,
+ leaf.versions[1].mode,
+ leaf.tree);
+ } else if (S_ISDIR(e->versions[1].mode)) {
+ /* This is a subdir that may contain note entries */
+ if (!e->tree)
+ load_tree(e);
+ num_notes += do_change_note_fanout(orig_root, e,
+ hex_sha1, tmp_hex_sha1_len,
+ fullpath, tmp_fullpath_len, fanout);
+ }
+
+ /* The above may have reallocated the current tree_content */
+ t = root->tree;
+ }
+ return num_notes;
+}
+
+static uintmax_t change_note_fanout(struct tree_entry *root,
+ unsigned char fanout)
+{
+ char hex_sha1[40], path[60];
+ return do_change_note_fanout(root, root, hex_sha1, 0, path, 0, fanout);
+}
+
static void file_change_m(struct branch *b)
{
const char *p = command_buf.buf + 2;
@@ -2061,14 +2166,16 @@ static void file_change_cr(struct branch *b, int rename)
leaf.tree);
}
-static void note_change_n(struct branch *b)
+static void note_change_n(struct branch *b, unsigned char old_fanout)
{
const char *p = command_buf.buf + 2;
static struct strbuf uq = STRBUF_INIT;
struct object_entry *oe = oe;
struct branch *s;
unsigned char sha1[20], commit_sha1[20];
+ char path[60];
uint16_t inline_data = 0;
+ unsigned char new_fanout;
/* <dataref> or 'inline' */
if (*p == ':') {
@@ -2122,7 +2229,7 @@ static void note_change_n(struct branch *b)
if (oe->type != OBJ_BLOB)
die("Not a blob (actually a %s): %s",
typename(oe->type), command_buf.buf);
- } else {
+ } else if (!is_null_sha1(sha1)) {
enum object_type type = sha1_object_info(sha1, NULL);
if (type < 0)
die("Blob not found: %s", command_buf.buf);
@@ -2131,8 +2238,17 @@ static void note_change_n(struct branch *b)
typename(type), command_buf.buf);
}
- tree_content_set(&b->branch_tree, sha1_to_hex(commit_sha1), sha1,
- S_IFREG | 0644, NULL);
+ construct_path_with_fanout(sha1_to_hex(commit_sha1), old_fanout, path);
+ if (tree_content_remove(&b->branch_tree, path, NULL))
+ b->num_notes--;
+
+ if (is_null_sha1(sha1))
+ return; /* nothing to insert */
+
+ b->num_notes++;
+ new_fanout = convert_num_notes_to_fanout(b->num_notes);
+ construct_path_with_fanout(sha1_to_hex(commit_sha1), new_fanout, path);
+ tree_content_set(&b->branch_tree, path, sha1, S_IFREG | 0644, NULL);
}
static void file_change_deleteall(struct branch *b)
@@ -2141,6 +2257,7 @@ static void file_change_deleteall(struct branch *b)
hashclr(b->branch_tree.versions[0].sha1);
hashclr(b->branch_tree.versions[1].sha1);
load_tree(&b->branch_tree);
+ b->num_notes = 0;
}
static void parse_from_commit(struct branch *b, char *buf, unsigned long size)
@@ -2264,6 +2381,7 @@ static void parse_new_commit(void)
char *committer = NULL;
struct hash_list *merge_list = NULL;
unsigned int merge_count;
+ unsigned char prev_fanout, new_fanout;
/* Obtain the branch name from the rest of our command */
sp = strchr(command_buf.buf, ' ') + 1;
@@ -2294,6 +2412,8 @@ static void parse_new_commit(void)
load_branch(b);
}
+ prev_fanout = convert_num_notes_to_fanout(b->num_notes);
+
/* file_change* */
while (command_buf.len > 0) {
if (!prefixcmp(command_buf.buf, "M "))
@@ -2305,7 +2425,7 @@ static void parse_new_commit(void)
else if (!prefixcmp(command_buf.buf, "C "))
file_change_cr(b, 0);
else if (!prefixcmp(command_buf.buf, "N "))
- note_change_n(b);
+ note_change_n(b, prev_fanout);
else if (!strcmp("deleteall", command_buf.buf))
file_change_deleteall(b);
else {
@@ -2316,6 +2436,10 @@ static void parse_new_commit(void)
break;
}
+ new_fanout = convert_num_notes_to_fanout(b->num_notes);
+ if (new_fanout != prev_fanout)
+ b->num_notes = change_note_fanout(&b->branch_tree, new_fanout);
+
/* build the tree and the commit */
store_tree(&b->branch_tree);
hashcpy(b->branch_tree.versions[0].sha1,
diff --git a/git-compat-util.h b/git-compat-util.h
index a979e41..aff627a 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -199,7 +199,7 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)))
extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
extern int prefixcmp(const char *str, const char *prefix);
-extern time_t tm_to_time_t(const struct tm *tm);
+extern int suffixcmp(const char *str, const char *suffix);
static inline const char *skip_prefix(const char *str, const char *prefix)
{
diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index a7d215c..4853bf7 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -609,16 +609,16 @@ $orig_git_index = $ENV{GIT_INDEX_FILE} if exists $ENV{GIT_INDEX_FILE};
my %index; # holds filenames of one index per branch
unless (-d $git_dir) {
- system("git-init");
+ system(qw(git init));
die "Cannot init the GIT db at $git_tree: $?\n" if $?;
- system("git-read-tree");
+ system(qw(git read-tree));
die "Cannot init an empty tree: $?\n" if $?;
$last_branch = $opt_o;
$orig_branch = "";
} else {
- open(F, "git-symbolic-ref HEAD |") or
- die "Cannot run git-symbolic-ref: $!\n";
+ open(F, "-|", qw(git symbolic-ref HEAD)) or
+ die "Cannot run git symbolic-ref: $!\n";
chomp ($last_branch = <F>);
$last_branch = basename($last_branch);
close(F);
@@ -627,12 +627,12 @@ unless (-d $git_dir) {
$last_branch = "master";
}
$orig_branch = $last_branch;
- $tip_at_start = `git-rev-parse --verify HEAD`;
+ $tip_at_start = `git rev-parse --verify HEAD`;
# Get the last import timestamps
my $fmt = '($ref, $author) = (%(refname), %(author));';
- open(H, "git-for-each-ref --perl --format='$fmt' $remote |") or
- die "Cannot run git-for-each-ref: $!\n";
+ my @cmd = ('git', 'for-each-ref', '--perl', "--format=$fmt", $remote);
+ open(H, "-|", @cmd) or die "Cannot run git for-each-ref: $!\n";
while (defined(my $entry = <H>)) {
my ($ref, $author);
eval($entry) || die "cannot eval refs list: $@";
@@ -687,7 +687,7 @@ unless ($opt_P) {
print $cvspsfh $_;
}
close CVSPS;
- $? == 0 or die "git-cvsimport: fatal: cvsps reported error\n";
+ $? == 0 or die "git cvsimport: fatal: cvsps reported error\n";
close $cvspsfh;
} else {
$cvspsfile = munge_user_filename($opt_P);
@@ -716,27 +716,27 @@ my $state = 0;
sub update_index (\@\@) {
my $old = shift;
my $new = shift;
- open(my $fh, '|-', qw(git-update-index -z --index-info))
- or die "unable to open git-update-index: $!";
+ open(my $fh, '|-', qw(git update-index -z --index-info))
+ or die "unable to open git update-index: $!";
print $fh
(map { "0 0000000000000000000000000000000000000000\t$_\0" }
@$old),
(map { '100' . sprintf('%o', $_->[0]) . " $_->[1]\t$_->[2]\0" }
@$new)
- or die "unable to write to git-update-index: $!";
+ or die "unable to write to git update-index: $!";
close $fh
- or die "unable to write to git-update-index: $!";
- $? and die "git-update-index reported error: $?";
+ or die "unable to write to git update-index: $!";
+ $? and die "git update-index reported error: $?";
}
sub write_tree () {
- open(my $fh, '-|', qw(git-write-tree))
- or die "unable to open git-write-tree: $!";
+ open(my $fh, '-|', qw(git write-tree))
+ or die "unable to open git write-tree: $!";
chomp(my $tree = <$fh>);
is_sha1($tree)
or die "Cannot get tree id ($tree): $!";
close($fh)
- or die "Error running git-write-tree: $?\n";
+ or die "Error running git write-tree: $?\n";
print "Tree ID $tree\n" if $opt_v;
return $tree;
}
@@ -751,7 +751,7 @@ sub commit {
if ($branch eq $opt_o && !$index{branch} &&
!get_headref("$remote/$branch")) {
# looks like an initial commit
- # use the index primed by git-init
+ # use the index primed by git init
$ENV{GIT_INDEX_FILE} = "$git_dir/index";
$index{$branch} = "$git_dir/index";
} else {
@@ -761,9 +761,9 @@ sub commit {
$index{$branch} = tmpnam();
$ENV{GIT_INDEX_FILE} = $index{$branch};
if ($ancestor) {
- system("git-read-tree", "$remote/$ancestor");
+ system("git", "read-tree", "$remote/$ancestor");
} else {
- system("git-read-tree", "$remote/$branch");
+ system("git", "read-tree", "$remote/$branch");
}
die "read-tree failed: $?\n" if $?;
}
@@ -798,7 +798,7 @@ sub commit {
$ENV{GIT_COMMITTER_EMAIL} = $author_email;
$ENV{GIT_COMMITTER_DATE} = $commit_date;
my $pid = open2(my $commit_read, my $commit_write,
- 'git-commit-tree', $tree, @commit_args);
+ 'git', 'commit-tree', $tree, @commit_args);
# compatibility with git2cvs
substr($logmsg,32767) = "" if length($logmsg) > 32767;
@@ -811,7 +811,7 @@ sub commit {
}
print($commit_write "$logmsg\n") && close($commit_write)
- or die "Error writing to git-commit-tree: $!\n";
+ or die "Error writing to git commit-tree: $!\n";
print "Committed patch $patchset ($branch $commit_date)\n" if $opt_v;
chomp(my $cid = <$commit_read>);
@@ -820,9 +820,9 @@ sub commit {
close($commit_read);
waitpid($pid,0);
- die "Error running git-commit-tree: $?\n" if $?;
+ die "Error running git commit-tree: $?\n" if $?;
- system('git-update-ref', "$remote/$branch", $cid) == 0
+ system('git' , 'update-ref', "$remote/$branch", $cid) == 0
or die "Cannot write branch $branch for update: $!\n";
if ($tag) {
@@ -832,7 +832,7 @@ sub commit {
$xtag =~ s/[\/]/$opt_s/g;
$xtag =~ s/\[//g;
- system('git-tag', '-f', $xtag, $cid) == 0
+ system('git' , 'tag', '-f', $xtag, $cid) == 0
or die "Cannot create tag $xtag: $!\n";
print "Created tag '$xtag' on '$branch'\n" if $opt_v;
@@ -969,7 +969,7 @@ while (<CVS>) {
my $pid = open(my $F, '-|');
die $! unless defined $pid;
if (!$pid) {
- exec("git-hash-object", "-w", $tmpname)
+ exec("git", "hash-object", "-w", $tmpname)
or die "Cannot create object: $!\n";
}
my $sha = <$F>;
@@ -993,7 +993,7 @@ while (<CVS>) {
}
commit();
if (($commitcount & 1023) == 0) {
- system("git repack -a -d");
+ system(qw(git repack -a -d));
}
$state = 1;
} elsif ($state == 11 and /^-+$/) {
@@ -1013,11 +1013,11 @@ unless ($opt_P) {
# The heuristic of repacking every 1024 commits can leave a
# lot of unpacked data. If there is more than 1MB worth of
# not-packed objects, repack once more.
-my $line = `git-count-objects`;
+my $line = `git count-objects`;
if ($line =~ /^(\d+) objects, (\d+) kilobytes$/) {
my ($n_objects, $kb) = ($1, $2);
1024 < $kb
- and system("git repack -a -d");
+ and system(qw(git repack -a -d));
}
foreach my $git_index (values %index) {
@@ -1038,28 +1038,28 @@ if ($orig_branch) {
if ($opt_i) {
exit 0;
}
- my $tip_at_end = `git-rev-parse --verify HEAD`;
+ my $tip_at_end = `git rev-parse --verify HEAD`;
if ($tip_at_start ne $tip_at_end) {
for ($tip_at_start, $tip_at_end) { chomp; }
print "Fetched into the current branch.\n" if $opt_v;
- system(qw(git-read-tree -u -m),
+ system(qw(git read-tree -u -m),
$tip_at_start, $tip_at_end);
die "Fast-forward update failed: $?\n" if $?;
}
else {
- system(qw(git-merge cvsimport HEAD), "$remote/$opt_o");
+ system(qw(git merge cvsimport HEAD), "$remote/$opt_o");
die "Could not merge $opt_o into the current branch.\n" if $?;
}
} else {
$orig_branch = "master";
print "DONE; creating $orig_branch branch\n" if $opt_v;
- system("git-update-ref", "refs/heads/master", "$remote/$opt_o")
+ system("git", "update-ref", "refs/heads/master", "$remote/$opt_o")
unless defined get_headref('refs/heads/master');
- system("git-symbolic-ref", "$remote/HEAD", "$remote/$opt_o")
+ system("git", "symbolic-ref", "$remote/HEAD", "$remote/$opt_o")
if ($opt_r && $opt_o ne 'HEAD');
- system('git-update-ref', 'HEAD', "$orig_branch");
+ system('git', 'update-ref', 'HEAD', "$orig_branch");
unless ($opt_i) {
- system('git checkout -f');
+ system(qw(git checkout -f));
die "checkout failed: $?\n" if $?;
}
}
diff --git a/git-difftool--helper.sh b/git-difftool--helper.sh
index 57e8e32..524f5ea 100755
--- a/git-difftool--helper.sh
+++ b/git-difftool--helper.sh
@@ -3,16 +3,16 @@
# This script is typically launched by using the 'git difftool'
# convenience command.
#
-# Copyright (c) 2009 David Aguilar
+# Copyright (c) 2009, 2010 David Aguilar
-# Load common functions from git-mergetool--lib
TOOL_MODE=diff
. git-mergetool--lib
# difftool.prompt controls the default prompt/no-prompt behavior
# and is overridden with $GIT_DIFFTOOL*_PROMPT.
should_prompt () {
- prompt=$(git config --bool difftool.prompt || echo true)
+ prompt_merge=$(git config --bool mergetool.prompt || echo true)
+ prompt=$(git config --bool difftool.prompt || echo $prompt_merge)
if test "$prompt" = true; then
test -z "$GIT_DIFFTOOL_NO_PROMPT"
else
@@ -20,7 +20,11 @@ should_prompt () {
fi
}
-# Sets up shell variables and runs a merge tool
+# Indicates that --extcmd=... was specified
+use_ext_cmd () {
+ test -n "$GIT_DIFFTOOL_EXTCMD"
+}
+
launch_merge_tool () {
# Merged is the filename as it appears in the work tree
# Local is the contents of a/filename
@@ -35,20 +39,28 @@ launch_merge_tool () {
# the user with the real $MERGED name before launching $merge_tool.
if should_prompt; then
printf "\nViewing: '$MERGED'\n"
- printf "Hit return to launch '%s': " "$merge_tool"
+ if use_ext_cmd; then
+ printf "Hit return to launch '%s': " \
+ "$GIT_DIFFTOOL_EXTCMD"
+ else
+ printf "Hit return to launch '%s': " "$merge_tool"
+ fi
read ans
fi
- # Run the appropriate merge tool command
- run_merge_tool "$merge_tool"
+ if use_ext_cmd; then
+ eval $GIT_DIFFTOOL_EXTCMD '"$LOCAL"' '"$REMOTE"'
+ else
+ run_merge_tool "$merge_tool"
+ fi
}
-# Allow GIT_DIFF_TOOL and GIT_MERGE_TOOL to provide default values
-test -n "$GIT_MERGE_TOOL" && merge_tool="$GIT_MERGE_TOOL"
-test -n "$GIT_DIFF_TOOL" && merge_tool="$GIT_DIFF_TOOL"
-
-if test -z "$merge_tool"; then
- merge_tool="$(get_merge_tool)" || exit
+if ! use_ext_cmd; then
+ if test -n "$GIT_DIFF_TOOL"; then
+ merge_tool="$GIT_DIFF_TOOL"
+ else
+ merge_tool="$(get_merge_tool)" || exit
+ fi
fi
# Launch the merge tool on each path provided by 'git diff'
diff --git a/git-difftool.perl b/git-difftool.perl
index ba5e60a..d975d07 100755
--- a/git-difftool.perl
+++ b/git-difftool.perl
@@ -1,5 +1,5 @@
#!/usr/bin/env perl
-# Copyright (c) 2009 David Aguilar
+# Copyright (c) 2009, 2010 David Aguilar
#
# This is a wrapper around the GIT_EXTERNAL_DIFF-compatible
# git-difftool--helper script.
@@ -15,13 +15,17 @@ use warnings;
use Cwd qw(abs_path);
use File::Basename qw(dirname);
+require Git;
+
my $DIR = abs_path(dirname($0));
sub usage
{
print << 'USAGE';
-usage: git difftool [--tool=<tool>] [-y|--no-prompt] ["git diff" options]
+usage: git difftool [-t|--tool=<tool>] [-x|--extcmd=<cmd>]
+ [-y|--no-prompt] [-g|--gui]
+ ['git diff' options]
USAGE
exit 1;
}
@@ -63,6 +67,24 @@ sub generate_command
$ENV{GIT_DIFF_TOOL} = substr($arg, 7);
next;
}
+ if ($arg eq '-x' || $arg eq '--extcmd') {
+ usage() if $#ARGV <= $idx;
+ $ENV{GIT_DIFFTOOL_EXTCMD} = $ARGV[$idx + 1];
+ $skip_next = 1;
+ next;
+ }
+ if ($arg =~ /^--extcmd=/) {
+ $ENV{GIT_DIFFTOOL_EXTCMD} = substr($arg, 9);
+ next;
+ }
+ if ($arg eq '-g' || $arg eq '--gui') {
+ my $tool = Git::command_oneline('config',
+ 'diff.guitool');
+ if (length($tool)) {
+ $ENV{GIT_DIFF_TOOL} = $tool;
+ }
+ next;
+ }
if ($arg eq '-y' || $arg eq '--no-prompt') {
$ENV{GIT_DIFFTOOL_NO_PROMPT} = 'true';
delete $ENV{GIT_DIFFTOOL_PROMPT};
diff --git a/git-pull.sh b/git-pull.sh
index 9e69ada..2de4c3a 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -13,11 +13,33 @@ set_reflog_action "pull $*"
require_work_tree
cd_to_toplevel
-test -z "$(git ls-files -u)" ||
- die "You are in the middle of a conflicted merge."
+
+die_conflict () {
+ git diff-index --cached --name-status -r --ignore-submodules HEAD --
+ if [ $(git config --bool --get advice.resolveConflict || echo true) = "true" ]; then
+ die "Pull is not possible because you have unmerged files.
+Please, fix them up in the work tree, and then use 'git add/rm <file>'
+as appropriate to mark resolution, or use 'git commit -a'."
+ else
+ die "Pull is not possible because you have unmerged files."
+ fi
+}
+
+die_merge () {
+ if [ $(git config --bool --get advice.resolveConflict || echo true) = "true" ]; then
+ die "You have not concluded your merge (MERGE_HEAD exists).
+Please, commit your changes before you can merge."
+ else
+ die "You have not concluded your merge (MERGE_HEAD exists)."
+ fi
+}
+
+test -z "$(git ls-files -u)" || die_conflict
+test -f "$GIT_DIR/MERGE_HEAD" && die_merge
strategy_args= diffstat= no_commit= squash= no_ff= ff_only=
log_arg= verbosity=
+merge_args=
curr_branch=$(git symbolic-ref -q HEAD)
curr_branch_short=$(echo "$curr_branch" | sed "s|refs/heads/||")
rebase=$(git config --bool branch.$curr_branch_short.rebase)
@@ -62,6 +84,18 @@ do
esac
strategy_args="${strategy_args}-s $strategy "
;;
+ -X*)
+ case "$#,$1" in
+ 1,-X)
+ usage ;;
+ *,-X)
+ xx="-X $(git rev-parse --sq-quote "$2")"
+ shift ;;
+ *,*)
+ xx=$(git rev-parse --sq-quote "$1") ;;
+ esac
+ merge_args="$merge_args$xx "
+ ;;
-r|--r|--re|--reb|--reba|--rebas|--rebase)
rebase=true
;;
@@ -233,8 +267,15 @@ then
fi
merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit
-test true = "$rebase" &&
- exec git-rebase $diffstat $strategy_args --onto $merge_head \
- ${oldremoteref:-$merge_head}
-exec git-merge $diffstat $no_commit $squash $no_ff $ff_only $log_arg $strategy_args \
- "$merge_name" HEAD $merge_head $verbosity
+case "$rebase" in
+true)
+ eval="git-rebase $diffstat $strategy_args $merge_args"
+ eval="$eval --onto $merge_head ${oldremoteref:-$merge_head}"
+ ;;
+*)
+ eval="git-merge $diffstat $no_commit $squash $no_ff $ff_only"
+ eval="$eval $log_arg $strategy_args $merge_args"
+ eval="$eval \"$merge_name\" HEAD $merge_head $verbosity"
+ ;;
+esac
+eval "exec $eval"
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 1560e84..c2f6089 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -28,24 +28,81 @@ abort abort rebasing process and restore original branch
skip skip current patch and continue rebasing process
no-verify override pre-rebase hook from stopping the operation
root rebase all reachable commmits up to the root(s)
+autosquash move commits that begin with squash!/fixup! under -i
"
. git-sh-setup
require_work_tree
DOTEST="$GIT_DIR/rebase-merge"
+
+# The file containing rebase commands, comments, and empty lines.
+# This file is created by "git rebase -i" then edited by the user. As
+# the lines are processed, they are removed from the front of this
+# file and written to the tail of $DONE.
TODO="$DOTEST"/git-rebase-todo
+
+# The rebase command lines that have already been processed. A line
+# is moved here when it is first handled, before any associated user
+# actions.
DONE="$DOTEST"/done
+
+# The commit message that is planned to be used for any changes that
+# need to be committed following a user interaction.
MSG="$DOTEST"/message
+
+# The file into which is accumulated the suggested commit message for
+# squash/fixup commands. When the first of a series of squash/fixups
+# is seen, the file is created and the commit message from the
+# previous commit and from the first squash/fixup commit are written
+# to it. The commit message for each subsequent squash/fixup commit
+# is appended to the file as it is processed.
+#
+# The first line of the file is of the form
+# # This is a combination of $COUNT commits.
+# where $COUNT is the number of commits whose messages have been
+# written to the file so far (including the initial "pick" commit).
+# Each time that a commit message is processed, this line is read and
+# updated. It is deleted just before the combined commit is made.
SQUASH_MSG="$DOTEST"/message-squash
+
+# If the current series of squash/fixups has not yet included a squash
+# command, then this file exists and holds the commit message of the
+# original "pick" commit. (If the series ends without a "squash"
+# command, then this can be used as the commit message of the combined
+# commit without opening the editor.)
+FIXUP_MSG="$DOTEST"/message-fixup
+
+# $REWRITTEN is the name of a directory containing files for each
+# commit that is reachable by at least one merge base of $HEAD and
+# $UPSTREAM. They are not necessarily rewritten, but their children
+# might be. This ensures that commits on merged, but otherwise
+# unrelated side branches are left alone. (Think "X" in the man page's
+# example.)
REWRITTEN="$DOTEST"/rewritten
+
DROPPED="$DOTEST"/dropped
+
+# A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
+# GIT_AUTHOR_DATE that will be used for the commit that is currently
+# being rebased.
+AUTHOR_SCRIPT="$DOTEST"/author-script
+
+# When an "edit" rebase command is being processed, the SHA1 of the
+# commit to be edited is recorded in this file. When "git rebase
+# --continue" is executed, if there are any staged changes then they
+# will be amended to the HEAD commit, but only provided the HEAD
+# commit is still the commit to be edited. When any other rebase
+# command is processed, this file is deleted.
+AMEND="$DOTEST"/amend
+
PRESERVE_MERGES=
STRATEGY=
ONTO=
VERBOSE=
OK_TO_SKIP_PRE_REBASE=
REBASE_ROOT=
+AUTOSQUASH=
GIT_CHERRY_PICK_HELP=" After resolving the conflicts,
mark the corrected paths with 'git add <paths>', and
@@ -70,6 +127,11 @@ output () {
esac
}
+# Output the commit message for the specified commit.
+commit_message () {
+ git cat-file commit "$1" | sed "1,/^$/d"
+}
+
run_pre_rebase_hook () {
if test -z "$OK_TO_SKIP_PRE_REBASE" &&
test -x "$GIT_DIR/hooks/pre-rebase"
@@ -129,10 +191,10 @@ make_patch () {
echo "Root commit"
;;
esac > "$DOTEST"/patch
- test -f "$DOTEST"/message ||
- git cat-file commit "$1" | sed "1,/^$/d" > "$DOTEST"/message
- test -f "$DOTEST"/author-script ||
- get_author_ident_from_commit "$1" > "$DOTEST"/author-script
+ test -f "$MSG" ||
+ commit_message "$1" > "$MSG"
+ test -f "$AUTHOR_SCRIPT" ||
+ get_author_ident_from_commit "$1" > "$AUTHOR_SCRIPT"
}
die_with_patch () {
@@ -150,13 +212,22 @@ has_action () {
sane_grep '^[^#]' "$1" >/dev/null
}
+# Run command with GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
+# GIT_AUTHOR_DATE exported from the current environment.
+do_with_author () {
+ GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" \
+ GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" \
+ GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE" \
+ "$@"
+}
+
pick_one () {
no_ff=
case "$1" in -n) sha1=$2; no_ff=t ;; *) sha1=$1 ;; esac
output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1"
test -d "$REWRITTEN" &&
pick_one_preserving_merges "$@" && return
- if test ! -z "$REBASE_ROOT"
+ if test -n "$REBASE_ROOT"
then
output git cherry-pick "$@"
return
@@ -164,11 +235,10 @@ pick_one () {
parent_sha1=$(git rev-parse --verify $sha1^) ||
die "Could not get the parent of $sha1"
current_sha1=$(git rev-parse --verify HEAD)
- if test "$no_ff$current_sha1" = "$parent_sha1"; then
+ if test -z "$no_ff" && test "$current_sha1" = "$parent_sha1"
+ then
output git reset --hard $sha1
- test "a$1" = a-n && output git reset --soft $current_sha1
- sha1=$(git rev-parse --short $sha1)
- output warn Fast-forward to $sha1
+ output warn Fast-forward to $(git rev-parse --short $sha1)
else
output git cherry-pick "$@"
fi
@@ -269,14 +339,11 @@ pick_one_preserving_merges () {
# redo merge
author_script=$(get_author_ident_from_commit $sha1)
eval "$author_script"
- msg="$(git cat-file commit $sha1 | sed -e '1,/^$/d')"
+ msg="$(commit_message $sha1)"
# No point in merging the first parent, that's HEAD
new_parents=${new_parents# $first_parent}
- if ! GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" \
- GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" \
- GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE" \
- output git merge $STRATEGY -m "$msg" \
- $new_parents
+ if ! do_with_author output \
+ git merge $STRATEGY -m "$msg" $new_parents
then
printf "%s\n" "$msg" > "$GIT_DIR"/MERGE_MSG
die_with_patch $sha1 "Error redoing merge $sha1"
@@ -300,34 +367,66 @@ nth_string () {
esac
}
-make_squash_message () {
+update_squash_messages () {
if test -f "$SQUASH_MSG"; then
- COUNT=$(($(sed -n "s/^# This is [^0-9]*\([1-9][0-9]*\).*/\1/p" \
- < "$SQUASH_MSG" | sed -ne '$p')+1))
- echo "# This is a combination of $COUNT commits."
- sed -e 1d -e '2,/^./{
- /^$/d
- }' <"$SQUASH_MSG"
+ mv "$SQUASH_MSG" "$SQUASH_MSG".bak || exit
+ COUNT=$(($(sed -n \
+ -e "1s/^# This is a combination of \(.*\) commits\./\1/p" \
+ -e "q" < "$SQUASH_MSG".bak)+1))
+ {
+ echo "# This is a combination of $COUNT commits."
+ sed -e 1d -e '2,/^./{
+ /^$/d
+ }' <"$SQUASH_MSG".bak
+ } >$SQUASH_MSG
else
+ commit_message HEAD > "$FIXUP_MSG" || die "Cannot write $FIXUP_MSG"
COUNT=2
- echo "# This is a combination of two commits."
- echo "# The first commit's message is:"
- echo
- git cat-file commit HEAD | sed -e '1,/^$/d'
+ {
+ echo "# This is a combination of 2 commits."
+ echo "# The first commit's message is:"
+ echo
+ cat "$FIXUP_MSG"
+ } >$SQUASH_MSG
fi
- echo
- echo "# This is the $(nth_string $COUNT) commit message:"
- echo
- git cat-file commit $1 | sed -e '1,/^$/d'
+ case $1 in
+ squash)
+ rm -f "$FIXUP_MSG"
+ echo
+ echo "# This is the $(nth_string $COUNT) commit message:"
+ echo
+ commit_message $2
+ ;;
+ fixup)
+ echo
+ echo "# The $(nth_string $COUNT) commit message will be skipped:"
+ echo
+ commit_message $2 | sed -e 's/^/# /'
+ ;;
+ esac >>$SQUASH_MSG
}
peek_next_command () {
sed -n -e "/^#/d" -e "/^$/d" -e "s/ .*//p" -e "q" < "$TODO"
}
+# A squash/fixup has failed. Prepare the long version of the squash
+# commit message, then die_with_patch. This code path requires the
+# user to edit the combined commit message for all commits that have
+# been squashed/fixedup so far. So also erase the old squash
+# messages, effectively causing the combined commit to be used as the
+# new basis for any further squash/fixups. Args: sha1 rest
+die_failed_squash() {
+ mv "$SQUASH_MSG" "$MSG" || exit
+ rm -f "$FIXUP_MSG"
+ cp "$MSG" "$GIT_DIR"/MERGE_MSG || exit
+ warn
+ warn "Could not apply $1... $2"
+ die_with_patch $1 ""
+}
+
do_next () {
- rm -f "$DOTEST"/message "$DOTEST"/author-script \
- "$DOTEST"/amend || exit
+ rm -f "$MSG" "$AUTHOR_SCRIPT" "$AMEND" || exit
read command sha1 rest < "$TODO"
case "$command" in
'#'*|''|noop)
@@ -355,7 +454,7 @@ do_next () {
pick_one $sha1 ||
die_with_patch $sha1 "Could not apply $sha1... $rest"
make_patch $sha1
- git rev-parse --verify HEAD > "$DOTEST"/amend
+ git rev-parse --verify HEAD > "$AMEND"
warn "Stopped at $sha1... $rest"
warn "You can amend the commit now, with"
warn
@@ -367,52 +466,49 @@ do_next () {
warn
exit 0
;;
- squash|s)
- comment_for_reflog squash
+ squash|s|fixup|f)
+ case "$command" in
+ squash|s)
+ squash_style=squash
+ ;;
+ fixup|f)
+ squash_style=fixup
+ ;;
+ esac
+ comment_for_reflog $squash_style
test -f "$DONE" && has_action "$DONE" ||
- die "Cannot 'squash' without a previous commit"
+ die "Cannot '$squash_style' without a previous commit"
mark_action_done
- make_squash_message $sha1 > "$MSG"
- failed=f
+ update_squash_messages $squash_style $sha1
author_script=$(get_author_ident_from_commit HEAD)
+ echo "$author_script" > "$AUTHOR_SCRIPT"
+ eval "$author_script"
output git reset --soft HEAD^
- pick_one -n $sha1 || failed=t
+ pick_one -n $sha1 || die_failed_squash $sha1 "$rest"
case "$(peek_next_command)" in
- squash|s)
- USE_OUTPUT=output
- MSG_OPT=-F
- EDIT_OR_FILE="$MSG"
- cp "$MSG" "$SQUASH_MSG"
+ squash|s|fixup|f)
+ # This is an intermediate commit; its message will only be
+ # used in case of trouble. So use the long version:
+ do_with_author output git commit --no-verify -F "$SQUASH_MSG" ||
+ die_failed_squash $sha1 "$rest"
;;
*)
- USE_OUTPUT=
- MSG_OPT=
- EDIT_OR_FILE=-e
- rm -f "$SQUASH_MSG" || exit
- cp "$MSG" "$GIT_DIR"/SQUASH_MSG
- rm -f "$GIT_DIR"/MERGE_MSG || exit
+ # This is the final command of this squash/fixup group
+ if test -f "$FIXUP_MSG"
+ then
+ do_with_author git commit --no-verify -F "$FIXUP_MSG" ||
+ die_failed_squash $sha1 "$rest"
+ else
+ cp "$SQUASH_MSG" "$GIT_DIR"/SQUASH_MSG || exit
+ rm -f "$GIT_DIR"/MERGE_MSG
+ do_with_author git commit --no-verify -e ||
+ die_failed_squash $sha1 "$rest"
+ fi
+ rm -f "$SQUASH_MSG" "$FIXUP_MSG"
;;
esac
- echo "$author_script" > "$DOTEST"/author-script
- if test $failed = f
- then
- # This is like --amend, but with a different message
- eval "$author_script"
- GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" \
- GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" \
- GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE" \
- $USE_OUTPUT git commit --no-verify \
- $MSG_OPT "$EDIT_OR_FILE" || failed=t
- fi
- if test $failed = t
- then
- cp "$MSG" "$GIT_DIR"/MERGE_MSG
- warn
- warn "Could not apply $sha1... $rest"
- die_with_patch $sha1 ""
- fi
;;
*)
warn "Unknown command: $command $sha1 $rest"
@@ -495,6 +591,37 @@ get_saved_options () {
test -f "$DOTEST"/rebase-root && REBASE_ROOT=t
}
+# Rearrange the todo list that has both "pick sha1 msg" and
+# "pick sha1 fixup!/squash! msg" appears in it so that the latter
+# comes immediately after the former, and change "pick" to
+# "fixup"/"squash".
+rearrange_squash () {
+ sed -n -e 's/^pick \([0-9a-f]*\) \(squash\)! /\1 \2 /p' \
+ -e 's/^pick \([0-9a-f]*\) \(fixup\)! /\1 \2 /p' \
+ "$1" >"$1.sq"
+ test -s "$1.sq" || return
+
+ used=
+ while read pick sha1 message
+ do
+ case " $used" in
+ *" $sha1 "*) continue ;;
+ esac
+ echo "$pick $sha1 $message"
+ while read squash action msg
+ do
+ case "$message" in
+ "$msg"*)
+ echo "$action $squash $action! $msg"
+ used="$used$squash "
+ ;;
+ esac
+ done <"$1.sq"
+ done >"$1.rearranged" <"$1"
+ cat "$1.rearranged" >"$1"
+ rm -f "$1.sq" "$1.rearranged"
+}
+
LF='
'
parse_onto () {
@@ -541,21 +668,20 @@ do
then
: Nothing to commit -- skip this
else
- . "$DOTEST"/author-script ||
+ . "$AUTHOR_SCRIPT" ||
die "Cannot find the author identity"
amend=
- if test -f "$DOTEST"/amend
+ if test -f "$AMEND"
then
amend=$(git rev-parse --verify HEAD)
- test "$amend" = $(cat "$DOTEST"/amend) ||
+ test "$amend" = $(cat "$AMEND") ||
die "\
You have uncommitted changes in your working tree. Please, commit them
first and then run 'git rebase --continue' again."
git reset --soft HEAD^ ||
die "Cannot rewind the HEAD"
fi
- export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE &&
- git commit --no-verify -F "$DOTEST"/message -e || {
+ do_with_author git commit --no-verify -F "$MSG" -e || {
test -n "$amend" && git reset --soft $amend
die "Could not commit staged changes."
}
@@ -619,6 +745,9 @@ first and then run 'git rebase --continue' again."
--root)
REBASE_ROOT=t
;;
+ --autosquash)
+ AUTOSQUASH=t
+ ;;
--onto)
shift
ONTO=$(parse_onto "$1") ||
@@ -679,13 +808,6 @@ first and then run 'git rebase --continue' again."
test t = "$VERBOSE" && : > "$DOTEST"/verbose
if test t = "$PRESERVE_MERGES"
then
- # $REWRITTEN contains files for each commit that is
- # reachable by at least one merge base of $HEAD and
- # $UPSTREAM. They are not necessarily rewritten, but
- # their children might be.
- # This ensures that commits on merged, but otherwise
- # unrelated side branches are left alone. (Think "X"
- # in the man page's example.)
if test -z "$REBASE_ROOT"
then
mkdir "$REWRITTEN" &&
@@ -778,6 +900,7 @@ first and then run 'git rebase --continue' again."
fi
test -s "$TODO" || echo noop >> "$TODO"
+ test -n "$AUTOSQUASH" && rearrange_squash "$TODO"
cat >> "$TODO" << EOF
# Rebase $SHORTREVISIONS onto $SHORTONTO
@@ -787,6 +910,7 @@ first and then run 'git rebase --continue' again."
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
+# f, fixup = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index dfcb807..d56426d 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -120,20 +120,11 @@ is_bare_repository () {
}
cd_to_toplevel () {
- cdup=$(git rev-parse --show-cdup)
- if test ! -z "$cdup"
- then
- # The "-P" option says to follow "physical" directory
- # structure instead of following symbolic links. When cdup is
- # "../", this means following the ".." entry in the current
- # directory instead textually removing a symlink path element
- # from the PWD shell variable. The "-P" behavior is more
- # consistent with the C-style chdir used by most of Git.
- cd -P "$cdup" || {
- echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree"
- exit 1
- }
- fi
+ cdup=$(git rev-parse --show-toplevel) &&
+ cd "$cdup" || {
+ echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree"
+ exit 1
+ }
}
require_work_tree () {
diff --git a/git.c b/git.c
index 11544cd..32f76e1 100644
--- a/git.c
+++ b/git.c
@@ -317,8 +317,10 @@ static void handle_internal_command(int argc, const char **argv)
{ "fsck-objects", cmd_fsck, RUN_SETUP },
{ "gc", cmd_gc, RUN_SETUP },
{ "get-tar-commit-id", cmd_get_tar_commit_id },
- { "grep", cmd_grep, RUN_SETUP | USE_PAGER },
+ { "grep", cmd_grep, USE_PAGER },
+ { "hash-object", cmd_hash_object },
{ "help", cmd_help },
+ { "index-pack", cmd_index_pack },
{ "init", cmd_init_db },
{ "init-db", cmd_init_db },
{ "log", cmd_log, RUN_SETUP | USE_PAGER },
@@ -330,13 +332,21 @@ static void handle_internal_command(int argc, const char **argv)
{ "merge", cmd_merge, RUN_SETUP | NEED_WORK_TREE },
{ "merge-base", cmd_merge_base, RUN_SETUP },
{ "merge-file", cmd_merge_file },
+ { "merge-index", cmd_merge_index, RUN_SETUP },
{ "merge-ours", cmd_merge_ours, RUN_SETUP },
{ "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
+ { "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
+ { "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
{ "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
+ { "merge-tree", cmd_merge_tree, RUN_SETUP },
+ { "mktag", cmd_mktag, RUN_SETUP },
{ "mktree", cmd_mktree, RUN_SETUP },
{ "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
{ "name-rev", cmd_name_rev, RUN_SETUP },
+ { "notes", cmd_notes, RUN_SETUP },
{ "pack-objects", cmd_pack_objects, RUN_SETUP },
+ { "pack-redundant", cmd_pack_redundant, RUN_SETUP },
+ { "patch-id", cmd_patch_id },
{ "peek-remote", cmd_ls_remote },
{ "pickaxe", cmd_blame, RUN_SETUP },
{ "prune", cmd_prune, RUN_SETUP },
@@ -363,11 +373,13 @@ static void handle_internal_command(int argc, const char **argv)
{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
{ "tag", cmd_tag, RUN_SETUP },
{ "tar-tree", cmd_tar_tree },
+ { "unpack-file", cmd_unpack_file, RUN_SETUP },
{ "unpack-objects", cmd_unpack_objects, RUN_SETUP },
{ "update-index", cmd_update_index, RUN_SETUP },
{ "update-ref", cmd_update_ref, RUN_SETUP },
{ "update-server-info", cmd_update_server_info, RUN_SETUP },
{ "upload-archive", cmd_upload_archive },
+ { "var", cmd_var },
{ "verify-tag", cmd_verify_tag, RUN_SETUP },
{ "version", cmd_version },
{ "whatchanged", cmd_whatchanged, RUN_SETUP | USE_PAGER },
diff --git a/grep.c b/grep.c
index bdadf2c..8e1f7de 100644
--- a/grep.c
+++ b/grep.c
@@ -29,13 +29,6 @@ void append_grep_pattern(struct grep_opt *opt, const char *pat,
p->next = NULL;
}
-static int is_fixed(const char *s)
-{
- while (*s && !is_regex_special(*s))
- s++;
- return !*s;
-}
-
static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
{
int err;
@@ -43,7 +36,7 @@ static void compile_regexp(struct grep_pat *p, struct grep_opt *opt)
p->word_regexp = opt->word_regexp;
p->ignore_case = opt->ignore_case;
- if (opt->fixed || is_fixed(p->pattern))
+ if (opt->fixed)
p->fixed = 1;
if (opt->regflags & REG_ICASE)
p->fixed = 0;
@@ -615,6 +608,65 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
}
}
+static int should_lookahead(struct grep_opt *opt)
+{
+ struct grep_pat *p;
+
+ if (opt->extended)
+ return 0; /* punt for too complex stuff */
+ if (opt->invert)
+ return 0;
+ for (p = opt->pattern_list; p; p = p->next) {
+ if (p->token != GREP_PATTERN)
+ return 0; /* punt for "header only" and stuff */
+ }
+ return 1;
+}
+
+static int look_ahead(struct grep_opt *opt,
+ unsigned long *left_p,
+ unsigned *lno_p,
+ char **bol_p)
+{
+ unsigned lno = *lno_p;
+ char *bol = *bol_p;
+ struct grep_pat *p;
+ char *sp, *last_bol;
+ regoff_t earliest = -1;
+
+ for (p = opt->pattern_list; p; p = p->next) {
+ int hit;
+ regmatch_t m;
+
+ if (p->fixed)
+ hit = !fixmatch(p->pattern, bol, p->ignore_case, &m);
+ else
+ hit = !regexec(&p->regexp, bol, 1, &m, 0);
+ if (!hit || m.rm_so < 0 || m.rm_eo < 0)
+ continue;
+ if (earliest < 0 || m.rm_so < earliest)
+ earliest = m.rm_so;
+ }
+
+ if (earliest < 0) {
+ *bol_p = bol + *left_p;
+ *left_p = 0;
+ return 1;
+ }
+ for (sp = bol + earliest; bol < sp && sp[-1] != '\n'; sp--)
+ ; /* find the beginning of the line */
+ last_bol = sp;
+
+ for (sp = bol; sp < last_bol; sp++) {
+ if (*sp == '\n')
+ lno++;
+ }
+ *left_p -= last_bol - bol;
+ *bol_p = last_bol;
+ *lno_p = lno;
+ return 0;
+}
+
static int grep_buffer_1(struct grep_opt *opt, const char *name,
char *buf, unsigned long size, int collect_hits)
{
@@ -624,6 +676,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
unsigned last_hit = 0;
int binary_match_only = 0;
unsigned count = 0;
+ int try_lookahead = 0;
enum grep_context ctx = GREP_CONTEXT_HEAD;
xdemitconf_t xecfg;
@@ -652,11 +705,26 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
opt->priv = &xecfg;
}
}
+ try_lookahead = should_lookahead(opt);
while (left) {
char *eol, ch;
int hit;
+ /*
+ * look_ahead() skips quicly to the line that possibly
+ * has the next hit; don't call it if we need to do
+ * something more than just skipping the current line
+ * in response to an unmatch for the current line. E.g.
+ * inside a post-context window, we will show the current
+ * line as a context around the previous hit when it
+ * doesn't hit.
+ */
+ if (try_lookahead
+ && !(last_hit
+ && lno <= last_hit + opt->post_context)
+ && look_ahead(opt, &left, &lno, &bol))
+ break;
eol = end_of_line(bol, &left);
ch = *eol;
*eol = 0;
diff --git a/grep.h b/grep.h
index 75370f6..0c61b00 100644
--- a/grep.h
+++ b/grep.h
@@ -85,7 +85,6 @@ struct grep_opt {
int max_depth;
int funcname;
char color_match[COLOR_MAXLEN];
- const char *color_external;
int regflags;
unsigned pre_context;
unsigned post_context;
diff --git a/hex.c b/hex.c
new file mode 100644
index 0000000..bb402fb
--- /dev/null
+++ b/hex.c
@@ -0,0 +1,67 @@
+#include "cache.h"
+
+const signed char hexval_table[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 00-07 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 08-0f */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 10-17 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 18-1f */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 20-27 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 28-2f */
+ 0, 1, 2, 3, 4, 5, 6, 7, /* 30-37 */
+ 8, 9, -1, -1, -1, -1, -1, -1, /* 38-3f */
+ -1, 10, 11, 12, 13, 14, 15, -1, /* 40-47 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 48-4f */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 50-57 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 58-5f */
+ -1, 10, 11, 12, 13, 14, 15, -1, /* 60-67 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 68-67 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 70-77 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 78-7f */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 80-87 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 88-8f */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 90-97 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* 98-9f */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* a0-a7 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* a8-af */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* b0-b7 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* b8-bf */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* c0-c7 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* c8-cf */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* d0-d7 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* d8-df */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* e0-e7 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* e8-ef */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* f0-f7 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* f8-ff */
+};
+
+int get_sha1_hex(const char *hex, unsigned char *sha1)
+{
+ int i;
+ for (i = 0; i < 20; i++) {
+ unsigned int val = (hexval(hex[0]) << 4) | hexval(hex[1]);
+ if (val & ~0xff)
+ return -1;
+ *sha1++ = val;
+ hex += 2;
+ }
+ return 0;
+}
+
+char *sha1_to_hex(const unsigned char *sha1)
+{
+ static int bufno;
+ static char hexbuffer[4][50];
+ static const char hex[] = "0123456789abcdef";
+ char *buffer = hexbuffer[3 & ++bufno], *buf = buffer;
+ int i;
+
+ for (i = 0; i < 20; i++) {
+ unsigned int val = *sha1++;
+ *buf++ = hex[val >> 4];
+ *buf++ = hex[val & 0xf];
+ }
+ *buf = '\0';
+
+ return buffer;
+}
diff --git a/http.c b/http.c
index 5c3efb9..deab595 100644
--- a/http.c
+++ b/http.c
@@ -651,7 +651,7 @@ static void closedown_active_slot(struct active_request_slot *slot)
slot->in_use = 0;
}
-void release_active_slot(struct active_request_slot *slot)
+static void release_active_slot(struct active_request_slot *slot)
{
closedown_active_slot(slot);
if (slot->curl && curl_session_count > min_curl_sessions) {
@@ -834,7 +834,13 @@ int http_get_strbuf(const char *url, struct strbuf *result, int options)
return http_request(url, result, HTTP_REQUEST_STRBUF, options);
}
-int http_get_file(const char *url, const char *filename, int options)
+/*
+ * Downloads an url and stores the result in the given file.
+ *
+ * If a previous interrupted download is detected (i.e. a previous temporary
+ * file is still around) the download is resumed.
+ */
+static int http_get_file(const char *url, const char *filename, int options)
{
int ret;
struct strbuf tmpfile = STRBUF_INIT;
diff --git a/http.h b/http.h
index f828e1d..5c9441c 100644
--- a/http.h
+++ b/http.h
@@ -81,7 +81,6 @@ extern int start_active_slot(struct active_request_slot *slot);
extern void run_active_slot(struct active_request_slot *slot);
extern void finish_active_slot(struct active_request_slot *slot);
extern void finish_all_active_slots(void);
-extern void release_active_slot(struct active_request_slot *slot);
#ifdef USE_CURL_MULTI
extern void fill_active_slots(void);
@@ -136,14 +135,6 @@ extern char *get_remote_object_url(const char *url, const char *hex,
int http_get_strbuf(const char *url, struct strbuf *result, int options);
/*
- * Downloads an url and stores the result in the given file.
- *
- * If a previous interrupted download is detected (i.e. a previous temporary
- * file is still around) the download is resumed.
- */
-int http_get_file(const char *url, const char *filename, int options);
-
-/*
* Prints an error message using error() containing url and curl_errorstr,
* and returns ret.
*/
diff --git a/ident.c b/ident.c
index 26409b2..9e24388 100644
--- a/ident.c
+++ b/ident.c
@@ -85,10 +85,11 @@ static void setup_ident(void)
if (!git_default_email[0]) {
const char *email = getenv("EMAIL");
- if (email && email[0])
+ if (email && email[0]) {
strlcpy(git_default_email, email,
sizeof(git_default_email));
- else {
+ user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
+ } else {
if (!pw)
pw = getpwuid(getuid());
if (!pw)
@@ -168,8 +169,6 @@ static int copy(char *buf, size_t size, int offset, const char *src)
return offset;
}
-static const char au_env[] = "GIT_AUTHOR_NAME";
-static const char co_env[] = "GIT_COMMITTER_NAME";
static const char *env_hint =
"\n"
"*** Please tell me who you are.\n"
@@ -204,7 +203,7 @@ const char *fmt_ident(const char *name, const char *email,
if ((warn_on_no_name || error_on_no_name) &&
name == git_default_name && env_hint) {
- fprintf(stderr, env_hint, au_env, co_env);
+ fputs(env_hint, stderr);
env_hint = NULL; /* warn only once */
}
if (error_on_no_name)
@@ -251,11 +250,21 @@ const char *git_author_info(int flag)
const char *git_committer_info(int flag)
{
- if (getenv("GIT_COMMITTER_NAME") &&
- getenv("GIT_COMMITTER_EMAIL"))
- user_ident_explicitly_given = 1;
+ if (getenv("GIT_COMMITTER_NAME"))
+ user_ident_explicitly_given |= IDENT_NAME_GIVEN;
+ if (getenv("GIT_COMMITTER_EMAIL"))
+ user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
return fmt_ident(getenv("GIT_COMMITTER_NAME"),
getenv("GIT_COMMITTER_EMAIL"),
getenv("GIT_COMMITTER_DATE"),
flag);
}
+
+int user_ident_sufficiently_given(void)
+{
+#ifndef WINDOWS
+ return (user_ident_explicitly_given & IDENT_MAIL_GIVEN);
+#else
+ return (user_ident_explicitly_given == IDENT_ALL_GIVEN);
+#endif
+}
diff --git a/ll-merge.c b/ll-merge.c
index 18511e2..4c7f11b 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -18,7 +18,8 @@ typedef int (*ll_merge_fn)(const struct ll_merge_driver *,
mmfile_t *orig,
mmfile_t *src1, const char *name1,
mmfile_t *src2, const char *name2,
- int virtual_ancestor);
+ int flag,
+ int marker_size);
struct ll_merge_driver {
const char *name;
@@ -38,14 +39,14 @@ static int ll_binary_merge(const struct ll_merge_driver *drv_unused,
mmfile_t *orig,
mmfile_t *src1, const char *name1,
mmfile_t *src2, const char *name2,
- int virtual_ancestor)
+ int flag, int marker_size)
{
/*
* The tentative merge result is "ours" for the final round,
* or common ancestor for an internal merge. Still return
* "conflicted merge" status.
*/
- mmfile_t *stolen = virtual_ancestor ? orig : src1;
+ mmfile_t *stolen = (flag & 01) ? orig : src1;
result->ptr = stolen->ptr;
result->size = stolen->size;
@@ -59,10 +60,11 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
mmfile_t *orig,
mmfile_t *src1, const char *name1,
mmfile_t *src2, const char *name2,
- int virtual_ancestor)
+ int flag, int marker_size)
{
- xpparam_t xpp;
+ xmparam_t xmp;
int style = 0;
+ int favor = (flag >> 1) & 03;
if (buffer_is_binary(orig->ptr, orig->size) ||
buffer_is_binary(src1->ptr, src1->size) ||
@@ -73,16 +75,18 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
path,
orig, src1, name1,
src2, name2,
- virtual_ancestor);
+ flag, marker_size);
}
- memset(&xpp, 0, sizeof(xpp));
+ memset(&xmp, 0, sizeof(xmp));
if (git_xmerge_style >= 0)
style = git_xmerge_style;
+ if (marker_size > 0)
+ xmp.marker_size = marker_size;
return xdl_merge(orig,
src1, name1,
src2, name2,
- &xpp, XDL_MERGE_ZEALOUS | style,
+ &xmp, XDL_MERGE_FLAGS(XDL_MERGE_ZEALOUS, style, favor),
result);
}
@@ -92,11 +96,10 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused,
mmfile_t *orig,
mmfile_t *src1, const char *name1,
mmfile_t *src2, const char *name2,
- int virtual_ancestor)
+ int flag, int marker_size)
{
char *src, *dst;
long size;
- const int marker_size = 7;
int status, saved_style;
/* We have to force the RCS "merge" style */
@@ -104,7 +107,7 @@ static int ll_union_merge(const struct ll_merge_driver *drv_unused,
git_xmerge_style = 0;
status = ll_xdl_merge(drv_unused, result, path_unused,
orig, src1, NULL, src2, NULL,
- virtual_ancestor);
+ flag, marker_size);
git_xmerge_style = saved_style;
if (status <= 0)
return status;
@@ -165,14 +168,15 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
mmfile_t *orig,
mmfile_t *src1, const char *name1,
mmfile_t *src2, const char *name2,
- int virtual_ancestor)
+ int flag, int marker_size)
{
- char temp[3][50];
+ char temp[4][50];
struct strbuf cmd = STRBUF_INIT;
struct strbuf_expand_dict_entry dict[] = {
{ "O", temp[0] },
{ "A", temp[1] },
{ "B", temp[2] },
+ { "L", temp[3] },
{ NULL }
};
const char *args[] = { NULL, NULL };
@@ -187,6 +191,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
create_temp(orig, temp[0]);
create_temp(src1, temp[1]);
create_temp(src2, temp[2]);
+ sprintf(temp[3], "%d", marker_size);
strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict);
@@ -279,6 +284,7 @@ static int read_merge_config(const char *var, const char *value, void *cb)
* %O - temporary file name for the merge base.
* %A - temporary file name for our version.
* %B - temporary file name for the other branches' version.
+ * %L - conflict marker length
*
* The external merge driver should write the results in the
* file named by %A, and signal that it has done with zero exit
@@ -339,16 +345,13 @@ static const struct ll_merge_driver *find_ll_merge_driver(const char *merge_attr
return &ll_merge_drv[LL_TEXT_MERGE];
}
-static const char *git_path_check_merge(const char *path)
+static int git_path_check_merge(const char *path, struct git_attr_check check[2])
{
- static struct git_attr_check attr_merge_check;
-
- if (!attr_merge_check.attr)
- attr_merge_check.attr = git_attr("merge", 5);
-
- if (git_checkattr(path, 1, &attr_merge_check))
- return NULL;
- return attr_merge_check.value;
+ if (!check[0].attr) {
+ check[0].attr = git_attr("merge");
+ check[1].attr = git_attr("conflict-marker-size");
+ }
+ return git_checkattr(path, 2, check);
}
int ll_merge(mmbuffer_t *result_buf,
@@ -356,18 +359,41 @@ int ll_merge(mmbuffer_t *result_buf,
mmfile_t *ancestor,
mmfile_t *ours, const char *our_label,
mmfile_t *theirs, const char *their_label,
- int virtual_ancestor)
+ int flag)
{
- const char *ll_driver_name;
+ static struct git_attr_check check[2];
+ const char *ll_driver_name = NULL;
+ int marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
const struct ll_merge_driver *driver;
-
- ll_driver_name = git_path_check_merge(path);
+ int virtual_ancestor = flag & 01;
+
+ if (!git_path_check_merge(path, check)) {
+ ll_driver_name = check[0].value;
+ if (check[1].value) {
+ marker_size = atoi(check[1].value);
+ if (marker_size <= 0)
+ marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
+ }
+ }
driver = find_ll_merge_driver(ll_driver_name);
-
if (virtual_ancestor && driver->recursive)
driver = find_ll_merge_driver(driver->recursive);
- return driver->fn(driver, result_buf, path,
- ancestor,
- ours, our_label,
- theirs, their_label, virtual_ancestor);
+ return driver->fn(driver, result_buf, path, ancestor,
+ ours, our_label, theirs, their_label,
+ flag, marker_size);
+}
+
+int ll_merge_marker_size(const char *path)
+{
+ static struct git_attr_check check;
+ int marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
+
+ if (!check.attr)
+ check.attr = git_attr("conflict-marker-size");
+ if (!git_checkattr(path, 1, &check) && check.value) {
+ marker_size = atoi(check.value);
+ if (marker_size <= 0)
+ marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
+ }
+ return marker_size;
}
diff --git a/ll-merge.h b/ll-merge.h
index 5388422..5788922 100644
--- a/ll-merge.h
+++ b/ll-merge.h
@@ -10,6 +10,8 @@ int ll_merge(mmbuffer_t *result_buf,
mmfile_t *ancestor,
mmfile_t *ours, const char *our_label,
mmfile_t *theirs, const char *their_label,
- int virtual_ancestor);
+ int flag);
+
+int ll_merge_marker_size(const char *path);
#endif
diff --git a/log-tree.c b/log-tree.c
index 0fdf159..27afcf6 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -284,6 +284,7 @@ void show_log(struct rev_info *opt)
struct pretty_print_context ctx = {0};
opt->loginfo = NULL;
+ ctx.show_notes = opt->show_notes;
if (!opt->verbose_header) {
graph_show_commit(opt->graph);
diff --git a/mailmap.c b/mailmap.c
index f167c00..b68c1fe 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -243,8 +243,3 @@ int map_user(struct string_list *map,
debug_mm("map_user: --\n");
return 0;
}
-
-int map_email(struct string_list *map, const char *email, char *name, int maxlen)
-{
- return map_user(map, (char *)email, 0, name, maxlen);
-}
diff --git a/mailmap.h b/mailmap.h
index 4b2ca3a..d5c3664 100644
--- a/mailmap.h
+++ b/mailmap.h
@@ -4,7 +4,6 @@
int read_mailmap(struct string_list *map, char **repo_abbrev);
void clear_mailmap(struct string_list *map);
-int map_email(struct string_list *mailmap, const char *email, char *name, int maxlen);
int map_user(struct string_list *mailmap,
char *email, int maxlen_email, char *name, int maxlen_name);
diff --git a/match-trees.c b/match-trees.c
index 0fd6df7..26f7ed1 100644
--- a/match-trees.c
+++ b/match-trees.c
@@ -185,7 +185,7 @@ static void match_trees(const unsigned char *hash1,
* tree object by replacing it with another tree "hash2".
*/
static int splice_tree(const unsigned char *hash1,
- char *prefix,
+ const char *prefix,
const unsigned char *hash2,
unsigned char *result)
{
@@ -264,6 +264,13 @@ void shift_tree(const unsigned char *hash1,
char *del_prefix;
int add_score, del_score;
+ /*
+ * NEEDSWORK: this limits the recursion depth to hardcoded
+ * value '2' to avoid excessive overhead.
+ */
+ if (!depth_limit)
+ depth_limit = 2;
+
add_score = del_score = score_trees(hash1, hash2);
add_prefix = xcalloc(1, 1);
del_prefix = xcalloc(1, 1);
@@ -301,3 +308,63 @@ void shift_tree(const unsigned char *hash1,
splice_tree(hash1, add_prefix, hash2, shifted);
}
+
+/*
+ * The user says the trees will be shifted by this much.
+ * Unfortunately we cannot fundamentally tell which one to
+ * be prefixed, as recursive merge can work in either direction.
+ */
+void shift_tree_by(const unsigned char *hash1,
+ const unsigned char *hash2,
+ unsigned char *shifted,
+ const char *shift_prefix)
+{
+ unsigned char sub1[20], sub2[20];
+ unsigned mode1, mode2;
+ unsigned candidate = 0;
+
+ /* Can hash2 be a tree at shift_prefix in tree hash1? */
+ if (!get_tree_entry(hash1, shift_prefix, sub1, &mode1) &&
+ S_ISDIR(mode1))
+ candidate |= 1;
+
+ /* Can hash1 be a tree at shift_prefix in tree hash2? */
+ if (!get_tree_entry(hash2, shift_prefix, sub2, &mode2) &&
+ S_ISDIR(mode2))
+ candidate |= 2;
+
+ if (candidate == 3) {
+ /* Both are plausible -- we need to evaluate the score */
+ int best_score = score_trees(hash1, hash2);
+ int score;
+
+ candidate = 0;
+ score = score_trees(sub1, hash2);
+ if (score > best_score) {
+ candidate = 1;
+ best_score = score;
+ }
+ score = score_trees(sub2, hash1);
+ if (score > best_score)
+ candidate = 2;
+ }
+
+ if (!candidate) {
+ /* Neither is plausible -- do not shift */
+ hashcpy(shifted, hash2);
+ return;
+ }
+
+ if (candidate == 1)
+ /*
+ * shift tree2 down by adding shift_prefix above it
+ * to match tree1.
+ */
+ splice_tree(hash1, shift_prefix, hash2, shifted);
+ else
+ /*
+ * shift tree2 up by removing shift_prefix from it
+ * to match tree1.
+ */
+ hashcpy(shifted, sub2);
+}
diff --git a/merge-file.c b/merge-file.c
index 3120a95..fd34d76 100644
--- a/merge-file.c
+++ b/merge-file.c
@@ -1,6 +1,7 @@
#include "cache.h"
#include "run-command.h"
#include "xdiff-interface.h"
+#include "ll-merge.h"
#include "blob.h"
static int fill_mmfile_blob(mmfile_t *f, struct blob *obj)
@@ -24,16 +25,13 @@ static void free_mmfile(mmfile_t *f)
free(f->ptr);
}
-static void *three_way_filemerge(mmfile_t *base, mmfile_t *our, mmfile_t *their, unsigned long *size)
+static void *three_way_filemerge(const char *path, mmfile_t *base, mmfile_t *our, mmfile_t *their, unsigned long *size)
{
- mmbuffer_t res;
- xpparam_t xpp;
int merge_status;
+ mmbuffer_t res;
- memset(&xpp, 0, sizeof(xpp));
- merge_status = xdl_merge(base, our, ".our", their, ".their",
- &xpp, XDL_MERGE_ZEALOUS, &res);
-
+ merge_status = ll_merge(&res, path, base,
+ our, ".our", their, ".their", 0);
if (merge_status < 0)
return NULL;
@@ -75,7 +73,7 @@ static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2)
return xdi_diff(f1, f2, &xpp, &xecfg, &ecb);
}
-void *merge_file(struct blob *base, struct blob *our, struct blob *their, unsigned long *size)
+void *merge_file(const char *path, struct blob *base, struct blob *our, struct blob *their, unsigned long *size)
{
void *res = NULL;
mmfile_t f1, f2, common;
@@ -108,7 +106,7 @@ void *merge_file(struct blob *base, struct blob *our, struct blob *their, unsign
if (generate_common_file(&common, &f1, &f2) < 0)
goto out_free_f2_f1;
}
- res = three_way_filemerge(&common, &f1, &f2, size);
+ res = three_way_filemerge(path, &common, &f1, &f2, size);
free_mmfile(&common);
out_free_f2_f1:
free_mmfile(&f2);
diff --git a/merge-recursive.c b/merge-recursive.c
index dd4fbd0..cb53b01 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -21,15 +21,17 @@
#include "merge-recursive.h"
#include "dir.h"
-static struct tree *shift_tree_object(struct tree *one, struct tree *two)
+static struct tree *shift_tree_object(struct tree *one, struct tree *two,
+ const char *subtree_shift)
{
unsigned char shifted[20];
- /*
- * NEEDSWORK: this limits the recursion depth to hardcoded
- * value '2' to avoid excessive overhead.
- */
- shift_tree(one->object.sha1, two->object.sha1, shifted, 2);
+ if (!*subtree_shift) {
+ shift_tree(one->object.sha1, two->object.sha1, shifted, 0);
+ } else {
+ shift_tree_by(one->object.sha1, two->object.sha1, shifted,
+ subtree_shift);
+ }
if (!hashcmp(two->object.sha1, shifted))
return two;
return lookup_tree(shifted);
@@ -200,14 +202,14 @@ struct tree *write_tree_from_memory(struct merge_options *o)
if (unmerged_cache()) {
int i;
- output(o, 0, "There are unmerged index entries:");
+ fprintf(stderr, "BUG: There are unmerged index entries:\n");
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];
if (ce_stage(ce))
- output(o, 0, "%d %.*s", ce_stage(ce),
- (int)ce_namelen(ce), ce->name);
+ fprintf(stderr, "BUG: %d %.*s", ce_stage(ce),
+ (int)ce_namelen(ce), ce->name);
}
- return NULL;
+ die("Bug in merge-recursive.c");
}
if (!active_cache_tree)
@@ -625,6 +627,23 @@ static int merge_3way(struct merge_options *o,
mmfile_t orig, src1, src2;
char *name1, *name2;
int merge_status;
+ int favor;
+
+ if (o->call_depth)
+ favor = 0;
+ else {
+ switch (o->recursive_variant) {
+ case MERGE_RECURSIVE_OURS:
+ favor = XDL_MERGE_FAVOR_OURS;
+ break;
+ case MERGE_RECURSIVE_THEIRS:
+ favor = XDL_MERGE_FAVOR_THEIRS;
+ break;
+ default:
+ favor = 0;
+ break;
+ }
+ }
if (strcmp(a->path, b->path)) {
name1 = xstrdup(mkpath("%s:%s", branch1, a->path));
@@ -640,7 +659,7 @@ static int merge_3way(struct merge_options *o,
merge_status = ll_merge(result_buf, a->path, &orig,
&src1, name1, &src2, name2,
- o->call_depth);
+ (!!o->call_depth) | (favor << 1));
free(name1);
free(name2);
@@ -1201,9 +1220,9 @@ int merge_trees(struct merge_options *o,
{
int code, clean;
- if (o->subtree_merge) {
- merge = shift_tree_object(head, merge);
- common = shift_tree_object(head, common);
+ if (o->subtree_shift) {
+ merge = shift_tree_object(head, merge, o->subtree_shift);
+ common = shift_tree_object(head, common, o->subtree_shift);
}
if (sha_eq(common->object.sha1, merge->object.sha1)) {
diff --git a/merge-recursive.h b/merge-recursive.h
index d8bc729..be8410a 100644
--- a/merge-recursive.h
+++ b/merge-recursive.h
@@ -6,7 +6,12 @@
struct merge_options {
const char *branch1;
const char *branch2;
- unsigned subtree_merge : 1;
+ enum {
+ MERGE_RECURSIVE_NORMAL = 0,
+ MERGE_RECURSIVE_OURS,
+ MERGE_RECURSIVE_THEIRS,
+ } recursive_variant;
+ const char *subtree_shift;
unsigned buffer_output : 1;
int verbosity;
int diff_rename_limit;
diff --git a/notes.c b/notes.c
index 023adce..3ba3e6d 100644
--- a/notes.c
+++ b/notes.c
@@ -1,7 +1,7 @@
#include "cache.h"
-#include "commit.h"
#include "notes.h"
-#include "refs.h"
+#include "blob.h"
+#include "tree.h"
#include "utf8.h"
#include "strbuf.h"
#include "tree-walk.h"
@@ -25,10 +25,10 @@ struct int_node {
/*
* Leaf nodes come in two variants, note entries and subtree entries,
* distinguished by the LSb of the leaf node pointer (see above).
- * As a note entry, the key is the SHA1 of the referenced commit, and the
+ * As a note entry, the key is the SHA1 of the referenced object, and the
* value is the SHA1 of the note object.
* As a subtree entry, the key is the prefix SHA1 (w/trailing NULs) of the
- * referenced commit, using the last byte of the key to store the length of
+ * referenced object, using the last byte of the key to store the length of
* the prefix. The value is the SHA1 of the tree object containing the notes
* subtree.
*/
@@ -37,6 +37,21 @@ struct leaf_node {
unsigned char val_sha1[20];
};
+/*
+ * A notes tree may contain entries that are not notes, and that do not follow
+ * the naming conventions of notes. There are typically none/few of these, but
+ * we still need to keep track of them. Keep a simple linked list sorted alpha-
+ * betically on the non-note path. The list is populated when parsing tree
+ * objects in load_subtree(), and the non-notes are correctly written back into
+ * the tree objects produced by write_notes_tree().
+ */
+struct non_note {
+ struct non_note *next; /* grounded (last->next == NULL) */
+ char *path;
+ unsigned int mode;
+ unsigned char sha1[20];
+};
+
#define PTR_TYPE_NULL 0
#define PTR_TYPE_INTERNAL 1
#define PTR_TYPE_NOTE 2
@@ -46,17 +61,15 @@ struct leaf_node {
#define CLR_PTR_TYPE(ptr) ((void *) ((uintptr_t) (ptr) & ~3))
#define SET_PTR_TYPE(ptr, type) ((void *) ((uintptr_t) (ptr) | (type)))
-#define GET_NIBBLE(n, sha1) (((sha1[n >> 1]) >> ((~n & 0x01) << 2)) & 0x0f)
+#define GET_NIBBLE(n, sha1) (((sha1[(n) >> 1]) >> ((~(n) & 0x01) << 2)) & 0x0f)
#define SUBTREE_SHA1_PREFIXCMP(key_sha1, subtree_sha1) \
(memcmp(key_sha1, subtree_sha1, subtree_sha1[19]))
-static struct int_node root_node;
+struct notes_tree default_notes_tree;
-static int initialized;
-
-static void load_subtree(struct leaf_node *subtree, struct int_node *node,
- unsigned int n);
+static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
+ struct int_node *node, unsigned int n);
/*
* Search the tree until the appropriate location for the given key is found:
@@ -73,7 +86,7 @@ static void load_subtree(struct leaf_node *subtree, struct int_node *node,
* - an unused leaf node (NULL)
* In any case, set *tree and *n, and return pointer to the tree location.
*/
-static void **note_tree_search(struct int_node **tree,
+static void **note_tree_search(struct notes_tree *t, struct int_node **tree,
unsigned char *n, const unsigned char *key_sha1)
{
struct leaf_node *l;
@@ -85,27 +98,27 @@ static void **note_tree_search(struct int_node **tree,
if (!SUBTREE_SHA1_PREFIXCMP(key_sha1, l->key_sha1)) {
/* unpack tree and resume search */
(*tree)->a[0] = NULL;
- load_subtree(l, *tree, *n);
+ load_subtree(t, l, *tree, *n);
free(l);
- return note_tree_search(tree, n, key_sha1);
+ return note_tree_search(t, tree, n, key_sha1);
}
}
i = GET_NIBBLE(*n, key_sha1);
p = (*tree)->a[i];
- switch(GET_PTR_TYPE(p)) {
+ switch (GET_PTR_TYPE(p)) {
case PTR_TYPE_INTERNAL:
*tree = CLR_PTR_TYPE(p);
(*n)++;
- return note_tree_search(tree, n, key_sha1);
+ return note_tree_search(t, tree, n, key_sha1);
case PTR_TYPE_SUBTREE:
l = (struct leaf_node *) CLR_PTR_TYPE(p);
if (!SUBTREE_SHA1_PREFIXCMP(key_sha1, l->key_sha1)) {
/* unpack tree and resume search */
(*tree)->a[i] = NULL;
- load_subtree(l, *tree, *n);
+ load_subtree(t, l, *tree, *n);
free(l);
- return note_tree_search(tree, n, key_sha1);
+ return note_tree_search(t, tree, n, key_sha1);
}
/* fall through */
default:
@@ -118,10 +131,11 @@ static void **note_tree_search(struct int_node **tree,
* Search to the tree location appropriate for the given key:
* If a note entry with matching key, return the note entry, else return NULL.
*/
-static struct leaf_node *note_tree_find(struct int_node *tree, unsigned char n,
+static struct leaf_node *note_tree_find(struct notes_tree *t,
+ struct int_node *tree, unsigned char n,
const unsigned char *key_sha1)
{
- void **p = note_tree_search(&tree, &n, key_sha1);
+ void **p = note_tree_search(t, &tree, &n, key_sha1);
if (GET_PTR_TYPE(*p) == PTR_TYPE_NOTE) {
struct leaf_node *l = (struct leaf_node *) CLR_PTR_TYPE(*p);
if (!hashcmp(key_sha1, l->key_sha1))
@@ -130,55 +144,12 @@ static struct leaf_node *note_tree_find(struct int_node *tree, unsigned char n,
return NULL;
}
-/* Create a new blob object by concatenating the two given blob objects */
-static int concatenate_notes(unsigned char *cur_sha1,
- const unsigned char *new_sha1)
-{
- char *cur_msg, *new_msg, *buf;
- unsigned long cur_len, new_len, buf_len;
- enum object_type cur_type, new_type;
- int ret;
-
- /* read in both note blob objects */
- new_msg = read_sha1_file(new_sha1, &new_type, &new_len);
- if (!new_msg || !new_len || new_type != OBJ_BLOB) {
- free(new_msg);
- return 0;
- }
- cur_msg = read_sha1_file(cur_sha1, &cur_type, &cur_len);
- if (!cur_msg || !cur_len || cur_type != OBJ_BLOB) {
- free(cur_msg);
- free(new_msg);
- hashcpy(cur_sha1, new_sha1);
- return 0;
- }
-
- /* we will separate the notes by a newline anyway */
- if (cur_msg[cur_len - 1] == '\n')
- cur_len--;
-
- /* concatenate cur_msg and new_msg into buf */
- buf_len = cur_len + 1 + new_len;
- buf = (char *) xmalloc(buf_len);
- memcpy(buf, cur_msg, cur_len);
- buf[cur_len] = '\n';
- memcpy(buf + cur_len + 1, new_msg, new_len);
-
- free(cur_msg);
- free(new_msg);
-
- /* create a new blob object from buf */
- ret = write_sha1_file(buf, buf_len, "blob", cur_sha1);
- free(buf);
- return ret;
-}
-
/*
* To insert a leaf_node:
* Search to the tree location appropriate for the given leaf_node's key:
* - If location is unused (NULL), store the tweaked pointer directly there
* - If location holds a note entry that matches the note-to-be-inserted, then
- * concatenate the two notes.
+ * combine the two notes (by calling the given combine_notes function).
* - If location holds a note entry that matches the subtree-to-be-inserted,
* then unpack the subtree-to-be-inserted into the location.
* - If location holds a matching subtree entry, unpack the subtree at that
@@ -186,16 +157,17 @@ static int concatenate_notes(unsigned char *cur_sha1,
* - Else, create a new int_node, holding both the node-at-location and the
* node-to-be-inserted, and store the new int_node into the location.
*/
-static void note_tree_insert(struct int_node *tree, unsigned char n,
- struct leaf_node *entry, unsigned char type)
+static void note_tree_insert(struct notes_tree *t, struct int_node *tree,
+ unsigned char n, struct leaf_node *entry, unsigned char type,
+ combine_notes_fn combine_notes)
{
struct int_node *new_node;
struct leaf_node *l;
- void **p = note_tree_search(&tree, &n, entry->key_sha1);
+ void **p = note_tree_search(t, &tree, &n, entry->key_sha1);
assert(GET_PTR_TYPE(entry) == 0); /* no type bits set */
l = (struct leaf_node *) CLR_PTR_TYPE(*p);
- switch(GET_PTR_TYPE(*p)) {
+ switch (GET_PTR_TYPE(*p)) {
case PTR_TYPE_NULL:
assert(!*p);
*p = SET_PTR_TYPE(entry, type);
@@ -208,12 +180,11 @@ static void note_tree_insert(struct int_node *tree, unsigned char n,
if (!hashcmp(l->val_sha1, entry->val_sha1))
return;
- if (concatenate_notes(l->val_sha1,
- entry->val_sha1))
- die("failed to concatenate note %s "
- "into note %s for commit %s",
- sha1_to_hex(entry->val_sha1),
+ if (combine_notes(l->val_sha1, entry->val_sha1))
+ die("failed to combine notes %s and %s"
+ " for object %s",
sha1_to_hex(l->val_sha1),
+ sha1_to_hex(entry->val_sha1),
sha1_to_hex(l->key_sha1));
free(entry);
return;
@@ -223,7 +194,7 @@ static void note_tree_insert(struct int_node *tree, unsigned char n,
if (!SUBTREE_SHA1_PREFIXCMP(l->key_sha1,
entry->key_sha1)) {
/* unpack 'entry' */
- load_subtree(entry, tree, n);
+ load_subtree(t, entry, tree, n);
free(entry);
return;
}
@@ -234,9 +205,10 @@ static void note_tree_insert(struct int_node *tree, unsigned char n,
if (!SUBTREE_SHA1_PREFIXCMP(entry->key_sha1, l->key_sha1)) {
/* unpack 'l' and restart insert */
*p = NULL;
- load_subtree(l, tree, n);
+ load_subtree(t, l, tree, n);
free(l);
- note_tree_insert(tree, n, entry, type);
+ note_tree_insert(t, tree, n, entry, type,
+ combine_notes);
return;
}
break;
@@ -246,9 +218,83 @@ static void note_tree_insert(struct int_node *tree, unsigned char n,
assert(GET_PTR_TYPE(*p) == PTR_TYPE_NOTE ||
GET_PTR_TYPE(*p) == PTR_TYPE_SUBTREE);
new_node = (struct int_node *) xcalloc(sizeof(struct int_node), 1);
- note_tree_insert(new_node, n + 1, l, GET_PTR_TYPE(*p));
+ note_tree_insert(t, new_node, n + 1, l, GET_PTR_TYPE(*p),
+ combine_notes);
*p = SET_PTR_TYPE(new_node, PTR_TYPE_INTERNAL);
- note_tree_insert(new_node, n + 1, entry, type);
+ note_tree_insert(t, new_node, n + 1, entry, type, combine_notes);
+}
+
+/*
+ * How to consolidate an int_node:
+ * If there are > 1 non-NULL entries, give up and return non-zero.
+ * Otherwise replace the int_node at the given index in the given parent node
+ * with the only entry (or a NULL entry if no entries) from the given tree,
+ * and return 0.
+ */
+static int note_tree_consolidate(struct int_node *tree,
+ struct int_node *parent, unsigned char index)
+{
+ unsigned int i;
+ void *p = NULL;
+
+ assert(tree && parent);
+ assert(CLR_PTR_TYPE(parent->a[index]) == tree);
+
+ for (i = 0; i < 16; i++) {
+ if (GET_PTR_TYPE(tree->a[i]) != PTR_TYPE_NULL) {
+ if (p) /* more than one entry */
+ return -2;
+ p = tree->a[i];
+ }
+ }
+
+ /* replace tree with p in parent[index] */
+ parent->a[index] = p;
+ free(tree);
+ return 0;
+}
+
+/*
+ * To remove a leaf_node:
+ * Search to the tree location appropriate for the given leaf_node's key:
+ * - If location does not hold a matching entry, abort and do nothing.
+ * - Replace the matching leaf_node with a NULL entry (and free the leaf_node).
+ * - Consolidate int_nodes repeatedly, while walking up the tree towards root.
+ */
+static void note_tree_remove(struct notes_tree *t, struct int_node *tree,
+ unsigned char n, struct leaf_node *entry)
+{
+ struct leaf_node *l;
+ struct int_node *parent_stack[20];
+ unsigned char i, j;
+ void **p = note_tree_search(t, &tree, &n, entry->key_sha1);
+
+ assert(GET_PTR_TYPE(entry) == 0); /* no type bits set */
+ if (GET_PTR_TYPE(*p) != PTR_TYPE_NOTE)
+ return; /* type mismatch, nothing to remove */
+ l = (struct leaf_node *) CLR_PTR_TYPE(*p);
+ if (hashcmp(l->key_sha1, entry->key_sha1))
+ return; /* key mismatch, nothing to remove */
+
+ /* we have found a matching entry */
+ free(l);
+ *p = SET_PTR_TYPE(NULL, PTR_TYPE_NULL);
+
+ /* consolidate this tree level, and parent levels, if possible */
+ if (!n)
+ return; /* cannot consolidate top level */
+ /* first, build stack of ancestors between root and current node */
+ parent_stack[0] = t->root;
+ for (i = 0; i < n; i++) {
+ j = GET_NIBBLE(i, entry->key_sha1);
+ parent_stack[i + 1] = CLR_PTR_TYPE(parent_stack[i]->a[j]);
+ }
+ assert(i == n && parent_stack[i] == tree);
+ /* next, unwind stack until note_tree_consolidate() is done */
+ while (i > 0 &&
+ !note_tree_consolidate(parent_stack[i], parent_stack[i - 1],
+ GET_NIBBLE(i - 1, entry->key_sha1)))
+ i--;
}
/* Free the entire notes data contained in the given tree */
@@ -257,7 +303,7 @@ static void note_tree_free(struct int_node *tree)
unsigned int i;
for (i = 0; i < 16; i++) {
void *p = tree->a[i];
- switch(GET_PTR_TYPE(p)) {
+ switch (GET_PTR_TYPE(p)) {
case PTR_TYPE_INTERNAL:
note_tree_free(CLR_PTR_TYPE(p));
/* fall through */
@@ -274,7 +320,7 @@ static void note_tree_free(struct int_node *tree)
* - hex_len - Length of above segment. Must be multiple of 2 between 0 and 40
* - sha1 - Partial SHA1 value is written here
* - sha1_len - Max #bytes to store in sha1, Must be >= hex_len / 2, and < 20
- * Returns -1 on error (invalid arguments or invalid SHA1 (not in hex format).
+ * Returns -1 on error (invalid arguments or invalid SHA1 (not in hex format)).
* Otherwise, returns number of bytes written to sha1 (i.e. hex_len / 2).
* Pads sha1 with NULs up to sha1_len (not included in returned length).
*/
@@ -296,14 +342,67 @@ static int get_sha1_hex_segment(const char *hex, unsigned int hex_len,
return len;
}
-static void load_subtree(struct leaf_node *subtree, struct int_node *node,
- unsigned int n)
+static int non_note_cmp(const struct non_note *a, const struct non_note *b)
+{
+ return strcmp(a->path, b->path);
+}
+
+static void add_non_note(struct notes_tree *t, const char *path,
+ unsigned int mode, const unsigned char *sha1)
+{
+ struct non_note *p = t->prev_non_note, *n;
+ n = (struct non_note *) xmalloc(sizeof(struct non_note));
+ n->next = NULL;
+ n->path = xstrdup(path);
+ n->mode = mode;
+ hashcpy(n->sha1, sha1);
+ t->prev_non_note = n;
+
+ if (!t->first_non_note) {
+ t->first_non_note = n;
+ return;
+ }
+
+ if (non_note_cmp(p, n) < 0)
+ ; /* do nothing */
+ else if (non_note_cmp(t->first_non_note, n) <= 0)
+ p = t->first_non_note;
+ else {
+ /* n sorts before t->first_non_note */
+ n->next = t->first_non_note;
+ t->first_non_note = n;
+ return;
+ }
+
+ /* n sorts equal or after p */
+ while (p->next && non_note_cmp(p->next, n) <= 0)
+ p = p->next;
+
+ if (non_note_cmp(p, n) == 0) { /* n ~= p; overwrite p with n */
+ assert(strcmp(p->path, n->path) == 0);
+ p->mode = n->mode;
+ hashcpy(p->sha1, n->sha1);
+ free(n);
+ t->prev_non_note = p;
+ return;
+ }
+
+ /* n sorts between p and p->next */
+ n->next = p->next;
+ p->next = n;
+}
+
+static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
+ struct int_node *node, unsigned int n)
{
- unsigned char commit_sha1[20];
+ unsigned char object_sha1[20];
unsigned int prefix_len;
void *buf;
struct tree_desc desc;
struct name_entry entry;
+ int len, path_len;
+ unsigned char type;
+ struct leaf_node *l;
buf = fill_tree_descriptor(&desc, subtree->val_sha1);
if (!buf)
@@ -312,86 +411,588 @@ static void load_subtree(struct leaf_node *subtree, struct int_node *node,
prefix_len = subtree->key_sha1[19];
assert(prefix_len * 2 >= n);
- memcpy(commit_sha1, subtree->key_sha1, prefix_len);
+ memcpy(object_sha1, subtree->key_sha1, prefix_len);
while (tree_entry(&desc, &entry)) {
- int len = get_sha1_hex_segment(entry.path, strlen(entry.path),
- commit_sha1 + prefix_len, 20 - prefix_len);
+ path_len = strlen(entry.path);
+ len = get_sha1_hex_segment(entry.path, path_len,
+ object_sha1 + prefix_len, 20 - prefix_len);
if (len < 0)
- continue; /* entry.path is not a SHA1 sum. Skip */
+ goto handle_non_note; /* entry.path is not a SHA1 */
len += prefix_len;
/*
- * If commit SHA1 is complete (len == 20), assume note object
- * If commit SHA1 is incomplete (len < 20), assume note subtree
+ * If object SHA1 is complete (len == 20), assume note object
+ * If object SHA1 is incomplete (len < 20), and current
+ * component consists of 2 hex chars, assume note subtree
*/
if (len <= 20) {
- unsigned char type = PTR_TYPE_NOTE;
- struct leaf_node *l = (struct leaf_node *)
+ type = PTR_TYPE_NOTE;
+ l = (struct leaf_node *)
xcalloc(sizeof(struct leaf_node), 1);
- hashcpy(l->key_sha1, commit_sha1);
+ hashcpy(l->key_sha1, object_sha1);
hashcpy(l->val_sha1, entry.sha1);
if (len < 20) {
- if (!S_ISDIR(entry.mode))
- continue; /* entry cannot be subtree */
+ if (!S_ISDIR(entry.mode) || path_len != 2)
+ goto handle_non_note; /* not subtree */
l->key_sha1[19] = (unsigned char) len;
type = PTR_TYPE_SUBTREE;
}
- note_tree_insert(node, n, l, type);
+ note_tree_insert(t, node, n, l, type,
+ combine_notes_concatenate);
+ }
+ continue;
+
+handle_non_note:
+ /*
+ * Determine full path for this non-note entry:
+ * The filename is already found in entry.path, but the
+ * directory part of the path must be deduced from the subtree
+ * containing this entry. We assume here that the overall notes
+ * tree follows a strict byte-based progressive fanout
+ * structure (i.e. using 2/38, 2/2/36, etc. fanouts, and not
+ * e.g. 4/36 fanout). This means that if a non-note is found at
+ * path "dead/beef", the following code will register it as
+ * being found on "de/ad/beef".
+ * On the other hand, if you use such non-obvious non-note
+ * paths in the middle of a notes tree, you deserve what's
+ * coming to you ;). Note that for non-notes that are not
+ * SHA1-like at the top level, there will be no problems.
+ *
+ * To conclude, it is strongly advised to make sure non-notes
+ * have at least one non-hex character in the top-level path
+ * component.
+ */
+ {
+ char non_note_path[PATH_MAX];
+ char *p = non_note_path;
+ const char *q = sha1_to_hex(subtree->key_sha1);
+ int i;
+ for (i = 0; i < prefix_len; i++) {
+ *p++ = *q++;
+ *p++ = *q++;
+ *p++ = '/';
+ }
+ strcpy(p, entry.path);
+ add_non_note(t, non_note_path, entry.mode, entry.sha1);
}
}
free(buf);
}
-static void initialize_notes(const char *notes_ref_name)
+/*
+ * Determine optimal on-disk fanout for this part of the notes tree
+ *
+ * Given a (sub)tree and the level in the internal tree structure, determine
+ * whether or not the given existing fanout should be expanded for this
+ * (sub)tree.
+ *
+ * Values of the 'fanout' variable:
+ * - 0: No fanout (all notes are stored directly in the root notes tree)
+ * - 1: 2/38 fanout
+ * - 2: 2/2/36 fanout
+ * - 3: 2/2/2/34 fanout
+ * etc.
+ */
+static unsigned char determine_fanout(struct int_node *tree, unsigned char n,
+ unsigned char fanout)
{
- unsigned char sha1[20], commit_sha1[20];
+ /*
+ * The following is a simple heuristic that works well in practice:
+ * For each even-numbered 16-tree level (remember that each on-disk
+ * fanout level corresponds to _two_ 16-tree levels), peek at all 16
+ * entries at that tree level. If all of them are either int_nodes or
+ * subtree entries, then there are likely plenty of notes below this
+ * level, so we return an incremented fanout.
+ */
+ unsigned int i;
+ if ((n % 2) || (n > 2 * fanout))
+ return fanout;
+ for (i = 0; i < 16; i++) {
+ switch (GET_PTR_TYPE(tree->a[i])) {
+ case PTR_TYPE_SUBTREE:
+ case PTR_TYPE_INTERNAL:
+ continue;
+ default:
+ return fanout;
+ }
+ }
+ return fanout + 1;
+}
+
+static void construct_path_with_fanout(const unsigned char *sha1,
+ unsigned char fanout, char *path)
+{
+ unsigned int i = 0, j = 0;
+ const char *hex_sha1 = sha1_to_hex(sha1);
+ assert(fanout < 20);
+ while (fanout) {
+ path[i++] = hex_sha1[j++];
+ path[i++] = hex_sha1[j++];
+ path[i++] = '/';
+ fanout--;
+ }
+ strcpy(path + i, hex_sha1 + j);
+}
+
+static int for_each_note_helper(struct notes_tree *t, struct int_node *tree,
+ unsigned char n, unsigned char fanout, int flags,
+ each_note_fn fn, void *cb_data)
+{
+ unsigned int i;
+ void *p;
+ int ret = 0;
+ struct leaf_node *l;
+ static char path[40 + 19 + 1]; /* hex SHA1 + 19 * '/' + NUL */
+
+ fanout = determine_fanout(tree, n, fanout);
+ for (i = 0; i < 16; i++) {
+redo:
+ p = tree->a[i];
+ switch (GET_PTR_TYPE(p)) {
+ case PTR_TYPE_INTERNAL:
+ /* recurse into int_node */
+ ret = for_each_note_helper(t, CLR_PTR_TYPE(p), n + 1,
+ fanout, flags, fn, cb_data);
+ break;
+ case PTR_TYPE_SUBTREE:
+ l = (struct leaf_node *) CLR_PTR_TYPE(p);
+ /*
+ * Subtree entries in the note tree represent parts of
+ * the note tree that have not yet been explored. There
+ * is a direct relationship between subtree entries at
+ * level 'n' in the tree, and the 'fanout' variable:
+ * Subtree entries at level 'n <= 2 * fanout' should be
+ * preserved, since they correspond exactly to a fanout
+ * directory in the on-disk structure. However, subtree
+ * entries at level 'n > 2 * fanout' should NOT be
+ * preserved, but rather consolidated into the above
+ * notes tree level. We achieve this by unconditionally
+ * unpacking subtree entries that exist below the
+ * threshold level at 'n = 2 * fanout'.
+ */
+ if (n <= 2 * fanout &&
+ flags & FOR_EACH_NOTE_YIELD_SUBTREES) {
+ /* invoke callback with subtree */
+ unsigned int path_len =
+ l->key_sha1[19] * 2 + fanout;
+ assert(path_len < 40 + 19);
+ construct_path_with_fanout(l->key_sha1, fanout,
+ path);
+ /* Create trailing slash, if needed */
+ if (path[path_len - 1] != '/')
+ path[path_len++] = '/';
+ path[path_len] = '\0';
+ ret = fn(l->key_sha1, l->val_sha1, path,
+ cb_data);
+ }
+ if (n > fanout * 2 ||
+ !(flags & FOR_EACH_NOTE_DONT_UNPACK_SUBTREES)) {
+ /* unpack subtree and resume traversal */
+ tree->a[i] = NULL;
+ load_subtree(t, l, tree, n);
+ free(l);
+ goto redo;
+ }
+ break;
+ case PTR_TYPE_NOTE:
+ l = (struct leaf_node *) CLR_PTR_TYPE(p);
+ construct_path_with_fanout(l->key_sha1, fanout, path);
+ ret = fn(l->key_sha1, l->val_sha1, path, cb_data);
+ break;
+ }
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+struct tree_write_stack {
+ struct tree_write_stack *next;
+ struct strbuf buf;
+ char path[2]; /* path to subtree in next, if any */
+};
+
+static inline int matches_tree_write_stack(struct tree_write_stack *tws,
+ const char *full_path)
+{
+ return full_path[0] == tws->path[0] &&
+ full_path[1] == tws->path[1] &&
+ full_path[2] == '/';
+}
+
+static void write_tree_entry(struct strbuf *buf, unsigned int mode,
+ const char *path, unsigned int path_len, const
+ unsigned char *sha1)
+{
+ strbuf_addf(buf, "%06o %.*s%c", mode, path_len, path, '\0');
+ strbuf_add(buf, sha1, 20);
+}
+
+static void tree_write_stack_init_subtree(struct tree_write_stack *tws,
+ const char *path)
+{
+ struct tree_write_stack *n;
+ assert(!tws->next);
+ assert(tws->path[0] == '\0' && tws->path[1] == '\0');
+ n = (struct tree_write_stack *)
+ xmalloc(sizeof(struct tree_write_stack));
+ n->next = NULL;
+ strbuf_init(&n->buf, 256 * (32 + 40)); /* assume 256 entries per tree */
+ n->path[0] = n->path[1] = '\0';
+ tws->next = n;
+ tws->path[0] = path[0];
+ tws->path[1] = path[1];
+}
+
+static int tree_write_stack_finish_subtree(struct tree_write_stack *tws)
+{
+ int ret;
+ struct tree_write_stack *n = tws->next;
+ unsigned char s[20];
+ if (n) {
+ ret = tree_write_stack_finish_subtree(n);
+ if (ret)
+ return ret;
+ ret = write_sha1_file(n->buf.buf, n->buf.len, tree_type, s);
+ if (ret)
+ return ret;
+ strbuf_release(&n->buf);
+ free(n);
+ tws->next = NULL;
+ write_tree_entry(&tws->buf, 040000, tws->path, 2, s);
+ tws->path[0] = tws->path[1] = '\0';
+ }
+ return 0;
+}
+
+static int write_each_note_helper(struct tree_write_stack *tws,
+ const char *path, unsigned int mode,
+ const unsigned char *sha1)
+{
+ size_t path_len = strlen(path);
+ unsigned int n = 0;
+ int ret;
+
+ /* Determine common part of tree write stack */
+ while (tws && 3 * n < path_len &&
+ matches_tree_write_stack(tws, path + 3 * n)) {
+ n++;
+ tws = tws->next;
+ }
+
+ /* tws point to last matching tree_write_stack entry */
+ ret = tree_write_stack_finish_subtree(tws);
+ if (ret)
+ return ret;
+
+ /* Start subtrees needed to satisfy path */
+ while (3 * n + 2 < path_len && path[3 * n + 2] == '/') {
+ tree_write_stack_init_subtree(tws, path + 3 * n);
+ n++;
+ tws = tws->next;
+ }
+
+ /* There should be no more directory components in the given path */
+ assert(memchr(path + 3 * n, '/', path_len - (3 * n)) == NULL);
+
+ /* Finally add given entry to the current tree object */
+ write_tree_entry(&tws->buf, mode, path + 3 * n, path_len - (3 * n),
+ sha1);
+
+ return 0;
+}
+
+struct write_each_note_data {
+ struct tree_write_stack *root;
+ struct non_note *next_non_note;
+};
+
+static int write_each_non_note_until(const char *note_path,
+ struct write_each_note_data *d)
+{
+ struct non_note *n = d->next_non_note;
+ int cmp, ret;
+ while (n && (!note_path || (cmp = strcmp(n->path, note_path)) <= 0)) {
+ if (note_path && cmp == 0)
+ ; /* do nothing, prefer note to non-note */
+ else {
+ ret = write_each_note_helper(d->root, n->path, n->mode,
+ n->sha1);
+ if (ret)
+ return ret;
+ }
+ n = n->next;
+ }
+ d->next_non_note = n;
+ return 0;
+}
+
+static int write_each_note(const unsigned char *object_sha1,
+ const unsigned char *note_sha1, char *note_path,
+ void *cb_data)
+{
+ struct write_each_note_data *d =
+ (struct write_each_note_data *) cb_data;
+ size_t note_path_len = strlen(note_path);
+ unsigned int mode = 0100644;
+
+ if (note_path[note_path_len - 1] == '/') {
+ /* subtree entry */
+ note_path_len--;
+ note_path[note_path_len] = '\0';
+ mode = 040000;
+ }
+ assert(note_path_len <= 40 + 19);
+
+ /* Weave non-note entries into note entries */
+ return write_each_non_note_until(note_path, d) ||
+ write_each_note_helper(d->root, note_path, mode, note_sha1);
+}
+
+struct note_delete_list {
+ struct note_delete_list *next;
+ const unsigned char *sha1;
+};
+
+static int prune_notes_helper(const unsigned char *object_sha1,
+ const unsigned char *note_sha1, char *note_path,
+ void *cb_data)
+{
+ struct note_delete_list **l = (struct note_delete_list **) cb_data;
+ struct note_delete_list *n;
+
+ if (has_sha1_file(object_sha1))
+ return 0; /* nothing to do for this note */
+
+ /* failed to find object => prune this note */
+ n = (struct note_delete_list *) xmalloc(sizeof(*n));
+ n->next = *l;
+ n->sha1 = object_sha1;
+ *l = n;
+ return 0;
+}
+
+int combine_notes_concatenate(unsigned char *cur_sha1,
+ const unsigned char *new_sha1)
+{
+ char *cur_msg = NULL, *new_msg = NULL, *buf;
+ unsigned long cur_len, new_len, buf_len;
+ enum object_type cur_type, new_type;
+ int ret;
+
+ /* read in both note blob objects */
+ if (!is_null_sha1(new_sha1))
+ new_msg = read_sha1_file(new_sha1, &new_type, &new_len);
+ if (!new_msg || !new_len || new_type != OBJ_BLOB) {
+ free(new_msg);
+ return 0;
+ }
+ if (!is_null_sha1(cur_sha1))
+ cur_msg = read_sha1_file(cur_sha1, &cur_type, &cur_len);
+ if (!cur_msg || !cur_len || cur_type != OBJ_BLOB) {
+ free(cur_msg);
+ free(new_msg);
+ hashcpy(cur_sha1, new_sha1);
+ return 0;
+ }
+
+ /* we will separate the notes by a newline anyway */
+ if (cur_msg[cur_len - 1] == '\n')
+ cur_len--;
+
+ /* concatenate cur_msg and new_msg into buf */
+ buf_len = cur_len + 1 + new_len;
+ buf = (char *) xmalloc(buf_len);
+ memcpy(buf, cur_msg, cur_len);
+ buf[cur_len] = '\n';
+ memcpy(buf + cur_len + 1, new_msg, new_len);
+ free(cur_msg);
+ free(new_msg);
+
+ /* create a new blob object from buf */
+ ret = write_sha1_file(buf, buf_len, blob_type, cur_sha1);
+ free(buf);
+ return ret;
+}
+
+int combine_notes_overwrite(unsigned char *cur_sha1,
+ const unsigned char *new_sha1)
+{
+ hashcpy(cur_sha1, new_sha1);
+ return 0;
+}
+
+int combine_notes_ignore(unsigned char *cur_sha1,
+ const unsigned char *new_sha1)
+{
+ return 0;
+}
+
+void init_notes(struct notes_tree *t, const char *notes_ref,
+ combine_notes_fn combine_notes, int flags)
+{
+ unsigned char sha1[20], object_sha1[20];
unsigned mode;
struct leaf_node root_tree;
- if (!notes_ref_name || read_ref(notes_ref_name, commit_sha1) ||
- get_tree_entry(commit_sha1, "", sha1, &mode))
+ if (!t)
+ t = &default_notes_tree;
+ assert(!t->initialized);
+
+ if (!notes_ref)
+ notes_ref = getenv(GIT_NOTES_REF_ENVIRONMENT);
+ if (!notes_ref)
+ notes_ref = notes_ref_name; /* value of core.notesRef config */
+ if (!notes_ref)
+ notes_ref = GIT_NOTES_DEFAULT_REF;
+
+ if (!combine_notes)
+ combine_notes = combine_notes_concatenate;
+
+ t->root = (struct int_node *) xcalloc(sizeof(struct int_node), 1);
+ t->first_non_note = NULL;
+ t->prev_non_note = NULL;
+ t->ref = notes_ref ? xstrdup(notes_ref) : NULL;
+ t->combine_notes = combine_notes;
+ t->initialized = 1;
+
+ if (flags & NOTES_INIT_EMPTY || !notes_ref ||
+ read_ref(notes_ref, object_sha1))
return;
+ if (get_tree_entry(object_sha1, "", sha1, &mode))
+ die("Failed to read notes tree referenced by %s (%s)",
+ notes_ref, object_sha1);
hashclr(root_tree.key_sha1);
hashcpy(root_tree.val_sha1, sha1);
- load_subtree(&root_tree, &root_node, 0);
+ load_subtree(t, &root_tree, t->root, 0);
}
-static unsigned char *lookup_notes(const unsigned char *commit_sha1)
+void add_note(struct notes_tree *t, const unsigned char *object_sha1,
+ const unsigned char *note_sha1, combine_notes_fn combine_notes)
{
- struct leaf_node *found = note_tree_find(&root_node, 0, commit_sha1);
- if (found)
- return found->val_sha1;
- return NULL;
+ struct leaf_node *l;
+
+ if (!t)
+ t = &default_notes_tree;
+ assert(t->initialized);
+ if (!combine_notes)
+ combine_notes = t->combine_notes;
+ l = (struct leaf_node *) xmalloc(sizeof(struct leaf_node));
+ hashcpy(l->key_sha1, object_sha1);
+ hashcpy(l->val_sha1, note_sha1);
+ note_tree_insert(t, t->root, 0, l, PTR_TYPE_NOTE, combine_notes);
+}
+
+void remove_note(struct notes_tree *t, const unsigned char *object_sha1)
+{
+ struct leaf_node l;
+
+ if (!t)
+ t = &default_notes_tree;
+ assert(t->initialized);
+ hashcpy(l.key_sha1, object_sha1);
+ hashclr(l.val_sha1);
+ return note_tree_remove(t, t->root, 0, &l);
+}
+
+const unsigned char *get_note(struct notes_tree *t,
+ const unsigned char *object_sha1)
+{
+ struct leaf_node *found;
+
+ if (!t)
+ t = &default_notes_tree;
+ assert(t->initialized);
+ found = note_tree_find(t, t->root, 0, object_sha1);
+ return found ? found->val_sha1 : NULL;
}
-void free_notes(void)
+int for_each_note(struct notes_tree *t, int flags, each_note_fn fn,
+ void *cb_data)
{
- note_tree_free(&root_node);
- memset(&root_node, 0, sizeof(struct int_node));
- initialized = 0;
+ if (!t)
+ t = &default_notes_tree;
+ assert(t->initialized);
+ return for_each_note_helper(t, t->root, 0, 0, flags, fn, cb_data);
}
-void get_commit_notes(const struct commit *commit, struct strbuf *sb,
- const char *output_encoding, int flags)
+int write_notes_tree(struct notes_tree *t, unsigned char *result)
+{
+ struct tree_write_stack root;
+ struct write_each_note_data cb_data;
+ int ret;
+
+ if (!t)
+ t = &default_notes_tree;
+ assert(t->initialized);
+
+ /* Prepare for traversal of current notes tree */
+ root.next = NULL; /* last forward entry in list is grounded */
+ strbuf_init(&root.buf, 256 * (32 + 40)); /* assume 256 entries */
+ root.path[0] = root.path[1] = '\0';
+ cb_data.root = &root;
+ cb_data.next_non_note = t->first_non_note;
+
+ /* Write tree objects representing current notes tree */
+ ret = for_each_note(t, FOR_EACH_NOTE_DONT_UNPACK_SUBTREES |
+ FOR_EACH_NOTE_YIELD_SUBTREES,
+ write_each_note, &cb_data) ||
+ write_each_non_note_until(NULL, &cb_data) ||
+ tree_write_stack_finish_subtree(&root) ||
+ write_sha1_file(root.buf.buf, root.buf.len, tree_type, result);
+ strbuf_release(&root.buf);
+ return ret;
+}
+
+void prune_notes(struct notes_tree *t)
+{
+ struct note_delete_list *l = NULL;
+
+ if (!t)
+ t = &default_notes_tree;
+ assert(t->initialized);
+
+ for_each_note(t, 0, prune_notes_helper, &l);
+
+ while (l) {
+ remove_note(t, l->sha1);
+ l = l->next;
+ }
+}
+
+void free_notes(struct notes_tree *t)
+{
+ if (!t)
+ t = &default_notes_tree;
+ if (t->root)
+ note_tree_free(t->root);
+ free(t->root);
+ while (t->first_non_note) {
+ t->prev_non_note = t->first_non_note->next;
+ free(t->first_non_note->path);
+ free(t->first_non_note);
+ t->first_non_note = t->prev_non_note;
+ }
+ free(t->ref);
+ memset(t, 0, sizeof(struct notes_tree));
+}
+
+void format_note(struct notes_tree *t, const unsigned char *object_sha1,
+ struct strbuf *sb, const char *output_encoding, int flags)
{
static const char utf8[] = "utf-8";
- unsigned char *sha1;
+ const unsigned char *sha1;
char *msg, *msg_p;
unsigned long linelen, msglen;
enum object_type type;
- if (!initialized) {
- const char *env = getenv(GIT_NOTES_REF_ENVIRONMENT);
- if (env)
- notes_ref_name = getenv(GIT_NOTES_REF_ENVIRONMENT);
- else if (!notes_ref_name)
- notes_ref_name = GIT_NOTES_DEFAULT_REF;
- initialize_notes(notes_ref_name);
- initialized = 1;
- }
+ if (!t)
+ t = &default_notes_tree;
+ if (!t->initialized)
+ init_notes(t, NULL, NULL, 0);
- sha1 = lookup_notes(commit->object.sha1);
+ sha1 = get_note(t, object_sha1);
if (!sha1)
return;
diff --git a/notes.h b/notes.h
index a1421e3..bad03cc 100644
--- a/notes.h
+++ b/notes.h
@@ -1,13 +1,201 @@
#ifndef NOTES_H
#define NOTES_H
-/* Free (and de-initialize) the internal notes tree structure */
-void free_notes(void);
+/*
+ * Function type for combining two notes annotating the same object.
+ *
+ * When adding a new note annotating the same object as an existing note, it is
+ * up to the caller to decide how to combine the two notes. The decision is
+ * made by passing in a function of the following form. The function accepts
+ * two SHA1s -- of the existing note and the new note, respectively. The
+ * function then combines the notes in whatever way it sees fit, and writes the
+ * resulting SHA1 into the first SHA1 argument (cur_sha1). A non-zero return
+ * value indicates failure.
+ *
+ * The two given SHA1s must both be non-NULL and different from each other.
+ *
+ * The default combine_notes function (you get this when passing NULL) is
+ * combine_notes_concatenate(), which appends the contents of the new note to
+ * the contents of the existing note.
+ */
+typedef int combine_notes_fn(unsigned char *cur_sha1, const unsigned char *new_sha1);
+/* Common notes combinators */
+int combine_notes_concatenate(unsigned char *cur_sha1, const unsigned char *new_sha1);
+int combine_notes_overwrite(unsigned char *cur_sha1, const unsigned char *new_sha1);
+int combine_notes_ignore(unsigned char *cur_sha1, const unsigned char *new_sha1);
+
+/*
+ * Notes tree object
+ *
+ * Encapsulates the internal notes tree structure associated with a notes ref.
+ * Whenever a struct notes_tree pointer is required below, you may pass NULL in
+ * order to use the default/internal notes tree. E.g. you only need to pass a
+ * non-NULL value if you need to refer to several different notes trees
+ * simultaneously.
+ */
+extern struct notes_tree {
+ struct int_node *root;
+ struct non_note *first_non_note, *prev_non_note;
+ char *ref;
+ combine_notes_fn *combine_notes;
+ int initialized;
+} default_notes_tree;
+
+/*
+ * Flags controlling behaviour of notes tree initialization
+ *
+ * Default behaviour is to initialize the notes tree from the tree object
+ * specified by the given (or default) notes ref.
+ */
+#define NOTES_INIT_EMPTY 1
+
+/*
+ * Initialize the given notes_tree with the notes tree structure at the given
+ * ref. If given ref is NULL, the value of the $GIT_NOTES_REF environment
+ * variable is used, and if that is missing, the default notes ref is used
+ * ("refs/notes/commits").
+ *
+ * If you need to re-intialize a notes_tree structure (e.g. when switching from
+ * one notes ref to another), you must first de-initialize the notes_tree
+ * structure by calling free_notes(struct notes_tree *).
+ *
+ * If you pass t == NULL, the default internal notes_tree will be initialized.
+ *
+ * The combine_notes function that is passed becomes the default combine_notes
+ * function for the given notes_tree. If NULL is passed, the default
+ * combine_notes function is combine_notes_concatenate().
+ *
+ * Precondition: The notes_tree structure is zeroed (this can be achieved with
+ * memset(t, 0, sizeof(struct notes_tree)))
+ */
+void init_notes(struct notes_tree *t, const char *notes_ref,
+ combine_notes_fn combine_notes, int flags);
+
+/*
+ * Add the given note object to the given notes_tree structure
+ *
+ * IMPORTANT: The changes made by add_note() to the given notes_tree structure
+ * are not persistent until a subsequent call to write_notes_tree() returns
+ * zero.
+ */
+void add_note(struct notes_tree *t, const unsigned char *object_sha1,
+ const unsigned char *note_sha1, combine_notes_fn combine_notes);
+
+/*
+ * Remove the given note object from the given notes_tree structure
+ *
+ * IMPORTANT: The changes made by remove_note() to the given notes_tree
+ * structure are not persistent until a subsequent call to write_notes_tree()
+ * returns zero.
+ */
+void remove_note(struct notes_tree *t, const unsigned char *object_sha1);
+
+/*
+ * Get the note object SHA1 containing the note data for the given object
+ *
+ * Return NULL if the given object has no notes.
+ */
+const unsigned char *get_note(struct notes_tree *t,
+ const unsigned char *object_sha1);
+
+/*
+ * Flags controlling behaviour of for_each_note()
+ *
+ * Default behaviour of for_each_note() is to traverse every single note object
+ * in the given notes tree, unpacking subtree entries along the way.
+ * The following flags can be used to alter the default behaviour:
+ *
+ * - DONT_UNPACK_SUBTREES causes for_each_note() NOT to unpack and recurse into
+ * subtree entries while traversing the notes tree. This causes notes within
+ * those subtrees NOT to be passed to the callback. Use this flag if you
+ * don't want to traverse _all_ notes, but only want to traverse the parts
+ * of the notes tree that have already been unpacked (this includes at least
+ * all notes that have been added/changed).
+ *
+ * - YIELD_SUBTREES causes any subtree entries that are encountered to be
+ * passed to the callback, before recursing into them. Subtree entries are
+ * not note objects, but represent intermediate directories in the notes
+ * tree. When passed to the callback, subtree entries will have a trailing
+ * slash in their path, which the callback may use to differentiate between
+ * note entries and subtree entries. Note that already-unpacked subtree
+ * entries are not part of the notes tree, and will therefore not be yielded.
+ * If this flag is used together with DONT_UNPACK_SUBTREES, for_each_note()
+ * will yield the subtree entry, but not recurse into it.
+ */
+#define FOR_EACH_NOTE_DONT_UNPACK_SUBTREES 1
+#define FOR_EACH_NOTE_YIELD_SUBTREES 2
+
+/*
+ * Invoke the specified callback function for each note in the given notes_tree
+ *
+ * If the callback returns nonzero, the note walk is aborted, and the return
+ * value from the callback is returned from for_each_note(). Hence, a zero
+ * return value from for_each_note() indicates that all notes were walked
+ * successfully.
+ *
+ * IMPORTANT: The callback function is NOT allowed to change the notes tree.
+ * In other words, the following functions can NOT be invoked (on the current
+ * notes tree) from within the callback:
+ * - add_note()
+ * - remove_note()
+ * - free_notes()
+ */
+typedef int each_note_fn(const unsigned char *object_sha1,
+ const unsigned char *note_sha1, char *note_path,
+ void *cb_data);
+int for_each_note(struct notes_tree *t, int flags, each_note_fn fn,
+ void *cb_data);
+
+/*
+ * Write the given notes_tree structure to the object database
+ *
+ * Creates a new tree object encapsulating the current state of the given
+ * notes_tree, and stores its SHA1 into the 'result' argument.
+ *
+ * Returns zero on success, non-zero on failure.
+ *
+ * IMPORTANT: Changes made to the given notes_tree are not persistent until
+ * this function has returned zero. Please also remember to create a
+ * corresponding commit object, and update the appropriate notes ref.
+ */
+int write_notes_tree(struct notes_tree *t, unsigned char *result);
+
+/*
+ * Remove all notes annotating non-existing objects from the given notes tree
+ *
+ * All notes in the given notes_tree that are associated with objects that no
+ * longer exist in the database, are removed from the notes tree.
+ *
+ * IMPORTANT: The changes made by prune_notes() to the given notes_tree
+ * structure are not persistent until a subsequent call to write_notes_tree()
+ * returns zero.
+ */
+void prune_notes(struct notes_tree *t);
+
+/*
+ * Free (and de-initialize) the given notes_tree structure
+ *
+ * IMPORTANT: Changes made to the given notes_tree since the last, successful
+ * call to write_notes_tree() will be lost.
+ */
+void free_notes(struct notes_tree *t);
+
+/* Flags controlling how notes are formatted */
#define NOTES_SHOW_HEADER 1
#define NOTES_INDENT 2
-void get_commit_notes(const struct commit *commit, struct strbuf *sb,
- const char *output_encoding, int flags);
+/*
+ * Fill the given strbuf with the notes associated with the given object.
+ *
+ * If the given notes_tree structure is not initialized, it will be auto-
+ * initialized to the default value (see documentation for init_notes() above).
+ * If the given notes_tree is NULL, the internal/default notes_tree will be
+ * used instead.
+ *
+ * 'flags' is a bitwise combination of the above formatting flags.
+ */
+void format_note(struct notes_tree *t, const unsigned char *object_sha1,
+ struct strbuf *sb, const char *output_encoding, int flags);
#endif
diff --git a/object.c b/object.c
index fe8eaaf..3ca92c4 100644
--- a/object.c
+++ b/object.c
@@ -217,27 +217,6 @@ struct object_list *object_list_insert(struct object *item,
return new_list;
}
-void object_list_append(struct object *item,
- struct object_list **list_p)
-{
- while (*list_p) {
- list_p = &((*list_p)->next);
- }
- *list_p = xmalloc(sizeof(struct object_list));
- (*list_p)->next = NULL;
- (*list_p)->item = item;
-}
-
-unsigned object_list_length(struct object_list *list)
-{
- unsigned ret = 0;
- while (list) {
- list = list->next;
- ret++;
- }
- return ret;
-}
-
int object_list_contains(struct object_list *list, struct object *obj)
{
while (list) {
diff --git a/object.h b/object.h
index 89dd0c4..82877c8 100644
--- a/object.h
+++ b/object.h
@@ -72,11 +72,6 @@ struct object *lookup_unknown_object(const unsigned char *sha1);
struct object_list *object_list_insert(struct object *item,
struct object_list **list_p);
-void object_list_append(struct object *item,
- struct object_list **list_p);
-
-unsigned object_list_length(struct object_list *list);
-
int object_list_contains(struct object_list *list, struct object *obj);
/* Object array handling .. */
diff --git a/pack-write.c b/pack-write.c
index 741efcd..9f47cf9 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -17,8 +17,8 @@ static int sha1_compare(const void *_a, const void *_b)
* the SHA1 hash of sorted object names. The objects array passed in
* will be sorted by SHA1 on exit.
*/
-char *write_idx_file(char *index_name, struct pack_idx_entry **objects,
- int nr_objects, unsigned char *sha1)
+const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects,
+ int nr_objects, unsigned char *sha1)
{
struct sha1file *f;
struct pack_idx_entry **sorted_by_sha, **list, **last;
diff --git a/pack.h b/pack.h
index a883334..b759a23 100644
--- a/pack.h
+++ b/pack.h
@@ -55,7 +55,7 @@ struct pack_idx_entry {
off_t offset;
};
-extern char *write_idx_file(char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1);
+extern const char *write_idx_file(const char *index_name, struct pack_idx_entry **objects, int nr_objects, unsigned char *sha1);
extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, off_t offset, off_t len, unsigned int nr);
extern int verify_pack(struct packed_git *);
extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t, unsigned char *, off_t);
diff --git a/parse-options.c b/parse-options.c
index 10ec21f..d218122 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -3,6 +3,9 @@
#include "cache.h"
#include "commit.h"
+static int parse_options_usage(const char * const *usagestr,
+ const struct option *opts);
+
#define OPT_SHORT 1
#define OPT_UNSET 2
@@ -560,8 +563,8 @@ void usage_msg_opt(const char *msg,
usage_with_options(usagestr, options);
}
-int parse_options_usage(const char * const *usagestr,
- const struct option *opts)
+static int parse_options_usage(const char * const *usagestr,
+ const struct option *opts)
{
return usage_with_options_internal(usagestr, opts, 0);
}
diff --git a/parse-options.h b/parse-options.h
index 91c1500..0c99691 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -173,9 +173,6 @@ struct parse_opt_ctx_t {
const char *prefix;
};
-extern int parse_options_usage(const char * const *usagestr,
- const struct option *opts);
-
extern void parse_options_start(struct parse_opt_ctx_t *ctx,
int argc, const char **argv, const char *prefix,
int flags);
diff --git a/pretty.c b/pretty.c
index 8f5bd1a..f999485 100644
--- a/pretty.c
+++ b/pretty.c
@@ -83,7 +83,7 @@ static int get_one_line(const char *msg)
}
/* High bit set, or ISO-2022-INT */
-int non_ascii(int ch)
+static int non_ascii(int ch)
{
return !isascii(ch) || ch == '\033';
}
@@ -775,8 +775,9 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
}
return 0; /* unknown %g placeholder */
case 'N':
- get_commit_notes(commit, sb, git_log_output_encoding ?
- git_log_output_encoding : git_commit_encoding, 0);
+ format_note(NULL, commit->object.sha1, sb,
+ git_log_output_encoding ? git_log_output_encoding
+ : git_commit_encoding, 0);
return 1;
}
@@ -1094,9 +1095,9 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
if (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body)
strbuf_addch(sb, '\n');
- if (fmt != CMIT_FMT_ONELINE)
- get_commit_notes(commit, sb, encoding,
- NOTES_SHOW_HEADER | NOTES_INDENT);
+ if (context->show_notes)
+ format_note(NULL, commit->object.sha1, sb, encoding,
+ NOTES_SHOW_HEADER | NOTES_INDENT);
free(reencoded);
}
diff --git a/quote.c b/quote.c
index 848d174..acb6bf9 100644
--- a/quote.c
+++ b/quote.c
@@ -72,7 +72,7 @@ void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
}
}
-char *sq_dequote_step(char *arg, char **next)
+static char *sq_dequote_step(char *arg, char **next)
{
char *dst = arg;
char *src = arg;
diff --git a/quote.h b/quote.h
index 66730f2..f83eb23 100644
--- a/quote.h
+++ b/quote.h
@@ -45,7 +45,6 @@ extern char *sq_dequote(char *);
* next argument that should be passed as first parameter. When there
* is no more argument to be dequoted, "next" is updated to point to NULL.
*/
-extern char *sq_dequote_step(char *arg, char **next);
extern int sq_dequote_to_argv(char *arg, const char ***argv, int *nr, int *alloc);
extern int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
diff --git a/read-cache.c b/read-cache.c
index d214aba..79938bf 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -10,10 +10,10 @@
#include "dir.h"
#include "tree.h"
#include "commit.h"
-#include "diff.h"
-#include "diffcore.h"
-#include "revision.h"
#include "blob.h"
+#include "resolve-undo.h"
+
+static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
/* Index extensions.
*
@@ -26,6 +26,7 @@
#define CACHE_EXT(s) ( (s[0]<<24)|(s[1]<<16)|(s[2]<<8)|(s[3]) )
#define CACHE_EXT_TREE 0x54524545 /* "TREE" */
+#define CACHE_EXT_RESOLVE_UNDO 0x52455543 /* "REUN" */
struct index_state the_index;
@@ -156,7 +157,7 @@ static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
return 0;
}
-int is_empty_blob_sha1(const unsigned char *sha1)
+static int is_empty_blob_sha1(const unsigned char *sha1)
{
static const unsigned char empty_blob_sha1[20] = {
0xe6,0x9d,0xe2,0x9b,0xb2,0xd1,0xd6,0x43,0x4b,0x8b,
@@ -454,6 +455,7 @@ int remove_index_entry_at(struct index_state *istate, int pos)
{
struct cache_entry *ce = istate->cache[pos];
+ record_resolve_undo(istate, ce);
remove_name_hash(ce);
istate->cache_changed = 1;
istate->cache_nr--;
@@ -1152,7 +1154,7 @@ int refresh_index(struct index_state *istate, unsigned int flags, const char **p
return has_errors;
}
-struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really)
+static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really)
{
return refresh_cache_ent(&the_index, ce, really, NULL);
}
@@ -1181,6 +1183,9 @@ static int read_index_extension(struct index_state *istate,
case CACHE_EXT_TREE:
istate->cache_tree = cache_tree_read(data, sz);
break;
+ case CACHE_EXT_RESOLVE_UNDO:
+ istate->resolve_undo = resolve_undo_read(data, sz);
+ break;
default:
if (*ext < 'A' || 'Z' < *ext)
return error("index uses %.4s extension, which we do not understand",
@@ -1360,6 +1365,7 @@ int is_index_unborn(struct index_state *istate)
int discard_index(struct index_state *istate)
{
+ resolve_undo_clear_index(istate);
istate->cache_nr = 0;
istate->cache_changed = 0;
istate->timestamp.sec = 0;
@@ -1585,6 +1591,17 @@ int write_index(struct index_state *istate, int newfd)
if (err)
return -1;
}
+ if (istate->resolve_undo) {
+ struct strbuf sb = STRBUF_INIT;
+
+ resolve_undo_write(&sb, istate->resolve_undo);
+ err = write_index_ext_header(&c, newfd, CACHE_EXT_RESOLVE_UNDO,
+ sb.len) < 0
+ || ce_write(&c, newfd, sb.buf, sb.len) < 0;
+ strbuf_release(&sb);
+ if (err)
+ return -1;
+ }
if (ce_flush(&c, newfd) || fstat(newfd, &st))
return -1;
@@ -1628,81 +1645,6 @@ int read_index_unmerged(struct index_state *istate)
return unmerged;
}
-struct update_callback_data
-{
- int flags;
- int add_errors;
-};
-
-static void update_callback(struct diff_queue_struct *q,
- struct diff_options *opt, void *cbdata)
-{
- int i;
- struct update_callback_data *data = cbdata;
-
- for (i = 0; i < q->nr; i++) {
- struct diff_filepair *p = q->queue[i];
- const char *path = p->one->path;
- switch (p->status) {
- default:
- die("unexpected diff status %c", p->status);
- case DIFF_STATUS_UNMERGED:
- /*
- * ADD_CACHE_IGNORE_REMOVAL is unset if "git
- * add -u" is calling us, In such a case, a
- * missing work tree file needs to be removed
- * if there is an unmerged entry at stage #2,
- * but such a diff record is followed by
- * another with DIFF_STATUS_DELETED (and if
- * there is no stage #2, we won't see DELETED
- * nor MODIFIED). We can simply continue
- * either way.
- */
- if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL))
- continue;
- /*
- * Otherwise, it is "git add path" is asking
- * to explicitly add it; we fall through. A
- * missing work tree file is an error and is
- * caught by add_file_to_index() in such a
- * case.
- */
- case DIFF_STATUS_MODIFIED:
- case DIFF_STATUS_TYPE_CHANGED:
- if (add_file_to_index(&the_index, path, data->flags)) {
- if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
- die("updating files failed");
- data->add_errors++;
- }
- break;
- case DIFF_STATUS_DELETED:
- if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
- break;
- if (!(data->flags & ADD_CACHE_PRETEND))
- remove_file_from_index(&the_index, path);
- if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
- printf("remove '%s'\n", path);
- break;
- }
- }
-}
-
-int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
-{
- struct update_callback_data data;
- struct rev_info rev;
- init_revisions(&rev, prefix);
- setup_revisions(0, NULL, &rev, NULL);
- rev.prune_data = pathspec;
- rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
- rev.diffopt.format_callback = update_callback;
- data.flags = flags;
- data.add_errors = 0;
- rev.diffopt.format_callback_data = &data;
- run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
- return !!data.add_errors;
-}
-
/*
* Returns 1 if the path is an "other" path with respect to
* the index; that is, the path is not mentioned in the index at all,
diff --git a/remote-curl.c b/remote-curl.c
index 70fdcea..a904164 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -102,7 +102,7 @@ static struct discovery* discover_refs(const char *service)
struct strbuf buffer = STRBUF_INIT;
struct discovery *last = last_discovery;
char *refs_url;
- int http_ret, is_http = 0;
+ int http_ret, is_http = 0, proto_git_candidate = 1;
if (last && !strcmp(service, last->service))
return last;
@@ -121,6 +121,19 @@ static struct discovery* discover_refs(const char *service)
init_walker();
http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);
+
+ /* try again with "plain" url (no ? or & appended) */
+ if (http_ret != HTTP_OK) {
+ free(refs_url);
+ strbuf_reset(&buffer);
+
+ proto_git_candidate = 0;
+ strbuf_addf(&buffer, "%s/info/refs", url);
+ refs_url = strbuf_detach(&buffer, NULL);
+
+ http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);
+ }
+
switch (http_ret) {
case HTTP_OK:
break;
@@ -137,7 +150,8 @@ static struct discovery* discover_refs(const char *service)
last->buf_alloc = strbuf_detach(&buffer, &last->len);
last->buf = last->buf_alloc;
- if (is_http && 5 <= last->len && last->buf[4] == '#') {
+ if (is_http && proto_git_candidate
+ && 5 <= last->len && last->buf[4] == '#') {
/* smart HTTP response; validate that the service
* pkt-line matches our request.
*/
@@ -317,7 +331,7 @@ static size_t rpc_out(void *ptr, size_t eltsize,
}
#ifndef NO_CURL_IOCTL
-curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
+static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
{
struct rpc_state *rpc = clientp;
diff --git a/remote.c b/remote.c
index e3afecd..c70181c 100644
--- a/remote.c
+++ b/remote.c
@@ -1247,6 +1247,56 @@ int match_refs(struct ref *src, struct ref **dst,
return 0;
}
+void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
+ int force_update)
+{
+ struct ref *ref;
+
+ for (ref = remote_refs; ref; ref = ref->next) {
+ if (ref->peer_ref)
+ hashcpy(ref->new_sha1, ref->peer_ref->new_sha1);
+ else if (!send_mirror)
+ continue;
+
+ ref->deletion = is_null_sha1(ref->new_sha1);
+ if (!ref->deletion &&
+ !hashcmp(ref->old_sha1, ref->new_sha1)) {
+ ref->status = REF_STATUS_UPTODATE;
+ continue;
+ }
+
+ /* This part determines what can overwrite what.
+ * The rules are:
+ *
+ * (0) you can always use --force or +A:B notation to
+ * selectively force individual ref pairs.
+ *
+ * (1) if the old thing does not exist, it is OK.
+ *
+ * (2) if you do not have the old thing, you are not allowed
+ * to overwrite it; you would not know what you are losing
+ * otherwise.
+ *
+ * (3) if both new and old are commit-ish, and new is a
+ * descendant of old, it is OK.
+ *
+ * (4) regardless of all of the above, removing :B is
+ * always allowed.
+ */
+
+ ref->nonfastforward =
+ !ref->deletion &&
+ !is_null_sha1(ref->old_sha1) &&
+ (!has_sha1_file(ref->old_sha1)
+ || !ref_newer(ref->new_sha1, ref->old_sha1));
+
+ if (ref->nonfastforward && !ref->force && !force_update) {
+ ref->status = REF_STATUS_REJECT_NONFASTFORWARD;
+ continue;
+ }
+ }
+}
+
struct branch *branch_get(const char *name)
{
struct branch *ret;
diff --git a/remote.h b/remote.h
index 8b7ecf9..6e13643 100644
--- a/remote.h
+++ b/remote.h
@@ -98,6 +98,8 @@ char *apply_refspecs(struct refspec *refspecs, int nr_refspec,
int match_refs(struct ref *src, struct ref **dst,
int nr_refspec, const char **refspec, int all);
+void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
+ int force_update);
/*
* Given a list of the remote refs and the specification of things to
diff --git a/rerere.c b/rerere.c
index e0ac5bc..a86d73d 100644
--- a/rerere.c
+++ b/rerere.c
@@ -1,8 +1,11 @@
#include "cache.h"
#include "string-list.h"
#include "rerere.h"
-#include "xdiff/xdiff.h"
#include "xdiff-interface.h"
+#include "dir.h"
+#include "resolve-undo.h"
+#include "ll-merge.h"
+#include "attr.h"
/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
static int rerere_enabled = -1;
@@ -83,61 +86,106 @@ static inline void ferr_puts(const char *s, FILE *fp, int *err)
ferr_write(s, strlen(s), fp, err);
}
-static int handle_file(const char *path,
- unsigned char *sha1, const char *output)
+struct rerere_io {
+ int (*getline)(struct strbuf *, struct rerere_io *);
+ FILE *output;
+ int wrerror;
+ /* some more stuff */
+};
+
+static void rerere_io_putstr(const char *str, struct rerere_io *io)
+{
+ if (io->output)
+ ferr_puts(str, io->output, &io->wrerror);
+}
+
+static void rerere_io_putconflict(int ch, int size, struct rerere_io *io)
+{
+ char buf[64];
+
+ while (size) {
+ if (size < sizeof(buf) - 2) {
+ memset(buf, ch, size);
+ buf[size] = '\n';
+ buf[size + 1] = '\0';
+ size = 0;
+ } else {
+ int sz = sizeof(buf) - 1;
+ if (size <= sz)
+ sz -= (sz - size) + 1;
+ memset(buf, ch, sz);
+ buf[sz] = '\0';
+ size -= sz;
+ }
+ rerere_io_putstr(buf, io);
+ }
+}
+
+static void rerere_io_putmem(const char *mem, size_t sz, struct rerere_io *io)
+{
+ if (io->output)
+ ferr_write(mem, sz, io->output, &io->wrerror);
+}
+
+struct rerere_io_file {
+ struct rerere_io io;
+ FILE *input;
+};
+
+static int rerere_file_getline(struct strbuf *sb, struct rerere_io *io_)
+{
+ struct rerere_io_file *io = (struct rerere_io_file *)io_;
+ return strbuf_getwholeline(sb, io->input, '\n');
+}
+
+static int is_cmarker(char *buf, int marker_char, int marker_size, int want_sp)
+{
+ while (marker_size--)
+ if (*buf++ != marker_char)
+ return 0;
+ if (want_sp && *buf != ' ')
+ return 0;
+ return isspace(*buf);
+}
+
+static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_size)
{
git_SHA_CTX ctx;
- char buf[1024];
int hunk_no = 0;
enum {
RR_CONTEXT = 0, RR_SIDE_1, RR_SIDE_2, RR_ORIGINAL,
} hunk = RR_CONTEXT;
struct strbuf one = STRBUF_INIT, two = STRBUF_INIT;
- FILE *f = fopen(path, "r");
- FILE *out = NULL;
- int wrerror = 0;
-
- if (!f)
- return error("Could not open %s", path);
-
- if (output) {
- out = fopen(output, "w");
- if (!out) {
- fclose(f);
- return error("Could not write %s", output);
- }
- }
+ struct strbuf buf = STRBUF_INIT;
if (sha1)
git_SHA1_Init(&ctx);
- while (fgets(buf, sizeof(buf), f)) {
- if (!prefixcmp(buf, "<<<<<<< ")) {
+ while (!io->getline(&buf, io)) {
+ if (is_cmarker(buf.buf, '<', marker_size, 1)) {
if (hunk != RR_CONTEXT)
goto bad;
hunk = RR_SIDE_1;
- } else if (!prefixcmp(buf, "|||||||") && isspace(buf[7])) {
+ } else if (is_cmarker(buf.buf, '|', marker_size, 0)) {
if (hunk != RR_SIDE_1)
goto bad;
hunk = RR_ORIGINAL;
- } else if (!prefixcmp(buf, "=======") && isspace(buf[7])) {
+ } else if (is_cmarker(buf.buf, '=', marker_size, 0)) {
if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL)
goto bad;
hunk = RR_SIDE_2;
- } else if (!prefixcmp(buf, ">>>>>>> ")) {
+ } else if (is_cmarker(buf.buf, '>', marker_size, 1)) {
if (hunk != RR_SIDE_2)
goto bad;
if (strbuf_cmp(&one, &two) > 0)
strbuf_swap(&one, &two);
hunk_no++;
hunk = RR_CONTEXT;
- if (out) {
- ferr_puts("<<<<<<<\n", out, &wrerror);
- ferr_write(one.buf, one.len, out, &wrerror);
- ferr_puts("=======\n", out, &wrerror);
- ferr_write(two.buf, two.len, out, &wrerror);
- ferr_puts(">>>>>>>\n", out, &wrerror);
- }
+ rerere_io_putconflict('<', marker_size, io);
+ rerere_io_putmem(one.buf, one.len, io);
+ rerere_io_putconflict('=', marker_size, io);
+ rerere_io_putmem(two.buf, two.len, io);
+ rerere_io_putconflict('>', marker_size, io);
if (sha1) {
git_SHA1_Update(&ctx, one.buf ? one.buf : "",
one.len + 1);
@@ -147,13 +195,13 @@ static int handle_file(const char *path,
strbuf_reset(&one);
strbuf_reset(&two);
} else if (hunk == RR_SIDE_1)
- strbuf_addstr(&one, buf);
+ strbuf_addstr(&one, buf.buf);
else if (hunk == RR_ORIGINAL)
; /* discard */
else if (hunk == RR_SIDE_2)
- strbuf_addstr(&two, buf);
- else if (out)
- ferr_puts(buf, out, &wrerror);
+ strbuf_addstr(&two, buf.buf);
+ else
+ rerere_io_putstr(buf.buf, io);
continue;
bad:
hunk = 99; /* force error exit */
@@ -161,23 +209,135 @@ static int handle_file(const char *path,
}
strbuf_release(&one);
strbuf_release(&two);
+ strbuf_release(&buf);
- fclose(f);
- if (wrerror)
- error("There were errors while writing %s (%s)",
- path, strerror(wrerror));
- if (out && fclose(out))
- wrerror = error("Failed to flush %s: %s",
- path, strerror(errno));
if (sha1)
git_SHA1_Final(sha1, &ctx);
- if (hunk != RR_CONTEXT) {
+ if (hunk != RR_CONTEXT)
+ return -1;
+ return hunk_no;
+}
+
+static int handle_file(const char *path, unsigned char *sha1, const char *output)
+{
+ int hunk_no = 0;
+ struct rerere_io_file io;
+ int marker_size = ll_merge_marker_size(path);
+
+ memset(&io, 0, sizeof(io));
+ io.io.getline = rerere_file_getline;
+ io.input = fopen(path, "r");
+ io.io.wrerror = 0;
+ if (!io.input)
+ return error("Could not open %s", path);
+
+ if (output) {
+ io.io.output = fopen(output, "w");
+ if (!io.io.output) {
+ fclose(io.input);
+ return error("Could not write %s", output);
+ }
+ }
+
+ hunk_no = handle_path(sha1, (struct rerere_io *)&io, marker_size);
+
+ fclose(io.input);
+ if (io.io.wrerror)
+ error("There were errors while writing %s (%s)",
+ path, strerror(io.io.wrerror));
+ if (io.io.output && fclose(io.io.output))
+ io.io.wrerror = error("Failed to flush %s: %s",
+ path, strerror(errno));
+
+ if (hunk_no < 0) {
if (output)
unlink_or_warn(output);
return error("Could not parse conflict hunks in %s", path);
}
- if (wrerror)
+ if (io.io.wrerror)
+ return -1;
+ return hunk_no;
+}
+
+struct rerere_io_mem {
+ struct rerere_io io;
+ struct strbuf input;
+};
+
+static int rerere_mem_getline(struct strbuf *sb, struct rerere_io *io_)
+{
+ struct rerere_io_mem *io = (struct rerere_io_mem *)io_;
+ char *ep;
+ size_t len;
+
+ strbuf_release(sb);
+ if (!io->input.len)
+ return -1;
+ ep = strchrnul(io->input.buf, '\n');
+ if (*ep == '\n')
+ ep++;
+ len = ep - io->input.buf;
+ strbuf_add(sb, io->input.buf, len);
+ strbuf_remove(&io->input, 0, len);
+ return 0;
+}
+
+static int handle_cache(const char *path, unsigned char *sha1, const char *output)
+{
+ mmfile_t mmfile[3];
+ mmbuffer_t result = {NULL, 0};
+ struct cache_entry *ce;
+ int pos, len, i, hunk_no;
+ struct rerere_io_mem io;
+ int marker_size = ll_merge_marker_size(path);
+
+ /*
+ * Reproduce the conflicted merge in-core
+ */
+ len = strlen(path);
+ pos = cache_name_pos(path, len);
+ if (0 <= pos)
return -1;
+ pos = -pos - 1;
+
+ for (i = 0; i < 3; i++) {
+ enum object_type type;
+ unsigned long size;
+
+ mmfile[i].size = 0;
+ mmfile[i].ptr = NULL;
+ if (active_nr <= pos)
+ break;
+ ce = active_cache[pos++];
+ if (ce_namelen(ce) != len || memcmp(ce->name, path, len)
+ || ce_stage(ce) != i + 1)
+ break;
+ mmfile[i].ptr = read_sha1_file(ce->sha1, &type, &size);
+ mmfile[i].size = size;
+ }
+ for (i = 0; i < 3; i++) {
+ if (!mmfile[i].ptr && !mmfile[i].size)
+ mmfile[i].ptr = xstrdup("");
+ }
+ ll_merge(&result, path, &mmfile[0],
+ &mmfile[1], "ours",
+ &mmfile[2], "theirs", 0);
+ for (i = 0; i < 3; i++)
+ free(mmfile[i].ptr);
+
+ memset(&io, 0, sizeof(&io));
+ io.io.getline = rerere_mem_getline;
+ if (output)
+ io.io.output = fopen(output, "w");
+ else
+ io.io.output = NULL;
+ strbuf_init(&io.input, 0);
+ strbuf_attach(&io.input, result.ptr, result.size, result.size);
+
+ hunk_no = handle_path(sha1, (struct rerere_io *)&io, marker_size);
+ strbuf_release(&io.input);
+ if (io.io.output)
+ fclose(io.io.output);
return hunk_no;
}
@@ -206,7 +366,6 @@ static int merge(const char *name, const char *path)
int ret;
mmfile_t cur, base, other;
mmbuffer_t result = {NULL, 0};
- xpparam_t xpp = {XDF_NEED_MINIMAL};
if (handle_file(path, NULL, rerere_path(name, "thisimage")) < 0)
return 1;
@@ -215,8 +374,7 @@ static int merge(const char *name, const char *path)
read_mmfile(&base, rerere_path(name, "preimage")) ||
read_mmfile(&other, rerere_path(name, "postimage")))
return 1;
- ret = xdl_merge(&base, &cur, "", &other, "",
- &xpp, XDL_MERGE_ZEALOUS, &result);
+ ret = ll_merge(&result, path, &base, &cur, "", &other, "", 0);
if (!ret) {
FILE *f = fopen(path, "w");
if (!f)
@@ -394,3 +552,52 @@ int rerere(int flags)
return 0;
return do_plain_rerere(&merge_rr, fd);
}
+
+static int rerere_forget_one_path(const char *path, struct string_list *rr)
+{
+ const char *filename;
+ char *hex;
+ unsigned char sha1[20];
+ int ret;
+
+ ret = handle_cache(path, sha1, NULL);
+ if (ret < 1)
+ return error("Could not parse conflict hunks in '%s'", path);
+ hex = xstrdup(sha1_to_hex(sha1));
+ filename = rerere_path(hex, "postimage");
+ if (unlink(filename))
+ return (errno == ENOENT
+ ? error("no remembered resolution for %s", path)
+ : error("cannot unlink %s: %s", filename, strerror(errno)));
+
+ handle_cache(path, sha1, rerere_path(hex, "preimage"));
+ fprintf(stderr, "Updated preimage for '%s'\n", path);
+
+
+ string_list_insert(path, rr)->util = hex;
+ fprintf(stderr, "Forgot resolution for %s\n", path);
+ return 0;
+}
+
+int rerere_forget(const char **pathspec)
+{
+ int i, fd;
+ struct string_list conflict = { NULL, 0, 0, 1 };
+ struct string_list merge_rr = { NULL, 0, 0, 1 };
+
+ if (read_cache() < 0)
+ return error("Could not read index");
+
+ fd = setup_rerere(&merge_rr, RERERE_NOAUTOUPDATE);
+
+ unmerge_cache(pathspec);
+ find_conflict(&conflict);
+ for (i = 0; i < conflict.nr; i++) {
+ struct string_list_item *it = &conflict.items[i];
+ if (!match_pathspec(pathspec, it->string, strlen(it->string),
+ 0, NULL))
+ continue;
+ rerere_forget_one_path(it->string, &merge_rr);
+ }
+ return write_rr(&merge_rr, fd);
+}
diff --git a/rerere.h b/rerere.h
index 10a94a4..eaa9004 100644
--- a/rerere.h
+++ b/rerere.h
@@ -10,6 +10,7 @@ extern int setup_rerere(struct string_list *, int);
extern int rerere(int);
extern const char *rerere_path(const char *hex, const char *file);
extern int has_rerere_resolution(const char *hex);
+extern int rerere_forget(const char **);
#define OPT_RERERE_AUTOUPDATE(v) OPT_UYN(0, "rerere-autoupdate", (v), \
"update the index with reused conflict resolution if possible")
diff --git a/resolve-undo.c b/resolve-undo.c
new file mode 100644
index 0000000..37d73cd
--- /dev/null
+++ b/resolve-undo.c
@@ -0,0 +1,176 @@
+#include "cache.h"
+#include "dir.h"
+#include "resolve-undo.h"
+#include "string-list.h"
+
+/* The only error case is to run out of memory in string-list */
+void record_resolve_undo(struct index_state *istate, struct cache_entry *ce)
+{
+ struct string_list_item *lost;
+ struct resolve_undo_info *ui;
+ struct string_list *resolve_undo;
+ int stage = ce_stage(ce);
+
+ if (!stage)
+ return;
+
+ if (!istate->resolve_undo) {
+ resolve_undo = xcalloc(1, sizeof(*resolve_undo));
+ resolve_undo->strdup_strings = 1;
+ istate->resolve_undo = resolve_undo;
+ }
+ resolve_undo = istate->resolve_undo;
+ lost = string_list_insert(ce->name, resolve_undo);
+ if (!lost->util)
+ lost->util = xcalloc(1, sizeof(*ui));
+ ui = lost->util;
+ hashcpy(ui->sha1[stage - 1], ce->sha1);
+ ui->mode[stage - 1] = ce->ce_mode;
+}
+
+static int write_one(struct string_list_item *item, void *cbdata)
+{
+ struct strbuf *sb = cbdata;
+ struct resolve_undo_info *ui = item->util;
+ int i;
+
+ if (!ui)
+ return 0;
+ strbuf_addstr(sb, item->string);
+ strbuf_addch(sb, 0);
+ for (i = 0; i < 3; i++)
+ strbuf_addf(sb, "%o%c", ui->mode[i], 0);
+ for (i = 0; i < 3; i++) {
+ if (!ui->mode[i])
+ continue;
+ strbuf_add(sb, ui->sha1[i], 20);
+ }
+ return 0;
+}
+
+void resolve_undo_write(struct strbuf *sb, struct string_list *resolve_undo)
+{
+ for_each_string_list(write_one, resolve_undo, sb);
+}
+
+struct string_list *resolve_undo_read(void *data, unsigned long size)
+{
+ struct string_list *resolve_undo;
+ size_t len;
+ char *endptr;
+ int i;
+
+ resolve_undo = xcalloc(1, sizeof(*resolve_undo));
+ resolve_undo->strdup_strings = 1;
+
+ while (size) {
+ struct string_list_item *lost;
+ struct resolve_undo_info *ui;
+
+ len = strlen(data) + 1;
+ if (size <= len)
+ goto error;
+ lost = string_list_insert(data, resolve_undo);
+ if (!lost->util)
+ lost->util = xcalloc(1, sizeof(*ui));
+ ui = lost->util;
+ size -= len;
+ data += len;
+
+ for (i = 0; i < 3; i++) {
+ ui->mode[i] = strtoul(data, &endptr, 8);
+ if (!endptr || endptr == data || *endptr)
+ goto error;
+ len = (endptr + 1) - (char*)data;
+ if (size <= len)
+ goto error;
+ size -= len;
+ data += len;
+ }
+
+ for (i = 0; i < 3; i++) {
+ if (!ui->mode[i])
+ continue;
+ if (size < 20)
+ goto error;
+ hashcpy(ui->sha1[i], data);
+ size -= 20;
+ data += 20;
+ }
+ }
+ return resolve_undo;
+
+error:
+ string_list_clear(resolve_undo, 1);
+ error("Index records invalid resolve-undo information");
+ return NULL;
+}
+
+void resolve_undo_clear_index(struct index_state *istate)
+{
+ struct string_list *resolve_undo = istate->resolve_undo;
+ if (!resolve_undo)
+ return;
+ string_list_clear(resolve_undo, 1);
+ free(resolve_undo);
+ istate->resolve_undo = NULL;
+ istate->cache_changed = 1;
+}
+
+int unmerge_index_entry_at(struct index_state *istate, int pos)
+{
+ struct cache_entry *ce;
+ struct string_list_item *item;
+ struct resolve_undo_info *ru;
+ int i, err = 0;
+
+ if (!istate->resolve_undo)
+ return pos;
+
+ ce = istate->cache[pos];
+ if (ce_stage(ce)) {
+ /* already unmerged */
+ while ((pos < istate->cache_nr) &&
+ ! strcmp(istate->cache[pos]->name, ce->name))
+ pos++;
+ return pos - 1; /* return the last entry processed */
+ }
+ item = string_list_lookup(ce->name, istate->resolve_undo);
+ if (!item)
+ return pos;
+ ru = item->util;
+ if (!ru)
+ return pos;
+ remove_index_entry_at(istate, pos);
+ for (i = 0; i < 3; i++) {
+ struct cache_entry *nce;
+ if (!ru->mode[i])
+ continue;
+ nce = make_cache_entry(ru->mode[i], ru->sha1[i],
+ ce->name, i + 1, 0);
+ if (add_index_entry(istate, nce, ADD_CACHE_OK_TO_ADD)) {
+ err = 1;
+ error("cannot unmerge '%s'", ce->name);
+ }
+ }
+ if (err)
+ return pos;
+ free(ru);
+ item->util = NULL;
+ return unmerge_index_entry_at(istate, pos);
+}
+
+void unmerge_index(struct index_state *istate, const char **pathspec)
+{
+ int i;
+
+ if (!istate->resolve_undo)
+ return;
+
+ for (i = 0; i < istate->cache_nr; i++) {
+ struct cache_entry *ce = istate->cache[i];
+ if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, NULL))
+ continue;
+ i = unmerge_index_entry_at(istate, i);
+ }
+}
diff --git a/resolve-undo.h b/resolve-undo.h
new file mode 100644
index 0000000..e4e5c1b
--- /dev/null
+++ b/resolve-undo.h
@@ -0,0 +1,16 @@
+#ifndef RESOLVE_UNDO_H
+#define RESOLVE_UNDO_H
+
+struct resolve_undo_info {
+ unsigned int mode[3];
+ unsigned char sha1[3][20];
+};
+
+extern void record_resolve_undo(struct index_state *, struct cache_entry *);
+extern void resolve_undo_write(struct strbuf *, struct string_list *);
+extern struct string_list *resolve_undo_read(void *, unsigned long);
+extern void resolve_undo_clear_index(struct index_state *);
+extern int unmerge_index_entry_at(struct index_state *, int);
+extern void unmerge_index(struct index_state *, const char **);
+
+#endif
diff --git a/revision.c b/revision.c
index 1e9277d..1d3457c 100644
--- a/revision.c
+++ b/revision.c
@@ -1167,13 +1167,22 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
revs->verbose_header = 1;
} else if (!strcmp(arg, "--pretty")) {
revs->verbose_header = 1;
+ revs->pretty_given = 1;
get_commit_format(arg+8, revs);
} else if (!prefixcmp(arg, "--pretty=") || !prefixcmp(arg, "--format=")) {
revs->verbose_header = 1;
+ revs->pretty_given = 1;
get_commit_format(arg+9, revs);
+ } else if (!strcmp(arg, "--show-notes")) {
+ revs->show_notes = 1;
+ revs->show_notes_given = 1;
+ } else if (!strcmp(arg, "--no-notes")) {
+ revs->show_notes = 0;
+ revs->show_notes_given = 1;
} else if (!strcmp(arg, "--oneline")) {
revs->verbose_header = 1;
get_commit_format("oneline", revs);
+ revs->pretty_given = 1;
revs->abbrev_commit = 1;
} else if (!strcmp(arg, "--graph")) {
revs->topo_order = 1;
diff --git a/revision.h b/revision.h
index d368003..a14deef 100644
--- a/revision.h
+++ b/revision.h
@@ -80,6 +80,9 @@ struct rev_info {
/* Format info */
unsigned int shown_one:1,
show_merge:1,
+ show_notes:1,
+ show_notes_given:1,
+ pretty_given:1,
abbrev_commit:1,
use_terminator:1,
missing_newline:1,
diff --git a/run-command.c b/run-command.c
index a909845..2feb493 100644
--- a/run-command.c
+++ b/run-command.c
@@ -61,6 +61,78 @@ static int execv_shell_cmd(const char **argv)
}
#endif
+#ifndef WIN32
+static int child_err = 2;
+static int child_notifier = -1;
+
+static void notify_parent(void)
+{
+ write(child_notifier, "", 1);
+}
+
+static NORETURN void die_child(const char *err, va_list params)
+{
+ char msg[4096];
+ int len = vsnprintf(msg, sizeof(msg), err, params);
+ if (len > sizeof(msg))
+ len = sizeof(msg);
+
+ write(child_err, "fatal: ", 7);
+ write(child_err, msg, len);
+ write(child_err, "\n", 1);
+ exit(128);
+}
+
+static inline void set_cloexec(int fd)
+{
+ int flags = fcntl(fd, F_GETFD);
+ if (flags >= 0)
+ fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
+}
+#endif
+
+static int wait_or_whine(pid_t pid, const char *argv0, int silent_exec_failure)
+{
+ int status, code = -1;
+ pid_t waiting;
+ int failed_errno = 0;
+
+ while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
+ ; /* nothing */
+
+ if (waiting < 0) {
+ failed_errno = errno;
+ error("waitpid for %s failed: %s", argv0, strerror(errno));
+ } else if (waiting != pid) {
+ error("waitpid is confused (%s)", argv0);
+ } else if (WIFSIGNALED(status)) {
+ code = WTERMSIG(status);
+ error("%s died of signal %d", argv0, code);
+ /*
+ * This return value is chosen so that code & 0xff
+ * mimics the exit code that a POSIX shell would report for
+ * a program that died from this signal.
+ */
+ code -= 128;
+ } else if (WIFEXITED(status)) {
+ code = WEXITSTATUS(status);
+ /*
+ * Convert special exit code when execvp failed.
+ */
+ if (code == 127) {
+ code = -1;
+ failed_errno = ENOENT;
+ if (!silent_exec_failure)
+ error("cannot run %s: %s", argv0,
+ strerror(ENOENT));
+ }
+ } else {
+ error("waitpid is confused (%s)", argv0);
+ }
+ errno = failed_errno;
+ return code;
+}
+
int start_command(struct child_process *cmd)
{
int need_in, need_out, need_err;
@@ -122,9 +194,30 @@ fail_pipe:
trace_argv_printf(cmd->argv, "trace: run_command:");
#ifndef WIN32
+{
+ int notify_pipe[2];
+ if (pipe(notify_pipe))
+ notify_pipe[0] = notify_pipe[1] = -1;
+
fflush(NULL);
cmd->pid = fork();
if (!cmd->pid) {
+ /*
+ * Redirect the channel to write syscall error messages to
+ * before redirecting the process's stderr so that all die()
+ * in subsequent call paths use the parent's stderr.
+ */
+ if (cmd->no_stderr || need_err) {
+ child_err = dup(2);
+ set_cloexec(child_err);
+ }
+ set_die_routine(die_child);
+
+ close(notify_pipe[0]);
+ set_cloexec(notify_pipe[1]);
+ child_notifier = notify_pipe[1];
+ atexit(notify_parent);
+
if (cmd->no_stdin)
dup_devnull(0);
else if (need_in) {
@@ -165,8 +258,16 @@ fail_pipe:
unsetenv(*cmd->env);
}
}
- if (cmd->preexec_cb)
+ if (cmd->preexec_cb) {
+ /*
+ * We cannot predict what the pre-exec callback does.
+ * Forgo parent notification.
+ */
+ close(child_notifier);
+ child_notifier = -1;
+
cmd->preexec_cb();
+ }
if (cmd->git_cmd) {
execv_git_cmd(cmd->argv);
} else if (cmd->use_shell) {
@@ -174,13 +275,39 @@ fail_pipe:
} else {
execvp(cmd->argv[0], (char *const*) cmd->argv);
}
- trace_printf("trace: exec '%s' failed: %s\n", cmd->argv[0],
- strerror(errno));
- exit(127);
+ /*
+ * Do not check for cmd->silent_exec_failure; the parent
+ * process will check it when it sees this exit code.
+ */
+ if (errno == ENOENT)
+ exit(127);
+ else
+ die_errno("cannot exec '%s'", cmd->argv[0]);
}
if (cmd->pid < 0)
error("cannot fork() for %s: %s", cmd->argv[0],
strerror(failed_errno = errno));
+
+ /*
+ * Wait for child's execvp. If the execvp succeeds (or if fork()
+ * failed), EOF is seen immediately by the parent. Otherwise, the
+ * child process sends a single byte.
+ * Note that use of this infrastructure is completely advisory,
+ * therefore, we keep error checks minimal.
+ */
+ close(notify_pipe[1]);
+ if (read(notify_pipe[0], &notify_pipe[1], 1) == 1) {
+ /*
+ * At this point we know that fork() succeeded, but execvp()
+ * failed. Errors have been reported to our stderr.
+ */
+ wait_or_whine(cmd->pid, cmd->argv[0],
+ cmd->silent_exec_failure);
+ failed_errno = errno;
+ cmd->pid = -1;
+ }
+ close(notify_pipe[0]);
+}
#else
{
int fhin = 0, fhout = 1, fherr = 2;
@@ -271,48 +398,6 @@ fail_pipe:
return 0;
}
-static int wait_or_whine(pid_t pid, const char *argv0, int silent_exec_failure)
-{
- int status, code = -1;
- pid_t waiting;
- int failed_errno = 0;
-
- while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
- ; /* nothing */
-
- if (waiting < 0) {
- failed_errno = errno;
- error("waitpid for %s failed: %s", argv0, strerror(errno));
- } else if (waiting != pid) {
- error("waitpid is confused (%s)", argv0);
- } else if (WIFSIGNALED(status)) {
- code = WTERMSIG(status);
- error("%s died of signal %d", argv0, code);
- /*
- * This return value is chosen so that code & 0xff
- * mimics the exit code that a POSIX shell would report for
- * a program that died from this signal.
- */
- code -= 128;
- } else if (WIFEXITED(status)) {
- code = WEXITSTATUS(status);
- /*
- * Convert special exit code when execvp failed.
- */
- if (code == 127) {
- code = -1;
- failed_errno = ENOENT;
- if (!silent_exec_failure)
- error("cannot run %s: %s", argv0,
- strerror(ENOENT));
- }
- } else {
- error("waitpid is confused (%s)", argv0);
- }
- errno = failed_errno;
- return code;
-}
-
int finish_command(struct child_process *cmd)
{
return wait_or_whine(cmd->pid, cmd->argv[0], cmd->silent_exec_failure);
diff --git a/setup.c b/setup.c
index 3a07aa4..710e2f3 100644
--- a/setup.c
+++ b/setup.c
@@ -263,6 +263,8 @@ static int check_repository_format_gently(int *nongit_ok)
const char *read_gitfile_gently(const char *path)
{
char *buf;
+ char *dir;
+ const char *slash;
struct stat st;
int fd;
size_t len;
@@ -287,9 +289,23 @@ const char *read_gitfile_gently(const char *path)
if (len < 9)
die("No path in gitfile: %s", path);
buf[len] = '\0';
- if (!is_git_directory(buf + 8))
- die("Not a git repository: %s", buf + 8);
- path = make_absolute_path(buf + 8);
+ dir = buf + 8;
+
+ if (!is_absolute_path(dir) && (slash = strrchr(path, '/'))) {
+ size_t pathlen = slash+1 - path;
+ size_t dirlen = pathlen + len - 8;
+ dir = xmalloc(dirlen + 1);
+ strncpy(dir, path, pathlen);
+ strncpy(dir + pathlen, buf + 8, len - 8);
+ dir[dirlen] = '\0';
+ free(buf);
+ buf = dir;
+ }
+
+ if (!is_git_directory(dir))
+ die("Not a git repository: %s", dir);
+ path = make_absolute_path(dir);
+
free(buf);
return path;
}
diff --git a/sha1_file.c b/sha1_file.c
index 63981fb..12478a3 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -35,54 +35,6 @@ static size_t sz_fmt(size_t s) { return s; }
const unsigned char null_sha1[20];
-const signed char hexval_table[256] = {
- -1, -1, -1, -1, -1, -1, -1, -1, /* 00-07 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 08-0f */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 10-17 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 18-1f */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 20-27 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 28-2f */
- 0, 1, 2, 3, 4, 5, 6, 7, /* 30-37 */
- 8, 9, -1, -1, -1, -1, -1, -1, /* 38-3f */
- -1, 10, 11, 12, 13, 14, 15, -1, /* 40-47 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 48-4f */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 50-57 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 58-5f */
- -1, 10, 11, 12, 13, 14, 15, -1, /* 60-67 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 68-67 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 70-77 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 78-7f */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 80-87 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 88-8f */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 90-97 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 98-9f */
- -1, -1, -1, -1, -1, -1, -1, -1, /* a0-a7 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* a8-af */
- -1, -1, -1, -1, -1, -1, -1, -1, /* b0-b7 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* b8-bf */
- -1, -1, -1, -1, -1, -1, -1, -1, /* c0-c7 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* c8-cf */
- -1, -1, -1, -1, -1, -1, -1, -1, /* d0-d7 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* d8-df */
- -1, -1, -1, -1, -1, -1, -1, -1, /* e0-e7 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* e8-ef */
- -1, -1, -1, -1, -1, -1, -1, -1, /* f0-f7 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* f8-ff */
-};
-
-int get_sha1_hex(const char *hex, unsigned char *sha1)
-{
- int i;
- for (i = 0; i < 20; i++) {
- unsigned int val = (hexval(hex[0]) << 4) | hexval(hex[1]);
- if (val & ~0xff)
- return -1;
- *sha1++ = val;
- hex += 2;
- }
- return 0;
-}
-
static inline int offset_1st_component(const char *path)
{
if (has_dos_drive_prefix(path))
@@ -133,24 +85,6 @@ int safe_create_leading_directories_const(const char *path)
return result;
}
-char *sha1_to_hex(const unsigned char *sha1)
-{
- static int bufno;
- static char hexbuffer[4][50];
- static const char hex[] = "0123456789abcdef";
- char *buffer = hexbuffer[3 & ++bufno], *buf = buffer;
- int i;
-
- for (i = 0; i < 20; i++) {
- unsigned int val = *sha1++;
- *buf++ = hex[val >> 4];
- *buf++ = hex[val & 0xf];
- }
- *buf = '\0';
-
- return buffer;
-}
-
static void fill_sha1_path(char *pathbuf, const unsigned char *sha1)
{
int i;
@@ -2458,14 +2392,6 @@ int has_pack_index(const unsigned char *sha1)
return 1;
}
-int has_pack_file(const unsigned char *sha1)
-{
- struct stat st;
- if (stat(sha1_pack_name(sha1), &st))
- return 0;
- return 1;
-}
-
int has_sha1_pack(const unsigned char *sha1)
{
struct pack_entry e;
diff --git a/show-index.c b/show-index.c
index 63f9da5..4c0ac13 100644
--- a/show-index.c
+++ b/show-index.c
@@ -48,7 +48,7 @@ int main(int argc, char **argv)
unsigned char sha1[20];
uint32_t crc;
uint32_t off;
- } *entries = xmalloc(nr * sizeof(entries[0]));
+ } *entries = malloc(nr * sizeof(entries[0]));
for (i = 0; i < nr; i++)
if (fread(entries[i].sha1, 20, 1, stdin) != 1)
die("unable to read sha1 %u/%u", i, nr);
diff --git a/strbuf.c b/strbuf.c
index a6153dc..bc3a080 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -10,6 +10,15 @@ int prefixcmp(const char *str, const char *prefix)
return (unsigned char)*prefix - (unsigned char)*str;
}
+int suffixcmp(const char *str, const char *suffix)
+{
+ int len = strlen(str), suflen = strlen(suffix);
+ if (len < suflen)
+ return -1;
+ else
+ return strcmp(str + len - suflen, suffix);
+}
+
/*
* Used as the default ->buf value, so that people can always assume
* buf is non NULL and ->buf is NUL terminated even for a freshly
@@ -91,13 +100,6 @@ void strbuf_ltrim(struct strbuf *sb)
sb->buf[sb->len] = '\0';
}
-void strbuf_tolower(struct strbuf *sb)
-{
- int i;
- for (i = 0; i < sb->len; i++)
- sb->buf[i] = tolower(sb->buf[i]);
-}
-
struct strbuf **strbuf_split(const struct strbuf *sb, int delim)
{
int alloc = 2, pos = 0;
@@ -227,6 +229,12 @@ void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
break;
format = percent + 1;
+ if (*format == '%') {
+ strbuf_addch(sb, '%');
+ format++;
+ continue;
+ }
+
consumed = fn(sb, format, context);
if (consumed)
format += consumed;
@@ -251,6 +259,17 @@ size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
return 0;
}
+void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src)
+{
+ int i, len = src->len;
+
+ for (i = 0; i < len; i++) {
+ if (src->buf[i] == '%')
+ strbuf_addch(dst, '%');
+ strbuf_addch(dst, src->buf[i]);
+ }
+}
+
size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
{
size_t res;
diff --git a/strbuf.h b/strbuf.h
index fa07ecf..fac2dbc 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -81,7 +81,6 @@ extern void strbuf_trim(struct strbuf *);
extern void strbuf_rtrim(struct strbuf *);
extern void strbuf_ltrim(struct strbuf *);
extern int strbuf_cmp(const struct strbuf *, const struct strbuf *);
-extern void strbuf_tolower(struct strbuf *);
extern struct strbuf **strbuf_split(const struct strbuf *, int delim);
extern void strbuf_list_free(struct strbuf **);
@@ -105,6 +104,7 @@ static inline void strbuf_addstr(struct strbuf *sb, const char *s) {
strbuf_add(sb, s, strlen(s));
}
static inline void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2) {
+ strbuf_grow(sb, sb2->len);
strbuf_add(sb, sb2->buf, sb2->len);
}
extern void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len);
@@ -116,6 +116,7 @@ struct strbuf_expand_dict_entry {
const char *value;
};
extern size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder, void *context);
+extern void strbuf_addbuf_percentquote(struct strbuf *dst, const struct strbuf *src);
__attribute__((format (printf,2,3)))
extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
diff --git a/submodule.c b/submodule.c
index 86aad65..3007f7d 100644
--- a/submodule.c
+++ b/submodule.c
@@ -5,7 +5,7 @@
#include "commit.h"
#include "revision.h"
-int add_submodule_odb(const char *path)
+static int add_submodule_odb(const char *path)
{
struct strbuf objects_directory = STRBUF_INIT;
struct alternate_object_database *alt_odb;
diff --git a/symlinks.c b/symlinks.c
index 7b0a86d..8860120 100644
--- a/symlinks.c
+++ b/symlinks.c
@@ -179,37 +179,6 @@ static int lstat_cache(struct cache_def *cache, const char *name, int len,
return ret_flags;
}
-/*
- * Invalidate the given 'name' from the cache, if 'name' matches
- * completely with the cache.
- */
-void invalidate_lstat_cache(const char *name, int len)
-{
- int match_len, previous_slash;
- struct cache_def *cache = &default_cache; /* FIXME */
-
- match_len = longest_path_match(name, len, cache->path, cache->len,
- &previous_slash);
- if (len == match_len) {
- if ((cache->track_flags & FL_DIR) && previous_slash > 0) {
- cache->path[previous_slash] = '\0';
- cache->len = previous_slash;
- cache->flags = FL_DIR;
- } else {
- reset_lstat_cache(cache);
- }
- }
-}
-
-/*
- * Completely clear the contents of the cache
- */
-void clear_lstat_cache(void)
-{
- struct cache_def *cache = &default_cache; /* FIXME */
- reset_lstat_cache(cache);
-}
-
#define USE_ONLY_LSTAT 0
/*
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
index 62f452c..6aefe27 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -2,21 +2,33 @@
# After setting the fake editor with this function, you can
#
-# - override the commit message with $FAKE_COMMIT_MESSAGE,
+# - override the commit message with $FAKE_COMMIT_MESSAGE
# - amend the commit message with $FAKE_COMMIT_AMEND
# - check that non-commit messages have a certain line count with $EXPECT_COUNT
-# - rewrite a rebase -i script with $FAKE_LINES in the form
+# - check the commit count in the commit message header with $EXPECT_HEADER_COUNT
+# - rewrite a rebase -i script as directed by $FAKE_LINES.
+# $FAKE_LINES consists of a sequence of words separated by spaces.
+# The following word combinations are possible:
#
-# "[<lineno1>] [<lineno2>]..."
+# "<lineno>" -- add a "pick" line with the SHA1 taken from the
+# specified line.
#
-# If a line number is prefixed with "squash", "edit", or "reword", the
-# respective line's command will be replaced with the specified one.
+# "<cmd> <lineno>" -- add a line with the specified command
+# ("squash", "fixup", "edit", or "reword") and the SHA1 taken
+# from the specified line.
+#
+# "#" -- Add a comment line.
+#
+# ">" -- Add a blank line.
set_fake_editor () {
echo "#!$SHELL_PATH" >fake-editor.sh
cat >> fake-editor.sh <<\EOF
case "$1" in
*/COMMIT_EDITMSG)
+ test -z "$EXPECT_HEADER_COUNT" ||
+ test "$EXPECT_HEADER_COUNT" = "$(sed -n '1s/^# This is a combination of \(.*\) commits\./\1/p' < "$1")" ||
+ exit
test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
exit
@@ -28,19 +40,24 @@ test -z "$EXPECT_COUNT" ||
test -z "$FAKE_LINES" && exit
grep -v '^#' < "$1" > "$1".tmp
rm -f "$1"
+echo 'rebase -i script before editing:'
cat "$1".tmp
action=pick
for line in $FAKE_LINES; do
case $line in
- squash|edit|reword)
+ squash|fixup|edit|reword)
action="$line";;
+ "#")
+ echo '# comment' >> "$1";;
+ ">")
+ echo >> "$1";;
*)
- echo sed -n "${line}s/^pick/$action/p"
- sed -n "${line}p" < "$1".tmp
sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
action=pick;;
esac
done
+echo 'rebase -i script after editing:'
+cat "$1"
EOF
test_set_editor "$(pwd)/fake-editor.sh"
diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh
new file mode 100755
index 0000000..10b26e4
--- /dev/null
+++ b/t/t0061-run-command.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Ilari Liusvaara
+#
+
+test_description='Test run command'
+
+. ./test-lib.sh
+
+test_expect_success 'start_command reports ENOENT' '
+ test-run-command start-command-ENOENT ./does-not-exist
+'
+
+test_done
diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh
new file mode 100755
index 0000000..cb7effe
--- /dev/null
+++ b/t/t2030-unresolve-info.sh
@@ -0,0 +1,170 @@
+#!/bin/sh
+
+test_description='undoing resolution'
+
+. ./test-lib.sh
+
+check_resolve_undo () {
+ msg=$1
+ shift
+ while case $# in
+ 0) break ;;
+ 1|2|3) die "Bug in check-resolve-undo test" ;;
+ esac
+ do
+ path=$1
+ shift
+ for stage in 1 2 3
+ do
+ sha1=$1
+ shift
+ case "$sha1" in
+ '') continue ;;
+ esac
+ sha1=$(git rev-parse --verify "$sha1")
+ printf "100644 %s %s\t%s\n" $sha1 $stage $path
+ done
+ done >"$msg.expect" &&
+ git ls-files --resolve-undo >"$msg.actual" &&
+ test_cmp "$msg.expect" "$msg.actual"
+}
+
+prime_resolve_undo () {
+ git reset --hard &&
+ git checkout second^0 &&
+ test_tick &&
+ test_must_fail git merge third^0 &&
+ echo merge does not leave anything &&
+ check_resolve_undo empty &&
+ echo different >fi/le &&
+ git add fi/le &&
+ echo resolving records &&
+ check_resolve_undo recorded fi/le initial:fi/le second:fi/le third:fi/le
+}
+
+test_expect_success setup '
+ mkdir fi &&
+ test_commit initial fi/le first &&
+ git branch side &&
+ git branch another &&
+ test_commit second fi/le second &&
+ git checkout side &&
+ test_commit third fi/le third &&
+ git checkout another &&
+ test_commit fourth fi/le fourth &&
+ git checkout master
+'
+
+test_expect_success 'add records switch clears' '
+ prime_resolve_undo &&
+ test_tick &&
+ git commit -m merged &&
+ echo committing keeps &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+ git checkout second^0 &&
+ echo switching clears &&
+ check_resolve_undo cleared
+'
+
+test_expect_success 'rm records reset clears' '
+ prime_resolve_undo &&
+ test_tick &&
+ git commit -m merged &&
+ echo committing keeps &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+
+ echo merge clears upfront &&
+ test_must_fail git merge fourth^0 &&
+ check_resolve_undo nuked &&
+
+ git rm -f fi/le &&
+ echo resolving records &&
+ check_resolve_undo recorded fi/le initial:fi/le HEAD:fi/le fourth:fi/le &&
+
+ git reset --hard &&
+ echo resetting discards &&
+ check_resolve_undo discarded
+'
+
+test_expect_success 'plumbing clears' '
+ prime_resolve_undo &&
+ test_tick &&
+ git commit -m merged &&
+ echo committing keeps &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+
+ echo plumbing clear &&
+ git update-index --clear-resolve-undo &&
+ check_resolve_undo cleared
+'
+
+test_expect_success 'add records checkout -m undoes' '
+ prime_resolve_undo &&
+ git diff HEAD &&
+ git checkout --conflict=merge fi/le &&
+ echo checkout used the record and removed it &&
+ check_resolve_undo removed &&
+ echo the index and the work tree is unmerged again &&
+ git diff >actual &&
+ grep "^++<<<<<<<" actual
+'
+
+test_expect_success 'unmerge with plumbing' '
+ prime_resolve_undo &&
+ git update-index --unresolve fi/le &&
+ git ls-files -u >actual &&
+ test $(wc -l <actual) = 3
+'
+
+test_expect_success 'rerere and rerere forget' '
+ mkdir .git/rr-cache &&
+ prime_resolve_undo &&
+ echo record the resolution &&
+ git rerere &&
+ rerere_id=$(cd .git/rr-cache && echo */postimage) &&
+ rerere_id=${rerere_id%/postimage} &&
+ test -f .git/rr-cache/$rerere_id/postimage &&
+ git checkout -m fi/le &&
+ echo resurrect the conflict &&
+ grep "^=======" fi/le &&
+ echo reresolve the conflict &&
+ git rerere &&
+ test "z$(cat fi/le)" = zdifferent &&
+ echo register the resolution again &&
+ git add fi/le &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+ test -z "$(git ls-files -u)" &&
+ git rerere forget fi/le &&
+ ! test -f .git/rr-cache/$rerere_id/postimage &&
+ tr "\0" "\n" <.git/MERGE_RR >actual &&
+ echo "$rerere_id fi/le" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rerere and rerere forget (subdirectory)' '
+ rm -fr .git/rr-cache &&
+ mkdir .git/rr-cache &&
+ prime_resolve_undo &&
+ echo record the resolution &&
+ (cd fi && git rerere) &&
+ rerere_id=$(cd .git/rr-cache && echo */postimage) &&
+ rerere_id=${rerere_id%/postimage} &&
+ test -f .git/rr-cache/$rerere_id/postimage &&
+ (cd fi && git checkout -m le) &&
+ echo resurrect the conflict &&
+ grep "^=======" fi/le &&
+ echo reresolve the conflict &&
+ (cd fi && git rerere) &&
+ test "z$(cat fi/le)" = zdifferent &&
+ echo register the resolution again &&
+ (cd fi && git add le) &&
+ check_resolve_undo kept fi/le initial:fi/le second:fi/le third:fi/le &&
+ test -z "$(git ls-files -u)" &&
+ (cd fi && git rerere forget le) &&
+ ! test -f .git/rr-cache/$rerere_id/postimage &&
+ tr "\0" "\n" <.git/MERGE_RR >actual &&
+ echo "$rerere_id fi/le" >expect &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t2105-update-index-gitfile.sh b/t/t2105-update-index-gitfile.sh
new file mode 100755
index 0000000..641607d
--- /dev/null
+++ b/t/t2105-update-index-gitfile.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Brad King
+#
+
+test_description='git update-index for gitlink to .git file.
+'
+
+. ./test-lib.sh
+
+test_expect_success 'submodule with absolute .git file' '
+ mkdir sub1 &&
+ (cd sub1 &&
+ git init &&
+ REAL="$(pwd)/.real" &&
+ mv .git "$REAL"
+ echo "gitdir: $REAL" >.git &&
+ test_commit first)
+'
+
+test_expect_success 'add gitlink to absolute .git file' '
+ git update-index --add -- sub1
+'
+
+test_expect_success 'submodule with relative .git file' '
+ mkdir sub2 &&
+ (cd sub2 &&
+ git init &&
+ mv .git .real &&
+ echo "gitdir: .real" >.git &&
+ test_commit first)
+'
+
+test_expect_success 'add gitlink to relative .git file' '
+ git update-index --add -- sub2
+'
+
+test_done
diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh
index 132c476..6d2f2b6 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -175,4 +175,43 @@ test_expect_success 'negated exclude matches can override previous ones' '
grep "^a.1" output
'
+test_expect_success 'subdirectory ignore (setup)' '
+ mkdir -p top/l1/l2 &&
+ (
+ cd top &&
+ git init &&
+ echo /.gitignore >.gitignore &&
+ echo l1 >>.gitignore &&
+ echo l2 >l1/.gitignore &&
+ >l1/l2/l1
+ )
+'
+
+test_expect_success 'subdirectory ignore (toplevel)' '
+ (
+ cd top &&
+ git ls-files -o --exclude-standard
+ ) >actual &&
+ >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'subdirectory ignore (l1/l2)' '
+ (
+ cd top/l1/l2 &&
+ git ls-files -o --exclude-standard
+ ) >actual &&
+ >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success 'subdirectory ignore (l1)' '
+ (
+ cd top/l1 &&
+ git ls-files -o --exclude-standard
+ ) >actual &&
+ >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh
index 9b3fa2b..9929f82 100755
--- a/t/t3030-merge-recursive.sh
+++ b/t/t3030-merge-recursive.sh
@@ -276,11 +276,13 @@ test_expect_success 'fail if the index has unresolved entries' '
test_must_fail git merge "$c5" &&
test_must_fail git merge "$c5" 2> out &&
+ grep "not possible because you have unmerged files" out &&
+ git add -u &&
+ test_must_fail git merge "$c5" 2> out &&
grep "You have not concluded your merge" out &&
rm -f .git/MERGE_HEAD &&
test_must_fail git merge "$c5" 2> out &&
- grep "You are in the middle of a conflicted merge" out
-
+ grep "Your local changes to .* would be overwritten by merge." out
'
test_expect_success 'merge-recursive remove conflict' '
diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
index 1e34f48..90178f9 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -12,11 +12,11 @@ echo "$MSG" > "$1"
echo "$MSG" >& 2
EOF
chmod a+x fake_editor.sh
-VISUAL=./fake_editor.sh
-export VISUAL
+GIT_EDITOR=./fake_editor.sh
+export GIT_EDITOR
test_expect_success 'cannot annotate non-existing HEAD' '
- (MSG=3 && export MSG && test_must_fail git notes edit)
+ (MSG=3 && export MSG && test_must_fail git notes add)
'
test_expect_success setup '
@@ -32,18 +32,18 @@ test_expect_success setup '
test_expect_success 'need valid notes ref' '
(MSG=1 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF &&
- test_must_fail git notes edit) &&
+ test_must_fail git notes add) &&
(MSG=2 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF &&
test_must_fail git notes show)
'
-test_expect_success 'refusing to edit in refs/heads/' '
+test_expect_success 'refusing to add notes in refs/heads/' '
(MSG=1 GIT_NOTES_REF=refs/heads/bogus &&
export MSG GIT_NOTES_REF &&
- test_must_fail git notes edit)
+ test_must_fail git notes add)
'
-test_expect_success 'refusing to edit in refs/remotes/' '
+test_expect_success 'refusing to edit notes in refs/remotes/' '
(MSG=1 GIT_NOTES_REF=refs/remotes/bogus &&
export MSG GIT_NOTES_REF &&
test_must_fail git notes edit)
@@ -56,8 +56,35 @@ test_expect_success 'handle empty notes gracefully' '
test_expect_success 'create notes' '
git config core.notesRef refs/notes/commits &&
- MSG=b1 git notes edit &&
- test ! -f .git/new-notes &&
+ MSG=b4 git notes add &&
+ test ! -f .git/NOTES_EDITMSG &&
+ test 1 = $(git ls-tree refs/notes/commits | wc -l) &&
+ test b4 = $(git notes show) &&
+ git show HEAD^ &&
+ test_must_fail git notes show HEAD^
+'
+
+test_expect_success 'edit existing notes' '
+ MSG=b3 git notes edit &&
+ test ! -f .git/NOTES_EDITMSG &&
+ test 1 = $(git ls-tree refs/notes/commits | wc -l) &&
+ test b3 = $(git notes show) &&
+ git show HEAD^ &&
+ test_must_fail git notes show HEAD^
+'
+
+test_expect_success 'cannot add note where one exists' '
+ ! MSG=b2 git notes add &&
+ test ! -f .git/NOTES_EDITMSG &&
+ test 1 = $(git ls-tree refs/notes/commits | wc -l) &&
+ test b3 = $(git notes show) &&
+ git show HEAD^ &&
+ test_must_fail git notes show HEAD^
+'
+
+test_expect_success 'can overwrite existing note with "git notes add -f"' '
+ MSG=b1 git notes add -f &&
+ test ! -f .git/NOTES_EDITMSG &&
test 1 = $(git ls-tree refs/notes/commits | wc -l) &&
test b1 = $(git notes show) &&
git show HEAD^ &&
@@ -80,6 +107,7 @@ test_expect_success 'show notes' '
git log -1 > output &&
test_cmp expect output
'
+
test_expect_success 'create multi-line notes (setup)' '
: > a3 &&
git add a3 &&
@@ -87,7 +115,7 @@ test_expect_success 'create multi-line notes (setup)' '
git commit -m 3rd &&
MSG="b3
c3c3c3c3
-d3d3d3" git notes edit
+d3d3d3" git notes add
'
cat > expect-multiline << EOF
@@ -110,19 +138,16 @@ test_expect_success 'show multi-line notes' '
git log -2 > output &&
test_cmp expect-multiline output
'
-test_expect_success 'create -m and -F notes (setup)' '
+test_expect_success 'create -F notes (setup)' '
: > a4 &&
git add a4 &&
test_tick &&
git commit -m 4th &&
echo "xyzzy" > note5 &&
- git notes edit -m spam -F note5 -m "foo
-bar
-baz"
+ git notes add -F note5
'
-whitespace=" "
-cat > expect-m-and-F << EOF
+cat > expect-F << EOF
commit 15023535574ded8b1a89052b32673f84cf9582b8
Author: A U Thor <author@example.com>
Date: Thu Apr 7 15:16:13 2005 -0700
@@ -130,21 +155,493 @@ Date: Thu Apr 7 15:16:13 2005 -0700
4th
Notes:
- spam
-$whitespace
xyzzy
+EOF
+
+printf "\n" >> expect-F
+cat expect-multiline >> expect-F
+
+test_expect_success 'show -F notes' '
+ git log -3 > output &&
+ test_cmp expect-F output
+'
+
+cat >expect << EOF
+commit 15023535574ded8b1a89052b32673f84cf9582b8
+tree e070e3af51011e47b183c33adf9736736a525709
+parent 1584215f1d29c65e99c6c6848626553fdd07fd75
+author A U Thor <author@example.com> 1112912173 -0700
+committer C O Mitter <committer@example.com> 1112912173 -0700
+
+ 4th
+EOF
+test_expect_success 'git log --pretty=raw does not show notes' '
+ git log -1 --pretty=raw >output &&
+ test_cmp expect output
+'
+
+cat >>expect <<EOF
+
+Notes:
+ xyzzy
+EOF
+test_expect_success 'git log --show-notes' '
+ git log -1 --pretty=raw --show-notes >output &&
+ test_cmp expect output
+'
+
+test_expect_success 'git log --no-notes' '
+ git log -1 --no-notes >output &&
+ ! grep xyzzy output
+'
+
+test_expect_success 'git format-patch does not show notes' '
+ git format-patch -1 --stdout >output &&
+ ! grep xyzzy output
+'
+
+test_expect_success 'git format-patch --show-notes does show notes' '
+ git format-patch --show-notes -1 --stdout >output &&
+ grep xyzzy output
+'
+
+for pretty in \
+ "" --pretty --pretty=raw --pretty=short --pretty=medium \
+ --pretty=full --pretty=fuller --pretty=format:%s --oneline
+do
+ case "$pretty" in
+ "") p= not= negate="" ;;
+ ?*) p="$pretty" not=" not" negate="!" ;;
+ esac
+ test_expect_success "git show $pretty does$not show notes" '
+ git show $p >output &&
+ eval "$negate grep xyzzy output"
+ '
+done
+
+test_expect_success 'create -m notes (setup)' '
+ : > a5 &&
+ git add a5 &&
+ test_tick &&
+ git commit -m 5th &&
+ git notes add -m spam -m "foo
+bar
+baz"
+'
+
+whitespace=" "
+cat > expect-m << EOF
+commit bd1753200303d0a0344be813e504253b3d98e74d
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:17:13 2005 -0700
+
+ 5th
+
+Notes:
+ spam
$whitespace
foo
bar
baz
EOF
-printf "\n" >> expect-m-and-F
-cat expect-multiline >> expect-m-and-F
+printf "\n" >> expect-m
+cat expect-F >> expect-m
-test_expect_success 'show -m and -F notes' '
- git log -3 > output &&
- test_cmp expect-m-and-F output
+test_expect_success 'show -m notes' '
+ git log -4 > output &&
+ test_cmp expect-m output
+'
+
+test_expect_success 'remove note with add -f -F /dev/null (setup)' '
+ git notes add -f -F /dev/null
+'
+
+cat > expect-rm-F << EOF
+commit bd1753200303d0a0344be813e504253b3d98e74d
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:17:13 2005 -0700
+
+ 5th
+EOF
+
+printf "\n" >> expect-rm-F
+cat expect-F >> expect-rm-F
+
+test_expect_success 'verify note removal with -F /dev/null' '
+ git log -4 > output &&
+ test_cmp expect-rm-F output &&
+ ! git notes show
+'
+
+test_expect_success 'do not create empty note with -m "" (setup)' '
+ git notes add -m ""
+'
+
+test_expect_success 'verify non-creation of note with -m ""' '
+ git log -4 > output &&
+ test_cmp expect-rm-F output &&
+ ! git notes show
+'
+
+cat > expect-combine_m_and_F << EOF
+foo
+
+xyzzy
+
+bar
+
+zyxxy
+
+baz
+EOF
+
+test_expect_success 'create note with combination of -m and -F' '
+ echo "xyzzy" > note_a &&
+ echo "zyxxy" > note_b &&
+ git notes add -m "foo" -F note_a -m "bar" -F note_b -m "baz" &&
+ git notes show > output &&
+ test_cmp expect-combine_m_and_F output
+'
+
+test_expect_success 'remove note with "git notes remove" (setup)' '
+ git notes remove HEAD^ &&
+ git notes remove
+'
+
+cat > expect-rm-remove << EOF
+commit bd1753200303d0a0344be813e504253b3d98e74d
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:17:13 2005 -0700
+
+ 5th
+
+commit 15023535574ded8b1a89052b32673f84cf9582b8
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:16:13 2005 -0700
+
+ 4th
+EOF
+
+printf "\n" >> expect-rm-remove
+cat expect-multiline >> expect-rm-remove
+
+test_expect_success 'verify note removal with "git notes remove"' '
+ git log -4 > output &&
+ test_cmp expect-rm-remove output &&
+ ! git notes show HEAD^
+'
+
+cat > expect << EOF
+c18dc024e14f08d18d14eea0d747ff692d66d6a3 1584215f1d29c65e99c6c6848626553fdd07fd75
+c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 268048bfb8a1fb38e703baceb8ab235421bf80c5
+EOF
+
+test_expect_success 'list notes with "git notes list"' '
+ git notes list > output &&
+ test_cmp expect output
+'
+
+test_expect_success 'list notes with "git notes"' '
+ git notes > output &&
+ test_cmp expect output
+'
+
+cat > expect << EOF
+c18dc024e14f08d18d14eea0d747ff692d66d6a3
+EOF
+
+test_expect_success 'list specific note with "git notes list <object>"' '
+ git notes list HEAD^^ > output &&
+ test_cmp expect output
+'
+
+cat > expect << EOF
+EOF
+
+test_expect_success 'listing non-existing notes fails' '
+ test_must_fail git notes list HEAD > output &&
+ test_cmp expect output
+'
+
+cat > expect << EOF
+Initial set of notes
+
+More notes appended with git notes append
+EOF
+
+test_expect_success 'append to existing note with "git notes append"' '
+ git notes add -m "Initial set of notes" &&
+ git notes append -m "More notes appended with git notes append" &&
+ git notes show > output &&
+ test_cmp expect output
+'
+
+test_expect_success 'appending empty string does not change existing note' '
+ git notes append -m "" &&
+ git notes show > output &&
+ test_cmp expect output
+'
+
+test_expect_success 'git notes append == add when there is no existing note' '
+ git notes remove HEAD &&
+ test_must_fail git notes list HEAD &&
+ git notes append -m "Initial set of notes
+
+More notes appended with git notes append" &&
+ git notes show > output &&
+ test_cmp expect output
+'
+
+test_expect_success 'appending empty string to non-existing note does not create note' '
+ git notes remove HEAD &&
+ test_must_fail git notes list HEAD &&
+ git notes append -m "" &&
+ test_must_fail git notes list HEAD
+'
+
+test_expect_success 'create other note on a different notes ref (setup)' '
+ : > a6 &&
+ git add a6 &&
+ test_tick &&
+ git commit -m 6th &&
+ GIT_NOTES_REF="refs/notes/other" git notes add -m "other note"
+'
+
+cat > expect-other << EOF
+commit 387a89921c73d7ed72cd94d179c1c7048ca47756
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:18:13 2005 -0700
+
+ 6th
+
+Notes:
+ other note
+EOF
+
+cat > expect-not-other << EOF
+commit 387a89921c73d7ed72cd94d179c1c7048ca47756
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:18:13 2005 -0700
+
+ 6th
+EOF
+
+test_expect_success 'Do not show note on other ref by default' '
+ git log -1 > output &&
+ test_cmp expect-not-other output
+'
+
+test_expect_success 'Do show note when ref is given in GIT_NOTES_REF' '
+ GIT_NOTES_REF="refs/notes/other" git log -1 > output &&
+ test_cmp expect-other output
+'
+
+test_expect_success 'Do show note when ref is given in core.notesRef config' '
+ git config core.notesRef "refs/notes/other" &&
+ git log -1 > output &&
+ test_cmp expect-other output
+'
+
+test_expect_success 'Do not show note when core.notesRef is overridden' '
+ GIT_NOTES_REF="refs/notes/wrong" git log -1 > output &&
+ test_cmp expect-not-other output
+'
+
+test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' '
+ echo "Note on a tree" > expect
+ git notes add -m "Note on a tree" HEAD: &&
+ git notes show HEAD: > actual &&
+ test_cmp expect actual &&
+ echo "Note on a blob" > expect
+ filename=$(git ls-tree --name-only HEAD | head -n1) &&
+ git notes add -m "Note on a blob" HEAD:$filename &&
+ git notes show HEAD:$filename > actual &&
+ test_cmp expect actual &&
+ echo "Note on a tag" > expect
+ git tag -a -m "This is an annotated tag" foobar HEAD^ &&
+ git notes add -m "Note on a tag" foobar &&
+ git notes show foobar > actual &&
+ test_cmp expect actual
+'
+
+cat > expect << EOF
+commit 2ede89468182a62d0bde2583c736089bcf7d7e92
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:19:13 2005 -0700
+
+ 7th
+
+Notes:
+ other note
+EOF
+
+test_expect_success 'create note from other note with "git notes add -C"' '
+ : > a7 &&
+ git add a7 &&
+ test_tick &&
+ git commit -m 7th &&
+ git notes add -C $(git notes list HEAD^) &&
+ git log -1 > actual &&
+ test_cmp expect actual &&
+ test "$(git notes list HEAD)" = "$(git notes list HEAD^)"
+'
+
+test_expect_success 'create note from non-existing note with "git notes add -C" fails' '
+ : > a8 &&
+ git add a8 &&
+ test_tick &&
+ git commit -m 8th &&
+ test_must_fail git notes add -C deadbeef &&
+ test_must_fail git notes list HEAD
+'
+
+cat > expect << EOF
+commit 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:21:13 2005 -0700
+
+ 9th
+
+Notes:
+ yet another note
+EOF
+
+test_expect_success 'create note from other note with "git notes add -c"' '
+ : > a9 &&
+ git add a9 &&
+ test_tick &&
+ git commit -m 9th &&
+ MSG="yet another note" git notes add -c $(git notes list HEAD^^) &&
+ git log -1 > actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'create note from non-existing note with "git notes add -c" fails' '
+ : > a10 &&
+ git add a10 &&
+ test_tick &&
+ git commit -m 10th &&
+ test_must_fail MSG="yet another note" git notes add -c deadbeef &&
+ test_must_fail git notes list HEAD
+'
+
+cat > expect << EOF
+commit 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:21:13 2005 -0700
+
+ 9th
+
+Notes:
+ yet another note
+$whitespace
+ yet another note
+EOF
+
+test_expect_success 'append to note from other note with "git notes append -C"' '
+ git notes append -C $(git notes list HEAD^) HEAD^ &&
+ git log -1 HEAD^ > actual &&
+ test_cmp expect actual
+'
+
+cat > expect << EOF
+commit ffed603236bfa3891c49644257a83598afe8ae5a
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:22:13 2005 -0700
+
+ 10th
+
+Notes:
+ other note
+EOF
+
+test_expect_success 'create note from other note with "git notes append -c"' '
+ MSG="other note" git notes append -c $(git notes list HEAD^) &&
+ git log -1 > actual &&
+ test_cmp expect actual
+'
+
+cat > expect << EOF
+commit ffed603236bfa3891c49644257a83598afe8ae5a
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:22:13 2005 -0700
+
+ 10th
+
+Notes:
+ other note
+$whitespace
+ yet another note
+EOF
+
+test_expect_success 'append to note from other note with "git notes append -c"' '
+ MSG="yet another note" git notes append -c $(git notes list HEAD) &&
+ git log -1 > actual &&
+ test_cmp expect actual
+'
+
+cat > expect << EOF
+commit 6352c5e33dbcab725fe0579be16aa2ba8eb369be
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:23:13 2005 -0700
+
+ 11th
+
+Notes:
+ other note
+$whitespace
+ yet another note
+EOF
+
+test_expect_success 'copy note with "git notes copy"' '
+ : > a11 &&
+ git add a11 &&
+ test_tick &&
+ git commit -m 11th &&
+ git notes copy HEAD^ HEAD &&
+ git log -1 > actual &&
+ test_cmp expect actual &&
+ test "$(git notes list HEAD)" = "$(git notes list HEAD^)"
+'
+
+test_expect_success 'prevent overwrite with "git notes copy"' '
+ test_must_fail git notes copy HEAD~2 HEAD &&
+ git log -1 > actual &&
+ test_cmp expect actual &&
+ test "$(git notes list HEAD)" = "$(git notes list HEAD^)"
+'
+
+cat > expect << EOF
+commit 6352c5e33dbcab725fe0579be16aa2ba8eb369be
+Author: A U Thor <author@example.com>
+Date: Thu Apr 7 15:23:13 2005 -0700
+
+ 11th
+
+Notes:
+ yet another note
+$whitespace
+ yet another note
+EOF
+
+test_expect_success 'allow overwrite with "git notes copy -f"' '
+ git notes copy -f HEAD~2 HEAD &&
+ git log -1 > actual &&
+ test_cmp expect actual &&
+ test "$(git notes list HEAD)" = "$(git notes list HEAD~2)"
+'
+
+test_expect_success 'cannot copy note from object without notes' '
+ : > a12 &&
+ git add a12 &&
+ test_tick &&
+ git commit -m 12th &&
+ : > a13 &&
+ git add a13 &&
+ test_tick &&
+ git commit -m 13th &&
+ test_must_fail git notes copy HEAD^ HEAD
'
test_done
diff --git a/t/t3303-notes-subtrees.sh b/t/t3303-notes-subtrees.sh
index edc4bc8..75ec187 100755
--- a/t/t3303-notes-subtrees.sh
+++ b/t/t3303-notes-subtrees.sh
@@ -95,12 +95,12 @@ INPUT_END
test_expect_success 'test notes in 2/38-fanout' 'test_sha1_based "s|^..|&/|"'
test_expect_success 'verify notes in 2/38-fanout' 'verify_notes'
-test_expect_success 'test notes in 4/36-fanout' 'test_sha1_based "s|^....|&/|"'
-test_expect_success 'verify notes in 4/36-fanout' 'verify_notes'
-
test_expect_success 'test notes in 2/2/36-fanout' 'test_sha1_based "s|^\(..\)\(..\)|\1/\2/|"'
test_expect_success 'verify notes in 2/2/36-fanout' 'verify_notes'
+test_expect_success 'test notes in 2/2/2/34-fanout' 'test_sha1_based "s|^\(..\)\(..\)\(..\)|\1/\2/\3/|"'
+test_expect_success 'verify notes in 2/2/2/34-fanout' 'verify_notes'
+
test_same_notes () {
(
start_note_commit &&
@@ -128,14 +128,17 @@ INPUT_END
git fast-import --quiet
}
-test_expect_success 'test same notes in 4/36-fanout and 2/38-fanout' 'test_same_notes "s|^..|&/|" "s|^....|&/|"'
-test_expect_success 'verify same notes in 4/36-fanout and 2/38-fanout' 'verify_notes'
+test_expect_success 'test same notes in no fanout and 2/38-fanout' 'test_same_notes "s|^..|&/|" ""'
+test_expect_success 'verify same notes in no fanout and 2/38-fanout' 'verify_notes'
+
+test_expect_success 'test same notes in no fanout and 2/2/36-fanout' 'test_same_notes "s|^\(..\)\(..\)|\1/\2/|" ""'
+test_expect_success 'verify same notes in no fanout and 2/2/36-fanout' 'verify_notes'
test_expect_success 'test same notes in 2/38-fanout and 2/2/36-fanout' 'test_same_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^..|&/|"'
test_expect_success 'verify same notes in 2/38-fanout and 2/2/36-fanout' 'verify_notes'
-test_expect_success 'test same notes in 4/36-fanout and 2/2/36-fanout' 'test_same_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^....|&/|"'
-test_expect_success 'verify same notes in 4/36-fanout and 2/2/36-fanout' 'verify_notes'
+test_expect_success 'test same notes in 2/2/2/34-fanout and 2/2/36-fanout' 'test_same_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^\(..\)\(..\)\(..\)|\1/\2/\3/|"'
+test_expect_success 'verify same notes in 2/2/2/34-fanout and 2/2/36-fanout' 'verify_notes'
test_concatenated_notes () {
(
@@ -176,13 +179,16 @@ verify_concatenated_notes () {
test_cmp expect output
}
-test_expect_success 'test notes in 4/36-fanout concatenated with 2/38-fanout' 'test_concatenated_notes "s|^..|&/|" "s|^....|&/|"'
-test_expect_success 'verify notes in 4/36-fanout concatenated with 2/38-fanout' 'verify_concatenated_notes'
+test_expect_success 'test notes in no fanout concatenated with 2/38-fanout' 'test_concatenated_notes "s|^..|&/|" ""'
+test_expect_success 'verify notes in no fanout concatenated with 2/38-fanout' 'verify_concatenated_notes'
+
+test_expect_success 'test notes in no fanout concatenated with 2/2/36-fanout' 'test_concatenated_notes "s|^\(..\)\(..\)|\1/\2/|" ""'
+test_expect_success 'verify notes in no fanout concatenated with 2/2/36-fanout' 'verify_concatenated_notes'
test_expect_success 'test notes in 2/38-fanout concatenated with 2/2/36-fanout' 'test_concatenated_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^..|&/|"'
test_expect_success 'verify notes in 2/38-fanout concatenated with 2/2/36-fanout' 'verify_concatenated_notes'
-test_expect_success 'test notes in 4/36-fanout concatenated with 2/2/36-fanout' 'test_concatenated_notes "s|^\(..\)\(..\)|\1/\2/|" "s|^....|&/|"'
-test_expect_success 'verify notes in 4/36-fanout concatenated with 2/2/36-fanout' 'verify_concatenated_notes'
+test_expect_success 'test notes in 2/2/36-fanout concatenated with 2/2/2/34-fanout' 'test_concatenated_notes "s|^\(..\)\(..\)\(..\)|\1/\2/\3/|" "s|^\(..\)\(..\)|\1/\2/|"'
+test_expect_success 'verify notes in 2/2/36-fanout concatenated with 2/2/2/34-fanout' 'verify_concatenated_notes'
test_done
diff --git a/t/t3304-notes-mixed.sh b/t/t3304-notes-mixed.sh
index 256687f..1709e8c 100755
--- a/t/t3304-notes-mixed.sh
+++ b/t/t3304-notes-mixed.sh
@@ -131,6 +131,17 @@ data <<EOF
another non-note with SHA1-like name
EOF
+M 644 inline de/adbeefdeadbeefdeadbeefdeadbeefdeadbeef
+data <<EOF
+This is actually a valid note, albeit to a non-existing object.
+It is needed in order to trigger the "mishandling" of the dead/beef non-note.
+EOF
+
+M 644 inline dead/beef
+data <<EOF
+yet another non-note with SHA1-like name
+EOF
+
INPUT_END
git fast-import --quiet <input &&
git config core.notesRef refs/notes/commits
@@ -158,6 +169,9 @@ EXPECT_END
cat >expect_nn3 <<EXPECT_END
another non-note with SHA1-like name
EXPECT_END
+cat >expect_nn4 <<EXPECT_END
+yet another non-note with SHA1-like name
+EXPECT_END
test_expect_success "verify contents of non-notes" '
@@ -166,7 +180,27 @@ test_expect_success "verify contents of non-notes" '
git cat-file -p refs/notes/commits:deadbeef > actual_nn2 &&
test_cmp expect_nn2 actual_nn2 &&
git cat-file -p refs/notes/commits:de/adbeef > actual_nn3 &&
- test_cmp expect_nn3 actual_nn3
+ test_cmp expect_nn3 actual_nn3 &&
+ git cat-file -p refs/notes/commits:dead/beef > actual_nn4 &&
+ test_cmp expect_nn4 actual_nn4
+'
+