summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Documentation/Makefile10
-rw-r--r--Documentation/RelNotes/1.7.10.1.txt78
-rw-r--r--Documentation/RelNotes/1.7.11.txt155
-rw-r--r--Documentation/RelNotes/1.7.7.7.txt13
-rw-r--r--Documentation/RelNotes/1.7.8.6.txt22
-rw-r--r--Documentation/RelNotes/1.7.9.7.txt13
-rw-r--r--Documentation/config.txt5
-rw-r--r--Documentation/git-cherry-pick.txt19
-rw-r--r--Documentation/git-fast-import.txt42
-rw-r--r--Documentation/git-fetch-pack.txt10
-rw-r--r--Documentation/git-p4.txt73
-rw-r--r--Documentation/git-push.txt14
-rw-r--r--Documentation/git-rebase.txt4
-rw-r--r--Documentation/git-update-index.txt6
-rw-r--r--Documentation/git-var.txt12
-rw-r--r--Documentation/git.txt12
-rw-r--r--Documentation/gitweb.conf.txt7
-rw-r--r--Documentation/technical/api-argv-array.txt5
-rw-r--r--Documentation/technical/api-revision-walking.txt5
-rw-r--r--Documentation/technical/index-format.txt13
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--INSTALL3
-rw-r--r--Makefile9
-rw-r--r--argv-array.c14
-rw-r--r--argv-array.h3
-rw-r--r--builtin/apply.c174
-rw-r--r--builtin/blame.c1
-rw-r--r--builtin/fetch-pack.c42
-rw-r--r--builtin/fetch.c23
-rw-r--r--builtin/fmt-merge-msg.c128
-rw-r--r--builtin/gc.c89
-rw-r--r--builtin/merge.c142
-rw-r--r--builtin/pack-objects.c25
-rw-r--r--builtin/push.c10
-rw-r--r--builtin/remote.c4
-rw-r--r--builtin/rev-parse.c2
-rw-r--r--builtin/revert.c14
-rw-r--r--builtin/update-index.c14
-rw-r--r--bundle.c2
-rw-r--r--cache.h52
-rw-r--r--command-list.txt1
-rw-r--r--commit.c56
-rw-r--r--commit.h2
-rw-r--r--compat/mingw.h7
-rw-r--r--config.c30
-rwxr-xr-xcontrib/completion/git-completion.bash22
-rw-r--r--contrib/fast-import/git-p4.README12
-rw-r--r--contrib/fast-import/git-p4.bat1
-rw-r--r--diff-no-index.c38
-rw-r--r--diff.c6
-rw-r--r--fast-import.c110
-rw-r--r--fetch-pack.h1
-rwxr-xr-xgit-p4.py (renamed from contrib/fast-import/git-p4)303
-rw-r--r--git-rebase--am.sh19
-rw-r--r--git-rebase--interactive.sh37
-rwxr-xr-xgit-rebase.sh5
-rw-r--r--git-remote-testgit.py7
-rwxr-xr-xgit-repack.sh10
-rw-r--r--git-sh-setup.sh4
-rwxr-xr-xgit-stash.sh4
-rwxr-xr-xgit-submodule.sh161
-rwxr-xr-xgit-svn.perl40
-rwxr-xr-xgitweb/gitweb.perl364
-rw-r--r--gitweb/static/gitweb.css8
-rw-r--r--http.c21
-rw-r--r--log-tree.c5
-rw-r--r--mergesort.c73
-rw-r--r--mergesort.h17
-rw-r--r--object.c11
-rw-r--r--object.h2
-rw-r--r--po/TEAMS8
-rw-r--r--po/da.po3503
-rw-r--r--po/de.po3825
-rw-r--r--po/git.pot720
-rw-r--r--po/pt_PT.po242
-rw-r--r--po/zh_CN.po783
-rw-r--r--read-cache.c265
-rw-r--r--refs.c1015
-rw-r--r--refs.h7
-rw-r--r--remote-curl.c18
-rw-r--r--revision.c33
-rw-r--r--revision.h2
-rw-r--r--sequencer.c124
-rw-r--r--sequencer.h2
-rw-r--r--setup.c22
-rw-r--r--sha1_name.c20
-rw-r--r--submodule.c73
-rw-r--r--submodule.h4
-rw-r--r--t/lib-git-daemon.sh22
-rw-r--r--t/lib-git-p4.sh9
-rwxr-xr-xt/t0062-revision-walking.sh33
-rwxr-xr-xt/t1300-repo-config.sh8
-rwxr-xr-xt/t1305-config-include.sh8
-rwxr-xr-xt/t1410-reflog.sh26
-rwxr-xr-xt/t1501-worktree.sh2
-rwxr-xr-xt/t1507-rev-parse-upstream.sh81
-rwxr-xr-xt/t2004-checkout-cache-temp.sh20
-rwxr-xr-xt/t2020-checkout-detach.sh2
-rwxr-xr-xt/t2030-unresolve-info.sh2
-rwxr-xr-xt/t3404-rebase-interactive.sh30
-rwxr-xr-xt/t3415-rebase-autosquash.sh16
-rwxr-xr-xt/t3505-cherry-pick-empty.sh25
-rwxr-xr-xt/t3900-i18n-commit.sh2
-rwxr-xr-xt/t4035-diff-quiet.sh26
-rwxr-xr-xt/t4150-am.sh4
-rwxr-xr-xt/t4202-log.sh290
-rwxr-xr-xt/t5100-mailinfo.sh2
-rwxr-xr-xt/t5500-fetch-pack.sh66
-rwxr-xr-xt/t5510-fetch.sh30
-rwxr-xr-xt/t5531-deep-submodule-push.sh94
-rwxr-xr-xt/t5550-http-fetch.sh15
-rwxr-xr-xt/t5551-http-fetch.sh31
-rwxr-xr-xt/t5700-clone-reference.sh4
-rwxr-xr-xt/t5710-info-alternate.sh2
-rwxr-xr-xt/t5800-remote-helpers.sh13
-rwxr-xr-xt/t6006-rev-list-format.sh13
-rwxr-xr-xt/t6028-merge-up-to-date.sh17
-rwxr-xr-xt/t6030-bisect-porcelain.sh2
-rwxr-xr-xt/t6032-merge-large-rename.sh2
-rwxr-xr-xt/t6040-tracking-info.sh10
-rwxr-xr-xt/t6042-merge-rename-corner-cases.sh2
-rwxr-xr-xt/t7201-co.sh4
-rwxr-xr-xt/t7400-submodule-basic.sh2
-rwxr-xr-xt/t7408-submodule-reference.sh4
-rwxr-xr-xt/t7502-commit.sh2
-rwxr-xr-xt/t7602-merge-octopus-many.sh8
-rwxr-xr-xt/t7603-merge-reduce-heads.sh50
-rwxr-xr-xt/t7701-repack-unpack-unreachable.sh14
-rwxr-xr-xt/t9300-fast-import.sh375
-rwxr-xr-xt/t9350-fast-export.sh4
-rwxr-xr-xt/t9400-git-cvsserver-server.sh8
-rwxr-xr-xt/t9800-git-p4-basic.sh88
-rwxr-xr-xt/t9801-git-p4-branch.sh32
-rwxr-xr-xt/t9802-git-p4-filetype.sh10
-rwxr-xr-xt/t9803-git-p4-shell-metachars.sh12
-rwxr-xr-xt/t9804-git-p4-label.sh6
-rwxr-xr-xt/t9805-git-p4-skip-submit-edit.sh22
-rwxr-xr-xt/t9806-git-p4-options.sh28
-rwxr-xr-xt/t9807-git-p4-submit.sh22
-rwxr-xr-xt/t9808-git-p4-chdir.sh6
-rwxr-xr-xt/t9809-git-p4-client-view.sh88
-rwxr-xr-xt/t9810-git-p4-rcs.sh48
-rwxr-xr-xt/t9811-git-p4-label-import.sh202
-rwxr-xr-xt/t9902-completion.sh243
-rw-r--r--test-mergesort.c52
-rw-r--r--test-revision-walking.c66
-rw-r--r--transport.c41
-rw-r--r--transport.h1
-rw-r--r--unpack-trees.c1
-rw-r--r--varint.c29
-rw-r--r--varint.h9
152 files changed, 13423 insertions, 2280 deletions
diff --git a/.gitignore b/.gitignore
index 87fcc5f6ff..1dbeb668db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -92,6 +92,7 @@
/git-name-rev
/git-mv
/git-notes
+/git-p4
/git-pack-redundant
/git-pack-objects
/git-pack-refs
@@ -180,9 +181,11 @@
/test-index-version
/test-line-buffer
/test-match-trees
+/test-mergesort
/test-mktemp
/test-parse-options
/test-path-utils
+/test-revision-walking
/test-run-command
/test-sha1
/test-sigchain
diff --git a/Documentation/Makefile b/Documentation/Makefile
index d40e211f22..9fee0b9261 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -124,6 +124,16 @@ SHELL_PATH ?= $(SHELL)
# Shell quote;
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
+ifdef DEFAULT_PAGER
+DEFAULT_PAGER_SQ = $(subst ','\'',$(DEFAULT_PAGER))
+ASCIIDOC_EXTRA += -a 'git-default-pager=$(DEFAULT_PAGER_SQ)'
+endif
+
+ifdef DEFAULT_EDITOR
+DEFAULT_EDITOR_SQ = $(subst ','\'',$(DEFAULT_EDITOR))
+ASCIIDOC_EXTRA += -a 'git-default-editor=$(DEFAULT_EDITOR_SQ)'
+endif
+
#
# Please note that there is a minor bug in asciidoc.
# The version after 6.0.3 _will_ include the patch found here:
diff --git a/Documentation/RelNotes/1.7.10.1.txt b/Documentation/RelNotes/1.7.10.1.txt
new file mode 100644
index 0000000000..806a965a1b
--- /dev/null
+++ b/Documentation/RelNotes/1.7.10.1.txt
@@ -0,0 +1,78 @@
+Git v1.7.10.1 Release Notes
+===========================
+
+Additions since v1.7.10
+-----------------------
+
+Localization message files for Danish and German have been added.
+
+
+Fixes since v1.7.10
+-------------------
+
+ * "git add -p" is not designed to deal with unmerged paths but did
+ not exclude them and tried to apply funny patches only to fail.
+
+ * "git blame" started missing quite a few changes from the origin
+ since we stopped using the diff minimalization by default in v1.7.2
+ era.
+
+ * When PATH contains an unreadable directory, alias expansion code
+ did not kick in, and failed with an error that said "git-subcmd"
+ was not found.
+
+ * "git clean -d -f" (not "-d -f -f") is supposed to protect nested
+ working trees of independent git repositories that exist in the
+ current project working tree from getting removed, but the
+ protection applied only to such working trees that are at the
+ top-level of the current project by mistake.
+
+ * "git commit --author=$name" did not tell the name that was being
+ recorded in the resulting commit to hooks, even though it does do
+ so when the end user overrode the authorship via the
+ "GIT_AUTHOR_NAME" environment variable.
+
+ * When "git commit --template F" errors out because the user did not
+ touch the message, it claimed that it aborts due to "empty
+ message", which was utterly wrong.
+
+ * The regexp configured with diff.wordregex was incorrectly reused
+ across files.
+
+ * An age-old corner case bug in combine diff (only triggered with -U0
+ and the hunk at the beginning of the file needs to be shown) has
+ been fixed.
+
+ * Rename detection logic used to match two empty files as renames
+ during merge-recursive, leading to unnatural mismerges.
+
+ * The parser in "fast-import" did not diagnose ":9" style references
+ that is not followed by required SP/LF as an error.
+
+ * When "git fetch" encounters repositories with too many references,
+ the command line of "fetch-pack" that is run by a helper
+ e.g. remote-curl, may fail to hold all of them. Now such an
+ internal invocation can feed the references through the standard
+ input of "fetch-pack".
+
+ * "git fetch" that recurses into submodules on demand did not check
+ if it needs to go into submodules when non branches (most notably,
+ tags) are fetched.
+
+ * "log -p --graph" used with "--stat" had a few formatting error.
+
+ * Running "notes merge --commit" failed to perform correctly when run
+ from any directory inside $GIT_DIR/. When "notes merge" stops with
+ conflicts, $GIT_DIR/NOTES_MERGE_WORKTREE is the place a user edits
+ to resolve it.
+
+ * The 'push to upstream' implementation was broken in some corner
+ cases. "git push $there" without refspec, when the current branch
+ is set to push to a remote different from $there, used to push to
+ $there using the upstream information to a remote unreleated to
+ $there.
+
+ * Giving "--continue" to a conflicted "rebase -i" session skipped a
+ commit that only results in changes to submodules.
+
+Also contains minor fixes and documentation updates.
diff --git a/Documentation/RelNotes/1.7.11.txt b/Documentation/RelNotes/1.7.11.txt
index 7694203cad..429f304972 100644
--- a/Documentation/RelNotes/1.7.11.txt
+++ b/Documentation/RelNotes/1.7.11.txt
@@ -8,6 +8,9 @@ UI, Workflows & Features
* A third-party tool "git subtree" is distributed in contrib/
+ * Error messages given when @{u} is used for a branch without its
+ upstream configured have been clatified.
+
* Even with "-q"uiet option, "checkout" used to report setting up
tracking. Also "branch" learned the "-q"uiet option to squelch
informational message.
@@ -16,6 +19,9 @@ UI, Workflows & Features
variables with REMOTE_USER and REMOTE_ADDR, but these variables are
now preserved when set.
+ * "include.path" mechanism of the configuration files learned to
+ understand "~/path" and "~user/path".
+
* "git am" learned the "--include" option, which is an opposite of
existing the "--exclude" option.
@@ -30,17 +36,43 @@ UI, Workflows & Features
* The cases "git push" fails due to non-ff can be broken into three
categories; each case is given a separate advise message.
+ * "git push --recurse-submodules" learned to optionally look into the
+ histories of submodules bound to the superproject and push them
+ out.
+
* A 'snapshot' request to "gitweb" honors If-Modified-Since: header,
based on the commit date.
+ * "gitweb" learned to highlight the patch it outputs even more.
+
Foreign Interface
+ * "git svn" used to die with unwanted SIGPIPE when talking with HTTP
+ server that uses keep-alive.
+
+ * "git svn" learned to use platform specific authentication
+ providers, e.g. gnome-keyring, kwallet, etc.
+
+ * "git p4" has been moved out of contrib/ area.
Performance
+ * "git apply" had some memory leaks plugged.
+
+ * "git repack" used to write out unreachable objects as loose objects
+ when repacking, even if such loose objects will immediately pruned
+ due to its age.
+
+ * Setting up a revision traversal with many starting points was
+ inefficient as these were placed in a date-order priority queue
+ one-by-one. Now they are collected in the queue unordered first,
+ and sorted immediately before getting used.
Internal Implementation (please report possible regressions)
+ * "git rev-parse --show-prefix" used to emit nothing when run at the
+ top-level of the working tree, but now it gives a blank line.
+
* Minor memory leak during unpack_trees (hence "merge" and "checkout"
to check out another branch) has been plugged.
@@ -51,6 +83,9 @@ Internal Implementation (please report possible regressions)
systems, run-command API now uses SHELL_PATH, not /bin/sh, when
spawning an external command (not applicable to Windows port).
+ * The API to iterate over refs/ hierarchy has been tweaked to allow
+ walking only a subset of it more efficiently.
+
Also contains minor documentation updates and code clean-ups.
@@ -61,55 +96,71 @@ Unless otherwise noted, all the fixes since v1.7.10 in the maintenance
releases are contained in this release (see release notes to them for
details).
- * When PATH contains an unreadable directory, alias expansion code
- did not kick in, and failed with an error that said "git-subcmd"
- was not found.
- (merge 38f865c jk/run-command-eacces later to maint).
-
- * The 'push to upstream' implementation was broken in some corner
- cases. "git push $there" without refspec, when the current branch
- is set to push to a remote different from $there, used to push to
- $there using the upstream information to a remote unreleated to
- $there.
- (merge 135dade jc/push-upstream-sanity later to maint).
-
- * "git clean -d -f" (not "-d -f -f") is supposed to protect nested
- working trees of independent git repositories that exist in the
- current project working tree from getting removed, but the
- protection applied only to such working trees that are at the
- top-level of the current project by mistake.
- (merge ae2f203 jc/maint-clean-nested-worktree-in-subdir later to maint).
-
- * Rename detection logic used to match two empty files as renames
- during merge-recursive, leading unnatural mismerges.
- (merge 4f7cb99 jk/diff-no-rename-empty later to maint).
-
- * An age-old corner case bug in combine diff (only triggered with -U0
- and the hunk at the beginning of the file needs to be shown) has
- been fixed.
- (merge e5e9b56 rs/combine-diff-zero-context-at-the-beginning later to maint).
-
- * When "git commit --template F" errors out because the user did not
- touch the message, it claimed that it aborts due to "empty
- message", which was utterly wrong.
- (merge 1f08c2c jc/commit-unedited-template later to maint).
-
- * "git add -p" is not designed to deal with unmerged paths but did
- not exclude them and tried to apply funny patches only to fail.
- (merge 4066bd6 jk/add-p-skip-conflicts later to maint).
-
- * "git commit --author=$name" did not tell the name that was being
- recorded in the resulting commit to hooks, even though it does do
- so when the end user overrode the authorship via the
- "GIT_AUTHOR_NAME" environment variable.
- (merge 7dfe8ad jc/commit-hook-authorship later to maint).
-
- * The regexp configured with diff.wordregex was incorrectly reused
- across files.
- (merge 6440d34 tr/maint-word-diff-regex-sticky later to maint).
-
- * Running "notes merge --commit" failed to perform correctly when run
- from any directory inside $GIT_DIR/. When "notes merge" stops with
- conflicts, $GIT_DIR/NOTES_MERGE_WORKTREE is the place a user edits
- to resolve it.
- (merge dabba59 jh/notes-merge-in-git-dir-worktree later to maint).
+ * The test scaffolding for git-daemon was flaky.
+ (merge 46e3581 js/daemon-test-race-fix later to maint).
+
+ * The test scaffolding for fast-import was flaky.
+ (merge 7fb8e16 pw/t5800-import-race-fix later to maint).
+
+ * Octopus merge strategy did not reduce heads that are recorded in the
+ final commit correctly.
+ (merge 5802f81 jc/merge-reduce-parents-early later to maint).
+
+ * In the older days, the header "Conflicts:" in "cherry-pick" and
+ "merge" was separated by a blank line from the list of paths that
+ follow for readability, but when "merge" was rewritten in C, we lost
+ it by mistake. Remove the newline from "cherry-pick" to make them
+ match again.
+ (merge 5112068 rt/cherry-revert-conflict-summary later to maint).
+
+ * The filesystem boundary was not correctly reported when .git
+ directory discovery stopped at a mount point.
+ (merge 2565b43 cb/maint-report-mount-point-correctly-in-setup later to maint).
+
+ * The command line parser choked "git cherry-pick $name" when $name
+ can be both revision name and a pathname, even though $name can
+ never be a path in the context of the command.
+ (merge 6d5b93f cb/cherry-pick-rev-path-confusion later to maint).
+
+ * HTTP transport that requires authentication did not work correctly
+ when multiple connections are used simultaneously.
+ (merge 6f4c347 cb/http-multi-curl-auth later to maint).
+
+ * The i18n of error message "git stash save" was not properly done.
+ (merge ed3c400 rl/maint-stash-i18n-save-error later to maint).
+
+ * The report from "git fetch" said "new branch" even for a non branch
+ ref.
+ (merge 0997ada mb/fetch-call-a-non-branch-a-ref later to maint).
+
+ * The "diff --no-index" codepath used limited-length buffers, risking
+ pathnames getting truncated. Update it to use the strbuf API.
+ (merge 875b91b jm/maint-strncpy-diff-no-index later to maint).
+
+ * The parser in "fast-import" did not diagnose ":9" style references
+ that is not followed by required SP/LF as an error.
+ (merge 06454cb pw/fast-import-dataref-parsing later to maint).
+
+ * When "git fetch" encounters repositories with too many references,
+ the command line of "fetch-pack" that is run by a helper
+ e.g. remote-curl, may fail to hold all of them. Now such an
+ internal invocation can feed the references through the standard
+ input of "fetch-pack".
+ (merge 7103d25 it/fetch-pack-many-refs later to maint).
+
+ * "git fetch" that recurses into submodules on demand did not check
+ if it needs to go into submodules when non branches (most notably,
+ tags) are fetched.
+ (merge a6801ad jl/maint-submodule-recurse-fetch later to maint).
+
+ * "git blame" started missing quite a few changes from the origin
+ since we stopped using the diff minimalization by default in v1.7.2
+ era.
+ (merge 059a500 jc/maint-blame-minimal later to maint).
+
+ * "log -p --graph" used with "--stat" had a few formatting error.
+ (merge e2c5966 lp/maint-diff-three-dash-with-graph later to maint).
+
+ * Giving "--continue" to a conflicted "rebase -i" session skipped a
+ commit that only results in changes to submodules.
+ (merge a6754cd jk/rebase-i-submodule-conflict-only later to maint).
diff --git a/Documentation/RelNotes/1.7.7.7.txt b/Documentation/RelNotes/1.7.7.7.txt
new file mode 100644
index 0000000000..e79118d063
--- /dev/null
+++ b/Documentation/RelNotes/1.7.7.7.txt
@@ -0,0 +1,13 @@
+Git v1.7.7.7 Release Notes
+==========================
+
+Fixes since v1.7.7.6
+--------------------
+
+ * An error message from 'git bundle' had an unmatched single quote pair in it.
+
+ * 'git diff --histogram' option was not described.
+
+ * 'git imap-send' carried an unused dead code.
+
+Also contains minor fixes and documentation updates.
diff --git a/Documentation/RelNotes/1.7.8.6.txt b/Documentation/RelNotes/1.7.8.6.txt
new file mode 100644
index 0000000000..d9bf2b741a
--- /dev/null
+++ b/Documentation/RelNotes/1.7.8.6.txt
@@ -0,0 +1,22 @@
+Git v1.7.8.6 Release Notes
+==========================
+
+Fixes since v1.7.8.5
+--------------------
+
+ * An error message from 'git bundle' had an unmatched single quote pair in it.
+
+ * 'git diff --histogram' option was not described.
+
+ * Documentation for 'git rev-list' had minor formatting errors.
+
+ * 'git imap-send' carried an unused dead code.
+
+ * The way 'git fetch' implemented its connectivity check over
+ received objects was overly pessimistic, and wasted a lot of
+ cycles.
+
+ * Various minor backports of fixes from the 'master' and the 'maint'
+ branch.
+
+Also contains minor fixes and documentation updates.
diff --git a/Documentation/RelNotes/1.7.9.7.txt b/Documentation/RelNotes/1.7.9.7.txt
new file mode 100644
index 0000000000..59667d0f2a
--- /dev/null
+++ b/Documentation/RelNotes/1.7.9.7.txt
@@ -0,0 +1,13 @@
+Git v1.7.9.7 Release Notes
+==========================
+
+Fixes since v1.7.9.6
+--------------------
+
+ * An error message from 'git bundle' had an unmatched single quote pair in it.
+
+ * The way 'git fetch' implemented its connectivity check over
+ received objects was overly pessimistic, and wasted a lot of
+ cycles.
+
+Also contains minor fixes and documentation updates.
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 6a4c130602..40a6e8fb89 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -95,7 +95,9 @@ included file is expanded immediately, as if its contents had been
found at the location of the include directive. If the value of the
`include.path` variable is a relative path, the path is considered to be
relative to the configuration file in which the include directive was
-found. See below for examples.
+found. The value of `include.path` is subject to tilde expansion: `{tilde}/`
+is expanded to the value of `$HOME`, and `{tilde}user/` to the specified
+user's home directory. See below for examples.
Example
~~~~~~~
@@ -122,6 +124,7 @@ Example
[include]
path = /path/to/foo.inc ; include by absolute path
path = foo ; expand "foo" relative to the current file
+ path = ~/foo ; expand "foo" in your $HOME directory
Variables
~~~~~~~~~
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index fed5097e00..3d25a20b67 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -103,6 +103,25 @@ effect to your index in a row.
cherry-pick'ed commit, then a fast forward to this commit will
be performed.
+--allow-empty::
+ By default, cherry-picking an empty commit will fail,
+ indicating that an explicit invocation of `git commit
+ --allow-empty` is required. This option overrides that
+ behavior, allowing empty commits to be preserved automatically
+ in a cherry-pick. Note that when "--ff" is in effect, empty
+ commits that meet the "fast-forward" requirement will be kept
+ even without this option. Note also, that use of this option only
+ keeps commits that were initially empty (i.e. the commit recorded the
+ same tree as its parent). Commits which are made empty due to a
+ previous commit are dropped. To force the inclusion of those commits
+ use `--keep-redundant-commits`.
+
+--keep-redundant-commits::
+ If a commit being cherry picked duplicates a commit already in the
+ current history, it will become empty. By default these
+ redundant commits are ignored. This option overrides that behavior and
+ creates an empty commit object. Implies `--allow-empty`.
+
--strategy=<strategy>::
Use the given merge strategy. Should only be used once.
See the MERGE STRATEGIES section in linkgit:git-merge[1]
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index ec6ef31197..b52dca5133 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -98,9 +98,10 @@ OPTIONS
options.
--cat-blob-fd=<fd>::
- Specify the file descriptor that will be written to
- when the `cat-blob` command is encountered in the stream.
- The default behaviour is to write to `stdout`.
+ Write responses to `cat-blob` and `ls` queries to the
+ file descriptor <fd> instead of `stdout`. Allows `progress`
+ output intended for the end-user to be separated from other
+ output.
--done::
Require a `done` command at the end of the stream.
@@ -942,6 +943,9 @@ This command can be used anywhere in the stream that comments are
accepted. In particular, the `cat-blob` command can be used in the
middle of a commit but not in the middle of a `data` command.
+See ``Responses To Commands'' below for details about how to read
+this output safely.
+
`ls`
~~~~
Prints information about the object at a path to a file descriptor
@@ -991,6 +995,9 @@ instead report
missing SP <path> LF
====
+See ``Responses To Commands'' below for details about how to read
+this output safely.
+
`feature`
~~~~~~~~~
Require that fast-import supports the specified feature, or abort if
@@ -1079,6 +1086,35 @@ If the `--done` command line option or `feature done` command is
in use, the `done` command is mandatory and marks the end of the
stream.
+Responses To Commands
+---------------------
+New objects written by fast-import are not available immediately.
+Most fast-import commands have no visible effect until the next
+checkpoint (or completion). The frontend can send commands to
+fill fast-import's input pipe without worrying about how quickly
+they will take effect, which improves performance by simplifying
+scheduling.
+
+For some frontends, though, it is useful to be able to read back
+data from the current repository as it is being updated (for
+example when the source material describes objects in terms of
+patches to be applied to previously imported objects). This can
+be accomplished by connecting the frontend and fast-import via
+bidirectional pipes:
+
+====
+ mkfifo fast-import-output
+ frontend <fast-import-output |
+ git fast-import >fast-import-output
+====
+
+A frontend set up this way can use `progress`, `ls`, and `cat-blob`
+commands to read information from the import in progress.
+
+To avoid deadlock, such frontends must completely consume any
+pending output from `progress`, `ls`, and `cat-blob` before
+performing writes to fast-import that might block.
+
Crash Reports
-------------
If fast-import is supplied invalid input it will terminate with a
diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt
index ed1bdaacd1..474fa307a0 100644
--- a/Documentation/git-fetch-pack.txt
+++ b/Documentation/git-fetch-pack.txt
@@ -32,6 +32,16 @@ OPTIONS
--all::
Fetch all remote refs.
+--stdin::
+ Take the list of refs from stdin, one per line. If there
+ are refs specified on the command line in addition to this
+ option, then the refs from stdin are processed after those
+ on the command line.
++
+If '--stateless-rpc' is specified together with this option then
+the list of refs must be in packet format (pkt-line). Each ref must
+be in a separate packet, and the list must end with a flush packet.
+
-q::
--quiet::
Pass '-q' flag to 'git unpack-objects'; this makes the
diff --git a/Documentation/git-p4.txt b/Documentation/git-p4.txt
index b7c7929716..51955a5f7c 100644
--- a/Documentation/git-p4.txt
+++ b/Documentation/git-p4.txt
@@ -31,13 +31,6 @@ the updated p4 remote branch.
EXAMPLE
-------
-* Create an alias for 'git p4', using the full path to the 'git-p4'
- script if needed:
-+
-------------
-$ git config --global alias.p4 '!git-p4'
-------------
-
* Clone a repository:
+
------------
@@ -165,11 +158,14 @@ OPTIONS
General options
~~~~~~~~~~~~~~~
-All commands except clone accept this option.
+All commands except clone accept these options.
--git-dir <dir>::
Set the 'GIT_DIR' environment variable. See linkgit:git[1].
+--verbose::
+ Provide more progress information.
+
Sync options
~~~~~~~~~~~~
These options can be used in the initial 'clone' as well as in
@@ -200,12 +196,13 @@ git repository:
--silent::
Do not print any progress information.
---verbose::
- Provide more progress information.
-
--detect-labels::
Query p4 for labels associated with the depot paths, and add
- them as tags in git.
+ them as tags in git. Limited usefulness as only imports labels
+ associated with new changelists. Deprecated.
+
+--import-labels::
+ Import labels from p4 into git.
--import-local::
By default, p4 branches are stored in 'refs/remotes/p4/',
@@ -252,9 +249,6 @@ Submit options
~~~~~~~~~~~~~~
These options can be used to modify 'git p4 submit' behavior.
---verbose::
- Provide more progress information.
-
--origin <commit>::
Upstream location from which commits are identified to submit to
p4. By default, this is the most recent p4 commit reachable
@@ -270,6 +264,16 @@ These options can be used to modify 'git p4 submit' behavior.
Re-author p4 changes before submitting to p4. This option
requires p4 admin privileges.
+--export-labels::
+ Export tags from git as p4 labels. Tags found in git are applied
+ to the perforce working directory.
+
+Rebase options
+~~~~~~~~~~~~~~
+These options can be used to modify 'git p4 rebase' behavior.
+
+--import-labels::
+ Import p4 labels.
DEPOT PATH SYNTAX
-----------------
@@ -311,19 +315,19 @@ configuration file. This allows future 'git p4 submit' commands to
work properly; the submit command looks only at the variable and does
not have a command-line option.
-The full syntax for a p4 view is documented in 'p4 help views'. Git-p4
+The full syntax for a p4 view is documented in 'p4 help views'. 'Git p4'
knows only a subset of the view syntax. It understands multi-line
mappings, overlays with '+', exclusions with '-' and double-quotes
-around whitespace. Of the possible wildcards, git-p4 only handles
-'...', and only when it is at the end of the path. Git-p4 will complain
+around whitespace. Of the possible wildcards, 'git p4' only handles
+'...', and only when it is at the end of the path. 'Git p4' will complain
if it encounters an unhandled wildcard.
Bugs in the implementation of overlap mappings exist. If multiple depot
paths map through overlays to the same location in the repository,
-git-p4 can choose the wrong one. This is hard to solve without
-dedicating a client spec just for git-p4.
+'git p4' can choose the wrong one. This is hard to solve without
+dedicating a client spec just for 'git p4'.
-The name of the client can be given to git-p4 in multiple ways. The
+The name of the client can be given to 'git p4' in multiple ways. The
variable 'git-p4.client' takes precedence if it exists. Otherwise,
normal p4 mechanisms of determining the client are used: environment
variable P4CLIENT, a file referenced by P4CONFIG, or the local host name.
@@ -434,11 +438,23 @@ git-p4.branchList::
enabled. Each entry should be a pair of branch names separated
by a colon (:). This example declares that both branchA and
branchB were created from main:
+
-------------
git config git-p4.branchList main:branchA
git config --add git-p4.branchList main:branchB
-------------
+git-p4.ignoredP4Labels::
+ List of p4 labels to ignore. This is built automatically as
+ unimportable labels are discovered.
+
+git-p4.importLabels::
+ Import p4 labels into git, as per --import-labels.
+
+git-p4.labelImportRegexp::
+ Only p4 labels matching this regular expression will be imported. The
+ default value is '[a-zA-Z0-9_\-.]+$'.
+
git-p4.useClientSpec::
Specify that the p4 client spec should be used to identify p4
depot paths of interest. This is equivalent to specifying the
@@ -488,10 +504,17 @@ git-p4.skipUserNameCheck::
submission regardless.
git-p4.attemptRCSCleanup:
- If enabled, 'git p4 submit' will attempt to cleanup RCS keywords
- ($Header$, etc). These would otherwise cause merge conflicts and prevent
- the submit going ahead. This option should be considered experimental at
- present.
+ If enabled, 'git p4 submit' will attempt to cleanup RCS keywords
+ ($Header$, etc). These would otherwise cause merge conflicts and prevent
+ the submit going ahead. This option should be considered experimental at
+ present.
+
+git-p4.exportLabels::
+ Export git tags to p4 labels, as per --export-labels.
+
+git-p4.labelExportRegexp::
+ Only p4 labels matching this regular expression will be exported. The
+ default value is '[a-zA-Z0-9_\-.]+$'.
IMPLEMENTATION DETAILS
----------------------
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 48760db337..a52b7b1a19 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -170,10 +170,16 @@ useful if you write an alias or script around 'git push'.
is specified. This flag forces progress status even if the
standard error stream is not directed to a terminal.
---recurse-submodules=check::
- Check whether all submodule commits used by the revisions to be
- pushed are available on a remote tracking branch. Otherwise the
- push will be aborted and the command will exit with non-zero status.
+--recurse-submodules=check|on-demand::
+ Make sure all submodule commits used by the revisions to be
+ pushed are available on a remote tracking branch. If 'check' is
+ used git will verify that all submodule commits that changed in
+ the revisions to be pushed are available on at least one remote
+ of the submodule. If any commits are missing the push will be
+ aborted and exit with non-zero status. If 'on-demand' is used
+ all submodules that changed in the revisions to be pushed will
+ be pushed. If on-demand was not able to push all necessary
+ revisions it will also be aborted and exit with non-zero status.
include::urls-remotes.txt[]
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 520aaa94fb..841ebd6a9f 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -238,6 +238,10 @@ leave out at most one of A and B, in which case it defaults to HEAD.
will be reset to where it was when the rebase operation was
started.
+--keep-empty::
+ Keep the commits that do not change anything from its
+ parents in the result.
+
--skip::
Restart the rebasing process by skipping the current patch.
diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
index a3081f4e23..9d0b1515c5 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -19,7 +19,7 @@ SYNOPSIS
[--ignore-submodules]
[--really-refresh] [--unresolve] [--again | -g]
[--info-only] [--index-info]
- [-z] [--stdin]
+ [-z] [--stdin] [--index-version <n>]
[--verbose]
[--] [<file>...]
@@ -143,6 +143,10 @@ you will need to handle the situation manually.
--verbose::
Report what is being added and removed from index.
+--index-version <n>::
+ Write the resulting index out in the named on-disk format version.
+ The current default version is 2.
+
-z::
Only meaningful with `--stdin` or `--index-info`; paths are
separated with NUL character instead of LF.
diff --git a/Documentation/git-var.txt b/Documentation/git-var.txt
index 5317cc2474..988a3234f4 100644
--- a/Documentation/git-var.txt
+++ b/Documentation/git-var.txt
@@ -43,13 +43,21 @@ GIT_EDITOR::
`$SOME_ENVIRONMENT_VARIABLE`, `"C:\Program Files\Vim\gvim.exe"
--nofork`. The order of preference is the `$GIT_EDITOR`
environment variable, then `core.editor` configuration, then
- `$VISUAL`, then `$EDITOR`, and then finally 'vi'.
+ `$VISUAL`, then `$EDITOR`, and then the default chosen at compile
+ time, which is usually 'vi'.
+ifdef::git-default-editor[]
+ The build you are using chose '{git-default-editor}' as the default.
+endif::git-default-editor[]
GIT_PAGER::
Text viewer for use by git commands (e.g., 'less'). The value
is meant to be interpreted by the shell. The order of preference
is the `$GIT_PAGER` environment variable, then `core.pager`
- configuration, then `$PAGER`, and then finally 'less'.
+ configuration, then `$PAGER`, and then the default chosen at
+ compile time (usually 'less').
+ifdef::git-default-pager[]
+ The build you are using chose '{git-default-pager}' as the default.
+endif::git-default-pager[]
Diagnostics
-----------
diff --git a/Documentation/git.txt b/Documentation/git.txt
index ca85d1d210..8527775988 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -44,14 +44,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.7.10/git.html[documentation for release 1.7.10]
+* link:v1.7.10.1/git.html[documentation for release 1.7.10.1]
* release notes for
+ link:RelNotes/1.7.10.1.txt[1.7.10.1],
link:RelNotes/1.7.10.txt[1.7.10].
-* link:v1.7.9.6/git.html[documentation for release 1.7.9.6]
+* link:v1.7.9.7/git.html[documentation for release 1.7.9.7]
* release notes for
+ link:RelNotes/1.7.9.7.txt[1.7.9.7],
link:RelNotes/1.7.9.6.txt[1.7.9.6],
link:RelNotes/1.7.9.5.txt[1.7.9.5],
link:RelNotes/1.7.9.4.txt[1.7.9.4],
@@ -60,9 +62,10 @@ Documentation for older releases are available here:
link:RelNotes/1.7.9.1.txt[1.7.9.1],
link:RelNotes/1.7.9.txt[1.7.9].
-* link:v1.7.8.5/git.html[documentation for release 1.7.8.5]
+* link:v1.7.8.6/git.html[documentation for release 1.7.8.6]
* release notes for
+ link:RelNotes/1.7.8.6.txt[1.7.8.6],
link:RelNotes/1.7.8.5.txt[1.7.8.5],
link:RelNotes/1.7.8.4.txt[1.7.8.4],
link:RelNotes/1.7.8.3.txt[1.7.8.3],
@@ -70,9 +73,10 @@ Documentation for older releases are available here:
link:RelNotes/1.7.8.1.txt[1.7.8.1],
link:RelNotes/1.7.8.txt[1.7.8].
-* link:v1.7.7.6/git.html[documentation for release 1.7.7.6]
+* link:v1.7.7.7/git.html[documentation for release 1.7.7.7]
* release notes for
+ link:RelNotes/1.7.7.7.txt[1.7.7.7],
link:RelNotes/1.7.7.6.txt[1.7.7.6],
link:RelNotes/1.7.7.5.txt[1.7.7.5],
link:RelNotes/1.7.7.4.txt[1.7.7.4],
diff --git a/Documentation/gitweb.conf.txt b/Documentation/gitweb.conf.txt
index 7aba497b74..4b8d1b1d4c 100644
--- a/Documentation/gitweb.conf.txt
+++ b/Documentation/gitweb.conf.txt
@@ -499,6 +499,13 @@ $maxload::
Set `$maxload` to undefined value (`undef`) to turn this feature off.
The default value is 300.
+$omit_age_column::
+ If true, omit the column with date of the most current commit on the
+ projects list page. It can save a bit of I/O and a fork per repository.
+
+$omit_owner::
+ If true prevents displaying information about repository owner.
+
$per_request_config::
If this is set to code reference, it will be run once for each request.
You can set parts of configuration that change per session this way.
diff --git a/Documentation/technical/api-argv-array.txt b/Documentation/technical/api-argv-array.txt
index 49b3d52952..1b7d8f140c 100644
--- a/Documentation/technical/api-argv-array.txt
+++ b/Documentation/technical/api-argv-array.txt
@@ -37,6 +37,11 @@ Functions
`argv_array_push`::
Push a copy of a string onto the end of the array.
+`argv_array_pushl`::
+ Push a list of strings onto the end of the array. The arguments
+ should be a list of `const char *` strings, terminated by a NULL
+ argument.
+
`argv_array_pushf`::
Format a string and push it onto the end of the array. This is a
convenience wrapper combining `strbuf_addf` and `argv_array_push`.
diff --git a/Documentation/technical/api-revision-walking.txt b/Documentation/technical/api-revision-walking.txt
index 996da0503a..b7d0d9a8a7 100644
--- a/Documentation/technical/api-revision-walking.txt
+++ b/Documentation/technical/api-revision-walking.txt
@@ -56,6 +56,11 @@ function.
returning a `struct commit *` each time you call it. The end of the
revision list is indicated by returning a NULL pointer.
+`reset_revision_walk`::
+
+ Reset the flags used by the revision walking api. You can use
+ this to do multiple sequencial revision walks.
+
Data structures
---------------
diff --git a/Documentation/technical/index-format.txt b/Documentation/technical/index-format.txt
index 8930b3fabc..9d25b30178 100644
--- a/Documentation/technical/index-format.txt
+++ b/Documentation/technical/index-format.txt
@@ -113,9 +113,22 @@ GIT index format
are encoded in 7-bit ASCII and the encoding cannot contain a NUL
byte (iow, this is a UNIX pathname).
+ (Version 4) In version 4, the entry path name is prefix-compressed
+ relative to the path name for the previous entry (the very first
+ entry is encoded as if the path name for the previous entry is an
+ empty string). At the beginning of an entry, an integer N in the
+ variable width encoding (the same encoding as the offset is encoded
+ for OFS_DELTA pack entries; see pack-format.txt) is stored, followed
+ by a NUL-terminated string S. Removing N bytes from the end of the
+ path name for the previous entry, and replacing it with the string S
+ yields the path name for this entry.
+
1-8 nul bytes as necessary to pad the entry to a multiple of eight bytes
while keeping the name NUL-terminated.
+ (Version 4) In version 4, the padding after the pathname does not
+ exist.
+
== Extensions
=== Cached tree
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index b982e33299..c92dbed2ec 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -12,7 +12,7 @@ if test -f version
then
VN=$(cat version) || VN="$DEF_VER"
elif test -d .git -o -f .git &&
- VN=$(git describe --match "v[0-9]*" --abbrev=4 HEAD 2>/dev/null) &&
+ VN=$(git describe --match "v[0-9]*" --abbrev=7 HEAD 2>/dev/null) &&
case "$VN" in
*$LF*) (exit 1) ;;
v[0-9]*)
diff --git a/INSTALL b/INSTALL
index 58b2b86ccf..87e03bbfd4 100644
--- a/INSTALL
+++ b/INSTALL
@@ -131,6 +131,9 @@ Issues of note:
use English. Under autoconf the configure script will do this
automatically if it can't find libintl on the system.
+ - Python version 2.6 or later is needed to use the git-p4
+ interface to Perforce.
+
- Some platform specific issues are dealt with Makefile rules,
but depending on your specific installation, you may not
have all the libraries/tools needed, or you may have
diff --git a/Makefile b/Makefile
index abee43e264..a14732c4cd 100644
--- a/Makefile
+++ b/Makefile
@@ -440,6 +440,7 @@ SCRIPT_PERL += git-send-email.perl
SCRIPT_PERL += git-svn.perl
SCRIPT_PYTHON += git-remote-testgit.py
+SCRIPT_PYTHON += git-p4.py
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
@@ -480,9 +481,11 @@ TEST_PROGRAMS_NEED_X += test-genrandom
TEST_PROGRAMS_NEED_X += test-index-version
TEST_PROGRAMS_NEED_X += test-line-buffer
TEST_PROGRAMS_NEED_X += test-match-trees
+TEST_PROGRAMS_NEED_X += test-mergesort
TEST_PROGRAMS_NEED_X += test-mktemp
TEST_PROGRAMS_NEED_X += test-parse-options
TEST_PROGRAMS_NEED_X += test-path-utils
+TEST_PROGRAMS_NEED_X += test-revision-walking
TEST_PROGRAMS_NEED_X += test-run-command
TEST_PROGRAMS_NEED_X += test-sha1
TEST_PROGRAMS_NEED_X += test-sigchain
@@ -590,6 +593,7 @@ LIB_H += log-tree.h
LIB_H += mailmap.h
LIB_H += merge-file.h
LIB_H += merge-recursive.h
+LIB_H += mergesort.h
LIB_H += notes.h
LIB_H += notes-cache.h
LIB_H += notes-merge.h
@@ -627,6 +631,7 @@ LIB_H += tree-walk.h
LIB_H += unpack-trees.h
LIB_H += userdiff.h
LIB_H += utf8.h
+LIB_H += varint.h
LIB_H += xdiff-interface.h
LIB_H += xdiff/xdiff.h
@@ -694,6 +699,7 @@ LIB_OBJS += mailmap.o
LIB_OBJS += match-trees.o
LIB_OBJS += merge-file.o
LIB_OBJS += merge-recursive.o
+LIB_OBJS += mergesort.o
LIB_OBJS += name-hash.o
LIB_OBJS += notes.o
LIB_OBJS += notes-cache.o
@@ -752,6 +758,7 @@ LIB_OBJS += url.o
LIB_OBJS += usage.o
LIB_OBJS += userdiff.o
LIB_OBJS += utf8.o
+LIB_OBJS += varint.o
LIB_OBJS += walker.o
LIB_OBJS += wrapper.o
LIB_OBJS += write_or_die.o
@@ -2265,6 +2272,8 @@ $(XDIFF_LIB): $(XDIFF_OBJS)
$(VCSSVN_LIB): $(VCSSVN_OBJS)
$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(VCSSVN_OBJS)
+export DEFAULT_EDITOR DEFAULT_PAGER
+
doc:
$(MAKE) -C Documentation all
diff --git a/argv-array.c b/argv-array.c
index a4e04201e6..0b5f8898a1 100644
--- a/argv-array.c
+++ b/argv-array.c
@@ -2,8 +2,7 @@
#include "argv-array.h"
#include "strbuf.h"
-static const char *empty_argv_storage = NULL;
-const char **empty_argv = &empty_argv_storage;
+const char *empty_argv[] = { NULL };
void argv_array_init(struct argv_array *array)
{
@@ -39,6 +38,17 @@ void argv_array_pushf(struct argv_array *array, const char *fmt, ...)
argv_array_push_nodup(array, strbuf_detach(&v, NULL));
}
+void argv_array_pushl(struct argv_array *array, ...)
+{
+ va_list ap;
+ const char *arg;
+
+ va_start(ap, array);
+ while((arg = va_arg(ap, const char *)))
+ argv_array_push(array, arg);
+ va_end(ap);
+}
+
void argv_array_clear(struct argv_array *array)
{
if (array->argv != empty_argv) {
diff --git a/argv-array.h b/argv-array.h
index 74dd2b1bc0..b93a69c36c 100644
--- a/argv-array.h
+++ b/argv-array.h
@@ -1,7 +1,7 @@
#ifndef ARGV_ARRAY_H
#define ARGV_ARRAY_H
-extern const char **empty_argv;
+extern const char *empty_argv[];
struct argv_array {
const char **argv;
@@ -15,6 +15,7 @@ void argv_array_init(struct argv_array *);
void argv_array_push(struct argv_array *, const char *);
__attribute__((format (printf,2,3)))
void argv_array_pushf(struct argv_array *, const char *fmt, ...);
+void argv_array_pushl(struct argv_array *, ...);
void argv_array_clear(struct argv_array *);
#endif /* ARGV_ARRAY_H */
diff --git a/builtin/apply.c b/builtin/apply.c
index 389898f133..799bb5e906 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -152,9 +152,14 @@ struct fragment {
unsigned long leading, trailing;
unsigned long oldpos, oldlines;
unsigned long newpos, newlines;
+ /*
+ * 'patch' is usually borrowed from buf in apply_patch(),
+ * but some codepaths store an allocated buffer.
+ */
const char *patch;
+ unsigned free_patch:1,
+ rejected:1;
int size;
- int rejected;
int linenr;
struct fragment *next;
};
@@ -196,6 +201,36 @@ struct patch {
struct patch *next;
};
+static void free_fragment_list(struct fragment *list)
+{
+ while (list) {
+ struct fragment *next = list->next;
+ if (list->free_patch)
+ free((char *)list->patch);
+ free(list);
+ list = next;
+ }
+}
+
+static void free_patch(struct patch *patch)
+{
+ free_fragment_list(patch->fragments);
+ free(patch->def_name);
+ free(patch->old_name);
+ free(patch->new_name);
+ free(patch->result);
+ free(patch);
+}
+
+static void free_patch_list(struct patch *list)
+{
+ while (list) {
+ struct patch *next = list->next;
+ free_patch(list);
+ list = next;
+ }
+}
+
/*
* A line in a file, len-bytes long (includes the terminating LF,
* except for an incomplete line at the end if the file ends with
@@ -302,6 +337,11 @@ static void add_line_info(struct image *img, const char *bol, size_t len, unsign
img->nr++;
}
+/*
+ * "buf" has the file contents to be patched (read from various sources).
+ * attach it to "image" and add line-based index to it.
+ * "image" now owns the "buf".
+ */
static void prepare_image(struct image *image, char *buf, size_t len,
int prepare_linetable)
{
@@ -353,7 +393,6 @@ static void say_patch_name(FILE *output, const char *pre,
fputs(post, output);
}
-#define CHUNKSIZE (8192)
#define SLOP (16)
static void read_patch_file(struct strbuf *sb, int fd)
@@ -416,7 +455,7 @@ static char *squash_slash(char *name)
return name;
}
-static char *find_name_gnu(const char *line, char *def, int p_value)
+static char *find_name_gnu(const char *line, const char *def, int p_value)
{
struct strbuf name = STRBUF_INIT;
char *cp;
@@ -439,11 +478,7 @@ static char *find_name_gnu(const char *line, char *def, int p_value)
cp++;
}
- /* name can later be freed, so we need
- * to memmove, not just return cp
- */
strbuf_remove(&name, 0, cp - name.buf);
- free(def);
if (root)
strbuf_insert(&name, 0, root, root_len);
return squash_slash(strbuf_detach(&name, NULL));
@@ -608,8 +643,13 @@ static size_t diff_timestamp_len(const char *line, size_t len)
return line + len - end;
}
-static char *find_name_common(const char *line, char *def, int p_value,
- const char *end, int terminate)
+static char *null_strdup(const char *s)
+{
+ return s ? xstrdup(s) : NULL;
+}
+
+static char *find_name_common(const char *line, const char *def,
+ int p_value, const char *end, int terminate)
{
int len;
const char *start = NULL;
@@ -630,10 +670,10 @@ static char *find_name_common(const char *line, char *def, int p_value,
start = line;
}
if (!start)
- return squash_slash(def);
+ return squash_slash(null_strdup(def));
len = line - start;
if (!len)
- return squash_slash(def);
+ return squash_slash(null_strdup(def));
/*
* Generally we prefer the shorter name, especially
@@ -644,8 +684,7 @@ static char *find_name_common(const char *line, char *def, int p_value,
if (def) {
int deflen = strlen(def);
if (deflen < len && !strncmp(start, def, deflen))
- return squash_slash(def);
- free(def);
+ return squash_slash(xstrdup(def));
}
if (root) {
@@ -842,8 +881,10 @@ static void parse_traditional_patch(const char *first, const char *second, struc
name = find_name_traditional(first, NULL, p_value);
patch->old_name = name;
} else {
- name = find_name_traditional(first, NULL, p_value);
- name = find_name_traditional(second, name, p_value);
+ char *first_name;
+ first_name = find_name_traditional(first, NULL, p_value);
+ name = find_name_traditional(second, first_name, p_value);
+ free(first_name);
if (has_epoch_timestamp(first)) {
patch->is_new = 1;
patch->is_delete = 0;
@@ -853,7 +894,8 @@ static void parse_traditional_patch(const char *first, const char *second, struc
patch->is_delete = 1;
patch->old_name = name;
} else {
- patch->old_name = patch->new_name = name;
+ patch->old_name = name;
+ patch->new_name = xstrdup(name);
}
}
if (!name)
@@ -903,13 +945,19 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
static int gitdiff_oldname(const char *line, struct patch *patch)
{
+ char *orig = patch->old_name;
patch->old_name = gitdiff_verify_name(line, patch->is_new, patch->old_name, "old");
+ if (orig != patch->old_name)
+ free(orig);
return 0;
}
static int gitdiff_newname(const char *line, struct patch *patch)
{
+ char *orig = patch->new_name;
patch->new_name = gitdiff_verify_name(line, patch->is_delete, patch->new_name, "new");
+ if (orig != patch->new_name)
+ free(orig);
return 0;
}
@@ -928,20 +976,23 @@ static int gitdiff_newmode(const char *line, struct patch *patch)
static int gitdiff_delete(const char *line, struct patch *patch)
{
patch->is_delete = 1;
- patch->old_name = patch->def_name;
+ free(patch->old_name);
+ patch->old_name = null_strdup(patch->def_name);
return gitdiff_oldmode(line, patch);
}
static int gitdiff_newfile(const char *line, struct patch *patch)
{
patch->is_new = 1;
- patch->new_name = patch->def_name;
+ free(patch->new_name);
+ patch->new_name = null_strdup(patch->def_name);
return gitdiff_newmode(line, patch);
}
static int gitdiff_copysrc(const char *line, struct patch *patch)
{
patch->is_copy = 1;
+ free(patch->old_name);
patch->old_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0);
return 0;
}
@@ -949,6 +1000,7 @@ static int gitdiff_copysrc(const char *line, struct patch *patch)
static int gitdiff_copydst(const char *line, struct patch *patch)
{
patch->is_copy = 1;
+ free(patch->new_name);
patch->new_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0);
return 0;
}
@@ -956,6 +1008,7 @@ static int gitdiff_copydst(const char *line, struct patch *patch)
static int gitdiff_renamesrc(const char *line, struct patch *patch)
{
patch->is_rename = 1;
+ free(patch->old_name);
patch->old_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0);
return 0;
}
@@ -963,6 +1016,7 @@ static int gitdiff_renamesrc(const char *line, struct patch *patch)
static int gitdiff_renamedst(const char *line, struct patch *patch)
{
patch->is_rename = 1;
+ free(patch->new_name);
patch->new_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0);
return 0;
}
@@ -1044,7 +1098,7 @@ static const char *stop_at_slash(const char *line, int llen)
* creation or deletion of an empty file. In any of these cases,
* both sides are the same name under a/ and b/ respectively.
*/
-static char *git_header_name(char *line, int llen)
+static char *git_header_name(const char *line, int llen)
{
const char *name;
const char *second = NULL;
@@ -1171,7 +1225,7 @@ static char *git_header_name(char *line, int llen)
}
/* Verify that we recognize the lines following a git header */
-static int parse_git_header(char *line, int len, unsigned int size, struct patch *patch)
+static int parse_git_header(const char *line, int len, unsigned int size, struct patch *patch)
{
unsigned long offset;
@@ -1287,7 +1341,7 @@ static int parse_range(const char *line, int len, int offset, const char *expect
return offset + ex;
}
-static void recount_diff(char *line, int size, struct fragment *fragment)
+static void recount_diff(const char *line, int size, struct fragment *fragment)
{
int oldlines = 0, newlines = 0, ret = 0;
@@ -1341,7 +1395,7 @@ static void recount_diff(char *line, int size, struct fragment *fragment)
* Parse a unified diff fragment header of the
* form "@@ -a,b +c,d @@"
*/
-static int parse_fragment_header(char *line, int len, struct fragment *fragment)
+static int parse_fragment_header(const char *line, int len, struct fragment *fragment)
{
int offset;
@@ -1355,7 +1409,7 @@ static int parse_fragment_header(char *line, int len, struct fragment *fragment)
return offset;
}
-static int find_header(char *line, unsigned long size, int *hdrsize, struct patch *patch)
+static int find_header(const char *line, unsigned long size, int *hdrsize, struct patch *patch)
{
unsigned long offset, len;
@@ -1403,7 +1457,8 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
if (!patch->def_name)
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->old_name = xstrdup(patch->def_name);
+ patch->new_name = xstrdup(patch->def_name);
}
if (!patch->is_delete && !patch->new_name)
die("git diff header lacks filename information "
@@ -1466,7 +1521,7 @@ static void check_whitespace(const char *line, int len, unsigned ws_rule)
* between a "---" that is part of a patch, and a "---" that starts
* the next patch is to look at the line counts..
*/
-static int parse_fragment(char *line, unsigned long size,
+static int parse_fragment(const char *line, unsigned long size,
struct patch *patch, struct fragment *fragment)
{
int added, deleted;
@@ -1562,7 +1617,15 @@ static int parse_fragment(char *line, unsigned long size,
return offset;
}
-static int parse_single_patch(char *line, unsigned long size, struct patch *patch)
+/*
+ * We have seen "diff --git a/... b/..." header (or a traditional patch
+ * header). Read hunks that belong to this patch into fragments and hang
+ * them to the given patch structure.
+ *
+ * The (fragment->patch, fragment->size) pair points into the memory given
+ * by the caller, not a copy, when we return.
+ */
+static int parse_single_patch(const char *line, unsigned long size, struct patch *patch)
{
unsigned long offset = 0;
unsigned long oldlines = 0, newlines = 0, context = 0;
@@ -1655,6 +1718,11 @@ static char *inflate_it(const void *data, unsigned long size,
return out;
}
+/*
+ * Read a binary hunk and return a new fragment; fragment->patch
+ * points at an allocated memory that the caller must free, so
+ * it is marked as "->free_patch = 1".
+ */
static struct fragment *parse_binary_hunk(char **buf_p,
unsigned long *sz_p,
int *status_p,
@@ -1742,6 +1810,7 @@ static struct fragment *parse_binary_hunk(char **buf_p,
frag = xcalloc(1, sizeof(*frag));
frag->patch = inflate_it(data, hunk_size, origlen);
+ frag->free_patch = 1;
if (!frag->patch)
goto corrupt;
free(data);
@@ -1807,6 +1876,13 @@ static int parse_binary(char *buffer, unsigned long size, struct patch *patch)
return used;
}
+/*
+ * Read the patch text in "buffer" taht extends for "size" bytes; stop
+ * reading after seeing a single patch (i.e. changes to a single file).
+ * Create fragments (i.e. patch hunks) and hang them to the given patch.
+ * Return the number of bytes consumed, so that the caller can call us
+ * again for the next patch.
+ */
static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
{
int hdrsize, patchsize;
@@ -2367,6 +2443,11 @@ static void remove_last_line(struct image *img)
img->len -= img->line[--img->nr].len;
}
+/*
+ * The change from "preimage" and "postimage" has been found to
+ * apply at applied_pos (counts in line numbers) in "img".
+ * Update "img" to remove "preimage" and replace it with "postimage".
+ */
static void update_image(struct image *img,
int applied_pos,
struct image *preimage,
@@ -2438,6 +2519,11 @@ static void update_image(struct image *img,
img->nr = nr;
}
+/*
+ * Use the patch-hunk text in "frag" to prepare two images (preimage and
+ * postimage) for the hunk. Find lines that match "preimage" in "img" and
+ * replace the part of "img" with "postimage" text.
+ */
static int apply_one_fragment(struct image *img, struct fragment *frag,
int inaccurate_eof, unsigned ws_rule,
int nth_fragment)
@@ -2728,6 +2814,12 @@ static int apply_binary_fragment(struct image *img, struct patch *patch)
return -1;
}
+/*
+ * Replace "img" with the result of applying the binary patch.
+ * The binary patch data itself in patch->fragment is still kept
+ * but the preimage prepared by the caller in "img" is freed here
+ * or in the helper function apply_binary_fragment() this calls.
+ */
static int apply_binary(struct image *img, struct patch *patch)
{
const char *name = patch->old_name ? patch->old_name : patch->new_name;
@@ -2935,7 +3027,7 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
return error("patch %s has been renamed/deleted",
patch->old_name);
}
- /* We have a patched copy in memory use that */
+ /* We have a patched copy in memory; use that. */
strbuf_add(&buf, tpatch->result, tpatch->resultsize);
} else if (cached) {
if (read_file_or_gitlink(ce, &buf))
@@ -2948,7 +3040,10 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
/*
* There is no way to apply subproject
* patch without looking at the index.
+ * NEEDSWORK: shouldn't this be flagged
+ * as an error???
*/
+ free_fragment_list(patch->fragments);
patch->fragments = NULL;
}
} else {
@@ -3085,10 +3180,15 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
is_new:
patch->is_new = 1;
patch->is_delete = 0;
+ free(patch->old_name);
patch->old_name = NULL;
return 0;
}
+/*
+ * Check and apply the patch in-core; leave the result in patch->result
+ * for the caller to write it out to the final destination.
+ */
static int check_patch(struct patch *patch)
{
struct stat st;
@@ -3665,15 +3765,8 @@ static void prefix_patches(struct patch *p)
if (!prefix || p->is_toplevel_relative)
return;
for ( ; p; p = p->next) {
- if (p->new_name == p->old_name) {
- char *prefixed = p->new_name;
- prefix_one(&prefixed);
- p->new_name = p->old_name = prefixed;
- }
- else {
- prefix_one(&p->new_name);
- prefix_one(&p->old_name);
- }
+ prefix_one(&p->new_name);
+ prefix_one(&p->old_name);
}
}
@@ -3683,12 +3776,10 @@ static void prefix_patches(struct patch *p)
static int apply_patch(int fd, const char *filename, int options)
{
size_t offset;
- struct strbuf buf = STRBUF_INIT;
+ struct strbuf buf = STRBUF_INIT; /* owns the patch text */
struct patch *list = NULL, **listp = &list;
int skipped_patch = 0;
- /* FIXME - memory leak when using multiple patch files as inputs */
- memset(&fn_table, 0, sizeof(struct string_list));
patch_input_file = filename;
read_patch_file(&buf, fd);
offset = 0;
@@ -3712,8 +3803,7 @@ static int apply_patch(int fd, const char *filename, int options)
listp = &patch->next;
}
else {
- /* perhaps free it a bit better? */
- free(patch);
+ free_patch(patch);
skipped_patch++;
}
offset += nr;
@@ -3754,7 +3844,9 @@ static int apply_patch(int fd, const char *filename, int options)
if (summary)
summary_patch_list(list);
+ free_patch_list(list);
strbuf_release(&buf);
+ string_list_clear(&fn_table, 0);
return 0;
}
diff --git a/builtin/blame.c b/builtin/blame.c
index b35bd6249d..324d476abf 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -2302,6 +2302,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
OPT_BIT('s', NULL, &output_option, "Suppress author name and timestamp (Default: off)", OUTPUT_NO_AUTHOR),
OPT_BIT('e', "show-email", &output_option, "Show author email instead of name (Default: off)", OUTPUT_SHOW_EMAIL),
OPT_BIT('w', NULL, &xdl_opts, "Ignore whitespace differences", XDF_IGNORE_WHITESPACE),
+ OPT_BIT(0, "minimal", &xdl_opts, "Spend extra cycles to find better match", XDF_NEED_MINIMAL),
OPT_STRING('S', NULL, &revs_file, "file", "Use revisions from <file> instead of calling git-rev-list"),
OPT_STRING(0, "contents", &contents_from, "file", "Use <file>'s contents as the final image"),
{ OPTION_CALLBACK, 'C', NULL, &opt, "score", "Find line copies within and across files", PARSE_OPT_OPTARG, blame_copy_callback },
diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index 7124c4b49c..10db15b184 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -23,7 +23,9 @@ static struct fetch_pack_args args = {
};
static const char fetch_pack_usage[] =
-"git fetch-pack [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] [--no-progress] [-v] [<host>:]<directory> [<refs>...]";
+"git fetch-pack [--all] [--stdin] [--quiet|-q] [--keep|-k] [--thin] "
+"[--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] "
+"[--no-progress] [-v] [<host>:]<directory> [<refs>...]";
#define COMPLETE (1U << 0)
#define COMMON (1U << 1)
@@ -942,6 +944,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
args.fetch_all = 1;
continue;
}
+ if (!strcmp("--stdin", arg)) {
+ args.stdin_refs = 1;
+ continue;
+ }
if (!strcmp("-v", arg)) {
args.verbose = 1;
continue;
@@ -973,6 +979,40 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
if (!dest)
usage(fetch_pack_usage);
+ if (args.stdin_refs) {
+ /*
+ * Copy refs from cmdline to new growable list, then
+ * append the refs from the standard input.
+ */
+ int alloc_heads = nr_heads;
+ int size = nr_heads * sizeof(*heads);
+ heads = memcpy(xmalloc(size), heads, size);
+ if (args.stateless_rpc) {
+ /* in stateless RPC mode we use pkt-line to read
+ * from stdin, until we get a flush packet
+ */
+ static char line[1000];
+ for (;;) {
+ int n = packet_read_line(0, line, sizeof(line));
+ if (!n)
+ break;
+ if (line[n-1] == '\n')
+ n--;
+ ALLOC_GROW(heads, nr_heads + 1, alloc_heads);
+ heads[nr_heads++] = xmemdupz(line, n);
+ }
+ }
+ else {
+ /* read from stdin one ref per line, until EOF */
+ struct strbuf line = STRBUF_INIT;
+ while (strbuf_getline(&line, stdin, '\n') != EOF) {
+ ALLOC_GROW(heads, nr_heads + 1, alloc_heads);
+ heads[nr_heads++] = strbuf_detach(&line, NULL);
+ }
+ strbuf_release(&line);
+ }
+ }
+
if (args.stateless_rpc) {
conn = NULL;
fd[0] = 0;
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 65f5f9b72f..1c8cb62445 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -240,6 +240,7 @@ static int s_update_ref(const char *action,
static int update_local_ref(struct ref *ref,
const char *remote,
+ const struct ref *remote_ref,
struct strbuf *display)
{
struct commit *current = NULL, *updated;
@@ -293,18 +294,26 @@ static int update_local_ref(struct ref *ref,
const char *msg;
const char *what;
int r;
- if (!strncmp(ref->name, "refs/tags/", 10)) {
+ /*
+ * Nicely describe the new ref we're fetching.
+ * Base this on the remote's ref name, as it's
+ * more likely to follow a standard layout.
+ */
+ const char *name = remote_ref ? remote_ref->name : "";
+ if (!prefixcmp(name, "refs/tags/")) {
msg = "storing tag";
what = _("[new tag]");
- }
- else {
+ } else if (!prefixcmp(name, "refs/heads/")) {
msg = "storing head";
what = _("[new branch]");
- if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
- (recurse_submodules != RECURSE_SUBMODULES_ON))
- check_for_new_submodule_commits(ref->new_sha1);
+ } else {
+ msg = "storing ref";
+ what = _("[new ref]");
}
+ if ((recurse_submodules != RECURSE_SUBMODULES_OFF) &&
+ (recurse_submodules != RECURSE_SUBMODULES_ON))
+ check_for_new_submodule_commits(ref->new_sha1);
r = s_update_ref(msg, ref, 0);
strbuf_addf(display, "%c %-*s %-*s -> %s%s",
r ? '!' : '*',
@@ -466,7 +475,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
strbuf_reset(&note);
if (ref) {
- rc |= update_local_ref(ref, what, &note);
+ rc |= update_local_ref(ref, what, rm, &note);
free(ref);
} else
strbuf_addf(&note, "* %-*s %-*s -> FETCH_HEAD",
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 1bc6b8b8c3..a517f1794a 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -55,7 +55,48 @@ static void init_src_data(struct src_data *data)
static struct string_list srcs = STRING_LIST_INIT_DUP;
static struct string_list origins = STRING_LIST_INIT_DUP;
-static int handle_line(char *line)
+struct merge_parents {
+ int alloc, nr;
+ struct merge_parent {
+ unsigned char given[20];
+ unsigned char commit[20];
+ unsigned char used;
+ } *item;
+};
+
+/*
+ * I know, I know, this is inefficient, but you won't be pulling and merging
+ * hundreds of heads at a time anyway.
+ */
+static struct merge_parent *find_merge_parent(struct merge_parents *table,
+ unsigned char *given,
+ unsigned char *commit)
+{
+ int i;
+ for (i = 0; i < table->nr; i++) {
+ if (given && hashcmp(table->item[i].given, given))
+ continue;
+ if (commit && hashcmp(table->item[i].commit, commit))
+ continue;
+ return &table->item[i];
+ }
+ return NULL;
+}
+
+static void add_merge_parent(struct merge_parents *table,
+ unsigned char *given,
+ unsigned char *commit)
+{
+ if (table->nr && find_merge_parent(table, given, commit))
+ return;
+ ALLOC_GROW(table->item, table->nr + 1, table->alloc);
+ hashcpy(table->item[table->nr].given, given);
+ hashcpy(table->item[table->nr].commit, commit);
+ table->item[table->nr].used = 0;
+ table->nr++;
+}
+
+static int handle_line(char *line, struct merge_parents *merge_parents)
{
int i, len = strlen(line);
struct origin_data *origin_data;
@@ -63,6 +104,7 @@ static int handle_line(char *line)
struct src_data *src_data;
struct string_list_item *item;
int pulling_head = 0;
+ unsigned char sha1[20];
if (len < 43 || line[40] != '\t')
return 1;
@@ -73,14 +115,15 @@ static int handle_line(char *line)
if (line[41] != '\t')
return 2;
- line[40] = 0;
- origin_data = xcalloc(1, sizeof(struct origin_data));
- i = get_sha1(line, origin_data->sha1);
- line[40] = '\t';
- if (i) {
- free(origin_data);
+ i = get_sha1_hex(line, sha1);
+ if (i)
return 3;
- }
+
+ if (!find_merge_parent(merge_parents, sha1, NULL))
+ return 0; /* subsumed by other parents */
+
+ origin_data = xcalloc(1, sizeof(struct origin_data));
+ hashcpy(origin_data->sha1, sha1);
if (line[len - 1] == '\n')
line[len - 1] = 0;
@@ -472,6 +515,67 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
strbuf_release(&tagbuf);
}
+static void find_merge_parents(struct merge_parents *result,
+ struct strbuf *in, unsigned char *head)
+{
+ struct commit_list *parents, *next;
+ struct commit *head_commit;
+ int pos = 0, i, j;
+
+ parents = NULL;
+ while (pos < in->len) {
+ int len;
+ char *p = in->buf + pos;
+ char *newline = strchr(p, '\n');
+ unsigned char sha1[20];
+ struct commit *parent;
+ struct object *obj;
+
+ len = newline ? newline - p : strlen(p);
+ pos += len + !!newline;
+
+ if (len < 43 ||
+ get_sha1_hex(p, sha1) ||
+ p[40] != '\t' ||
+ p[41] != '\t')
+ continue; /* skip not-for-merge */
+ /*
+ * Do not use get_merge_parent() here; we do not have
+ * "name" here and we do not want to contaminate its
+ * util field yet.
+ */
+ obj = parse_object(sha1);
+ parent = (struct commit *)peel_to_type(NULL, 0, obj, OBJ_COMMIT);
+ if (!parent)
+ continue;
+ commit_list_insert(parent, &parents);
+ add_merge_parent(result, obj->sha1, parent->object.sha1);
+ }
+ head_commit = lookup_commit(head);
+ if (head_commit)
+ commit_list_insert(head_commit, &parents);
+ parents = reduce_heads(parents);
+
+ while (parents) {
+ for (i = 0; i < result->nr; i++)
+ if (!hashcmp(result->item[i].commit,
+ parents->item->object.sha1))
+ result->item[i].used = 1;
+ next = parents->next;
+ free(parents);
+ parents = next;
+ }
+
+ for (i = j = 0; i < result->nr; i++) {
+ if (result->item[i].used) {
+ if (i != j)
+ result->item[j] = result->item[i];
+ j++;
+ }
+ }
+ result->nr = j;
+}
+
int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
struct fmt_merge_msg_opts *opts)
{
@@ -479,6 +583,9 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
unsigned char head_sha1[20];
const char *current_branch;
void *current_branch_to_free;
+ struct merge_parents merge_parents;
+
+ memset(&merge_parents, 0, sizeof(merge_parents));
/* get current branch */
current_branch = current_branch_to_free =
@@ -488,6 +595,8 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
if (!prefixcmp(current_branch, "refs/heads/"))
current_branch += 11;
+ find_merge_parents(&merge_parents, in, head_sha1);
+
/* get a line */
while (pos < in->len) {
int len;
@@ -498,7 +607,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
pos += len + !!newline;
i++;
p[len] = 0;
- if (handle_line(p))
+ if (handle_line(p, &merge_parents))
die ("Error in line %d: %.*s", i, len, p);
}
@@ -529,6 +638,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
strbuf_complete_line(out);
free(current_branch_to_free);
+ free(merge_parents.item);
return 0;
}
diff --git a/builtin/gc.c b/builtin/gc.c
index 271376d82b..9b4232c8f3 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -14,6 +14,7 @@
#include "cache.h"
#include "parse-options.h"
#include "run-command.h"
+#include "argv-array.h"
#define FAILED_RUN "failed to run %s"
@@ -28,12 +29,11 @@ static int gc_auto_threshold = 6700;
static int gc_auto_pack_limit = 50;
static const char *prune_expire = "2.weeks.ago";
-#define MAX_ADD 10
-static const char *argv_pack_refs[] = {"pack-refs", "--all", "--prune", NULL};
-static const char *argv_reflog[] = {"reflog", "expire", "--all", NULL};
-static const char *argv_repack[MAX_ADD] = {"repack", "-d", "-l", NULL};
-static const char *argv_prune[] = {"prune", "--expire", NULL, NULL, NULL};
-static const char *argv_rerere[] = {"rerere", "gc", NULL};
+static struct argv_array pack_refs_cmd = ARGV_ARRAY_INIT;
+static struct argv_array reflog = ARGV_ARRAY_INIT;
+static struct argv_array repack = ARGV_ARRAY_INIT;
+static struct argv_array prune = ARGV_ARRAY_INIT;
+static struct argv_array rerere = ARGV_ARRAY_INIT;
static int gc_config(const char *var, const char *value, void *cb)
{
@@ -67,19 +67,6 @@ static int gc_config(const char *var, const char *value, void *cb)
return git_default_config(var, value, cb);
}
-static void append_option(const char **cmd, const char *opt, int max_length)
-{
- int i;
-
- for (i = 0; cmd[i]; i++)
- ;
-
- if (i + 2 >= max_length)
- die(_("Too many options specified"));
- cmd[i++] = opt;
- cmd[i] = NULL;
-}
-
static int too_many_loose_objects(void)
{
/*
@@ -144,6 +131,17 @@ static int too_many_packs(void)
return gc_auto_pack_limit <= cnt;
}
+static void add_repack_all_option(void)
+{
+ if (prune_expire && !strcmp(prune_expire, "now"))
+ argv_array_push(&repack, "-a");
+ else {
+ argv_array_push(&repack, "-A");
+ if (prune_expire)
+ argv_array_pushf(&repack, "--unpack-unreachable=%s", prune_expire);
+ }
+}
+
static int need_to_gc(void)
{
/*
@@ -160,10 +158,7 @@ static int need_to_gc(void)
* there is no need.
*/
if (too_many_packs())
- append_option(argv_repack,
- prune_expire && !strcmp(prune_expire, "now") ?
- "-a" : "-A",
- MAX_ADD);
+ add_repack_all_option();
else if (!too_many_loose_objects())
return 0;
@@ -177,7 +172,6 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
int aggressive = 0;
int auto_gc = 0;
int quiet = 0;
- char buf[80];
struct option builtin_gc_options[] = {
OPT__QUIET(&quiet, "suppress progress reporting"),
@@ -192,6 +186,12 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
if (argc == 2 && !strcmp(argv[1], "-h"))
usage_with_options(builtin_gc_usage, builtin_gc_options);
+ argv_array_pushl(&pack_refs_cmd, "pack-refs", "--all", "--prune", NULL);
+ argv_array_pushl(&reflog, "reflog", "expire", "--all", NULL);
+ argv_array_pushl(&repack, "repack", "-d", "-l", NULL);
+ argv_array_pushl(&prune, "prune", "--expire", NULL );
+ argv_array_pushl(&rerere, "rerere", "gc", NULL);
+
git_config(gc_config, NULL);
if (pack_refs < 0)
@@ -203,15 +203,13 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
usage_with_options(builtin_gc_usage, builtin_gc_options);
if (aggressive) {
- append_option(argv_repack, "-f", MAX_ADD);
- append_option(argv_repack, "--depth=250", MAX_ADD);
- if (aggressive_window > 0) {
- sprintf(buf, "--window=%d", aggressive_window);
- append_option(argv_repack, buf, MAX_ADD);
- }
+ argv_array_push(&repack, "-f");
+ argv_array_push(&repack, "--depth=250");
+ if (aggressive_window > 0)
+ argv_array_pushf(&repack, "--window=%d", aggressive_window);
}
if (quiet)
- append_option(argv_repack, "-q", MAX_ADD);
+ argv_array_push(&repack, "-q");
if (auto_gc) {
/*
@@ -227,30 +225,27 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
"run \"git gc\" manually. See "
"\"git help gc\" for more information.\n"));
} else
- append_option(argv_repack,
- prune_expire && !strcmp(prune_expire, "now")
- ? "-a" : "-A",
- MAX_ADD);
+ add_repack_all_option();
- if (pack_refs && run_command_v_opt(argv_pack_refs, RUN_GIT_CMD))
- return error(FAILED_RUN, argv_pack_refs[0]);
+ if (pack_refs && run_command_v_opt(pack_refs_cmd.argv, RUN_GIT_CMD))
+ return error(FAILED_RUN, pack_refs_cmd.argv[0]);
- if (run_command_v_opt(argv_reflog, RUN_GIT_CMD))
- return error(FAILED_RUN, argv_reflog[0]);
+ if (run_command_v_opt(reflog.argv, RUN_GIT_CMD))
+ return error(FAILED_RUN, reflog.argv[0]);
- if (run_command_v_opt(argv_repack, RUN_GIT_CMD))
- return error(FAILED_RUN, argv_repack[0]);
+ if (run_command_v_opt(repack.argv, RUN_GIT_CMD))
+ return error(FAILED_RUN, repack.argv[0]);
if (prune_expire) {
- argv_prune[2] = prune_expire;
+ argv_array_push(&prune, prune_expire);
if (quiet)
- argv_prune[3] = "--no-progress";
- if (run_command_v_opt(argv_prune, RUN_GIT_CMD))
- return error(FAILED_RUN, argv_prune[0]);
+ argv_array_push(&prune, "--no-progress");
+ if (run_command_v_opt(prune.argv, RUN_GIT_CMD))
+ return error(FAILED_RUN, prune.argv[0]);
}
- if (run_command_v_opt(argv_rerere, RUN_GIT_CMD))
- return error(FAILED_RUN, argv_rerere[0]);
+ if (run_command_v_opt(rerere.argv, RUN_GIT_CMD))
+ return error(FAILED_RUN, rerere.argv[0]);
if (auto_gc && too_many_loose_objects())
warning(_("There are too many unreachable loose objects; "
diff --git a/builtin/merge.c b/builtin/merge.c
index 08e01e8a60..470fc57c5d 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -52,7 +52,6 @@ static int fast_forward_only, option_edit = -1;
static int allow_trivial = 1, have_message;
static int overwrite_ignore = 1;
static struct strbuf merge_msg = STRBUF_INIT;
-static struct commit_list *remoteheads;
static struct strategy **use_strategies;
static size_t use_strategies_nr, use_strategies_alloc;
static const char **xopts;
@@ -318,7 +317,7 @@ static void finish_up_to_date(const char *msg)
drop_save();
}
-static void squash_message(struct commit *commit)
+static void squash_message(struct commit *commit, struct commit_list *remoteheads)
{
struct rev_info rev;
struct strbuf out = STRBUF_INIT;
@@ -366,6 +365,7 @@ static void squash_message(struct commit *commit)
}
static void finish(struct commit *head_commit,
+ struct commit_list *remoteheads,
const unsigned char *new_head, const char *msg)
{
struct strbuf reflog_message = STRBUF_INIT;
@@ -380,7 +380,7 @@ static void finish(struct commit *head_commit,
getenv("GIT_REFLOG_ACTION"), msg);
}
if (squash) {
- squash_message(head_commit);
+ squash_message(head_commit, remoteheads);
} else {
if (verbosity >= 0 && !merge_msg.len)
printf(_("No merge message -- not updating HEAD\n"));
@@ -683,6 +683,7 @@ int try_merge_command(const char *strategy, size_t xopts_nr,
}
static int try_merge_strategy(const char *strategy, struct commit_list *common,
+ struct commit_list *remoteheads,
struct commit *head, const char *head_arg)
{
int index_fd;
@@ -876,14 +877,14 @@ static void read_merge_msg(struct strbuf *msg)
die_errno(_("Could not read from '%s'"), filename);
}
-static void write_merge_state(void);
-static void abort_commit(const char *err_msg)
+static void write_merge_state(struct commit_list *);
+static void abort_commit(struct commit_list *remoteheads, const char *err_msg)
{
if (err_msg)
error("%s", err_msg);
fprintf(stderr,
_("Not committing merge; use 'git commit' to complete the merge.\n"));
- write_merge_state();
+ write_merge_state(remoteheads);
exit(1);
}
@@ -894,7 +895,7 @@ N_("Please enter a commit message to explain why this merge is necessary,\n"
"Lines starting with '#' will be ignored, and an empty message aborts\n"
"the commit.\n");
-static void prepare_to_commit(void)
+static void prepare_to_commit(struct commit_list *remoteheads)
{
struct strbuf msg = STRBUF_INIT;
const char *comment = _(merge_editor_comment);
@@ -907,18 +908,18 @@ static void prepare_to_commit(void)
git_path("MERGE_MSG"), "merge", NULL, NULL);
if (0 < option_edit) {
if (launch_editor(git_path("MERGE_MSG"), NULL, NULL))
- abort_commit(NULL);
+ abort_commit(remoteheads, NULL);
}
read_merge_msg(&msg);
stripspace(&msg, 0 < option_edit);
if (!msg.len)
- abort_commit(_("Empty commit message."));
+ abort_commit(remoteheads, _("Empty commit message."));
strbuf_release(&merge_msg);
strbuf_addbuf(&merge_msg, &msg);
strbuf_release(&msg);
}
-static int merge_trivial(struct commit *head)
+static int merge_trivial(struct commit *head, struct commit_list *remoteheads)
{
unsigned char result_tree[20], result_commit[20];
struct commit_list *parent = xmalloc(sizeof(*parent));
@@ -929,45 +930,37 @@ static int merge_trivial(struct commit *head)
parent->next = xmalloc(sizeof(*parent->next));
parent->next->item = remoteheads->item;
parent->next->next = NULL;
- prepare_to_commit();
+ prepare_to_commit(remoteheads);
if (commit_tree(&merge_msg, result_tree, parent, result_commit, NULL,
sign_commit))
die(_("failed to write commit object"));
- finish(head, result_commit, "In-index merge");
+ finish(head, remoteheads, result_commit, "In-index merge");
drop_save();
return 0;
}
static int finish_automerge(struct commit *head,
+ int head_subsumed,
struct commit_list *common,
+ struct commit_list *remoteheads,
unsigned char *result_tree,
const char *wt_strategy)
{
- struct commit_list *parents = NULL, *j;
+ struct commit_list *parents = NULL;
struct strbuf buf = STRBUF_INIT;
unsigned char result_commit[20];
free_commit_list(common);
- if (allow_fast_forward) {
- parents = remoteheads;
+ parents = remoteheads;
+ if (!head_subsumed || !allow_fast_forward)
commit_list_insert(head, &parents);
- parents = reduce_heads(parents);
- } else {
- struct commit_list **pptr = &parents;
-
- pptr = &commit_list_insert(head,
- pptr)->next;
- for (j = remoteheads; j; j = j->next)
- pptr = &commit_list_insert(j->item, pptr)->next;
- }
strbuf_addch(&merge_msg, '\n');
- prepare_to_commit();
- free_commit_list(remoteheads);
+ prepare_to_commit(remoteheads);
if (commit_tree(&merge_msg, result_tree, parents, result_commit,
NULL, sign_commit))
die(_("failed to write commit object"));
strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
- finish(head, result_commit, buf.buf);
+ finish(head, remoteheads, result_commit, buf.buf);
strbuf_release(&buf);
drop_save();
return 0;
@@ -1072,7 +1065,7 @@ static int setup_with_upstream(const char ***argv)
return i;
}
-static void write_merge_state(void)
+static void write_merge_state(struct commit_list *remoteheads)
{
const char *filename;
int fd;
@@ -1137,6 +1130,39 @@ static int default_edit_option(void)
st_stdin.st_mode == st_stdout.st_mode);
}
+static struct commit_list *collect_parents(struct commit *head_commit,
+ int *head_subsumed,
+ int argc, const char **argv)
+{
+ int i;
+ struct commit_list *remoteheads = NULL, *parents, *next;
+ struct commit_list **remotes = &remoteheads;
+
+ if (head_commit)
+ remotes = &commit_list_insert(head_commit, remotes)->next;
+ for (i = 0; i < argc; i++) {
+ struct commit *commit = get_merge_parent(argv[i]);
+ if (!commit)
+ die(_("%s - not something we can merge"), argv[i]);
+ remotes = &commit_list_insert(commit, remotes)->next;
+ }
+ *remotes = NULL;
+
+ parents = reduce_heads(remoteheads);
+
+ *head_subsumed = 1; /* we will flip this to 0 when we find it */
+ for (remoteheads = NULL, remotes = &remoteheads;
+ parents;
+ parents = next) {
+ struct commit *commit = parents->item;
+ next = parents->next;
+ if (commit == head_commit)
+ *head_subsumed = 0;
+ else
+ remotes = &commit_list_insert(commit, remotes)->next;
+ }
+ return remoteheads;
+}
int cmd_merge(int argc, const char **argv, const char *prefix)
{
@@ -1146,11 +1172,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
struct commit *head_commit;
struct strbuf buf = STRBUF_INIT;
const char *head_arg;
- int flag, i, ret = 0;
+ int flag, i, ret = 0, head_subsumed;
int best_cnt = -1, merge_was_ok = 0, automerge_was_ok = 0;
struct commit_list *common = NULL;
const char *best_strategy = NULL, *wt_strategy = NULL;
- struct commit_list **remotes = &remoteheads;
+ struct commit_list *remoteheads, *p;
void *branch_to_free;
if (argc == 2 && !strcmp(argv[1], "-h"))
@@ -1255,6 +1281,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
head_arg = argv[1];
argv += 2;
argc -= 2;
+ remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
} else if (!head_commit) {
struct commit *remote_head;
/*
@@ -1270,7 +1297,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
if (!allow_fast_forward)
die(_("Non-fast-forward commit does not make sense into "
"an empty head"));
- remote_head = get_merge_parent(argv[0]);
+ remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
+ remote_head = remoteheads->item;
if (!remote_head)
die(_("%s - not something we can merge"), argv[0]);
read_empty(remote_head->object.sha1, 0);
@@ -1288,8 +1316,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
* the standard merge summary message to be appended
* to the given message.
*/
- for (i = 0; i < argc; i++)
- merge_name(argv[i], &merge_names);
+ remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
+ for (p = remoteheads; p; p = p->next)
+ merge_name(merge_remote_util(p->item)->name, &merge_names);
if (!have_message || shortlog_len) {
struct fmt_merge_msg_opts opts;
@@ -1308,19 +1337,16 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
builtin_merge_options);
strbuf_addstr(&buf, "merge");
- for (i = 0; i < argc; i++)
- strbuf_addf(&buf, " %s", argv[i]);
+ for (p = remoteheads; p; p = p->next)
+ strbuf_addf(&buf, " %s", merge_remote_util(p->item)->name);
setenv("GIT_REFLOG_ACTION", buf.buf, 0);
strbuf_reset(&buf);
- for (i = 0; i < argc; i++) {
- struct commit *commit = get_merge_parent(argv[i]);
- if (!commit)
- die(_("%s - not something we can merge"), argv[i]);
- remotes = &commit_list_insert(commit, remotes)->next;
+ for (p = remoteheads; p; p = p->next) {
+ struct commit *commit = p->item;
strbuf_addf(&buf, "GITHEAD_%s",
sha1_to_hex(commit->object.sha1));
- setenv(buf.buf, argv[i], 1);
+ setenv(buf.buf, merge_remote_util(commit)->name, 1);
strbuf_reset(&buf);
if (!fast_forward_only &&
merge_remote_util(commit) &&
@@ -1333,7 +1359,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
option_edit = default_edit_option();
if (!use_strategies) {
- if (!remoteheads->next)
+ if (!remoteheads)
+ ; /* already up-to-date */
+ else if (!remoteheads->next)
add_strategies(pull_twohead, DEFAULT_TWOHEAD);
else
add_strategies(pull_octopus, DEFAULT_OCTOPUS);
@@ -1346,7 +1374,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
allow_trivial = 0;
}
- if (!remoteheads->next)
+ if (!remoteheads)
+ ; /* already up-to-date */
+ else if (!remoteheads->next)
common = get_merge_bases(head_commit, remoteheads->item, 1);
else {
struct commit_list *list = remoteheads;
@@ -1358,10 +1388,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.sha1,
NULL, 0, DIE_ON_ERR);
- if (!common)
+ if (remoteheads && !common)
; /* No common ancestors found. We need a real merge. */
- else if (!remoteheads->next && !common->next &&
- common->item == remoteheads->item) {
+ else if (!remoteheads ||
+ (!remoteheads->next && !common->next &&
+ common->item == remoteheads->item)) {
/*
* If head can reach all the merge then we are up to date.
* but first the most common case of merging one remote.
@@ -1399,7 +1430,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
goto done;
}
- finish(head_commit, commit->object.sha1, msg.buf);
+ finish(head_commit, remoteheads, commit->object.sha1, msg.buf);
drop_save();
goto done;
} else if (!remoteheads->next && common->next)
@@ -1421,7 +1452,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
if (!read_tree_trivial(common->item->object.sha1,
head_commit->object.sha1,
remoteheads->item->object.sha1)) {
- ret = merge_trivial(head_commit);
+ ret = merge_trivial(head_commit, remoteheads);
goto done;
}
printf(_("Nope.\n"));
@@ -1492,7 +1523,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
wt_strategy = use_strategies[i]->name;
ret = try_merge_strategy(use_strategies[i]->name,
- common, head_commit, head_arg);
+ common, remoteheads,
+ head_commit, head_arg);
if (!option_commit && !ret) {
merge_was_ok = 1;
/*
@@ -1534,8 +1566,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
* auto resolved the merge cleanly.
*/
if (automerge_was_ok) {
- ret = finish_automerge(head_commit, common, result_tree,
- wt_strategy);
+ ret = finish_automerge(head_commit, head_subsumed,
+ common, remoteheads,
+ result_tree, wt_strategy);
goto done;
}
@@ -1560,13 +1593,14 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
restore_state(head_commit->object.sha1, stash);
printf(_("Using the %s to prepare resolving by hand.\n"),
best_strategy);
- try_merge_strategy(best_strategy, common, head_commit, head_arg);
+ try_merge_strategy(best_strategy, common, remoteheads,
+ head_commit, head_arg);
}
if (squash)
- finish(head_commit, NULL, NULL);
+ finish(head_commit, remoteheads, NULL, NULL);
else
- write_merge_state();
+ write_merge_state(remoteheads);
if (merge_was_ok)
fprintf(stderr, _("Automatic merge went well; "
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 7b07c092cc..1861093e9d 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -63,6 +63,7 @@ static uint32_t nr_objects, nr_alloc, nr_result, nr_written;
static int non_empty;
static int reuse_delta = 1, reuse_object = 1;
static int keep_unreachable, unpack_unreachable, include_tag;
+static unsigned long unpack_unreachable_expiration;
static int local;
static int incremental;
static int ignore_packed_keep;
@@ -2249,6 +2250,10 @@ static void loosen_unused_packed_objects(struct rev_info *revs)
if (!p->pack_local || p->pack_keep)
continue;
+ if (unpack_unreachable_expiration &&
+ p->mtime < unpack_unreachable_expiration)
+ continue;
+
if (open_pack_index(p))
die("cannot open pack index");
@@ -2315,6 +2320,21 @@ static int option_parse_index_version(const struct option *opt,
return 0;
}
+static int option_parse_unpack_unreachable(const struct option *opt,
+ const char *arg, int unset)
+{
+ if (unset) {
+ unpack_unreachable = 0;
+ unpack_unreachable_expiration = 0;
+ }
+ else {
+ unpack_unreachable = 1;
+ if (arg)
+ unpack_unreachable_expiration = approxidate(arg);
+ }
+ return 0;
+}
+
static int option_parse_ulong(const struct option *opt,
const char *arg, int unset)
{
@@ -2392,8 +2412,9 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
"include tag objects that refer to objects to be packed"),
OPT_BOOL(0, "keep-unreachable", &keep_unreachable,
"keep unreachable objects"),
- OPT_BOOL(0, "unpack-unreachable", &unpack_unreachable,
- "unpack unreachable objects"),
+ { OPTION_CALLBACK, 0, "unpack-unreachable", NULL, "time",
+ "unpack unreachable objects newer than <time>",
+ PARSE_OPT_OPTARG, option_parse_unpack_unreachable },
OPT_BOOL(0, "thin", &thin,
"create thin packs"),
OPT_BOOL(0, "honor-pack-keep", &ignore_packed_keep,
diff --git a/builtin/push.c b/builtin/push.c
index 08ccb891c6..fdfcc6c716 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -327,13 +327,21 @@ static int option_parse_recurse_submodules(const struct option *opt,
const char *arg, int unset)
{
int *flags = opt->value;
+
+ if (*flags & (TRANSPORT_RECURSE_SUBMODULES_CHECK |
+ TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND))
+ die("%s can only be used once.", opt->long_name);
+
if (arg) {
if (!strcmp(arg, "check"))
*flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK;
+ else if (!strcmp(arg, "on-demand"))
+ *flags |= TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND;
else
die("bad %s argument: %s", opt->long_name, arg);
} else
- die("option %s needs an argument (check)", opt->long_name);
+ die("option %s needs an argument (check|on-demand)",
+ opt->long_name);
return 0;
}
diff --git a/builtin/remote.c b/builtin/remote.c
index fec92bc66e..b5645fe0ae 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -9,7 +9,7 @@
static const char * const builtin_remote_usage[] = {
"git remote [-v | --verbose]",
- "git remote add [-t <branch>] [-m <master>] [-f] [--mirror=<fetch|push>] <name> <url>",
+ "git remote add [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>",
"git remote rename <old> <new>",
"git remote rm <name>",
"git remote set-head <name> (-a | -d | <branch>)",
@@ -17,7 +17,7 @@ static const char * const builtin_remote_usage[] = {
"git remote prune [-n | --dry-run] <name>",
"git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]",
"git remote set-branches [--add] <name> <branch>...",
- "git remote set-url <name> <newurl> [<oldurl>]",
+ "git remote set-url [--push] <name> <newurl> [<oldurl>]",
"git remote set-url --add <name> <newurl>",
"git remote set-url --delete <name> <url>",
NULL
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 98d1cbecca..733f626f6c 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -634,6 +634,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
if (!strcmp(arg, "--show-prefix")) {
if (prefix)
puts(prefix);
+ else
+ putchar('\n');
continue;
}
if (!strcmp(arg, "--show-cdup")) {
diff --git a/builtin/revert.c b/builtin/revert.c
index e6840f23dc..82d1bf844b 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -86,6 +86,7 @@ static void verify_opt_mutually_compatible(const char *me, ...)
break;
}
}
+ va_end(ap);
if (opt1 && opt2)
die(_("%s: %s cannot be used with %s"), me, opt1, opt2);
@@ -114,12 +115,16 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
OPT_END(),
OPT_END(),
OPT_END(),
+ OPT_END(),
+ OPT_END(),
};
if (opts->action == REPLAY_PICK) {
struct option cp_extra[] = {
OPT_BOOLEAN('x', NULL, &opts->record_origin, "append commit name"),
OPT_BOOLEAN(0, "ff", &opts->allow_ff, "allow fast-forward"),
+ OPT_BOOLEAN(0, "allow-empty", &opts->allow_empty, "preserve initially empty commits"),
+ OPT_BOOLEAN(0, "keep-redundant-commits", &opts->keep_redundant_commits, "keep redundant, empty commits"),
OPT_END(),
};
if (parse_options_concat(options, ARRAY_SIZE(options), cp_extra))
@@ -137,6 +142,10 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
"--abort", rollback,
NULL);
+ /* implies allow_empty */
+ if (opts->keep_redundant_commits)
+ opts->allow_empty = 1;
+
/* Set the subcommand */
if (remove_state)
opts->subcommand = REPLAY_REMOVE_STATE;
@@ -181,12 +190,15 @@ static void parse_args(int argc, const char **argv, struct replay_opts *opts)
if (opts->subcommand != REPLAY_NONE) {
opts->revs = NULL;
} else {
+ struct setup_revision_opt s_r_opt;
opts->revs = xmalloc(sizeof(*opts->revs));
init_revisions(opts->revs, NULL);
opts->revs->no_walk = 1;
if (argc < 2)
usage_with_options(usage_str, options);
- argc = setup_revisions(argc, argv, opts->revs, NULL);
+ memset(&s_r_opt, 0, sizeof(s_r_opt));
+ s_r_opt.assume_dashdash = 1;
+ argc = setup_revisions(argc, argv, opts->revs, &s_r_opt);
}
if (argc > 1)
diff --git a/builtin/update-index.c b/builtin/update-index.c
index a6a23fa1f3..5f038d64da 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -708,6 +708,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
int newfd, entries, has_errors = 0, line_termination = '\n';
int read_from_stdin = 0;
int prefix_length = prefix ? strlen(prefix) : 0;
+ int preferred_index_format = 0;
char set_executable_bit = 0;
struct refresh_params refresh_args = {0, &has_errors};
int lock_error = 0;
@@ -791,6 +792,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
"(for porcelains) forget saved unresolved conflicts",
PARSE_OPT_NOARG | PARSE_OPT_NONEG,
resolve_undo_clear_callback},
+ OPT_INTEGER(0, "index-version", &preferred_index_format,
+ "write index in this format"),
OPT_END()
};
@@ -851,6 +854,17 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
}
}
argc = parse_options_end(&ctx);
+ if (preferred_index_format) {
+ if (preferred_index_format < INDEX_FORMAT_LB ||
+ INDEX_FORMAT_UB < preferred_index_format)
+ die("index-version %d not in range: %d..%d",
+ preferred_index_format,
+ INDEX_FORMAT_LB, INDEX_FORMAT_UB);
+
+ if (the_index.version != preferred_index_format)
+ active_cache_changed = 1;
+ the_index.version = preferred_index_format;
+ }
if (read_from_stdin) {
struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT;
diff --git a/bundle.c b/bundle.c
index d9cfd90534..27ab32e431 100644
--- a/bundle.c
+++ b/bundle.c
@@ -289,7 +289,7 @@ int create_bundle(struct bundle_header *header, const char *path,
argc = setup_revisions(argc, argv, &revs, NULL);
if (argc > 1)
- return error("unrecognized argument: %s'", argv[1]);
+ return error("unrecognized argument: %s", argv[1]);
object_array_remove_duplicates(&revs.pending);
diff --git a/cache.h b/cache.h
index b60d49085e..5e419a11cc 100644
--- a/cache.h
+++ b/cache.h
@@ -105,6 +105,9 @@ struct cache_header {
unsigned int hdr_entries;
};
+#define INDEX_FORMAT_LB 2
+#define INDEX_FORMAT_UB 4
+
/*
* The "cache_time" is just the low 32 bits of the
* time. It doesn't matter if it overflows - we only
@@ -115,48 +118,6 @@ struct cache_time {
unsigned int nsec;
};
-/*
- * dev/ino/uid/gid/size are also just tracked to the low 32 bits
- * Again - this is just a (very strong in practice) heuristic that
- * the inode hasn't changed.
- *
- * We save the fields in big-endian order to allow using the
- * index file over NFS transparently.
- */
-struct ondisk_cache_entry {
- struct cache_time ctime;
- struct cache_time mtime;
- unsigned int dev;
- unsigned int ino;
- unsigned int mode;
- unsigned int uid;
- unsigned int gid;
- unsigned int size;
- unsigned char sha1[20];
- unsigned short flags;
- char name[FLEX_ARRAY]; /* more */
-};
-
-/*
- * This struct is used when CE_EXTENDED bit is 1
- * The struct must match ondisk_cache_entry exactly from
- * ctime till flags
- */
-struct ondisk_cache_entry_extended {
- struct cache_time ctime;
- struct cache_time mtime;
- unsigned int dev;
- unsigned int ino;
- unsigned int mode;
- unsigned int uid;
- unsigned int gid;
- unsigned int size;
- unsigned char sha1[20];
- unsigned short flags;
- unsigned short flags2;
- char name[FLEX_ARRAY]; /* more */
-};
-
struct cache_entry {
struct cache_time ce_ctime;
struct cache_time ce_mtime;
@@ -253,9 +214,6 @@ static inline size_t ce_namelen(const struct cache_entry *ce)
}
#define ce_size(ce) cache_entry_size(ce_namelen(ce))
-#define ondisk_ce_size(ce) (((ce)->ce_flags & CE_EXTENDED) ? \
- ondisk_cache_entry_extended_size(ce_namelen(ce)) : \
- ondisk_cache_entry_size(ce_namelen(ce)))
#define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT)
#define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE)
#define ce_skip_worktree(ce) ((ce)->ce_flags & CE_SKIP_WORKTREE)
@@ -306,13 +264,11 @@ static inline unsigned int canon_mode(unsigned int mode)
return S_IFGITLINK;
}
-#define flexible_size(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
#define cache_entry_size(len) (offsetof(struct cache_entry,name) + (len) + 1)
-#define ondisk_cache_entry_size(len) flexible_size(ondisk_cache_entry,len)
-#define ondisk_cache_entry_extended_size(len) flexible_size(ondisk_cache_entry_extended,len)
struct index_state {
struct cache_entry **cache;
+ unsigned int version;
unsigned int cache_nr, cache_alloc, cache_changed;
struct string_list *resolve_undo;
struct cache_tree *cache_tree;
diff --git a/command-list.txt b/command-list.txt
index a36ee9b015..38ec5f7b86 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -76,6 +76,7 @@ git-mktree plumbingmanipulators
git-mv mainporcelain common
git-name-rev plumbinginterrogators
git-notes mainporcelain
+git-p4 foreignscminterface
git-pack-objects plumbingmanipulators
git-pack-redundant plumbinginterrogators
git-pack-refs ancillarymanipulators
diff --git a/commit.c b/commit.c
index 4b39c19123..9ed36c7db5 100644
--- a/commit.c
+++ b/commit.c
@@ -7,6 +7,7 @@
#include "revision.h"
#include "notes.h"
#include "gpg-interface.h"
+#include "mergesort.h"
int save_commit_buffer = 1;
@@ -390,15 +391,31 @@ struct commit_list * commit_list_insert_by_date(struct commit *item, struct comm
return commit_list_insert(item, pp);
}
+static int commit_list_compare_by_date(const void *a, const void *b)
+{
+ unsigned long a_date = ((const struct commit_list *)a)->item->date;
+ unsigned long b_date = ((const struct commit_list *)b)->item->date;
+ if (a_date < b_date)
+ return 1;
+ if (a_date > b_date)
+ return -1;
+ return 0;
+}
+
+static void *commit_list_get_next(const void *a)
+{
+ return ((const struct commit_list *)a)->next;
+}
+
+static void commit_list_set_next(void *a, void *next)
+{
+ ((struct commit_list *)a)->next = next;
+}
void commit_list_sort_by_date(struct commit_list **list)
{
- struct commit_list *ret = NULL;
- while (*list) {
- commit_list_insert_by_date((*list)->item, &ret);
- *list = (*list)->next;
- }
- *list = ret;
+ *list = llist_mergesort(*list, commit_list_get_next, commit_list_set_next,
+ commit_list_compare_by_date);
}
struct commit *pop_most_recent_commit(struct commit_list **list,
@@ -1182,3 +1199,30 @@ struct commit *get_merge_parent(const char *name)
}
return commit;
}
+
+/*
+ * Append a commit to the end of the commit_list.
+ *
+ * next starts by pointing to the variable that holds the head of an
+ * empty commit_list, and is updated to point to the "next" field of
+ * the last item on the list as new commits are appended.
+ *
+ * Usage example:
+ *
+ * struct commit_list *list;
+ * struct commit_list **next = &list;
+ *
+ * next = commit_list_append(c1, next);
+ * next = commit_list_append(c2, next);
+ * assert(commit_list_count(list) == 2);
+ * return list;
+ */
+struct commit_list **commit_list_append(struct commit *commit,
+ struct commit_list **next)
+{
+ struct commit_list *new = xmalloc(sizeof(struct commit_list));
+ new->item = commit;
+ *next = new;
+ new->next = NULL;
+ return &new->next;
+}
diff --git a/commit.h b/commit.h
index 154c0e34ff..ccaa20b262 100644
--- a/commit.h
+++ b/commit.h
@@ -53,6 +53,8 @@ int find_commit_subject(const char *commit_buffer, const char **subject);
struct commit_list *commit_list_insert(struct commit *item,
struct commit_list **list);
+struct commit_list **commit_list_append(struct commit *commit,
+ struct commit_list **next);
unsigned commit_list_count(const struct commit_list *l);
struct commit_list *commit_list_insert_by_date(struct commit *item,
struct commit_list **list);
diff --git a/compat/mingw.h b/compat/mingw.h
index ef5b15014e..61a652138a 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -22,9 +22,10 @@ typedef int socklen_t;
#define S_IWOTH 0
#define S_IXOTH 0
#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
-#define S_ISUID 0
-#define S_ISGID 0
-#define S_ISVTX 0
+
+#define S_ISUID 0004000
+#define S_ISGID 0002000
+#define S_ISVTX 0001000
#define WIFEXITED(x) 1
#define WIFSIGNALED(x) 0
diff --git a/config.c b/config.c
index bfe0c79aea..eeee986022 100644
--- a/config.c
+++ b/config.c
@@ -37,6 +37,11 @@ static int handle_path_include(const char *path, struct config_include_data *inc
{
int ret = 0;
struct strbuf buf = STRBUF_INIT;
+ char *expanded = expand_user_path(path);
+
+ if (!expanded)
+ return error("Could not expand include path '%s'", path);
+ path = expanded;
/*
* Use an absolute path as-is, but interpret relative paths
@@ -63,6 +68,7 @@ static int handle_path_include(const char *path, struct config_include_data *inc
inc->depth--;
}
strbuf_release(&buf);
+ free(expanded);
return ret;
}
@@ -1554,20 +1560,42 @@ static int section_name_match (const char *buf, const char *name)
return 0;
}
+static int section_name_is_ok(const char *name)
+{
+ /* Empty section names are bogus. */
+ if (!*name)
+ return 0;
+
+ /*
+ * Before a dot, we must be alphanumeric or dash. After the first dot,
+ * anything goes, so we can stop checking.
+ */
+ for (; *name && *name != '.'; name++)
+ if (*name != '-' && !isalnum(*name))
+ return 0;
+ return 1;
+}
+
/* if new_name == NULL, the section is removed instead */
int git_config_rename_section_in_file(const char *config_filename,
const char *old_name, const char *new_name)
{
int ret = 0, remove = 0;
char *filename_buf = NULL;
- struct lock_file *lock = xcalloc(sizeof(struct lock_file), 1);
+ struct lock_file *lock;
int out_fd;
char buf[1024];
FILE *config_file;
+ if (new_name && !section_name_is_ok(new_name)) {
+ ret = error("invalid section name: %s", new_name);
+ goto out;
+ }
+
if (!config_filename)
config_filename = filename_buf = git_pathdup("config");
+ lock = xcalloc(sizeof(struct lock_file), 1);
out_fd = hold_lock_file_for_update(lock, config_filename, 0);
if (out_fd < 0) {
ret = error("could not lock config file %s", config_filename);
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 31f714da92..9f56ec7a6b 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -304,16 +304,16 @@ __git_ps1 ()
fi
}
-# __gitcomp_1 requires 2 arguments
__gitcomp_1 ()
{
- local c IFS=' '$'\t'$'\n'
+ local c IFS=$' \t\n'
for c in $1; do
- case "$c$2" in
- --*=*) printf %s$'\n' "$c$2" ;;
- *.) printf %s$'\n' "$c$2" ;;
- *) printf %s$'\n' "$c$2 " ;;
+ c="$c$2"
+ case $c in
+ --*=*|*.) ;;
+ *) c="$c " ;;
esac
+ printf '%s\n' "$c"
done
}
@@ -1658,7 +1658,7 @@ _git_notes ()
__gitcomp '--ref'
;;
,*)
- case "${words[cword-1]}" in
+ case "$prev" in
--ref)
__gitcomp_nl "$(__git_refs)"
;;
@@ -1684,7 +1684,7 @@ _git_notes ()
prune,*)
;;
*)
- case "${words[cword-1]}" in
+ case "$prev" in
-m|-F)
;;
*)
@@ -2623,8 +2623,9 @@ _git ()
case "$i" in
--git-dir=*) __git_dir="${i#--git-dir=}" ;;
--bare) __git_dir="." ;;
- --version|-p|--paginate) ;;
--help) command="help"; break ;;
+ -c) c=$((++c)) ;;
+ -*) ;;
*) command="$i"; break ;;
esac
((c++))
@@ -2639,9 +2640,12 @@ _git ()
--bare
--version
--exec-path
+ --exec-path=
--html-path
+ --info-path
--work-tree=
--namespace=
+ --no-replace-objects
--help
"
;;
diff --git a/contrib/fast-import/git-p4.README b/contrib/fast-import/git-p4.README
new file mode 100644
index 0000000000..cec5ecfa7c
--- /dev/null
+++ b/contrib/fast-import/git-p4.README
@@ -0,0 +1,12 @@
+The git-p4 script moved to the top-level of the git source directory.
+
+Invoke it as any other git command, like "git p4 clone", for instance.
+
+Note that the top-level git-p4.py script is now the source. It is
+built using make to git-p4, which will be installed.
+
+Windows users can copy the git-p4.py source script directly, possibly
+invoking it through a batch file called "git-p4.bat" in the same folder.
+It should contain just one line:
+
+ @python "%~d0%~p0git-p4.py" %*
diff --git a/contrib/fast-import/git-p4.bat b/contrib/fast-import/git-p4.bat
deleted file mode 100644
index 9f97e884f5..0000000000
--- a/contrib/fast-import/git-p4.bat
+++ /dev/null
@@ -1 +0,0 @@
-@python "%~d0%~p0git-p4" %*
diff --git a/diff-no-index.c b/diff-no-index.c
index 3a36144687..b44473e3c1 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -52,7 +52,7 @@ static int get_mode(const char *path, int *mode)
}
static int queue_diff(struct diff_options *o,
- const char *name1, const char *name2)
+ const char *name1, const char *name2)
{
int mode1 = 0, mode2 = 0;
@@ -63,10 +63,11 @@ static int queue_diff(struct diff_options *o,
return error("file/directory conflict: %s, %s", name1, name2);
if (S_ISDIR(mode1) || S_ISDIR(mode2)) {
- char buffer1[PATH_MAX], buffer2[PATH_MAX];
+ struct strbuf buffer1 = STRBUF_INIT;
+ struct strbuf buffer2 = STRBUF_INIT;
struct string_list p1 = STRING_LIST_INIT_DUP;
struct string_list p2 = STRING_LIST_INIT_DUP;
- int len1 = 0, len2 = 0, i1, i2, ret = 0;
+ int i1, i2, ret = 0;
if (name1 && read_directory(name1, &p1))
return -1;
@@ -76,19 +77,15 @@ static int queue_diff(struct diff_options *o,
}
if (name1) {
- len1 = strlen(name1);
- if (len1 > 0 && name1[len1 - 1] == '/')
- len1--;
- memcpy(buffer1, name1, len1);
- buffer1[len1++] = '/';
+ strbuf_addstr(&buffer1, name1);
+ if (buffer1.len && buffer1.buf[buffer1.len - 1] != '/')
+ strbuf_addch(&buffer1, '/');
}
if (name2) {
- len2 = strlen(name2);
- if (len2 > 0 && name2[len2 - 1] == '/')
- len2--;
- memcpy(buffer2, name2, len2);
- buffer2[len2++] = '/';
+ strbuf_addstr(&buffer2, name2);
+ if (buffer2.len && buffer2.buf[buffer2.len - 1] != '/')
+ strbuf_addch(&buffer2, '/');
}
for (i1 = i2 = 0; !ret && (i1 < p1.nr || i2 < p2.nr); ) {
@@ -100,29 +97,28 @@ static int queue_diff(struct diff_options *o,
else if (i2 == p2.nr)
comp = -1;
else
- comp = strcmp(p1.items[i1].string,
- p2.items[i2].string);
+ comp = strcmp(p1.items[i1].string, p2.items[i2].string);
if (comp > 0)
n1 = NULL;
else {
- n1 = buffer1;
- strncpy(buffer1 + len1, p1.items[i1++].string,
- PATH_MAX - len1);
+ strbuf_addstr(&buffer1, p1.items[i1++].string);
+ n1 = buffer1.buf;
}
if (comp < 0)
n2 = NULL;
else {
- n2 = buffer2;
- strncpy(buffer2 + len2, p2.items[i2++].string,
- PATH_MAX - len2);
+ strbuf_addstr(&buffer2, p2.items[i2++].string);
+ n2 = buffer2.buf;
}
ret = queue_diff(o, n1, n2);
}
string_list_clear(&p1, 0);
string_list_clear(&p2, 0);
+ strbuf_reset(&buffer1);
+ strbuf_reset(&buffer2);
return ret;
} else {
diff --git a/diff.c b/diff.c
index 5d6349feb3..22288b0106 100644
--- a/diff.c
+++ b/diff.c
@@ -4414,6 +4414,12 @@ void diff_flush(struct diff_options *options)
if (output_format & DIFF_FORMAT_PATCH) {
if (separator) {
+ if (options->output_prefix) {
+ struct strbuf *msg = NULL;
+ msg = options->output_prefix(options,
+ options->output_prefix_data);
+ fwrite(msg->buf, msg->len, 1, stdout);
+ }
putc(options->line_termination, options->file);
if (options->stat_sep) {
/* attach patch instead of inline */
diff --git a/fast-import.c b/fast-import.c
index a85275dc68..eed97c8fa9 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -2207,6 +2207,59 @@ static uintmax_t change_note_fanout(struct tree_entry *root,
return do_change_note_fanout(root, root, hex_sha1, 0, path, 0, fanout);
}
+/*
+ * Given a pointer into a string, parse a mark reference:
+ *
+ * idnum ::= ':' bigint;
+ *
+ * Return the first character after the value in *endptr.
+ *
+ * Complain if the following character is not what is expected,
+ * either a space or end of the string.
+ */
+static uintmax_t parse_mark_ref(const char *p, char **endptr)
+{
+ uintmax_t mark;
+
+ assert(*p == ':');
+ p++;
+ mark = strtoumax(p, endptr, 10);
+ if (*endptr == p)
+ die("No value after ':' in mark: %s", command_buf.buf);
+ return mark;
+}
+
+/*
+ * Parse the mark reference, and complain if this is not the end of
+ * the string.
+ */
+static uintmax_t parse_mark_ref_eol(const char *p)
+{
+ char *end;
+ uintmax_t mark;
+
+ mark = parse_mark_ref(p, &end);
+ if (*end != '\0')
+ die("Garbage after mark: %s", command_buf.buf);
+ return mark;
+}
+
+/*
+ * Parse the mark reference, demanding a trailing space. Return a
+ * pointer to the space.
+ */
+static uintmax_t parse_mark_ref_space(const char **p)
+{
+ uintmax_t mark;
+ char *end;
+
+ mark = parse_mark_ref(*p, &end);
+ if (*end != ' ')
+ die("Missing space after mark: %s", command_buf.buf);
+ *p = end;
+ return mark;
+}
+
static void file_change_m(struct branch *b)
{
const char *p = command_buf.buf + 2;
@@ -2235,21 +2288,21 @@ static void file_change_m(struct branch *b)
}
if (*p == ':') {
- char *x;
- oe = find_mark(strtoumax(p + 1, &x, 10));
+ oe = find_mark(parse_mark_ref_space(&p));
hashcpy(sha1, oe->idx.sha1);
- p = x;
- } else if (!prefixcmp(p, "inline")) {
+ } else if (!prefixcmp(p, "inline ")) {
inline_data = 1;
- p += 6;
+ p += strlen("inline"); /* advance to space */
} else {
if (get_sha1_hex(p, sha1))
- die("Invalid SHA1: %s", command_buf.buf);
+ die("Invalid dataref: %s", command_buf.buf);
oe = find_object(sha1);
p += 40;
+ if (*p != ' ')
+ die("Missing space after SHA1: %s", command_buf.buf);
}
- if (*p++ != ' ')
- die("Missing space after SHA1: %s", command_buf.buf);
+ assert(*p == ' ');
+ p++; /* skip space */
strbuf_reset(&uq);
if (!unquote_c_style(&uq, p, &endp)) {
@@ -2407,21 +2460,21 @@ static void note_change_n(struct branch *b, unsigned char *old_fanout)
/* Now parse the notemodify command. */
/* <dataref> or 'inline' */
if (*p == ':') {
- char *x;
- oe = find_mark(strtoumax(p + 1, &x, 10));
+ oe = find_mark(parse_mark_ref_space(&p));
hashcpy(sha1, oe->idx.sha1);
- p = x;
- } else if (!prefixcmp(p, "inline")) {
+ } else if (!prefixcmp(p, "inline ")) {
inline_data = 1;
- p += 6;
+ p += strlen("inline"); /* advance to space */
} else {
if (get_sha1_hex(p, sha1))
- die("Invalid SHA1: %s", command_buf.buf);
+ die("Invalid dataref: %s", command_buf.buf);
oe = find_object(sha1);
p += 40;
+ if (*p != ' ')
+ die("Missing space after SHA1: %s", command_buf.buf);
}
- if (*p++ != ' ')
- die("Missing space after SHA1: %s", command_buf.buf);
+ assert(*p == ' ');
+ p++; /* skip space */
/* <committish> */
s = lookup_branch(p);
@@ -2430,7 +2483,7 @@ static void note_change_n(struct branch *b, unsigned char *old_fanout)
die("Can't add a note on empty branch.");
hashcpy(commit_sha1, s->sha1);
} else if (*p == ':') {
- uintmax_t commit_mark = strtoumax(p + 1, NULL, 10);
+ uintmax_t commit_mark = parse_mark_ref_eol(p);
struct object_entry *commit_oe = find_mark(commit_mark);
if (commit_oe->type != OBJ_COMMIT)
die("Mark :%" PRIuMAX " not a commit", commit_mark);
@@ -2537,7 +2590,7 @@ static int parse_from(struct branch *b)
hashcpy(b->branch_tree.versions[0].sha1, t);
hashcpy(b->branch_tree.versions[1].sha1, t);
} else if (*from == ':') {
- uintmax_t idnum = strtoumax(from + 1, NULL, 10);
+ uintmax_t idnum = parse_mark_ref_eol(from);
struct object_entry *oe = find_mark(idnum);
if (oe->type != OBJ_COMMIT)
die("Mark :%" PRIuMAX " not a commit", idnum);
@@ -2572,7 +2625,7 @@ static struct hash_list *parse_merge(unsigned int *count)
if (s)
hashcpy(n->sha1, s->sha1);
else if (*from == ':') {
- uintmax_t idnum = strtoumax(from + 1, NULL, 10);
+ uintmax_t idnum = parse_mark_ref_eol(from);
struct object_entry *oe = find_mark(idnum);
if (oe->type != OBJ_COMMIT)
die("Mark :%" PRIuMAX " not a commit", idnum);
@@ -2735,7 +2788,7 @@ static void parse_new_tag(void)
type = OBJ_COMMIT;
} else if (*from == ':') {
struct object_entry *oe;
- from_mark = strtoumax(from + 1, NULL, 10);
+ from_mark = parse_mark_ref_eol(from);
oe = find_mark(from_mark);
type = oe->type;
hashcpy(sha1, oe->idx.sha1);
@@ -2867,18 +2920,13 @@ static void parse_cat_blob(void)
/* cat-blob SP <object> LF */
p = command_buf.buf + strlen("cat-blob ");
if (*p == ':') {
- char *x;
- oe = find_mark(strtoumax(p + 1, &x, 10));
- if (x == p + 1)
- die("Invalid mark: %s", command_buf.buf);
+ oe = find_mark(parse_mark_ref_eol(p));
if (!oe)
die("Unknown mark: %s", command_buf.buf);
- if (*x)
- die("Garbage after mark: %s", command_buf.buf);
hashcpy(sha1, oe->idx.sha1);
} else {
if (get_sha1_hex(p, sha1))
- die("Invalid SHA1: %s", command_buf.buf);
+ die("Invalid dataref: %s", command_buf.buf);
if (p[40])
die("Garbage after SHA1: %s", command_buf.buf);
oe = find_object(sha1);
@@ -2944,17 +2992,13 @@ static struct object_entry *parse_treeish_dataref(const char **p)
struct object_entry *e;
if (**p == ':') { /* <mark> */
- char *endptr;
- e = find_mark(strtoumax(*p + 1, &endptr, 10));
- if (endptr == *p + 1)
- die("Invalid mark: %s", command_buf.buf);
+ e = find_mark(parse_mark_ref_space(p));
if (!e)
die("Unknown mark: %s", command_buf.buf);
- *p = endptr;
hashcpy(sha1, e->idx.sha1);
} else { /* <sha1> */
if (get_sha1_hex(*p, sha1))
- die("Invalid SHA1: %s", command_buf.buf);
+ die("Invalid dataref: %s", command_buf.buf);
e = find_object(sha1);
*p += 40;
}
diff --git a/fetch-pack.h b/fetch-pack.h
index 0608edae3f..7c2069c972 100644
--- a/fetch-pack.h
+++ b/fetch-pack.h
@@ -10,6 +10,7 @@ struct fetch_pack_args {
lock_pack:1,
use_thin_pack:1,
fetch_all:1,
+ stdin_refs:1,
verbose:1,
no_progress:1,
include_tag:1,
diff --git a/contrib/fast-import/git-p4 b/git-p4.py
index c5362c4c11..eab69590c4 100755
--- a/contrib/fast-import/git-p4
+++ b/git-p4.py
@@ -14,6 +14,8 @@ import re, shutil
verbose = False
+# Only labels/tags matching this will be imported/exported
+defaultLabelRegexp = r'[a-zA-Z0-9_\-.]+$'
def p4_build_cmd(cmd):
"""Build a suitable p4 command line.
@@ -253,6 +255,26 @@ def getP4OpenedType(file):
else:
die("Could not determine file type for %s (result: '%s')" % (file, result))
+# Return the set of all p4 labels
+def getP4Labels(depotPaths):
+ labels = set()
+ if isinstance(depotPaths,basestring):
+ depotPaths = [depotPaths]
+
+ for l in p4CmdList(["labels"] + ["%s..." % p for p in depotPaths]):
+ label = l['label']
+ labels.add(label)
+
+ return labels
+
+# Return the set of all git tags
+def getGitTags():
+ gitTags = set()
+ for line in read_pipe_lines(["git", "tag"]):
+ tag = line.strip()
+ gitTags.add(tag)
+ return gitTags
+
def diffTreePattern():
# This is a simple generator for the diff tree regex pattern. This could be
# a class variable if this and parseDiffTreeEntry were a part of a class.
@@ -640,6 +662,7 @@ class Command:
def __init__(self):
self.usage = "usage: %prog [options]"
self.needsGit = True
+ self.verbose = False
class P4UserMap:
def __init__(self):
@@ -705,13 +728,9 @@ class P4UserMap:
class P4Debug(Command):
def __init__(self):
Command.__init__(self)
- self.options = [
- optparse.make_option("--verbose", dest="verbose", action="store_true",
- default=False),
- ]
+ self.options = []
self.description = "A tool to debug the output of p4 -G."
self.needsGit = False
- self.verbose = False
def run(self, args):
j = 0
@@ -725,11 +744,9 @@ class P4RollBack(Command):
def __init__(self):
Command.__init__(self)
self.options = [
- optparse.make_option("--verbose", dest="verbose", action="store_true"),
optparse.make_option("--local", dest="rollbackLocalBranches", action="store_true")
]
self.description = "A tool to debug the multi-branch import. Don't use :)"
- self.verbose = False
self.rollbackLocalBranches = False
def run(self, args):
@@ -787,20 +804,20 @@ class P4Submit(Command, P4UserMap):
Command.__init__(self)
P4UserMap.__init__(self)
self.options = [
- optparse.make_option("--verbose", dest="verbose", action="store_true"),
optparse.make_option("--origin", dest="origin"),
optparse.make_option("-M", dest="detectRenames", action="store_true"),
# preserve the user, requires relevant p4 permissions
optparse.make_option("--preserve-user", dest="preserveUser", action="store_true"),
+ optparse.make_option("--export-labels", dest="exportLabels", action="store_true"),
]
self.description = "Submit changes from git to the perforce depot."
self.usage += " [name of git branch to submit into perforce depot]"
self.interactive = True
self.origin = ""
self.detectRenames = False
- self.verbose = False
self.preserveUser = gitConfig("git-p4.preserveUser").lower() == "true"
self.isWindows = (platform.system() == "Windows")
+ self.exportLabels = False
def check(self):
if len(p4CmdList("opened ...")) > 0:
@@ -970,7 +987,7 @@ class P4Submit(Command, P4UserMap):
mtime = os.stat(template_file).st_mtime
# invoke the editor
- if os.environ.has_key("P4EDITOR"):
+ if os.environ.has_key("P4EDITOR") and (os.environ.get("P4EDITOR") != ""):
editor = os.environ.get("P4EDITOR")
else:
editor = read_pipe("git var GIT_EDITOR").strip()
@@ -1129,12 +1146,12 @@ class P4Submit(Command, P4UserMap):
print "The following files should be scheduled for deletion with p4 delete:"
print " ".join(filesToDelete)
die("Please resolve and submit the conflict manually and "
- + "continue afterwards with git-p4 submit --continue")
+ + "continue afterwards with git p4 submit --continue")
elif response == "w":
system(diffcmd + " > patch.txt")
print "Patch saved to patch.txt in %s !" % self.clientPath
die("Please resolve and submit the conflict manually and "
- "continue afterwards with git-p4 submit --continue")
+ "continue afterwards with git p4 submit --continue")
system(applyPatchCmd)
@@ -1178,8 +1195,8 @@ class P4Submit(Command, P4UserMap):
if self.checkAuthorship and not self.p4UserIsMe(p4User):
submitTemplate += "######## git author %s does not match your p4 account.\n" % gitEmail
- submitTemplate += "######## Use git-p4 option --preserve-user to modify authorship\n"
- submitTemplate += "######## Use git-p4 config git-p4.skipUserNameCheck hides this message.\n"
+ submitTemplate += "######## Use option --preserve-user to modify authorship.\n"
+ submitTemplate += "######## Variable git-p4.skipUserNameCheck hides this message.\n"
separatorLine = "######## everything below this line is just the diff #######\n"
@@ -1228,6 +1245,71 @@ class P4Submit(Command, P4UserMap):
+ "Please review/edit and then use p4 submit -i < %s to submit directly!"
% (fileName, fileName))
+ # Export git tags as p4 labels. Create a p4 label and then tag
+ # with that.
+ def exportGitTags(self, gitTags):
+ validLabelRegexp = gitConfig("git-p4.labelExportRegexp")
+ if len(validLabelRegexp) == 0:
+ validLabelRegexp = defaultLabelRegexp
+ m = re.compile(validLabelRegexp)
+
+ for name in gitTags:
+
+ if not m.match(name):
+ if verbose:
+ print "tag %s does not match regexp %s" % (name, validTagRegexp)
+ continue
+
+ # Get the p4 commit this corresponds to
+ logMessage = extractLogMessageFromGitCommit(name)
+ values = extractSettingsGitLog(logMessage)
+
+ if not values.has_key('change'):
+ # a tag pointing to something not sent to p4; ignore
+ if verbose:
+ print "git tag %s does not give a p4 commit" % name
+ continue
+ else:
+ changelist = values['change']
+
+ # Get the tag details.
+ inHeader = True
+ isAnnotated = False
+ body = []
+ for l in read_pipe_lines(["git", "cat-file", "-p", name]):
+ l = l.strip()
+ if inHeader:
+ if re.match(r'tag\s+', l):
+ isAnnotated = True
+ elif re.match(r'\s*$', l):
+ inHeader = False
+ continue
+ else:
+ body.append(l)
+
+ if not isAnnotated:
+ body = ["lightweight tag imported by git p4\n"]
+
+ # Create the label - use the same view as the client spec we are using
+ clientSpec = getClientSpec()
+
+ labelTemplate = "Label: %s\n" % name
+ labelTemplate += "Description:\n"
+ for b in body:
+ labelTemplate += "\t" + b + "\n"
+ labelTemplate += "View:\n"
+ for mapping in clientSpec.mappings:
+ labelTemplate += "\t%s\n" % mapping.depot_side.path
+
+ p4_write_pipe(["label", "-i"], labelTemplate)
+
+ # Use the label
+ p4_system(["tag", "-l", name] +
+ ["%s@%s" % (mapping.depot_side.path, changelist) for mapping in clientSpec.mappings])
+
+ if verbose:
+ print "created p4 label for tag %s" % name
+
def run(self, args):
if len(args) == 0:
self.master = currentGitBranch()
@@ -1317,6 +1399,16 @@ class P4Submit(Command, P4UserMap):
rebase = P4Rebase()
rebase.rebase()
+ if gitConfig("git-p4.exportLabels", "--bool") == "true":
+ self.exportLabels = true
+
+ if self.exportLabels:
+ p4Labels = getP4Labels(self.depotPath)
+ gitTags = getGitTags()
+
+ missingGitTags = gitTags - p4Labels
+ self.exportGitTags(missingGitTags)
+
return True
class View(object):
@@ -1544,7 +1636,7 @@ class P4Sync(Command, P4UserMap):
optparse.make_option("--changesfile", dest="changesFile"),
optparse.make_option("--silent", dest="silent", action="store_true"),
optparse.make_option("--detect-labels", dest="detectLabels", action="store_true"),
- optparse.make_option("--verbose", dest="verbose", action="store_true"),
+ optparse.make_option("--import-labels", dest="importLabels", action="store_true"),
optparse.make_option("--import-local", dest="importIntoRemotes", action="store_false",
help="Import into refs/heads/ , not refs/remotes"),
optparse.make_option("--max-changes", dest="maxChanges"),
@@ -1568,9 +1660,9 @@ class P4Sync(Command, P4UserMap):
self.branch = ""
self.detectBranches = False
self.detectLabels = False
+ self.importLabels = False
self.changesFile = ""
self.syncWithOrigin = True
- self.verbose = False
self.importIntoRemotes = True
self.maxChanges = ""
self.isWindows = (platform.system() == "Windows")
@@ -1829,6 +1921,38 @@ class P4Sync(Command, P4UserMap):
else:
return "%s <a@b>" % userid
+ # Stream a p4 tag
+ def streamTag(self, gitStream, labelName, labelDetails, commit, epoch):
+ if verbose:
+ print "writing tag %s for commit %s" % (labelName, commit)
+ gitStream.write("tag %s\n" % labelName)
+ gitStream.write("from %s\n" % commit)
+
+ if labelDetails.has_key('Owner'):
+ owner = labelDetails["Owner"]
+ else:
+ owner = None
+
+ # Try to use the owner of the p4 label, or failing that,
+ # the current p4 user id.
+ if owner:
+ email = self.make_email(owner)
+ else:
+ email = self.make_email(self.p4UserId())
+ tagger = "%s %s %s" % (email, epoch, self.tz)
+
+ gitStream.write("tagger %s\n" % tagger)
+
+ print "labelDetails=",labelDetails
+ if labelDetails.has_key('Description'):
+ description = labelDetails['Description']
+ else:
+ description = 'Label from git p4'
+
+ gitStream.write("data %d\n" % len(description))
+ gitStream.write(description)
+ gitStream.write("\n")
+
def commit(self, details, files, branch, branchPrefixes, parent = ""):
epoch = details["time"]
author = details["user"]
@@ -1893,25 +2017,7 @@ class P4Sync(Command, P4UserMap):
cleanedFiles[info["depotFile"]] = info["rev"]
if cleanedFiles == labelRevisions:
- self.gitStream.write("tag tag_%s\n" % labelDetails["label"])
- self.gitStream.write("from %s\n" % branch)
-
- owner = labelDetails["Owner"]
-
- # Try to use the owner of the p4 label, or failing that,
- # the current p4 user id.
- if owner:
- email = self.make_email(owner)
- else:
- email = self.make_email(self.p4UserId())
- tagger = "%s %s %s" % (email, epoch, self.tz)
-
- self.gitStream.write("tagger %s\n" % tagger)
-
- description = labelDetails["Description"]
- self.gitStream.write("data %d\n" % len(description))
- self.gitStream.write(description)
- self.gitStream.write("\n")
+ self.streamTag(self.gitStream, 'tag_%s' % labelDetails['label'], labelDetails, branch, epoch)
else:
if not self.silent:
@@ -1923,6 +2029,7 @@ class P4Sync(Command, P4UserMap):
print ("Tag %s does not match with change %s: file count is different."
% (labelDetails["label"], change))
+ # Build a dictionary of changelists and labels, for "detect-labels" option.
def getLabels(self):
self.labels = {}
@@ -1949,6 +2056,69 @@ class P4Sync(Command, P4UserMap):
if self.verbose:
print "Label changes: %s" % self.labels.keys()
+ # Import p4 labels as git tags. A direct mapping does not
+ # exist, so assume that if all the files are at the same revision
+ # then we can use that, or it's something more complicated we should
+ # just ignore.
+ def importP4Labels(self, stream, p4Labels):
+ if verbose:
+ print "import p4 labels: " + ' '.join(p4Labels)
+
+ ignoredP4Labels = gitConfigList("git-p4.ignoredP4Labels")
+ validLabelRegexp = gitConfig("git-p4.labelImportRegexp")
+ if len(validLabelRegexp) == 0:
+ validLabelRegexp = defaultLabelRegexp
+ m = re.compile(validLabelRegexp)
+
+ for name in p4Labels:
+ commitFound = False
+
+ if not m.match(name):
+ if verbose:
+ print "label %s does not match regexp %s" % (name,validLabelRegexp)
+ continue
+
+ if name in ignoredP4Labels:
+ continue
+
+ labelDetails = p4CmdList(['label', "-o", name])[0]
+
+ # get the most recent changelist for each file in this label
+ change = p4Cmd(["changes", "-m", "1"] + ["%s...@%s" % (p, name)
+ for p in self.depotPaths])
+
+ if change.has_key('change'):
+ # find the corresponding git commit; take the oldest commit
+ changelist = int(change['change'])
+ gitCommit = read_pipe(["git", "rev-list", "--max-count=1",
+ "--reverse", ":/\[git-p4:.*change = %d\]" % changelist])
+ if len(gitCommit) == 0:
+ print "could not find git commit for changelist %d" % changelist
+ else:
+ gitCommit = gitCommit.strip()
+ commitFound = True
+ # Convert from p4 time format
+ try:
+ tmwhen = time.strptime(labelDetails['Update'], "%Y/%m/%d %H:%M:%S")
+ except ValueError:
+ print "Could not convert label time %s" % labelDetail['Update']
+ tmwhen = 1
+
+ when = int(time.mktime(tmwhen))
+ self.streamTag(stream, name, labelDetails, gitCommit, when)
+ if verbose:
+ print "p4 label %s mapped to git commit %s" % (name, gitCommit)
+ else:
+ if verbose:
+ print "Label %s has no changelists - possibly deleted?" % name
+
+ if not commitFound:
+ # We can't import this label; don't try again as it will get very
+ # expensive repeatedly fetching all the files for labels that will
+ # never be imported. If the label is moved in the future, the
+ # ignore will need to be removed manually.
+ system(["git", "config", "--add", "git-p4.ignoredP4Labels", name])
+
def guessProjectName(self):
for p in self.depotPaths:
if p.endswith("/"):
@@ -2254,7 +2424,7 @@ class P4Sync(Command, P4UserMap):
details["change"] = newestRevision
- # Use time from top-most change so that all git-p4 clones of
+ # Use time from top-most change so that all git p4 clones of
# the same p4 repo have the same commit SHA1s.
res = p4CmdList("describe -s %d" % newestRevision)
newestTime = None
@@ -2425,7 +2595,6 @@ class P4Sync(Command, P4UserMap):
self.depotPaths = newPaths
-
self.loadUserMapFromCache()
self.labels = {}
if self.detectLabels:
@@ -2474,8 +2643,8 @@ class P4Sync(Command, P4UserMap):
changes.sort()
else:
- # catch "git-p4 sync" with no new branches, in a repo that
- # does not have any existing git-p4 branches
+ # catch "git p4 sync" with no new branches, in a repo that
+ # does not have any existing p4 branches
if len(args) == 0 and not self.p4BranchesInGit:
die("No remote p4 branches. Perhaps you never did \"git p4 clone\" in here.");
if self.verbose:
@@ -2489,22 +2658,31 @@ class P4Sync(Command, P4UserMap):
if len(changes) == 0:
if not self.silent:
print "No changes to import!"
- return True
+ else:
+ if not self.silent and not self.detectBranches:
+ print "Import destination: %s" % self.branch
- if not self.silent and not self.detectBranches:
- print "Import destination: %s" % self.branch
+ self.updatedBranches = set()
- self.updatedBranches = set()
+ self.importChanges(changes)
- self.importChanges(changes)
+ if not self.silent:
+ print ""
+ if len(self.updatedBranches) > 0:
+ sys.stdout.write("Updated branches: ")
+ for b in self.updatedBranches:
+ sys.stdout.write("%s " % b)
+ sys.stdout.write("\n")
- if not self.silent:
- print ""
- if len(self.updatedBranches) > 0:
- sys.stdout.write("Updated branches: ")
- for b in self.updatedBranches:
- sys.stdout.write("%s " % b)
- sys.stdout.write("\n")
+ if gitConfig("git-p4.importLabels", "--bool") == "true":
+ self.importLabels = true
+
+ if self.importLabels:
+ p4Labels = getP4Labels(self.depotPaths)
+ gitTags = getGitTags()
+
+ missingP4Labels = p4Labels - gitTags
+ self.importP4Labels(self.gitStream, missingP4Labels)
self.gitStream.close()
if importProcess.wait() != 0:
@@ -2523,13 +2701,16 @@ class P4Sync(Command, P4UserMap):
class P4Rebase(Command):
def __init__(self):
Command.__init__(self)
- self.options = [ ]
+ self.options = [
+ optparse.make_option("--import-labels", dest="importLabels", action="store_true"),
+ ]
+ self.importLabels = False
self.description = ("Fetches the latest revision from perforce and "
+ "rebases the current work (branch) against it")
- self.verbose = False
def run(self, args):
sync = P4Sync()
+ sync.importLabels = self.importLabels
sync.run([])
return self.rebase()
@@ -2719,16 +2900,16 @@ def main():
args = sys.argv[2:]
- if len(options) > 0:
- if cmd.needsGit:
- options.append(optparse.make_option("--git-dir", dest="gitdir"))
+ options.append(optparse.make_option("--verbose", dest="verbose", action="store_true"))
+ if cmd.needsGit:
+ options.append(optparse.make_option("--git-dir", dest="gitdir"))
- parser = optparse.OptionParser(cmd.usage.replace("%prog", "%prog " + cmdName),
- options,
- description = cmd.description,
- formatter = HelpFormatter())
+ parser = optparse.OptionParser(cmd.usage.replace("%prog", "%prog " + cmdName),
+ options,
+ description = cmd.description,
+ formatter = HelpFormatter())
- (cmd, args) = parser.parse_args(sys.argv[2:], cmd);
+ (cmd, args) = parser.parse_args(sys.argv[2:], cmd);
global verbose
verbose = cmd.verbose
if cmd.needsGit:
diff --git a/git-rebase--am.sh b/git-rebase--am.sh
index c815a2412c..04d89415fe 100644
--- a/git-rebase--am.sh
+++ b/git-rebase--am.sh
@@ -20,11 +20,20 @@ esac
test -n "$rebase_root" && root_flag=--root
-git format-patch -k --stdout --full-index --ignore-if-in-upstream \
- --src-prefix=a/ --dst-prefix=b/ \
- --no-renames $root_flag "$revisions" |
-git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" &&
-move_to_original_branch
+if test -n "$keep_empty"
+then
+ # we have to do this the hard way. git format-patch completely squashes
+ # empty commits and even if it didn't the format doesn't really lend
+ # itself well to recording empty patches. fortunately, cherry-pick
+ # makes this easy
+ git cherry-pick --allow-empty "$revisions"
+else
+ git format-patch -k --stdout --full-index --ignore-if-in-upstream \
+ --src-prefix=a/ --dst-prefix=b/ \
+ --no-renames $root_flag "$revisions" |
+ git am $git_am_opt --rebasing --resolvemsg="$resolvemsg"
+fi && move_to_original_branch
+
ret=$?
test 0 != $ret -a -d "$state_dir" && write_basic_state
exit $ret
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 2b7eb6dda4..0c19b7c753 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -167,6 +167,14 @@ has_action () {
sane_grep '^[^#]' "$1" >/dev/null
}
+is_empty_commit() {
+ tree=$(git rev-parse -q --verify "$1"^{tree} 2>/dev/null ||
+ die "$1: not a commit that can be picked")
+ ptree=$(git rev-parse -q --verify "$1"^^{tree} 2>/dev/null ||
+ ptree=4b825dc642cb6eb9a060e54bf8d69288fbee4904)
+ test "$tree" = "$ptree"
+}
+
# Run command with GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
# GIT_AUTHOR_DATE exported from the current environment.
do_with_author () {
@@ -191,12 +199,19 @@ git_sequence_editor () {
pick_one () {
ff=--ff
+
case "$1" in -n) sha1=$2; ff= ;; *) sha1=$1 ;; esac
case "$force_rebase" in '') ;; ?*) ff= ;; esac
output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1"
+
+ if is_empty_commit "$sha1"
+ then
+ empty_args="--allow-empty"
+ fi
+
test -d "$rewritten" &&
pick_one_preserving_merges "$@" && return
- output git cherry-pick $ff "$@"
+ output git cherry-pick $empty_args $ff "$@"
}
pick_one_preserving_merges () {
@@ -672,7 +687,7 @@ rearrange_squash () {
case "$action" in
continue)
# do we have anything to commit?
- if git diff-index --cached --quiet --ignore-submodules HEAD --
+ if git diff-index --cached --quiet HEAD --
then
: Nothing to commit -- skip this
else
@@ -780,9 +795,17 @@ git rev-list $merges_option --pretty=oneline --abbrev-commit \
sed -n "s/^>//p" |
while read -r shortsha1 rest
do
+
+ if test -z "$keep_empty" && is_empty_commit $shortsha1
+ then
+ comment_out="# "
+ else
+ comment_out=
+ fi
+
if test t != "$preserve_merges"
then
- printf '%s\n' "pick $shortsha1 $rest" >> "$todo"
+ printf '%s\n' "${comment_out}pick $shortsha1 $rest" >>"$todo"
else
sha1=$(git rev-parse $shortsha1)
if test -z "$rebase_root"
@@ -801,7 +824,7 @@ do
if test f = "$preserve"
then
touch "$rewritten"/$sha1
- printf '%s\n' "pick $shortsha1 $rest" >> "$todo"
+ printf '%s\n' "${comment_out}pick $shortsha1 $rest" >>"$todo"
fi
fi
done
@@ -853,6 +876,12 @@ cat >> "$todo" << EOF
#
EOF
+if test -z "$keep_empty"
+then
+ echo "# Note that empty commits are commented out" >>"$todo"
+fi
+
+
has_action "$todo" ||
die_abort "Nothing to do"
diff --git a/git-rebase.sh b/git-rebase.sh
index 69c1374823..24a2840033 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -43,6 +43,7 @@ s,strategy=! use the given merge strategy
no-ff! cherry-pick all commits, even if unchanged
m,merge! use merging strategies to rebase
i,interactive! let the user edit the list of commits to rebase
+k,keep-empty preserve empty commits during rebase
f,force-rebase! force rebase even if branch is up to date
X,strategy-option=! pass the argument through to the merge strategy
stat! display a diffstat of what changed upstream
@@ -97,6 +98,7 @@ state_dir=
action=
preserve_merges=
autosquash=
+keep_empty=
test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
read_basic_state () {
@@ -220,6 +222,9 @@ do
-i)
interactive_rebase=explicit
;;
+ -k)
+ keep_empty=yes
+ ;;
-p)
preserve_merges=t
test -z "$interactive_rebase" && interactive_rebase=implied
diff --git a/git-remote-testgit.py b/git-remote-testgit.py
index 3dc4851cfc..5f3ebd244d 100644
--- a/git-remote-testgit.py
+++ b/git-remote-testgit.py
@@ -22,6 +22,7 @@ except ImportError:
_digest = sha.new
import sys
import os
+import time
sys.path.insert(0, os.getenv("GITPYTHONLIB","."))
from git_remote_helpers.util import die, debug, warn
@@ -204,6 +205,11 @@ def read_one_line(repo):
"""Reads and processes one command.
"""
+ sleepy = os.environ.get("GIT_REMOTE_TESTGIT_SLEEPY")
+ if sleepy:
+ debug("Sleeping %d sec before readline" % int(sleepy))
+ time.sleep(int(sleepy))
+
line = sys.stdin.readline()
cmdline = line
@@ -258,6 +264,7 @@ def main(args):
more = True
+ sys.stdin = os.fdopen(sys.stdin.fileno(), 'r', 0)
while (more):
more = read_one_line(repo)
diff --git a/git-repack.sh b/git-repack.sh
index 624feec26f..757933174e 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -15,6 +15,7 @@ F pass --no-reuse-object to git-pack-objects
n do not run git-update-server-info
q,quiet be quiet
l pass --local to git-pack-objects
+unpack-unreachable= with -A, do not loosen objects older than this
Packing constraints
window= size of the window used for delta compression
window-memory= same as the above, but limit memory size instead of entries count
@@ -33,6 +34,8 @@ do
-a) all_into_one=t ;;
-A) all_into_one=t
unpack_unreachable=--unpack-unreachable ;;
+ --unpack-unreachable)
+ unpack_unreachable="--unpack-unreachable=$2"; shift ;;
-d) remove_redundant=t ;;
-q) GIT_QUIET=t ;;
-f) no_reuse=--no-reuse-delta ;;
@@ -76,7 +79,12 @@ case ",$all_into_one," in
if test -n "$existing" -a -n "$unpack_unreachable" -a \
-n "$remove_redundant"
then
- args="$args $unpack_unreachable"
+ # This may have arbitrary user arguments, so we
+ # have to protect it against whitespace splitting
+ # when it gets run as "pack-objects $args" later.
+ # Fortunately, we know it's an approxidate, so we
+ # can just use dots instead.
+ args="$args $(echo "$unpack_unreachable" | tr ' ' .)"
fi
fi
;;
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 5d8e4e6c89..7b3ae75d7a 100644
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -248,6 +248,10 @@ case $(uname -s) in
find () {
/usr/bin/find "$@"
}
+ # git sees Windows-style pwd
+ pwd () {
+ builtin pwd -W
+ }
is_absolute_path () {
case "$1" in
[/\\]* | [A-Za-z]:*)
diff --git a/git-stash.sh b/git-stash.sh
index fe4ab28b2e..4e2c7f8331 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -199,8 +199,8 @@ save_stash () {
# $ git stash save --blah-blah 2>&1 | head -n 2
# error: unknown option for 'stash save': --blah-blah
# To provide a message, use git stash save -- '--blah-blah'
- eval_gettextln "$("error: unknown option for 'stash save': \$option
- To provide a message, use git stash save -- '\$option'")"
+ eval_gettextln "error: unknown option for 'stash save': \$option
+ To provide a message, use git stash save -- '\$option'"
usage
;;
*)
diff --git a/git-submodule.sh b/git-submodule.sh
index 3d94a14079..64a70d621a 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -101,11 +101,12 @@ module_list()
module_name()
{
# Do we have "submodule.<something>.path = $1" defined in .gitmodules file?
+ sm_path="$1"
re=$(printf '%s\n' "$1" | sed -e 's/[].[^$\\*]/\\&/g')
name=$( git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
sed -n -e 's|^submodule\.\(.*\)\.path '"$re"'$|\1|p' )
test -z "$name" &&
- die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$path'")"
+ die "$(eval_gettext "No submodule mapping found in .gitmodules for path '\$sm_path'")"
echo "$name"
}
@@ -119,7 +120,7 @@ module_name()
#
module_clone()
{
- path=$1
+ sm_path=$1
url=$2
reference="$3"
quiet=
@@ -130,8 +131,8 @@ module_clone()
gitdir=
gitdir_base=
- name=$(module_name "$path" 2>/dev/null)
- test -n "$name" || name="$path"
+ name=$(module_name "$sm_path" 2>/dev/null)
+ test -n "$name" || name="$sm_path"
base_name=$(dirname "$name")
gitdir=$(git rev-parse --git-dir)
@@ -140,17 +141,17 @@ module_clone()
if test -d "$gitdir"
then
- mkdir -p "$path"
+ mkdir -p "$sm_path"
rm -f "$gitdir/index"
else
mkdir -p "$gitdir_base"
git clone $quiet -n ${reference:+"$reference"} \
- --separate-git-dir "$gitdir" "$url" "$path" ||
- die "$(eval_gettext "Clone of '\$url' into submodule path '\$path' failed")"
+ --separate-git-dir "$gitdir" "$url" "$sm_path" ||
+ die "$(eval_gettext "Clone of '\$url' into submodule path '\$sm_path' failed")"
fi
a=$(cd "$gitdir" && pwd)/
- b=$(cd "$path" && pwd)/
+ b=$(cd "$sm_path" && pwd)/
# normalize Windows-style absolute paths to POSIX-style absolute paths
case $a in [a-zA-Z]:/*) a=/${a%%:*}${a#*:} ;; esac
case $b in [a-zA-Z]:/*) b=/${b%%:*}${b#*:} ;; esac
@@ -169,10 +170,10 @@ module_clone()
# Turn each leading "*/" component into "../"
rel=$(echo $b | sed -e 's|[^/][^/]*|..|g')
- echo "gitdir: $rel/$a" >"$path/.git"
+ echo "gitdir: $rel/$a" >"$sm_path/.git"
rel=$(echo $a | sed -e 's|[^/][^/]*|..|g')
- (clear_local_git_env; cd "$path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b")
+ (clear_local_git_env; cd "$sm_path" && GIT_WORK_TREE=. git config core.worktree "$rel/$b")
}
#
@@ -223,14 +224,14 @@ cmd_add()
done
repo=$1
- path=$2
+ sm_path=$2
- if test -z "$path"; then
- path=$(echo "$repo" |
+ if test -z "$sm_path"; then
+ sm_path=$(echo "$repo" |
sed -e 's|/$||' -e 's|:*/*\.git$||' -e 's|.*[/:]||g')
fi
- if test -z "$repo" -o -z "$path"; then
+ if test -z "$repo" -o -z "$sm_path"; then
usage
fi
@@ -251,7 +252,7 @@ cmd_add()
# normalize path:
# multiple //; leading ./; /./; /../; trailing /
- path=$(printf '%s/\n' "$path" |
+ sm_path=$(printf '%s/\n' "$sm_path" |
sed -e '
s|//*|/|g
s|^\(\./\)*||
@@ -261,49 +262,49 @@ cmd_add()
tstart
s|/*$||
')
- git ls-files --error-unmatch "$path" > /dev/null 2>&1 &&
- die "$(eval_gettext "'\$path' already exists in the index")"
+ git ls-files --error-unmatch "$sm_path" > /dev/null 2>&1 &&
+ die "$(eval_gettext "'\$sm_path' already exists in the index")"
- if test -z "$force" && ! git add --dry-run --ignore-missing "$path" > /dev/null 2>&1
+ if test -z "$force" && ! git add --dry-run --ignore-missing "$sm_path" > /dev/null 2>&1
then
eval_gettextln "The following path is ignored by one of your .gitignore files:
-\$path
+\$sm_path
Use -f if you really want to add it." >&2
exit 1
fi
# perhaps the path exists and is already a git repo, else clone it
- if test -e "$path"
+ if test -e "$sm_path"
then
- if test -d "$path"/.git -o -f "$path"/.git
+ if test -d "$sm_path"/.git -o -f "$sm_path"/.git
then
- eval_gettextln "Adding existing repo at '\$path' to the index"
+ eval_gettextln "Adding existing repo at '\$sm_path' to the index"
else
- die "$(eval_gettext "'\$path' already exists and is not a valid git repo")"
+ die "$(eval_gettext "'\$sm_path' already exists and is not a valid git repo")"
fi
else
- module_clone "$path" "$realrepo" "$reference" || exit
+ module_clone "$sm_path" "$realrepo" "$reference" || exit
(
clear_local_git_env
- cd "$path" &&
+ cd "$sm_path" &&
# ash fails to wordsplit ${branch:+-b "$branch"...}
case "$branch" in
'') git checkout -f -q ;;
?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
esac
- ) || die "$(eval_gettext "Unable to checkout submodule '\$path'")"
+ ) || die "$(eval_gettext "Unable to checkout submodule '\$sm_path'")"
fi
- git config submodule."$path".url "$realrepo"
+ git config submodule."$sm_path".url "$realrepo"
- git add $force "$path" ||
- die "$(eval_gettext "Failed to add submodule '\$path'")"
+ git add $force "$sm_path" ||
+ die "$(eval_gettext "Failed to add submodule '\$sm_path'")"
- git config -f .gitmodules submodule."$path".path "$path" &&
- git config -f .gitmodules submodule."$path".url "$repo" &&
+ git config -f .gitmodules submodule."$sm_path".path "$sm_path" &&
+ git config -f .gitmodules submodule."$sm_path".url "$repo" &&
git add --force .gitmodules ||
- die "$(eval_gettext "Failed to register submodule '\$path'")"
+ die "$(eval_gettext "Failed to register submodule '\$sm_path'")"
}
#
@@ -341,23 +342,25 @@ cmd_foreach()
exec 3<&0
module_list |
- while read mode sha1 stage path
+ while read mode sha1 stage sm_path
do
- if test -e "$path"/.git
+ if test -e "$sm_path"/.git
then
- say "$(eval_gettext "Entering '\$prefix\$path'")"
- name=$(module_name "$path")
+ say "$(eval_gettext "Entering '\$prefix\$sm_path'")"
+ name=$(module_name "$sm_path")
(
- prefix="$prefix$path/"
+ prefix="$prefix$sm_path/"
clear_local_git_env
- cd "$path" &&
+ # we make $path available to scripts ...
+ path=$sm_path
+ cd "$sm_path" &&
eval "$@" &&
if test -n "$recursive"
then
cmd_foreach "--recursive" "$@"
fi
) <&3 3<&- ||
- die "$(eval_gettext "Stopping at '\$path'; script returned non-zero status.")"
+ die "$(eval_gettext "Stopping at '\$sm_path'; script returned non-zero status.")"
fi
done
}
@@ -391,15 +394,15 @@ cmd_init()
done
module_list "$@" |
- while read mode sha1 stage path
+ while read mode sha1 stage sm_path
do
# Skip already registered paths
- name=$(module_name "$path") || exit
+ name=$(module_name "$sm_path") || exit
if test -z "$(git config "submodule.$name.url")"
then
url=$(git config -f .gitmodules submodule."$name".url)
test -z "$url" &&
- die "$(eval_gettext "No url found for submodule path '\$path' in .gitmodules")"
+ die "$(eval_gettext "No url found for submodule path '\$sm_path' in .gitmodules")"
# Possibly a url relative to parent
case "$url" in
@@ -408,7 +411,7 @@ cmd_init()
;;
esac
git config submodule."$name".url "$url" ||
- die "$(eval_gettext "Failed to register url for submodule path '\$path'")"
+ die "$(eval_gettext "Failed to register url for submodule path '\$sm_path'")"
fi
# Copy "update" setting when it is not set yet
@@ -416,9 +419,9 @@ cmd_init()
test -z "$upd" ||
test -n "$(git config submodule."$name".update)" ||
git config submodule."$name".update "$upd" ||
- die "$(eval_gettext "Failed to register update mode for submodule path '\$path'")"
+ die "$(eval_gettext "Failed to register update mode for submodule path '\$sm_path'")"
- say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$path'")"
+ say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$sm_path'")"
done
}
@@ -490,14 +493,14 @@ cmd_update()
cloned_modules=
module_list "$@" | {
err=
- while read mode sha1 stage path
+ while read mode sha1 stage sm_path
do
if test "$stage" = U
then
- echo >&2 "Skipping unmerged submodule $path"
+ echo >&2 "Skipping unmerged submodule $sm_path"
continue
fi
- name=$(module_name "$path") || exit
+ name=$(module_name "$sm_path") || exit
url=$(git config submodule."$name".url)
if ! test -z "$update"
then
@@ -508,7 +511,7 @@ cmd_update()
if test "$update_module" = "none"
then
- echo "Skipping submodule '$path'"
+ echo "Skipping submodule '$sm_path'"
continue
fi
@@ -517,20 +520,20 @@ cmd_update()
# Only mention uninitialized submodules when its
# path have been specified
test "$#" != "0" &&
- say "$(eval_gettext "Submodule path '\$path' not initialized
+ say "$(eval_gettext "Submodule path '\$sm_path' not initialized
Maybe you want to use 'update --init'?")"
continue
fi
- if ! test -d "$path"/.git -o -f "$path"/.git
+ if ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
then
- module_clone "$path" "$url" "$reference"|| exit
+ module_clone "$sm_path" "$url" "$reference"|| exit
cloned_modules="$cloned_modules;$name"
subsha1=
else
- subsha1=$(clear_local_git_env; cd "$path" &&
+ subsha1=$(clear_local_git_env; cd "$sm_path" &&
git rev-parse --verify HEAD) ||
- die "$(eval_gettext "Unable to find current revision in submodule path '\$path'")"
+ die "$(eval_gettext "Unable to find current revision in submodule path '\$sm_path'")"
fi
if test "$subsha1" != "$sha1"
@@ -546,10 +549,10 @@ Maybe you want to use 'update --init'?")"
then
# Run fetch only if $sha1 isn't present or it
# is not reachable from a ref.
- (clear_local_git_env; cd "$path" &&
+ (clear_local_git_env; cd "$sm_path" &&
( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
test -z "$rev") || git-fetch)) ||
- die "$(eval_gettext "Unable to fetch in submodule path '\$path'")"
+ die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
fi
# Is this something we just cloned?
@@ -563,24 +566,24 @@ Maybe you want to use 'update --init'?")"
case "$update_module" in
rebase)
command="git rebase"
- die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$path'")"
- say_msg="$(eval_gettext "Submodule path '\$path': rebased into '\$sha1'")"
+ die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$sm_path'")"
+ say_msg="$(eval_gettext "Submodule path '\$sm_path': rebased into '\$sha1'")"
must_die_on_failure=yes
;;
merge)
command="git merge"
- die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$path'")"
- say_msg="$(eval_gettext "Submodule path '\$path': merged in '\$sha1'")"
+ die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$sm_path'")"
+ say_msg="$(eval_gettext "Submodule path '\$sm_path': merged in '\$sha1'")"
must_die_on_failure=yes
;;
*)
command="git checkout $subforce -q"
- die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$path'")"
- say_msg="$(eval_gettext "Submodule path '\$path': checked out '\$sha1'")"
+ die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$sm_path'")"
+ say_msg="$(eval_gettext "Submodule path '\$sm_path': checked out '\$sha1'")"
;;
esac
- if (clear_local_git_env; cd "$path" && $command "$sha1")
+ if (clear_local_git_env; cd "$sm_path" && $command "$sha1")
then
say "$say_msg"
elif test -n "$must_die_on_failure"
@@ -594,11 +597,11 @@ Maybe you want to use 'update --init'?")"
if test -n "$recursive"
then
- (clear_local_git_env; cd "$path" && eval cmd_update "$orig_flags")
+ (clear_local_git_env; cd "$sm_path" && eval cmd_update "$orig_flags")
res=$?
if test $res -gt 0
then
- die_msg="$(eval_gettext "Failed to recurse into submodule path '\$path'")"
+ die_msg="$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")"
if test $res -eq 1
then
err="${err};$die_msg"
@@ -885,30 +888,30 @@ cmd_status()
done
module_list "$@" |
- while read mode sha1 stage path
+ while read mode sha1 stage sm_path
do
- name=$(module_name "$path") || exit
+ name=$(module_name "$sm_path") || exit
url=$(git config submodule."$name".url)
- displaypath="$prefix$path"
+ displaypath="$prefix$sm_path"
if test "$stage" = U
then
say "U$sha1 $displaypath"
continue
fi
- if test -z "$url" || ! test -d "$path"/.git -o -f "$path"/.git
+ if test -z "$url" || ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
then
say "-$sha1 $displaypath"
continue;
fi
- set_name_rev "$path" "$sha1"
- if git diff-files --ignore-submodules=dirty --quiet -- "$path"
+ set_name_rev "$sm_path" "$sha1"
+ if git diff-files --ignore-submodules=dirty --quiet -- "$sm_path"
then
say " $sha1 $displaypath$revname"
else
if test -z "$cached"
then
- sha1=$(clear_local_git_env; cd "$path" && git rev-parse --verify HEAD)
- set_name_rev "$path" "$sha1"
+ sha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD)
+ set_name_rev "$sm_path" "$sha1"
fi
say "+$sha1 $displaypath$revname"
fi
@@ -918,10 +921,10 @@ cmd_status()
(
prefix="$displaypath/"
clear_local_git_env
- cd "$path" &&
+ cd "$sm_path" &&
eval cmd_status "$orig_args"
) ||
- die "$(eval_gettext "Failed to recurse into submodule path '\$path'")"
+ die "$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")"
fi
done
}
@@ -953,9 +956,9 @@ cmd_sync()
done
cd_to_toplevel
module_list "$@" |
- while read mode sha1 stage path
+ while read mode sha1 stage sm_path
do
- name=$(module_name "$path")
+ name=$(module_name "$sm_path")
url=$(git config -f .gitmodules --get submodule."$name".url)
# Possibly a url relative to parent
@@ -970,11 +973,11 @@ cmd_sync()
say "$(eval_gettext "Synchronizing submodule url for '\$name'")"
git config submodule."$name".url "$url"
- if test -e "$path"/.git
+ if test -e "$sm_path"/.git
then
(
clear_local_git_env
- cd "$path"
+ cd "$sm_path"
remote=$(get_default_remote)
git config remote."$remote".url "$url"
)
diff --git a/git-svn.perl b/git-svn.perl
index 4334b95f70..427da9e7a1 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -36,6 +36,11 @@ $ENV{TZ} = 'UTC';
$| = 1; # unbuffer STDOUT
sub fatal (@) { print STDERR "@_\n"; exit 1 }
+
+# All SVN commands do it. Otherwise we may die on SIGPIPE when the remote
+# repository decides to close the connection which we expect to be kept alive.
+$SIG{PIPE} = 'IGNORE';
+
sub _req_svn {
require SVN::Core; # use()-ing this causes segfaults for me... *shrug*
require SVN::Ra;
@@ -2031,6 +2036,7 @@ use IPC::Open3;
use Time::Local;
use Memoize; # core since 5.8.0, Jul 2002
use Memoize::Storable;
+use POSIX qw(:signal_h);
my ($_gc_nr, $_gc_period);
@@ -4059,11 +4065,14 @@ sub rev_map_set {
length $commit == 40 or die "arg3 must be a full SHA1 hexsum\n";
my $db = $self->map_path($uuid);
my $db_lock = "$db.lock";
- my $sig;
+ my $sigmask;
$update_ref ||= 0;
if ($update_ref) {
- $SIG{INT} = $SIG{HUP} = $SIG{TERM} = $SIG{ALRM} = $SIG{PIPE} =
- $SIG{USR1} = $SIG{USR2} = sub { $sig = $_[0] };
+ $sigmask = POSIX::SigSet->new();
+ my $signew = POSIX::SigSet->new(SIGINT, SIGHUP, SIGTERM,
+ SIGALRM, SIGUSR1, SIGUSR2);
+ sigprocmask(SIG_BLOCK, $signew, $sigmask) or
+ croak "Can't block signals: $!";
}
mkfile($db);
@@ -4102,9 +4111,8 @@ sub rev_map_set {
"$db_lock => $db ($!)\n";
delete $LOCKFILES{$db_lock};
if ($update_ref) {
- $SIG{INT} = $SIG{HUP} = $SIG{TERM} = $SIG{ALRM} = $SIG{PIPE} =
- $SIG{USR1} = $SIG{USR2} = 'DEFAULT';
- kill $sig, $$ if defined $sig;
+ sigprocmask(SIG_SETMASK, $sigmask) or
+ croak "Can't restore signal mask: $!";
}
}
@@ -5436,7 +5444,7 @@ BEGIN {
}
sub _auth_providers () {
- [
+ my @rv = (
SVN::Client::get_simple_provider(),
SVN::Client::get_ssl_server_trust_file_provider(),
SVN::Client::get_simple_prompt_provider(
@@ -5452,7 +5460,23 @@ sub _auth_providers () {
\&Git::SVN::Prompt::ssl_server_trust),
SVN::Client::get_username_prompt_provider(
\&Git::SVN::Prompt::username, 2)
- ]
+ );
+
+ # earlier 1.6.x versions would segfault, and <= 1.5.x didn't have
+ # this function
+ if ($SVN::Core::VERSION gt '1.6.12') {
+ my $config = SVN::Core::config_get_config($config_dir);
+ my ($p, @a);
+ # config_get_config returns all config files from
+ # ~/.subversion, auth_get_platform_specific_client_providers
+ # just wants the config "file".
+ @a = ($config->{'config'}, undef);
+ $p = SVN::Core::auth_get_platform_specific_client_providers(@a);
+ # Insert the return value from
+ # auth_get_platform_specific_providers
+ unshift @rv, @$p;
+ }
+ \@rv;
}
sub escape_uri_only {
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 4171de86e3..55e0e9ea38 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -133,6 +133,12 @@ our $default_projects_order = "project";
# (only effective if this variable evaluates to true)
our $export_ok = "++GITWEB_EXPORT_OK++";
+# don't generate age column on the projects list page
+our $omit_age_column = 0;
+
+# don't generate information about owners of repositories
+our $omit_owner=0;
+
# show repository only if this subroutine returns true
# when given the path to the project, for example:
# sub { return -e "$_[0]/git-daemon-export-ok"; }
@@ -1732,20 +1738,29 @@ sub chop_and_escape_str {
# '<span class="mark">foo</span>bar'
sub esc_html_hl_regions {
my ($str, $css_class, @sel) = @_;
- return esc_html($str) unless @sel;
+ my %opts = grep { ref($_) ne 'ARRAY' } @sel;
+ @sel = grep { ref($_) eq 'ARRAY' } @sel;
+ return esc_html($str, %opts) unless @sel;
my $out = '';
my $pos = 0;
for my $s (@sel) {
- $out .= esc_html(substr($str, $pos, $s->[0] - $pos))
- if ($s->[0] - $pos > 0);
- $out .= $cgi->span({-class => $css_class},
- esc_html(substr($str, $s->[0], $s->[1] - $s->[0])));
+ my ($begin, $end) = @$s;
+
+ # Don't create empty <span> elements.
+ next if $end <= $begin;
- $pos = $s->[1];
+ my $escaped = esc_html(substr($str, $begin, $end - $begin),
+ %opts);
+
+ $out .= esc_html(substr($str, $pos, $begin - $pos), %opts)
+ if ($begin - $pos > 0);
+ $out .= $cgi->span({-class => $css_class}, $escaped);
+
+ $pos = $end;
}
- $out .= esc_html(substr($str, $pos))
+ $out .= esc_html(substr($str, $pos), %opts)
if ($pos < length($str));
return $out;
@@ -2421,26 +2436,32 @@ sub format_cc_diff_chunk_header {
}
# process patch (diff) line (not to be used for diff headers),
-# returning class and HTML-formatted (but not wrapped) line
-sub process_diff_line {
- my $line = shift;
- my ($from, $to) = @_;
-
- my $diff_class = diff_line_class($line, $from, $to);
-
- chomp $line;
- $line = untabify($line);
+# returning HTML-formatted (but not wrapped) line.
+# If the line is passed as a reference, it is treated as HTML and not
+# esc_html()'ed.
+sub format_diff_line {
+ my ($line, $diff_class, $from, $to) = @_;
+
+ if (ref($line)) {
+ $line = $$line;
+ } else {
+ chomp $line;
+ $line = untabify($line);
- if ($from && $to && $line =~ m/^\@{2} /) {
- $line = format_unidiff_chunk_header($line, $from, $to);
- return $diff_class, $line;
+ if ($from && $to && $line =~ m/^\@{2} /) {
+ $line = format_unidiff_chunk_header($line, $from, $to);
+ } elsif ($from && $to && $line =~ m/^\@{3}/) {
+ $line = format_cc_diff_chunk_header($line, $from, $to);
+ } else {
+ $line = esc_html($line, -nbsp=>1);
+ }
+ }
- } elsif ($from && $to && $line =~ m/^\@{3}/) {
- $line = format_cc_diff_chunk_header($line, $from, $to);
- return $diff_class, $line;
+ my $diff_classes = "diff";
+ $diff_classes .= " $diff_class" if ($diff_class);
+ $line = "<div class=\"$diff_classes\">$line</div>\n";
- }
- return $diff_class, esc_html($line, -nbsp=>1);
+ return $line;
}
# Generates undef or something like "_snapshot_" or "snapshot (_tbz2_ _zip_)",
@@ -2997,9 +3018,11 @@ sub git_get_projects_list {
}
if (check_export_ok("$projectroot/$path")) {
my $pr = {
- path => $path,
- owner => to_utf8($owner),
+ path => $path
};
+ if ($owner) {
+ $pr->{'owner'} = to_utf8($owner);
+ }
push @list, $pr;
}
}
@@ -4994,10 +5017,186 @@ sub git_difftree_body {
print "</table>\n";
}
-sub print_sidebyside_diff_chunk {
- my @chunk = @_;
+# Print context lines and then rem/add lines in a side-by-side manner.
+sub print_sidebyside_diff_lines {
+ my ($ctx, $rem, $add) = @_;
+
+ # print context block before add/rem block
+ if (@$ctx) {
+ print join '',
+ '<div class="chunk_block ctx">',
+ '<div class="old">',
+ @$ctx,
+ '</div>',
+ '<div class="new">',
+ @$ctx,
+ '</div>',
+ '</div>';
+ }
+
+ if (!@$add) {
+ # pure removal
+ print join '',
+ '<div class="chunk_block rem">',
+ '<div class="old">',
+ @$rem,
+ '</div>',
+ '</div>';
+ } elsif (!@$rem) {
+ # pure addition
+ print join '',
+ '<div class="chunk_block add">',
+ '<div class="new">',
+ @$add,
+ '</div>',
+ '</div>';
+ } else {
+ print join '',
+ '<div class="chunk_block chg">',
+ '<div class="old">',
+ @$rem,
+ '</div>',
+ '<div class="new">',
+ @$add,
+ '</div>',
+ '</div>';
+ }
+}
+
+# Print context lines and then rem/add lines in inline manner.
+sub print_inline_diff_lines {
+ my ($ctx, $rem, $add) = @_;
+
+ print @$ctx, @$rem, @$add;
+}
+
+# Format removed and added line, mark changed part and HTML-format them.
+# Implementation is based on contrib/diff-highlight
+sub format_rem_add_lines_pair {
+ my ($rem, $add, $num_parents) = @_;
+
+ # We need to untabify lines before split()'ing them;
+ # otherwise offsets would be invalid.
+ chomp $rem;
+ chomp $add;
+ $rem = untabify($rem);
+ $add = untabify($add);
+
+ my @rem = split(//, $rem);
+ my @add = split(//, $add);
+ my ($esc_rem, $esc_add);
+ # Ignore leading +/- characters for each parent.
+ my ($prefix_len, $suffix_len) = ($num_parents, 0);
+ my ($prefix_has_nonspace, $suffix_has_nonspace);
+
+ my $shorter = (@rem < @add) ? @rem : @add;
+ while ($prefix_len < $shorter) {
+ last if ($rem[$prefix_len] ne $add[$prefix_len]);
+
+ $prefix_has_nonspace = 1 if ($rem[$prefix_len] !~ /\s/);
+ $prefix_len++;
+ }
+
+ while ($prefix_len + $suffix_len < $shorter) {
+ last if ($rem[-1 - $suffix_len] ne $add[-1 - $suffix_len]);
+
+ $suffix_has_nonspace = 1 if ($rem[-1 - $suffix_len] !~ /\s/);
+ $suffix_len++;
+ }
+
+ # Mark lines that are different from each other, but have some common
+ # part that isn't whitespace. If lines are completely different, don't
+ # mark them because that would make output unreadable, especially if
+ # diff consists of multiple lines.
+ if ($prefix_has_nonspace || $suffix_has_nonspace) {
+ $esc_rem = esc_html_hl_regions($rem, 'marked',
+ [$prefix_len, @rem - $suffix_len], -nbsp=>1);
+ $esc_add = esc_html_hl_regions($add, 'marked',
+ [$prefix_len, @add - $suffix_len], -nbsp=>1);
+ } else {
+ $esc_rem = esc_html($rem, -nbsp=>1);
+ $esc_add = esc_html($add, -nbsp=>1);
+ }
+
+ return format_diff_line(\$esc_rem, 'rem'),
+ format_diff_line(\$esc_add, 'add');
+}
+
+# HTML-format diff context, removed and added lines.
+sub format_ctx_rem_add_lines {
+ my ($ctx, $rem, $add, $num_parents) = @_;
+ my (@new_ctx, @new_rem, @new_add);
+ my $can_highlight = 0;
+ my $is_combined = ($num_parents > 1);
+
+ # Highlight if every removed line has a corresponding added line.
+ if (@$add > 0 && @$add == @$rem) {
+ $can_highlight = 1;
+
+ # Highlight lines in combined diff only if the chunk contains
+ # diff between the same version, e.g.
+ #
+ # - a
+ # - b
+ # + c
+ # + d
+ #
+ # Otherwise the highlightling would be confusing.
+ if ($is_combined) {
+ for (my $i = 0; $i < @$add; $i++) {
+ my $prefix_rem = substr($rem->[$i], 0, $num_parents);
+ my $prefix_add = substr($add->[$i], 0, $num_parents);
+
+ $prefix_rem =~ s/-/+/g;
+
+ if ($prefix_rem ne $prefix_add) {
+ $can_highlight = 0;
+ last;
+ }
+ }
+ }
+ }
+
+ if ($can_highlight) {
+ for (my $i = 0; $i < @$add; $i++) {
+ my ($line_rem, $line_add) = format_rem_add_lines_pair(
+ $rem->[$i], $add->[$i], $num_parents);
+ push @new_rem, $line_rem;
+ push @new_add, $line_add;
+ }
+ } else {
+ @new_rem = map { format_diff_line($_, 'rem') } @$rem;
+ @new_add = map { format_diff_line($_, 'add') } @$add;
+ }
+
+ @new_ctx = map { format_diff_line($_, 'ctx') } @$ctx;
+
+ return (\@new_ctx, \@new_rem, \@new_add);
+}
+
+# Print context lines and then rem/add lines.
+sub print_diff_lines {
+ my ($ctx, $rem, $add, $diff_style, $num_parents) = @_;
+ my $is_combined = $num_parents > 1;
+
+ ($ctx, $rem, $add) = format_ctx_rem_add_lines($ctx, $rem, $add,
+ $num_parents);
+
+ if ($diff_style eq 'sidebyside' && !$is_combined) {
+ print_sidebyside_diff_lines($ctx, $rem, $add);
+ } else {
+ # default 'inline' style and unknown styles
+ print_inline_diff_lines($ctx, $rem, $add);
+ }
+}
+
+sub print_diff_chunk {
+ my ($diff_style, $num_parents, $from, $to, @chunk) = @_;
my (@ctx, @rem, @add);
+ # The class of the previous line.
+ my $prev_class = '';
+
return unless @chunk;
# incomplete last line might be among removed or added lines,
@@ -5016,55 +5215,19 @@ sub print_sidebyside_diff_chunk {
# print chunk headers
if ($class && $class eq 'chunk_header') {
- print $line;
+ print format_diff_line($line, $class, $from, $to);
next;
}
- ## print from accumulator when type of class of lines change
- # empty contents block on start rem/add block, or end of chunk
- if (@ctx && (!$class || $class eq 'rem' || $class eq 'add')) {
- print join '',
- '<div class="chunk_block ctx">',
- '<div class="old">',
- @ctx,
- '</div>',
- '<div class="new">',
- @ctx,
- '</div>',
- '</div>';
- @ctx = ();
- }
- # empty add/rem block on start context block, or end of chunk
- if ((@rem || @add) && (!$class || $class eq 'ctx')) {
- if (!@add) {
- # pure removal
- print join '',
- '<div class="chunk_block rem">',
- '<div class="old">',
- @rem,
- '</div>',
- '</div>';
- } elsif (!@rem) {
- # pure addition
- print join '',
- '<div class="chunk_block add">',
- '<div class="new">',
- @add,
- '</div>',
- '</div>';
- } else {
- # assume that it is change
- print join '',
- '<div class="chunk_block chg">',
- '<div class="old">',
- @rem,
- '</div>',
- '<div class="new">',
- @add,
- '</div>',
- '</div>';
- }
- @rem = @add = ();
+ ## print from accumulator when have some add/rem lines or end
+ # of chunk (flush context lines), or when have add and rem
+ # lines and new block is reached (otherwise add/rem lines could
+ # be reordered)
+ if (!$class || ((@rem || @add) && $class eq 'ctx') ||
+ (@rem && @add && $class ne $prev_class)) {
+ print_diff_lines(\@ctx, \@rem, \@add,
+ $diff_style, $num_parents);
+ @ctx = @rem = @add = ();
}
## adding lines to accumulator
@@ -5080,6 +5243,8 @@ sub print_sidebyside_diff_chunk {
if ($class eq 'ctx') {
push @ctx, $line;
}
+
+ $prev_class = $class;
}
}
@@ -5201,27 +5366,19 @@ sub git_patchset_body {
next PATCH if ($patch_line =~ m/^diff /);
- my ($class, $line) = process_diff_line($patch_line, \%from, \%to);
- my $diff_classes = "diff";
- $diff_classes .= " $class" if ($class);
- $line = "<div class=\"$diff_classes\">$line</div>\n";
+ my $class = diff_line_class($patch_line, \%from, \%to);
- if ($diff_style eq 'sidebyside' && !$is_combined) {
- if ($class eq 'chunk_header') {
- print_sidebyside_diff_chunk(@chunk);
- @chunk = ( [ $class, $line ] );
- } else {
- push @chunk, [ $class, $line ];
- }
- } else {
- # default 'inline' style and unknown styles
- print $line;
+ if ($class eq 'chunk_header') {
+ print_diff_chunk($diff_style, scalar @hash_parents, \%from, \%to, @chunk);
+ @chunk = ();
}
+
+ push @chunk, [ $class, $patch_line ];
}
} continue {
if (@chunk) {
- print_sidebyside_diff_chunk(@chunk);
+ print_diff_chunk($diff_style, scalar @hash_parents, \%from, \%to, @chunk);
@chunk = ();
}
print "</div>\n"; # class="patch"
@@ -5461,11 +5618,15 @@ sub git_project_list_rows {
? esc_html_match_hl_chopped($pr->{'descr_long'},
$pr->{'descr'}, $search_regexp)
: esc_html($pr->{'descr'})) .
- "</td>\n" .
- "<td><i>" . chop_and_escape_str($pr->{'owner'}, 15) . "</i></td>\n";
- print "<td class=\"". age_class($pr->{'age'}) . "\">" .
- (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "</td>\n" .
- "<td class=\"link\">" .
+ "</td>\n";
+ unless ($omit_owner) {
+ print "<td><i>" . chop_and_escape_str($pr->{'owner'}, 15) . "</i></td>\n";
+ }
+ unless ($omit_age_column) {
+ print "<td class=\"". age_class($pr->{'age'}) . "\">" .
+ (defined $pr->{'age_string'} ? $pr->{'age_string'} : "No commits") . "</td>\n";
+ }
+ print"<td class=\"link\">" .
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"summary")}, "summary") . " | " .
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"shortlog")}, "shortlog") . " | " .
$cgi->a({-href => href(project=>$pr->{'path'}, action=>"log")}, "log") . " | " .
@@ -5496,7 +5657,10 @@ sub git_project_list_body {
'tagfilter' => $tagfilter)
if ($tagfilter || $search_regexp);
# fill the rest
- @projects = fill_project_list_info(\@projects);
+ my @all_fields = ('descr', 'descr_long', 'ctags', 'category');
+ push @all_fields, ('age', 'age_string') unless($omit_age_column);
+ push @all_fields, 'owner' unless($omit_owner);
+ @projects = fill_project_list_info(\@projects, @all_fields);
$order ||= $default_projects_order;
$from = 0 unless defined $from;
@@ -5527,8 +5691,8 @@ sub git_project_list_body {
}
print_sort_th('project', $order, 'Project');
print_sort_th('descr', $order, 'Description');
- print_sort_th('owner', $order, 'Owner');
- print_sort_th('age', $order, 'Last Change');
+ print_sort_th('owner', $order, 'Owner') unless $omit_owner;
+ print_sort_th('age', $order, 'Last Change') unless $omit_age_column;
print "<th></th>\n" . # for links
"</tr>\n";
}
@@ -6281,8 +6445,10 @@ sub git_summary {
print "<div class=\"title\">&nbsp;</div>\n";
print "<table class=\"projects_list\">\n" .
- "<tr id=\"metadata_desc\"><td>description</td><td>" . esc_html($descr) . "</td></tr>\n" .
- "<tr id=\"metadata_owner\"><td>owner</td><td>" . esc_html($owner) . "</td></tr>\n";
+ "<tr id=\"metadata_desc\"><td>description</td><td>" . esc_html($descr) . "</td></tr>\n";
+ unless ($omit_owner) {
+ print "<tr id=\"metadata_owner\"><td>owner</td><td>" . esc_html($owner) . "</td></tr>\n";
+ }
if (defined $cd{'rfc2822'}) {
print "<tr id=\"metadata_lchange\"><td>last change</td>" .
"<td>".format_timestamp_html(\%cd)."</td></tr>\n";
diff --git a/gitweb/static/gitweb.css b/gitweb/static/gitweb.css
index c530355a7c..cb86d2d029 100644
--- a/gitweb/static/gitweb.css
+++ b/gitweb/static/gitweb.css
@@ -438,6 +438,10 @@ div.diff.add {
color: #008800;
}
+div.diff.add span.marked {
+ background-color: #aaffaa;
+}
+
div.diff.from_file a.path,
div.diff.from_file {
color: #aa0000;
@@ -447,6 +451,10 @@ div.diff.rem {
color: #cc0000;
}
+div.diff.rem span.marked {
+ background-color: #ffaaaa;
+}
+
div.diff.chunk_header a,
div.diff.chunk_header {
color: #990099;
diff --git a/http.c b/http.c
index f3f83d70cd..2ec37891f3 100644
--- a/http.c
+++ b/http.c
@@ -210,14 +210,23 @@ static int http_options(const char *var, const char *value, void *cb)
static void init_curl_http_auth(CURL *result)
{
- if (http_auth.username) {
- struct strbuf up = STRBUF_INIT;
- credential_fill(&http_auth);
+ if (!http_auth.username)
+ return;
+
+ credential_fill(&http_auth);
+
+#if LIBCURL_VERSION_NUM >= 0x071301
+ curl_easy_setopt(result, CURLOPT_USERNAME, http_auth.username);
+ curl_easy_setopt(result, CURLOPT_PASSWORD, http_auth.password);
+#else
+ {
+ static struct strbuf up = STRBUF_INIT;
+ strbuf_reset(&up);
strbuf_addf(&up, "%s:%s",
http_auth.username, http_auth.password);
- curl_easy_setopt(result, CURLOPT_USERPWD,
- strbuf_detach(&up, NULL));
+ curl_easy_setopt(result, CURLOPT_USERPWD, up.buf);
}
+#endif
}
static int has_cert_password(void)
@@ -494,6 +503,8 @@ struct active_request_slot *get_active_slot(void)
curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, NULL);
curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0);
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
+ if (http_auth.password)
+ init_curl_http_auth(slot->curl);
return slot;
}
diff --git a/log-tree.c b/log-tree.c
index cea8756866..34c49e7b33 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -711,14 +711,15 @@ int log_tree_diff_flush(struct rev_info *opt)
opt->verbose_header &&
opt->commit_format != CMIT_FMT_ONELINE) {
int pch = DIFF_FORMAT_DIFFSTAT | DIFF_FORMAT_PATCH;
- if ((pch & opt->diffopt.output_format) == pch)
- printf("---");
if (opt->diffopt.output_prefix) {
struct strbuf *msg = NULL;
msg = opt->diffopt.output_prefix(&opt->diffopt,
opt->diffopt.output_prefix_data);
fwrite(msg->buf, msg->len, 1, stdout);
}
+ if ((pch & opt->diffopt.output_format) == pch) {
+ printf("---");
+ }
putchar('\n');
}
}
diff --git a/mergesort.c b/mergesort.c
new file mode 100644
index 0000000000..e5fdf2ee4a
--- /dev/null
+++ b/mergesort.c
@@ -0,0 +1,73 @@
+#include "cache.h"
+#include "mergesort.h"
+
+struct mergesort_sublist {
+ void *ptr;
+ unsigned long len;
+};
+
+static void *get_nth_next(void *list, unsigned long n,
+ void *(*get_next_fn)(const void *))
+{
+ while (n-- && list)
+ list = get_next_fn(list);
+ return list;
+}
+
+static void *pop_item(struct mergesort_sublist *l,
+ void *(*get_next_fn)(const void *))
+{
+ void *p = l->ptr;
+ l->ptr = get_next_fn(l->ptr);
+ l->len = l->ptr ? (l->len - 1) : 0;
+ return p;
+}
+
+void *llist_mergesort(void *list,
+ void *(*get_next_fn)(const void *),
+ void (*set_next_fn)(void *, void *),
+ int (*compare_fn)(const void *, const void *))
+{
+ unsigned long l;
+
+ if (!list)
+ return NULL;
+ for (l = 1; ; l *= 2) {
+ void *curr;
+ struct mergesort_sublist p, q;
+
+ p.ptr = list;
+ q.ptr = get_nth_next(p.ptr, l, get_next_fn);
+ if (!q.ptr)
+ break;
+ p.len = q.len = l;
+
+ if (compare_fn(p.ptr, q.ptr) > 0)
+ list = curr = pop_item(&q, get_next_fn);
+ else
+ list = curr = pop_item(&p, get_next_fn);
+
+ while (p.ptr) {
+ while (p.len || q.len) {
+ void *prev = curr;
+
+ if (!p.len)
+ curr = pop_item(&q, get_next_fn);
+ else if (!q.len)
+ curr = pop_item(&p, get_next_fn);
+ else if (compare_fn(p.ptr, q.ptr) > 0)
+ curr = pop_item(&q, get_next_fn);
+ else
+ curr = pop_item(&p, get_next_fn);
+ set_next_fn(prev, curr);
+ }
+ p.ptr = q.ptr;
+ p.len = l;
+ q.ptr = get_nth_next(p.ptr, l, get_next_fn);
+ q.len = q.ptr ? l : 0;
+
+ }
+ set_next_fn(curr, NULL);
+ }
+ return list;
+}
diff --git a/mergesort.h b/mergesort.h
new file mode 100644
index 0000000000..644cff1f96
--- /dev/null
+++ b/mergesort.h
@@ -0,0 +1,17 @@
+#ifndef MERGESORT_H
+#define MERGESORT_H
+
+/*
+ * Sort linked list in place.
+ * - get_next_fn() returns the next element given an element of a linked list.
+ * - set_next_fn() takes two elements A and B, and makes B the "next" element
+ * of A on the list.
+ * - compare_fn() takes two elements A and B, and returns negative, 0, positive
+ * as the same sign as "subtracting" B from A.
+ */
+void *llist_mergesort(void *list,
+ void *(*get_next_fn)(const void *),
+ void (*set_next_fn)(void *, void *),
+ int (*compare_fn)(const void *, const void *));
+
+#endif
diff --git a/object.c b/object.c
index 0498b18d45..49a864ce54 100644
--- a/object.c
+++ b/object.c
@@ -286,3 +286,14 @@ void object_array_remove_duplicates(struct object_array *array)
array->nr = dst;
}
}
+
+void clear_object_flags(unsigned flags)
+{
+ int i;
+
+ for (i=0; i < obj_hash_size; i++) {
+ struct object *obj = obj_hash[i];
+ if (obj)
+ obj->flags &= ~flags;
+ }
+}
diff --git a/object.h b/object.h
index b6618d92bf..6a97b6ba1a 100644
--- a/object.h
+++ b/object.h
@@ -76,4 +76,6 @@ void add_object_array(struct object *obj, const char *name, struct object_array
void add_object_array_with_mode(struct object *obj, const char *name, struct object_array *array, unsigned mode);
void object_array_remove_duplicates(struct object_array *);
+void clear_object_flags(unsigned flags);
+
#endif /* OBJECT_H */
diff --git a/po/TEAMS b/po/TEAMS
index 7fcf1ec119..4515f578c8 100644
--- a/po/TEAMS
+++ b/po/TEAMS
@@ -1,6 +1,14 @@
Core Git translation language teams
(please keep the list sorted alphabetically on language field)
+Language: da (Danish)
+Repository: https://github.com/git-da/git-po/
+Leader: Byrial Jensen <byrial@vip.cybercity.dk>
+
+Language: de (German)
+Repository: https://github.com/ralfth/git-po-de
+Leader: Ralf Thielow <ralf.thielow@googlemail.com>
+
Language: is (Icelandic)
Leader: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
diff --git a/po/da.po b/po/da.po
new file mode 100644
index 0000000000..20a88ea529
--- /dev/null
+++ b/po/da.po
@@ -0,0 +1,3503 @@
+# Danish translations for Git.
+# This file is distributed under the same license as the PACKAGE package.
+# Byrial Jensen <byrial@vip.cybercity.dk>, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Git\n"
+"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
+"POT-Creation-Date: 2012-03-16 20:18+0800\n"
+"PO-Revision-Date: 2012-04-10 18:41+0200\n"
+"Last-Translator: Byrial Jensen <byrial@vip.cybercity.dk>\n"
+"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
+"Language: da\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: advice.c:34
+#, c-format
+msgid "hint: %.*s\n"
+msgstr ""
+
+#.
+#. * Message used both when 'git commit' fails and when
+#. * other commands doing a merge do.
+#.
+#: advice.c:64
+msgid ""
+"Fix them up in the work tree,\n"
+"and then use 'git add/rm <file>' as\n"
+"appropriate to mark resolution and make a commit,\n"
+"or use 'git commit -a'."
+msgstr ""
+
+#: commit.c:47
+#, c-format
+msgid "could not parse %s"
+msgstr ""
+
+#: commit.c:49
+#, c-format
+msgid "%s %s is not a commit!"
+msgstr ""
+
+#: compat/obstack.c:406 compat/obstack.c:408
+msgid "memory exhausted"
+msgstr ""
+
+#: connected.c:39
+msgid "Could not run 'git rev-list'"
+msgstr ""
+
+#: connected.c:48
+#, c-format
+msgid "failed write to rev-list: %s"
+msgstr ""
+
+#: connected.c:56
+#, c-format
+msgid "failed to close rev-list's stdin: %s"
+msgstr ""
+
+#: diff.c:105
+#, c-format
+msgid " Failed to parse dirstat cut-off percentage '%.*s'\n"
+msgstr ""
+
+#: diff.c:110
+#, c-format
+msgid " Unknown dirstat parameter '%.*s'\n"
+msgstr ""
+
+#: diff.c:210
+#, c-format
+msgid ""
+"Found errors in 'diff.dirstat' config variable:\n"
+"%s"
+msgstr ""
+
+#: diff.c:1336
+msgid " 0 files changed\n"
+msgstr ""
+
+#: diff.c:1340
+#, c-format
+msgid " %d file changed"
+msgid_plural " %d files changed"
+msgstr[0] ""
+msgstr[1] ""
+
+#: diff.c:1357
+#, c-format
+msgid ", %d insertion(+)"
+msgid_plural ", %d insertions(+)"
+msgstr[0] ""
+msgstr[1] ""
+
+#: diff.c:1368
+#, c-format
+msgid ", %d deletion(-)"
+msgid_plural ", %d deletions(-)"
+msgstr[0] ""
+msgstr[1] ""
+
+#: diff.c:3424
+#, c-format
+msgid ""
+"Failed to parse --dirstat/-X option parameter:\n"
+"%s"
+msgstr ""
+
+#: gpg-interface.c:59
+msgid "could not run gpg."
+msgstr ""
+
+#: gpg-interface.c:71
+msgid "gpg did not accept the data"
+msgstr ""
+
+#: gpg-interface.c:82
+msgid "gpg failed to sign the data"
+msgstr ""
+
+#: grep.c:1280
+#, c-format
+msgid "'%s': unable to read %s"
+msgstr ""
+
+#: grep.c:1297
+#, c-format
+msgid "'%s': %s"
+msgstr ""
+
+#: grep.c:1308
+#, c-format
+msgid "'%s': short read %s"
+msgstr ""
+
+#: help.c:287
+#, c-format
+msgid ""
+"'%s' appears to be a git command, but we were not\n"
+"able to execute it. Maybe git-%s is broken?"
+msgstr ""
+
+#: remote.c:1607
+#, c-format
+msgid "Your branch is ahead of '%s' by %d commit.\n"
+msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: remote.c:1613
+#, c-format
+msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
+msgid_plural ""
+"Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: remote.c:1621
+#, c-format
+msgid ""
+"Your branch and '%s' have diverged,\n"
+"and have %d and %d different commit each, respectively.\n"
+msgid_plural ""
+"Your branch and '%s' have diverged,\n"
+"and have %d and %d different commits each, respectively.\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: sequencer.c:120 builtin/merge.c:864 builtin/merge.c:985
+#: builtin/merge.c:1095 builtin/merge.c:1105
+#, c-format
+msgid "Could not open '%s' for writing"
+msgstr ""
+
+#: sequencer.c:122 builtin/merge.c:334 builtin/merge.c:867
+#: builtin/merge.c:1097 builtin/merge.c:1110
+#, c-format
+msgid "Could not write to '%s'"
+msgstr ""
+
+#: sequencer.c:143
+msgid ""
+"after resolving the conflicts, mark the corrected paths\n"
+"with 'git add <paths>' or 'git rm <paths>'"
+msgstr ""
+
+#: sequencer.c:146
+msgid ""
+"after resolving the conflicts, mark the corrected paths\n"
+"with 'git add <paths>' or 'git rm <paths>'\n"
+"and commit the result with 'git commit'"
+msgstr ""
+
+#: sequencer.c:159 sequencer.c:685 sequencer.c:768
+#, c-format
+msgid "Could not write to %s"
+msgstr ""
+
+#: sequencer.c:162
+#, c-format
+msgid "Error wrapping up %s"
+msgstr ""
+
+#: sequencer.c:177
+msgid "Your local changes would be overwritten by cherry-pick."
+msgstr ""
+
+#: sequencer.c:179
+msgid "Your local changes would be overwritten by revert."
+msgstr ""
+
+#: sequencer.c:182
+msgid "Commit your changes or stash them to proceed."
+msgstr ""
+
+#. TRANSLATORS: %s will be "revert" or "cherry-pick"
+#: sequencer.c:232
+#, c-format
+msgid "%s: Unable to write new index file"
+msgstr ""
+
+#: sequencer.c:298
+msgid "Your index file is unmerged."
+msgstr ""
+
+#: sequencer.c:301
+msgid "You do not have a valid HEAD"
+msgstr ""
+
+#: sequencer.c:316
+#, c-format
+msgid "Commit %s is a merge but no -m option was given."
+msgstr ""
+
+#: sequencer.c:324
+#, c-format
+msgid "Commit %s does not have parent %d"
+msgstr ""
+
+#: sequencer.c:328
+#, c-format
+msgid "Mainline was specified but commit %s is not a merge."
+msgstr ""
+
+#. TRANSLATORS: The first %s will be "revert" or
+#. "cherry-pick", the second %s a SHA1
+#: sequencer.c:339
+#, c-format
+msgid "%s: cannot parse parent commit %s"
+msgstr ""
+
+#: sequencer.c:343
+#, c-format
+msgid "Cannot get commit message for %s"
+msgstr ""
+
+#: sequencer.c:427
+#, c-format
+msgid "could not revert %s... %s"
+msgstr ""
+
+#: sequencer.c:428
+#, c-format
+msgid "could not apply %s... %s"
+msgstr ""
+
+#: sequencer.c:450 sequencer.c:909 builtin/log.c:288 builtin/log.c:713
+#: builtin/log.c:1329 builtin/log.c:1548 builtin/merge.c:348
+#: builtin/shortlog.c:181
+msgid "revision walk setup failed"
+msgstr ""
+
+#: sequencer.c:453
+msgid "empty commit set passed"
+msgstr ""
+
+#: sequencer.c:461
+#, c-format
+msgid "git %s: failed to read the index"
+msgstr ""
+
+#: sequencer.c:466
+#, c-format
+msgid "git %s: failed to refresh the index"
+msgstr ""
+
+#: sequencer.c:551
+#, c-format
+msgid "Cannot %s during a %s"
+msgstr ""
+
+#: sequencer.c:573
+#, c-format
+msgid "Could not parse line %d."
+msgstr ""
+
+#: sequencer.c:578
+msgid "No commits parsed."
+msgstr ""
+
+#: sequencer.c:591
+#, c-format
+msgid "Could not open %s"
+msgstr ""
+
+#: sequencer.c:595
+#, c-format
+msgid "Could not read %s."
+msgstr ""
+
+#: sequencer.c:602
+#, c-format
+msgid "Unusable instruction sheet: %s"
+msgstr ""
+
+#: sequencer.c:630
+#, c-format
+msgid "Invalid key: %s"
+msgstr ""
+
+#: sequencer.c:633
+#, c-format
+msgid "Invalid value for %s: %s"
+msgstr ""
+
+#: sequencer.c:645
+#, c-format
+msgid "Malformed options sheet: %s"
+msgstr ""
+
+#: sequencer.c:666
+msgid "a cherry-pick or revert is already in progress"
+msgstr ""
+
+#: sequencer.c:667
+msgid "try \"git cherry-pick (--continue | --quit | --abort)\""
+msgstr ""
+
+#: sequencer.c:671
+#, c-format
+msgid "Could not create sequencer directory %s"
+msgstr ""
+
+#: sequencer.c:687 sequencer.c:772
+#, c-format
+msgid "Error wrapping up %s."
+msgstr ""
+
+#: sequencer.c:706 sequencer.c:840
+msgid "no cherry-pick or revert in progress"
+msgstr ""
+
+#: sequencer.c:708
+msgid "cannot resolve HEAD"
+msgstr ""
+
+#: sequencer.c:710
+msgid "cannot abort from a branch yet to be born"
+msgstr ""
+
+#: sequencer.c:732
+#, c-format
+msgid "cannot open %s: %s"
+msgstr ""
+
+#: sequencer.c:735
+#, c-format
+msgid "cannot read %s: %s"
+msgstr ""
+
+#: sequencer.c:736
+msgid "unexpected end of file"
+msgstr ""
+
+#: sequencer.c:742
+#, c-format
+msgid "stored pre-cherry-pick HEAD file '%s' is corrupt"
+msgstr ""
+
+#: sequencer.c:765
+#, c-format
+msgid "Could not format %s."
+msgstr ""
+
+#: sequencer.c:927
+msgid "Can't revert as initial commit"
+msgstr ""
+
+#: sequencer.c:928
+msgid "Can't cherry-pick into empty head"
+msgstr ""
+
+#: wt-status.c:134
+msgid "Unmerged paths:"
+msgstr ""
+
+#: wt-status.c:140 wt-status.c:157
+#, c-format
+msgid " (use \"git reset %s <file>...\" to unstage)"
+msgstr ""
+
+#: wt-status.c:142 wt-status.c:159
+msgid " (use \"git rm --cached <file>...\" to unstage)"
+msgstr ""
+
+#: wt-status.c:143
+msgid " (use \"git add/rm <file>...\" as appropriate to mark resolution)"
+msgstr ""
+
+#: wt-status.c:151
+msgid "Changes to be committed:"
+msgstr ""
+
+#: wt-status.c:169
+msgid "Changes not staged for commit:"
+msgstr ""
+
+#: wt-status.c:173
+msgid " (use \"git add <file>...\" to update what will be committed)"
+msgstr ""
+
+#: wt-status.c:175
+msgid " (use \"git add/rm <file>...\" to update what will be committed)"
+msgstr ""
+
+#: wt-status.c:176
+msgid ""
+" (use \"git checkout -- <file>...\" to discard changes in working directory)"
+msgstr ""
+
+#: wt-status.c:178
+msgid " (commit or discard the untracked or modified content in submodules)"
+msgstr ""
+
+#: wt-status.c:187
+#, c-format
+msgid "%s files:"
+msgstr ""
+
+#: wt-status.c:190
+#, c-format
+msgid " (use \"git %s <file>...\" to include in what will be committed)"
+msgstr ""
+
+#: wt-status.c:207
+msgid "bug"
+msgstr ""
+
+#: wt-status.c:212
+msgid "both deleted:"
+msgstr ""
+
+#: wt-status.c:213
+msgid "added by us:"
+msgstr ""
+
+#: wt-status.c:214
+msgid "deleted by them:"
+msgstr ""
+
+#: wt-status.c:215
+msgid "added by them:"
+msgstr ""
+
+#: wt-status.c:216
+msgid "deleted by us:"
+msgstr ""
+
+#: wt-status.c:217
+msgid "both added:"
+msgstr ""
+
+#: wt-status.c:218
+msgid "both modified:"
+msgstr ""
+
+#: wt-status.c:248
+msgid "new commits, "
+msgstr ""
+
+#: wt-status.c:250
+msgid "modified content, "
+msgstr ""
+
+#: wt-status.c:252
+msgid "untracked content, "
+msgstr ""
+
+#: wt-status.c:266
+#, c-format
+msgid "new file: %s"
+msgstr ""
+
+#: wt-status.c:269
+#, c-format
+msgid "copied: %s -> %s"
+msgstr ""
+
+#: wt-status.c:272
+#, c-format
+msgid "deleted: %s"
+msgstr ""
+
+#: wt-status.c:275
+#, c-format
+msgid "modified: %s"
+msgstr ""
+
+#: wt-status.c:278
+#, c-format
+msgid "renamed: %s -> %s"
+msgstr ""
+
+#: wt-status.c:281
+#, c-format
+msgid "typechange: %s"
+msgstr ""
+
+#: wt-status.c:284
+#, c-format
+msgid "unknown: %s"
+msgstr ""
+
+#: wt-status.c:287
+#, c-format
+msgid "unmerged: %s"
+msgstr ""
+
+#: wt-status.c:290
+#, c-format
+msgid "bug: unhandled diff status %c"
+msgstr ""
+
+#: wt-status.c:713
+msgid "On branch "
+msgstr ""
+
+#: wt-status.c:720
+msgid "Not currently on any branch."
+msgstr ""
+
+#: wt-status.c:731
+msgid "Initial commit"
+msgstr ""
+
+#: wt-status.c:745
+msgid "Untracked"
+msgstr ""
+
+#: wt-status.c:747
+msgid "Ignored"
+msgstr ""
+
+#: wt-status.c:749
+#, c-format
+msgid "Untracked files not listed%s"
+msgstr ""
+
+#: wt-status.c:751
+msgid " (use -u option to show untracked files)"
+msgstr ""
+
+#: wt-status.c:757
+msgid "No changes"
+msgstr ""
+
+#: wt-status.c:761
+#, c-format
+msgid "no changes added to commit%s\n"
+msgstr ""
+
+#: wt-status.c:763
+msgid " (use \"git add\" and/or \"git commit -a\")"
+msgstr ""
+
+#: wt-status.c:765
+#, c-format
+msgid "nothing added to commit but untracked files present%s\n"
+msgstr ""
+
+#: wt-status.c:767
+msgid " (use \"git add\" to track)"
+msgstr ""
+
+#: wt-status.c:769 wt-status.c:772 wt-status.c:775
+#, c-format
+msgid "nothing to commit%s\n"
+msgstr ""
+
+#: wt-status.c:770
+msgid " (create/copy files and use \"git add\" to track)"
+msgstr ""
+
+#: wt-status.c:773
+msgid " (use -u to show untracked files)"
+msgstr ""
+
+#: wt-status.c:776
+msgid " (working directory clean)"
+msgstr ""
+
+#: wt-status.c:884
+msgid "HEAD (no branch)"
+msgstr ""
+
+#: wt-status.c:890
+msgid "Initial commit on "
+msgstr ""
+
+#: wt-status.c:905
+msgid "behind "
+msgstr ""
+
+#: wt-status.c:908 wt-status.c:911
+msgid "ahead "
+msgstr ""
+
+#: wt-status.c:913
+msgid ", behind "
+msgstr ""
+
+#: builtin/add.c:62
+#, c-format
+msgid "unexpected diff status %c"
+msgstr ""
+
+#: builtin/add.c:67 builtin/commit.c:298
+msgid "updating files failed"
+msgstr ""
+
+#: builtin/add.c:77
+#, c-format
+msgid "remove '%s'\n"
+msgstr ""
+
+#: builtin/add.c:176
+#, c-format
+msgid "Path '%s' is in submodule '%.*s'"
+msgstr ""
+
+#: builtin/add.c:192
+msgid "Unstaged changes after refreshing the index:"
+msgstr ""
+
+#: builtin/add.c:195 builtin/add.c:456 builtin/rm.c:186
+#, c-format
+msgid "pathspec '%s' did not match any files"
+msgstr ""
+
+#: builtin/add.c:209
+#, c-format
+msgid "'%s' is beyond a symbolic link"
+msgstr ""
+
+#: builtin/add.c:276
+msgid "Could not read the index"
+msgstr ""
+
+#: builtin/add.c:286
+#, c-format
+msgid "Could not open '%s' for writing."
+msgstr ""
+
+#: builtin/add.c:290
+msgid "Could not write patch"
+msgstr ""
+
+#: builtin/add.c:295
+#, c-format
+msgid "Could not stat '%s'"
+msgstr ""
+
+#: builtin/add.c:297
+msgid "Empty patch. Aborted."
+msgstr ""
+
+#: builtin/add.c:303
+#, c-format
+msgid "Could not apply '%s'"
+msgstr ""
+
+#: builtin/add.c:312
+msgid "The following paths are ignored by one of your .gitignore files:\n"
+msgstr ""
+
+#: builtin/add.c:352
+#, c-format
+msgid "Use -f if you really want to add them.\n"
+msgstr ""
+
+#: builtin/add.c:353
+msgid "no files added"
+msgstr ""
+
+#: builtin/add.c:359
+msgid "adding files failed"
+msgstr ""
+
+#: builtin/add.c:391
+msgid "-A and -u are mutually incompatible"
+msgstr ""
+
+#: builtin/add.c:393
+msgid "Option --ignore-missing can only be used together with --dry-run"
+msgstr ""
+
+#: builtin/add.c:413
+#, c-format
+msgid "Nothing specified, nothing added.\n"
+msgstr ""
+
+#: builtin/add.c:414
+#, c-format
+msgid "Maybe you wanted to say 'git add .'?\n"
+msgstr ""
+
+#: builtin/add.c:420 builtin/clean.c:95 builtin/commit.c:358 builtin/mv.c:82
+#: builtin/rm.c:162
+msgid "index file corrupt"
+msgstr ""
+
+#: builtin/add.c:476 builtin/mv.c:229 builtin/rm.c:260
+msgid "Unable to write new index file"
+msgstr ""
+
+#: builtin/archive.c:17
+#, c-format
+msgid "could not create archive file '%s'"
+msgstr ""
+
+#: builtin/archive.c:20
+msgid "could not redirect output"
+msgstr ""
+
+#: builtin/archive.c:37
+msgid "git archive: Remote with no URL"
+msgstr ""
+
+#: builtin/archive.c:58
+msgid "git archive: expected ACK/NAK, got EOF"
+msgstr ""
+
+#: builtin/archive.c:63
+#, c-format
+msgid "git archive: NACK %s"
+msgstr ""
+
+#: builtin/archive.c:65
+#, c-format
+msgid "remote error: %s"
+msgstr ""
+
+#: builtin/archive.c:66
+msgid "git archive: protocol error"
+msgstr ""
+
+#: builtin/archive.c:71
+msgid "git archive: expected a flush"
+msgstr ""
+
+#: builtin/branch.c:137
+#, c-format
+msgid ""
+"deleting branch '%s' that has been merged to\n"
+" '%s', but not yet merged to HEAD."
+msgstr ""
+
+#: builtin/branch.c:141
+#, c-format
+msgid ""
+"not deleting branch '%s' that is not yet merged to\n"
+" '%s', even though it is merged to HEAD."
+msgstr ""
+
+#. TRANSLATORS: This is "remote " in "remote branch '%s' not found"
+#: builtin/branch.c:163
+msgid "remote "
+msgstr ""
+
+#: builtin/branch.c:171
+msgid "cannot use -a with -d"
+msgstr ""
+
+#: builtin/branch.c:177
+msgid "Couldn't look up commit object for HEAD"
+msgstr ""
+
+#: builtin/branch.c:182
+#, c-format
+msgid "Cannot delete the branch '%s' which you are currently on."
+msgstr ""
+
+#: builtin/branch.c:192
+#, c-format
+msgid "%sbranch '%s' not found."
+msgstr ""
+
+#: builtin/branch.c:200
+#, c-format
+msgid "Couldn't look up commit object for '%s'"
+msgstr ""
+
+#: builtin/branch.c:206
+#, c-format
+msgid ""
+"The branch '%s' is not fully merged.\n"
+"If you are sure you want to delete it, run 'git branch -D %s'."
+msgstr ""
+
+#: builtin/branch.c:214
+#, c-format
+msgid "Error deleting %sbranch '%s'"
+msgstr ""
+
+#: builtin/branch.c:219
+#, c-format
+msgid "Deleted %sbranch %s (was %s).\n"
+msgstr ""
+
+#: builtin/branch.c:224
+msgid "Update of config-file failed"
+msgstr ""
+
+#: builtin/branch.c:322
+#, c-format
+msgid "branch '%s' does not point at a commit"
+msgstr ""
+
+#: builtin/branch.c:394
+#, c-format
+msgid "behind %d] "
+msgstr ""
+
+#: builtin/branch.c:396
+#, c-format
+msgid "ahead %d] "
+msgstr ""
+
+#: builtin/branch.c:398
+#, c-format
+msgid "ahead %d, behind %d] "
+msgstr ""
+
+#: builtin/branch.c:501
+msgid "(no branch)"
+msgstr ""
+
+#: builtin/branch.c:566
+msgid "some refs could not be read"
+msgstr ""
+
+#: builtin/branch.c:579
+msgid "cannot rename the current branch while not on any."
+msgstr ""
+
+#: builtin/branch.c:589
+#, c-format
+msgid "Invalid branch name: '%s'"
+msgstr ""
+
+#: builtin/branch.c:604
+msgid "Branch rename failed"
+msgstr ""
+
+#: builtin/branch.c:608
+#, c-format
+msgid "Renamed a misnamed branch '%s' away"
+msgstr ""
+
+#: builtin/branch.c:612
+#, c-format
+msgid "Branch renamed to %s, but HEAD is not updated!"
+msgstr ""
+
+#: builtin/branch.c:619
+msgid "Branch is renamed, but update of config-file failed"
+msgstr ""
+
+#: builtin/branch.c:634
+#, c-format
+msgid "malformed object name %s"
+msgstr ""
+
+#: builtin/branch.c:658
+#, c-format
+msgid "could not write branch description template: %s\n"
+msgstr ""
+
+#: builtin/branch.c:746
+msgid "Failed to resolve HEAD as a valid ref."
+msgstr ""
+
+#: builtin/branch.c:751 builtin/clone.c:558
+msgid "HEAD not found below refs/heads!"
+msgstr ""
+
+#: builtin/branch.c:809
+msgid "-a and -r options to 'git branch' do not make sense with a branch name"
+msgstr ""
+
+#: builtin/bundle.c:47
+#, c-format
+msgid "%s is okay\n"
+msgstr ""
+
+#: builtin/bundle.c:56
+msgid "Need a repository to create a bundle."
+msgstr ""
+
+#: builtin/bundle.c:60
+msgid "Need a repository to unbundle."
+msgstr ""
+
+#: builtin/checkout.c:113 builtin/checkout.c:146
+#, c-format
+msgid "path '%s' does not have our version"
+msgstr ""
+
+#: builtin/checkout.c:115 builtin/checkout.c:148
+#, c-format
+msgid "path '%s' does not have their version"
+msgstr ""
+
+#: builtin/checkout.c:131
+#, c-format
+msgid "path '%s' does not have all necessary versions"
+msgstr ""
+
+#: builtin/checkout.c:175
+#, c-format
+msgid "path '%s' does not have necessary versions"
+msgstr ""
+
+#: builtin/checkout.c:192
+#, c-format
+msgid "path '%s': cannot merge"
+msgstr ""
+
+#: builtin/checkout.c:209
+#, c-format
+msgid "Unable to add merge result for '%s'"
+msgstr ""
+
+#: builtin/checkout.c:212 builtin/reset.c:158
+#, c-format
+msgid "make_cache_entry failed for path '%s'"
+msgstr ""
+
+#: builtin/checkout.c:234 builtin/checkout.c:392
+msgid "corrupt index file"
+msgstr ""
+
+#: builtin/checkout.c:264 builtin/checkout.c:271
+#, c-format
+msgid "path '%s' is unmerged"
+msgstr ""
+
+#: builtin/checkout.c:302 builtin/checkout.c:498 builtin/clone.c:583
+#: builtin/merge.c:811
+msgid "unable to write new index file"
+msgstr ""
+
+#: builtin/checkout.c:319 builtin/diff.c:302 builtin/merge.c:408
+msgid "diff_setup_done failed"
+msgstr ""
+
+#: builtin/checkout.c:414
+msgid "you need to resolve your current index first"
+msgstr ""
+
+#: builtin/checkout.c:533
+#, c-format
+msgid "Can not do reflog for '%s'\n"
+msgstr ""
+
+#: builtin/checkout.c:565
+msgid "HEAD is now at"
+msgstr ""
+
+#: builtin/checkout.c:572
+#, c-format
+msgid "Reset branch '%s'\n"
+msgstr ""
+
+#: builtin/checkout.c:575
+#, c-format
+msgid "Already on '%s'\n"
+msgstr ""
+
+#: builtin/checkout.c:579
+#, c-format
+msgid "Switched to and reset branch '%s'\n"
+msgstr ""
+
+#: builtin/checkout.c:581
+#, c-format
+msgid "Switched to a new branch '%s'\n"
+msgstr ""
+
+#: builtin/checkout.c:583
+#, c-format
+msgid "Switched to branch '%s'\n"
+msgstr ""
+
+#: builtin/checkout.c:639
+#, c-format
+msgid " ... and %d more.\n"
+msgstr ""
+
+#. The singular version
+#: builtin/checkout.c:645
+#, c-format
+msgid ""
+"Warning: you are leaving %d commit behind, not connected to\n"
+"any of your branches:\n"
+"\n"
+"%s\n"
+msgid_plural ""
+"Warning: you are leaving %d commits behind, not connected to\n"
+"any of your branches:\n"
+"\n"
+"%s\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: builtin/checkout.c:663
+#, c-format
+msgid ""
+"If you want to keep them by creating a new branch, this may be a good time\n"
+"to do so with:\n"
+"\n"
+" git branch new_branch_name %s\n"
+"\n"
+msgstr ""
+
+#: builtin/checkout.c:692
+msgid "internal error in revision walk"
+msgstr ""
+
+#: builtin/checkout.c:696
+msgid "Previous HEAD position was"
+msgstr ""
+
+#: builtin/checkout.c:722
+msgid "You are on a branch yet to be born"
+msgstr ""
+
+#. case (1)
+#: builtin/checkout.c:853
+#, c-format
+msgid "invalid reference: %s"
+msgstr ""
+
+#. case (1): want a tree
+#: builtin/checkout.c:892
+#, c-format
+msgid "reference is not a tree: %s"
+msgstr ""
+
+#: builtin/checkout.c:972
+msgid "-B cannot be used with -b"
+msgstr ""
+
+#: builtin/checkout.c:981
+msgid "--patch is incompatible with all other options"
+msgstr ""
+
+#: builtin/checkout.c:984
+msgid "--detach cannot be used with -b/-B/--orphan"
+msgstr ""
+
+#: builtin/checkout.c:986
+msgid "--detach cannot be used with -t"
+msgstr ""
+
+#: builtin/checkout.c:992
+msgid "--track needs a branch name"
+msgstr ""
+
+#: builtin/checkout.c:999
+msgid "Missing branch name; try -b"
+msgstr ""
+
+#: builtin/checkout.c:1005
+msgid "--orphan and -b|-B are mutually exclusive"
+msgstr ""
+
+#: builtin/checkout.c:1007
+msgid "--orphan cannot be used with -t"
+msgstr ""
+
+#: builtin/checkout.c:1017
+msgid "git checkout: -f and -m are incompatible"
+msgstr ""
+
+#: builtin/checkout.c:1051
+msgid "invalid path specification"
+msgstr ""
+
+#: builtin/checkout.c:1059
+#, c-format
+msgid ""
+"git checkout: updating paths is incompatible with switching branches.\n"
+"Did you intend to checkout '%s' which can not be resolved as commit?"
+msgstr ""
+
+#: builtin/checkout.c:1061
+msgid "git checkout: updating paths is incompatible with switching branches."
+msgstr ""
+
+#: builtin/checkout.c:1066
+msgid "git checkout: --detach does not take a path argument"
+msgstr ""
+
+#: builtin/checkout.c:1069
+msgid ""
+"git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
+"checking out of the index."
+msgstr ""
+
+#: builtin/checkout.c:1088
+msgid "Cannot switch branch to a non-commit."
+msgstr ""
+
+#: builtin/checkout.c:1091
+msgid "--ours/--theirs is incompatible with switching branches."
+msgstr ""
+
+#: builtin/clean.c:78
+msgid "-x and -X cannot be used together"
+msgstr ""
+
+#: builtin/clean.c:82
+msgid ""
+"clean.requireForce set to true and neither -n nor -f given; refusing to clean"
+msgstr ""
+
+#: builtin/clean.c:85
+msgid ""
+"clean.requireForce defaults to true and neither -n nor -f given; refusing to "
+"clean"
+msgstr ""
+
+#: builtin/clean.c:155 builtin/clean.c:176
+#, c-format
+msgid "Would remove %s\n"
+msgstr ""
+
+#: builtin/clean.c:159 builtin/clean.c:179
+#, c-format
+msgid "Removing %s\n"
+msgstr ""
+
+#: builtin/clean.c:162 builtin/clean.c:182
+#, c-format
+msgid "failed to remove %s"
+msgstr ""
+
+#: builtin/clean.c:166
+#, c-format
+msgid "Would not remove %s\n"
+msgstr ""
+
+#: builtin/clean.c:168
+#, c-format
+msgid "Not removing %s\n"
+msgstr ""
+
+#: builtin/clone.c:243
+#, c-format
+msgid "reference repository '%s' is not a local directory."
+msgstr ""
+
+#: builtin/clone.c:302
+#, c-format
+msgid "failed to open '%s'"
+msgstr ""
+
+#: builtin/clone.c:306
+#, c-format
+msgid "failed to create directory '%s'"
+msgstr ""
+
+#: builtin/clone.c:308 builtin/diff.c:75
+#, c-format
+msgid "failed to stat '%s'"
+msgstr ""
+
+#: builtin/clone.c:310
+#, c-format
+msgid "%s exists and is not a directory"
+msgstr ""
+
+#: builtin/clone.c:324
+#, c-format
+msgid "failed to stat %s\n"
+msgstr ""
+
+#: builtin/clone.c:341
+#, c-format
+msgid "failed to unlink '%s'"
+msgstr ""
+
+#: builtin/clone.c:346
+#, c-format
+msgid "failed to create link '%s'"
+msgstr ""
+
+#: builtin/clone.c:350
+#, c-format
+msgid "failed to copy file to '%s'"
+msgstr ""
+
+#: builtin/clone.c:373
+#, c-format
+msgid "done.\n"
+msgstr ""
+
+#: builtin/clone.c:440
+#, c-format
+msgid "Could not find remote branch %s to clone."
+msgstr ""
+
+#: builtin/clone.c:549
+msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n"
+msgstr ""
+
+#: builtin/clone.c:639
+msgid "Too many arguments."
+msgstr ""
+
+#: builtin/clone.c:643
+msgid "You must specify a repository to clone."
+msgstr ""
+
+#: builtin/clone.c:654
+#, c-format
+msgid "--bare and --origin %s options are incompatible."
+msgstr ""
+
+#: builtin/clone.c:668
+#, c-format
+msgid "repository '%s' does not exist"
+msgstr ""
+
+#: builtin/clone.c:673
+msgid "--depth is ignored in local clones; use file:// instead."
+msgstr ""
+
+#: builtin/clone.c:683
+#, c-format
+msgid "destination path '%s' already exists and is not an empty directory."
+msgstr ""
+
+#: builtin/clone.c:693
+#, c-format
+msgid "working tree '%s' already exists."
+msgstr ""
+
+#: builtin/clone.c:706 builtin/clone.c:720
+#, c-format
+msgid "could not create leading directories of '%s'"
+msgstr ""
+
+#: builtin/clone.c:709
+#, c-format
+msgid "could not create work tree dir '%s'."
+msgstr ""
+
+#: builtin/clone.c:728
+#, c-format
+msgid "Cloning into bare repository '%s'...\n"
+msgstr ""
+
+#: builtin/clone.c:730
+#, c-format
+msgid "Cloning into '%s'...\n"
+msgstr ""
+
+#: builtin/clone.c:786
+#, c-format
+msgid "Don't know how to clone %s"
+msgstr ""
+
+#: builtin/clone.c:835
+#, c-format
+msgid "Remote branch %s not found in upstream %s"
+msgstr ""
+
+#: builtin/clone.c:842
+msgid "You appear to have cloned an empty repository."
+msgstr ""
+
+#: builtin/commit.c:42
+msgid ""
+"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"
+"After doing this, you may fix the identity used for this commit with:\n"
+"\n"
+" git commit --amend --reset-author\n"
+msgstr ""
+
+#: builtin/commit.c:54
+msgid ""
+"You asked to amend the most recent commit, but doing so would make\n"
+"it empty. You can repeat your command with --allow-empty, or you can\n"
+"remove the commit entirely with \"git reset HEAD^\".\n"
+msgstr ""
+
+#: builtin/commit.c:59
+msgid ""
+"The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
+"If you wish to commit it anyway, use:\n"
+"\n"
+" git commit --allow-empty\n"
+"\n"
+"Otherwise, please use 'git reset'\n"
+msgstr ""
+
+#: builtin/commit.c:205 builtin/reset.c:33
+msgid "merge"
+msgstr ""
+
+#: builtin/commit.c:208
+msgid "cherry-pick"
+msgstr ""
+
+#: builtin/commit.c:325
+msgid "failed to unpack HEAD tree object"
+msgstr ""
+
+#: builtin/commit.c:367
+msgid "unable to create temporary index"
+msgstr ""
+
+#: builtin/commit.c:373
+msgid "interactive add failed"
+msgstr ""
+
+#: builtin/commit.c:406 builtin/commit.c:427 builtin/commit.c:473
+msgid "unable to write new_index file"
+msgstr ""
+
+#: builtin/commit.c:457
+#, c-format
+msgid "cannot do a partial commit during a %s."
+msgstr ""
+
+#: builtin/commit.c:466
+msgid "cannot read the index"
+msgstr ""
+
+#: builtin/commit.c:486
+msgid "unable to write temporary index file"
+msgstr ""
+
+#: builtin/commit.c:550 builtin/commit.c:556
+#, c-format
+msgid "invalid commit: %s"
+msgstr ""
+
+#: builtin/commit.c:579
+msgid "malformed --author parameter"
+msgstr ""
+
+#: builtin/commit.c:635
+#, c-format
+msgid "Malformed ident string: '%s'"
+msgstr ""
+
+#: builtin/commit.c:670 builtin/commit.c:703 builtin/commit.c:1000
+#, c-format
+msgid "could not lookup commit %s"
+msgstr ""
+
+#: builtin/commit.c:682 builtin/shortlog.c:296
+#, c-format
+msgid "(reading log message from standard input)\n"
+msgstr ""
+
+#: builtin/commit.c:684
+msgid "could not read log from standard input"
+msgstr ""
+
+#: builtin/commit.c:688
+#, c-format
+msgid "could not read log file '%s'"
+msgstr ""
+
+#: builtin/commit.c:694
+msgid "commit has empty message"
+msgstr ""
+
+#: builtin/commit.c:710
+msgid "could not read MERGE_MSG"
+msgstr ""
+
+#: builtin/commit.c:714
+msgid "could not read SQUASH_MSG"
+msgstr ""
+
+#: builtin/commit.c:718
+#, c-format
+msgid "could not read '%s'"
+msgstr ""
+
+#: builtin/commit.c:746
+#, c-format
+msgid "could not open '%s'"
+msgstr ""
+
+#: builtin/commit.c:770
+msgid "could not write commit template"
+msgstr ""
+
+#: builtin/commit.c:783
+#, c-format
+msgid ""
+"\n"
+"It looks like you may be committing a %s.\n"
+"If this is not correct, please remove the file\n"
+"\t%s\n"
+"and try again.\n"
+msgstr ""
+
+#: builtin/commit.c:796
+msgid "Please enter the commit message for your changes."
+msgstr ""
+
+#: builtin/commit.c:799
+msgid ""
+" Lines starting\n"
+"with '#' will be ignored, and an empty message aborts the commit.\n"
+msgstr ""
+
+#: builtin/commit.c:804
+msgid ""
+" Lines starting\n"
+"with '#' will be kept; you may remove them yourself if you want to.\n"
+"An empty message aborts the commit.\n"
+msgstr ""
+
+#: builtin/commit.c:816
+#, c-format
+msgid "%sAuthor: %s"
+msgstr ""
+
+#: builtin/commit.c:823
+#, c-format
+msgid "%sCommitter: %s"
+msgstr ""
+
+#: builtin/commit.c:843
+msgid "Cannot read index"
+msgstr ""
+
+#: builtin/commit.c:880
+msgid "Error building trees"
+msgstr ""
+
+#: builtin/commit.c:895 builtin/tag.c:357
+#, c-format
+msgid "Please supply the message using either -m or -F option.\n"
+msgstr ""
+
+#: builtin/commit.c:975
+#, c-format
+msgid "No existing author found with '%s'"
+msgstr ""
+
+#: builtin/commit.c:990 builtin/commit.c:1182
+#, c-format
+msgid "Invalid untracked files mode '%s'"
+msgstr ""
+
+#: builtin/commit.c:1030
+msgid "Using both --reset-author and --author does not make sense"
+msgstr ""
+
+#: builtin/commit.c:1041
+msgid "You have nothing to amend."
+msgstr ""
+
+#: builtin/commit.c:1043
+#, c-format
+msgid "You are in the middle of a %s -- cannot amend."
+msgstr ""
+
+#: builtin/commit.c:1045
+msgid "Options --squash and --fixup cannot be used together"
+msgstr ""
+
+#: builtin/commit.c:1055
+msgid "Only one of -c/-C/-F/--fixup can be used."
+msgstr ""
+
+#: builtin/commit.c:1057
+msgid "Option -m cannot be combined with -c/-C/-F/--fixup."
+msgstr ""
+
+#: builtin/commit.c:1063
+msgid "--reset-author can be used only with -C, -c or --amend."
+msgstr ""
+
+#: builtin/commit.c:1080
+msgid "Only one of --include/--only/--all/--interactive/--patch can be used."
+msgstr ""
+
+#: builtin/commit.c:1082
+msgid "No paths with --include/--only does not make sense."
+msgstr ""
+
+#: builtin/commit.c:1084
+msgid "Clever... amending the last one with dirty index."
+msgstr ""
+
+#: builtin/commit.c:1086
+msgid "Explicit paths specified without -i nor -o; assuming --only paths..."
+msgstr ""
+
+#: builtin/commit.c:1096 builtin/tag.c:556
+#, c-format
+msgid "Invalid cleanup mode %s"
+msgstr ""
+
+#: builtin/commit.c:1101
+msgid "Paths with -a does not make sense."
+msgstr ""
+
+#: builtin/commit.c:1280
+msgid "couldn't look up newly created commit"
+msgstr ""
+
+#: builtin/commit.c:1282
+msgid "could not parse newly created commit"
+msgstr ""
+
+#: builtin/commit.c:1323
+msgid "detached HEAD"
+msgstr ""
+
+#: builtin/commit.c:1325
+msgid " (root-commit)"
+msgstr ""
+
+#: builtin/commit.c:1415
+msgid "could not parse HEAD commit"
+msgstr ""
+
+#: builtin/commit.c:1452 builtin/merge.c:509
+#, c-format
+msgid "could not open '%s' for reading"
+msgstr ""
+
+#: builtin/commit.c:1459
+#, c-format
+msgid "Corrupt MERGE_HEAD file (%s)"
+msgstr ""
+
+#: builtin/commit.c:1466
+msgid "could not read MERGE_MODE"
+msgstr ""
+
+#: builtin/commit.c:1485
+#, c-format
+msgid "could not read commit message: %s"
+msgstr ""
+
+#: builtin/commit.c:1499
+#, c-format
+msgid "Aborting commit due to empty commit message.\n"
+msgstr ""
+
+#: builtin/commit.c:1514 builtin/merge.c:935 builtin/merge.c:968
+msgid "failed to write commit object"
+msgstr ""
+
+#: builtin/commit.c:1535
+msgid "cannot lock HEAD ref"
+msgstr ""
+
+#: builtin/commit.c:1539
+msgid "cannot update HEAD ref"
+msgstr ""
+
+#: builtin/commit.c:1550
+msgid ""
+"Repository has been updated, but unable to write\n"
+"new_index file. Check that disk is not full or quota is\n"
+"not exceeded, and then \"git reset HEAD\" to recover."
+msgstr ""
+
+#: builtin/describe.c:234
+#, c-format
+msgid "annotated tag %s not available"
+msgstr ""
+
+#: builtin/describe.c:238
+#, c-format
+msgid "annotated tag %s has no embedded name"
+msgstr ""
+
+#: builtin/describe.c:240
+#, c-format
+msgid "tag '%s' is really '%s' here"
+msgstr ""
+
+#: builtin/describe.c:267
+#, c-format
+msgid "Not a valid object name %s"
+msgstr ""
+
+#: builtin/describe.c:270
+#, c-format
+msgid "%s is not a valid '%s' object"
+msgstr ""
+
+#: builtin/describe.c:287
+#, c-format
+msgid "no tag exactly matches '%s'"
+msgstr ""
+
+#: builtin/describe.c:289
+#, c-format
+msgid "searching to describe %s\n"
+msgstr ""
+
+#: builtin/describe.c:329
+#, c-format
+msgid "finished search at %s\n"
+msgstr ""
+
+#: builtin/describe.c:353
+#, c-format
+msgid ""
+"No annotated tags can describe '%s'.\n"
+"However, there were unannotated tags: try --tags."
+msgstr ""
+
+#: builtin/describe.c:357
+#, c-format
+msgid ""
+"No tags can describe '%s'.\n"
+"Try --always, or create some tags."
+msgstr ""
+
+#: builtin/describe.c:378
+#, c-format
+msgid "traversed %lu commits\n"
+msgstr ""
+
+#: builtin/describe.c:381
+#, c-format
+msgid ""
+"more than %i tags found; listed %i most recent\n"
+"gave up search at %s\n"
+msgstr ""
+
+#: builtin/describe.c:436
+msgid "--long is incompatible with --abbrev=0"
+msgstr ""
+
+#: builtin/describe.c:462
+msgid "No names found, cannot describe anything."
+msgstr ""
+
+#: builtin/describe.c:482
+msgid "--dirty is incompatible with committishes"
+msgstr ""
+
+#: builtin/diff.c:77
+#, c-format
+msgid "'%s': not a regular file or symlink"
+msgstr ""
+
+#: builtin/diff.c:220
+#, c-format
+msgid "invalid option: %s"
+msgstr ""
+
+#: builtin/diff.c:297
+msgid "Not a git repository"
+msgstr ""
+
+#: builtin/diff.c:347
+#, c-format
+msgid "invalid object '%s' given."
+msgstr ""
+
+#: builtin/diff.c:352
+#, c-format
+msgid "more than %d trees given: '%s'"
+msgstr ""
+
+#: builtin/diff.c:362
+#, c-format
+msgid "more than two blobs given: '%s'"
+msgstr ""
+
+#: builtin/diff.c:370
+#, c-format
+msgid "unhandled object '%s' given."
+msgstr ""
+
+#: builtin/fetch.c:200
+msgid "Couldn't find remote ref HEAD"
+msgstr ""
+
+#: builtin/fetch.c:252
+#, c-format
+msgid "object %s not found"
+msgstr ""
+
+#: builtin/fetch.c:258
+msgid "[up to date]"
+msgstr ""
+
+#: builtin/fetch.c:272
+#, c-format
+msgid "! %-*s %-*s -> %s (can't fetch in current branch)"
+msgstr ""
+
+#: builtin/fetch.c:273 builtin/fetch.c:351
+msgid "[rejected]"
+msgstr ""
+
+#: builtin/fetch.c:284
+msgid "[tag update]"
+msgstr ""
+
+#: builtin/fetch.c:286 builtin/fetch.c:313 builtin/fetch.c:331
+msgid " (unable to update local ref)"
+msgstr ""
+
+#: builtin/fetch.c:298
+msgid "[new tag]"
+msgstr ""
+
+#: builtin/fetch.c:302
+msgid "[new branch]"
+msgstr ""
+
+#: builtin/fetch.c:347
+msgid "unable to update local ref"
+msgstr ""
+
+#: builtin/fetch.c:347
+msgid "forced update"
+msgstr ""
+
+#: builtin/fetch.c:353
+msgid "(non-fast-forward)"
+msgstr ""
+
+#: builtin/fetch.c:384 builtin/fetch.c:676
+#, c-format
+msgid "cannot open %s: %s\n"
+msgstr ""
+
+#: builtin/fetch.c:393
+#, c-format
+msgid "%s did not send all necessary objects\n"
+msgstr ""
+
+#: builtin/fetch.c:479
+#, c-format
+msgid "From %.*s\n"
+msgstr ""
+
+#: builtin/fetch.c:490
+#, c-format
+msgid ""
+"some local refs could not be updated; try running\n"
+" 'git remote prune %s' to remove any old, conflicting branches"
+msgstr ""
+
+#: builtin/fetch.c:540
+#, c-format
+msgid " (%s will become dangling)\n"
+msgstr ""
+
+#: builtin/fetch.c:541
+#, c-format
+msgid " (%s has become dangling)\n"
+msgstr ""
+
+#: builtin/fetch.c:548
+msgid "[deleted]"
+msgstr ""
+
+#: builtin/fetch.c:549
+msgid "(none)"
+msgstr ""
+
+#: builtin/fetch.c:666
+#, c-format
+msgid "Refusing to fetch into current branch %s of non-bare repository"
+msgstr ""
+
+#: builtin/fetch.c:700
+#, c-format
+msgid "Don't know how to fetch from %s"
+msgstr ""
+
+#: builtin/fetch.c:777
+#, c-format
+msgid "Option \"%s\" value \"%s\" is not valid for %s"
+msgstr ""
+
+#: builtin/fetch.c:780
+#, c-format
+msgid "Option \"%s\" is ignored for %s\n"
+msgstr ""
+
+#: builtin/fetch.c:879
+#, c-format
+msgid "Fetching %s\n"
+msgstr ""
+
+#: builtin/fetch.c:881
+#, c-format
+msgid "Could not fetch %s"
+msgstr ""
+
+#: builtin/fetch.c:898
+msgid ""
+"No remote repository specified. Please, specify either a URL or a\n"
+"remote name from which new revisions should be fetched."
+msgstr ""
+
+#: builtin/fetch.c:918
+msgid "You need to specify a tag name."
+msgstr ""
+
+#: builtin/fetch.c:970
+msgid "fetch --all does not take a repository argument"
+msgstr ""
+
+#: builtin/fetch.c:972
+msgid "fetch --all does not make sense with refspecs"
+msgstr ""
+
+#: builtin/fetch.c:983
+#, c-format
+msgid "No such remote or remote group: %s"
+msgstr ""
+
+#: builtin/fetch.c:991
+msgid "Fetching a group and specifying refspecs does not make sense"
+msgstr ""
+
+#: builtin/gc.c:63
+#, c-format
+msgid "Invalid %s: '%s'"
+msgstr ""
+
+#: builtin/gc.c:78
+msgid "Too many options specified"
+msgstr ""
+
+#: builtin/gc.c:103
+#, c-format
+msgid "insanely long object directory %.*s"
+msgstr ""
+
+#: builtin/gc.c:223
+#, c-format
+msgid "Auto packing the repository for optimum performance.\n"
+msgstr ""
+
+#: builtin/gc.c:226
+#, c-format
+msgid ""
+"Auto packing the repository for optimum performance. You may also\n"
+"run \"git gc\" manually. See \"git help gc\" for more information.\n"
+msgstr ""
+
+#: builtin/gc.c:256
+msgid ""
+"There are too many unreachable loose objects; run 'git prune' to remove them."
+msgstr ""
+
+#: builtin/grep.c:216
+#, c-format
+msgid "grep: failed to create thread: %s"
+msgstr ""
+
+#: builtin/grep.c:402
+#, c-format
+msgid "Failed to chdir: %s"
+msgstr ""
+
+#: builtin/grep.c:478 builtin/grep.c:512
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr ""
+
+#: builtin/grep.c:526
+#, c-format
+msgid "unable to grep from object of type %s"
+msgstr ""
+
+#: builtin/grep.c:584
+#, c-format
+msgid "switch `%c' expects a numerical value"
+msgstr ""
+
+#: builtin/grep.c:601
+#, c-format
+msgid "cannot open '%s'"
+msgstr ""
+
+#: builtin/grep.c:888
+msgid "no pattern given."
+msgstr ""
+
+#: builtin/grep.c:902
+#, c-format
+msgid "bad object %s"
+msgstr ""
+
+#: builtin/grep.c:943
+msgid "--open-files-in-pager only works on the worktree"
+msgstr ""
+
+#: builtin/grep.c:966
+msgid "--cached or --untracked cannot be used with --no-index."
+msgstr ""
+
+#: builtin/grep.c:971
+msgid "--no-index or --untracked cannot be used with revs."
+msgstr ""
+
+#: builtin/grep.c:974
+msgid "--[no-]exclude-standard cannot be used for tracked contents."
+msgstr ""
+
+#: builtin/grep.c:982
+msgid "both --cached and trees are given."
+msgstr ""
+
+#: builtin/init-db.c:35
+#, c-format
+msgid "Could not make %s writable by group"
+msgstr ""
+
+#: builtin/init-db.c:62
+#, c-format
+msgid "insanely long template name %s"
+msgstr ""
+
+#: builtin/init-db.c:67
+#, c-format
+msgid "cannot stat '%s'"
+msgstr ""
+
+#: builtin/init-db.c:73
+#, c-format
+msgid "cannot stat template '%s'"
+msgstr ""
+
+#: builtin/init-db.c:80
+#, c-format
+msgid "cannot opendir '%s'"
+msgstr ""
+
+#: builtin/init-db.c:97
+#, c-format
+msgid "cannot readlink '%s'"
+msgstr ""
+
+#: builtin/init-db.c:99
+#, c-format
+msgid "insanely long symlink %s"
+msgstr ""
+
+#: builtin/init-db.c:102
+#, c-format
+msgid "cannot symlink '%s' '%s'"
+msgstr ""
+
+#: builtin/init-db.c:106
+#, c-format
+msgid "cannot copy '%s' to '%s'"
+msgstr ""
+
+#: builtin/init-db.c:110
+#, c-format
+msgid "ignoring template %s"
+msgstr ""
+
+#: builtin/init-db.c:133
+#, c-format
+msgid "insanely long template path %s"
+msgstr ""
+
+#: builtin/init-db.c:141
+#, c-format
+msgid "templates not found %s"
+msgstr ""
+
+#: builtin/init-db.c:154
+#, c-format
+msgid "not copying templates of a wrong format version %d from '%s'"
+msgstr ""
+
+#: builtin/init-db.c:192
+#, c-format
+msgid "insane git directory %s"
+msgstr ""
+
+#: builtin/init-db.c:322 builtin/init-db.c:325
+#, c-format
+msgid "%s already exists"
+msgstr ""
+
+#: builtin/init-db.c:354
+#, c-format
+msgid "unable to handle file type %d"
+msgstr ""
+
+#: builtin/init-db.c:357
+#, c-format
+msgid "unable to move %s to %s"
+msgstr ""
+
+#: builtin/init-db.c:362
+#, c-format
+msgid "Could not create git link %s"
+msgstr ""
+
+#.
+#. * TRANSLATORS: The first '%s' is either "Reinitialized
+#. * existing" or "Initialized empty", the second " shared" or
+#. * "", and the last '%s%s' is the verbatim directory name.
+#.
+#: builtin/init-db.c:419
+#, c-format
+msgid "%s%s Git repository in %s%s\n"
+msgstr ""
+
+#: builtin/init-db.c:420
+msgid "Reinitialized existing"
+msgstr ""
+
+#: builtin/init-db.c:420
+msgid "Initialized empty"
+msgstr ""
+
+#: builtin/init-db.c:421
+msgid " shared"
+msgstr ""
+
+#: builtin/init-db.c:440
+msgid "cannot tell cwd"
+msgstr ""
+
+#: builtin/init-db.c:521 builtin/init-db.c:528
+#, c-format
+msgid "cannot mkdir %s"
+msgstr ""
+
+#: builtin/init-db.c:532
+#, c-format
+msgid "cannot chdir to %s"
+msgstr ""
+
+#: builtin/init-db.c:554
+#, c-format
+msgid ""
+"%s (or --work-tree=<directory>) not allowed without specifying %s (or --git-"
+"dir=<directory>)"
+msgstr ""
+
+#: builtin/init-db.c:578
+msgid "Cannot access current working directory"
+msgstr ""
+
+#: builtin/init-db.c:585
+#, c-format
+msgid "Cannot access work tree '%s'"
+msgstr ""
+
+#: builtin/log.c:187
+#, c-format
+msgid "Final output: %d %s\n"
+msgstr ""
+
+#: builtin/log.c:395 builtin/log.c:483
+#, c-format
+msgid "Could not read object %s"
+msgstr ""
+
+#: builtin/log.c:507
+#, c-format
+msgid "Unknown type: %d"
+msgstr ""
+
+#: builtin/log.c:596
+msgid "format.headers without value"
+msgstr ""
+
+#: builtin/log.c:669
+msgid "name of output directory is too long"
+msgstr ""
+
+#: builtin/log.c:680
+#, c-format
+msgid "Cannot open patch file %s"
+msgstr ""
+
+#: builtin/log.c:694
+msgid "Need exactly one range."
+msgstr ""
+
+#: builtin/log.c:702
+msgid "Not a range."
+msgstr ""
+
+#: builtin/log.c:739
+msgid "Could not extract email from committer identity."
+msgstr ""
+
+#: builtin/log.c:785
+msgid "Cover letter needs email format"
+msgstr ""
+
+#: builtin/log.c:879
+#, c-format
+msgid "insane in-reply-to: %s"
+msgstr ""
+
+#: builtin/log.c:952
+msgid "Two output directories?"
+msgstr ""
+
+#: builtin/log.c:1173
+#, c-format
+msgid "bogus committer info %s"
+msgstr ""
+
+#: builtin/log.c:1218
+msgid "-n and -k are mutually exclusive."
+msgstr ""
+
+#: builtin/log.c:1220
+msgid "--subject-prefix and -k are mutually exclusive."
+msgstr ""
+
+#: builtin/log.c:1225 builtin/shortlog.c:284
+#, c-format
+msgid "unrecognized argument: %s"
+msgstr ""
+
+#: builtin/log.c:1228
+msgid "--name-only does not make sense"
+msgstr ""
+
+#: builtin/log.c:1230
+msgid "--name-status does not make sense"
+msgstr ""
+
+#: builtin/log.c:1232
+msgid "--check does not make sense"
+msgstr ""
+
+#: builtin/log.c:1255
+msgid "standard output, or directory, which one?"
+msgstr ""
+
+#: builtin/log.c:1257
+#, c-format
+msgid "Could not create directory '%s'"
+msgstr ""
+
+#: builtin/log.c:1410
+msgid "Failed to create output files"
+msgstr ""
+
+#: builtin/log.c:1514
+#, c-format
+msgid ""
+"Could not find a tracked remote branch, please specify <upstream> manually.\n"
+msgstr ""
+
+#: builtin/log.c:1530 builtin/log.c:1532 builtin/log.c:1544
+#, c-format
+msgid "Unknown commit %s"
+msgstr ""
+
+#: builtin/merge.c:91
+msgid "switch `m' requires a value"
+msgstr ""
+
+#: builtin/merge.c:128
+#, c-format
+msgid "Could not find merge strategy '%s'.\n"
+msgstr ""
+
+#: builtin/merge.c:129
+#, c-format
+msgid "Available strategies are:"
+msgstr ""
+
+#: builtin/merge.c:134
+#, c-format
+msgid "Available custom strategies are:"
+msgstr ""
+
+#: builtin/merge.c:241
+msgid "could not run stash."
+msgstr ""
+
+#: builtin/merge.c:246
+msgid "stash failed"
+msgstr ""
+
+#: builtin/merge.c:251
+#, c-format
+msgid "not a valid object: %s"
+msgstr ""
+
+#: builtin/merge.c:270 builtin/merge.c:287
+msgid "read-tree failed"
+msgstr ""
+
+#: builtin/merge.c:317
+msgid " (nothing to squash)"
+msgstr ""
+
+#: builtin/merge.c:330
+#, c-format
+msgid "Squash commit -- not updating HEAD\n"
+msgstr ""
+
+#: builtin/merge.c:362
+msgid "Writing SQUASH_MSG"
+msgstr ""
+
+#: builtin/merge.c:364
+msgid "Finishing SQUASH_MSG"
+msgstr ""
+
+#: builtin/merge.c:386
+#, c-format
+msgid "No merge message -- not updating HEAD\n"
+msgstr ""
+
+#: builtin/merge.c:437
+#, c-format
+msgid "'%s' does not point to a commit"
+msgstr ""
+
+#: builtin/merge.c:536
+#, c-format
+msgid "Bad branch.%s.mergeoptions string: %s"
+msgstr ""
+
+#: builtin/merge.c:629
+msgid "git write-tree failed to write a tree"
+msgstr ""
+
+#: builtin/merge.c:679
+msgid "failed to read the cache"
+msgstr ""
+
+#: builtin/merge.c:696
+msgid "Unable to write index."
+msgstr ""
+
+#: builtin/merge.c:709
+msgid "Not handling anything other than two heads merge."
+msgstr ""
+
+#: builtin/merge.c:723
+#, c-format
+msgid "Unknown option for merge-recursive: -X%s"
+msgstr ""
+
+#: builtin/merge.c:737
+#, c-format
+msgid "unable to write %s"
+msgstr ""
+
+#: builtin/merge.c:876
+#, c-format
+msgid "Could not read from '%s'"
+msgstr ""
+
+#: builtin/merge.c:885
+#, c-format
+msgid "Not committing merge; use 'git commit' to complete the merge.\n"
+msgstr ""
+
+#: builtin/merge.c:891
+msgid ""
+"Please enter a commit message to explain why this merge is necessary,\n"
+"especially if it merges an updated upstream into a topic branch.\n"
+"\n"
+"Lines starting with '#' will be ignored, and an empty message aborts\n"
+"the commit.\n"
+msgstr ""
+
+#: builtin/merge.c:915
+msgid "Empty commit message."
+msgstr ""
+
+#: builtin/merge.c:927
+#, c-format
+msgid "Wonderful.\n"
+msgstr ""
+
+#: builtin/merge.c:1000
+#, c-format
+msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
+msgstr ""
+
+#: builtin/merge.c:1016
+#, c-format
+msgid "'%s' is not a commit"
+msgstr ""
+
+#: builtin/merge.c:1057
+msgid "No current branch."
+msgstr ""
+
+#: builtin/merge.c:1059
+msgid "No remote for the current branch."
+msgstr ""
+
+#: builtin/merge.c:1061
+msgid "No default upstream defined for the current branch."
+msgstr ""
+
+#: builtin/merge.c:1066
+#, c-format
+msgid "No remote tracking branch for %s from %s"
+msgstr ""
+
+#: builtin/merge.c:1188
+msgid "There is no merge to abort (MERGE_HEAD missing)."
+msgstr ""
+
+#: builtin/merge.c:1204 git-pull.sh:31
+msgid ""
+"You have not concluded your merge (MERGE_HEAD exists).\n"
+"Please, commit your changes before you can merge."
+msgstr ""
+
+#: builtin/merge.c:1207 git-pull.sh:34
+msgid "You have not concluded your merge (MERGE_HEAD exists)."
+msgstr ""
+
+#: builtin/merge.c:1211
+msgid ""
+"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
+"Please, commit your changes before you can merge."
+msgstr ""
+
+#: builtin/merge.c:1214
+msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
+msgstr ""
+
+#: builtin/merge.c:1223
+msgid "You cannot combine --squash with --no-ff."
+msgstr ""
+
+#: builtin/merge.c:1228
+msgid "You cannot combine --no-ff with --ff-only."
+msgstr ""
+
+#: builtin/merge.c:1235
+msgid "No commit specified and merge.defaultToUpstream not set."
+msgstr ""
+
+#: builtin/merge.c:1266
+msgid "Can merge only exactly one commit into empty head"
+msgstr ""
+
+#: builtin/merge.c:1269
+msgid "Squash commit into empty head not supported yet"
+msgstr ""
+
+#: builtin/merge.c:1271
+msgid "Non-fast-forward commit does not make sense into an empty head"
+msgstr ""
+
+#: builtin/merge.c:1275 builtin/merge.c:1319
+#, c-format
+msgid "%s - not something we can merge"
+msgstr ""
+
+#: builtin/merge.c:1385
+#, c-format
+msgid "Updating %s..%s\n"
+msgstr ""
+
+#: builtin/merge.c:1423
+#, c-format
+msgid "Trying really trivial in-index merge...\n"
+msgstr ""
+
+#: builtin/merge.c:1430
+#, c-format
+msgid "Nope.\n"
+msgstr ""
+
+#: builtin/merge.c:1462
+msgid "Not possible to fast-forward, aborting."
+msgstr ""
+
+#: builtin/merge.c:1485 builtin/merge.c:1562
+#, c-format
+msgid "Rewinding the tree to pristine...\n"
+msgstr ""
+
+#: builtin/merge.c:1489
+#, c-format
+msgid "Trying merge strategy %s...\n"
+msgstr ""
+
+#: builtin/merge.c:1553
+#, c-format
+msgid "No merge strategy handled the merge.\n"
+msgstr ""
+
+#: builtin/merge.c:1555
+#, c-format
+msgid "Merge with strategy %s failed.\n"
+msgstr ""
+
+#: builtin/merge.c:1564
+#, c-format
+msgid "Using the %s to prepare resolving by hand.\n"
+msgstr ""
+
+#: builtin/merge.c:1575
+#, c-format
+msgid "Automatic merge went well; stopped before committing as requested\n"
+msgstr ""
+
+#: builtin/mv.c:108
+#, c-format
+msgid "Checking rename of '%s' to '%s'\n"
+msgstr ""
+
+#: builtin/mv.c:112
+msgid "bad source"
+msgstr ""
+
+#: builtin/mv.c:115
+msgid "can not move directory into itself"
+msgstr ""
+
+#: builtin/mv.c:118
+msgid "cannot move directory over file"
+msgstr ""
+
+#: builtin/mv.c:128
+#, c-format
+msgid "Huh? %.*s is in index?"
+msgstr ""
+
+#: builtin/mv.c:140
+msgid "source directory is empty"
+msgstr ""
+
+#: builtin/mv.c:171
+msgid "not under version control"
+msgstr ""
+
+#: builtin/mv.c:173
+msgid "destination exists"
+msgstr ""
+
+#: builtin/mv.c:181
+#, c-format
+msgid "overwriting '%s'"
+msgstr ""
+
+#: builtin/mv.c:184
+msgid "Cannot overwrite"
+msgstr ""
+
+#: builtin/mv.c:187
+msgid "multiple sources for the same target"
+msgstr ""
+
+#: builtin/mv.c:202
+#, c-format
+msgid "%s, source=%s, destination=%s"
+msgstr ""
+
+#: builtin/mv.c:212
+#, c-format
+msgid "Renaming %s to %s\n"
+msgstr ""
+
+#: builtin/mv.c:215
+#, c-format
+msgid "renaming '%s' failed"
+msgstr ""
+
+#: builtin/notes.c:139
+#, c-format
+msgid "unable to start 'show' for object '%s'"
+msgstr ""
+
+#: builtin/notes.c:145
+msgid "can't fdopen 'show' output fd"
+msgstr ""
+
+#: builtin/notes.c:155
+#, c-format
+msgid "failed to close pipe to 'show' for object '%s'"
+msgstr ""
+
+#: builtin/notes.c:158
+#, c-format
+msgid "failed to finish 'show' for object '%s'"
+msgstr ""
+
+#: builtin/notes.c:175 builtin/tag.c:343
+#, c-format
+msgid "could not create file '%s'"
+msgstr ""
+
+#: builtin/notes.c:189
+msgid "Please supply the note contents using either -m or -F option"
+msgstr ""
+
+#: builtin/notes.c:210 builtin/notes.c:973
+#, c-format
+msgid "Removing note for object %s\n"
+msgstr ""
+
+#: builtin/notes.c:215
+msgid "unable to write note object"
+msgstr ""
+
+#: builtin/notes.c:217
+#, c-format
+msgid "The note contents has been left in %s"
+msgstr ""
+
+#: builtin/notes.c:251 builtin/tag.c:521
+#, c-format
+msgid "cannot read '%s'"
+msgstr ""
+
+#: builtin/notes.c:253 builtin/tag.c:524
+#, c-format
+msgid "could not open or read '%s'"
+msgstr ""
+
+#: builtin/notes.c:272 builtin/notes.c:445 builtin/notes.c:447
+#: builtin/notes.c:507 builtin/notes.c:561 builtin/notes.c:644
+#: builtin/notes.c:649 builtin/notes.c:724 builtin/notes.c:766
+#: builtin/notes.c:968 builtin/reset.c:293 builtin/tag.c:537
+#, c-format
+msgid "Failed to resolve '%s' as a valid ref."
+msgstr ""
+
+#: builtin/notes.c:275
+#, c-format
+msgid "Failed to read object '%s'."
+msgstr ""
+
+#: builtin/notes.c:299
+msgid "Cannot commit uninitialized/unreferenced notes tree"
+msgstr ""
+
+#: builtin/notes.c:340
+#, c-format
+msgid "Bad notes.rewriteMode value: '%s'"
+msgstr ""
+
+#: builtin/notes.c:350
+#, c-format
+msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
+msgstr ""
+
+#. TRANSLATORS: The first %s is the name of the
+#. environment variable, the second %s is its value
+#: builtin/notes.c:377
+#, c-format
+msgid "Bad %s value: '%s'"
+msgstr ""
+
+#: builtin/notes.c:441
+#, c-format
+msgid "Malformed input line: '%s'."
+msgstr ""
+
+#: builtin/notes.c:456
+#, c-format
+msgid "Failed to copy notes from '%s' to '%s'"
+msgstr ""
+
+#: builtin/notes.c:500 builtin/notes.c:554 builtin/notes.c:627
+#: builtin/notes.c:639 builtin/notes.c:712 builtin/notes.c:759
+#: builtin/notes.c:1033
+msgid "too many parameters"
+msgstr ""
+
+#: builtin/notes.c:513 builtin/notes.c:772
+#, c-format
+msgid "No note found for object %s."
+msgstr ""
+
+#: builtin/notes.c:580
+#, c-format
+msgid ""
+"Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite "
+"existing notes"
+msgstr ""
+
+#: builtin/notes.c:585 builtin/notes.c:662
+#, c-format
+msgid "Overwriting existing notes for object %s\n"
+msgstr ""
+
+#: builtin/notes.c:635
+msgid "too few parameters"
+msgstr ""
+
+#: builtin/notes.c:656
+#, c-format
+msgid ""
+"Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite "
+"existing notes"
+msgstr ""
+
+#: builtin/notes.c:668
+#, c-format
+msgid "Missing notes on source object %s. Cannot copy."
+msgstr ""
+
+#: builtin/notes.c:717
+#, c-format
+msgid ""
+"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"
+msgstr ""
+
+#: builtin/notes.c:971
+#, c-format
+msgid "Object %s has no note\n"
+msgstr ""
+
+#: builtin/notes.c:1103
+#, c-format
+msgid "Unknown subcommand: %s"
+msgstr ""
+
+#: builtin/pack-objects.c:2310
+#, c-format
+msgid "unsupported index version %s"
+msgstr ""
+
+#: builtin/pack-objects.c:2314
+#, c-format
+msgid "bad index version '%s'"
+msgstr ""
+
+#: builtin/pack-objects.c:2322
+#, c-format
+msgid "option %s does not accept negative form"
+msgstr ""
+
+#: builtin/pack-objects.c:2326
+#, c-format
+msgid "unable to parse value '%s' for option %s"
+msgstr ""
+
+#: builtin/push.c:44
+msgid "tag shorthand without <tag>"
+msgstr ""
+
+#: builtin/push.c:63
+msgid "--delete only accepts plain target ref names"
+msgstr ""
+
+#: builtin/push.c:73
+#, c-format
+msgid ""
+"You are not currently on a branch.\n"
+"To push the history leading to the current (detached HEAD)\n"
+"state now, use\n"
+"\n"
+" git push %s HEAD:<name-of-remote-branch>\n"
+msgstr ""
+
+#: builtin/push.c:80
+#, c-format
+msgid ""
+"The current branch %s has no upstream branch.\n"
+"To push the current branch and set the remote as upstream, use\n"
+"\n"
+" git push --set-upstream %s %s\n"
+msgstr ""
+
+#: builtin/push.c:88
+#, c-format
+msgid "The current branch %s has multiple upstream branches, refusing to push."
+msgstr ""
+
+#: builtin/push.c:111
+msgid ""
+"You didn't specify any refspecs to push, and push.default is \"nothing\"."
+msgstr ""
+
+#: builtin/push.c:131
+#, c-format
+msgid "Pushing to %s\n"
+msgstr ""
+
+#: builtin/push.c:135
+#, c-format
+msgid "failed to push some refs to '%s'"
+msgstr ""
+
+#: builtin/push.c:143
+#, c-format
+msgid ""
+"To prevent you from losing history, non-fast-forward updates were rejected\n"
+"Merge the remote changes (e.g. 'git pull') before pushing again. See the\n"
+"'Note about fast-forwards' section of 'git push --help' for details.\n"
+msgstr ""
+
+#: builtin/push.c:160
+#, c-format
+msgid "bad repository '%s'"
+msgstr ""
+
+#: builtin/push.c:161
+msgid ""
+"No configured push destination.\n"
+"Either specify the URL from the command-line or configure a remote "
+"repository using\n"
+"\n"
+" git remote add <name> <url>\n"
+"\n"
+"and then push using the remote name\n"
+"\n"
+" git push <name>\n"
+msgstr ""
+
+#: builtin/push.c:176
+msgid "--all and --tags are incompatible"
+msgstr ""
+
+#: builtin/push.c:177
+msgid "--all can't be combined with refspecs"
+msgstr ""
+
+#: builtin/push.c:182
+msgid "--mirror and --tags are incompatible"
+msgstr ""
+
+#: builtin/push.c:183
+msgid "--mirror can't be combined with refspecs"
+msgstr ""
+
+#: builtin/push.c:188
+msgid "--all and --mirror are incompatible"
+msgstr ""
+
+#: builtin/push.c:274
+msgid "--delete is incompatible with --all, --mirror and --tags"
+msgstr ""
+
+#: builtin/push.c:276
+msgid "--delete doesn't make sense without any refs"
+msgstr ""
+
+#: builtin/reset.c:33
+msgid "mixed"
+msgstr ""
+
+#: builtin/reset.c:33
+msgid "soft"
+msgstr ""
+
+#: builtin/reset.c:33
+msgid "hard"
+msgstr ""
+
+#: builtin/reset.c:33
+msgid "keep"
+msgstr ""
+
+#: builtin/reset.c:77
+msgid "You do not have a valid HEAD."
+msgstr ""
+
+#: builtin/reset.c:79
+msgid "Failed to find tree of HEAD."
+msgstr ""
+
+#: builtin/reset.c:85
+#, c-format
+msgid "Failed to find tree of %s."
+msgstr ""
+
+#: builtin/reset.c:96
+msgid "Could not write new index file."
+msgstr ""
+
+#: builtin/reset.c:106
+#, c-format
+msgid "HEAD is now at %s"
+msgstr ""
+
+#: builtin/reset.c:130
+msgid "Could not read index"
+msgstr ""
+
+#: builtin/reset.c:133
+msgid "Unstaged changes after reset:"
+msgstr ""
+
+#: builtin/reset.c:223
+#, c-format
+msgid "Cannot do a %s reset in the middle of a merge."
+msgstr ""
+
+#: builtin/reset.c:297
+#, c-format
+msgid "Could not parse object '%s'."
+msgstr ""
+
+#: builtin/reset.c:302
+msgid "--patch is incompatible with --{hard,mixed,soft}"
+msgstr ""
+
+#: builtin/reset.c:311
+msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
+msgstr ""
+
+#: builtin/reset.c:313
+#, c-format
+msgid "Cannot do %s reset with paths."
+msgstr ""
+
+#: builtin/reset.c:325
+#, c-format
+msgid "%s reset is not allowed in a bare repository"
+msgstr ""
+
+#: builtin/reset.c:341
+#, c-format
+msgid "Could not reset index file to revision '%s'."
+msgstr ""
+
+#: builtin/revert.c:70 builtin/revert.c:91
+#, c-format
+msgid "%s: %s cannot be used with %s"
+msgstr ""
+
+#: builtin/revert.c:126
+msgid "program error"
+msgstr ""
+
+#: builtin/revert.c:209
+msgid "revert failed"
+msgstr ""
+
+#: builtin/revert.c:224
+msgid "cherry-pick failed"
+msgstr ""
+
+#: builtin/rm.c:109
+#, c-format
+msgid ""
+"'%s' has staged content different from both the file and the HEAD\n"
+"(use -f to force removal)"
+msgstr ""
+
+#: builtin/rm.c:115
+#, c-format
+msgid ""
+"'%s' has changes staged in the index\n"
+"(use --cached to keep the file, or -f to force removal)"
+msgstr ""
+
+#: builtin/rm.c:119
+#, c-format
+msgid ""
+"'%s' has local modifications\n"
+"(use --cached to keep the file, or -f to force removal)"
+msgstr ""
+
+#: builtin/rm.c:194
+#, c-format
+msgid "not removing '%s' recursively without -r"
+msgstr ""
+
+#: builtin/rm.c:230
+#, c-format
+msgid "git rm: unable to remove %s"
+msgstr ""
+
+#: builtin/shortlog.c:157
+#, c-format
+msgid "Missing author: %s"
+msgstr ""
+
+#: builtin/tag.c:58
+#, c-format
+msgid "malformed object at '%s'"
+msgstr ""
+
+#: builtin/tag.c:205
+#, c-format
+msgid "tag name too long: %.*s..."
+msgstr ""
+
+#: builtin/tag.c:210
+#, c-format
+msgid "tag '%s' not found."
+msgstr ""
+
+#: builtin/tag.c:225
+#, c-format
+msgid "Deleted tag '%s' (was %s)\n"
+msgstr ""
+
+#: builtin/tag.c:237
+#, c-format
+msgid "could not verify the tag '%s'"
+msgstr ""
+
+#: builtin/tag.c:247
+msgid ""
+"\n"
+"#\n"
+"# Write a tag message\n"
+"# Lines starting with '#' will be ignored.\n"
+"#\n"
+msgstr ""
+
+#: builtin/tag.c:254
+msgid ""
+"\n"
+"#\n"
+"# Write a tag message\n"
+"# Lines starting with '#' will be kept; you may remove them yourself if you "
+"want to.\n"
+"#\n"
+msgstr ""
+
+#: builtin/tag.c:294
+msgid "unable to sign the tag"
+msgstr ""
+
+#: builtin/tag.c:296
+msgid "unable to write tag file"
+msgstr ""
+
+#: builtin/tag.c:321
+msgid "bad object type."
+msgstr ""
+
+#: builtin/tag.c:334
+msgid "tag header too big."
+msgstr ""
+
+#: builtin/tag.c:366
+msgid "no tag message?"
+msgstr ""
+
+#: builtin/tag.c:372
+#, c-format
+msgid "The tag message has been left in %s\n"
+msgstr ""
+
+#: builtin/tag.c:421
+msgid "switch 'points-at' requires an object"
+msgstr ""
+
+#: builtin/tag.c:423
+#, c-format
+msgid "malformed object name '%s'"
+msgstr ""
+
+#: builtin/tag.c:502
+msgid "-n option is only allowed with -l."
+msgstr ""
+
+#: builtin/tag.c:504
+msgid "--contains option is only allowed with -l."
+msgstr ""
+
+#: builtin/tag.c:506
+msgid "--points-at option is only allowed with -l."
+msgstr ""
+
+#: builtin/tag.c:514
+msgid "only one -F or -m option is allowed."
+msgstr ""
+
+#: builtin/tag.c:534
+msgid "too many params"
+msgstr ""
+
+#: builtin/tag.c:540
+#, c-format
+msgid "'%s' is not a valid tag name."
+msgstr ""
+
+#: builtin/tag.c:545
+#, c-format
+msgid "tag '%s' already exists"
+msgstr ""
+
+#: builtin/tag.c:563
+#, c-format
+msgid "%s: cannot lock the ref"
+msgstr ""
+
+#: builtin/tag.c:565
+#, c-format
+msgid "%s: cannot update the ref"
+msgstr ""
+
+#: builtin/tag.c:567
+#, c-format
+msgid "Updated tag '%s' (was %s)\n"
+msgstr ""
+
+#: git-am.sh:49
+msgid "You need to set your committer info first"
+msgstr ""
+
+#: git-am.sh:136
+msgid "Repository lacks necessary blobs to fall back on 3-way merge."
+msgstr ""
+
+#: git-am.sh:147
+msgid ""
+"Did you hand edit your patch?\n"
+"It does not apply to blobs recorded in its index."
+msgstr ""
+
+#: git-am.sh:156
+msgid "Falling back to patching base and 3-way merge..."
+msgstr ""
+
+#: git-am.sh:268
+msgid "Only one StGIT patch series can be applied at once"
+msgstr ""
+
+#: git-am.sh:355
+#, sh-format
+msgid "Patch format $patch_format is not supported."
+msgstr ""
+
+#: git-am.sh:357
+msgid "Patch format detection failed."
+msgstr ""
+
+#: git-am.sh:411
+msgid "-d option is no longer supported. Do not use."
+msgstr ""
+
+#: git-am.sh:474
+#, sh-format
+msgid "previous rebase directory $dotest still exists but mbox given."
+msgstr ""
+
+#: git-am.sh:479
+msgid "Please make up your mind. --skip or --abort?"
+msgstr ""
+
+#: git-am.sh:506
+msgid "Resolve operation not in progress, we are not resuming."
+msgstr ""
+
+#: git-am.sh:572
+#, sh-format
+msgid "Dirty index: cannot apply patches (dirty: $files)"
+msgstr ""
+
+#: git-am.sh:748
+msgid "cannot be interactive without stdin connected to a terminal."
+msgstr ""
+
+#. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
+#. in your translation. The program will only accept English
+#. input at this point.
+#: git-am.sh:759
+msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
+msgstr ""
+
+#: git-am.sh:795
+#, sh-format
+msgid "Applying: $FIRSTLINE"
+msgstr ""
+
+#: git-am.sh:840
+msgid "No changes -- Patch already applied."
+msgstr ""
+
+#: git-am.sh:866
+msgid "applying to an empty history"
+msgstr ""
+
+#. TRANSLATORS: Make sure to include [Y] and [n] in your
+#. translation. The program will only accept English input
+#. at this point.
+#: git-bisect.sh:54
+msgid "Do you want me to do it for you [Y/n]? "
+msgstr ""
+
+#: git-bisect.sh:95
+#, sh-format
+msgid "unrecognised option: '$arg'"
+msgstr ""
+
+#: git-bisect.sh:99
+#, sh-format
+msgid "'$arg' does not appear to be a valid revision"
+msgstr ""
+
+#: git-bisect.sh:117
+msgid "Bad HEAD - I need a HEAD"
+msgstr ""
+
+#: git-bisect.sh:130
+#, sh-format
+msgid ""
+"Checking out '$start_head' failed. Try 'git bisect reset <validbranch>'."
+msgstr ""
+
+#: git-bisect.sh:140
+msgid "won't bisect on seeked tree"
+msgstr ""
+
+#: git-bisect.sh:144
+msgid "Bad HEAD - strange symbolic ref"
+msgstr ""
+
+#: git-bisect.sh:189
+#, sh-format
+msgid "Bad bisect_write argument: $state"
+msgstr ""
+
+#: git-bisect.sh:218
+#, sh-format
+msgid "Bad rev input: $arg"
+msgstr ""
+
+#: git-bisect.sh:232
+msgid "Please call 'bisect_state' with at least one argument."
+msgstr ""
+
+#: git-bisect.sh:244
+#, sh-format
+msgid "Bad rev input: $rev"
+msgstr ""
+
+#: git-bisect.sh:250
+msgid "'git bisect bad' can take only one argument."
+msgstr ""
+
+#. TRANSLATORS: Make sure to include [Y] and [n] in your
+#. translation. The program will only accept English input
+#. at this point.
+#: git-bisect.sh:279
+msgid "Are you sure [Y/n]? "
+msgstr ""
+
+#: git-bisect.sh:354
+#, sh-format
+msgid "'$invalid' is not a valid commit"
+msgstr ""
+
+#: git-bisect.sh:363
+#, sh-format
+msgid ""
+"Could not check out original HEAD '$branch'.\n"
+"Try 'git bisect reset <commit>'."
+msgstr ""
+
+#: git-bisect.sh:390
+msgid "No logfile given"
+msgstr ""
+
+#: git-bisect.sh:391
+#, sh-format
+msgid "cannot read $file for replaying"
+msgstr ""
+
+#: git-bisect.sh:408
+msgid "?? what are you talking about?"
+msgstr ""
+
+#: git-bisect.sh:474
+msgid "We are not bisecting."
+msgstr ""
+
+#: git-pull.sh:21
+msgid ""
+"Pull is not possible because you have unmerged files.\n"
+"Please, fix them up in the work tree, and then use 'git add/rm <file>'\n"
+"as appropriate to mark resolution, or use 'git commit -a'."
+msgstr ""
+
+#: git-pull.sh:25
+msgid "Pull is not possible because you have unmerged files."
+msgstr ""
+
+#: git-pull.sh:197
+msgid "updating an unborn branch with changes added to the index"
+msgstr ""
+
+#: git-pull.sh:253
+msgid "Cannot merge multiple branches into empty head"
+msgstr ""
+
+#: git-pull.sh:257
+msgid "Cannot rebase onto multiple branches"
+msgstr ""
+
+#: git-stash.sh:51
+msgid "git stash clear with parameters is unimplemented"
+msgstr ""
+
+#: git-stash.sh:74
+msgid "You do not have the initial commit yet"
+msgstr ""
+
+#: git-stash.sh:89
+msgid "Cannot save the current index state"
+msgstr ""
+
+#: git-stash.sh:123 git-stash.sh:136
+msgid "Cannot save the current worktree state"
+msgstr ""
+
+#: git-stash.sh:140
+msgid "No changes selected"
+msgstr ""
+
+#: git-stash.sh:143
+msgid "Cannot remove temporary index (can't happen)"
+msgstr ""
+
+#: git-stash.sh:156
+msgid "Cannot record working tree state"
+msgstr ""
+
+#: git-stash.sh:223
+msgid "No local changes to save"
+msgstr ""
+
+#: git-stash.sh:227
+msgid "Cannot initialize stash"
+msgstr ""
+
+#: git-stash.sh:235
+msgid "Cannot save the current status"
+msgstr ""
+
+#: git-stash.sh:253
+msgid "Cannot remove worktree changes"
+msgstr ""
+
+#: git-stash.sh:352
+msgid "No stash found."
+msgstr ""
+
+#: git-stash.sh:359
+#, sh-format
+msgid "Too many revisions specified: $REV"
+msgstr ""
+
+#: git-stash.sh:365
+#, sh-format
+msgid "$reference is not valid reference"
+msgstr ""
+
+#: git-stash.sh:393
+#, sh-format
+msgid "'$args' is not a stash-like commit"
+msgstr ""
+
+#: git-stash.sh:404
+#, sh-format
+msgid "'$args' is not a stash reference"
+msgstr ""
+
+#: git-stash.sh:412
+msgid "unable to refresh index"
+msgstr ""
+
+#: git-stash.sh:416
+msgid "Cannot apply a stash in the middle of a merge"
+msgstr ""
+
+#: git-stash.sh:424
+msgid "Conflicts in index. Try without --index."
+msgstr ""
+
+#: git-stash.sh:426
+msgid "Could not save index tree"
+msgstr ""
+
+#: git-stash.sh:460
+msgid "Cannot unstage modified files"
+msgstr ""
+
+#: git-stash.sh:491
+#, sh-format
+msgid "Dropped ${REV} ($s)"
+msgstr ""
+
+#: git-stash.sh:492
+#, sh-format
+msgid "${REV}: Could not drop stash entry"
+msgstr ""
+
+#: git-stash.sh:499
+msgid "No branch name specified"
+msgstr ""
+
+#: git-stash.sh:570
+msgid "(To restore them type \"git stash apply\")"
+msgstr ""
+
+#: git-submodule.sh:56
+#, sh-format
+msgid "cannot strip one component off url '$remoteurl'"
+msgstr ""
+
+#: git-submodule.sh:108
+#, sh-format
+msgid "No submodule mapping found in .gitmodules for path '$path'"
+msgstr ""
+
+#: git-submodule.sh:149
+#, sh-format
+msgid "Clone of '$url' into submodule path '$path' failed"
+msgstr ""
+
+#: git-submodule.sh:159
+#, sh-format
+msgid "Gitdir '$a' is part of the submodule path '$b' or vice versa"
+msgstr ""
+
+#: git-submodule.sh:247
+#, sh-format
+msgid "repo URL: '$repo' must be absolute or begin with ./|../"
+msgstr ""
+
+#: git-submodule.sh:264
+#, sh-format
+msgid "'$path' already exists in the index"
+msgstr ""
+
+#: git-submodule.sh:281
+#, sh-format
+msgid "'$path' already exists and is not a valid git repo"
+msgstr ""
+
+#: git-submodule.sh:295
+#, sh-format
+msgid "Unable to checkout submodule '$path'"
+msgstr ""
+
+#: git-submodule.sh:300
+#, sh-format
+msgid "Failed to add submodule '$path'"
+msgstr ""
+
+#: git-submodule.sh:305
+#, sh-format
+msgid "Failed to register submodule '$path'"
+msgstr ""
+
+#: git-submodule.sh:347
+#, sh-format
+msgid "Entering '$prefix$path'"
+msgstr ""
+
+#: git-submodule.sh:359
+#, sh-format
+msgid "Stopping at '$path'; script returned non-zero status."
+msgstr ""
+
+#: git-submodule.sh:401
+#, sh-format
+msgid "No url found for submodule path '$path' in .gitmodules"
+msgstr ""
+
+#: git-submodule.sh:410
+#, sh-format
+msgid "Failed to register url for submodule path '$path'"
+msgstr ""
+
+#: git-submodule.sh:418
+#, sh-format
+msgid "Failed to register update mode for submodule path '$path'"
+msgstr ""
+
+#: git-submodule.sh:420
+#, sh-format
+msgid "Submodule '$name' ($url) registered for path '$path'"
+msgstr ""
+
+#: git-submodule.sh:519
+#, sh-format
+msgid ""
+"Submodule path '$path' not initialized\n"
+"Maybe you want to use 'update --init'?"
+msgstr ""
+
+#: git-submodule.sh:532
+#, sh-format
+msgid "Unable to find current revision in submodule path '$path'"
+msgstr ""
+
+#: git-submodule.sh:551
+#, sh-format
+msgid "Unable to fetch in submodule path '$path'"
+msgstr ""
+
+#: git-submodule.sh:565
+#, sh-format
+msgid "Unable to rebase '$sha1' in submodule path '$path'"
+msgstr ""
+
+#: git-submodule.sh:566
+#, sh-format
+msgid "Submodule path '$path': rebased into '$sha1'"
+msgstr ""
+
+#: git-submodule.sh:571
+#, sh-format
+msgid "Unable to merge '$sha1' in submodule path '$path'"
+msgstr ""
+
+#: git-submodule.sh:572
+#, sh-format
+msgid "Submodule path '$path': merged in '$sha1'"
+msgstr ""
+
+#: git-submodule.sh:577
+#, sh-format
+msgid "Unable to checkout '$sha1' in submodule path '$path'"
+msgstr ""
+
+#: git-submodule.sh:578
+#, sh-format
+msgid "Submodule path '$path': checked out '$sha1'"
+msgstr ""
+
+#: git-submodule.sh:600 git-submodule.sh:923
+#, sh-format
+msgid "Failed to recurse into submodule path '$path'"
+msgstr ""
+
+#: git-submodule.sh:708
+msgid "--"
+msgstr ""
+
+#: git-submodule.sh:766
+#, sh-format
+msgid " Warn: $name doesn't contain commit $sha1_src"
+msgstr ""
+
+#: git-submodule.sh:769
+#, sh-format
+msgid " Warn: $name doesn't contain commit $sha1_dst"
+msgstr ""
+
+#: git-submodule.sh:772
+#, sh-format
+msgid " Warn: $name doesn't contain commits $sha1_src and $sha1_dst"
+msgstr ""
+
+#: git-submodule.sh:797
+msgid "blob"
+msgstr ""
+
+#: git-submodule.sh:798
+msgid "submodule"
+msgstr ""
+
+#: git-submodule.sh:969
+#, sh-format
+msgid "Synchronizing submodule url for '$name'"
+msgstr ""
diff --git a/po/de.po b/po/de.po
new file mode 100644
index 0000000000..a43f646450
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,3825 @@
+# German translations for Git.
+# Copyright (C) 2010-2012 Ralf Thielow <ralf.thielow@googlemail.com>
+# This file is distributed under the same license as the Git package.
+# Ralf Thielow <ralf.thielow@googlemail.com>, 2010, 2011, 2012.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: git 1.7.10\n"
+"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
+"POT-Creation-Date: 2012-04-28 20:17+0800\n"
+"PO-Revision-Date: 2012-03-28 18:46+0200\n"
+"Last-Translator: Ralf Thielow <ralf.thielow@googlemail.com>\n"
+"Language-Team: German\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: advice.c:40
+#, c-format
+msgid "hint: %.*s\n"
+msgstr "Hinweis: %.*s\n"
+
+#.
+#. * Message used both when 'git commit' fails and when
+#. * other commands doing a merge do.
+#.
+#: advice.c:70
+msgid ""
+"Fix them up in the work tree,\n"
+"and then use 'git add/rm <file>' as\n"
+"appropriate to mark resolution and make a commit,\n"
+"or use 'git commit -a'."
+msgstr ""
+"Korrigiere dies im Arbeitsbaum,\n"
+"und benutze dann 'git add/rm <Datei>' wie\n"
+"vorgesehen, um die Auflösung zu markieren und dann einzutragen,\n"
+"oder benutze 'git commit -a'."
+
+#: commit.c:48
+#, c-format
+msgid "could not parse %s"
+msgstr "konnte %s nicht parsen"
+
+#: commit.c:50
+#, c-format
+msgid "%s %s is not a commit!"
+msgstr "%s %s ist keine Version!"
+
+#: compat/obstack.c:406 compat/obstack.c:408
+msgid "memory exhausted"
+msgstr "Speicher verbraucht"
+
+#: connected.c:39
+msgid "Could not run 'git rev-list'"
+msgstr "'git rev-list' konnte nicht ausgeführt werden"
+
+#: connected.c:48
+#, c-format
+msgid "failed write to rev-list: %s"
+msgstr "Fehler beim Schreiben nach rev-list: %s"
+
+#: connected.c:56
+#, c-format
+msgid "failed to close rev-list's stdin: %s"
+msgstr "Fehler beim Schließen von rev-list's Standard-Eingabe: %s"
+
+#: diff.c:105
+#, c-format
+msgid " Failed to parse dirstat cut-off percentage '%.*s'\n"
+msgstr ""
+" Fehler beim Parsen des abgeschnittenen \"dirstat\" Prozentsatzes '%.*s'\n"
+
+#: diff.c:110
+#, c-format
+msgid " Unknown dirstat parameter '%.*s'\n"
+msgstr " Unbekannter \"dirstat\" Parameter '%.*s'\n"
+
+#: diff.c:210
+#, c-format
+msgid ""
+"Found errors in 'diff.dirstat' config variable:\n"
+"%s"
+msgstr ""
+"Fehler in 'diff.dirstat' Konfigurationsvariable gefunden:\n"
+"%s"
+
+#: diff.c:1400
+msgid " 0 files changed\n"
+msgstr " 0 Dateien geändert\n"
+
+#: diff.c:1404
+#, c-format
+msgid " %d file changed"
+msgid_plural " %d files changed"
+msgstr[0] " %d Datei geändert"
+msgstr[1] " %d Dateien geändert"
+
+#: diff.c:1421
+#, c-format
+msgid ", %d insertion(+)"
+msgid_plural ", %d insertions(+)"
+msgstr[0] ", %d Zeile hinzugefügt(+)"
+msgstr[1] ", %d Zeilen hinzugefügt(+)"
+
+#: diff.c:1432
+#, c-format
+msgid ", %d deletion(-)"
+msgid_plural ", %d deletions(-)"
+msgstr[0] ", %d Zeile entfernt(-)"
+msgstr[1] ", %d Zeilen entfernt(-)"
+
+#: diff.c:3435
+#, c-format
+msgid ""
+"Failed to parse --dirstat/-X option parameter:\n"
+"%s"
+msgstr ""
+"Fehler beim Parsen des --dirstat/-X Optionsparameters:\n"
+"%s"
+
+#: gpg-interface.c:59
+msgid "could not run gpg."
+msgstr "gpg konnte nicht ausgeführt werden"
+
+#: gpg-interface.c:71
+msgid "gpg did not accept the data"
+msgstr "gpg hat die Daten nicht akzeptiert"
+
+#: gpg-interface.c:82
+msgid "gpg failed to sign the data"
+msgstr "gpg beim Signieren der Daten fehlgeschlagen"
+
+#: grep.c:1280
+#, c-format
+msgid "'%s': unable to read %s"
+msgstr "'%s': konnte nicht lesen %s"
+
+#: grep.c:1297
+#, c-format
+msgid "'%s': %s"
+msgstr "'%s': %s"
+
+#: grep.c:1308
+#, c-format
+msgid "'%s': short read %s"
+msgstr "'%s': kurz gelesen %s"
+
+#: help.c:287
+#, c-format
+msgid ""
+"'%s' appears to be a git command, but we were not\n"
+"able to execute it. Maybe git-%s is broken?"
+msgstr ""
+"'%s' scheint ein git-Kommando zu sein, konnte aber\n"
+"nicht ausgeführt werden. Vielleicht ist git-%s fehlerhaft?"
+
+#: remote.c:1607
+#, c-format
+msgid "Your branch is ahead of '%s' by %d commit.\n"
+msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
+msgstr[0] "Dein Zweig ist vor '%s' um %d Version.\n"
+msgstr[1] "Dein Zweig ist vor '%s' um %d Versionen.\n"
+
+#: remote.c:1613
+#, c-format
+msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
+msgid_plural ""
+"Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n"
+msgstr[0] ""
+"Dein Zweig ist hinter '%s' um %d Version, und kann vorgespult werden.\n"
+msgstr[1] ""
+"Dein Zweig ist hinter '%s' um %d Versionen, und kann vorgespult werden.\n"
+
+#: remote.c:1621
+#, c-format
+msgid ""
+"Your branch and '%s' have diverged,\n"
+"and have %d and %d different commit each, respectively.\n"
+msgid_plural ""
+"Your branch and '%s' have diverged,\n"
+"and have %d and %d different commits each, respectively.\n"
+msgstr[0] ""
+"Dein Zweig und '%s' sind divergiert,\n"
+"und haben jeweils %d und %d unterschiedliche Versionen.\n"
+msgstr[1] ""
+"Dein Zweig und '%s' sind divergiert,\n"
+"und haben jeweils %d und %d unterschiedliche Versionen.\n"
+
+#: sequencer.c:120 builtin/merge.c:865 builtin/merge.c:978
+#: builtin/merge.c:1088 builtin/merge.c:1098
+#, c-format
+msgid "Could not open '%s' for writing"
+msgstr "Konnte '%s' nicht zum Schreiben öffnen."
+
+#: sequencer.c:122 builtin/merge.c:333 builtin/merge.c:868
+#: builtin/merge.c:1090 builtin/merge.c:1103
+#, c-format
+msgid "Could not write to '%s'"
+msgstr "Konnte nicht nach '%s' schreiben."
+
+#: sequencer.c:143
+msgid ""
+"after resolving the conflicts, mark the corrected paths\n"
+"with 'git add <paths>' or 'git rm <paths>'"
+msgstr ""
+"nach Auflösung der Konflikte, markiere die korrigierten Pfade\n"
+"mit 'git add <Pfade>' oder 'git rm <Pfade>'"
+
+#: sequencer.c:146
+msgid ""
+"after resolving the conflicts, mark the corrected paths\n"
+"with 'git add <paths>' or 'git rm <paths>'\n"
+"and commit the result with 'git commit'"
+msgstr ""
+"nach Auflösung der Konflikte, markiere die korrigierten Pfade\n"
+"mit 'git add <Pfade>' oder 'git rm <Pfade>'und trage das Ergebnis ein mit "
+"'git commit'"
+
+#: sequencer.c:159 sequencer.c:685 sequencer.c:768
+#, c-format
+msgid "Could not write to %s"
+msgstr "Konnte nicht nach %s schreiben"
+
+#: sequencer.c:162
+#, c-format
+msgid "Error wrapping up %s"
+msgstr "Fehler bei Nachbereitung von %s"
+
+#: sequencer.c:177
+msgid "Your local changes would be overwritten by cherry-pick."
+msgstr ""
+"Deine lokalen Änderungen würden von \"cherry-pick\" überschrieben werden."
+
+#: sequencer.c:179
+msgid "Your local changes would be overwritten by revert."
+msgstr "Deine lokalen Änderungen würden von \"revert\" überschrieben werden."
+
+#: sequencer.c:182
+msgid "Commit your changes or stash them to proceed."
+msgstr "Trage deine Änderungen ein oder benutze \"stash\" um fortzufahren."
+
+#. TRANSLATORS: %s will be "revert" or "cherry-pick"
+#: sequencer.c:232
+#, c-format
+msgid "%s: Unable to write new index file"
+msgstr "%s: Konnte neue Bereitstellungsdatei nicht schreiben"
+
+#: sequencer.c:298
+msgid "Your index file is unmerged."
+msgstr "Deine Bereitstellungsdatei ist nicht zusammengeführt."
+
+#: sequencer.c:301
+msgid "You do not have a valid HEAD"
+msgstr "Du hast keine gültige Zweigspitze (HEAD)"
+
+#: sequencer.c:316
+#, c-format
+msgid "Commit %s is a merge but no -m option was given."
+msgstr ""
+"Version %s ist eine Zusammenführung, aber es wurde keine Option -m angegeben."
+
+#: sequencer.c:324
+#, c-format
+msgid "Commit %s does not have parent %d"
+msgstr "Version %s hat keinen Elternteil %d"
+
+#: sequencer.c:328
+#, c-format
+msgid "Mainline was specified but commit %s is not a merge."
+msgstr ""
+"Hauptlinie wurde spezifiziert, aber Version %s ist keine Zusammenführung."
+
+#. TRANSLATORS: The first %s will be "revert" or
+#. "cherry-pick", the second %s a SHA1
+#: sequencer.c:339
+#, c-format
+msgid "%s: cannot parse parent commit %s"
+msgstr "%s: kann Elternversion %s nicht parsen"
+
+#: sequencer.c:343
+#, c-format
+msgid "Cannot get commit message for %s"
+msgstr "Kann keine Versionsbeschreibung für %s bekommen"
+
+#: sequencer.c:427
+#, c-format
+msgid "could not revert %s... %s"
+msgstr "Konnte %s nicht zurücksetzen... %s"
+
+#: sequencer.c:428
+#, c-format
+msgid "could not apply %s... %s"
+msgstr "Konnte %s nicht anwenden... %s"
+
+#: sequencer.c:450 sequencer.c:909 builtin/log.c:289 builtin/log.c:719
+#: builtin/log.c:1335 builtin/log.c:1554 builtin/merge.c:347
+#: builtin/shortlog.c:181
+msgid "revision walk setup failed"
+msgstr "Einrichtung des Revisionsgangs fehlgeschlagen"
+
+#: sequencer.c:453
+msgid "empty commit set passed"
+msgstr "leere Menge von Versionen übergeben"
+
+#: sequencer.c:461
+#, c-format
+msgid "git %s: failed to read the index"
+msgstr "git %s: Fehler beim Lesen der Bereitstellung"
+
+#: sequencer.c:466
+#, c-format
+msgid "git %s: failed to refresh the index"
+msgstr "git %s: Fehler beim Aktualisieren der Bereitstellung"
+
+#: sequencer.c:551
+#, c-format
+msgid "Cannot %s during a %s"
+msgstr "Kann %s nicht während eines %s durchführen"
+
+#: sequencer.c:573
+#, c-format
+msgid "Could not parse line %d."
+msgstr "Konnte Zeile %d nicht parsen."
+
+#: sequencer.c:578
+msgid "No commits parsed."
+msgstr "Keine Versionen geparst."
+
+#: sequencer.c:591
+#, c-format
+msgid "Could not open %s"
+msgstr "%s konnte nicht geöffnet werden."
+
+#: sequencer.c:595
+#, c-format
+msgid "Could not read %s."
+msgstr "%s konnte nicht gelesen werden."
+
+#: sequencer.c:602
+#, c-format
+msgid "Unusable instruction sheet: %s"
+msgstr "Unbenutzbares Instruktionsblatt: %s"
+
+#: sequencer.c:630
+#, c-format
+msgid "Invalid key: %s"
+msgstr "Ungültiger Schlüssel: %s"
+
+#: sequencer.c:633
+#, c-format
+msgid "Invalid value for %s: %s"
+msgstr "Ungültiger Wert für %s: %s"
+
+#: sequencer.c:645
+#, c-format
+msgid "Malformed options sheet: %s"
+msgstr "Fehlerhaftes Optionsblatt: %s"
+
+#: sequencer.c:666
+msgid "a cherry-pick or revert is already in progress"
+msgstr "\"cherry-pick\" oder \"revert\" wird bereits ausgeführt"
+
+#: sequencer.c:667
+msgid "try \"git cherry-pick (--continue | --quit | --abort)\""
+msgstr "versuche \"git cherry-pick (--continue | --quit | --abort)\""
+
+#: sequencer.c:671
+#, c-format
+msgid "Could not create sequencer directory %s"
+msgstr "Konnte \"sequencer\"-Verzeichnis %s nicht erstellen"
+
+#: sequencer.c:687 sequencer.c:772
+#, c-format
+msgid "Error wrapping up %s."
+msgstr "Fehler beim Einpacken von %s."
+
+#: sequencer.c:706 sequencer.c:840
+msgid "no cherry-pick or revert in progress"
+msgstr "kein \"cherry-pick\" oder \"revert\" in Ausführung"
+
+#: sequencer.c:708
+msgid "cannot resolve HEAD"
+msgstr "kann Zweigspitze (HEAD) nicht auflösen"
+
+#: sequencer.c:710
+msgid "cannot abort from a branch yet to be born"
+msgstr "kann nicht von einem Zweig abbrechen, der noch geboren wird"
+
+#: sequencer.c:732
+#, c-format
+msgid "cannot open %s: %s"
+msgstr "Kann %s nicht öffnen: %s"
+
+#: sequencer.c:735
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "Kann %s nicht lesen: %s"
+
+#: sequencer.c:736
+msgid "unexpected end of file"
+msgstr "Unerwartetes Dateiende"
+
+#: sequencer.c:742
+#, c-format
+msgid "stored pre-cherry-pick HEAD file '%s' is corrupt"
+msgstr ""
+"gespeicherte \"pre-cherry-pick\" Datei der Zweigspitze (HEAD) '%s' ist "
+"beschädigt"
+
+#: sequencer.c:765
+#, c-format
+msgid "Could not format %s."
+msgstr "Konnte %s nicht formatieren."
+
+#: sequencer.c:927
+msgid "Can't revert as initial commit"
+msgstr "Kann nicht zu initialer Version zurücksetzen."
+
+#: sequencer.c:928
+msgid "Can't cherry-pick into empty head"
+msgstr "Kann \"cherry-pick\" nicht in einem leerem Kopf ausführen."
+
+#: sha1_name.c:864
+msgid "HEAD does not point to a branch"
+msgstr "Zweigspitze (HEAD) zeigt auf keinen Zweig"
+
+#: sha1_name.c:867
+#, c-format
+msgid "No such branch: '%s'"
+msgstr "Kein solcher Zweig '%s'"
+
+#: sha1_name.c:869
+#, c-format
+msgid "No upstream configured for branch '%s'"
+msgstr "Kein entferntes Projektarchiv für Zweig '%s' konfiguriert."
+
+#: sha1_name.c:872
+#, c-format
+msgid "Upstream branch '%s' not stored as a remote-tracking branch"
+msgstr "Zweig '%s' des entfernten Projektarchivs ist nicht als entfernter "
+"Übernahmezweig gespeichert"
+
+#: wt-status.c:134
+msgid "Unmerged paths:"
+msgstr "Nicht zusammengeführte Pfade:"
+
+#: wt-status.c:140 wt-status.c:157
+#, c-format
+msgid " (use \"git reset %s <file>...\" to unstage)"
+msgstr ""
+" (benutze \"git reset %s <Datei>...\" zum Herausnehmen aus der "
+"Bereitstellung)"
+
+#: wt-status.c:142 wt-status.c:159
+msgid " (use \"git rm --cached <file>...\" to unstage)"
+msgstr ""
+" (benutze \"git rm --cached <Datei>...\" zum Herausnehmen aus der "
+"Bereitstellung)"
+
+#: wt-status.c:143
+msgid " (use \"git add/rm <file>...\" as appropriate to mark resolution)"
+msgstr ""
+" (benutze \"git add/rm <Datei>...\" wie vorgesehen, um die Auflösung zu "
+"markieren)"
+
+#: wt-status.c:151
+msgid "Changes to be committed:"
+msgstr "zum Eintragen bereitgestellte Änderungen:"
+
+#: wt-status.c:169
+msgid "Changes not staged for commit:"
+msgstr "Änderungen, die nicht zum Eintragen bereitgestellt sind:"
+
+#: wt-status.c:173
+msgid " (use \"git add <file>...\" to update what will be committed)"
+msgstr " (benutze \"git add <Datei>...\" zur Aktualisierung der Eintragung)"
+
+#: wt-status.c:175
+msgid " (use \"git add/rm <file>...\" to update what will be committed)"
+msgstr ""
+" (benutze \"git add/rm <Datei>...\" zur Aktualisierung der Eintragung)"
+
+#: wt-status.c:176
+msgid ""
+" (use \"git checkout -- <file>...\" to discard changes in working directory)"
+msgstr ""
+" (benutze \"git checkout -- <Datei>...\" um die Änderungen im "
+"Arbeitsverzeichnis zu verwerfen)"
+
+#: wt-status.c:178
+msgid " (commit or discard the untracked or modified content in submodules)"
+msgstr ""
+" (trage ein oder verwerfe den ungefolgten oder geänderten Inhalt in den "
+"Unterprojekten)"
+
+#: wt-status.c:187
+#, c-format
+msgid "%s files:"
+msgstr "%s Dateien:"
+
+#: wt-status.c:190
+#, c-format
+msgid " (use \"git %s <file>...\" to include in what will be committed)"
+msgstr " (benutze \"git %s <Datei>...\" zum Einfügen in die Eintragung)"
+
+#: wt-status.c:207
+msgid "bug"
+msgstr "Fehler"
+
+#: wt-status.c:212
+msgid "both deleted:"
+msgstr "beide gelöscht:"
+
+#: wt-status.c:213
+msgid "added by us:"
+msgstr "von uns hinzugefügt:"
+
+#: wt-status.c:214
+msgid "deleted by them:"
+msgstr "von denen gelöscht:"
+
+#: wt-status.c:215
+msgid "added by them:"
+msgstr "von denen hinzugefügt:"
+
+#: wt-status.c:216
+msgid "deleted by us:"
+msgstr "von uns gelöscht:"
+
+#: wt-status.c:217
+msgid "both added:"
+msgstr "von beiden hinzugefügt:"
+
+#: wt-status.c:218
+msgid "both modified:"
+msgstr "von beiden geändert:"
+
+#: wt-status.c:248
+msgid "new commits, "
+msgstr "neue Versionen, "
+
+#: wt-status.c:250
+msgid "modified content, "
+msgstr "geänderter Inhalt, "
+
+#: wt-status.c:252
+msgid "untracked content, "
+msgstr "unverfolgter Inhalt, "
+
+#: wt-status.c:266
+#, c-format
+msgid "new file: %s"
+msgstr "neue Datei: %s"
+
+#: wt-status.c:269
+#, c-format
+msgid "copied: %s -> %s"
+msgstr "kopiert: %s -> %s"
+
+#: wt-status.c:272
+#, c-format
+msgid "deleted: %s"
+msgstr "gelöscht: %s"
+
+#: wt-status.c:275
+#, c-format
+msgid "modified: %s"
+msgstr "geändert: %s"
+
+#: wt-status.c:278
+#, c-format
+msgid "renamed: %s -> %s"
+msgstr "umbenannt: %s -> %s"
+
+#: wt-status.c:281
+#, c-format
+msgid "typechange: %s"
+msgstr "Typänderung: %s"
+
+#: wt-status.c:284
+#, c-format
+msgid "unknown: %s"
+msgstr "unbekannt: %s"
+
+#: wt-status.c:287
+#, c-format
+msgid "unmerged: %s"
+msgstr "nicht zusammengeführt: %s"
+
+#: wt-status.c:290
+#, c-format
+msgid "bug: unhandled diff status %c"
+msgstr "Fehler: unbehandelter Differenz-Status %c"
+
+#: wt-status.c:713
+msgid "On branch "
+msgstr "Auf Zweig "
+
+#: wt-status.c:720
+msgid "Not currently on any branch."
+msgstr "Im Moment auf keinem Zweig."
+
+#: wt-status.c:731
+msgid "Initial commit"
+msgstr "Initiale Version"
+
+#: wt-status.c:745
+msgid "Untracked"
+msgstr "Unverfolgte"
+
+#: wt-status.c:747
+msgid "Ignored"
+msgstr "Ignorierte"
+
+#: wt-status.c:749
+#, c-format
+msgid "Untracked files not listed%s"
+msgstr "Unverfolgte Dateien nicht aufgelistet%s"
+
+#: wt-status.c:751
+msgid " (use -u option to show untracked files)"
+msgstr " (benutze die Option -u um unverfolgte Dateien anzuzeigen)"
+
+#: wt-status.c:757
+msgid "No changes"
+msgstr "Keine Änderungen"
+
+#: wt-status.c:761
+#, c-format
+msgid "no changes added to commit%s\n"
+msgstr "keine Änderungen zum Eintragen hinzugefügt%s\n"
+
+#: wt-status.c:763
+msgid " (use \"git add\" and/or \"git commit -a\")"
+msgstr " (benutze \"git add\" und/oder \"git commit -a\")"
+
+#: wt-status.c:765
+#, c-format
+msgid "nothing added to commit but untracked files present%s\n"
+msgstr "nichts zum Eintragen hinzugefügt, aber es gibt unverfolgte Dateien%s\n"
+
+#: wt-status.c:767
+msgid " (use \"git add\" to track)"
+msgstr " (benutze \"git add\" zum Verfolgen)"
+
+#: wt-status.c:769 wt-status.c:772 wt-status.c:775
+#, c-format
+msgid "nothing to commit%s\n"
+msgstr "nichts zum Eintragen%s\n"
+
+#: wt-status.c:770
+msgid " (create/copy files and use \"git add\" to track)"
+msgstr " (Erstelle/Kopiere Dateien und benutze \"git add\" zum Verfolgen)"
+
+#: wt-status.c:773
+msgid " (use -u to show untracked files)"
+msgstr " (benutze -u um unverfolgte Dateien anzuzeigen)"
+
+#: wt-status.c:776
+msgid " (working directory clean)"
+msgstr " (Arbeitsverzeichnis sauber)"
+
+#: wt-status.c:884
+msgid "HEAD (no branch)"
+msgstr "HEAD (kein Zweig)"
+
+#: wt-status.c:890
+msgid "Initial commit on "
+msgstr "Initiale Version auf "
+
+#: wt-status.c:905
+msgid "behind "
+msgstr "hinter "
+
+#: wt-status.c:908 wt-status.c:911
+msgid "ahead "
+msgstr "über "
+
+#: wt-status.c:913
+msgid ", behind "
+msgstr ", hinter "
+
+#: builtin/add.c:62
+#, c-format
+msgid "unexpected diff status %c"
+msgstr "unerwarteter Differenz-Status %c"
+
+#: builtin/add.c:67 builtin/commit.c:298
+msgid "updating files failed"
+msgstr "Aktualisierung von Dateien fehlgeschlagen"
+
+#: builtin/add.c:77
+#, c-format
+msgid "remove '%s'\n"
+msgstr "entferne '%s'\n"
+
+#: builtin/add.c:176
+#, c-format
+msgid "Path '%s' is in submodule '%.*s'"
+msgstr "Pfad '%s' befindet sich in Unterprojekt '%.*s'"
+
+#: builtin/add.c:192
+msgid "Unstaged changes after refreshing the index:"
+msgstr ""
+"Nicht bereitgestellte Änderungen nach Aktualisierung der Bereitstellung:"
+
+#: builtin/add.c:195 builtin/add.c:456 builtin/rm.c:186
+#, c-format
+msgid "pathspec '%s' did not match any files"
+msgstr "Pfadspezifikation '%s' stimmt mit keinen Dateien überein"
+
+#: builtin/add.c:209
+#, c-format
+msgid "'%s' is beyond a symbolic link"
+msgstr "'%s' ist über einem symbolischen Link"
+
+#: builtin/add.c:276
+msgid "Could not read the index"
+msgstr "Konnte die Bereitstellung nicht lesen"
+
+#: builtin/add.c:286
+#, c-format
+msgid "Could not open '%s' for writing."
+msgstr "Konnte '%s' nicht zum Schreiben öffnen."
+
+#: builtin/add.c:290
+msgid "Could not write patch"
+msgstr "Konnte Patch nicht schreiben"
+
+#: builtin/add.c:295
+#, c-format
+msgid "Could not stat '%s'"
+msgstr "Verzeichnis '%s' konnte nicht gelesen werden"
+
+#: builtin/add.c:297
+msgid "Empty patch. Aborted."
+msgstr "Leerer Patch. Abgebrochen."
+
+#: builtin/add.c:303
+#, c-format
+msgid "Could not apply '%s'"
+msgstr "Konnte '%s' nicht anwenden."
+
+#: builtin/add.c:312
+msgid "The following paths are ignored by one of your .gitignore files:\n"
+msgstr ""
+"Die folgenden Pfade werden durch eine deiner \".gitignore\" Dateien "
+"ignoriert:\n"
+
+#: builtin/add.c:352
+#, c-format
+msgid "Use -f if you really want to add them.\n"
+msgstr "Verwende -f wenn du diese wirklich hinzufügen möchtest.\n"
+
+#: builtin/add.c:353
+msgid "no files added"
+msgstr "keine Dateien hinzugefügt"
+
+#: builtin/add.c:359
+msgid "adding files failed"
+msgstr "Hinzufügen von Dateien fehlgeschlagen"
+
+#: builtin/add.c:391
+msgid "-A and -u are mutually incompatible"
+msgstr "-A und -u sind zueinander inkompatibel"
+
+#: builtin/add.c:393
+msgid "Option --ignore-missing can only be used together with --dry-run"
+msgstr ""
+"Die Option --ignore-missing kann nur zusammen mit --dry-run benutzt werden."
+
+#: builtin/add.c:413
+#, c-format
+msgid "Nothing specified, nothing added.\n"
+msgstr "Nichts spezifiziert, nichts hinzugefügt.\n"
+
+#: builtin/add.c:414
+#, c-format
+msgid "Maybe you wanted to say 'git add .'?\n"
+msgstr "Wolltest du vieleicht 'git add .' sagen?\n"
+
+#: builtin/add.c:420 builtin/clean.c:95 builtin/commit.c:358 builtin/mv.c:82
+#: builtin/rm.c:162
+msgid "index file corrupt"
+msgstr "Bereitstellungsdatei beschädigt"
+
+#: builtin/add.c:476 builtin/mv.c:229 builtin/rm.c:260
+msgid "Unable to write new index file"
+msgstr "Konnte neue Bereitstellungsdatei nicht schreiben."
+
+#: builtin/archive.c:17
+#, c-format
+msgid "could not create archive file '%s'"
+msgstr "Konnte Archiv-Datei '%s' nicht erstellen."
+
+#: builtin/archive.c:20
+msgid "could not redirect output"
+msgstr "Konnte Ausgabe nicht umleiten."
+
+#: builtin/archive.c:37
+msgid "git archive: Remote with no URL"
+msgstr "git archive: Anderes Archiv ohne URL"
+
+#: builtin/archive.c:58
+msgid "git archive: expected ACK/NAK, got EOF"
+msgstr "git archive: habe ACK/NAK erwartet, aber EOF bekommen"
+
+#: builtin/archive.c:63
+#, c-format
+msgid "git archive: NACK %s"
+msgstr "git archive: NACK %s"
+
+#: builtin/archive.c:65
+#, c-format
+msgid "remote error: %s"
+msgstr "Versandfehler: %s"
+
+#: builtin/archive.c:66
+msgid "git archive: protocol error"
+msgstr "git archive: Protokollfehler"
+
+#: builtin/archive.c:71
+msgid "git archive: expected a flush"
+msgstr "git archive: erwartete eine Spülung (flush)"
+
+#: builtin/branch.c:137
+#, c-format
+msgid ""
+"deleting branch '%s' that has been merged to\n"
+" '%s', but not yet merged to HEAD."
+msgstr ""
+"entferne Zweig '%s' der zusammengeführt wurde mit\n"
+" '%s', aber noch nicht mit der Zweigspitze (HEAD) zusammengeführt "
+"wurde."
+
+#: builtin/branch.c:141
+#, c-format
+msgid ""
+"not deleting branch '%s' that is not yet merged to\n"
+" '%s', even though it is merged to HEAD."
+msgstr ""
+"entferne nicht Zweig '%s' der noch nicht zusammengeführt wurde mit\n"
+" '%s', obwohl er mit der Zweigspitze (HEAD) zusammengeführt wurde."
+
+#. TRANSLATORS: This is "remote " in "remote branch '%s' not found"
+#: builtin/branch.c:164
+msgid "remote "
+msgstr "entfernter "
+
+#: builtin/branch.c:172
+msgid "cannot use -a with -d"
+msgstr "kann -a nicht mit -d benutzen"
+
+#: builtin/branch.c:178
+msgid "Couldn't look up commit object for HEAD"
+msgstr "Konnte Versionsobjekt für Zweigspitze (HEAD) nicht nachschlagen."
+
+#: builtin/branch.c:183
+#, c-format
+msgid "Cannot delete the branch '%s' which you are currently on."
+msgstr "Kann Zweig '%s' nicht entfernen auf dem du dich gerade befindest."
+
+#: builtin/branch.c:193
+#, c-format
+msgid "%sbranch '%s' not found."
+msgstr "%sZweig '%s' nicht gefunden."
+
+#: builtin/branch.c:201
+#, c-format
+msgid "Couldn't look up commit object for '%s'"
+msgstr "Konnte Versionsobjekt für '%s' nicht nachschlagen."
+
+#: builtin/branch.c:207
+#, c-format
+msgid ""
+"The branch '%s' is not fully merged.\n"
+"If you are sure you want to delete it, run 'git branch -D %s'."
+msgstr ""
+"Der Zweig '%s' ist nicht vollständig zusammengeführt.\n"
+"Wenn du sicher bist diesen Zweig zu entfernen, führe 'git branch -D %s' aus."
+
+#: builtin/branch.c:215
+#, c-format
+msgid "Error deleting %sbranch '%s'"
+msgstr "Fehler beim Löschen von %sZweig '%s'"
+
+#: builtin/branch.c:221
+#, c-format
+msgid "Deleted %sbranch %s (was %s).\n"
+msgstr "Entferne %sZweig %s (war %s).\n"
+
+#: builtin/branch.c:226
+msgid "Update of config-file failed"
+msgstr "Aktualisierung der Konfigurationsdatei fehlgeschlagen."
+
+#: builtin/branch.c:324
+#, c-format
+msgid "branch '%s' does not point at a commit"
+msgstr "Zweig '%s' zeigt auf keine Version"
+
+#: builtin/branch.c:396
+#, c-format
+msgid "behind %d] "
+msgstr "hinter %d] "
+
+#: builtin/branch.c:398
+#, c-format
+msgid "ahead %d] "
+msgstr "vor %d] "
+
+#: builtin/branch.c:400
+#, c-format
+msgid "ahead %d, behind %d] "
+msgstr "vor %d, hinter %d] "
+
+#: builtin/branch.c:503
+msgid "(no branch)"
+msgstr "(kein Zweig)"
+
+#: builtin/branch.c:568
+msgid "some refs could not be read"
+msgstr "einige Referenzen konnten nicht gelesen werden"
+
+#: builtin/branch.c:581
+msgid "cannot rename the current branch while not on any."
+msgstr ""
+"Kann aktuellen Zweig nicht umbennen, solange du dich auf keinem befindest."
+
+#: builtin/branch.c:591
+#, c-format
+msgid "Invalid branch name: '%s'"
+msgstr "Ungültiger Zweig-Name: '%s'"
+
+#: builtin/branch.c:606
+msgid "Branch rename failed"
+msgstr "Umbenennung des Zweiges fehlgeschlagen"
+
+#: builtin/branch.c:610
+#, c-format
+msgid "Renamed a misnamed branch '%s' away"
+msgstr "falsch benannten Zweig '%s' umbenannt"
+
+#: builtin/branch.c:614
+#, c-format
+msgid "Branch renamed to %s, but HEAD is not updated!"
+msgstr "Zweig umbenannt zu %s, aber Zweigspitze (HEAD) ist nicht aktualisiert!"
+
+#: builtin/branch.c:621
+msgid "Branch is renamed, but update of config-file failed"
+msgstr ""
+"Zweig ist umbenannt, aber die Aktualisierung der Konfigurationsdatei ist "
+"fehlgeschlagen."
+
+#: builtin/branch.c:636
+#, c-format
+msgid "malformed object name %s"
+msgstr "Missgebildeter Objektname %s"
+
+#: builtin/branch.c:660
+#, c-format
+msgid "could not write branch description template: %s\n"
+msgstr "Konnte Beschreibungsvorlage für Zweig nicht schreiben: %s\n"
+
+#: builtin/branch.c:750
+msgid "Failed to resolve HEAD as a valid ref."
+msgstr "Zweigspitze (HEAD) konnte nicht als gültige Referenz aufgelöst werden."
+
+#: builtin/branch.c:755 builtin/clone.c:558
+msgid "HEAD not found below refs/heads!"
+msgstr "Zweigspitze (HEAD) wurde nicht unter \"refs/heads\" gefunden!"
+
+#: builtin/branch.c:813
+msgid "-a and -r options to 'git branch' do not make sense with a branch name"
+msgstr ""
+"Die Optionen -a und -r bei 'git branch' machen mit einem Zweignamen keinen "
+"Sinn."
+
+#: builtin/bundle.c:47
+#, c-format
+msgid "%s is okay\n"
+msgstr "%s ist in Ordnung\n"
+
+#: builtin/bundle.c:56
+msgid "Need a repository to create a bundle."
+msgstr "Um ein Paket zu erstellen wird ein Projektarchiv benötigt."
+
+#: builtin/bundle.c:60
+msgid "Need a repository to unbundle."
+msgstr "Zum Zerlegen wird ein Projektarchiv benötigt."
+
+#: builtin/checkout.c:113 builtin/checkout.c:146
+#, c-format
+msgid "path '%s' does not have our version"
+msgstr "Pfad '%s' hat nicht unsere Version."
+
+#: builtin/checkout.c:115 builtin/checkout.c:148
+#, c-format
+msgid "path '%s' does not have their version"
+msgstr "Pfad '%s' hat nicht deren Version."
+
+#: builtin/checkout.c:131
+#, c-format
+msgid "path '%s' does not have all necessary versions"
+msgstr "Pfad '%s' hat nicht alle notwendigen Versionen."
+
+#: builtin/checkout.c:175
+#, c-format
+msgid "path '%s' does not have necessary versions"
+msgstr "Pfad '%s' hat nicht die notwendigen Versionen."
+
+#: builtin/checkout.c:192
+#, c-format
+msgid "path '%s': cannot merge"
+msgstr "Pfad '%s': kann nicht zusammenführen"
+
+#: builtin/checkout.c:209
+#, c-format
+msgid "Unable to add merge result for '%s'"
+msgstr "Konnte Ergebnis der Zusammenführung von '%s' nicht hinzufügen."
+
+#: builtin/checkout.c:212 builtin/reset.c:158
+#, c-format
+msgid "make_cache_entry failed for path '%s'"
+msgstr "make_cache_entry für Pfad '%s' fehlgeschlagen"
+
+#: builtin/checkout.c:234 builtin/checkout.c:392
+msgid "corrupt index file"
+msgstr "beschädigte Bereitstellungsdatei"
+
+#: builtin/checkout.c:264 builtin/checkout.c:271
+#, c-format
+msgid "path '%s' is unmerged"
+msgstr "Pfad '%s' ist nicht zusammengeführt."
+
+#: builtin/checkout.c:302 builtin/checkout.c:498 builtin/clone.c:583
+#: builtin/merge.c:812
+msgid "unable to write new index file"
+msgstr "Konnte neue Bereitstellungsdatei nicht schreiben."
+
+#: builtin/checkout.c:319 builtin/diff.c:302 builtin/merge.c:408
+msgid "diff_setup_done failed"
+msgstr "diff_setup_done fehlgeschlagen"
+
+#: builtin/checkout.c:414
+msgid "you need to resolve your current index first"
+msgstr "Du musst zuerst deine aktuelle Bereitstellung auflösen."
+
+#: builtin/checkout.c:533
+#, c-format
+msgid "Can not do reflog for '%s'\n"
+msgstr "Konnte \"reflog\" für '%s' nicht durchführen\n"
+
+#: builtin/checkout.c:566
+msgid "HEAD is now at"
+msgstr "Zweigspitze (HEAD) ist jetzt bei"
+
+#: builtin/checkout.c:573
+#, c-format
+msgid "Reset branch '%s'\n"
+msgstr "Setze Zweig '%s' zurück\n"
+
+#: builtin/checkout.c:576
+#, c-format
+msgid "Already on '%s'\n"
+msgstr "Bereits auf '%s'\n"
+
+#: builtin/checkout.c:580
+#, c-format
+msgid "Switched to and reset branch '%s'\n"
+msgstr "Gewechselt zu zurückgesetztem Zweig '%s'\n"
+
+#: builtin/checkout.c:582
+#, c-format
+msgid "Switched to a new branch '%s'\n"
+msgstr "Gewechselt zu einem neuen Zweig '%s'\n"
+
+#: builtin/checkout.c:584
+#, c-format
+msgid "Switched to branch '%s'\n"
+msgstr "Gewechselt zu Zweig '%s'\n"
+
+#: builtin/checkout.c:640
+#, c-format
+msgid " ... and %d more.\n"
+msgstr " ... und %d weitere.\n"
+
+#. The singular version
+#: builtin/checkout.c:646
+#, c-format
+msgid ""
+"Warning: you are leaving %d commit behind, not connected to\n"
+"any of your branches:\n"
+"\n"
+"%s\n"
+msgid_plural ""
+"Warning: you are leaving %d commits behind, not connected to\n"
+"any of your branches:\n"
+"\n"
+"%s\n"
+msgstr[0] ""
+"Warnung: Du verlässt %d Version zurückliegend, nicht verbunden zu\n"
+"einem deiner Zweige:\n"
+"\n"
+"%s\n"
+msgstr[1] ""
+"Warnung: Du verlässt %d Versionen zurückliegend, nicht verbunden zu\n"
+"einem deiner Zweige:\n"
+"\n"
+"%s\n"
+
+#: builtin/checkout.c:664
+#, c-format
+msgid ""
+"If you want to keep them by creating a new branch, this may be a good time\n"
+"to do so with:\n"
+"\n"
+" git branch new_branch_name %s\n"
+"\n"
+msgstr ""
+"Wenn du diese durch einen neuen Zweig behalten möchtest, dann könnte jetzt\n"
+"ein guter Zeitpunkt sein dies zu tun mit:\n"
+"\n"
+" git branch neuer_zweig_name %s\n"
+"\n"
+
+#: builtin/checkout.c:693
+msgid "internal error in revision walk"
+msgstr "interner Fehler im Revisionsgang"
+
+#: builtin/checkout.c:697
+msgid "Previous HEAD position was"
+msgstr "Vorherige Position der Zweigspitze (HEAD) war"
+
+#: builtin/checkout.c:723
+msgid "You are on a branch yet to be born"
+msgstr "Du bist auf einem Zweig, der noch nicht geboren wurde."
+
+#. case (1)
+#: builtin/checkout.c:854
+#, c-format
+msgid "invalid reference: %s"
+msgstr "Ungültige Referenz: %s"
+
+#. case (1): want a tree
+#: builtin/checkout.c:893
+#, c-format
+msgid "reference is not a tree: %s"
+msgstr "Referenz ist kein Baum: %s"
+
+#: builtin/checkout.c:973
+msgid "-B cannot be used with -b"
+msgstr "-B kann nicht mit -b benutzt werden"
+
+#: builtin/checkout.c:982
+msgid "--patch is incompatible with all other options"
+msgstr "--patch ist inkompatibel mit allen anderen Optionen"
+
+#: builtin/checkout.c:985
+msgid "--detach cannot be used with -b/-B/--orphan"
+msgstr "--detach kann nicht mit -b/-B/--orphan benutzt werden"
+
+#: builtin/checkout.c:987
+msgid "--detach cannot be used with -t"
+msgstr "--detach kann nicht mit -t benutzt werden"
+
+#: builtin/checkout.c:993
+msgid "--track needs a branch name"
+msgstr "--track benötigt einen Zweignamen"
+
+#: builtin/checkout.c:1000
+msgid "Missing branch name; try -b"
+msgstr "Vermisse Zweignamen; versuche -b"
+
+#: builtin/checkout.c:1006
+msgid "--orphan and -b|-B are mutually exclusive"
+msgstr "--orphan und -b|-B sind gegenseitig exklusiv"
+
+#: builtin/checkout.c:1008
+msgid "--orphan cannot be used with -t"
+msgstr "--orphan kann nicht mit -t benutzt werden"
+
+#: builtin/checkout.c:1018
+msgid "git checkout: -f and -m are incompatible"
+msgstr "git checkout: -f und -m sind inkompatibel"
+
+#: builtin/checkout.c:1052
+msgid "invalid path specification"
+msgstr "ungültige Pfadspezifikation"
+
+#: builtin/checkout.c:1060
+#, c-format
+msgid ""
+"git checkout: updating paths is incompatible with switching branches.\n"
+"Did you intend to checkout '%s' which can not be resolved as commit?"
+msgstr ""
+"git checkout: Aktualisierung der Pfade ist inkompatibel mit dem Wechsel von "
+"Zweigen.\n"
+"Hast du beabsichtigt '%s' auszuchecken, welcher nicht als Version aufgelöst "
+"werden kann?"
+
+#: builtin/checkout.c:1062
+msgid "git checkout: updating paths is incompatible with switching branches."
+msgstr ""
+"git checkout: Aktualisierung von Pfaden ist inkompatibel mit dem Wechsel von "
+"Zweigen."
+
+#: builtin/checkout.c:1067
+msgid "git checkout: --detach does not take a path argument"
+msgstr "git checkout: --detach nimmt kein Pfad-Argument"
+
+#: builtin/checkout.c:1070
+msgid ""
+"git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
+"checking out of the index."
+msgstr ""
+"git checkout: --ours/--theirs, --force and --merge sind inkompatibel wenn\n"
+"du außerhalb der Bereitstellung auscheckst."
+
+#: builtin/checkout.c:1089
+msgid "Cannot switch branch to a non-commit."
+msgstr "Kann Zweig nur zu einer Version wechseln."
+
+#: builtin/checkout.c:1092
+msgid "--ours/--theirs is incompatible with switching branches."
+msgstr "--ours/--theirs ist inkompatibel mit den Wechseln von Zweigen."
+
+#: builtin/clean.c:78
+msgid "-x and -X cannot be used together"
+msgstr "-x und -X können nicht zusammen benutzt werden"
+
+#: builtin/clean.c:82
+msgid ""
+"clean.requireForce set to true and neither -n nor -f given; refusing to clean"
+msgstr ""
+"clean.requireForce auf \"true\" gesetzt und weder -n noch -f gegeben; "
+"Ablehnung der Reinigung"
+
+#: builtin/clean.c:85
+msgid ""
+"clean.requireForce defaults to true and neither -n nor -f given; refusing to "
+"clean"
+msgstr ""
+"clean.requireForce standardmäßig auf \"true\" gesetzt und weder -n noch -f "
+"gegeben; Ablehnung der Reinigung"
+
+#: builtin/clean.c:155 builtin/clean.c:176
+#, c-format
+msgid "Would remove %s\n"
+msgstr "Würde entfernen %s\n"
+
+#: builtin/clean.c:159 builtin/clean.c:179
+#, c-format
+msgid "Removing %s\n"
+msgstr "Entferne %s\n"
+
+#: builtin/clean.c:162 builtin/clean.c:182
+#, c-format
+msgid "failed to remove %s"
+msgstr "Fehler beim Entfernen von %s"
+
+#: builtin/clean.c:166
+#, c-format
+msgid "Would not remove %s\n"
+msgstr "Würde nicht entfernen %s\n"
+
+#: builtin/clean.c:168
+#, c-format
+msgid "Not removing %s\n"
+msgstr "Entferne nicht %s\n"
+
+#: builtin/clone.c:243
+#, c-format
+msgid "reference repository '%s' is not a local directory."
+msgstr "Referenziertes Projektarchiv '%s' ist kein lokales Verzeichnis."
+
+#: builtin/clone.c:302
+#, c-format
+msgid "failed to open '%s'"
+msgstr "Fehler beim Öffnen von '%s'"
+
+#: builtin/clone.c:306
+#, c-format
+msgid "failed to create directory '%s'"
+msgstr "Fehler beim Erstellen von Verzeichnis '%s'"
+
+#: builtin/clone.c:308 builtin/diff.c:75
+#, c-format
+msgid "failed to stat '%s'"
+msgstr "'%s' konnte nicht gelesen werden"
+
+#: builtin/clone.c:310
+#, c-format
+msgid "%s exists and is not a directory"
+msgstr "%s existiert und ist kein Verzeichnis"
+
+#: builtin/clone.c:324
+#, c-format
+msgid "failed to stat %s\n"
+msgstr "%s konnte nicht gelesen werden\n"
+
+#: builtin/clone.c:341
+#, c-format
+msgid "failed to unlink '%s'"
+msgstr "Verknüpfung von '%s' konnte nicht aufgehoben werden."
+
+#: builtin/clone.c:346
+#, c-format
+msgid "failed to create link '%s'"
+msgstr "Verknüpfung '%s' konnte nicht erstellt werden."
+
+#: builtin/clone.c:350
+#, c-format
+msgid "failed to copy file to '%s'"
+msgstr "Datei konnte nicht nach '%s' kopiert werden."
+
+#: builtin/clone.c:373
+#, c-format
+msgid "done.\n"
+msgstr "Fertig.\n"
+
+#: builtin/clone.c:440
+#, c-format
+msgid "Could not find remote branch %s to clone."
+msgstr "Entfernter Zweig %s konnte nicht zum Klonen gefunden werden."
+
+#: builtin/clone.c:549
+msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n"
+msgstr ""
+"Entfernte Zweigspitze (HEAD) bezieht sich auf eine nicht existierende "
+"Referenz und kann nicht ausgecheckt werden.\n"
+
+#: builtin/clone.c:639
+msgid "Too many arguments."
+msgstr "Zu viele Argumente."
+
+#: builtin/clone.c:643
+msgid "You must specify a repository to clone."
+msgstr "Du musst ein Projektarchiv zum Klonen spezifizieren."
+
+#: builtin/clone.c:654
+#, c-format
+msgid "--bare and --origin %s options are incompatible."
+msgstr "--bare und --origin %s Optionen sind inkompatibel."
+
+#: builtin/clone.c:668
+#, c-format
+msgid "repository '%s' does not exist"
+msgstr "Projektarchiv '%s' existiert nicht."
+
+#: builtin/clone.c:673
+msgid "--depth is ignored in local clones; use file:// instead."
+msgstr "--depth wird in lokalen Klonen ignoriert; benutze stattdessen file://."
+
+#: builtin/clone.c:683
+#, c-format
+msgid "destination path '%s' already exists and is not an empty directory."
+msgstr "Zielpfad '%s' existiert bereits und ist kein leeres Verzeichnis."
+
+#: builtin/clone.c:693
+#, c-format
+msgid "working tree '%s' already exists."
+msgstr "Arbeitsbaum '%s' existiert bereits."
+
+#: builtin/clone.c:706 builtin/clone.c:720
+#, c-format
+msgid "could not create leading directories of '%s'"
+msgstr "Konnte führende Verzeichnisse von '%s' nicht erstellen."
+
+#: builtin/clone.c:709
+#, c-format
+msgid "could not create work tree dir '%s'."
+msgstr "Konnte Arbeitsverzeichnis '%s' nicht erstellen."
+
+#: builtin/clone.c:728
+#, c-format
+msgid "Cloning into bare repository '%s'...\n"
+msgstr "Klone in leeres Projektarchiv '%s'...\n"
+
+#: builtin/clone.c:730
+#, c-format
+msgid "Cloning into '%s'...\n"
+msgstr "Klone nach '%s'...\n"
+
+#: builtin/clone.c:786
+#, c-format
+msgid "Don't know how to clone %s"
+msgstr "Weiß nicht wie %s zu klonen ist."
+
+#: builtin/clone.c:835
+#, c-format
+msgid "Remote branch %s not found in upstream %s"
+msgstr "entfernter Zweig %s nicht im anderen Projektarchiv gefunden %s"
+
+#: builtin/clone.c:842
+msgid "You appear to have cloned an empty repository."
+msgstr "Du scheinst ein leeres Projektarchiv geklont zu haben."
+
+#: builtin/commit.c:42
+msgid ""
+"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"
+"After doing this, you may fix the identity used for this commit with:\n"
+"\n"
+" git commit --amend --reset-author\n"
+msgstr ""
+"Dein Name und E-Mail Adresse wurden automatisch auf Basis\n"
+"deines Benutzer- und Rechnernamens konfiguriert. Bitte prüfe, dass diese\n"
+"zutreffend sind. Du kannst diese Meldung unterdrücken, indem du diese\n"
+"explizit setzt:\n"
+"\n"
+" git config --global user.name \"Dein Name\"\n"
+" git config --global user.email deine@emailadresse.de\n"
+"\n"
+"Nachdem du das getan hast, kannst du deine Identität für diese Version "
+"ändern mit:\n"
+"\n"
+" git commit --amend --reset-author\n"
+
+#: builtin/commit.c:54
+msgid ""
+"You asked to amend the most recent commit, but doing so would make\n"
+"it empty. You can repeat your command with --allow-empty, or you can\n"
+"remove the commit entirely with \"git reset HEAD^\".\n"
+msgstr ""
+"Du fragtest die jüngste Version nachzubessern, aber das würde diese leer\n"
+"machen. Du kannst Dein Kommando mit --allow-empty wiederholen, oder die\n"
+"Version mit \"git reset HEAD^\" vollständig entfernen.\n"
+
+#: builtin/commit.c:59
+msgid ""
+"The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
+"If you wish to commit it anyway, use:\n"
+"\n"
+" git commit --allow-empty\n"
+"\n"
+"Otherwise, please use 'git reset'\n"
+msgstr ""
+"Der letzte \"cherry-pick\" ist jetzt leer, möglicherweise durch eine "
+"Konfliktauflösung.\n"
+"Wenn du dies trotzdem eintragen willst, benutze:\n"
+"\n"
+" git commit --allow-empty\n"
+"\n"
+"Andernfalls benutze bitte 'git reset'\n"
+
+#: builtin/commit.c:205 builtin/reset.c:33
+msgid "merge"
+msgstr "zusammenführen"
+
+#: builtin/commit.c:208
+msgid "cherry-pick"
+msgstr "cherry-pick"
+
+#: builtin/commit.c:325
+msgid "failed to unpack HEAD tree object"
+msgstr "Fehler beim Entpacken des Baum-Objektes der Zweigspitze (HEAD)."
+
+#: builtin/commit.c:367
+msgid "unable to create temporary index"
+msgstr "Konnte temporäre Bereitstellung nicht erstellen."
+
+#: builtin/commit.c:373
+msgid "interactive add failed"
+msgstr "interaktives Hinzufügen fehlgeschlagen"
+
+#: builtin/commit.c:406 builtin/commit.c:427 builtin/commit.c:473
+msgid "unable to write new_index file"
+msgstr "Konnte new_index Datei nicht schreiben"
+
+#: builtin/commit.c:457
+#, c-format
+msgid "cannot do a partial commit during a %s."
+msgstr "Kann keine partielle Eintragung während eines %s durchführen."
+
+#: builtin/commit.c:466
+msgid "cannot read the index"
+msgstr "Kann Bereitstellung nicht lesen"
+
+#: builtin/commit.c:486
+msgid "unable to write temporary index file"
+msgstr "Konnte temporäre Bereitstellungsdatei nicht schreiben."
+
+#: builtin/commit.c:561 builtin/commit.c:567
+#, c-format
+msgid "invalid commit: %s"
+msgstr "Ungültige Version: %s"
+
+#: builtin/commit.c:590
+msgid "malformed --author parameter"
+msgstr "Fehlerhafter --author Parameter"
+
+#: builtin/commit.c:651
+#, c-format
+msgid "Malformed ident string: '%s'"
+msgstr "Fehlerhafte Identifikations-String: '%s'"
+
+#: builtin/commit.c:689 builtin/commit.c:722 builtin/commit.c:1033
+#, c-format
+msgid "could not lookup commit %s"
+msgstr "Konnte Version %s nicht nachschlagen"
+
+#: builtin/commit.c:701 builtin/shortlog.c:296
+#, c-format
+msgid "(reading log message from standard input)\n"
+msgstr "(lese Log-Nachricht von Standard-Eingabe)\n"
+
+#: builtin/commit.c:703
+msgid "could not read log from standard input"
+msgstr "Konnte Log nicht von Standard-Eingabe lesen."
+
+#: builtin/commit.c:707
+#, c-format
+msgid "could not read log file '%s'"
+msgstr "Konnte Log-Datei '%s' nicht lesen"
+
+#: builtin/commit.c:713
+msgid "commit has empty message"
+msgstr "Version hat eine leere Beschreibung"
+
+#: builtin/commit.c:729
+msgid "could not read MERGE_MSG"
+msgstr "Konnte MERGE_MSG nicht lesen"
+
+#: builtin/commit.c:733
+msgid "could not read SQUASH_MSG"
+msgstr "Konnte SQUASH_MSG nicht lesen"
+
+#: builtin/commit.c:737
+#, c-format
+msgid "could not read '%s'"
+msgstr "Konnte '%s' nicht lesen"
+
+#: builtin/commit.c:765
+#, c-format
+msgid "could not open '%s'"
+msgstr "Konnte '%s' nicht öffnen"
+
+#: builtin/commit.c:789
+msgid "could not write commit template"
+msgstr "Konnte Versionsvorlage nicht schreiben"
+
+#: builtin/commit.c:799
+#, c-format
+msgid ""
+"\n"
+"It looks like you may be committing a %s.\n"
+"If this is not correct, please remove the file\n"
+"\t%s\n"
+"and try again.\n"
+msgstr ""
+"\n"
+"Es sieht so aus, als trägst du ein '%s' ein.\n"
+"Falls das nicht korrekt ist, entferne bitte die Datei\n"
+"\t%s\n"
+"und versuche es erneut.\n"
+
+#: builtin/commit.c:812
+msgid "Please enter the commit message for your changes."
+msgstr "Bitte gebe die Versionsbeschreibung für deine Änderungen ein."
+
+#: builtin/commit.c:815
+msgid ""
+" Lines starting\n"
+"with '#' will be ignored, and an empty message aborts the commit.\n"
+msgstr ""
+" Zeilen beginnend\n"
+"mit '#' werden ignoriert, und eine leere Versionsbeschreibung bricht die "
+"Eintragung ab.\n"
+
+#: builtin/commit.c:820
+msgid ""
+" Lines starting\n"
+"with '#' will be kept; you may remove them yourself if you want to.\n"
+"An empty message aborts the commit.\n"
+msgstr ""
+" Zeilen beginnend\n"
+"mit '#' werden beibehalten; wenn du möchtest, kannst du diese entfernen.\n"
+"Eine leere Versionsbeschreibung bricht die Eintragung ab.\n"
+
+#: builtin/commit.c:832
+#, c-format
+msgid "%sAuthor: %s"
+msgstr "%sAutor: %s"
+
+#: builtin/commit.c:839
+#, c-format
+msgid "%sCommitter: %s"
+msgstr "%sEintragender: %s"
+
+#: builtin/commit.c:859
+msgid "Cannot read index"
+msgstr "Kann Bereitstellung nicht lesen"
+
+#: builtin/commit.c:896
+msgid "Error building trees"
+msgstr "Fehler beim Erzeugen der Bäume"
+
+#: builtin/commit.c:911 builtin/tag.c:357
+#, c-format
+msgid "Please supply the message using either -m or -F option.\n"
+msgstr "Bitte liefere die Beschreibung entweder mit der Option -m oder -F.\n"
+
+#: builtin/commit.c:1008
+#, c-format
+msgid "No existing author found with '%s'"
+msgstr "Kein existierender Autor mit '%s' gefunden."
+
+#: builtin/commit.c:1023 builtin/commit.c:1217
+#, c-format
+msgid "Invalid untracked files mode '%s'"
+msgstr "Ungültiger Modus '%s' für unverfolgte Dateien"
+
+#: builtin/commit.c:1063
+msgid "Using both --reset-author and --author does not make sense"
+msgstr "Verwendung von --reset-author und --author macht keinen Sinn."
+
+#: builtin/commit.c:1074
+msgid "You have nothing to amend."
+msgstr "Du hast nichts zum nachbessern."
+
+#: builtin/commit.c:1076
+#, c-format
+msgid "You are in the middle of a %s -- cannot amend."
+msgstr "Du bist in der Mitte eines %s -- kann nicht nachbessern."
+
+#: builtin/commit.c:1078
+msgid "Options --squash and --fixup cannot be used together"
+msgstr ""
+"Die Optionen --squash und --fixup können nicht gemeinsam benutzt werden."
+
+#: builtin/commit.c:1088
+msgid "Only one of -c/-C/-F/--fixup can be used."
+msgstr "Nur eines von -c/-C/-F/--fixup kann benutzt werden."
+
+#: builtin/commit.c:1090
+msgid "Option -m cannot be combined with -c/-C/-F/--fixup."
+msgstr "Option -m kann nicht mit -c/-C/-F/--fixup kombiniert werden"
+
+#: builtin/commit.c:1098
+msgid "--reset-author can be used only with -C, -c or --amend."
+msgstr "--reset--author kann nur mit -C, -c oder --amend benutzt werden"
+
+#: builtin/commit.c:1115
+msgid "Only one of --include/--only/--all/--interactive/--patch can be used."
+msgstr ""
+"Nur eines von --include/--only/--all/--interactive/--patch kann benutzt "
+"werden."
+
+#: builtin/commit.c:1117
+msgid "No paths with --include/--only does not make sense."
+msgstr "--include/--only machen ohne Pfade keinen Sinn."
+
+#: builtin/commit.c:1119
+msgid "Clever... amending the last one with dirty index."
+msgstr ""
+"Klug... nachbessern der letzten Version mit einem unsauberen Bereitstellung."
+
+#: builtin/commit.c:1121
+msgid "Explicit paths specified without -i nor -o; assuming --only paths..."
+msgstr ""
+"Explizite Pfade ohne -i oder -o spezifiziert; unter der Annahme von --only "
+"Pfaden..."
+
+#: builtin/commit.c:1131 builtin/tag.c:556
+#, c-format
+msgid "Invalid cleanup mode %s"
+msgstr "Ungültiger \"cleanup\" Modus %s"
+
+#: builtin/commit.c:1136
+msgid "Paths with -a does not make sense."
+msgstr "Pfade mit -a machen keinen Sinn."
+
+#: builtin/commit.c:1315
+msgid "couldn't look up newly created commit"
+msgstr "Konnte neu erstellte Version nicht nachschlagen."
+
+#: builtin/commit.c:1317
+msgid "could not parse newly created commit"
+msgstr "Konnte neulich erstellte Version nicht analysieren."
+
+#: builtin/commit.c:1358
+msgid "detached HEAD"
+msgstr "losgelöste Zweigspitze (HEAD)"
+
+#: builtin/commit.c:1360
+msgid " (root-commit)"
+msgstr " (Basis-Version)"
+
+#: builtin/commit.c:1450
+msgid "could not parse HEAD commit"
+msgstr "Konnte Version der Zweigspitze (HEAD) nicht analysieren."
+
+#: builtin/commit.c:1487 builtin/merge.c:509
+#, c-format
+msgid "could not open '%s' for reading"
+msgstr "Konnte '%s' nicht zum Lesen öffnen."
+
+#: builtin/commit.c:1494
+#, c-format
+msgid "Corrupt MERGE_HEAD file (%s)"
+msgstr "Beschädigte MERGE_HEAD-Datei (%s)"
+
+#: builtin/commit.c:1501
+msgid "could not read MERGE_MODE"
+msgstr "Konnte MERGE_MODE nicht lesen"
+
+#: builtin/commit.c:1520
+#, c-format
+msgid "could not read commit message: %s"
+msgstr "Konnte Versionsbeschreibung nicht lesen: %s"
+
+#: builtin/commit.c:1534
+#, c-format
+msgid "Aborting commit; you did not edit the message.\n"
+msgstr "Eintragung abgebrochen; du hast die Beschreibung nicht editiert.\n"
+
+#: builtin/commit.c:1539
+#, c-format
+msgid "Aborting commit due to empty commit message.\n"
+msgstr "Eintragung aufgrund leerer Versionsbeschreibung abgebrochen.\n"
+
+#: builtin/commit.c:1554 builtin/merge.c:936 builtin/merge.c:961
+msgid "failed to write commit object"
+msgstr "Fehler beim Schreiben des Versionsobjektes."
+
+#: builtin/commit.c:1575
+msgid "cannot lock HEAD ref"
+msgstr "Kann Referenz der Zweigspitze (HEAD) nicht sperren."
+
+#: builtin/commit.c:1579
+msgid "cannot update HEAD ref"
+msgstr "Kann Referenz der Zweigspitze (HEAD) nicht aktualisieren."
+
+#: builtin/commit.c:1590
+msgid ""
+"Repository has been updated, but unable to write\n"
+"new_index file. Check that disk is not full or quota is\n"
+"not exceeded, and then \"git reset HEAD\" to recover."
+msgstr ""
+"Das Projektarchiv wurde aktualisiert, aber die \"new_index\"-Datei\n"
+"konnte nicht geschrieben werden. Prüfe, dass dein Speicher nicht\n"
+"voll und Dein Kontingent nicht aufgebraucht ist und führe\n"
+"anschließend \"git reset HEAD\" zu Wiederherstellung aus."
+
+#: builtin/describe.c:234
+#, c-format
+msgid "annotated tag %s not available"
+msgstr "annotierte Markierung %s ist nicht verfügbar"
+
+#: builtin/describe.c:238
+#, c-format
+msgid "annotated tag %s has no embedded name"
+msgstr "annotierte Markierung %s hat keinen eingebetteten Namen"
+
+#: builtin/describe.c:240
+#, c-format
+msgid "tag '%s' is really '%s' here"
+msgstr "Markierung '%s' ist wirklich '%s' hier"
+
+#: builtin/describe.c:267
+#, c-format
+msgid "Not a valid object name %s"
+msgstr "kein gültiger Objekt-Name %s"
+
+#: builtin/describe.c:270
+#, c-format
+msgid "%s is not a valid '%s' object"
+msgstr "%s ist kein gültiges '%s' Objekt"
+
+#: builtin/describe.c:287
+#, c-format
+msgid "no tag exactly matches '%s'"
+msgstr "kein Markierung entspricht exakt '%s'"
+
+#: builtin/describe.c:289
+#, c-format
+msgid "searching to describe %s\n"
+msgstr "suche um zu beschreiben %s\n"
+
+#: builtin/describe.c:329
+#, c-format
+msgid "finished search at %s\n"
+msgstr "beendete Suche bei %s\n"
+
+#: builtin/describe.c:353
+#, c-format
+msgid ""
+"No annotated tags can describe '%s'.\n"
+"However, there were unannotated tags: try --tags."
+msgstr ""
+"Keine annotierten Markierungen können '%s' beschreiben.\n"
+"Jedoch gab es nicht annotierte Markierungen: versuche --tags."
+
+#: builtin/describe.c:357
+#, c-format
+msgid ""
+"No tags can describe '%s'.\n"
+"Try --always, or create some tags."
+msgstr ""
+"Keine Markierungen können '%s' beschreiben.\n"
+"Versuche --always oder erstelle einige Markierungen."
+
+#: builtin/describe.c:378
+#, c-format
+msgid "traversed %lu commits\n"
+msgstr "verarbeitete %lu Versionen\n"
+
+#: builtin/describe.c:381
+#, c-format
+msgid ""
+"more than %i tags found; listed %i most recent\n"
+"gave up search at %s\n"
+msgstr ""
+"mehr als %i Markierungen gefunden; Führe die %i jüngsten auf\n"
+"Suche bei %s aufgegeben\n"
+
+#: builtin/describe.c:436
+msgid "--long is incompatible with --abbrev=0"
+msgstr "--long ist inkompatibel mit --abbrev=0"
+
+#: builtin/describe.c:462
+msgid "No names found, cannot describe anything."
+msgstr "Keine Namen gefunden, kann nichts beschreiben."
+
+#: builtin/describe.c:482
+msgid "--dirty is incompatible with committishes"
+msgstr "--dirty ist inkompatibel mit \"committish\"-Werten"
+
+#: builtin/diff.c:77
+#, c-format
+msgid "'%s': not a regular file or symlink"
+msgstr "'%s': keine reguläre Datei oder symbolischer Link"
+
+#: builtin/diff.c:220
+#, c-format
+msgid "invalid option: %s"
+msgstr "Ungültige Option: %s"
+
+#: builtin/diff.c:297
+msgid "Not a git repository"
+msgstr "Kein Git-Projektarchiv"
+
+#: builtin/diff.c:347
+#, c-format
+msgid "invalid object '%s' given."
+msgstr "Ungültiges Objekt '%s' gegeben."
+
+#: builtin/diff.c:352
+#, c-format
+msgid "more than %d trees given: '%s'"
+msgstr "Mehr als %d Bäume gegeben: '%s'"
+
+#: builtin/diff.c:362
+#, c-format
+msgid "more than two blobs given: '%s'"
+msgstr "Mehr als zwei Blobs gegeben: '%s'"
+
+#: builtin/diff.c:370
+#, c-format
+msgid "unhandled object '%s' given."
+msgstr "unbehandeltes Objekt '%s' gegeben"
+
+#: builtin/fetch.c:200
+msgid "Couldn't find remote ref HEAD"
+msgstr "Konnte entfernte Referenz der Zweigspitze (HEAD) nicht finden."
+
+#: builtin/fetch.c:253
+#, c-format
+msgid "object %s not found"
+msgstr "Objekt %s nicht gefunden"
+
+#: builtin/fetch.c:259
+msgid "[up to date]"
+msgstr "[aktuell]"
+
+#: builtin/fetch.c:273
+#, c-format
+msgid "! %-*s %-*s -> %s (can't fetch in current branch)"
+msgstr "! %-*s %-*s -> %s (kann nicht im aktuellen Zweig anfordern)"
+
+#: builtin/fetch.c:274 builtin/fetch.c:360
+msgid "[rejected]"
+msgstr "[zurückgewiesen]"
+
+#: builtin/fetch.c:285
+msgid "[tag update]"
+msgstr "[Markierungsaktualisierung]"
+
+#: builtin/fetch.c:287 builtin/fetch.c:322 builtin/fetch.c:340
+msgid " (unable to update local ref)"
+msgstr " (kann lokale Referenz nicht aktualisieren)"
+
+#: builtin/fetch.c:305
+msgid "[new tag]"
+msgstr "[neue Markierung]"
+
+#: builtin/fetch.c:308
+msgid "[new branch]"
+msgstr "[neuer Zweig]"
+
+#: builtin/fetch.c:311
+msgid "[new ref]"
+msgstr "[neue Referenz]"
+
+#: builtin/fetch.c:356
+msgid "unable to update local ref"
+msgstr "kann lokale Referenz nicht aktualisieren"
+
+#: builtin/fetch.c:356
+msgid "forced update"
+msgstr "Aktualisierung erzwungen"
+
+#: builtin/fetch.c:362
+msgid "(non-fast-forward)"
+msgstr "(kein Vorspulen)"
+
+#: builtin/fetch.c:393 builtin/fetch.c:685
+#, c-format
+msgid "cannot open %s: %s\n"
+msgstr "kann %s nicht öffnen: %s\n"
+
+#: builtin/fetch.c:402
+#, c-format
+msgid "%s did not send all necessary objects\n"
+msgstr "%s hat nicht alle erforderlichen Objekte gesendet\n"
+
+#: builtin/fetch.c:488
+#, c-format
+msgid "From %.*s\n"
+msgstr "Von %.*s\n"
+
+#: builtin/fetch.c:499
+#, c-format
+msgid ""
+"some local refs could not be updated; try running\n"
+" 'git remote prune %s' to remove any old, conflicting branches"
+msgstr ""
+"Einige lokale Referenzen konnten nicht aktualisiert werden; versuche\n"
+"'git remote prune %s' um jeden älteren, widersprüchlichen Zweig zu entfernen."
+
+#: builtin/fetch.c:549
+#, c-format
+msgid " (%s will become dangling)\n"
+msgstr " (%s wird unreferenziert werden)\n"
+
+#: builtin/fetch.c:550
+#, c-format
+msgid " (%s has become dangling)\n"
+msgstr " (%s wurde unreferenziert)\n"
+
+#: builtin/fetch.c:557
+msgid "[deleted]"
+msgstr "[gelöscht]"
+
+#: builtin/fetch.c:558
+msgid "(none)"
+msgstr "(keine)"
+
+#: builtin/fetch.c:675
+#, c-format
+msgid "Refusing to fetch into current branch %s of non-bare repository"
+msgstr ""
+"Ablehnung des Anforderns in aktuellen Zweig %s von einem nicht-leeren "
+"Projektarchiv"
+
+#: builtin/fetch.c:709
+#, c-format
+msgid "Don't know how to fetch from %s"
+msgstr "Weiß nicht wie von %s angefordert wird."
+
+#: builtin/fetch.c:786
+#, c-format
+msgid "Option \"%s\" value \"%s\" is not valid for %s"
+msgstr "Option \"%s\" Wert \"%s\" ist nicht gültig für %s"
+
+#: builtin/fetch.c:789
+#, c-format
+msgid "Option \"%s\" is ignored for %s\n"
+msgstr "Option \"%s\" wird ignoriert für %s\n"
+
+#: builtin/fetch.c:888
+#, c-format
+msgid "Fetching %s\n"
+msgstr "Hole %s ab\n"
+
+#: builtin/fetch.c:890
+#, c-format
+msgid "Could not fetch %s"
+msgstr "Konnte %s nicht anfordern"
+
+#: builtin/fetch.c:907
+msgid ""
+"No remote repository specified. Please, specify either a URL or a\n"
+"remote name from which new revisions should be fetched."
+msgstr ""
+"Kein entferntes Projektarchiv spezifiziert. Bitte spezifiziere entweder\n"
+"eine URL oder einen Entfernungsname, von welchem neue Revisionen angefordert "
+"werden sollen."
+
+#: builtin/fetch.c:927
+msgid "You need to specify a tag name."
+msgstr "Du musst den Namen der Markierung spezifizieren."
+
+#: builtin/fetch.c:979
+msgid "fetch --all does not take a repository argument"
+msgstr "fetch -all nimmt kein Projektarchiv als Argument"
+
+#: builtin/fetch.c:981
+msgid "fetch --all does not make sense with refspecs"
+msgstr "fetch --all macht keinen Sinn mit Referenzspezifikationen"
+
+#: builtin/fetch.c:992
+#, c-format
+msgid "No such remote or remote group: %s"
+msgstr "Keine solche Entfernung oder Entfernungsgruppe: %s"
+
+#: builtin/fetch.c:1000
+msgid "Fetching a group and specifying refspecs does not make sense"
+msgstr ""
+"Abholen einer Gruppe und Spezifizieren von Referenzspezifikationen macht "
+"keinen Sinn."
+
+#: builtin/gc.c:63
+#, c-format
+msgid "Invalid %s: '%s'"
+msgstr "Ungültiger %s: '%s'"
+
+#: builtin/gc.c:78
+msgid "Too many options specified"
+msgstr "Zu viele Optionen spezifiziert"
+
+#: builtin/gc.c:103
+#, c-format
+msgid "insanely long object directory %.*s"
+msgstr "wahnsinnig langes Objekt-Verzeichnis %.*s"
+
+#: builtin/gc.c:223
+#, c-format
+msgid "Auto packing the repository for optimum performance.\n"
+msgstr "Automatische Paketierung des Repositories für optimale Leitung.\n"
+
+#: builtin/gc.c:226
+#, c-format
+msgid ""
+"Auto packing the repository for optimum performance. You may also\n"
+"run \"git gc\" manually. See \"git help gc\" for more information.\n"
+msgstr ""
+"Automatische Paketierung des Repositories für optimale Leitung. Du darfst "
+"auch\n"
+"\"git gc\" manuell ausführen. Siehe \"git help gc\" für weitere "
+"Informationen.\n"
+
+#: builtin/gc.c:256
+msgid ""
+"There are too many unreachable loose objects; run 'git prune' to remove them."
+msgstr ""
+"Es gibt zu viele unerreichbare, verlorene Objekte; führe 'git prune' aus um "
+"diese zu entfernen."
+
+#: builtin/grep.c:216
+#, c-format
+msgid "grep: failed to create thread: %s"
+msgstr "grep: Fehler beim Erzeugen eines Thread: %s"
+
+#: builtin/grep.c:402
+#, c-format
+msgid "Failed to chdir: %s"
+msgstr "Fehler beim Verzeichniswechsel: %s"
+
+#: builtin/grep.c:478 builtin/grep.c:512
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr "konnte Baum (%s) nicht lesen"
+
+#: builtin/grep.c:526
+#, c-format
+msgid "unable to grep from object of type %s"
+msgstr "kann \"grep\" nicht mit Objekt des Typs \"%s\" durchführen"
+
+#: builtin/grep.c:584
+#, c-format
+msgid "switch `%c' expects a numerical value"
+msgstr "Schalter '%c' erwartet einen numerischen Wert"
+
+#: builtin/grep.c:601
+#, c-format
+msgid "cannot open '%s'"
+msgstr "kann '%s' nicht öffnen"
+
+#: builtin/grep.c:888
+msgid "no pattern given."
+msgstr "keine Muster gegeben"
+
+#: builtin/grep.c:902
+#, c-format
+msgid "bad object %s"
+msgstr "schlechtes Objekt %s"
+
+#: builtin/grep.c:943
+msgid "--open-files-in-pager only works on the worktree"
+msgstr "--open-files-in-pager arbeitet nur auf dem Arbeitsbaum"
+
+#: builtin/grep.c:966
+msgid "--cached or --untracked cannot be used with --no-index."
+msgstr "--cached oder --untracked kann nicht mit --no-index benutzt werden"
+
+#: builtin/grep.c:971
+msgid "--no-index or --untracked cannot be used with revs."
+msgstr "--no-index oder --untracked kann nicht mit Revisionen benutzt werden"
+
+#: builtin/grep.c:974
+msgid "--[no-]exclude-standard cannot be used for tracked contents."
+msgstr ""
+"--[no-]exlude-standard kann nicht mit verfolgten Inhalten benutzt werden"
+
+#: builtin/grep.c:982
+msgid "both --cached and trees are given."
+msgstr "sowohl --cached als auch Bäume gegeben"
+
+#: builtin/init-db.c:35
+#, c-format
+msgid "Could not make %s writable by group"
+msgstr "Konnte %s nicht schreibbar für Gruppen machen"
+
+#: builtin/init-db.c:62
+#, c-format
+msgid "insanely long template name %s"
+msgstr "verrückt langer Vorlagen-Name %s"
+
+#: builtin/init-db.c:67
+#, c-format
+msgid "cannot stat '%s'"
+msgstr "'%s' kann nicht gelesen werden"
+
+#: builtin/init-db.c:73
+#, c-format
+msgid "cannot stat template '%s'"
+msgstr "kann Vorlage '%s' nicht lesen"
+
+#: builtin/init-db.c:80
+#, c-format
+msgid "cannot opendir '%s'"
+msgstr "kann Verzeichnis '%s' nicht öffnen"
+
+#: builtin/init-db.c:97
+#, c-format
+msgid "cannot readlink '%s'"
+msgstr "kann Verknüfpung '%s' nicht lesen"
+
+#: builtin/init-db.c:99
+#, c-format
+msgid "insanely long symlink %s"
+msgstr "verrückt lange symbolische Verknüpfung %s"
+
+#: builtin/init-db.c:102
+#, c-format
+msgid "cannot symlink '%s' '%s'"
+msgstr "kann '%s' '%s' nicht symbolisch verknüpfen"
+
+#: builtin/init-db.c:106
+#, c-format
+msgid "cannot copy '%s' to '%s'"
+msgstr "kann '%s' nicht nach '%s' kopieren"
+
+#: builtin/init-db.c:110
+#, c-format
+msgid "ignoring template %s"
+msgstr "ignoriere Vorlage %s"
+
+#: builtin/init-db.c:133
+#, c-format
+msgid "insanely long template path %s"
+msgstr "verrückt langer Vorlagen-Pfad %s"
+
+#: builtin/init-db.c:141
+#, c-format
+msgid "templates not found %s"
+msgstr "Vorlagen nicht gefunden %s"
+
+#: builtin/init-db.c:154
+#, c-format
+msgid "not copying templates of a wrong format version %d from '%s'"
+msgstr "kopiere keine Vorlagen mit einer falschen Formatversion %d von '%s'"
+
+#: builtin/init-db.c:192
+#, c-format
+msgid "insane git directory %s"
+msgstr "verrücktes git Verzeichnis %s"
+
+#: builtin/init-db.c:322 builtin/init-db.c:325
+#, c-format
+msgid "%s already exists"
+msgstr "%s existiert bereits"
+
+#: builtin/init-db.c:354
+#, c-format
+msgid "unable to handle file type %d"
+msgstr "kann Dateityp %d nicht behandeln"
+
+#: builtin/init-db.c:357
+#, c-format
+msgid "unable to move %s to %s"
+msgstr "konnte %s nicht nach %s verschieben"
+
+#: builtin/init-db.c:362
+#, c-format
+msgid "Could not create git link %s"
+msgstr "Konnte git-Verknüfung %s nicht erstellen"
+
+#.
+#. * TRANSLATORS: The first '%s' is either "Reinitialized
+#. * existing" or "Initialized empty", the second " shared" or
+#. * "", and the last '%s%s' is the verbatim directory name.
+#.
+#: builtin/init-db.c:419
+#, c-format
+msgid "%s%s Git repository in %s%s\n"
+msgstr "%s%s Git-Projektarchiv in %s%s\n"
+
+#: builtin/init-db.c:420
+msgid "Reinitialized existing"
+msgstr "Reinitialisierte existierendes"
+
+#: builtin/init-db.c:420
+msgid "Initialized empty"
+msgstr "Initialisierte leeres"
+
+#: builtin/init-db.c:421
+msgid " shared"
+msgstr " geteilt"
+
+#: builtin/init-db.c:440
+msgid "cannot tell cwd"
+msgstr "kann nicht \"cwd\" sagen"
+
+#: builtin/init-db.c:521 builtin/init-db.c:528
+#, c-format
+msgid "cannot mkdir %s"
+msgstr "kann Verzeichnis %s nicht erstellen"
+
+#: builtin/init-db.c:532
+#, c-format
+msgid "cannot chdir to %s"
+msgstr "kann nicht zu Verzeichnis %s wechseln"
+
+#: builtin/init-db.c:554
+#, c-format
+msgid ""
+"%s (or --work-tree=<directory>) not allowed without specifying %s (or --git-"
+"dir=<directory>)"
+msgstr ""
+"%s (oder --work-tree=<Verzeichnis>) nicht erlaubt ohne Spezifizierung von %s "
+"(oder --git-dir=<Verzeichnis>)"
+
+#: builtin/init-db.c:578
+msgid "Cannot access current working directory"
+msgstr "Kann nicht auf aktuelles Arbeitsverzeichnis zugreifen."
+
+#: builtin/init-db.c:585
+#, c-format
+msgid "Cannot access work tree '%s'"
+msgstr "Kann nicht auf Arbeitsbaum '%s' zugreifen."
+
+#: builtin/log.c:188
+#, c-format
+msgid "Final output: %d %s\n"
+msgstr "letzte Ausgabe: %d %s\n"
+
+#: builtin/log.c:401 builtin/log.c:489
+#, c-format
+msgid "Could not read object %s"
+msgstr "Kann Objekt %s nicht lesen."
+
+#: builtin/log.c:513
+#, c-format
+msgid "Unknown type: %d"
+msgstr "Unbekannter Typ: %d"
+
+#: builtin/log.c:602
+msgid "format.headers without value"
+msgstr "format.headers ohne Wert"
+
+#: builtin/log.c:675
+msgid "name of output directory is too long"
+msgstr "Name des Ausgabeverzeichnisses ist zu lang."
+
+#: builtin/log.c:686
+#, c-format
+msgid "Cannot open patch file %s"
+msgstr "Kann Patch-Datei %s nicht öffnen"
+
+#: builtin/log.c:700
+msgid "Need exactly one range."
+msgstr "Brauche genau einen Bereich."
+
+#: builtin/log.c:708
+msgid "Not a range."
+msgstr "Kein Bereich."
+
+#: builtin/log.c:745
+msgid "Could not extract email from committer identity."
+msgstr "Konnte E-Mail von der Intentität des Einreichers nicht extrahieren."
+
+#: builtin/log.c:791
+msgid "Cover letter needs email format"
+msgstr "Anschreiben benötigt E-Mail-Format"
+
+#: builtin/log.c:885
+#, c-format
+msgid "insane in-reply-to: %s"
+msgstr "verrücktes in-reply-to: %s"
+
+#: builtin/log.c:958
+msgid "Two output directories?"
+msgstr "Zwei Ausgabeverzeichnisse?"
+
+#: builtin/log.c:1179
+#, c-format
+msgid "bogus committer info %s"
+msgstr "unechte Einreicher-Informationen %s"
+
+#: builtin/log.c:1224
+msgid "-n and -k are mutually exclusive."
+msgstr "-n und -k sind zueinander exklusiv"
+
+#: builtin/log.c:1226
+msgid "--subject-prefix and -k are mutually exclusive."
+msgstr "--subject-prefix und -k sind zueinander exklusiv"
+
+#: builtin/log.c:1231 builtin/shortlog.c:284
+#, c-format
+msgid "unrecognized argument: %s"
+msgstr "nicht erkanntes Argument: %s"
+
+#: builtin/log.c:1234
+msgid "--name-only does not make sense"
+msgstr "--name-only macht keinen Sinn"
+
+#: builtin/log.c:1236
+msgid "--name-status does not make sense"
+msgstr "--name-status macht keinen Sinn"
+
+#: builtin/log.c:1238
+msgid "--check does not make sense"
+msgstr "--check macht keinen Sinn"
+
+#: builtin/log.c:1261
+msgid "standard output, or directory, which one?"
+msgstr "Standard-Ausgabe oder Verzeichnis, welches von beidem?"
+
+#: builtin/log.c:1263
+#, c-format
+msgid "Could not create directory '%s'"
+msgstr "Konnte Verzeichnis '%s' nicht erstellen."
+
+#: builtin/log.c:1416
+msgid "Failed to create output files"
+msgstr "Fehler beim Erstellen der Ausgabedateien."
+
+#: builtin/log.c:1520
+#, c-format
+msgid ""
+"Could not find a tracked remote branch, please specify <upstream> manually.\n"
+msgstr ""
+"Konnte gefolgten, entfernten Zweig nicht finden, bitte spezifiziere "
+"<upstream> manuell.\n"
+
+#: builtin/log.c:1536 builtin/log.c:1538 builtin/log.c:1550
+#, c-format
+msgid "Unknown commit %s"
+msgstr "Unbekannte Version %s"
+
+#: builtin/merge.c:90
+msgid "switch `m' requires a value"
+msgstr "Schalter 'm' erfordert einen Wert."
+
+#: builtin/merge.c:127
+#, c-format
+msgid "Could not find merge strategy '%s'.\n"
+msgstr "Konnte Zusammenführungsstrategie '%s' nicht finden.\n"
+
+#: builtin/merge.c:128
+#, c-format
+msgid "Available strategies are:"
+msgstr "Verfügbare Strategien sind:"
+
+#: builtin/merge.c:133
+#, c-format
+msgid "Available custom strategies are:"
+msgstr "Verfügbare benutzerdefinierte Strategien sind:"
+
+#: builtin/merge.c:240
+msgid "could not run stash."
+msgstr "Konnte \"stash\" nicht ausführen."
+
+#: builtin/merge.c:245
+msgid "stash failed"
+msgstr "\"stash\" fehlgeschlagen"
+
+#: builtin/merge.c:250
+#, c-format
+msgid "not a valid object: %s"
+msgstr "kein gültiges Objekt: %s"
+
+#: builtin/merge.c:269 builtin/merge.c:286
+msgid "read-tree failed"
+msgstr "read-tree fehlgeschlagen"
+
+#: builtin/merge.c:316
+msgid " (nothing to squash)"
+msgstr " (nichts zu quetschen)"
+
+#: builtin/merge.c:329
+#, c-format
+msgid "Squash commit -- not updating HEAD\n"
+msgstr "Quetsche Version -- aktualisiere Zweigspitze (HEAD) nicht\n"
+
+#: builtin/merge.c:361
+msgid "Writing SQUASH_MSG"
+msgstr "Schreibe SQUASH_MSG"
+
+#: builtin/merge.c:363
+msgid "Finishing SQUASH_MSG"
+msgstr "Schließe SQUASH_MSG ab"
+
+#: builtin/merge.c:386
+#, c-format
+msgid "No merge message -- not updating HEAD\n"
+msgstr ""
+"Keine Zusammenführungsbeschreibung -- aktualisiere Zweigspitze (HEAD) nicht\n"
+
+#: builtin/merge.c:437
+#, c-format
+msgid "'%s' does not point to a commit"
+msgstr "'%s' zeigt auf keine Version"
+
+#: builtin/merge.c:536
+#, c-format
+msgid "Bad branch.%s.mergeoptions string: %s"
+msgstr "Schlechter branch.%s.mergeoptions String: %s"
+
+#: builtin/merge.c:629
+msgid "git write-tree failed to write a tree"
+msgstr "\"git write-tree\" schlug beim Schreiben eines Baumes fehl"
+
+#: builtin/merge.c:679
+msgid "failed to read the cache"
+msgstr "Lesen des Zwischenspeichers fehlgeschlagen"
+
+#: builtin/merge.c:697
+msgid "Unable to write index."
+msgstr "Konnte Bereitstellung nicht schreiben."
+
+#: builtin/merge.c:710
+msgid "Not handling anything other than two heads merge."
+msgstr "Behandle nichts anderes als die Zusammenführung von zwei Köpfen."
+
+#: builtin/merge.c:724
+#, c-format
+msgid "Unknown option for merge-recursive: -X%s"
+msgstr "Unbekannte Option für merge-recursive: -X%s"
+
+#: builtin/merge.c:738
+#, c-format
+msgid "unable to write %s"
+msgstr "konnte %s nicht schreiben"
+
+#: builtin/merge.c:877
+#, c-format
+msgid "Could not read from '%s'"
+msgstr "konnte nicht von '%s' lesen"
+
+#: builtin/merge.c:886
+#, c-format
+msgid "Not committing merge; use 'git commit' to complete the merge.\n"
+msgstr ""
+"Zusammenführung nicht eingetragen; benutze 'git commit' um die "
+"Zusammenführung abzuschließen.\n"
+
+#: builtin/merge.c:892
+msgid ""
+"Please enter a commit message to explain why this merge is necessary,\n"
+"especially if it merges an updated upstream into a topic branch.\n"
+"\n"
+"Lines starting with '#' will be ignored, and an empty message aborts\n"
+"the commit.\n"
+msgstr ""
+"Bitte gebe eine Versionsbeschreibung ein um zu erklären, warum diese "
+"Zusammenführung erforderlich ist,\n"
+"insbesondere wenn es einen aktualisierten entfernten Zweig mit einem Thema-"
+"Zweig zusammenführt.\n"
+"\n"
+"Zeilen beginnend mit '#' werden ignoriert, und eine leere Beschreibung "
+"bricht die Eintragung ab.\n"
+
+#: builtin/merge.c:916
+msgid "Empty commit message."
+msgstr "Leere Versionsbeschreibung"
+
+#: builtin/merge.c:928
+#, c-format
+msgid "Wonderful.\n"
+msgstr "Wunderbar.\n"
+
+#: builtin/merge.c:993
+#, c-format
+msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
+msgstr ""
+"Automatische Zusammenführung fehlgeschlagen; behebe die Konflikte und trage "
+"dann das Ergebnis ein.\n"
+
+#: builtin/merge.c:1009
+#, c-format
+msgid "'%s' is not a commit"
+msgstr "'%s' ist keine Version"
+
+#: builtin/merge.c:1050
+msgid "No current branch."
+msgstr "Kein aktueller Zweig."
+
+#: builtin/merge.c:1052
+msgid "No remote for the current branch."
+msgstr "Kein anderes Archiv für den aktuellen Zweig."
+
+#: builtin/merge.c:1054
+msgid "No default upstream defined for the current branch."
+msgstr ""
+"Kein entferntes Standard-Projektarchiv für den aktuellen Zweig definiert."
+
+#: builtin/merge.c:1059
+#, c-format
+msgid "No remote tracking branch for %s from %s"
+msgstr "Kein entfernter Übernahmezweig für %s von %s"
+
+#: builtin/merge.c:1146 builtin/merge.c:1303
+#, c-format
+msgid "%s - not something we can merge"
+msgstr "%s - nichts was wir zusammenführen können"
+
+#: builtin/merge.c:1214
+msgid "There is no merge to abort (MERGE_HEAD missing)."
+msgstr "Es gibt keine Zusammenführung zum Abbrechen (vermisse MERGE_HEAD)"
+
+#: builtin/merge.c:1230 git-pull.sh:31
+msgid ""
+"You have not concluded your merge (MERGE_HEAD exists).\n"
+"Please, commit your changes before you can merge."
+msgstr ""
+"Du hast deine Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert).\n"
+"Bitte trage deine Änderungen ein, bevor du zusammenführen kannst."
+
+#: builtin/merge.c:1233 git-pull.sh:34
+msgid "You have not concluded your merge (MERGE_HEAD exists)."
+msgstr ""
+"Du hast deine Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert)."
+
+#: builtin/merge.c:1237
+msgid ""
+"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
+"Please, commit your changes before you can merge."
+msgstr ""
+"Du hast deinen \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD "
+"existiert).\n"
+"Bitte trage deine Änderungen ein, bevor du zusammenführen kannst."
+
+#: builtin/merge.c:1240
+msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
+msgstr ""
+"Du hast deinen \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD "
+"existiert)."
+
+#: builtin/merge.c:1249
+msgid "You cannot combine --squash with --no-ff."
+msgstr "Du kannst --squash nicht mit --no-ff kombinieren."
+
+#: builtin/merge.c:1254
+msgid "You cannot combine --no-ff with --ff-only."
+msgstr "Du kannst --no-ff nicht mit --ff--only kombinieren."
+
+#: builtin/merge.c:1261
+msgid "No commit specified and merge.defaultToUpstream not set."
+msgstr "Keine Version spezifiziert und merge.defaultToUpstream nicht gesetzt."
+
+#: builtin/merge.c:1293
+msgid "Can merge only exactly one commit into empty head"
+msgstr "Kann nur exakt eine Version in einem leeren Kopf zusammenführen."
+
+#: builtin/merge.c:1296
+msgid "Squash commit into empty head not supported yet"
+msgstr ""
+"Quetschen einer Version in einen leeren Kopf wird momentan nicht unterstützt."
+
+#: builtin/merge.c:1298
+msgid "Non-fast-forward commit does not make sense into an empty head"
+msgstr "nicht vorzuspulende Version macht in einem leeren Kopf keinen Sinn"
+
+#: builtin/merge.c:1413
+#, c-format
+msgid "Updating %s..%s\n"
+msgstr "Aktualisiere %s..%s\n"
+
+#: builtin/merge.c:1451
+#, c-format
+msgid "Trying really trivial in-index merge...\n"
+msgstr "Probiere wirklich triviale \"in-index\"-Zusammenführung...\n"
+
+#: builtin/merge.c:1458
+#, c-format
+msgid "Nope.\n"
+msgstr "Nein.\n"
+
+#: builtin/merge.c:1490
+msgid "Not possible to fast-forward, aborting."
+msgstr "Vorspulen nicht möglich, breche ab."
+
+#: builtin/merge.c:1513 builtin/merge.c:1592
+#, c-format
+msgid "Rewinding the tree to pristine...\n"
+msgstr "Rücklauf des Baumes bis zum Ursprung...\n"
+
+#: builtin/merge.c:1517
+#, c-format
+msgid "Trying merge strategy %s...\n"
+msgstr "Probiere Zusammenführungsstrategie %s...\n"
+
+#: builtin/merge.c:1583
+#, c-format
+msgid "No merge strategy handled the merge.\n"
+msgstr "Keine Zusammenführungsstrategie behandelt die Zusammenführung.\n"
+
+#: builtin/merge.c:1585
+#, c-format
+msgid "Merge with strategy %s failed.\n"
+msgstr "Zusammenführung mit Strategie %s fehlgeschlagen.\n"
+
+#: builtin/merge.c:1594
+#, c-format
+msgid "Using the %s to prepare resolving by hand.\n"
+msgstr "Benutze \"%s\" um die Auflösung per Hand vorzubereiten.\n"
+
+#: builtin/merge.c:1606
+#, c-format
+msgid "Automatic merge went well; stopped before committing as requested\n"
+msgstr ""
+"Automatische Zusammenführung gut gegangen; stoppe, wie angefragt, vor der "
+"Eintragung\n"
+
+#: builtin/mv.c:108
+#, c-format
+msgid "Checking rename of '%s' to '%s'\n"
+msgstr "Prüfe Umbenennen von '%s' nach '%s'\n"
+
+#: builtin/mv.c:112
+msgid "bad source"
+msgstr "schlechte Quelle"
+
+#: builtin/mv.c:115
+msgid "can not move directory into itself"
+msgstr "kann Verzeichnis nicht in sich selbst verschieben"
+
+#: builtin/mv.c:118
+msgid "cannot move directory over file"
+msgstr "kann Verzeichnis nicht über Datei verschieben"
+
+#: builtin/mv.c:128
+#, c-format
+msgid "Huh? %.*s is in index?"
+msgstr "Huh? %.*s ist in der Bereitstellung?"
+
+#: builtin/mv.c:140
+msgid "source directory is empty"
+msgstr "Quellverzeichnis ist leer"
+
+#: builtin/mv.c:171
+msgid "not under version control"
+msgstr "nicht unter Versionskontrolle"
+
+#: builtin/mv.c:173
+msgid "destination exists"
+msgstr "Ziel existiert"
+
+#: builtin/mv.c:181
+#, c-format
+msgid "overwriting '%s'"
+msgstr "überschreibe '%s'"
+
+#: builtin/mv.c:184
+msgid "Cannot overwrite"
+msgstr "Kann nicht überschreiben"
+
+#: builtin/mv.c:187
+msgid "multiple sources for the same target"
+msgstr "mehrere Quellen für das selbe Ziel"
+
+#: builtin/mv.c:202
+#, c-format
+msgid "%s, source=%s, destination=%s"
+msgstr "%s, Quelle=%s, Ziel=%s"
+
+#: builtin/mv.c:212
+#, c-format
+msgid "Renaming %s to %s\n"
+msgstr "Benenne %s nach %s um\n"
+
+#: builtin/mv.c:215
+#, c-format
+msgid "renaming '%s' failed"
+msgstr "Umbenennen von '%s' fehlgeschlagen"
+
+#: builtin/notes.c:139
+#, c-format
+msgid "unable to start 'show' for object '%s'"
+msgstr "konnte 'show' für Objekt '%s' nicht starten"
+
+#: builtin/notes.c:145
+msgid "can't fdopen 'show' output fd"
+msgstr "konnte Datei-Deskriptor für Ausgabe von 'show' nicht öffnen"
+
+#: builtin/notes.c:155
+#, c-format
+msgid "failed to close pipe to 'show' for object '%s'"
+msgstr "Schließen der Pipe zu 'show' für Objekt '%s' fehlgeschlagen."
+
+#: builtin/notes.c:158
+#, c-format
+msgid "failed to finish 'show' for object '%s'"
+msgstr "'show' konnte für Objekt '%s' nicht abgeschlossen werden"
+
+#: builtin/notes.c:175 builtin/tag.c:343
+#, c-format
+msgid "could not create file '%s'"
+msgstr "konnte Datei '%s' nicht erstellen"
+
+#: builtin/notes.c:189
+msgid "Please supply the note contents using either -m or -F option"
+msgstr "Bitte liefere den Notiz-Inhalt unter Verwendung der Option -m oder -F."
+
+#: builtin/notes.c:210 builtin/notes.c:973
+#, c-format
+msgid "Removing note for object %s\n"
+msgstr "Entferne Notiz für Objekt %s\n"
+
+#: builtin/notes.c:215
+msgid "unable to write note object"
+msgstr "Konnte Notiz-Objekt nicht schreiben"
+
+#: builtin/notes.c:217
+#, c-format
+msgid "The note contents has been left in %s"
+msgstr "Die Notiz-Inhalte wurden in %s belassen"
+
+#: builtin/notes.c:251 builtin/tag.c:521
+#, c-format
+msgid "cannot read '%s'"
+msgstr "kann '%s' nicht lesen"
+
+#: builtin/notes.c:253 builtin/tag.c:524
+#, c-format
+msgid "could not open or read '%s'"
+msgstr "konnte '%s' nicht öffnen oder lesen"
+
+#: builtin/notes.c:272 builtin/notes.c:445 builtin/notes.c:447
+#: builtin/notes.c:507 builtin/notes.c:561 builtin/notes.c:644
+#: builtin/notes.c:649 builtin/notes.c:724 builtin/notes.c:766
+#: builtin/notes.c:968 builtin/reset.c:293 builtin/tag.c:537
+#, c-format
+msgid "Failed to resolve '%s' as a valid ref."
+msgstr "'%s' konnte nicht als gültige Referenz aufgelöst werden."
+
+#: builtin/notes.c:275
+#, c-format
+msgid "Failed to read object '%s'."
+msgstr "Fehler beim Lesen des Objektes '%s'."
+
+#: builtin/notes.c:299
+msgid "Cannot commit uninitialized/unreferenced notes tree"
+msgstr "Kann uninitialisierten/unreferenzierten Notiz-Baum nicht eintragen."
+
+#: builtin/notes.c:340
+#, c-format
+msgid "Bad notes.rewriteMode value: '%s'"
+msgstr "Schlechter notes.rewriteMode Wert: '%s'"
+
+#: builtin/notes.c:350
+#, c-format
+msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
+msgstr ""
+"Neuschreiben der Notizen in %s zurückgewiesen (außerhalb von refs/notes/)"
+
+#. TRANSLATORS: The first %s is the name of the
+#. environment variable, the second %s is its value
+#: builtin/notes.c:377
+#, c-format
+msgid "Bad %s value: '%s'"
+msgstr "Schlechter %s Wert: '%s'"
+
+#: builtin/notes.c:441
+#, c-format
+msgid "Malformed input line: '%s'."
+msgstr "Fehlerhafte Eingabezeile: '%s'."
+
+#: builtin/notes.c:456
+#, c-format
+msgid "Failed to copy notes from '%s' to '%s'"
+msgstr "Fehler beim Kopieren der Notizen von '%s' nach '%s'"
+
+#: builtin/notes.c:500 builtin/notes.c:554 builtin/notes.c:627
+#: builtin/notes.c:639 builtin/notes.c:712 builtin/notes.c:759
+#: builtin/notes.c:1033
+msgid "too many parameters"
+msgstr "zu viele Parameter"
+
+#: builtin/notes.c:513 builtin/notes.c:772
+#, c-format
+msgid "No note found for object %s."
+msgstr "Kein Notiz für Objekt %s gefunden."
+
+#: builtin/notes.c:580
+#, c-format
+msgid ""
+"Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite "
+"existing notes"
+msgstr ""
+"Konnte Notizen nicht hinzufügen. Existierende Notizen für Objekt %s "
+"gefunden. Verwende '-f' um die existierenden Notizen zu überschreiben."
+
+#: builtin/notes.c:585 builtin/notes.c:662
+#, c-format
+msgid "Overwriting existing notes for object %s\n"
+msgstr "Überschreibe existierende Notizen für Objekt %s\n"
+
+#: builtin/notes.c:635
+msgid "too few parameters"
+msgstr "zu wenig Parameter"
+
+#: builtin/notes.c:656
+#, c-format
+msgid ""
+"Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite "
+"existing notes"
+msgstr ""
+"Kann Notizen nicht kopieren. Existierende Notizen für Objekt %s gefunden. "
+"Verwende '-f' um die existierenden Notizen zu überschreiben."
+
+#: builtin/notes.c:668
+#, c-format
+msgid "Missing notes on source object %s. Cannot copy."
+msgstr "Vermisse Notizen für Quell-Objekt %s. Kann nicht kopieren."
+
+#: builtin/notes.c:717
+#, c-format
+msgid ""
+"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"
+msgstr ""
+"Die Optionen -m/-F/-c/-C sind veraltet für das 'edit' Unterkommando.\n"
+"Bitte benutze stattdessen 'git notes add -f -m/-F/-c/-C'.\n"
+
+#: builtin/notes.c:971
+#, c-format
+msgid "Object %s has no note\n"
+msgstr "Objekt %s hat keine Notiz\n"
+
+#: builtin/notes.c:1103
+#, c-format
+msgid "Unknown subcommand: %s"
+msgstr "Unbekanntes Unterkommando: %s"
+
+#: builtin/pack-objects.c:2310
+#, c-format
+msgid "unsupported index version %s"
+msgstr "Nicht unterstützte Bereitstellungsversion %s"
+
+#: builtin/pack-objects.c:2314
+#, c-format
+msgid "bad index version '%s'"
+msgstr "Schlechte Bereitstellungsversion '%s'"
+
+#: builtin/pack-objects.c:2322
+#, c-format
+msgid "option %s does not accept negative form"
+msgstr "Option %s akzeptiert keine negative Form"
+
+#: builtin/pack-objects.c:2326
+#, c-format
+msgid "unable to parse value '%s' for option %s"
+msgstr "konnte Wert '%s' für Option %s nicht analysieren"
+
+#: builtin/push.c:45
+msgid "tag shorthand without <tag>"
+msgstr "Kurzschrift für Markierung ohne <Markierung>"
+
+#: builtin/push.c:64
+msgid "--delete only accepts plain target ref names"
+msgstr "--delete akzeptiert nur reine Referenz-Namen als Ziel"
+
+#: builtin/push.c:84
+#, c-format
+msgid ""
+"You are not currently on a branch.\n"
+"To push the history leading to the current (detached HEAD)\n"
+"state now, use\n"
+"\n"
+" git push %s HEAD:<name-of-remote-branch>\n"
+msgstr ""
+"Du befindest dich sich im Moment auf keinem Zweig.\n"
+"Um die Historie, führend zum aktuellen (freistehende Zweigspitze (HEAD))\n"
+"Status zu versenden, benutze\n"
+"\n"
+" git push %s HEAD:<Name-des-entfernten-Zweiges>\n"
+
+#: builtin/push.c:91
+#, c-format
+msgid ""
+"The current branch %s has no upstream branch.\n"
+"To push the current branch and set the remote as upstream, use\n"
+"\n"
+" git push --set-upstream %s %s\n"
+msgstr ""
+"Der aktuelle Zweig %s hat keinen Zweig im entfernten Projektarchiv.\n"
+"Um den aktuellen Zweig zu versenden und die Entfernung als entferntes\n"
+"Projektarchiv zu setzen, benutze\n"
+"\n"
+" git push --set-upstream %s %s\n"
+
+#: builtin/push.c:99
+#, c-format
+msgid "The current branch %s has multiple upstream branches, refusing to push."
+msgstr ""
+"Der aktuelle Zweig %s hat mehrere entfernte Zweige, Versand verweigert."
+
+#: builtin/push.c:102
+#, c-format
+msgid ""
+"You are pushing to remote '%s', which is not the upstream of\n"
+"your current branch '%s', without telling me what to push\n"
+"to update which remote branch."
+msgstr ""
+"Du versendest nach '%s', welches kein entferntes Projektarchiv deines\n"
+"aktuellen Zweiges '%s' ist, ohne mir mitzuteilen, was ich versenden\n"
+"soll um welchen entfernten Zweig zu aktualisieren."
+
+#: builtin/push.c:131
+msgid ""
+"You didn't specify any refspecs to push, and push.default is \"nothing\"."
+msgstr ""
+"Du hast keine Referenzspezifikationen zum Versenden spezifiziert, und push."
+"default ist \"nothing\"."
+
+#: builtin/push.c:138
+msgid ""
+"Updates were rejected because the tip of your current branch is behind\n"
+"its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
+"before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
+msgstr ""
+"Aktualisierungen wurden zurückgewiesen, weil die Spitze deines aktuellen\n"
+"Zweiges hinter seinem entfernten Gegenstück ist. Führe die entfernten\n"
+"Änderungen zusammen (z.B. 'git pull') bevor du erneut versendest.\n"
+"Siehe auch die 'Note about fast-forwards' Sektion von 'git push --help'\n"
+"für weitere Details."
+
+#: builtin/push.c:144
+msgid ""
+"Updates were rejected because a pushed branch tip is behind its remote\n"
+"counterpart. If you did not intend to push that branch, you may want to\n"
+"specify branches to push or set the 'push.default' configuration\n"
+"variable to 'current' or 'upstream' to push only the current branch."
+msgstr ""
+"Aktualisierungen wurden zurückgewiesen, weil die Spitze eines versendeten\n"
+"Zweiges hinter seinem entfernten Gegenstück ist. Wenn du nicht beabsichtigt\n"
+"hast, diesen Zweig zu versenden, kannst du auch den zu versendenden Zweig\n"
+"spezifizieren oder die Konfigurationsvariable 'push.default' zu 'current'\n"
+"oder 'upstream' setze, um nur den aktuellen Zweig zu versenden."
+
+#: builtin/push.c:150
+msgid ""
+"Updates were rejected because a pushed branch tip is behind its remote\n"
+"counterpart. Check out this branch and merge the remote changes\n"
+"(e.g. 'git pull') before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
+msgstr ""
+"Aktualisierungen wurden zurückgewiesen, weil die Spitze eines versendeten\n"
+"Zweiges hinter seinem entfernten Gegenstück ist. Checke diesen Zweig aus\n"
+"und führe die entfernten Änderungen zusammen (z.B. 'git pull') bevor du\n"
+"erneut versendest.\n"
+"Sie auch die 'Note about fast-forwards' Sektion von 'git push --help'\n"
+"für weitere Details."
+
+#: builtin/push.c:190
+#, c-format
+msgid "Pushing to %s\n"
+msgstr "Schiebe zu %s\n"
+
+#: builtin/push.c:194
+#, c-format
+msgid "failed to push some refs to '%s'"
+msgstr "Fehler beim Versenden einiger Referenzen nach '%s'"
+
+#: builtin/push.c:226
+#, c-format
+msgid "bad repository '%s'"
+msgstr "schlechtes Projektarchiv '%s'"
+
+#: builtin/push.c:227
+msgid ""
+"No configured push destination.\n"
+"Either specify the URL from the command-line or configure a remote "
+"repository using\n"
+"\n"
+" git remote add <name> <url>\n"
+"\n"
+"and then push using the remote name\n"
+"\n"
+" git push <name>\n"
+msgstr ""
+"Kein Ziel zum Versenden konfiguriert.\n"
+"Entweder spezifizierst du die URL von der Kommandozeile oder konfigurierst "
+"ein entferntes Projektarchiv unter Benutzung von\n"
+"\n"
+" git remote add <Name> <URL>\n"
+"\n"
+"und versendest dann unter Benutzung dieses Namens\n"
+"\n"
+" git push <Name>\n"
+
+#: builtin/push.c:242
+msgid "--all and --tags are incompatible"
+msgstr "--all und --tags sind inkompatibel"
+
+#: builtin/push.c:243
+msgid "--all can't be combined with refspecs"
+msgstr "--all kann nicht mit Referenzspezifikationen kombiniert werden"
+
+#: builtin/push.c:248
+msgid "--mirror and --tags are incompatible"
+msgstr "--mirror und --tags sind inkompatibel"
+
+#: builtin/push.c:249
+msgid "--mirror can't be combined with refspecs"
+msgstr "--mirror kann nicht mit Referenzspezifikationen kombiniert werden"
+
+#: builtin/push.c:254
+msgid "--all and --mirror are incompatible"
+msgstr "--all und --mirror sind inkompatibel"
+
+#: builtin/push.c:342
+msgid "--delete is incompatible with --all, --mirror and --tags"
+msgstr "--delete ist inkompatibel mit --all, --mirror und --tags"
+
+#: builtin/push.c:344
+msgid "--delete doesn't make sense without any refs"
+msgstr "--delete macht ohne irgendeine Referenz ohne keinen Sinn"
+
+#: builtin/reset.c:33
+msgid "mixed"
+msgstr "gemischt"
+
+#: builtin/reset.c:33
+msgid "soft"
+msgstr "weich"
+
+#: builtin/reset.c:33
+msgid "hard"
+msgstr "hart"
+
+#: builtin/reset.c:33
+msgid "keep"
+msgstr "halten"
+
+#: builtin/reset.c:77
+msgid "You do not have a valid HEAD."
+msgstr "Du hast keine gültige Zweigspitze (HEAD)."
+
+#: builtin/reset.c:79
+msgid "Failed to find tree of HEAD."
+msgstr "Fehler beim Finden des Baumes der Zweigspitze (HEAD)."
+
+#: builtin/reset.c:85
+#, c-format
+msgid "Failed to find tree of %s."
+msgstr "Fehler beim Finden des Baumes von %s."
+
+#: builtin/reset.c:96
+msgid "Could not write new index file."
+msgstr "Konnte neue Bereitstellungsdatei nicht schreiben."
+
+#: builtin/reset.c:106
+#, c-format
+msgid "HEAD is now at %s"
+msgstr "Zweigspitze (HEAD) ist jetzt bei %s"
+
+#: builtin/reset.c:130
+msgid "Could not read index"
+msgstr "Konnte Bereitstellung nicht lesen"
+
+#: builtin/reset.c:133
+msgid "Unstaged changes after reset:"
+msgstr "Nicht bereitgestellte Änderungen nach Zurücksetzung:"
+
+#: builtin/reset.c:223
+#, c-format
+msgid "Cannot do a %s reset in the middle of a merge."
+msgstr ""
+"Kann keine %s Zurücksetzung innerhalb einer Zusammenführung durchführen."
+
+#: builtin/reset.c:297
+#, c-format
+msgid "Could not parse object '%s'."
+msgstr "Konnte Objekt '%s' nicht parsen."
+
+#: builtin/reset.c:302
+msgid "--patch is incompatible with --{hard,mixed,soft}"
+msgstr "--patch ist inkompatibel mit --{hard,mixed,soft}"
+
+#: builtin/reset.c:311
+msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
+msgstr ""
+"--mixed mit Pfaden ist veraltet; benutze stattdessen 'git reset -- <Pfade>'."
+
+#: builtin/reset.c:313
+#, c-format
+msgid "Cannot do %s reset with paths."
+msgstr "Kann keine %s Zurücksetzung mit Pfaden machen."
+
+#: builtin/reset.c:325
+#, c-format
+msgid "%s reset is not allowed in a bare repository"
+msgstr "%s Zurücksetzung ist in einem leeren Projektarchiv nicht erlaubt"
+
+#: builtin/reset.c:341
+#, c-format
+msgid "Could not reset index file to revision '%s'."
+msgstr "Konnte Bereitstellungsdatei nicht zu Revision '%s' zurücksetzen."
+
+#: builtin/revert.c:70 builtin/revert.c:92
+#, c-format
+msgid "%s: %s cannot be used with %s"
+msgstr "%s: %s kann nicht mit %s benutzt werden"
+
+#: builtin/revert.c:127
+msgid "program error"
+msgstr "Programmfehler"
+
+#: builtin/revert.c:213
+msgid "revert failed"
+msgstr "\"revert\" fehlgeschlagen"
+
+#: builtin/revert.c:228
+msgid "cherry-pick failed"
+msgstr "\"cherry-pick\" fehlgeschlagen"
+
+#: builtin/rm.c:109
+#, c-format
+msgid ""
+"'%s' has staged content different from both the file and the HEAD\n"
+"(use -f to force removal)"
+msgstr ""
+"'%s' hat bereitgestellten Inhalt unterschiedlich zu der Datei und der\n"
+"Zweigspitze (HEAD) (benutze -f um die Entfernung zu erzwingen)"
+
+#: builtin/rm.c:115
+#, c-format
+msgid ""
+"'%s' has changes staged in the index\n"
+"(use --cached to keep the file, or -f to force removal)"
+msgstr ""
+"'%s' hat Änderungen in der Bereitstellung\n"
+"(benutze --cached um die Datei zu behalten, oder -f um die Entfernung zu "
+"erzwingen)"
+
+#: builtin/rm.c:119
+#, c-format
+msgid ""
+"'%s' has local modifications\n"
+"(use --cached to keep the file, or -f to force removal)"
+msgstr ""
+"'%s' hat lokale Modifikationen\n"
+"(benutze --cached um die Datei zu behalten, oder -f um die Entfernung zu "
+"erzwingen)"
+
+#: builtin/rm.c:194
+#, c-format
+msgid "not removing '%s' recursively without -r"
+msgstr "entferne '%s' nicht rekursiv ohne -r"
+
+#: builtin/rm.c:230
+#, c-format
+msgid "git rm: unable to remove %s"
+msgstr "git rm: konnte %s nicht entfernen"
+
+#: builtin/shortlog.c:157
+#, c-format
+msgid "Missing author: %s"
+msgstr "fehlender Autor: %s"
+
+#: builtin/tag.c:58
+#, c-format
+msgid "malformed object at '%s'"
+msgstr "fehlerhaftes Objekt bei '%s'"
+
+#: builtin/tag.c:205
+#, c-format
+msgid "tag name too long: %.*s..."
+msgstr "Markierungsname zu lang: %.*s..."
+
+#: builtin/tag.c:210
+#, c-format
+msgid "tag '%s' not found."
+msgstr "Markierung '%s' nicht gefunden."
+
+#: builtin/tag.c:225
+#, c-format
+msgid "Deleted tag '%s' (was %s)\n"
+msgstr "Gelöschte Markierung '%s' (war %s)\n"
+
+#: builtin/tag.c:237
+#, c-format
+msgid "could not verify the tag '%s'"
+msgstr "Konnte Markierung '%s' nicht verifizieren"
+
+#: builtin/tag.c:247
+msgid ""
+"\n"
+"#\n"
+"# Write a tag message\n"
+"# Lines starting with '#' will be ignored.\n"
+"#\n"
+msgstr ""
+"\n"
+"#\n"
+"# Gebe eine Markierungsbeschreibung ein\n"
+"# Zeilen beginnend mit '#' werden ignoriert.\n"
+"#\n"
+
+#: builtin/tag.c:254
+msgid ""
+"\n"
+"#\n"
+"# Write a tag message\n"
+"# Lines starting with '#' will be kept; you may remove them yourself if you "
+"want to.\n"
+"#\n"
+msgstr ""
+"\n"
+"#\n"
+"# Gebe eine Markierungsbeschreibung ein\n"
+"# Zeilen beginnend mit '#' werden behalten; du darfst diese selbst entfernen "
+"wenn du möchtest.\n"
+"#\n"
+
+#: builtin/tag.c:294
+msgid "unable to sign the tag"
+msgstr "konnte Markierung nicht signieren"
+
+#: builtin/tag.c:296
+msgid "unable to write tag file"
+msgstr "konnte Markierungsdatei nicht schreiben"
+
+#: builtin/tag.c:321
+msgid "bad object type."
+msgstr "schlechter Objekt-Typ"
+
+#: builtin/tag.c:334
+msgid "tag header too big."
+msgstr "Markierungskopf zu groß."
+
+#: builtin/tag.c:366
+msgid "no tag message?"
+msgstr "keine Markierungsbeschreibung?"
+
+#: builtin/tag.c:372
+#, c-format
+msgid "The tag message has been left in %s\n"
+msgstr "Die Markierungsbeschreibung wurde gelassen in %s\n"
+
+#: builtin/tag.c:421
+msgid "switch 'points-at' requires an object"
+msgstr "Wechseln von 'points-at' erfordert ein Objekt"
+
+#: builtin/tag.c:423
+#, c-format
+msgid "malformed object name '%s'"
+msgstr "fehlerhafter Objekt-Name '%s'"
+
+#: builtin/tag.c:502
+msgid "-n option is only allowed with -l."
+msgstr "-n Option ist nur erlaubt mit -l."
+
+#: builtin/tag.c:504
+msgid "--contains option is only allowed with -l."
+msgstr "--contains Option ist nur erlaubt mit -l."
+
+#: builtin/tag.c:506
+msgid "--points-at option is only allowed with -l."
+msgstr "--points-at Option ist nur erlaubt mit -l."
+
+#: builtin/tag.c:514
+msgid "only one -F or -m option is allowed."
+msgstr "nur eine -F oder -m Option ist erlaubt."
+
+#: builtin/tag.c:534
+msgid "too many params"
+msgstr "zu viele Parameter"
+
+#: builtin/tag.c:540
+#, c-format
+msgid "'%s' is not a valid tag name."
+msgstr "'%s' ist kein gültiger Markierungsname."
+
+#: builtin/tag.c:545
+#, c-format
+msgid "tag '%s' already exists"
+msgstr "Markierung '%s' existiert bereits"
+
+#: builtin/tag.c:563
+#, c-format
+msgid "%s: cannot lock the ref"
+msgstr "%s: kann Referenz nicht sperren"
+
+#: builtin/tag.c:565
+#, c-format
+msgid "%s: cannot update the ref"
+msgstr "%s: kann Referenz nicht aktualisieren"
+
+#: builtin/tag.c:567
+#, c-format
+msgid "Updated tag '%s' (was %s)\n"
+msgstr "Aktualisierte Markierung '%s' (war %s)\n"
+
+#: git-am.sh:50
+msgid "You need to set your committer info first"
+msgstr "Du musst zuerst die Informationen des Eintragenden setzen."
+
+#: git-am.sh:137
+msgid "Repository lacks necessary blobs to fall back on 3-way merge."
+msgstr ""
+"Dem Projektarchiv fehlen notwendige Blobs um auf eine 3-Wege-Zusammenführung "
+"zurückzufallen."
+
+#: git-am.sh:154
+msgid ""
+"Did you hand edit your patch?\n"
+"It does not apply to blobs recorded in its index."
+msgstr ""
+"Hast du den Patch per Hand editiert?\n"
+"Er kann nicht auf aufgezeichnete Blobs in seiner Bereitstellung angewendet "
+"werden."
+
+#: git-am.sh:163
+msgid "Falling back to patching base and 3-way merge..."
+msgstr "Falle zurück zum Patchen der Basis und der 3-Wege-Zusammenführung..."
+
+#: git-am.sh:275
+msgid "Only one StGIT patch series can be applied at once"
+msgstr "Es kann nur eine StGIT Patch-Serie auf einmal angewendet werden."
+
+#: git-am.sh:362
+#, sh-format
+msgid "Patch format $patch_format is not supported."
+msgstr "Patch-Format $patch_format wird nicht unterstützt."
+
+#: git-am.sh:364
+msgid "Patch format detection failed."
+msgstr "Patch-Formaterkennung fehlgeschlagen."
+
+#: git-am.sh:418
+msgid "-d option is no longer supported. Do not use."
+msgstr "-d Option wird nicht länger unterstützt. Nicht benutzen."
+
+#: git-am.sh:481
+#, sh-format
+msgid "previous rebase directory $dotest still exists but mbox given."
+msgstr ""
+"Vorheriges Verzeichnis des Neuaufbaus $dotest existiert noch, aber mbox "
+"gegeben."
+
+#: git-am.sh:486
+msgid "Please make up your mind. --skip or --abort?"
+msgstr "Bitte werde dir klar. --skip oder --abort?"
+
+#: git-am.sh:513
+msgid "Resolve operation not in progress, we are not resuming."
+msgstr "keine Auflösung in Durchführung, wir setzen nicht fort."
+
+#: git-am.sh:579
+#, sh-format
+msgid "Dirty index: cannot apply patches (dirty: $files)"
+msgstr ""
+"Unsaubere Bereitstellung: kann Patches nicht anwenden (unsauber: $files)"
+
+#: git-am.sh:755
+msgid "cannot be interactive without stdin connected to a terminal."
+msgstr ""
+"Kann nicht interaktiv sein, ohne das die Standard-Eingabe mit einem Terminal "
+"verbunden ist."
+
+#. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
+#. in your translation. The program will only accept English
+#. input at this point.
+#: git-am.sh:766
+msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
+msgstr "Anwenden? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
+
+#: git-am.sh:802
+#, sh-format
+msgid "Applying: $FIRSTLINE"
+msgstr "Wende an: $FIRSTLINE"
+
+#: git-am.sh:847
+msgid "No changes -- Patch already applied."
+msgstr "Keine Änderungen -- Patches bereits angewendet."
+
+#: git-am.sh:873
+msgid "applying to an empty history"
+msgstr "wende zu leerer Historie an"
+
+#. TRANSLATORS: Make sure to include [Y] and [n] in your
+#. translation. The program will only accept English input
+#. at this point.
+#: git-bisect.sh:54
+msgid "Do you want me to do it for you [Y/n]? "
+msgstr "Willst du, dass ich es für dich mache [Y/n]? "
+
+#: git-bisect.sh:95
+#, sh-format
+msgid "unrecognised option: '$arg'"
+msgstr "nicht erkannte Option: '$arg'"
+
+#: git-bisect.sh:99
+#, sh-format
+msgid "'$arg' does not appear to be a valid revision"
+msgstr "'$arg' scheint keine gültige Option zu sein"
+
+#: git-bisect.sh:117
+msgid "Bad HEAD - I need a HEAD"
+msgstr "Schlechte Zweigspitze (HEAD) - Ich brauche eine Zweigspitze (HEAD)"
+
+#: git-bisect.sh:130
+#, sh-format
+msgid ""
+"Checking out '$start_head' failed. Try 'git bisect reset <validbranch>'."
+msgstr ""
+"Auschecken von '$start_head' fehlgeschlagen. Versuche 'git bisect reset "
+"<gueltigerzweig>'."
+
+#: git-bisect.sh:140
+msgid "won't bisect on seeked tree"
+msgstr "werde nicht auf gesuchtem Baum halbieren"
+
+#: git-bisect.sh:144
+msgid "Bad HEAD - strange symbolic ref"
+msgstr "Schlechte Zweigspitze (HEAD) - merkwürdige symbolische Referenz"
+
+#: git-bisect.sh:189
+#, sh-format
+msgid "Bad bisect_write argument: $state"
+msgstr "Schlechtes \"bisect_write\" Argument: $state"
+
+#: git-bisect.sh:218
+#, sh-format
+msgid "Bad rev input: $arg"
+msgstr "Schlechte Referenz-Eingabe: $arg"
+
+#: git-bisect.sh:232
+msgid "Please call 'bisect_state' with at least one argument."
+msgstr "Bitte rufe 'bisect_state' mit mindestens einem Argument."
+
+#: git-bisect.sh:244
+#, sh-format
+msgid "Bad rev input: $rev"
+msgstr "Schlechte Referenz-Eingabe: $rev"
+
+#: git-bisect.sh:250
+msgid "'git bisect bad' can take only one argument."
+msgstr "'git bisect bad' kann nur ein Argument entgegennehmen."
+
+#. TRANSLATORS: Make sure to include [Y] and [n] in your
+#. translation. The program will only accept English input
+#. at this point.
+#: git-bisect.sh:279
+msgid "Are you sure [Y/n]? "
+msgstr "Bist du sicher [Y/n]? "
+
+#: git-bisect.sh:354
+#, sh-format
+msgid "'$invalid' is not a valid commit"
+msgstr "'$invalid' ist keine gültige Version"
+
+#: git-bisect.sh:363
+#, sh-format
+msgid ""
+"Could not check out original HEAD '$branch'.\n"
+"Try 'git bisect reset <commit>'."
+msgstr ""
+"Konnte die originale Zweigspitze (HEAD) '$branch' nicht auschecken.\n"
+"Versuche 'git bisect reset <Version>'."
+
+#: git-bisect.sh:390
+msgid "No logfile given"
+msgstr "Keine Log-Datei gegeben"
+
+#: git-bisect.sh:391
+#, sh-format
+msgid "cannot read $file for replaying"
+msgstr "kann $file nicht für das Abspielen lesen"
+
+#: git-bisect.sh:408
+msgid "?? what are you talking about?"
+msgstr "?? Was redest du da?"
+
+#: git-bisect.sh:474
+msgid "We are not bisecting."
+msgstr "Wir sind nicht beim Halbieren."
+
+#: git-pull.sh:21
+msgid ""
+"Pull is not possible because you have unmerged files.\n"
+"Please, fix them up in the work tree, and then use 'git add/rm <file>'\n"
+"as appropriate to mark resolution, or use 'git commit -a'."
+msgstr ""
+"\"pull\" ist nicht möglich weil du nicht zusammengeführte Dateien hast.\n"
+"Bitte korrigiere dies im Arbeitsbaum und benutze dann 'git add/rm <Datei>'\n"
+"wie vorgesehen, um die Auflösung zu markieren, oder benutze 'git commit -a'."
+
+#: git-pull.sh:25
+msgid "Pull is not possible because you have unmerged files."
+msgstr ""
+"\"pull\" ist nicht möglich, weil du nicht zusammengeführte Dateien hast."
+
+#: git-pull.sh:197
+msgid "updating an unborn branch with changes added to the index"
+msgstr ""
+"Aktualisiere eine ungeborenen Zweig mit Änderungen, die zur Bereitstellung "
+"hinzugefügt wurden"
+
+#: git-pull.sh:253
+msgid "Cannot merge multiple branches into empty head"
+msgstr "Kann nicht mehrere Zweige in einen leeren Kopf zusammenführen"
+
+#: git-pull.sh:257
+msgid "Cannot rebase onto multiple branches"
+msgstr "kann nicht auf mehrere Zweige neu aufbauen"
+
+#: git-stash.sh:51
+msgid "git stash clear with parameters is unimplemented"
+msgstr "git stash clear mit Parametern ist nicht implementiert"
+
+#: git-stash.sh:74
+msgid "You do not have the initial commit yet"
+msgstr "Du hast bisher noch keine initiale Version"
+
+#: git-stash.sh:89
+msgid "Cannot save the current index state"
+msgstr "Kann den aktuellen Zustand der Bereitstellung nicht speichern"
+
+#: git-stash.sh:123 git-stash.sh:136
+msgid "Cannot save the current worktree state"
+msgstr "Kann den aktuellen Zustand des Arbeitsbaumes nicht speichern"
+
+#: git-stash.sh:140
+msgid "No changes selected"
+msgstr "Keine Änderungen ausgewählt"
+
+#: git-stash.sh:143
+msgid "Cannot remove temporary index (can't happen)"
+msgstr "Kann temporäre Bereitstellung nicht entfernen (kann nicht passieren)"
+
+#: git-stash.sh:156
+msgid "Cannot record working tree state"
+msgstr "Kann Zustand des Arbeitsbaumes nicht aufzeichnen"
+
+#: git-stash.sh:223
+msgid "No local changes to save"
+msgstr "Keine lokalen Änderungen zum Speichern"
+
+#: git-stash.sh:227
+msgid "Cannot initialize stash"
+msgstr "Kann \"stash\" nicht initialisieren"
+
+#: git-stash.sh:235
+msgid "Cannot save the current status"
+msgstr "Kann den aktuellen Status nicht speichern"
+
+#: git-stash.sh:253
+msgid "Cannot remove worktree changes"
+msgstr "Kann Änderungen am Arbeitsbaum nicht entfernen"
+
+#: git-stash.sh:352
+msgid "No stash found."
+msgstr "Kein \"stash\" gefunden."
+
+#: git-stash.sh:359
+#, sh-format
+msgid "Too many revisions specified: $REV"
+msgstr "Zu viele Revisionen spezifiziert: $REV"
+
+#: git-stash.sh:365
+#, sh-format
+msgid "$reference is not valid reference"
+msgstr "$reference ist keine gültige Referenz"
+
+#: git-stash.sh:393
+#, sh-format
+msgid "'$args' is not a stash-like commit"
+msgstr "'$args' ist keine \"stash\"-artiger Version"
+
+#: git-stash.sh:404
+#, sh-format
+msgid "'$args' is not a stash reference"
+msgstr "'$args' ist keine \"stash\"-Referenz"
+
+#: git-stash.sh:412
+msgid "unable to refresh index"
+msgstr "unfähig die Bereitstellung zu aktualisieren"
+
+#: git-stash.sh:416
+msgid "Cannot apply a stash in the middle of a merge"
+msgstr "Kann keinen \"stash\" innerhalb einer Zusammenführung anwenden"
+
+#: git-stash.sh:424
+msgid "Conflicts in index. Try without --index."
+msgstr "Konflikte in der Bereitstellung. Versuche es ohne --index."
+
+#: git-stash.sh:426
+msgid "Could not save index tree"
+msgstr "Konnte Bereitstellungsbaum nicht speichern"
+
+#: git-stash.sh:460
+msgid "Cannot unstage modified files"
+msgstr "Kann geänderte Dateien nicht aus der Bereitstellung herausnehmen"
+
+#: git-stash.sh:491
+#, sh-format
+msgid "Dropped ${REV} ($s)"
+msgstr "Gelöscht ${REV} ($s)"
+
+#: git-stash.sh:492
+#, sh-format
+msgid "${REV}: Could not drop stash entry"
+msgstr "${REV}: Konnte \"stash\"-Eintrag nicht löschen"
+
+#: git-stash.sh:499
+msgid "No branch name specified"
+msgstr "Kein Zweigname spezifiziert"
+
+#: git-stash.sh:570
+msgid "(To restore them type \"git stash apply\")"
+msgstr "(Um es wiederherzustellen schreibe \"git stash apply\")"
+
+#: git-submodule.sh:56
+#, sh-format
+msgid "cannot strip one component off url '$remoteurl'"
+msgstr "Kann eine Komponente von URL '$remoteurl' nicht abstreifen"
+
+#: git-submodule.sh:109
+#, sh-format
+msgid "No submodule mapping found in .gitmodules for path '$sm_path'"
+msgstr "Keine Unterprojekt-Zuordnung in .gitmodules für Pfad '$sm_path' gefunden"
+
+#: git-submodule.sh:150
+#, sh-format
+msgid "Clone of '$url' into submodule path '$sm_path' failed"
+msgstr "Klonen von '$url' in Unterprojekt-Pfad '$sm_path' fehlgeschlagen"
+
+#: git-submodule.sh:160
+#, sh-format
+msgid "Gitdir '$a' is part of the submodule path '$b' or vice versa"
+msgstr ""
+"Git-Verzeichnis '$a' ist Teil des Unterprojekt-Pfades '$b' oder umgekehrt"
+
+#: git-submodule.sh:249
+#, sh-format
+msgid "repo URL: '$repo' must be absolute or begin with ./|../"
+msgstr "repo URL: '$repo' muss absolut sein oder mit ./|../ beginnen"
+
+#: git-submodule.sh:266
+#, sh-format
+msgid "'$sm_path' already exists in the index"
+msgstr "'$sm_path' existiert bereits in der Bereitstellung"
+
+#: git-submodule.sh:283
+#, sh-format
+msgid "'$sm_path' already exists and is not a valid git repo"
+msgstr "'$sm_path' existiert bereits und ist kein gültiges Git-Projektarchiv"
+
+#: git-submodule.sh:297
+#, sh-format
+msgid "Unable to checkout submodule '$sm_path'"
+msgstr "Unfähig Unterprojekt '$sm_path' auszuchecken"
+
+#: git-submodule.sh:302
+#, sh-format
+msgid "Failed to add submodule '$sm_path'"
+msgstr "Hinzufügen von Unterprojekt '$sm_path' fehlgeschlagen"
+
+#: git-submodule.sh:307
+#, sh-format
+msgid "Failed to register submodule '$sm_path'"
+msgstr "Registierung von Unterprojekt '$sm_path' fehlgeschlagen"
+
+#: git-submodule.sh:349
+#, sh-format
+msgid "Entering '$prefix$sm_path'"
+msgstr "Betrete '$prefix$sm_path'"
+
+#: git-submodule.sh:363
+#, sh-format
+msgid "Stopping at '$sm_path'; script returned non-zero status."
+msgstr "Stoppe bei '$sm_path'; Skript gab nicht-Null Status zurück."
+
+#: git-submodule.sh:405
+#, sh-format
+msgid "No url found for submodule path '$sm_path' in .gitmodules"
+msgstr "Keine URL für Unterprojekt-Pfad '$sm_path' in .gitmodules gefunden"
+
+#: git-submodule.sh:414
+#, sh-format
+msgid "Failed to register url for submodule path '$sm_path'"
+msgstr "Fehler beim Registrieren der URL für Unterprojekt-Pfad '$sm_path'"
+
+#: git-submodule.sh:422
+#, sh-format
+msgid "Failed to register update mode for submodule path '$sm_path'"
+msgstr ""
+"Fehler beim Registrieren des Aktualisierungsmodus für Unterprojekt-Pfad "
+"'$sm_path'"
+
+#: git-submodule.sh:424
+#, sh-format
+msgid "Submodule '$name' ($url) registered for path '$sm_path'"
+msgstr "Unterprojekt '$name' ($url) registriert für Pfad '$sm_path'"
+
+#: git-submodule.sh:523
+#, sh-format
+msgid ""
+"Submodule path '$sm_path' not initialized\n"
+"Maybe you want to use 'update --init'?"
+msgstr ""
+"Unterprojekt-Pfad '$sm_path' nicht initialisiert\n"
+"Vielleicht möchtest du 'update --init' benutzen?"
+
+#: git-submodule.sh:536
+#, sh-format
+msgid "Unable to find current revision in submodule path '$sm_path'"
+msgstr "Konnte aktuelle Revision in Unterprojekt-Pfad '$sm_path' nicht finden"
+
+#: git-submodule.sh:555
+#, sh-format
+msgid "Unable to fetch in submodule path '$sm_path'"
+msgstr "Konnte in Unterprojekt-Pfad '$sm_path' nicht anfordern"
+
+#: git-submodule.sh:569
+#, sh-format
+msgid "Unable to rebase '$sha1' in submodule path '$sm_path'"
+msgstr "Neuaufbau von '$sha1' in Unterprojekt-Pfad '$sm_path' nicht möglich"
+
+#: git-submodule.sh:570
+#, sh-format
+msgid "Submodule path '$sm_path': rebased into '$sha1'"
+msgstr "Unterprojekt-Pfad '$sm_path': neu aufgebaut in '$sha1'"
+
+#: git-submodule.sh:575
+#, sh-format
+msgid "Unable to merge '$sha1' in submodule path '$sm_path'"
+msgstr "Konnte '$sha1' nicht in Unterprojekt-Pfad '$sm_path' zusammenführen"
+
+#: git-submodule.sh:576
+#, sh-format
+msgid "Submodule path '$sm_path': merged in '$sha1'"
+msgstr "Unterprojekt-Pfad '$sm_path': zusammengeführt in '$sha1'"
+
+#: git-submodule.sh:581
+#, sh-format
+msgid "Unable to checkout '$sha1' in submodule path '$sm_path'"
+msgstr "Konnte '$sha1' in Unterprojekt-Pfad '$sm_path' nicht auschecken."
+
+#: git-submodule.sh:582
+#, sh-format
+msgid "Submodule path '$sm_path': checked out '$sha1'"
+msgstr "Unterprojekt-Pfad: '$sm_path': '$sha1' ausgecheckt"
+
+#: git-submodule.sh:604 git-submodule.sh:927
+#, sh-format
+msgid "Failed to recurse into submodule path '$sm_path'"
+msgstr "Fehler bei Rekursion in Unterprojekt-Pfad '$sm_path'"
+
+#: git-submodule.sh:712
+msgid "--"
+msgstr "--"
+
+#: git-submodule.sh:770
+#, sh-format
+msgid " Warn: $name doesn't contain commit $sha1_src"
+msgstr " Warnung: $name beinhaltet nicht Version $sha1_src"
+
+#: git-submodule.sh:773
+#, sh-format
+msgid " Warn: $name doesn't contain commit $sha1_dst"
+msgstr " Warnung: $name beinhaltet nicht Version $sha1_dst"
+
+#: git-submodule.sh:776
+#, sh-format
+msgid " Warn: $name doesn't contain commits $sha1_src and $sha1_dst"
+msgstr " Warnung: $name beinhaltet nich die Versionen $sha1_src und $sha1_dst"
+
+#: git-submodule.sh:801
+msgid "blob"
+msgstr "Blob"
+
+#: git-submodule.sh:802
+msgid "submodule"
+msgstr "Unterprojekt"
+
+#: git-submodule.sh:973
+#, sh-format
+msgid "Synchronizing submodule url for '$name'"
+msgstr "Synchronisiere Unterprojekt-URL für '$name'"
diff --git a/po/git.pot b/po/git.pot
index 566c7fdda6..730cac7b83 100644
--- a/po/git.pot
+++ b/po/git.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2012-03-16 20:18+0800\n"
+"POT-Creation-Date: 2012-04-28 20:17+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,7 +18,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
-#: advice.c:34
+#: advice.c:40
#, c-format
msgid "hint: %.*s\n"
msgstr ""
@@ -27,7 +27,7 @@ msgstr ""
#. * Message used both when 'git commit' fails and when
#. * other commands doing a merge do.
#.
-#: advice.c:64
+#: advice.c:70
msgid ""
"Fix them up in the work tree,\n"
"and then use 'git add/rm <file>' as\n"
@@ -35,12 +35,12 @@ msgid ""
"or use 'git commit -a'."
msgstr ""
-#: commit.c:47
+#: commit.c:48
#, c-format
msgid "could not parse %s"
msgstr ""
-#: commit.c:49
+#: commit.c:50
#, c-format
msgid "%s %s is not a commit!"
msgstr ""
@@ -80,32 +80,32 @@ msgid ""
"%s"
msgstr ""
-#: diff.c:1336
+#: diff.c:1400
msgid " 0 files changed\n"
msgstr ""
-#: diff.c:1340
+#: diff.c:1404
#, c-format
msgid " %d file changed"
msgid_plural " %d files changed"
msgstr[0] ""
msgstr[1] ""
-#: diff.c:1357
+#: diff.c:1421
#, c-format
msgid ", %d insertion(+)"
msgid_plural ", %d insertions(+)"
msgstr[0] ""
msgstr[1] ""
-#: diff.c:1368
+#: diff.c:1432
#, c-format
msgid ", %d deletion(-)"
msgid_plural ", %d deletions(-)"
msgstr[0] ""
msgstr[1] ""
-#: diff.c:3424
+#: diff.c:3435
#, c-format
msgid ""
"Failed to parse --dirstat/-X option parameter:\n"
@@ -172,14 +172,14 @@ msgid_plural ""
msgstr[0] ""
msgstr[1] ""
-#: sequencer.c:120 builtin/merge.c:864 builtin/merge.c:985
-#: builtin/merge.c:1095 builtin/merge.c:1105
+#: sequencer.c:120 builtin/merge.c:865 builtin/merge.c:978
+#: builtin/merge.c:1088 builtin/merge.c:1098
#, c-format
msgid "Could not open '%s' for writing"
msgstr ""
-#: sequencer.c:122 builtin/merge.c:334 builtin/merge.c:867
-#: builtin/merge.c:1097 builtin/merge.c:1110
+#: sequencer.c:122 builtin/merge.c:333 builtin/merge.c:868
+#: builtin/merge.c:1090 builtin/merge.c:1103
#, c-format
msgid "Could not write to '%s'"
msgstr ""
@@ -270,8 +270,8 @@ msgstr ""
msgid "could not apply %s... %s"
msgstr ""
-#: sequencer.c:450 sequencer.c:909 builtin/log.c:288 builtin/log.c:713
-#: builtin/log.c:1329 builtin/log.c:1548 builtin/merge.c:348
+#: sequencer.c:450 sequencer.c:909 builtin/log.c:289 builtin/log.c:719
+#: builtin/log.c:1335 builtin/log.c:1554 builtin/merge.c:347
#: builtin/shortlog.c:181
msgid "revision walk setup failed"
msgstr ""
@@ -396,6 +396,25 @@ msgstr ""
msgid "Can't cherry-pick into empty head"
msgstr ""
+#: sha1_name.c:864
+msgid "HEAD does not point to a branch"
+msgstr ""
+
+#: sha1_name.c:867
+#, c-format
+msgid "No such branch: '%s'"
+msgstr ""
+
+#: sha1_name.c:869
+#, c-format
+msgid "No upstream configured for branch '%s'"
+msgstr ""
+
+#: sha1_name.c:872
+#, c-format
+msgid "Upstream branch '%s' not stored as a remote-tracking branch"
+msgstr ""
+
#: wt-status.c:134
msgid "Unmerged paths:"
msgstr ""
@@ -779,128 +798,128 @@ msgid ""
msgstr ""
#. TRANSLATORS: This is "remote " in "remote branch '%s' not found"
-#: builtin/branch.c:163
+#: builtin/branch.c:164
msgid "remote "
msgstr ""
-#: builtin/branch.c:171
+#: builtin/branch.c:172
msgid "cannot use -a with -d"
msgstr ""
-#: builtin/branch.c:177
+#: builtin/branch.c:178
msgid "Couldn't look up commit object for HEAD"
msgstr ""
-#: builtin/branch.c:182
+#: builtin/branch.c:183
#, c-format
msgid "Cannot delete the branch '%s' which you are currently on."
msgstr ""
-#: builtin/branch.c:192
+#: builtin/branch.c:193
#, c-format
msgid "%sbranch '%s' not found."
msgstr ""
-#: builtin/branch.c:200
+#: builtin/branch.c:201
#, c-format
msgid "Couldn't look up commit object for '%s'"
msgstr ""
-#: builtin/branch.c:206
+#: builtin/branch.c:207
#, c-format
msgid ""
"The branch '%s' is not fully merged.\n"
"If you are sure you want to delete it, run 'git branch -D %s'."
msgstr ""
-#: builtin/branch.c:214
+#: builtin/branch.c:215
#, c-format
msgid "Error deleting %sbranch '%s'"
msgstr ""
-#: builtin/branch.c:219
+#: builtin/branch.c:221
#, c-format
msgid "Deleted %sbranch %s (was %s).\n"
msgstr ""
-#: builtin/branch.c:224
+#: builtin/branch.c:226
msgid "Update of config-file failed"
msgstr ""
-#: builtin/branch.c:322
+#: builtin/branch.c:324
#, c-format
msgid "branch '%s' does not point at a commit"
msgstr ""
-#: builtin/branch.c:394
+#: builtin/branch.c:396
#, c-format
msgid "behind %d] "
msgstr ""
-#: builtin/branch.c:396
+#: builtin/branch.c:398
#, c-format
msgid "ahead %d] "
msgstr ""
-#: builtin/branch.c:398
+#: builtin/branch.c:400
#, c-format
msgid "ahead %d, behind %d] "
msgstr ""
-#: builtin/branch.c:501
+#: builtin/branch.c:503
msgid "(no branch)"
msgstr ""
-#: builtin/branch.c:566
+#: builtin/branch.c:568
msgid "some refs could not be read"
msgstr ""
-#: builtin/branch.c:579
+#: builtin/branch.c:581
msgid "cannot rename the current branch while not on any."
msgstr ""
-#: builtin/branch.c:589
+#: builtin/branch.c:591
#, c-format
msgid "Invalid branch name: '%s'"
msgstr ""
-#: builtin/branch.c:604
+#: builtin/branch.c:606
msgid "Branch rename failed"
msgstr ""
-#: builtin/branch.c:608
+#: builtin/branch.c:610
#, c-format
msgid "Renamed a misnamed branch '%s' away"
msgstr ""
-#: builtin/branch.c:612
+#: builtin/branch.c:614
#, c-format
msgid "Branch renamed to %s, but HEAD is not updated!"
msgstr ""
-#: builtin/branch.c:619
+#: builtin/branch.c:621
msgid "Branch is renamed, but update of config-file failed"
msgstr ""
-#: builtin/branch.c:634
+#: builtin/branch.c:636
#, c-format
msgid "malformed object name %s"
msgstr ""
-#: builtin/branch.c:658
+#: builtin/branch.c:660
#, c-format
msgid "could not write branch description template: %s\n"
msgstr ""
-#: builtin/branch.c:746
+#: builtin/branch.c:750
msgid "Failed to resolve HEAD as a valid ref."
msgstr ""
-#: builtin/branch.c:751 builtin/clone.c:558
+#: builtin/branch.c:755 builtin/clone.c:558
msgid "HEAD not found below refs/heads!"
msgstr ""
-#: builtin/branch.c:809
+#: builtin/branch.c:813
msgid "-a and -r options to 'git branch' do not make sense with a branch name"
msgstr ""
@@ -962,7 +981,7 @@ msgid "path '%s' is unmerged"
msgstr ""
#: builtin/checkout.c:302 builtin/checkout.c:498 builtin/clone.c:583
-#: builtin/merge.c:811
+#: builtin/merge.c:812
msgid "unable to write new index file"
msgstr ""
@@ -979,42 +998,42 @@ msgstr ""
msgid "Can not do reflog for '%s'\n"
msgstr ""
-#: builtin/checkout.c:565
+#: builtin/checkout.c:566
msgid "HEAD is now at"
msgstr ""
-#: builtin/checkout.c:572
+#: builtin/checkout.c:573
#, c-format
msgid "Reset branch '%s'\n"
msgstr ""
-#: builtin/checkout.c:575
+#: builtin/checkout.c:576
#, c-format
msgid "Already on '%s'\n"
msgstr ""
-#: builtin/checkout.c:579
+#: builtin/checkout.c:580
#, c-format
msgid "Switched to and reset branch '%s'\n"
msgstr ""
-#: builtin/checkout.c:581
+#: builtin/checkout.c:582
#, c-format
msgid "Switched to a new branch '%s'\n"
msgstr ""
-#: builtin/checkout.c:583
+#: builtin/checkout.c:584
#, c-format
msgid "Switched to branch '%s'\n"
msgstr ""
-#: builtin/checkout.c:639
+#: builtin/checkout.c:640
#, c-format
msgid " ... and %d more.\n"
msgstr ""
#. The singular version
-#: builtin/checkout.c:645
+#: builtin/checkout.c:646
#, c-format
msgid ""
"Warning: you are leaving %d commit behind, not connected to\n"
@@ -1029,7 +1048,7 @@ msgid_plural ""
msgstr[0] ""
msgstr[1] ""
-#: builtin/checkout.c:663
+#: builtin/checkout.c:664
#, c-format
msgid ""
"If you want to keep them by creating a new branch, this may be a good time\n"
@@ -1039,96 +1058,96 @@ msgid ""
"\n"
msgstr ""
-#: builtin/checkout.c:692
+#: builtin/checkout.c:693
msgid "internal error in revision walk"
msgstr ""
-#: builtin/checkout.c:696
+#: builtin/checkout.c:697
msgid "Previous HEAD position was"
msgstr ""
-#: builtin/checkout.c:722
+#: builtin/checkout.c:723
msgid "You are on a branch yet to be born"
msgstr ""
#. case (1)
-#: builtin/checkout.c:853
+#: builtin/checkout.c:854
#, c-format
msgid "invalid reference: %s"
msgstr ""
#. case (1): want a tree
-#: builtin/checkout.c:892
+#: builtin/checkout.c:893
#, c-format
msgid "reference is not a tree: %s"
msgstr ""
-#: builtin/checkout.c:972
+#: builtin/checkout.c:973
msgid "-B cannot be used with -b"
msgstr ""
-#: builtin/checkout.c:981
+#: builtin/checkout.c:982
msgid "--patch is incompatible with all other options"
msgstr ""
-#: builtin/checkout.c:984
+#: builtin/checkout.c:985
msgid "--detach cannot be used with -b/-B/--orphan"
msgstr ""
-#: builtin/checkout.c:986
+#: builtin/checkout.c:987
msgid "--detach cannot be used with -t"
msgstr ""
-#: builtin/checkout.c:992
+#: builtin/checkout.c:993
msgid "--track needs a branch name"
msgstr ""
-#: builtin/checkout.c:999
+#: builtin/checkout.c:1000
msgid "Missing branch name; try -b"
msgstr ""
-#: builtin/checkout.c:1005
+#: builtin/checkout.c:1006
msgid "--orphan and -b|-B are mutually exclusive"
msgstr ""
-#: builtin/checkout.c:1007
+#: builtin/checkout.c:1008
msgid "--orphan cannot be used with -t"
msgstr ""
-#: builtin/checkout.c:1017
+#: builtin/checkout.c:1018
msgid "git checkout: -f and -m are incompatible"
msgstr ""
-#: builtin/checkout.c:1051
+#: builtin/checkout.c:1052
msgid "invalid path specification"
msgstr ""
-#: builtin/checkout.c:1059
+#: builtin/checkout.c:1060
#, c-format
msgid ""
"git checkout: updating paths is incompatible with switching branches.\n"
"Did you intend to checkout '%s' which can not be resolved as commit?"
msgstr ""
-#: builtin/checkout.c:1061
+#: builtin/checkout.c:1062
msgid "git checkout: updating paths is incompatible with switching branches."
msgstr ""
-#: builtin/checkout.c:1066
+#: builtin/checkout.c:1067
msgid "git checkout: --detach does not take a path argument"
msgstr ""
-#: builtin/checkout.c:1069
+#: builtin/checkout.c:1070
msgid ""
"git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
"checking out of the index."
msgstr ""
-#: builtin/checkout.c:1088
+#: builtin/checkout.c:1089
msgid "Cannot switch branch to a non-commit."
msgstr ""
-#: builtin/checkout.c:1091
+#: builtin/checkout.c:1092
msgid "--ours/--theirs is incompatible with switching branches."
msgstr ""
@@ -1365,66 +1384,66 @@ msgstr ""
msgid "unable to write temporary index file"
msgstr ""
-#: builtin/commit.c:550 builtin/commit.c:556
+#: builtin/commit.c:561 builtin/commit.c:567
#, c-format
msgid "invalid commit: %s"
msgstr ""
-#: builtin/commit.c:579
+#: builtin/commit.c:590
msgid "malformed --author parameter"
msgstr ""
-#: builtin/commit.c:635
+#: builtin/commit.c:651
#, c-format
msgid "Malformed ident string: '%s'"
msgstr ""
-#: builtin/commit.c:670 builtin/commit.c:703 builtin/commit.c:1000
+#: builtin/commit.c:689 builtin/commit.c:722 builtin/commit.c:1033
#, c-format
msgid "could not lookup commit %s"
msgstr ""
-#: builtin/commit.c:682 builtin/shortlog.c:296
+#: builtin/commit.c:701 builtin/shortlog.c:296
#, c-format
msgid "(reading log message from standard input)\n"
msgstr ""
-#: builtin/commit.c:684
+#: builtin/commit.c:703
msgid "could not read log from standard input"
msgstr ""
-#: builtin/commit.c:688
+#: builtin/commit.c:707
#, c-format
msgid "could not read log file '%s'"
msgstr ""
-#: builtin/commit.c:694
+#: builtin/commit.c:713
msgid "commit has empty message"
msgstr ""
-#: builtin/commit.c:710
+#: builtin/commit.c:729
msgid "could not read MERGE_MSG"
msgstr ""
-#: builtin/commit.c:714
+#: builtin/commit.c:733
msgid "could not read SQUASH_MSG"
msgstr ""
-#: builtin/commit.c:718
+#: builtin/commit.c:737
#, c-format
msgid "could not read '%s'"
msgstr ""
-#: builtin/commit.c:746
+#: builtin/commit.c:765
#, c-format
msgid "could not open '%s'"
msgstr ""
-#: builtin/commit.c:770
+#: builtin/commit.c:789
msgid "could not write commit template"
msgstr ""
-#: builtin/commit.c:783
+#: builtin/commit.c:799
#, c-format
msgid ""
"\n"
@@ -1434,167 +1453,172 @@ msgid ""
"and try again.\n"
msgstr ""
-#: builtin/commit.c:796
+#: builtin/commit.c:812
msgid "Please enter the commit message for your changes."
msgstr ""
-#: builtin/commit.c:799
+#: builtin/commit.c:815
msgid ""
" Lines starting\n"
"with '#' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
-#: builtin/commit.c:804
+#: builtin/commit.c:820
msgid ""
" Lines starting\n"
"with '#' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
-#: builtin/commit.c:816
+#: builtin/commit.c:832
#, c-format
msgid "%sAuthor: %s"
msgstr ""
-#: builtin/commit.c:823
+#: builtin/commit.c:839
#, c-format
msgid "%sCommitter: %s"
msgstr ""
-#: builtin/commit.c:843
+#: builtin/commit.c:859
msgid "Cannot read index"
msgstr ""
-#: builtin/commit.c:880
+#: builtin/commit.c:896
msgid "Error building trees"
msgstr ""
-#: builtin/commit.c:895 builtin/tag.c:357
+#: builtin/commit.c:911 builtin/tag.c:357
#, c-format
msgid "Please supply the message using either -m or -F option.\n"
msgstr ""
-#: builtin/commit.c:975
+#: builtin/commit.c:1008
#, c-format
msgid "No existing author found with '%s'"
msgstr ""
-#: builtin/commit.c:990 builtin/commit.c:1182
+#: builtin/commit.c:1023 builtin/commit.c:1217
#, c-format
msgid "Invalid untracked files mode '%s'"
msgstr ""
-#: builtin/commit.c:1030
+#: builtin/commit.c:1063
msgid "Using both --reset-author and --author does not make sense"
msgstr ""
-#: builtin/commit.c:1041
+#: builtin/commit.c:1074
msgid "You have nothing to amend."
msgstr ""
-#: builtin/commit.c:1043
+#: builtin/commit.c:1076
#, c-format
msgid "You are in the middle of a %s -- cannot amend."
msgstr ""
-#: builtin/commit.c:1045
+#: builtin/commit.c:1078
msgid "Options --squash and --fixup cannot be used together"
msgstr ""
-#: builtin/commit.c:1055
+#: builtin/commit.c:1088
msgid "Only one of -c/-C/-F/--fixup can be used."
msgstr ""
-#: builtin/commit.c:1057
+#: builtin/commit.c:1090
msgid "Option -m cannot be combined with -c/-C/-F/--fixup."
msgstr ""
-#: builtin/commit.c:1063
+#: builtin/commit.c:1098
msgid "--reset-author can be used only with -C, -c or --amend."
msgstr ""
-#: builtin/commit.c:1080
+#: builtin/commit.c:1115
msgid "Only one of --include/--only/--all/--interactive/--patch can be used."
msgstr ""
-#: builtin/commit.c:1082
+#: builtin/commit.c:1117
msgid "No paths with --include/--only does not make sense."
msgstr ""
-#: builtin/commit.c:1084
+#: builtin/commit.c:1119
msgid "Clever... amending the last one with dirty index."
msgstr ""
-#: builtin/commit.c:1086
+#: builtin/commit.c:1121
msgid "Explicit paths specified without -i nor -o; assuming --only paths..."
msgstr ""
-#: builtin/commit.c:1096 builtin/tag.c:556
+#: builtin/commit.c:1131 builtin/tag.c:556
#, c-format
msgid "Invalid cleanup mode %s"
msgstr ""
-#: builtin/commit.c:1101
+#: builtin/commit.c:1136
msgid "Paths with -a does not make sense."
msgstr ""
-#: builtin/commit.c:1280
+#: builtin/commit.c:1315
msgid "couldn't look up newly created commit"
msgstr ""
-#: builtin/commit.c:1282
+#: builtin/commit.c:1317
msgid "could not parse newly created commit"
msgstr ""
-#: builtin/commit.c:1323
+#: builtin/commit.c:1358
msgid "detached HEAD"
msgstr ""
-#: builtin/commit.c:1325
+#: builtin/commit.c:1360
msgid " (root-commit)"
msgstr ""
-#: builtin/commit.c:1415
+#: builtin/commit.c:1450
msgid "could not parse HEAD commit"
msgstr ""
-#: builtin/commit.c:1452 builtin/merge.c:509
+#: builtin/commit.c:1487 builtin/merge.c:509
#, c-format
msgid "could not open '%s' for reading"
msgstr ""
-#: builtin/commit.c:1459
+#: builtin/commit.c:1494
#, c-format
msgid "Corrupt MERGE_HEAD file (%s)"
msgstr ""
-#: builtin/commit.c:1466
+#: builtin/commit.c:1501
msgid "could not read MERGE_MODE"
msgstr ""
-#: builtin/commit.c:1485
+#: builtin/commit.c:1520
#, c-format
msgid "could not read commit message: %s"
msgstr ""
-#: builtin/commit.c:1499
+#: builtin/commit.c:1534
+#, c-format
+msgid "Aborting commit; you did not edit the message.\n"
+msgstr ""
+
+#: builtin/commit.c:1539
#, c-format
msgid "Aborting commit due to empty commit message.\n"
msgstr ""
-#: builtin/commit.c:1514 builtin/merge.c:935 builtin/merge.c:968
+#: builtin/commit.c:1554 builtin/merge.c:936 builtin/merge.c:961
msgid "failed to write commit object"
msgstr ""
-#: builtin/commit.c:1535
+#: builtin/commit.c:1575
msgid "cannot lock HEAD ref"
msgstr ""
-#: builtin/commit.c:1539
+#: builtin/commit.c:1579
msgid "cannot update HEAD ref"
msgstr ""
-#: builtin/commit.c:1550
+#: builtin/commit.c:1590
msgid ""
"Repository has been updated, but unable to write\n"
"new_index file. Check that disk is not full or quota is\n"
@@ -1717,146 +1741,150 @@ msgstr ""
msgid "Couldn't find remote ref HEAD"
msgstr ""
-#: builtin/fetch.c:252
+#: builtin/fetch.c:253
#, c-format
msgid "object %s not found"
msgstr ""
-#: builtin/fetch.c:258
+#: builtin/fetch.c:259
msgid "[up to date]"
msgstr ""
-#: builtin/fetch.c:272
+#: builtin/fetch.c:273
#, c-format
msgid "! %-*s %-*s -> %s (can't fetch in current branch)"
msgstr ""
-#: builtin/fetch.c:273 builtin/fetch.c:351
+#: builtin/fetch.c:274 builtin/fetch.c:360
msgid "[rejected]"
msgstr ""
-#: builtin/fetch.c:284
+#: builtin/fetch.c:285
msgid "[tag update]"
msgstr ""
-#: builtin/fetch.c:286 builtin/fetch.c:313 builtin/fetch.c:331
+#: builtin/fetch.c:287 builtin/fetch.c:322 builtin/fetch.c:340
msgid " (unable to update local ref)"
msgstr ""
-#: builtin/fetch.c:298
+#: builtin/fetch.c:305
msgid "[new tag]"
msgstr ""
-#: builtin/fetch.c:302
+#: builtin/fetch.c:308
msgid "[new branch]"
msgstr ""
-#: builtin/fetch.c:347
+#: builtin/fetch.c:311
+msgid "[new ref]"
+msgstr ""
+
+#: builtin/fetch.c:356
msgid "unable to update local ref"
msgstr ""
-#: builtin/fetch.c:347
+#: builtin/fetch.c:356
msgid "forced update"
msgstr ""
-#: builtin/fetch.c:353
+#: builtin/fetch.c:362
msgid "(non-fast-forward)"
msgstr ""
-#: builtin/fetch.c:384 builtin/fetch.c:676
+#: builtin/fetch.c:393 builtin/fetch.c:685
#, c-format
msgid "cannot open %s: %s\n"
msgstr ""
-#: builtin/fetch.c:393
+#: builtin/fetch.c:402
#, c-format
msgid "%s did not send all necessary objects\n"
msgstr ""
-#: builtin/fetch.c:479
+#: builtin/fetch.c:488
#, c-format
msgid "From %.*s\n"
msgstr ""
-#: builtin/fetch.c:490
+#: builtin/fetch.c:499
#, c-format
msgid ""
"some local refs could not be updated; try running\n"
" 'git remote prune %s' to remove any old, conflicting branches"
msgstr ""
-#: builtin/fetch.c:540
+#: builtin/fetch.c:549
#, c-format
msgid " (%s will become dangling)\n"
msgstr ""
-#: builtin/fetch.c:541
+#: builtin/fetch.c:550
#, c-format
msgid " (%s has become dangling)\n"
msgstr ""
-#: builtin/fetch.c:548
+#: builtin/fetch.c:557
msgid "[deleted]"
msgstr ""
-#: builtin/fetch.c:549
+#: builtin/fetch.c:558
msgid "(none)"
msgstr ""
-#: builtin/fetch.c:666
+#: builtin/fetch.c:675
#, c-format
msgid "Refusing to fetch into current branch %s of non-bare repository"
msgstr ""
-#: builtin/fetch.c:700
+#: builtin/fetch.c:709
#, c-format
msgid "Don't know how to fetch from %s"
msgstr ""
-#: builtin/fetch.c:777
+#: builtin/fetch.c:786
#, c-format
msgid "Option \"%s\" value \"%s\" is not valid for %s"
msgstr ""
-#: builtin/fetch.c:780
+#: builtin/fetch.c:789
#, c-format
msgid "Option \"%s\" is ignored for %s\n"
msgstr ""
-#: builtin/fetch.c:879
+#: builtin/fetch.c:888
#, c-format
msgid "Fetching %s\n"
msgstr ""
-#: builtin/fetch.c:881
+#: builtin/fetch.c:890
#, c-format
msgid "Could not fetch %s"
msgstr ""
-#: builtin/fetch.c:898
+#: builtin/fetch.c:907
msgid ""
"No remote repository specified. Please, specify either a URL or a\n"
"remote name from which new revisions should be fetched."
msgstr ""
-#: builtin/fetch.c:918
+#: builtin/fetch.c:927
msgid "You need to specify a tag name."
msgstr ""
-#: builtin/fetch.c:970
+#: builtin/fetch.c:979
msgid "fetch --all does not take a repository argument"
msgstr ""
-#: builtin/fetch.c:972
+#: builtin/fetch.c:981
msgid "fetch --all does not make sense with refspecs"
msgstr ""
-#: builtin/fetch.c:983
+#: builtin/fetch.c:992
#, c-format
msgid "No such remote or remote group: %s"
msgstr ""
-#: builtin/fetch.c:991
+#: builtin/fetch.c:1000
msgid "Fetching a group and specifying refspecs does not make sense"
msgstr ""
@@ -2092,163 +2120,163 @@ msgstr ""
msgid "Cannot access work tree '%s'"
msgstr ""
-#: builtin/log.c:187
+#: builtin/log.c:188
#, c-format
msgid "Final output: %d %s\n"
msgstr ""
-#: builtin/log.c:395 builtin/log.c:483
+#: builtin/log.c:401 builtin/log.c:489
#, c-format
msgid "Could not read object %s"
msgstr ""
-#: builtin/log.c:507
+#: builtin/log.c:513
#, c-format
msgid "Unknown type: %d"
msgstr ""
-#: builtin/log.c:596
+#: builtin/log.c:602
msgid "format.headers without value"
msgstr ""
-#: builtin/log.c:669
+#: builtin/log.c:675
msgid "name of output directory is too long"
msgstr ""
-#: builtin/log.c:680
+#: builtin/log.c:686
#, c-format
msgid "Cannot open patch file %s"
msgstr ""
-#: builtin/log.c:694
+#: builtin/log.c:700
msgid "Need exactly one range."
msgstr ""
-#: builtin/log.c:702
+#: builtin/log.c:708
msgid "Not a range."
msgstr ""
-#: builtin/log.c:739
+#: builtin/log.c:745
msgid "Could not extract email from committer identity."
msgstr ""
-#: builtin/log.c:785
+#: builtin/log.c:791
msgid "Cover letter needs email format"
msgstr ""
-#: builtin/log.c:879
+#: builtin/log.c:885
#, c-format
msgid "insane in-reply-to: %s"
msgstr ""
-#: builtin/log.c:952
+#: builtin/log.c:958
msgid "Two output directories?"
msgstr ""
-#: builtin/log.c:1173
+#: builtin/log.c:1179
#, c-format
msgid "bogus committer info %s"
msgstr ""
-#: builtin/log.c:1218
+#: builtin/log.c:1224
msgid "-n and -k are mutually exclusive."
msgstr ""
-#: builtin/log.c:1220
+#: builtin/log.c:1226
msgid "--subject-prefix and -k are mutually exclusive."
msgstr ""
-#: builtin/log.c:1225 builtin/shortlog.c:284
+#: builtin/log.c:1231 builtin/shortlog.c:284
#, c-format
msgid "unrecognized argument: %s"
msgstr ""
-#: builtin/log.c:1228
+#: builtin/log.c:1234
msgid "--name-only does not make sense"
msgstr ""
-#: builtin/log.c:1230
+#: builtin/log.c:1236
msgid "--name-status does not make sense"
msgstr ""
-#: builtin/log.c:1232
+#: builtin/log.c:1238
msgid "--check does not make sense"
msgstr ""
-#: builtin/log.c:1255
+#: builtin/log.c:1261
msgid "standard output, or directory, which one?"
msgstr ""
-#: builtin/log.c:1257
+#: builtin/log.c:1263
#, c-format
msgid "Could not create directory '%s'"
msgstr ""
-#: builtin/log.c:1410
+#: builtin/log.c:1416
msgid "Failed to create output files"
msgstr ""
-#: builtin/log.c:1514
+#: builtin/log.c:1520
#, c-format
msgid ""
"Could not find a tracked remote branch, please specify <upstream> manually.\n"
msgstr ""
-#: builtin/log.c:1530 builtin/log.c:1532 builtin/log.c:1544
+#: builtin/log.c:1536 builtin/log.c:1538 builtin/log.c:1550
#, c-format
msgid "Unknown commit %s"
msgstr ""
-#: builtin/merge.c:91
+#: builtin/merge.c:90
msgid "switch `m' requires a value"
msgstr ""
-#: builtin/merge.c:128
+#: builtin/merge.c:127
#, c-format
msgid "Could not find merge strategy '%s'.\n"
msgstr ""
-#: builtin/merge.c:129
+#: builtin/merge.c:128
#, c-format
msgid "Available strategies are:"
msgstr ""
-#: builtin/merge.c:134
+#: builtin/merge.c:133
#, c-format
msgid "Available custom strategies are:"
msgstr ""
-#: builtin/merge.c:241
+#: builtin/merge.c:240
msgid "could not run stash."
msgstr ""
-#: builtin/merge.c:246
+#: builtin/merge.c:245
msgid "stash failed"
msgstr ""
-#: builtin/merge.c:251
+#: builtin/merge.c:250
#, c-format
msgid "not a valid object: %s"
msgstr ""
-#: builtin/merge.c:270 builtin/merge.c:287
+#: builtin/merge.c:269 builtin/merge.c:286
msgid "read-tree failed"
msgstr ""
-#: builtin/merge.c:317
+#: builtin/merge.c:316
msgid " (nothing to squash)"
msgstr ""
-#: builtin/merge.c:330
+#: builtin/merge.c:329
#, c-format
msgid "Squash commit -- not updating HEAD\n"
msgstr ""
-#: builtin/merge.c:362
+#: builtin/merge.c:361
msgid "Writing SQUASH_MSG"
msgstr ""
-#: builtin/merge.c:364
+#: builtin/merge.c:363
msgid "Finishing SQUASH_MSG"
msgstr ""
@@ -2275,35 +2303,35 @@ msgstr ""
msgid "failed to read the cache"
msgstr ""
-#: builtin/merge.c:696
+#: builtin/merge.c:697
msgid "Unable to write index."
msgstr ""
-#: builtin/merge.c:709
+#: builtin/merge.c:710
msgid "Not handling anything other than two heads merge."
msgstr ""
-#: builtin/merge.c:723
+#: builtin/merge.c:724
#, c-format
msgid "Unknown option for merge-recursive: -X%s"
msgstr ""
-#: builtin/merge.c:737
+#: builtin/merge.c:738
#, c-format
msgid "unable to write %s"
msgstr ""
-#: builtin/merge.c:876
+#: builtin/merge.c:877
#, c-format
msgid "Could not read from '%s'"
msgstr ""
-#: builtin/merge.c:885
+#: builtin/merge.c:886
#, c-format
msgid "Not committing merge; use 'git commit' to complete the merge.\n"
msgstr ""
-#: builtin/merge.c:891
+#: builtin/merge.c:892
msgid ""
"Please enter a commit message to explain why this merge is necessary,\n"
"especially if it merges an updated upstream into a topic branch.\n"
@@ -2312,140 +2340,140 @@ msgid ""
"the commit.\n"
msgstr ""
-#: builtin/merge.c:915
+#: builtin/merge.c:916
msgid "Empty commit message."
msgstr ""
-#: builtin/merge.c:927
+#: builtin/merge.c:928
#, c-format
msgid "Wonderful.\n"
msgstr ""
-#: builtin/merge.c:1000
+#: builtin/merge.c:993
#, c-format
msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
msgstr ""
-#: builtin/merge.c:1016
+#: builtin/merge.c:1009
#, c-format
msgid "'%s' is not a commit"
msgstr ""
-#: builtin/merge.c:1057
+#: builtin/merge.c:1050
msgid "No current branch."
msgstr ""
-#: builtin/merge.c:1059
+#: builtin/merge.c:1052
msgid "No remote for the current branch."
msgstr ""
-#: builtin/merge.c:1061
+#: builtin/merge.c:1054
msgid "No default upstream defined for the current branch."
msgstr ""
-#: builtin/merge.c:1066
+#: builtin/merge.c:1059
#, c-format
msgid "No remote tracking branch for %s from %s"
msgstr ""
-#: builtin/merge.c:1188
+#: builtin/merge.c:1146 builtin/merge.c:1303
+#, c-format
+msgid "%s - not something we can merge"
+msgstr ""
+
+#: builtin/merge.c:1214
msgid "There is no merge to abort (MERGE_HEAD missing)."
msgstr ""
-#: builtin/merge.c:1204 git-pull.sh:31
+#: builtin/merge.c:1230 git-pull.sh:31
msgid ""
"You have not concluded your merge (MERGE_HEAD exists).\n"
"Please, commit your changes before you can merge."
msgstr ""
-#: builtin/merge.c:1207 git-pull.sh:34
+#: builtin/merge.c:1233 git-pull.sh:34
msgid "You have not concluded your merge (MERGE_HEAD exists)."
msgstr ""
-#: builtin/merge.c:1211
+#: builtin/merge.c:1237
msgid ""
"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
"Please, commit your changes before you can merge."
msgstr ""
-#: builtin/merge.c:1214
+#: builtin/merge.c:1240
msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
msgstr ""
-#: builtin/merge.c:1223
+#: builtin/merge.c:1249
msgid "You cannot combine --squash with --no-ff."
msgstr ""
-#: builtin/merge.c:1228
+#: builtin/merge.c:1254
msgid "You cannot combine --no-ff with --ff-only."
msgstr ""
-#: builtin/merge.c:1235
+#: builtin/merge.c:1261
msgid "No commit specified and merge.defaultToUpstream not set."
msgstr ""
-#: builtin/merge.c:1266
+#: builtin/merge.c:1293
msgid "Can merge only exactly one commit into empty head"
msgstr ""
-#: builtin/merge.c:1269
+#: builtin/merge.c:1296
msgid "Squash commit into empty head not supported yet"
msgstr ""
-#: builtin/merge.c:1271
+#: builtin/merge.c:1298
msgid "Non-fast-forward commit does not make sense into an empty head"
msgstr ""
-#: builtin/merge.c:1275 builtin/merge.c:1319
-#, c-format
-msgid "%s - not something we can merge"
-msgstr ""
-
-#: builtin/merge.c:1385
+#: builtin/merge.c:1413
#, c-format
msgid "Updating %s..%s\n"
msgstr ""
-#: builtin/merge.c:1423
+#: builtin/merge.c:1451
#, c-format
msgid "Trying really trivial in-index merge...\n"
msgstr ""
-#: builtin/merge.c:1430
+#: builtin/merge.c:1458
#, c-format
msgid "Nope.\n"
msgstr ""
-#: builtin/merge.c:1462
+#: builtin/merge.c:1490
msgid "Not possible to fast-forward, aborting."
msgstr ""
-#: builtin/merge.c:1485 builtin/merge.c:1562
+#: builtin/merge.c:1513 builtin/merge.c:1592
#, c-format
msgid "Rewinding the tree to pristine...\n"
msgstr ""
-#: builtin/merge.c:1489
+#: builtin/merge.c:1517
#, c-format
msgid "Trying merge strategy %s...\n"
msgstr ""
-#: builtin/merge.c:1553
+#: builtin/merge.c:1583
#, c-format
msgid "No merge strategy handled the merge.\n"
msgstr ""
-#: builtin/merge.c:1555
+#: builtin/merge.c:1585
#, c-format
msgid "Merge with strategy %s failed.\n"
msgstr ""
-#: builtin/merge.c:1564
+#: builtin/merge.c:1594
#, c-format
msgid "Using the %s to prepare resolving by hand.\n"
msgstr ""
-#: builtin/merge.c:1575
+#: builtin/merge.c:1606
#, c-format
msgid "Automatic merge went well; stopped before committing as requested\n"
msgstr ""
@@ -2684,15 +2712,15 @@ msgstr ""
msgid "unable to parse value '%s' for option %s"
msgstr ""
-#: builtin/push.c:44
+#: builtin/push.c:45
msgid "tag shorthand without <tag>"
msgstr ""
-#: builtin/push.c:63
+#: builtin/push.c:64
msgid "--delete only accepts plain target ref names"
msgstr ""
-#: builtin/push.c:73
+#: builtin/push.c:84
#, c-format
msgid ""
"You are not currently on a branch.\n"
@@ -2702,7 +2730,7 @@ msgid ""
" git push %s HEAD:<name-of-remote-branch>\n"
msgstr ""
-#: builtin/push.c:80
+#: builtin/push.c:91
#, c-format
msgid ""
"The current branch %s has no upstream branch.\n"
@@ -2711,40 +2739,64 @@ msgid ""
" git push --set-upstream %s %s\n"
msgstr ""
-#: builtin/push.c:88
+#: builtin/push.c:99
#, c-format
msgid "The current branch %s has multiple upstream branches, refusing to push."
msgstr ""
-#: builtin/push.c:111
+#: builtin/push.c:102
+#, c-format
msgid ""
-"You didn't specify any refspecs to push, and push.default is \"nothing\"."
+"You are pushing to remote '%s', which is not the upstream of\n"
+"your current branch '%s', without telling me what to push\n"
+"to update which remote branch."
msgstr ""
#: builtin/push.c:131
-#, c-format
-msgid "Pushing to %s\n"
+msgid ""
+"You didn't specify any refspecs to push, and push.default is \"nothing\"."
+msgstr ""
+
+#: builtin/push.c:138
+msgid ""
+"Updates were rejected because the tip of your current branch is behind\n"
+"its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
+"before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
+msgstr ""
+
+#: builtin/push.c:144
+msgid ""
+"Updates were rejected because a pushed branch tip is behind its remote\n"
+"counterpart. If you did not intend to push that branch, you may want to\n"
+"specify branches to push or set the 'push.default' configuration\n"
+"variable to 'current' or 'upstream' to push only the current branch."
msgstr ""
-#: builtin/push.c:135
+#: builtin/push.c:150
+msgid ""
+"Updates were rejected because a pushed branch tip is behind its remote\n"
+"counterpart. Check out this branch and merge the remote changes\n"
+"(e.g. 'git pull') before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
+msgstr ""
+
+#: builtin/push.c:190
#, c-format
-msgid "failed to push some refs to '%s'"
+msgid "Pushing to %s\n"
msgstr ""
-#: builtin/push.c:143
+#: builtin/push.c:194
#, c-format
-msgid ""
-"To prevent you from losing history, non-fast-forward updates were rejected\n"
-"Merge the remote changes (e.g. 'git pull') before pushing again. See the\n"
-"'Note about fast-forwards' section of 'git push --help' for details.\n"
+msgid "failed to push some refs to '%s'"
msgstr ""
-#: builtin/push.c:160
+#: builtin/push.c:226
#, c-format
msgid "bad repository '%s'"
msgstr ""
-#: builtin/push.c:161
+#: builtin/push.c:227
msgid ""
"No configured push destination.\n"
"Either specify the URL from the command-line or configure a remote "
@@ -2757,31 +2809,31 @@ msgid ""
" git push <name>\n"
msgstr ""
-#: builtin/push.c:176
+#: builtin/push.c:242
msgid "--all and --tags are incompatible"
msgstr ""
-#: builtin/push.c:177
+#: builtin/push.c:243
msgid "--all can't be combined with refspecs"
msgstr ""
-#: builtin/push.c:182
+#: builtin/push.c:248
msgid "--mirror and --tags are incompatible"
msgstr ""
-#: builtin/push.c:183
+#: builtin/push.c:249
msgid "--mirror can't be combined with refspecs"
msgstr ""
-#: builtin/push.c:188
+#: builtin/push.c:254
msgid "--all and --mirror are incompatible"
msgstr ""
-#: builtin/push.c:274
+#: builtin/push.c:342
msgid "--delete is incompatible with --all, --mirror and --tags"
msgstr ""
-#: builtin/push.c:276
+#: builtin/push.c:344
msgid "--delete doesn't make sense without any refs"
msgstr ""
@@ -2864,20 +2916,20 @@ msgstr ""
msgid "Could not reset index file to revision '%s'."
msgstr ""
-#: builtin/revert.c:70 builtin/revert.c:91
+#: builtin/revert.c:70 builtin/revert.c:92
#, c-format
msgid "%s: %s cannot be used with %s"
msgstr ""
-#: builtin/revert.c:126
+#: builtin/revert.c:127
msgid "program error"
msgstr ""
-#: builtin/revert.c:209
+#: builtin/revert.c:213
msgid "revert failed"
msgstr ""
-#: builtin/revert.c:224
+#: builtin/revert.c:228
msgid "cherry-pick failed"
msgstr ""
@@ -3040,80 +3092,80 @@ msgstr ""
msgid "Updated tag '%s' (was %s)\n"
msgstr ""
-#: git-am.sh:49
+#: git-am.sh:50
msgid "You need to set your committer info first"
msgstr ""
-#: git-am.sh:136
+#: git-am.sh:137
msgid "Repository lacks necessary blobs to fall back on 3-way merge."
msgstr ""
-#: git-am.sh:147
+#: git-am.sh:154
msgid ""
"Did you hand edit your patch?\n"
"It does not apply to blobs recorded in its index."
msgstr ""
-#: git-am.sh:156
+#: git-am.sh:163
msgid "Falling back to patching base and 3-way merge..."
msgstr ""
-#: git-am.sh:268
+#: git-am.sh:275
msgid "Only one StGIT patch series can be applied at once"
msgstr ""
-#: git-am.sh:355
+#: git-am.sh:362
#, sh-format
msgid "Patch format $patch_format is not supported."
msgstr ""
-#: git-am.sh:357
+#: git-am.sh:364
msgid "Patch format detection failed."
msgstr ""
-#: git-am.sh:411
+#: git-am.sh:418
msgid "-d option is no longer supported. Do not use."
msgstr ""
-#: git-am.sh:474
+#: git-am.sh:481
#, sh-format
msgid "previous rebase directory $dotest still exists but mbox given."
msgstr ""
-#: git-am.sh:479
+#: git-am.sh:486
msgid "Please make up your mind. --skip or --abort?"
msgstr ""
-#: git-am.sh:506
+#: git-am.sh:513
msgid "Resolve operation not in progress, we are not resuming."
msgstr ""
-#: git-am.sh:572
+#: git-am.sh:579
#, sh-format
msgid "Dirty index: cannot apply patches (dirty: $files)"
msgstr ""
-#: git-am.sh:748
+#: git-am.sh:755
msgid "cannot be interactive without stdin connected to a terminal."
msgstr ""
#. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
#. in your translation. The program will only accept English
#. input at this point.
-#: git-am.sh:759
+#: git-am.sh:766
msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
msgstr ""
-#: git-am.sh:795
+#: git-am.sh:802
#, sh-format
msgid "Applying: $FIRSTLINE"
msgstr ""
-#: git-am.sh:840
+#: git-am.sh:847
msgid "No changes -- Patch already applied."
msgstr ""
-#: git-am.sh:866
+#: git-am.sh:873
msgid "applying to an empty history"
msgstr ""
@@ -3345,161 +3397,161 @@ msgstr ""
msgid "cannot strip one component off url '$remoteurl'"
msgstr ""
-#: git-submodule.sh:108
+#: git-submodule.sh:109
#, sh-format
-msgid "No submodule mapping found in .gitmodules for path '$path'"
+msgid "No submodule mapping found in .gitmodules for path '$sm_path'"
msgstr ""
-#: git-submodule.sh:149
+#: git-submodule.sh:150
#, sh-format
-msgid "Clone of '$url' into submodule path '$path' failed"
+msgid "Clone of '$url' into submodule path '$sm_path' failed"
msgstr ""
-#: git-submodule.sh:159
+#: git-submodule.sh:160
#, sh-format
msgid "Gitdir '$a' is part of the submodule path '$b' or vice versa"
msgstr ""
-#: git-submodule.sh:247
+#: git-submodule.sh:249
#, sh-format
msgid "repo URL: '$repo' must be absolute or begin with ./|../"
msgstr ""
-#: git-submodule.sh:264
+#: git-submodule.sh:266
#, sh-format
-msgid "'$path' already exists in the index"
+msgid "'$sm_path' already exists in the index"
msgstr ""
-#: git-submodule.sh:281
+#: git-submodule.sh:283
#, sh-format
-msgid "'$path' already exists and is not a valid git repo"
+msgid "'$sm_path' already exists and is not a valid git repo"
msgstr ""
-#: git-submodule.sh:295
+#: git-submodule.sh:297
#, sh-format
-msgid "Unable to checkout submodule '$path'"
+msgid "Unable to checkout submodule '$sm_path'"
msgstr ""
-#: git-submodule.sh:300
+#: git-submodule.sh:302
#, sh-format
-msgid "Failed to add submodule '$path'"
+msgid "Failed to add submodule '$sm_path'"
msgstr ""
-#: git-submodule.sh:305
+#: git-submodule.sh:307
#, sh-format
-msgid "Failed to register submodule '$path'"
+msgid "Failed to register submodule '$sm_path'"
msgstr ""
-#: git-submodule.sh:347
+#: git-submodule.sh:349
#, sh-format
-msgid "Entering '$prefix$path'"
+msgid "Entering '$prefix$sm_path'"
msgstr ""
-#: git-submodule.sh:359
+#: git-submodule.sh:363
#, sh-format
-msgid "Stopping at '$path'; script returned non-zero status."
+msgid "Stopping at '$sm_path'; script returned non-zero status."
msgstr ""
-#: git-submodule.sh:401
+#: git-submodule.sh:405
#, sh-format
-msgid "No url found for submodule path '$path' in .gitmodules"
+msgid "No url found for submodule path '$sm_path' in .gitmodules"
msgstr ""
-#: git-submodule.sh:410
+#: git-submodule.sh:414
#, sh-format
-msgid "Failed to register url for submodule path '$path'"
+msgid "Failed to register url for submodule path '$sm_path'"
msgstr ""
-#: git-submodule.sh:418
+#: git-submodule.sh:422
#, sh-format
-msgid "Failed to register update mode for submodule path '$path'"
+msgid "Failed to register update mode for submodule path '$sm_path'"
msgstr ""
-#: git-submodule.sh:420
+#: git-submodule.sh:424
#, sh-format
-msgid "Submodule '$name' ($url) registered for path '$path'"
+msgid "Submodule '$name' ($url) registered for path '$sm_path'"
msgstr ""
-#: git-submodule.sh:519
+#: git-submodule.sh:523
#, sh-format
msgid ""
-"Submodule path '$path' not initialized\n"
+"Submodule path '$sm_path' not initialized\n"
"Maybe you want to use 'update --init'?"
msgstr ""
-#: git-submodule.sh:532
+#: git-submodule.sh:536
#, sh-format
-msgid "Unable to find current revision in submodule path '$path'"
+msgid "Unable to find current revision in submodule path '$sm_path'"
msgstr ""
-#: git-submodule.sh:551
+#: git-submodule.sh:555
#, sh-format
-msgid "Unable to fetch in submodule path '$path'"
+msgid "Unable to fetch in submodule path '$sm_path'"
msgstr ""
-#: git-submodule.sh:565
+#: git-submodule.sh:569
#, sh-format
-msgid "Unable to rebase '$sha1' in submodule path '$path'"
+msgid "Unable to rebase '$sha1' in submodule path '$sm_path'"
msgstr ""
-#: git-submodule.sh:566
+#: git-submodule.sh:570
#, sh-format
-msgid "Submodule path '$path': rebased into '$sha1'"
+msgid "Submodule path '$sm_path': rebased into '$sha1'"
msgstr ""
-#: git-submodule.sh:571
+#: git-submodule.sh:575
#, sh-format
-msgid "Unable to merge '$sha1' in submodule path '$path'"
+msgid "Unable to merge '$sha1' in submodule path '$sm_path'"
msgstr ""
-#: git-submodule.sh:572
+#: git-submodule.sh:576
#, sh-format
-msgid "Submodule path '$path': merged in '$sha1'"
+msgid "Submodule path '$sm_path': merged in '$sha1'"
msgstr ""
-#: git-submodule.sh:577
+#: git-submodule.sh:581
#, sh-format
-msgid "Unable to checkout '$sha1' in submodule path '$path'"
+msgid "Unable to checkout '$sha1' in submodule path '$sm_path'"
msgstr ""
-#: git-submodule.sh:578
+#: git-submodule.sh:582
#, sh-format
-msgid "Submodule path '$path': checked out '$sha1'"
+msgid "Submodule path '$sm_path': checked out '$sha1'"
msgstr ""
-#: git-submodule.sh:600 git-submodule.sh:923
+#: git-submodule.sh:604 git-submodule.sh:927
#, sh-format
-msgid "Failed to recurse into submodule path '$path'"
+msgid "Failed to recurse into submodule path '$sm_path'"
msgstr ""
-#: git-submodule.sh:708
+#: git-submodule.sh:712
msgid "--"
msgstr ""
-#: git-submodule.sh:766
+#: git-submodule.sh:770
#, sh-format
msgid " Warn: $name doesn't contain commit $sha1_src"
msgstr ""
-#: git-submodule.sh:769
+#: git-submodule.sh:773
#, sh-format
msgid " Warn: $name doesn't contain commit $sha1_dst"
msgstr ""
-#: git-submodule.sh:772
+#: git-submodule.sh:776
#, sh-format
msgid " Warn: $name doesn't contain commits $sha1_src and $sha1_dst"
msgstr ""
-#: git-submodule.sh:797
+#: git-submodule.sh:801
msgid "blob"
msgstr ""
-#: git-submodule.sh:798
+#: git-submodule.sh:802
msgid "submodule"
msgstr ""
-#: git-submodule.sh:969
+#: git-submodule.sh:973
#, sh-format
msgid "Synchronizing submodule url for '$name'"
msgstr ""
diff --git a/po/pt_PT.po b/po/pt_PT.po
index a0e9b0cf40..d28c568c73 100644
--- a/po/pt_PT.po
+++ b/po/pt_PT.po
@@ -9,7 +9,7 @@ msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
"POT-Creation-Date: 2012-03-16 20:18+0800\n"
-"PO-Revision-Date: 2012-04-01 11:26+0100\n"
+"PO-Revision-Date: 2012-04-05 20:48+0100\n"
"Last-Translator: Marco Sousa <marcomsousa AT gmail.com>\n"
"Language-Team: Portuguese\n"
"Language: pt\n"
@@ -48,11 +48,11 @@ msgstr "%s %s não é um commit!"
#: compat/obstack.c:406
#: compat/obstack.c:408
msgid "memory exhausted"
-msgstr "memoria exausta"
+msgstr "memória esgotada"
#: connected.c:39
msgid "Could not run 'git rev-list'"
-msgstr ""
+msgstr "Não foi possível executar 'git rev-list'"
#: connected.c:48
#, c-format
@@ -151,8 +151,8 @@ msgstr ""
#, c-format
msgid "Your branch is ahead of '%s' by %d commit.\n"
msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "A sua rama está à frente de '%s' pelo commit %d.\n"
+msgstr[1] "A sua rama está à frente de '%s' pelos commites %d.\n"
#: remote.c:1613
#, c-format
@@ -188,7 +188,7 @@ msgstr ""
#: builtin/merge.c:1110
#, c-format
msgid "Could not write to '%s'"
-msgstr ""
+msgstr "Não foi possível escrever para '%s'"
#: sequencer.c:143
msgid ""
@@ -208,7 +208,7 @@ msgstr ""
#: sequencer.c:768
#, c-format
msgid "Could not write to %s"
-msgstr ""
+msgstr "Não foi possível gravar para %s"
#: sequencer.c:162
#, c-format
@@ -235,11 +235,11 @@ msgstr ""
#: sequencer.c:298
msgid "Your index file is unmerged."
-msgstr ""
+msgstr "O seu ficheiro de índice é não fundido."
#: sequencer.c:301
msgid "You do not have a valid HEAD"
-msgstr ""
+msgstr "Você não tem uma HEAD válida"
#: sequencer.c:316
#, c-format
@@ -266,7 +266,7 @@ msgstr ""
#: sequencer.c:343
#, c-format
msgid "Cannot get commit message for %s"
-msgstr ""
+msgstr "Não é possível obter mensagem commit para %s"
#: sequencer.c:427
#, c-format
@@ -291,7 +291,7 @@ msgstr ""
#: sequencer.c:453
msgid "empty commit set passed"
-msgstr ""
+msgstr "passado commit com o set vazio"
#: sequencer.c:461
#, c-format
@@ -306,12 +306,12 @@ msgstr ""
#: sequencer.c:551
#, c-format
msgid "Cannot %s during a %s"
-msgstr ""
+msgstr "Não foi possível abrir %s durante um %s"
#: sequencer.c:573
#, c-format
msgid "Could not parse line %d."
-msgstr ""
+msgstr "Não foi possível parsear linha %d."
#: sequencer.c:578
msgid "No commits parsed."
@@ -320,12 +320,12 @@ msgstr "Nenhum commit parseado."
#: sequencer.c:591
#, c-format
msgid "Could not open %s"
-msgstr ""
+msgstr "Não foi possível abrir %s"
#: sequencer.c:595
#, c-format
msgid "Could not read %s."
-msgstr ""
+msgstr "Não foi possível ler %s."
#: sequencer.c:602
#, c-format
@@ -382,12 +382,12 @@ msgstr ""
#: sequencer.c:732
#, c-format
msgid "cannot open %s: %s"
-msgstr ""
+msgstr "não foi possível abrir %s: %s"
#: sequencer.c:735
#, c-format
msgid "cannot read %s: %s"
-msgstr ""
+msgstr "não foi possível ler %s: %s"
#: sequencer.c:736
msgid "unexpected end of file"
@@ -401,7 +401,7 @@ msgstr ""
#: sequencer.c:765
#, c-format
msgid "Could not format %s."
-msgstr ""
+msgstr "Não foi possível formatear %s."
#: sequencer.c:927
msgid "Can't revert as initial commit"
@@ -413,7 +413,7 @@ msgstr ""
#: wt-status.c:134
msgid "Unmerged paths:"
-msgstr ""
+msgstr "caminhos não fundidos:"
#: wt-status.c:140
#: wt-status.c:157
@@ -470,31 +470,31 @@ msgstr "erro"
#: wt-status.c:212
msgid "both deleted:"
-msgstr ""
+msgstr "eliminados em ambos:"
#: wt-status.c:213
msgid "added by us:"
-msgstr ""
+msgstr "adicionado por nós:"
#: wt-status.c:214
msgid "deleted by them:"
-msgstr ""
+msgstr "eliminados por eles:"
#: wt-status.c:215
msgid "added by them:"
-msgstr ""
+msgstr "adicionados por eles:"
#: wt-status.c:216
msgid "deleted by us:"
-msgstr ""
+msgstr "eliminados por nós:"
#: wt-status.c:217
msgid "both added:"
-msgstr ""
+msgstr "adicionados em ambos:"
#: wt-status.c:218
msgid "both modified:"
-msgstr ""
+msgstr "modificados em ambos:"
#: wt-status.c:248
msgid "new commits, "
@@ -502,11 +502,11 @@ msgstr "novos commits, "
#: wt-status.c:250
msgid "modified content, "
-msgstr ""
+msgstr "conteúdo modificado, "
#: wt-status.c:252
msgid "untracked content, "
-msgstr ""
+msgstr "conteúdo não seguido"
#: wt-status.c:266
#, c-format
@@ -546,7 +546,7 @@ msgstr "desconhecido: %s"
#: wt-status.c:287
#, c-format
msgid "unmerged: %s"
-msgstr ""
+msgstr "não fundidos: %s"
#: wt-status.c:290
#, c-format
@@ -559,7 +559,7 @@ msgstr "Na rama"
#: wt-status.c:720
msgid "Not currently on any branch."
-msgstr ""
+msgstr "Não está em nenhuma rama."
#: wt-status.c:731
msgid "Initial commit"
@@ -567,7 +567,7 @@ msgstr "Commit inicial"
#: wt-status.c:745
msgid "Untracked"
-msgstr ""
+msgstr "Não seguido"
#: wt-status.c:747
msgid "Ignored"
@@ -589,7 +589,7 @@ msgstr "Sem mudanças"
#: wt-status.c:761
#, c-format
msgid "no changes added to commit%s\n"
-msgstr ""
+msgstr "nenhuma alteração adicionado ao commit%s\n"
#: wt-status.c:763
msgid " (use \"git add\" and/or \"git commit -a\")"
@@ -652,7 +652,7 @@ msgstr ""
#: builtin/add.c:67
#: builtin/commit.c:298
msgid "updating files failed"
-msgstr ""
+msgstr "Falou a atualização dos ficheiros"
#: builtin/add.c:77
#, c-format
@@ -682,16 +682,16 @@ msgstr ""
#: builtin/add.c:276
msgid "Could not read the index"
-msgstr ""
+msgstr "Não foi possível ler o indíce"
#: builtin/add.c:286
#, c-format
msgid "Could not open '%s' for writing."
-msgstr ""
+msgstr "Não foi possível abrir '%s' para escrever."
#: builtin/add.c:290
msgid "Could not write patch"
-msgstr ""
+msgstr "Não consegue escrever patch"
#: builtin/add.c:295
#, c-format
@@ -700,12 +700,12 @@ msgstr ""
#: builtin/add.c:297
msgid "Empty patch. Aborted."
-msgstr ""
+msgstr "Patch vazio. Aborted."
#: builtin/add.c:303
#, c-format
msgid "Could not apply '%s'"
-msgstr ""
+msgstr "Não foi possível aplicar o '%s'"
#: builtin/add.c:312
msgid "The following paths are ignored by one of your .gitignore files:\n"
@@ -722,7 +722,7 @@ msgstr "nenhum ficheiros adicionado"
#: builtin/add.c:359
msgid "adding files failed"
-msgstr ""
+msgstr "falhou a adicionar ficheiros"
#: builtin/add.c:391
msgid "-A and -u are mutually incompatible"
@@ -748,7 +748,7 @@ msgstr ""
#: builtin/mv.c:82
#: builtin/rm.c:162
msgid "index file corrupt"
-msgstr ""
+msgstr "ficheiro index corrupto"
#: builtin/add.c:476
#: builtin/mv.c:229
@@ -781,7 +781,7 @@ msgstr ""
#: builtin/archive.c:65
#, c-format
msgid "remote error: %s"
-msgstr ""
+msgstr "erro remoto: %s"
#: builtin/archive.c:66
msgid "git archive: protocol error"
@@ -812,7 +812,7 @@ msgstr "remota"
#: builtin/branch.c:171
msgid "cannot use -a with -d"
-msgstr ""
+msgstr "Não é possível usar -a com um -d"
#: builtin/branch.c:177
msgid "Couldn't look up commit object for HEAD"
@@ -826,7 +826,7 @@ msgstr ""
#: builtin/branch.c:192
#, c-format
msgid "%sbranch '%s' not found."
-msgstr ""
+msgstr "%sbranch '%s' não encontrado."
#: builtin/branch.c:200
#, c-format
@@ -862,17 +862,17 @@ msgstr ""
#: builtin/branch.c:394
#, c-format
msgid "behind %d] "
-msgstr ""
+msgstr "atrás %d] "
#: builtin/branch.c:396
#, c-format
msgid "ahead %d] "
-msgstr ""
+msgstr "a frente %d] "
#: builtin/branch.c:398
#, c-format
msgid "ahead %d, behind %d] "
-msgstr ""
+msgstr "a frente %d, atrás %d] "
#: builtin/branch.c:501
msgid "(no branch)"
@@ -889,16 +889,16 @@ msgstr ""
#: builtin/branch.c:589
#, c-format
msgid "Invalid branch name: '%s'"
-msgstr ""
+msgstr "Nome da rama inválida: '%s'"
#: builtin/branch.c:604
msgid "Branch rename failed"
-msgstr ""
+msgstr "Falhou renomeação da rama"
#: builtin/branch.c:608
#, c-format
msgid "Renamed a misnamed branch '%s' away"
-msgstr ""
+msgstr "Renomeado uma rama erronea '%s'"
#: builtin/branch.c:612
#, c-format
@@ -986,7 +986,7 @@ msgstr ""
#: builtin/checkout.c:234
#: builtin/checkout.c:392
msgid "corrupt index file"
-msgstr ""
+msgstr "ficheiro index corrupto"
#: builtin/checkout.c:264
#: builtin/checkout.c:271
@@ -1038,17 +1038,17 @@ msgstr ""
#: builtin/checkout.c:581
#, c-format
msgid "Switched to a new branch '%s'\n"
-msgstr ""
+msgstr "Mudado para a nova rama '%s'\n"
#: builtin/checkout.c:583
#, c-format
msgid "Switched to branch '%s'\n"
-msgstr ""
+msgstr "Mudado para a rama '%s'\n"
#: builtin/checkout.c:639
#, c-format
msgid " ... and %d more.\n"
-msgstr ""
+msgstr " ... e %d mais.\n"
#. The singular version
#: builtin/checkout.c:645
@@ -1191,7 +1191,7 @@ msgstr ""
#: builtin/clean.c:179
#, c-format
msgid "Removing %s\n"
-msgstr ""
+msgstr "Eliminando %s\n"
#: builtin/clean.c:162
#: builtin/clean.c:182
@@ -1271,7 +1271,7 @@ msgstr ""
#: builtin/clone.c:639
msgid "Too many arguments."
-msgstr ""
+msgstr "Demasiados parametros."
#: builtin/clone.c:643
msgid "You must specify a repository to clone."
@@ -1315,17 +1315,17 @@ msgstr ""
#: builtin/clone.c:728
#, c-format
msgid "Cloning into bare repository '%s'...\n"
-msgstr ""
+msgstr "Clonando em um repositorio nu (bare) '%s'...\n"
#: builtin/clone.c:730
#, c-format
msgid "Cloning into '%s'...\n"
-msgstr ""
+msgstr "Clonar em '%s'...\n"
#: builtin/clone.c:786
#, c-format
msgid "Don't know how to clone %s"
-msgstr ""
+msgstr "Não sei como clonar %s"
#: builtin/clone.c:835
#, c-format
@@ -1349,6 +1349,16 @@ msgid ""
"\n"
" git commit --amend --reset-author\n"
msgstr ""
+"O seu nome e endereço de e-mail foram configurados automaticamente com base\n"
+"no o seu usuario e nome da maquina. Por favor, verifique se eles são precisos.\n"
+"Você pode suprimir esta mensagem, configurando-los explicitamente:\n"
+"\n"
+" git config --global user.name \"O teu Nome\"\n"
+" git config --global user.email tu@examplo.com\n"
+"\n"
+"Após fazer isso, você pode corregir a identidade usada em este commit com:\n"
+"\n"
+" git commit --amend --reset-author\n"
#: builtin/commit.c:54
msgid ""
@@ -1386,7 +1396,7 @@ msgstr ""
#: builtin/commit.c:373
msgid "interactive add failed"
-msgstr ""
+msgstr "falhou adicionar interativo"
#: builtin/commit.c:406
#: builtin/commit.c:427
@@ -1401,7 +1411,7 @@ msgstr ""
#: builtin/commit.c:466
msgid "cannot read the index"
-msgstr ""
+msgstr "não foi possível ler o indíce"
#: builtin/commit.c:486
msgid "unable to write temporary index file"
@@ -1442,29 +1452,29 @@ msgstr ""
#: builtin/commit.c:688
#, c-format
msgid "could not read log file '%s'"
-msgstr ""
+msgstr "não é possivel ler o ficheiro de log '%s'"
#: builtin/commit.c:694
msgid "commit has empty message"
-msgstr ""
+msgstr "a mensagem do commit está vazia"
#: builtin/commit.c:710
msgid "could not read MERGE_MSG"
-msgstr ""
+msgstr "não é possivel ler MERGE_MSG"
#: builtin/commit.c:714
msgid "could not read SQUASH_MSG"
-msgstr ""
+msgstr "não é possivel ler SQUASH_MSG"
#: builtin/commit.c:718
#, c-format
msgid "could not read '%s'"
-msgstr ""
+msgstr "não é possivel ler '%s'"
#: builtin/commit.c:746
#, c-format
msgid "could not open '%s'"
-msgstr ""
+msgstr "não é possivel abrir '%s'"
#: builtin/commit.c:770
msgid "could not write commit template"
@@ -1482,7 +1492,7 @@ msgstr ""
#: builtin/commit.c:796
msgid "Please enter the commit message for your changes."
-msgstr ""
+msgstr "Por favor insira a mensagem de commit das suas alterações."
#: builtin/commit.c:799
msgid ""
@@ -1538,7 +1548,7 @@ msgstr ""
#: builtin/commit.c:1041
msgid "You have nothing to amend."
-msgstr ""
+msgstr "Você não tem nada a corregir."
#: builtin/commit.c:1043
#, c-format
@@ -1725,7 +1735,7 @@ msgstr ""
#: builtin/describe.c:462
msgid "No names found, cannot describe anything."
-msgstr ""
+msgstr "Nenhum nome encontrado, não descreve nada."
#: builtin/describe.c:482
msgid "--dirty is incompatible with committishes"
@@ -1882,7 +1892,7 @@ msgstr ""
#: builtin/fetch.c:879
#, c-format
msgid "Fetching %s\n"
-msgstr ""
+msgstr "Baixando %s\n"
#: builtin/fetch.c:881
#, c-format
@@ -1894,10 +1904,12 @@ msgid ""
"No remote repository specified. Please, specify either a URL or a\n"
"remote name from which new revisions should be fetched."
msgstr ""
+"Nenhum repositório remoto especificado. Por favor, especifique um URL ou o\n"
+"nome remoto a partir do qual novas revisões devem ser obtida."
#: builtin/fetch.c:918
msgid "You need to specify a tag name."
-msgstr ""
+msgstr "Você precisa especificar um nome da etiqueta."
#: builtin/fetch.c:970
msgid "fetch --all does not take a repository argument"
@@ -1919,11 +1931,11 @@ msgstr ""
#: builtin/gc.c:63
#, c-format
msgid "Invalid %s: '%s'"
-msgstr ""
+msgstr "Inválido %s: '%s'"
#: builtin/gc.c:78
msgid "Too many options specified"
-msgstr ""
+msgstr "Demasiadas opções especificadas"
#: builtin/gc.c:103
#, c-format
@@ -2162,7 +2174,7 @@ msgstr ""
#: builtin/log.c:507
#, c-format
msgid "Unknown type: %d"
-msgstr ""
+msgstr "Tipo desconhecido: %d"
#: builtin/log.c:596
msgid "format.headers without value"
@@ -2170,28 +2182,28 @@ msgstr ""
#: builtin/log.c:669
msgid "name of output directory is too long"
-msgstr ""
+msgstr "nome do diretório de saída é demasiado longo"
#: builtin/log.c:680
#, c-format
msgid "Cannot open patch file %s"
-msgstr ""
+msgstr "Não é possivel abrir o ficheiro patch %s"
#: builtin/log.c:694
msgid "Need exactly one range."
-msgstr ""
+msgstr "Necessita de exatamente um intervalo."
#: builtin/log.c:702
msgid "Not a range."
-msgstr ""
+msgstr "Não é um intervalo."
#: builtin/log.c:739
msgid "Could not extract email from committer identity."
-msgstr ""
+msgstr "Não foi possível extrair a identidade do committer do e-mail."
#: builtin/log.c:785
msgid "Cover letter needs email format"
-msgstr ""
+msgstr "Carta de apresentação necessita um modelo de e-mail"
#: builtin/log.c:879
#, c-format
@@ -2200,7 +2212,7 @@ msgstr ""
#: builtin/log.c:952
msgid "Two output directories?"
-msgstr ""
+msgstr "Dois diretórios de saída?"
#: builtin/log.c:1173
#, c-format
@@ -2219,7 +2231,7 @@ msgstr ""
#: builtin/shortlog.c:284
#, c-format
msgid "unrecognized argument: %s"
-msgstr ""
+msgstr "argumento não reconhecido: %s"
#: builtin/log.c:1228
msgid "--name-only does not make sense"
@@ -2235,7 +2247,7 @@ msgstr ""
#: builtin/log.c:1255
msgid "standard output, or directory, which one?"
-msgstr ""
+msgstr "saída padrão, ou diretório, qual deles?"
#: builtin/log.c:1257
#, c-format
@@ -2244,7 +2256,7 @@ msgstr ""
#: builtin/log.c:1410
msgid "Failed to create output files"
-msgstr ""
+msgstr "Falhou ao criar ficheiros de saída"
#: builtin/log.c:1514
#, c-format
@@ -2270,12 +2282,12 @@ msgstr ""
#: builtin/merge.c:129
#, c-format
msgid "Available strategies are:"
-msgstr ""
+msgstr "As estratégias disponíveis são:"
#: builtin/merge.c:134
#, c-format
msgid "Available custom strategies are:"
-msgstr ""
+msgstr "Estratégias personalizadas disponíveis são:"
#: builtin/merge.c:241
msgid "could not run stash."
@@ -2361,7 +2373,7 @@ msgstr ""
#: builtin/merge.c:885
#, c-format
msgid "Not committing merge; use 'git commit' to complete the merge.\n"
-msgstr ""
+msgstr "Não commitando um merge; usa 'git commit' para completar o merge.\n"
#: builtin/merge.c:891
msgid ""
@@ -2374,7 +2386,7 @@ msgstr ""
#: builtin/merge.c:915
msgid "Empty commit message."
-msgstr ""
+msgstr "Mensagem de commit vazia."
#: builtin/merge.c:927
#, c-format
@@ -2502,7 +2514,7 @@ msgstr ""
#: builtin/merge.c:1555
#, c-format
msgid "Merge with strategy %s failed.\n"
-msgstr ""
+msgstr "Fundir com a estratégia %s falhou.\n"
#: builtin/merge.c:1564
#, c-format
@@ -2538,15 +2550,15 @@ msgstr ""
#: builtin/mv.c:140
msgid "source directory is empty"
-msgstr ""
+msgstr "o directorio fonte está vazio"
#: builtin/mv.c:171
msgid "not under version control"
-msgstr ""
+msgstr "não está no controlo de versões"
#: builtin/mv.c:173
msgid "destination exists"
-msgstr ""
+msgstr "existe destino"
#: builtin/mv.c:181
#, c-format
@@ -2559,7 +2571,7 @@ msgstr "Não consegue subscrever"
#: builtin/mv.c:187
msgid "multiple sources for the same target"
-msgstr ""
+msgstr "múltiplas fontes para o mesmo alvo"
#: builtin/mv.c:202
#, c-format
@@ -2569,12 +2581,12 @@ msgstr ""
#: builtin/mv.c:212
#, c-format
msgid "Renaming %s to %s\n"
-msgstr ""
+msgstr "Mudar de nome %s para %s\n"
#: builtin/mv.c:215
#, c-format
msgid "renaming '%s' failed"
-msgstr ""
+msgstr "mudar de nome '%s' falhou"
#: builtin/notes.c:139
#, c-format
@@ -2672,7 +2684,7 @@ msgstr ""
#: builtin/notes.c:377
#, c-format
msgid "Bad %s value: '%s'"
-msgstr ""
+msgstr "Inválido %s valor: '%s'"
#: builtin/notes.c:441
#, c-format
@@ -2692,13 +2704,13 @@ msgstr ""
#: builtin/notes.c:759
#: builtin/notes.c:1033
msgid "too many parameters"
-msgstr ""
+msgstr "demasiado parametros"
#: builtin/notes.c:513
#: builtin/notes.c:772
#, c-format
msgid "No note found for object %s."
-msgstr ""
+msgstr "Nenhuma nota encontrada para o objecto %s."
#: builtin/notes.c:580
#, c-format
@@ -2755,7 +2767,7 @@ msgstr ""
#: builtin/pack-objects.c:2322
#, c-format
msgid "option %s does not accept negative form"
-msgstr ""
+msgstr "opção %s não aceita formato negativo"
#: builtin/pack-objects.c:2326
#, c-format
@@ -2768,7 +2780,7 @@ msgstr ""
#: builtin/push.c:63
msgid "--delete only accepts plain target ref names"
-msgstr ""
+msgstr "--delete só aceita nomes simples para o ref de destino"
#: builtin/push.c:73
#, c-format
@@ -2835,7 +2847,7 @@ msgstr ""
#: builtin/push.c:176
msgid "--all and --tags are incompatible"
-msgstr ""
+msgstr "--all e --tags are são incompatíveis"
#: builtin/push.c:177
msgid "--all can't be combined with refspecs"
@@ -2879,7 +2891,7 @@ msgstr "manter"
#: builtin/reset.c:77
msgid "You do not have a valid HEAD."
-msgstr ""
+msgstr "Não tens a HEAD válida."
#: builtin/reset.c:79
msgid "Failed to find tree of HEAD."
@@ -2915,7 +2927,7 @@ msgstr ""
#: builtin/reset.c:297
#, c-format
msgid "Could not parse object '%s'."
-msgstr ""
+msgstr "Não foi possível analisar objeto '%s'."
#: builtin/reset.c:302
msgid "--patch is incompatible with --{hard,mixed,soft}"
@@ -3055,7 +3067,7 @@ msgstr ""
#: builtin/tag.c:366
msgid "no tag message?"
-msgstr ""
+msgstr "nenhuma mensaje para a etiqueta?"
#: builtin/tag.c:372
#, c-format
@@ -3099,7 +3111,7 @@ msgstr ""
#: builtin/tag.c:545
#, c-format
msgid "tag '%s' already exists"
-msgstr ""
+msgstr "etiqueta '%s' já existe"
#: builtin/tag.c:563
#, c-format
@@ -3118,7 +3130,7 @@ msgstr ""
#: git-am.sh:49
msgid "You need to set your committer info first"
-msgstr ""
+msgstr "Necessitas primeiro de especificiar os teus dados de committer"
#: git-am.sh:136
msgid "Repository lacks necessary blobs to fall back on 3-way merge."
@@ -3145,7 +3157,7 @@ msgstr ""
#: git-am.sh:357
msgid "Patch format detection failed."
-msgstr ""
+msgstr "Falhou a detecção do formato do patch."
#: git-am.sh:411
msgid "-d option is no longer supported. Do not use."
@@ -3187,7 +3199,7 @@ msgstr "Aplicando: $FIRSTLINE"
#: git-am.sh:840
msgid "No changes -- Patch already applied."
-msgstr ""
+msgstr "Nenhuma mudança -- Já foi aplicado o patch."
#: git-am.sh:866
msgid "applying to an empty history"
@@ -3307,7 +3319,7 @@ msgstr ""
#: git-pull.sh:257
msgid "Cannot rebase onto multiple branches"
-msgstr ""
+msgstr "Não é possível fazer rebase com várias ramas"
#: git-stash.sh:51
msgid "git stash clear with parameters is unimplemented"
@@ -3328,7 +3340,7 @@ msgstr ""
#: git-stash.sh:140
msgid "No changes selected"
-msgstr ""
+msgstr "Não há alterações seleccionadas"
#: git-stash.sh:143
msgid "Cannot remove temporary index (can't happen)"
@@ -3340,11 +3352,11 @@ msgstr ""
#: git-stash.sh:223
msgid "No local changes to save"
-msgstr ""
+msgstr "Sem alterações locais para guardar"
#: git-stash.sh:227
msgid "Cannot initialize stash"
-msgstr ""
+msgstr "Não é possível inicializar o stash"
#: git-stash.sh:235
msgid "Cannot save the current status"
@@ -3401,7 +3413,7 @@ msgstr ""
#: git-stash.sh:491
#, sh-format
msgid "Dropped ${REV} ($s)"
-msgstr ""
+msgstr "Deixado cair ${REV} ($s)"
#: git-stash.sh:492
#, sh-format
@@ -3410,7 +3422,7 @@ msgstr ""
#: git-stash.sh:499
msgid "No branch name specified"
-msgstr ""
+msgstr "Nenhum nome para a rama especificado"
#: git-stash.sh:570
msgid "(To restore them type \"git stash apply\")"
@@ -3469,7 +3481,7 @@ msgstr ""
#: git-submodule.sh:347
#, sh-format
msgid "Entering '$prefix$path'"
-msgstr ""
+msgstr "Entrando '$prefix$path'"
#: git-submodule.sh:359
#, sh-format
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 6474739480..701b693378 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2012-03-16 20:18+0800\n"
+"POT-Creation-Date: 2012-04-28 20:17+0800\n"
"PO-Revision-Date: 2012-01-30 00:00+0800\n"
"Last-Translator: Jiang Xin <worldhello.net@gmail.com>\n"
"Language-Team: GitHub <https://github.com/gotgit/git/>\n"
@@ -22,7 +22,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-#: advice.c:34
+#: advice.c:40
#, c-format
msgid "hint: %.*s\n"
msgstr "提示:%.*s\n"
@@ -31,7 +31,7 @@ msgstr "提示:%.*s\n"
#. * Message used both when 'git commit' fails and when
#. * other commands doing a merge do.
#.
-#: advice.c:64
+#: advice.c:70
msgid ""
"Fix them up in the work tree,\n"
"and then use 'git add/rm <file>' as\n"
@@ -42,12 +42,12 @@ msgstr ""
"'git add/rm <file>' 标记解决方案,\n"
"或使用 'git commit -a'。"
-#: commit.c:47
+#: commit.c:48
#, c-format
msgid "could not parse %s"
msgstr "不能解析 %s"
-#: commit.c:49
+#: commit.c:50
#, c-format
msgid "%s %s is not a commit!"
msgstr "%s %s 不是一个提交!"
@@ -91,29 +91,29 @@ msgstr ""
"发现配置变量 'diff.dirstat' 中的错误:\n"
"%s"
-#: diff.c:1336
+#: diff.c:1400
msgid " 0 files changed\n"
msgstr " 0 个文件被修改\n"
-#: diff.c:1340
+#: diff.c:1404
#, c-format
msgid " %d file changed"
msgid_plural " %d files changed"
msgstr[0] " %d 个文件被修改"
-#: diff.c:1357
+#: diff.c:1421
#, c-format
msgid ", %d insertion(+)"
msgid_plural ", %d insertions(+)"
msgstr[0] ",插入 %d 行(+)"
-#: diff.c:1368
+#: diff.c:1432
#, c-format
msgid ", %d deletion(-)"
msgid_plural ", %d deletions(-)"
msgstr[0] ",删除 %d 行(-)"
-#: diff.c:3424
+#: diff.c:3435
#, c-format
msgid ""
"Failed to parse --dirstat/-X option parameter:\n"
@@ -183,14 +183,14 @@ msgstr[0] ""
"您的分支和 '%s' 出现了偏离,\n"
"并且各自分别有 %d 和 %d 处不同的提交。\n"
-#: sequencer.c:120 builtin/merge.c:864 builtin/merge.c:985
-#: builtin/merge.c:1095 builtin/merge.c:1105
+#: sequencer.c:120 builtin/merge.c:865 builtin/merge.c:978
+#: builtin/merge.c:1088 builtin/merge.c:1098
#, c-format
msgid "Could not open '%s' for writing"
msgstr "不能为写入打开 '%s'"
-#: sequencer.c:122 builtin/merge.c:334 builtin/merge.c:867
-#: builtin/merge.c:1097 builtin/merge.c:1110
+#: sequencer.c:122 builtin/merge.c:333 builtin/merge.c:868
+#: builtin/merge.c:1090 builtin/merge.c:1103
#, c-format
msgid "Could not write to '%s'"
msgstr "不能写入 '%s'"
@@ -285,8 +285,8 @@ msgstr "不能还原 %s... %s"
msgid "could not apply %s... %s"
msgstr "不能应用 %s... %s"
-#: sequencer.c:450 sequencer.c:909 builtin/log.c:288 builtin/log.c:713
-#: builtin/log.c:1329 builtin/log.c:1548 builtin/merge.c:348
+#: sequencer.c:450 sequencer.c:909 builtin/log.c:289 builtin/log.c:719
+#: builtin/log.c:1335 builtin/log.c:1554 builtin/merge.c:347
#: builtin/shortlog.c:181
msgid "revision walk setup failed"
msgstr "版本遍历设置失败"
@@ -411,6 +411,25 @@ msgstr "不能作为初始提交还原"
msgid "Can't cherry-pick into empty head"
msgstr "不能拣选到空分支"
+#: sha1_name.c:864
+msgid "HEAD does not point to a branch"
+msgstr "HEAD 没有指向一个分支"
+
+#: sha1_name.c:867
+#, c-format
+msgid "No such branch: '%s'"
+msgstr "没有此分支:'%s'"
+
+#: sha1_name.c:869
+#, c-format
+msgid "No upstream configured for branch '%s'"
+msgstr "尚未给分支 '%s' 设置上游"
+
+#: sha1_name.c:872
+#, c-format
+msgid "Upstream branch '%s' not stored as a remote-tracking branch"
+msgstr "上游分支 '%s' 没有存储为一个远程跟踪分支"
+
#: wt-status.c:134
msgid "Unmerged paths:"
msgstr "未合并的路径:"
@@ -830,34 +849,34 @@ msgstr ""
# 译者:汉字之间无空格,故删除尾部空格
#. TRANSLATORS: This is "remote " in "remote branch '%s' not found"
-#: builtin/branch.c:163
+#: builtin/branch.c:164
msgid "remote "
msgstr "远程"
-#: builtin/branch.c:171
+#: builtin/branch.c:172
msgid "cannot use -a with -d"
msgstr "不能将 -a 和 -d 共用"
-#: builtin/branch.c:177
+#: builtin/branch.c:178
msgid "Couldn't look up commit object for HEAD"
msgstr "无法查询 HEAD 指向的提交对象"
-#: builtin/branch.c:182
+#: builtin/branch.c:183
#, c-format
msgid "Cannot delete the branch '%s' which you are currently on."
msgstr "无法删除您当前所在的分支 '%s'。"
-#: builtin/branch.c:192
+#: builtin/branch.c:193
#, c-format
msgid "%sbranch '%s' not found."
msgstr "%s分支 '%s' 未发现。"
-#: builtin/branch.c:200
+#: builtin/branch.c:201
#, c-format
msgid "Couldn't look up commit object for '%s'"
msgstr "无法查询 '%s' 指向的提交对象"
-#: builtin/branch.c:206
+#: builtin/branch.c:207
#, c-format
msgid ""
"The branch '%s' is not fully merged.\n"
@@ -866,97 +885,97 @@ msgstr ""
"分支 '%s' 没有完全合并。\n"
"如果您确认要删除它,执行 'git branch -D %s'。"
-#: builtin/branch.c:214
+#: builtin/branch.c:215
#, c-format
msgid "Error deleting %sbranch '%s'"
msgstr "删除 %s分支 '%s' 时出错"
-#: builtin/branch.c:219
+#: builtin/branch.c:221
#, c-format
msgid "Deleted %sbranch %s (was %s).\n"
msgstr "已删除 %s分支 %s(曾为 %s)。\n"
-#: builtin/branch.c:224
+#: builtin/branch.c:226
msgid "Update of config-file failed"
msgstr "无法更新 config 文件"
-#: builtin/branch.c:322
+#: builtin/branch.c:324
#, c-format
msgid "branch '%s' does not point at a commit"
msgstr "分支 '%s' 未指向一个提交"
# 译者:注意保持句尾空格
-#: builtin/branch.c:394
+#: builtin/branch.c:396
#, c-format
msgid "behind %d] "
msgstr "落后 %d] "
# 译者:注意保持句尾空格
-#: builtin/branch.c:396
+#: builtin/branch.c:398
#, c-format
msgid "ahead %d] "
msgstr "领先 %d] "
# 译者:注意保持句尾空格
-#: builtin/branch.c:398
+#: builtin/branch.c:400
#, c-format
msgid "ahead %d, behind %d] "
msgstr "领先 %d,落后 %d] "
-#: builtin/branch.c:501
+#: builtin/branch.c:503
msgid "(no branch)"
msgstr "(非分支)"
-#: builtin/branch.c:566
+#: builtin/branch.c:568
msgid "some refs could not be read"
msgstr "一些引用不能读取"
-#: builtin/branch.c:579
+#: builtin/branch.c:581
msgid "cannot rename the current branch while not on any."
msgstr "无法重命名当前分支因为不处于任何分支上。"
-#: builtin/branch.c:589
+#: builtin/branch.c:591
#, c-format
msgid "Invalid branch name: '%s'"
msgstr "无效的分支名:'%s'"
-#: builtin/branch.c:604
+#: builtin/branch.c:606
msgid "Branch rename failed"
msgstr "分支重命名失败"
-#: builtin/branch.c:608
+#: builtin/branch.c:610
#, c-format
msgid "Renamed a misnamed branch '%s' away"
msgstr "重命名掉一个错误命名的旧分支 '%s'"
-#: builtin/branch.c:612
+#: builtin/branch.c:614
#, c-format
msgid "Branch renamed to %s, but HEAD is not updated!"
msgstr "分支重命名为 %s,但 HEAD 没有更新!"
-#: builtin/branch.c:619
+#: builtin/branch.c:621
msgid "Branch is renamed, but update of config-file failed"
msgstr "分支被重命名,但更新 config 文件失败"
-#: builtin/branch.c:634
+#: builtin/branch.c:636
#, c-format
msgid "malformed object name %s"
msgstr "非法的对象名 %s"
-#: builtin/branch.c:658
+#: builtin/branch.c:660
#, c-format
msgid "could not write branch description template: %s\n"
msgstr "不能写分支描述模版:%s\n"
-#: builtin/branch.c:746
+#: builtin/branch.c:750
msgid "Failed to resolve HEAD as a valid ref."
msgstr "无法将 HEAD 解析为有效引用。"
-#: builtin/branch.c:751 builtin/clone.c:558
+#: builtin/branch.c:755 builtin/clone.c:558
msgid "HEAD not found below refs/heads!"
msgstr "HEAD 没有位于 /refs/heads 之下!"
-#: builtin/branch.c:809
+#: builtin/branch.c:813
msgid "-a and -r options to 'git branch' do not make sense with a branch name"
msgstr "'git branch' 的 -a 和 -r 选项带一个分支名参数没有意义"
@@ -1018,7 +1037,7 @@ msgid "path '%s' is unmerged"
msgstr "路径 '%s' 未合并"
#: builtin/checkout.c:302 builtin/checkout.c:498 builtin/clone.c:583
-#: builtin/merge.c:811
+#: builtin/merge.c:812
msgid "unable to write new index file"
msgstr "无法写新的索引文件"
@@ -1035,43 +1054,43 @@ msgstr "您需要先解决当前索引的冲突"
msgid "Can not do reflog for '%s'\n"
msgstr "不能对 '%s' 执行 reflog 操作\n"
-#: builtin/checkout.c:565
+#: builtin/checkout.c:566
msgid "HEAD is now at"
msgstr "HEAD 目前位于"
-#: builtin/checkout.c:572
+#: builtin/checkout.c:573
#, c-format
msgid "Reset branch '%s'\n"
msgstr "重置分支 '%s'\n"
-#: builtin/checkout.c:575
+#: builtin/checkout.c:576
#, c-format
msgid "Already on '%s'\n"
msgstr "已经位于 '%s'\n"
-#: builtin/checkout.c:579
+#: builtin/checkout.c:580
#, c-format
msgid "Switched to and reset branch '%s'\n"
msgstr "切换并重置分支 '%s'\n"
-#: builtin/checkout.c:581
+#: builtin/checkout.c:582
#, c-format
msgid "Switched to a new branch '%s'\n"
msgstr "切换到一个新分支 '%s'\n"
-#: builtin/checkout.c:583
+#: builtin/checkout.c:584
#, c-format
msgid "Switched to branch '%s'\n"
msgstr "切换到分支 '%s'\n"
# 译者:注意保持前导空格
-#: builtin/checkout.c:639
+#: builtin/checkout.c:640
#, c-format
msgid " ... and %d more.\n"
msgstr " ... 及其它 %d 个。\n"
#. The singular version
-#: builtin/checkout.c:645
+#: builtin/checkout.c:646
#, c-format
msgid ""
"Warning: you are leaving %d commit behind, not connected to\n"
@@ -1088,7 +1107,7 @@ msgstr[0] ""
"\n"
"%s\n"
-#: builtin/checkout.c:663
+#: builtin/checkout.c:664
#, c-format
msgid ""
"If you want to keep them by creating a new branch, this may be a good time\n"
@@ -1103,71 +1122,71 @@ msgstr ""
" git branch new_branch_name %s\n"
"\n"
-#: builtin/checkout.c:692
+#: builtin/checkout.c:693
msgid "internal error in revision walk"
msgstr "在版本遍历时遇到内部错误"
-#: builtin/checkout.c:696
+#: builtin/checkout.c:697
msgid "Previous HEAD position was"
msgstr "之前的 HEAD 位置是"
-#: builtin/checkout.c:722
+#: builtin/checkout.c:723
msgid "You are on a branch yet to be born"
msgstr "您位于一个尚未初始化的分支"
#. case (1)
-#: builtin/checkout.c:853
+#: builtin/checkout.c:854
#, c-format
msgid "invalid reference: %s"
msgstr "无效引用:%s"
#. case (1): want a tree
-#: builtin/checkout.c:892
+#: builtin/checkout.c:893
#, c-format
msgid "reference is not a tree: %s"
msgstr "引用不是一个树:%s"
-#: builtin/checkout.c:972
+#: builtin/checkout.c:973
msgid "-B cannot be used with -b"
msgstr "-B 不能和 -b 共用"
-#: builtin/checkout.c:981
+#: builtin/checkout.c:982
msgid "--patch is incompatible with all other options"
msgstr "--patch 选项和其他选项不兼容"
-#: builtin/checkout.c:984
+#: builtin/checkout.c:985
msgid "--detach cannot be used with -b/-B/--orphan"
msgstr "--detach 不能和 -b/-B/--orphan 共用"
-#: builtin/checkout.c:986
+#: builtin/checkout.c:987
msgid "--detach cannot be used with -t"
msgstr "--detach 不能和 -t 共用"
-#: builtin/checkout.c:992
+#: builtin/checkout.c:993
msgid "--track needs a branch name"
msgstr "--track 需要一个分支名"
-#: builtin/checkout.c:999
+#: builtin/checkout.c:1000
msgid "Missing branch name; try -b"
msgstr "缺少分支名;尝试 -b"
-#: builtin/checkout.c:1005
+#: builtin/checkout.c:1006
msgid "--orphan and -b|-B are mutually exclusive"
msgstr "--orphan 和 -b|-B 互斥"
-#: builtin/checkout.c:1007
+#: builtin/checkout.c:1008
msgid "--orphan cannot be used with -t"
msgstr "--orphan 不能和 -t 共用"
-#: builtin/checkout.c:1017
+#: builtin/checkout.c:1018
msgid "git checkout: -f and -m are incompatible"
msgstr "git checkout:-f 和 -m 不兼容"
-#: builtin/checkout.c:1051
+#: builtin/checkout.c:1052
msgid "invalid path specification"
msgstr "无效的路径规格"
-#: builtin/checkout.c:1059
+#: builtin/checkout.c:1060
#, c-format
msgid ""
"git checkout: updating paths is incompatible with switching branches.\n"
@@ -1176,26 +1195,26 @@ msgstr ""
"git checkout:更新路径和切换分支不兼容。\n"
"您是想要检出 '%s' 但未能将其解析为提交么?"
-#: builtin/checkout.c:1061
+#: builtin/checkout.c:1062
msgid "git checkout: updating paths is incompatible with switching branches."
msgstr "git checkout:更新路径和切换分支不兼容。"
-#: builtin/checkout.c:1066
+#: builtin/checkout.c:1067
msgid "git checkout: --detach does not take a path argument"
msgstr "git checkout:--detach 不跟路径参数"
-#: builtin/checkout.c:1069
+#: builtin/checkout.c:1070
msgid ""
"git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
"checking out of the index."
msgstr ""
"git checkout:在从索引检出时,--ours/--theirs、--force 和 --merge 不兼容。"
-#: builtin/checkout.c:1088
+#: builtin/checkout.c:1089
msgid "Cannot switch branch to a non-commit."
msgstr "无法切换分支到一个非提交。"
-#: builtin/checkout.c:1091
+#: builtin/checkout.c:1092
msgid "--ours/--theirs is incompatible with switching branches."
msgstr "--ours/--theirs 和切换分支不兼容。"
@@ -1452,67 +1471,67 @@ msgstr "无法读取索引"
msgid "unable to write temporary index file"
msgstr "无法写临时索引文件"
-#: builtin/commit.c:550 builtin/commit.c:556
+#: builtin/commit.c:561 builtin/commit.c:567
#, c-format
msgid "invalid commit: %s"
msgstr "无效的提交:%s"
-#: builtin/commit.c:579
+#: builtin/commit.c:590
msgid "malformed --author parameter"
msgstr "非法的 --author 参数"
-#: builtin/commit.c:635
+#: builtin/commit.c:651
#, c-format
msgid "Malformed ident string: '%s'"
msgstr "非法的身份字符串:'%s'"
-#: builtin/commit.c:670 builtin/commit.c:703 builtin/commit.c:1000
+#: builtin/commit.c:689 builtin/commit.c:722 builtin/commit.c:1033
#, c-format
msgid "could not lookup commit %s"
msgstr "不能查询提交 %s"
-#: builtin/commit.c:682 builtin/shortlog.c:296
+#: builtin/commit.c:701 builtin/shortlog.c:296
#, c-format
msgid "(reading log message from standard input)\n"
msgstr "(正从标准输入中读取日志信息)\n"
-#: builtin/commit.c:684
+#: builtin/commit.c:703
msgid "could not read log from standard input"
msgstr "不能从标准输入中读取日志信息"
-#: builtin/commit.c:688
+#: builtin/commit.c:707
#, c-format
msgid "could not read log file '%s'"
msgstr "不能读取日志文件 '%s'"
-#: builtin/commit.c:694
+#: builtin/commit.c:713
msgid "commit has empty message"
msgstr "提交说明为空"
-#: builtin/commit.c:710
+#: builtin/commit.c:729
msgid "could not read MERGE_MSG"
msgstr "不能读取 MERGE_MSG"
-#: builtin/commit.c:714
+#: builtin/commit.c:733
msgid "could not read SQUASH_MSG"
msgstr "不能读取 SQUASH_MSG"
-#: builtin/commit.c:718
+#: builtin/commit.c:737
#, c-format
msgid "could not read '%s'"
msgstr "不能读取 '%s'"
-#: builtin/commit.c:746
+#: builtin/commit.c:765
#, c-format
msgid "could not open '%s'"
msgstr "不能打开 '%s'"
-#: builtin/commit.c:770
+#: builtin/commit.c:789
msgid "could not write commit template"
msgstr "不能写提交模版"
# 译者:%s若翻为中文,前后不需要空格
-#: builtin/commit.c:783
+#: builtin/commit.c:799
#, c-format
msgid ""
"\n"
@@ -1527,12 +1546,12 @@ msgstr ""
"\t%s\n"
"然后重试。\n"
-#: builtin/commit.c:796
+#: builtin/commit.c:812
msgid "Please enter the commit message for your changes."
msgstr "请为您的修改输入提交说明。"
# 译者:中文字符串拼接,可删除前导空格
-#: builtin/commit.c:799
+#: builtin/commit.c:815
msgid ""
" Lines starting\n"
"with '#' will be ignored, and an empty message aborts the commit.\n"
@@ -1541,7 +1560,7 @@ msgstr ""
"的行将被忽略,并且空的提交说明将会中止提交。\n"
# 译者:中文字符串拼接,可删除前导空格
-#: builtin/commit.c:804
+#: builtin/commit.c:820
msgid ""
" Lines starting\n"
"with '#' will be kept; you may remove them yourself if you want to.\n"
@@ -1552,153 +1571,158 @@ msgstr ""
"中止提交。\n"
# 译者:为保证在输出中对齐,注意调整句中空格!
-#: builtin/commit.c:816
+#: builtin/commit.c:832
#, c-format
msgid "%sAuthor: %s"
msgstr "%s作者: %s"
# 译者:为保证在输出中对齐,注意调整句中空格!
-#: builtin/commit.c:823
+#: builtin/commit.c:839
#, c-format
msgid "%sCommitter: %s"
msgstr "%s提交者: %s"
-#: builtin/commit.c:843
+#: builtin/commit.c:859
msgid "Cannot read index"
msgstr "无法读取索引"
-#: builtin/commit.c:880
+#: builtin/commit.c:896
msgid "Error building trees"
msgstr "无法创建树对象"
-#: builtin/commit.c:895 builtin/tag.c:357
+#: builtin/commit.c:911 builtin/tag.c:357
#, c-format
msgid "Please supply the message using either -m or -F option.\n"
msgstr "请使用 -m 或者 -F 选项提供提交说明。\n"
-#: builtin/commit.c:975
+#: builtin/commit.c:1008
#, c-format
msgid "No existing author found with '%s'"
msgstr "没有找到匹配 '%s' 的作者"
-#: builtin/commit.c:990 builtin/commit.c:1182
+#: builtin/commit.c:1023 builtin/commit.c:1217
#, c-format
msgid "Invalid untracked files mode '%s'"
msgstr "无效的未追踪文件参数 '%s'"
-#: builtin/commit.c:1030
+#: builtin/commit.c:1063
msgid "Using both --reset-author and --author does not make sense"
msgstr "同时使用 --reset-author 和 --author 没有意义"
-#: builtin/commit.c:1041
+#: builtin/commit.c:1074
msgid "You have nothing to amend."
msgstr "您没有可修补的提交。"
# 译者:%s若翻为中文,前后不需要空格
-#: builtin/commit.c:1043
+#: builtin/commit.c:1076
#, c-format
msgid "You are in the middle of a %s -- cannot amend."
msgstr "您正处于一个%s的过程中 -- 无法修补提交。"
-#: builtin/commit.c:1045
+#: builtin/commit.c:1078
msgid "Options --squash and --fixup cannot be used together"
msgstr "选项 --squash 和 --fixup 不能共用"
-#: builtin/commit.c:1055
+#: builtin/commit.c:1088
msgid "Only one of -c/-C/-F/--fixup can be used."
msgstr "只能用一个 -c/-C/-F/--fixup 选项。"
-#: builtin/commit.c:1057
+#: builtin/commit.c:1090
msgid "Option -m cannot be combined with -c/-C/-F/--fixup."
msgstr "选项 -m 不能和 -c/-C/-F/--fixup 共用。"
-#: builtin/commit.c:1063
+#: builtin/commit.c:1098
msgid "--reset-author can be used only with -C, -c or --amend."
msgstr "--reset-author 只能和 -C、-c 或 --amend 共用。"
-#: builtin/commit.c:1080
+#: builtin/commit.c:1115
msgid "Only one of --include/--only/--all/--interactive/--patch can be used."
msgstr "只能用一个 --include/--only/--all/--interactive/--patch 选项。"
-#: builtin/commit.c:1082
+#: builtin/commit.c:1117
msgid "No paths with --include/--only does not make sense."
msgstr "参数 --include/--only 不跟路径没有意义。"
-#: builtin/commit.c:1084
+#: builtin/commit.c:1119
msgid "Clever... amending the last one with dirty index."
msgstr "聪明... 在索引不干净下修补最后的提交。"
-#: builtin/commit.c:1086
+#: builtin/commit.c:1121
msgid "Explicit paths specified without -i nor -o; assuming --only paths..."
msgstr "指定了明确的路径而没有使用 -i 或 -o 选项;认为是 --only paths..."
-#: builtin/commit.c:1096 builtin/tag.c:556
+#: builtin/commit.c:1131 builtin/tag.c:556
#, c-format
msgid "Invalid cleanup mode %s"
msgstr "无效的清理模式 %s"
-#: builtin/commit.c:1101
+#: builtin/commit.c:1136
msgid "Paths with -a does not make sense."
msgstr "路径和 -a 选项共用没有意义。"
-#: builtin/commit.c:1280
+#: builtin/commit.c:1315
msgid "couldn't look up newly created commit"
msgstr "无法找到新创建的提交"
-#: builtin/commit.c:1282
+#: builtin/commit.c:1317
msgid "could not parse newly created commit"
msgstr "不能解析新创建的提交"
-#: builtin/commit.c:1323
+#: builtin/commit.c:1358
msgid "detached HEAD"
msgstr "分离头指针"
# 译者:中文字符串拼接,可删除前导空格
-#: builtin/commit.c:1325
+#: builtin/commit.c:1360
msgid " (root-commit)"
msgstr "(根提交)"
-#: builtin/commit.c:1415
+#: builtin/commit.c:1450
msgid "could not parse HEAD commit"
msgstr "不能解析 HEAD 提交"
-#: builtin/commit.c:1452 builtin/merge.c:509
+#: builtin/commit.c:1487 builtin/merge.c:509
#, c-format
msgid "could not open '%s' for reading"
msgstr "不能为读入打开 '%s'"
-#: builtin/commit.c:1459
+#: builtin/commit.c:1494
#, c-format
msgid "Corrupt MERGE_HEAD file (%s)"
msgstr "损坏的 MERGE_HEAD 文件(%s)"
-#: builtin/commit.c:1466
+#: builtin/commit.c:1501
msgid "could not read MERGE_MODE"
msgstr "不能读取 MERGE_MODE"
-#: builtin/commit.c:1485
+#: builtin/commit.c:1520
#, c-format
msgid "could not read commit message: %s"
msgstr "不能读取提交说明:%s"
-#: builtin/commit.c:1499
+#: builtin/commit.c:1534
+#, c-format
+msgid "Aborting commit; you did not edit the message.\n"
+msgstr "终止提交;您未更改来自模版的提交说明。\n"
+
+#: builtin/commit.c:1539
#, c-format
msgid "Aborting commit due to empty commit message.\n"
msgstr "终止提交因为提交说明为空。\n"
-#: builtin/commit.c:1514 builtin/merge.c:935 builtin/merge.c:968
+#: builtin/commit.c:1554 builtin/merge.c:936 builtin/merge.c:961
msgid "failed to write commit object"
msgstr "无法写提交对象"
-#: builtin/commit.c:1535
+#: builtin/commit.c:1575
msgid "cannot lock HEAD ref"
msgstr "无法锁定 HEAD 引用"
-#: builtin/commit.c:1539
+#: builtin/commit.c:1579
msgid "cannot update HEAD ref"
msgstr "无法更新 HEAD 引用"
-#: builtin/commit.c:1550
+#: builtin/commit.c:1590
msgid ""
"Repository has been updated, but unable to write\n"
"new_index file. Check that disk is not full or quota is\n"
@@ -1829,69 +1853,73 @@ msgstr "提供了无法处理的对象 '%s'。"
msgid "Couldn't find remote ref HEAD"
msgstr "无法发现远程 HEAD 引用"
-#: builtin/fetch.c:252
+#: builtin/fetch.c:253
#, c-format
msgid "object %s not found"
msgstr "对象 %s 未发现"
-#: builtin/fetch.c:258
+#: builtin/fetch.c:259
msgid "[up to date]"
msgstr "[最新]"
-#: builtin/fetch.c:272
+#: builtin/fetch.c:273
#, c-format
msgid "! %-*s %-*s -> %s (can't fetch in current branch)"
msgstr "! %-*s %-*s -> %s (在当前分支下不能获取)"
-#: builtin/fetch.c:273 builtin/fetch.c:351
+#: builtin/fetch.c:274 builtin/fetch.c:360
msgid "[rejected]"
msgstr "[已拒绝]"
-#: builtin/fetch.c:284
+#: builtin/fetch.c:285
msgid "[tag update]"
msgstr "[tag更新]"
# 译者:注意保持前导空格
-#: builtin/fetch.c:286 builtin/fetch.c:313 builtin/fetch.c:331
+#: builtin/fetch.c:287 builtin/fetch.c:322 builtin/fetch.c:340
msgid " (unable to update local ref)"
msgstr " (不能更新本地引用)"
-#: builtin/fetch.c:298
+#: builtin/fetch.c:305
msgid "[new tag]"
msgstr "[新tag]"
-#: builtin/fetch.c:302
+#: builtin/fetch.c:308
msgid "[new branch]"
msgstr "[新分支]"
-#: builtin/fetch.c:347
+#: builtin/fetch.c:311
+msgid "[new ref]"
+msgstr "[新引用]"
+
+#: builtin/fetch.c:356
msgid "unable to update local ref"
msgstr "不能更新本地引用"
-#: builtin/fetch.c:347
+#: builtin/fetch.c:356
msgid "forced update"
msgstr "强制更新"
-#: builtin/fetch.c:353
+#: builtin/fetch.c:362
msgid "(non-fast-forward)"
msgstr "(非快进式)"
-#: builtin/fetch.c:384 builtin/fetch.c:676
+#: builtin/fetch.c:393 builtin/fetch.c:685
#, c-format
msgid "cannot open %s: %s\n"
msgstr "无法打开 %s:%s\n"
-#: builtin/fetch.c:393
+#: builtin/fetch.c:402
#, c-format
msgid "%s did not send all necessary objects\n"
msgstr "%s 未发送所有必须的对象\n"
-#: builtin/fetch.c:479
+#: builtin/fetch.c:488
#, c-format
msgid "From %.*s\n"
msgstr "来自 %.*s\n"
-#: builtin/fetch.c:490
+#: builtin/fetch.c:499
#, c-format
msgid ""
"some local refs could not be updated; try running\n"
@@ -1901,79 +1929,79 @@ msgstr ""
" 'git remote prune %s' 来删除旧的、有冲突的分支"
# 译者:注意保持前导空格
-#: builtin/fetch.c:540
+#: builtin/fetch.c:549
#, c-format
msgid " (%s will become dangling)\n"
msgstr " (%s 将成为悬空状态)\n"
# 译者:注意保持前导空格
-#: builtin/fetch.c:541
+#: builtin/fetch.c:550
#, c-format
msgid " (%s has become dangling)\n"
msgstr " (%s 已成为悬空状态)\n"
-#: builtin/fetch.c:548
+#: builtin/fetch.c:557
msgid "[deleted]"
msgstr "[已删除]"
-#: builtin/fetch.c:549
+#: builtin/fetch.c:558
msgid "(none)"
msgstr "(无)"
-#: builtin/fetch.c:666
+#: builtin/fetch.c:675
#, c-format
msgid "Refusing to fetch into current branch %s of non-bare repository"
msgstr "拒绝获取到非裸版本库的当前分支 %s"
-#: builtin/fetch.c:700
+#: builtin/fetch.c:709
#, c-format
msgid "Don't know how to fetch from %s"
msgstr "不知道如何从 %s 获取"
-#: builtin/fetch.c:777
+#: builtin/fetch.c:786
#, c-format
msgid "Option \"%s\" value \"%s\" is not valid for %s"
msgstr "选项 \"%s\" 的值 \"%s\" 对于 %s 是无效的"
-#: builtin/fetch.c:780
+#: builtin/fetch.c:789
#, c-format
msgid "Option \"%s\" is ignored for %s\n"
msgstr "选项 \"%s\" 对于 %s 被忽略\n"
-#: builtin/fetch.c:879
+#: builtin/fetch.c:888
#, c-format
msgid "Fetching %s\n"
msgstr "正在获取 %s\n"
-#: builtin/fetch.c:881
+#: builtin/fetch.c:890
#, c-format
msgid "Could not fetch %s"
msgstr "不能获取 %s"
-#: builtin/fetch.c:898
+#: builtin/fetch.c:907
msgid ""
"No remote repository specified. Please, specify either a URL or a\n"
"remote name from which new revisions should be fetched."
msgstr "未指定远程版本库。请通过一个URL或远程版本库名指定,用以获取新提交。"
-#: builtin/fetch.c:918
+#: builtin/fetch.c:927
msgid "You need to specify a tag name."
msgstr "您需要指定一个 tag 名称。"
-#: builtin/fetch.c:970
+#: builtin/fetch.c:979
msgid "fetch --all does not take a repository argument"
msgstr "fetch --all 不能带一个版本库参数"
-#: builtin/fetch.c:972
+#: builtin/fetch.c:981
msgid "fetch --all does not make sense with refspecs"
msgstr "fetch --all 带引用表达式没有任何意义"
-#: builtin/fetch.c:983
+#: builtin/fetch.c:992
#, c-format
msgid "No such remote or remote group: %s"
msgstr "没有这样的远程或远程组:%s"
-#: builtin/fetch.c:991
+#: builtin/fetch.c:1000
msgid "Fetching a group and specifying refspecs does not make sense"
msgstr "获取组并指定引用表达式没有意义"
@@ -2202,7 +2230,8 @@ msgid ""
"%s (or --work-tree=<directory>) not allowed without specifying %s (or --git-"
"dir=<directory>)"
msgstr ""
-"不允许 %s(或 --work-tree=<directory>)而没有指定 %s(或 --git-dir=<directory>)"
+"不允许 %s(或 --work-tree=<directory>)而没有指定 %s(或 --git-"
+"dir=<directory>)"
#: builtin/init-db.c:578
msgid "Cannot access current working directory"
@@ -2213,164 +2242,164 @@ msgstr "不能访问当前工作目录"
msgid "Cannot access work tree '%s'"
msgstr "不能访问工作区 '%s'"
-#: builtin/log.c:187
+#: builtin/log.c:188
#, c-format
msgid "Final output: %d %s\n"
msgstr "最终输出:%d %s\n"
-#: builtin/log.c:395 builtin/log.c:483
+#: builtin/log.c:401 builtin/log.c:489
#, c-format
msgid "Could not read object %s"
msgstr "不能读取对象 %s"
-#: builtin/log.c:507
+#: builtin/log.c:513
#, c-format
msgid "Unknown type: %d"
msgstr "未知类型:%d"
-#: builtin/log.c:596
+#: builtin/log.c:602
msgid "format.headers without value"
msgstr "format.headers 没有值"
-#: builtin/log.c:669
+#: builtin/log.c:675
msgid "name of output directory is too long"
msgstr "输出目录名太长"
-#: builtin/log.c:680
+#: builtin/log.c:686
#, c-format
msgid "Cannot open patch file %s"
msgstr "无法打开补丁文件 %s"
-#: builtin/log.c:694
+#: builtin/log.c:700
msgid "Need exactly one range."
msgstr "只需要一个范围。"
-#: builtin/log.c:702
+#: builtin/log.c:708
msgid "Not a range."
msgstr "不是一个范围。"
-#: builtin/log.c:739
+#: builtin/log.c:745
msgid "Could not extract email from committer identity."
msgstr "不能从提交者身份中提取邮件地址。"
-#: builtin/log.c:785
+#: builtin/log.c:791
msgid "Cover letter needs email format"
msgstr "信封需要邮件地址格式"
-#: builtin/log.c:879
+#: builtin/log.c:885
#, c-format
msgid "insane in-reply-to: %s"
msgstr "不正常的 in-reply-to:%s"
-#: builtin/log.c:952
+#: builtin/log.c:958
msgid "Two output directories?"
msgstr "两个输出目录?"
-#: builtin/log.c:1173
+#: builtin/log.c:1179
#, c-format
msgid "bogus committer info %s"
msgstr "虚假的提交者信息 %s"
-#: builtin/log.c:1218
+#: builtin/log.c:1224
msgid "-n and -k are mutually exclusive."
msgstr "-n 和 -k 互斥。"
-#: builtin/log.c:1220
+#: builtin/log.c:1226
msgid "--subject-prefix and -k are mutually exclusive."
msgstr "--subject-prefix 和 -k 互斥。"
-#: builtin/log.c:1225 builtin/shortlog.c:284
+#: builtin/log.c:1231 builtin/shortlog.c:284
#, c-format
msgid "unrecognized argument: %s"
msgstr "未识别的参数:%s"
-#: builtin/log.c:1228
+#: builtin/log.c:1234
msgid "--name-only does not make sense"
msgstr "--name-only 无意义"
-#: builtin/log.c:1230
+#: builtin/log.c:1236
msgid "--name-status does not make sense"
msgstr "--name-status 无意义"
-#: builtin/log.c:1232
+#: builtin/log.c:1238
msgid "--check does not make sense"
msgstr "--check 无意义"
-#: builtin/log.c:1255
+#: builtin/log.c:1261
msgid "standard output, or directory, which one?"
msgstr "标准输出或目录,哪一个?"
-#: builtin/log.c:1257
+#: builtin/log.c:1263
#, c-format
msgid "Could not create directory '%s'"
msgstr "不能创建目录 '%s'"
-#: builtin/log.c:1410
+#: builtin/log.c:1416
msgid "Failed to create output files"
msgstr "无法创建输出文件"
-#: builtin/log.c:1514
+#: builtin/log.c:1520
#, c-format
msgid ""
"Could not find a tracked remote branch, please specify <upstream> manually.\n"
msgstr "不能找到跟踪的远程分支,请手工指定 <upstream>。\n"
-#: builtin/log.c:1530 builtin/log.c:1532 builtin/log.c:1544
+#: builtin/log.c:1536 builtin/log.c:1538 builtin/log.c:1550
#, c-format
msgid "Unknown commit %s"
msgstr "未知提交 %s"
-#: builtin/merge.c:91
+#: builtin/merge.c:90
msgid "switch `m' requires a value"
msgstr "开关 `m' 需要一个值"
-#: builtin/merge.c:128
+#: builtin/merge.c:127
#, c-format
msgid "Could not find merge strategy '%s'.\n"
msgstr "不能找到合并策略 '%s'。\n"
-#: builtin/merge.c:129
+#: builtin/merge.c:128
#, c-format
msgid "Available strategies are:"
msgstr "可用的策略有:"
-#: builtin/merge.c:134
+#: builtin/merge.c:133
#, c-format
msgid "Available custom strategies are:"
msgstr "可用的自定义策略有:"
-#: builtin/merge.c:241
+#: builtin/merge.c:240
msgid "could not run stash."
msgstr "不能进行进度保存。"
-#: builtin/merge.c:246
+#: builtin/merge.c:245
msgid "stash failed"
msgstr "进度保存失败"
-#: builtin/merge.c:251
+#: builtin/merge.c:250
#, c-format
msgid "not a valid object: %s"
msgstr "不是一个有效对象:%s"
-#: builtin/merge.c:270 builtin/merge.c:287
+#: builtin/merge.c:269 builtin/merge.c:286
msgid "read-tree failed"
msgstr "读取树失败"
# 译者:注意保持前导空格
-#: builtin/merge.c:317
+#: builtin/merge.c:316
msgid " (nothing to squash)"
msgstr " (无可压缩)"
-#: builtin/merge.c:330
+#: builtin/merge.c:329
#, c-format
msgid "Squash commit -- not updating HEAD\n"
msgstr "压缩提交 -- 未更新 HEAD\n"
-#: builtin/merge.c:362
+#: builtin/merge.c:361
msgid "Writing SQUASH_MSG"
msgstr "写入 SQUASH_MSG"
-#: builtin/merge.c:364
+#: builtin/merge.c:363
msgid "Finishing SQUASH_MSG"
msgstr "完成 SQUASH_MSG"
@@ -2397,35 +2426,35 @@ msgstr "git write-tree 无法写入一树对象"
msgid "failed to read the cache"
msgstr "无法读取缓存"
-#: builtin/merge.c:696
+#: builtin/merge.c:697
msgid "Unable to write index."
msgstr "不能写索引。"
-#: builtin/merge.c:709
+#: builtin/merge.c:710
msgid "Not handling anything other than two heads merge."
msgstr "不能处理两个头合并之外的任何操作。"
-#: builtin/merge.c:723
+#: builtin/merge.c:724
#, c-format
msgid "Unknown option for merge-recursive: -X%s"
msgstr "merge-recursive 的未知选项:-X%s"
-#: builtin/merge.c:737
+#: builtin/merge.c:738
#, c-format
msgid "unable to write %s"
msgstr "不能写 %s"
-#: builtin/merge.c:876
+#: builtin/merge.c:877
#, c-format
msgid "Could not read from '%s'"
msgstr "不能从 '%s' 读取"
-#: builtin/merge.c:885
+#: builtin/merge.c:886
#, c-format
msgid "Not committing merge; use 'git commit' to complete the merge.\n"
msgstr "未提交合并,使用 'git commit' 完成此次合并。\n"
-#: builtin/merge.c:891
+#: builtin/merge.c:892
msgid ""
"Please enter a commit message to explain why this merge is necessary,\n"
"especially if it merges an updated upstream into a topic branch.\n"
@@ -2438,47 +2467,52 @@ msgstr ""
"\n"
"以 '#' 开头的行将被忽略,而且空提交说明将会终止提交。\n"
-#: builtin/merge.c:915
+#: builtin/merge.c:916
msgid "Empty commit message."
msgstr "空提交信息。"
-#: builtin/merge.c:927
+#: builtin/merge.c:928
#, c-format
msgid "Wonderful.\n"
msgstr "太棒了。\n"
-#: builtin/merge.c:1000
+#: builtin/merge.c:993
#, c-format
msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
msgstr "自动合并失败,修正冲突然后提交修正的结果。\n"
-#: builtin/merge.c:1016
+#: builtin/merge.c:1009
#, c-format
msgid "'%s' is not a commit"
msgstr "'%s' 不是一个提交"
-#: builtin/merge.c:1057
+#: builtin/merge.c:1050
msgid "No current branch."
msgstr "没有当前分支。"
-#: builtin/merge.c:1059
+#: builtin/merge.c:1052
msgid "No remote for the current branch."
msgstr "当前分支没有对应的远程版本库。"
-#: builtin/merge.c:1061
+#: builtin/merge.c:1054
msgid "No default upstream defined for the current branch."
msgstr "当前分支没有定义默认的上游分支。"
-#: builtin/merge.c:1066
+#: builtin/merge.c:1059
#, c-format
msgid "No remote tracking branch for %s from %s"
msgstr "%s 没有来自 %s 的远程跟踪分支"
-#: builtin/merge.c:1188
+#: builtin/merge.c:1146 builtin/merge.c:1303
+#, c-format
+msgid "%s - not something we can merge"
+msgstr "%s - 不能被合并"
+
+#: builtin/merge.c:1214
msgid "There is no merge to abort (MERGE_HEAD missing)."
msgstr "没有要终止的合并(MERGE_HEAD 丢失)。"
-#: builtin/merge.c:1204 git-pull.sh:31
+#: builtin/merge.c:1230 git-pull.sh:31
msgid ""
"You have not concluded your merge (MERGE_HEAD exists).\n"
"Please, commit your changes before you can merge."
@@ -2486,11 +2520,11 @@ msgstr ""
"您尚未结束您的合并(存在 MERGE_HEAD)。\n"
"请在合并前先提交您的修改。"
-#: builtin/merge.c:1207 git-pull.sh:34
+#: builtin/merge.c:1233 git-pull.sh:34
msgid "You have not concluded your merge (MERGE_HEAD exists)."
msgstr "您尚未结束您的合并(存在 MERGE_HEAD)。"
-#: builtin/merge.c:1211
+#: builtin/merge.c:1237
msgid ""
"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
"Please, commit your changes before you can merge."
@@ -2498,84 +2532,79 @@ msgstr ""
"您尚未结束您的拣选(存在 CHERRY_PICK_HEAD)。\n"
"请在合并前先提交您的修改。"
-#: builtin/merge.c:1214
+#: builtin/merge.c:1240
msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
msgstr "您尚未结束您的拣选(存在 CHERRY_PICK_HEAD)。"
-#: builtin/merge.c:1223
+#: builtin/merge.c:1249
msgid "You cannot combine --squash with --no-ff."
msgstr "您不能将 --squash 与 --no-ff 共用。"
-#: builtin/merge.c:1228
+#: builtin/merge.c:1254
msgid "You cannot combine --no-ff with --ff-only."
msgstr "您不能将 --no-ff 与 --ff-only 共用。"
-#: builtin/merge.c:1235
+#: builtin/merge.c:1261
msgid "No commit specified and merge.defaultToUpstream not set."
msgstr "未指定提交并且 merge.defaultToUpstream 未设置。"
-#: builtin/merge.c:1266
+#: builtin/merge.c:1293
msgid "Can merge only exactly one commit into empty head"
msgstr "只能将一个提交合并到空分支上"
-#: builtin/merge.c:1269
+#: builtin/merge.c:1296
msgid "Squash commit into empty head not supported yet"
msgstr "尚不支持到空分支的压缩提交"
-#: builtin/merge.c:1271
+#: builtin/merge.c:1298
msgid "Non-fast-forward commit does not make sense into an empty head"
msgstr "到空分支的非快进式提交没有意义"
-#: builtin/merge.c:1275 builtin/merge.c:1319
-#, c-format
-msgid "%s - not something we can merge"
-msgstr "%s - 不能被合并"
-
-#: builtin/merge.c:1385
+#: builtin/merge.c:1413
#, c-format
msgid "Updating %s..%s\n"
msgstr "更新 %s..%s\n"
-#: builtin/merge.c:1423
+#: builtin/merge.c:1451
#, c-format
msgid "Trying really trivial in-index merge...\n"
msgstr "尝试非常小的索引内合并...\n"
-#: builtin/merge.c:1430
+#: builtin/merge.c:1458
#, c-format
msgid "Nope.\n"
msgstr "无。\n"
-#: builtin/merge.c:1462
+#: builtin/merge.c:1490
msgid "Not possible to fast-forward, aborting."
msgstr "无法快进,终止。"
-#: builtin/merge.c:1485 builtin/merge.c:1562
+#: builtin/merge.c:1513 builtin/merge.c:1592
#, c-format
msgid "Rewinding the tree to pristine...\n"
msgstr "将树回滚至原始状态...\n"
-#: builtin/merge.c:1489
+#: builtin/merge.c:1517
#, c-format
msgid "Trying merge strategy %s...\n"
msgstr "尝试合并策略 %s...\n"
-#: builtin/merge.c:1553
+#: builtin/merge.c:1583
#, c-format
msgid "No merge strategy handled the merge.\n"
msgstr "没有合并策略处理此合并。\n"
-#: builtin/merge.c:1555
+#: builtin/merge.c:1585
#, c-format
msgid "Merge with strategy %s failed.\n"
msgstr "使用策略 %s 合并失败。\n"
-#: builtin/merge.c:1564
+#: builtin/merge.c:1594
#, c-format
msgid "Using the %s to prepare resolving by hand.\n"
msgstr "使用 %s 以准备手工解决。\n"
-#: builtin/merge.c:1575
+#: builtin/merge.c:1606
#, c-format
msgid "Automatic merge went well; stopped before committing as requested\n"
msgstr "自动合并进展顺利,按要求在提交前停止\n"
@@ -2816,15 +2845,15 @@ msgstr "选项 %s 不接受否定格式"
msgid "unable to parse value '%s' for option %s"
msgstr "不能解析值 '%s' 针对于选项 %s"
-#: builtin/push.c:44
+#: builtin/push.c:45
msgid "tag shorthand without <tag>"
msgstr "tag 简写没有跟 <tag> 参数"
-#: builtin/push.c:63
+#: builtin/push.c:64
msgid "--delete only accepts plain target ref names"
msgstr "--delete 只接受简单的目标引用名"
-#: builtin/push.c:73
+#: builtin/push.c:84
#, c-format
msgid ""
"You are not currently on a branch.\n"
@@ -2838,7 +2867,7 @@ msgstr ""
"\n"
" git push %s HEAD:<name-of-remote-branch>\n"
-#: builtin/push.c:80
+#: builtin/push.c:91
#, c-format
msgid ""
"The current branch %s has no upstream branch.\n"
@@ -2851,43 +2880,75 @@ msgstr ""
"\n"
" git push --set-upstream %s %s\n"
-#: builtin/push.c:88
+#: builtin/push.c:99
#, c-format
msgid "The current branch %s has multiple upstream branches, refusing to push."
msgstr "当前分支 %s 有多个上游分支,拒绝推送。"
-#: builtin/push.c:111
+#: builtin/push.c:102
+#, c-format
+msgid ""
+"You are pushing to remote '%s', which is not the upstream of\n"
+"your current branch '%s', without telling me what to push\n"
+"to update which remote branch."
+msgstr ""
+"您正推送至远程 '%s'(其并非当前分支 '%s' 的上游),\n"
+"而没有告诉我要推送什么、更新哪个远程分支。"
+
+#: builtin/push.c:131
msgid ""
"You didn't specify any refspecs to push, and push.default is \"nothing\"."
msgstr "您没有为推送指定任何引用表达式,并且 push.default 为 \"nothing\"。"
-#: builtin/push.c:131
+#: builtin/push.c:138
+msgid ""
+"Updates were rejected because the tip of your current branch is behind\n"
+"its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
+"before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
+msgstr ""
+"更新被拒绝,因为您当前分支落后于对应的远程分支。再次推送前先与远程变更\n"
+"合并(如 'git pull')。\n"
+"详见 'git push --help' 中的 'Note about fast-forwards' 的内容。"
+
+#: builtin/push.c:144
+msgid ""
+"Updates were rejected because a pushed branch tip is behind its remote\n"
+"counterpart. If you did not intend to push that branch, you may want to\n"
+"specify branches to push or set the 'push.default' configuration\n"
+"variable to 'current' or 'upstream' to push only the current branch."
+msgstr ""
+"更新被拒绝,因为推送的一个分支落后于对应的远程分支。如果您并非有意推送\n"
+"该分支,您可以指定要推送的分支或者设置 'push.default' 配置变量为\n"
+"'current' 或 'upstream' 以便只推送当前分支。"
+
+#: builtin/push.c:150
+msgid ""
+"Updates were rejected because a pushed branch tip is behind its remote\n"
+"counterpart. Check out this branch and merge the remote changes\n"
+"(e.g. 'git pull') before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
+msgstr ""
+"更新被拒绝,因为推送的一个分支落后于对应的远程分支。检出该分支并在再次\n"
+"推送之前与远程变更合并(如 'git pull')。\n"
+"详见 'git push --help' 中的 'Note about fast-forwards' 的内容。"
+
+#: builtin/push.c:190
#, c-format
msgid "Pushing to %s\n"
msgstr "推送到 %s\n"
-#: builtin/push.c:135
+#: builtin/push.c:194
#, c-format
msgid "failed to push some refs to '%s'"
msgstr "无法推送一些引用到 '%s'"
-#: builtin/push.c:143
-#, c-format
-msgid ""
-"To prevent you from losing history, non-fast-forward updates were rejected\n"
-"Merge the remote changes (e.g. 'git pull') before pushing again. See the\n"
-"'Note about fast-forwards' section of 'git push --help' for details.\n"
-msgstr ""
-"为了防止您丢失提交历史,非快进式更新被拒绝。\n"
-"再次推送前先与远程变更合并(如 'git pull')。详见\n"
-"'git push --help' 中的 'Note about fast-forwards' 小节。\n"
-
-#: builtin/push.c:160
+#: builtin/push.c:226
#, c-format
msgid "bad repository '%s'"
msgstr "坏的版本库 '%s'"
-#: builtin/push.c:161
+#: builtin/push.c:227
msgid ""
"No configured push destination.\n"
"Either specify the URL from the command-line or configure a remote "
@@ -2908,31 +2969,31 @@ msgstr ""
"\n"
" git push <name>\n"
-#: builtin/push.c:176
+#: builtin/push.c:242
msgid "--all and --tags are incompatible"
msgstr "--all 和 --tags 不兼容"
-#: builtin/push.c:177
+#: builtin/push.c:243
msgid "--all can't be combined with refspecs"
msgstr "--all 不能和引用表达式共用"
-#: builtin/push.c:182
+#: builtin/push.c:248
msgid "--mirror and --tags are incompatible"
msgstr "--mirror 和 --tags 不兼容"
-#: builtin/push.c:183
+#: builtin/push.c:249
msgid "--mirror can't be combined with refspecs"
msgstr "--mirror 不能和引用表达式共用"
-#: builtin/push.c:188
+#: builtin/push.c:254
msgid "--all and --mirror are incompatible"
msgstr "--all 和 --mirror 不兼容"
-#: builtin/push.c:274
+#: builtin/push.c:342
msgid "--delete is incompatible with --all, --mirror and --tags"
msgstr "--delete 与 --all、--mirror 及 --tags 不兼容"
-#: builtin/push.c:276
+#: builtin/push.c:344
msgid "--delete doesn't make sense without any refs"
msgstr "--delete 未接任何引用没有意义"
@@ -3018,20 +3079,20 @@ msgstr "不能对裸版本库进行%s重置"
msgid "Could not reset index file to revision '%s'."
msgstr "不能重置索引文件至版本 '%s'。"
-#: builtin/revert.c:70 builtin/revert.c:91
+#: builtin/revert.c:70 builtin/revert.c:92
#, c-format
msgid "%s: %s cannot be used with %s"
msgstr "%s:%s 不能和 %s 共用"
-#: builtin/revert.c:126
+#: builtin/revert.c:127
msgid "program error"
msgstr "程序错误"
-#: builtin/revert.c:209
+#: builtin/revert.c:213
msgid "revert failed"
msgstr "还原失败"
-#: builtin/revert.c:224
+#: builtin/revert.c:228
msgid "cherry-pick failed"
msgstr "拣选失败"
@@ -3210,15 +3271,15 @@ msgstr "%s:不能更新引用"
msgid "Updated tag '%s' (was %s)\n"
msgstr "已更新tag '%s'(曾为 %s)\n"
-#: git-am.sh:49
+#: git-am.sh:50
msgid "You need to set your committer info first"
msgstr "您需要先设置你的提交者信息"
-#: git-am.sh:136
+#: git-am.sh:137
msgid "Repository lacks necessary blobs to fall back on 3-way merge."
msgstr "版本库缺乏必要的 blob 数据以进行三路合并。"
-#: git-am.sh:147
+#: git-am.sh:154
msgid ""
"Did you hand edit your patch?\n"
"It does not apply to blobs recorded in its index."
@@ -3226,46 +3287,46 @@ msgstr ""
"您是否曾手动编辑过您的补丁?\n"
"无法应用补丁到索引中的数据上。"
-#: git-am.sh:156
+#: git-am.sh:163
msgid "Falling back to patching base and 3-way merge..."
msgstr "回退到补丁基础版本并使用三路合并..."
-#: git-am.sh:268
+#: git-am.sh:275
msgid "Only one StGIT patch series can be applied at once"
msgstr "一次只能有一个 StGIT 补丁队列被应用"
-#: git-am.sh:355
+#: git-am.sh:362
#, sh-format
msgid "Patch format $patch_format is not supported."
msgstr "不支持 $patch_format 补丁格式。"
-#: git-am.sh:357
+#: git-am.sh:364
msgid "Patch format detection failed."
msgstr "补丁格式检测失败。"
-#: git-am.sh:411
+#: git-am.sh:418
msgid "-d option is no longer supported. Do not use."
msgstr "不再支持 -d 选项。不要使用。"
-#: git-am.sh:474
+#: git-am.sh:481
#, sh-format
msgid "previous rebase directory $dotest still exists but mbox given."
msgstr "之前的变基目录 $dotest 仍然存在但给出了mbox。"
-#: git-am.sh:479
+#: git-am.sh:486
msgid "Please make up your mind. --skip or --abort?"
msgstr "请下决心。--skip 或是 --abort ?"
-#: git-am.sh:506
+#: git-am.sh:513
msgid "Resolve operation not in progress, we are not resuming."
msgstr "解决操作未进行,我们不会继续。"
-#: git-am.sh:572
+#: git-am.sh:579
#, sh-format
msgid "Dirty index: cannot apply patches (dirty: $files)"
msgstr "脏的索引:不能应用补丁(脏文件:$files)"
-#: git-am.sh:748
+#: git-am.sh:755
msgid "cannot be interactive without stdin connected to a terminal."
msgstr "标准输入没有和终端关联,不能进行交互式操作。"
@@ -3273,20 +3334,20 @@ msgstr "标准输入没有和终端关联,不能进行交互式操作。"
#. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
#. in your translation. The program will only accept English
#. input at this point.
-#: git-am.sh:759
+#: git-am.sh:766
msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
msgstr "应用?[y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
-#: git-am.sh:795
+#: git-am.sh:802
#, sh-format
msgid "Applying: $FIRSTLINE"
msgstr "正应用:$FIRSTLINE"
-#: git-am.sh:840
+#: git-am.sh:847
msgid "No changes -- Patch already applied."
msgstr "没有变更 -- 补丁已经应用过。"
-#: git-am.sh:866
+#: git-am.sh:873
msgid "applying to an empty history"
msgstr "正应用到一个空历史上"
@@ -3525,166 +3586,166 @@ msgstr "(为恢复数据输入 \"git stash apply\")"
msgid "cannot strip one component off url '$remoteurl'"
msgstr "无法从 url '$remoteurl' 剥离一个组件"
-#: git-submodule.sh:108
+#: git-submodule.sh:109
#, sh-format
-msgid "No submodule mapping found in .gitmodules for path '$path'"
-msgstr "未在 .gitmodules 中发现路径 '$path' 的子模组映射"
+msgid "No submodule mapping found in .gitmodules for path '$sm_path'"
+msgstr "未在 .gitmodules 中发现路径 '$sm_path' 的子模组映射"
-#: git-submodule.sh:149
+#: git-submodule.sh:150
#, sh-format
-msgid "Clone of '$url' into submodule path '$path' failed"
-msgstr "无法克隆 '$url' 到子模组路径 '$path'"
+msgid "Clone of '$url' into submodule path '$sm_path' failed"
+msgstr "无法克隆 '$url' 到子模组路径 '$sm_path'"
-#: git-submodule.sh:159
+#: git-submodule.sh:160
#, sh-format
msgid "Gitdir '$a' is part of the submodule path '$b' or vice versa"
msgstr "Gitdir '$a' 在子模组路径 '$b' 之下或者相反"
-#: git-submodule.sh:247
+#: git-submodule.sh:249
#, sh-format
msgid "repo URL: '$repo' must be absolute or begin with ./|../"
msgstr "版本库URL:'$repo' 必须是绝对路径或以 ./|../ 起始"
-#: git-submodule.sh:264
+#: git-submodule.sh:266
#, sh-format
-msgid "'$path' already exists in the index"
-msgstr "'$path' 已经存在于索引中"
+msgid "'$sm_path' already exists in the index"
+msgstr "'$sm_path' 已经存在于索引中"
-#: git-submodule.sh:281
+#: git-submodule.sh:283
#, sh-format
-msgid "'$path' already exists and is not a valid git repo"
-msgstr "'$path' 已存在且不是一个有效的 git 版本库"
+msgid "'$sm_path' already exists and is not a valid git repo"
+msgstr "'$sm_path' 已存在且不是一个有效的 git 版本库"
-#: git-submodule.sh:295
+#: git-submodule.sh:297
#, sh-format
-msgid "Unable to checkout submodule '$path'"
-msgstr "不能检出子模组 '$path'"
+msgid "Unable to checkout submodule '$sm_path'"
+msgstr "不能检出子模组 '$sm_path'"
-#: git-submodule.sh:300
+#: git-submodule.sh:302
#, sh-format
-msgid "Failed to add submodule '$path'"
-msgstr "无法添加子模组 '$path'"
+msgid "Failed to add submodule '$sm_path'"
+msgstr "无法添加子模组 '$sm_path'"
-#: git-submodule.sh:305
+#: git-submodule.sh:307
#, sh-format
-msgid "Failed to register submodule '$path'"
-msgstr "无法注册子模组 '$path'"
+msgid "Failed to register submodule '$sm_path'"
+msgstr "无法注册子模组 '$sm_path'"
-#: git-submodule.sh:347
+#: git-submodule.sh:349
#, sh-format
-msgid "Entering '$prefix$path'"
-msgstr "正在进入 '$prefix$path'"
+msgid "Entering '$prefix$sm_path'"
+msgstr "正在进入 '$prefix$sm_path'"
-#: git-submodule.sh:359
+#: git-submodule.sh:363
#, sh-format
-msgid "Stopping at '$path'; script returned non-zero status."
-msgstr "停止于 '$path',脚本返回非零值。"
+msgid "Stopping at '$sm_path'; script returned non-zero status."
+msgstr "停止于 '$sm_path',脚本返回非零值。"
-#: git-submodule.sh:401
+#: git-submodule.sh:405
#, sh-format
-msgid "No url found for submodule path '$path' in .gitmodules"
-msgstr "在 .gitmodules 中未找到子模组路径 '$path' 的 url"
+msgid "No url found for submodule path '$sm_path' in .gitmodules"
+msgstr "在 .gitmodules 中未找到子模组路径 '$sm_path' 的 url"
-#: git-submodule.sh:410
+#: git-submodule.sh:414
#, sh-format
-msgid "Failed to register url for submodule path '$path'"
-msgstr "无法为子模组路径 '$path' 注册 url"
+msgid "Failed to register url for submodule path '$sm_path'"
+msgstr "无法为子模组路径 '$sm_path' 注册 url"
-#: git-submodule.sh:418
+#: git-submodule.sh:422
#, sh-format
-msgid "Failed to register update mode for submodule path '$path'"
-msgstr "无法为子模组路径 '$path' 注册更新模式"
+msgid "Failed to register update mode for submodule path '$sm_path'"
+msgstr "无法为子模组路径 '$sm_path' 注册更新模式"
-#: git-submodule.sh:420
+#: git-submodule.sh:424
#, sh-format
-msgid "Submodule '$name' ($url) registered for path '$path'"
-msgstr "子模组 '$name' ($url) 已为路径 '$path' 注册"
+msgid "Submodule '$name' ($url) registered for path '$sm_path'"
+msgstr "子模组 '$name' ($url) 已为路径 '$sm_path' 注册"
-#: git-submodule.sh:519
+#: git-submodule.sh:523
#, sh-format
msgid ""
-"Submodule path '$path' not initialized\n"
+"Submodule path '$sm_path' not initialized\n"
"Maybe you want to use 'update --init'?"
msgstr ""
-"子模组路径 '$path' 没有初始化\n"
+"子模组路径 '$sm_path' 没有初始化\n"
"也许您想用 'update --init'?"
-#: git-submodule.sh:532
+#: git-submodule.sh:536
#, sh-format
-msgid "Unable to find current revision in submodule path '$path'"
-msgstr "无法在子模组路径 '$path' 中找到当前版本"
+msgid "Unable to find current revision in submodule path '$sm_path'"
+msgstr "无法在子模组路径 '$sm_path' 中找到当前版本"
-#: git-submodule.sh:551
+#: git-submodule.sh:555
#, sh-format
-msgid "Unable to fetch in submodule path '$path'"
-msgstr "无法在子模组路径 '$path' 中获取"
+msgid "Unable to fetch in submodule path '$sm_path'"
+msgstr "无法在子模组路径 '$sm_path' 中获取"
-#: git-submodule.sh:565
+#: git-submodule.sh:569
#, sh-format
-msgid "Unable to rebase '$sha1' in submodule path '$path'"
-msgstr "无法在子模组路径 '$path' 中变基 '$sha1'"
+msgid "Unable to rebase '$sha1' in submodule path '$sm_path'"
+msgstr "无法在子模组路径 '$sm_path' 中变基 '$sha1'"
-#: git-submodule.sh:566
+#: git-submodule.sh:570
#, sh-format
-msgid "Submodule path '$path': rebased into '$sha1'"
-msgstr "子模组路径 '$path':变基至 '$sha1'"
+msgid "Submodule path '$sm_path': rebased into '$sha1'"
+msgstr "子模组路径 '$sm_path':变基至 '$sha1'"
-#: git-submodule.sh:571
+#: git-submodule.sh:575
#, sh-format
-msgid "Unable to merge '$sha1' in submodule path '$path'"
-msgstr "无法合并 '$sha1' 到子模组路径 '$path' 中"
+msgid "Unable to merge '$sha1' in submodule path '$sm_path'"
+msgstr "无法合并 '$sha1' 到子模组路径 '$sm_path' 中"
-#: git-submodule.sh:572
+#: git-submodule.sh:576
#, sh-format
-msgid "Submodule path '$path': merged in '$sha1'"
-msgstr "子模组路径 '$path':已合并入 '$sha1'"
+msgid "Submodule path '$sm_path': merged in '$sha1'"
+msgstr "子模组路径 '$sm_path':已合并入 '$sha1'"
-#: git-submodule.sh:577
+#: git-submodule.sh:581
#, sh-format
-msgid "Unable to checkout '$sha1' in submodule path '$path'"
-msgstr "无法在子模组路径 '$path' 中检出 '$sha1'"
+msgid "Unable to checkout '$sha1' in submodule path '$sm_path'"
+msgstr "无法在子模组路径 '$sm_path' 中检出 '$sha1'"
-#: git-submodule.sh:578
+#: git-submodule.sh:582
#, sh-format
-msgid "Submodule path '$path': checked out '$sha1'"
-msgstr "子模组路径 '$path':检出 '$sha1'"
+msgid "Submodule path '$sm_path': checked out '$sha1'"
+msgstr "子模组路径 '$sm_path':检出 '$sha1'"
-#: git-submodule.sh:600 git-submodule.sh:923
+#: git-submodule.sh:604 git-submodule.sh:927
#, sh-format
-msgid "Failed to recurse into submodule path '$path'"
-msgstr "无法递归进子模组路径 '$path'"
+msgid "Failed to recurse into submodule path '$sm_path'"
+msgstr "无法递归进子模组路径 '$sm_path'"
-#: git-submodule.sh:708
+#: git-submodule.sh:712
msgid "--"
msgstr "--"
# 译者:注意保持前导空格
-#: git-submodule.sh:766
+#: git-submodule.sh:770
#, sh-format
msgid " Warn: $name doesn't contain commit $sha1_src"
msgstr " 警告:$name 未包含提交 $sha1_src"
# 译者:注意保持前导空格
-#: git-submodule.sh:769
+#: git-submodule.sh:773
#, sh-format
msgid " Warn: $name doesn't contain commit $sha1_dst"
msgstr " 警告:$name 未包含提交 $sha1_dst"
# 译者:注意保持前导空格
-#: git-submodule.sh:772
+#: git-submodule.sh:776
#, sh-format
msgid " Warn: $name doesn't contain commits $sha1_src and $sha1_dst"
msgstr " 警告:$name 未包含提交 $sha1_src 和 $sha1_dst"
-#: git-submodule.sh:797
+#: git-submodule.sh:801
msgid "blob"
msgstr "blob"
-#: git-submodule.sh:798
+#: git-submodule.sh:802
msgid "submodule"
msgstr "子模组"
-#: git-submodule.sh:969
+#: git-submodule.sh:973
#, sh-format
msgid "Synchronizing submodule url for '$name'"
msgstr "为 '$name' 同步子模组 url"
diff --git a/read-cache.c b/read-cache.c
index 6c8f395836..ef355cc9a8 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -12,6 +12,8 @@
#include "commit.h"
#include "blob.h"
#include "resolve-undo.h"
+#include "strbuf.h"
+#include "varint.h"
static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
@@ -1179,15 +1181,74 @@ static struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int reall
return refresh_cache_ent(&the_index, ce, really, NULL, NULL);
}
+
+/*****************************************************************
+ * Index File I/O
+ *****************************************************************/
+
+#define INDEX_FORMAT_DEFAULT 3
+
+/*
+ * dev/ino/uid/gid/size are also just tracked to the low 32 bits
+ * Again - this is just a (very strong in practice) heuristic that
+ * the inode hasn't changed.
+ *
+ * We save the fields in big-endian order to allow using the
+ * index file over NFS transparently.
+ */
+struct ondisk_cache_entry {
+ struct cache_time ctime;
+ struct cache_time mtime;
+ unsigned int dev;
+ unsigned int ino;
+ unsigned int mode;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int size;
+ unsigned char sha1[20];
+ unsigned short flags;
+ char name[FLEX_ARRAY]; /* more */
+};
+
+/*
+ * This struct is used when CE_EXTENDED bit is 1
+ * The struct must match ondisk_cache_entry exactly from
+ * ctime till flags
+ */
+struct ondisk_cache_entry_extended {
+ struct cache_time ctime;
+ struct cache_time mtime;
+ unsigned int dev;
+ unsigned int ino;
+ unsigned int mode;
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int size;
+ unsigned char sha1[20];
+ unsigned short flags;
+ unsigned short flags2;
+ char name[FLEX_ARRAY]; /* more */
+};
+
+/* These are only used for v3 or lower */
+#define align_flex_name(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
+#define ondisk_cache_entry_size(len) align_flex_name(ondisk_cache_entry,len)
+#define ondisk_cache_entry_extended_size(len) align_flex_name(ondisk_cache_entry_extended,len)
+#define ondisk_ce_size(ce) (((ce)->ce_flags & CE_EXTENDED) ? \
+ ondisk_cache_entry_extended_size(ce_namelen(ce)) : \
+ ondisk_cache_entry_size(ce_namelen(ce)))
+
static int verify_hdr(struct cache_header *hdr, unsigned long size)
{
git_SHA_CTX c;
unsigned char sha1[20];
+ int hdr_version;
if (hdr->hdr_signature != htonl(CACHE_SIGNATURE))
return error("bad signature");
- if (hdr->hdr_version != htonl(2) && hdr->hdr_version != htonl(3))
- return error("bad index version");
+ hdr_version = ntohl(hdr->hdr_version);
+ if (hdr_version < 2 || 4 < hdr_version)
+ return error("bad index version %d", hdr_version);
git_SHA1_Init(&c);
git_SHA1_Update(&c, hdr, size - 20);
git_SHA1_Final(sha1, &c);
@@ -1221,7 +1282,74 @@ int read_index(struct index_state *istate)
return read_index_from(istate, get_index_file());
}
-static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk)
+#ifndef NEEDS_ALIGNED_ACCESS
+#define ntoh_s(var) ntohs(var)
+#define ntoh_l(var) ntohl(var)
+#else
+static inline uint16_t ntoh_s_force_align(void *p)
+{
+ uint16_t x;
+ memcpy(&x, p, sizeof(x));
+ return ntohs(x);
+}
+static inline uint32_t ntoh_l_force_align(void *p)
+{
+ uint32_t x;
+ memcpy(&x, p, sizeof(x));
+ return ntohl(x);
+}
+#define ntoh_s(var) ntoh_s_force_align(&(var))
+#define ntoh_l(var) ntoh_l_force_align(&(var))
+#endif
+
+static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *ondisk,
+ unsigned int flags,
+ const char *name,
+ size_t len)
+{
+ struct cache_entry *ce = xmalloc(cache_entry_size(len));
+
+ ce->ce_ctime.sec = ntoh_l(ondisk->ctime.sec);
+ ce->ce_mtime.sec = ntoh_l(ondisk->mtime.sec);
+ ce->ce_ctime.nsec = ntoh_l(ondisk->ctime.nsec);
+ ce->ce_mtime.nsec = ntoh_l(ondisk->mtime.nsec);
+ ce->ce_dev = ntoh_l(ondisk->dev);
+ ce->ce_ino = ntoh_l(ondisk->ino);
+ ce->ce_mode = ntoh_l(ondisk->mode);
+ ce->ce_uid = ntoh_l(ondisk->uid);
+ ce->ce_gid = ntoh_l(ondisk->gid);
+ ce->ce_size = ntoh_l(ondisk->size);
+ ce->ce_flags = flags;
+ hashcpy(ce->sha1, ondisk->sha1);
+ memcpy(ce->name, name, len);
+ ce->name[len] = '\0';
+ return ce;
+}
+
+/*
+ * Adjacent cache entries tend to share the leading paths, so it makes
+ * sense to only store the differences in later entries. In the v4
+ * on-disk format of the index, each on-disk cache entry stores the
+ * number of bytes to be stripped from the end of the previous name,
+ * and the bytes to append to the result, to come up with its name.
+ */
+static unsigned long expand_name_field(struct strbuf *name, const char *cp_)
+{
+ const unsigned char *ep, *cp = (const unsigned char *)cp_;
+ size_t len = decode_varint(&cp);
+
+ if (name->len < len)
+ die("malformed name field in the index");
+ strbuf_remove(name, name->len - len, len);
+ for (ep = cp; *ep; ep++)
+ ; /* find the end */
+ strbuf_add(name, cp, ep - cp);
+ return (const char *)ep + 1 - cp_;
+}
+
+static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk,
+ unsigned long *ent_size,
+ struct strbuf *previous_name)
{
struct cache_entry *ce;
size_t len;
@@ -1229,14 +1357,14 @@ static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk)
unsigned int flags;
/* On-disk flags are just 16 bits */
- flags = ntohs(ondisk->flags);
+ flags = ntoh_s(ondisk->flags);
len = flags & CE_NAMEMASK;
if (flags & CE_EXTENDED) {
struct ondisk_cache_entry_extended *ondisk2;
int extended_flags;
ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
- extended_flags = ntohs(ondisk2->flags2) << 16;
+ extended_flags = ntoh_s(ondisk2->flags2) << 16;
/* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
if (extended_flags & ~CE_EXTENDED_FLAGS)
die("Unknown index entry format %08x", extended_flags);
@@ -1246,27 +1374,22 @@ static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk)
else
name = ondisk->name;
- if (len == CE_NAMEMASK)
- len = strlen(name);
-
- ce = xmalloc(cache_entry_size(len));
-
- ce->ce_ctime.sec = ntohl(ondisk->ctime.sec);
- ce->ce_mtime.sec = ntohl(ondisk->mtime.sec);
- ce->ce_ctime.nsec = ntohl(ondisk->ctime.nsec);
- ce->ce_mtime.nsec = ntohl(ondisk->mtime.nsec);
- ce->ce_dev = ntohl(ondisk->dev);
- ce->ce_ino = ntohl(ondisk->ino);
- ce->ce_mode = ntohl(ondisk->mode);
- ce->ce_uid = ntohl(ondisk->uid);
- ce->ce_gid = ntohl(ondisk->gid);
- ce->ce_size = ntohl(ondisk->size);
- ce->ce_flags = flags;
-
- hashcpy(ce->sha1, ondisk->sha1);
-
- memcpy(ce->name, name, len);
- ce->name[len] = '\0';
+ if (!previous_name) {
+ /* v3 and earlier */
+ if (len == CE_NAMEMASK)
+ len = strlen(name);
+ ce = cache_entry_from_ondisk(ondisk, flags, name, len);
+
+ *ent_size = ondisk_ce_size(ce);
+ } else {
+ unsigned long consumed;
+ consumed = expand_name_field(previous_name, name);
+ ce = cache_entry_from_ondisk(ondisk, flags,
+ previous_name->buf,
+ previous_name->len);
+
+ *ent_size = (name - ((char *)ondisk)) + consumed;
+ }
return ce;
}
@@ -1279,6 +1402,7 @@ int read_index_from(struct index_state *istate, const char *path)
struct cache_header *hdr;
void *mmap;
size_t mmap_size;
+ struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
errno = EBUSY;
if (istate->initialized)
@@ -1311,22 +1435,30 @@ int read_index_from(struct index_state *istate, const char *path)
if (verify_hdr(hdr, mmap_size) < 0)
goto unmap;
+ istate->version = ntohl(hdr->hdr_version);
istate->cache_nr = ntohl(hdr->hdr_entries);
istate->cache_alloc = alloc_nr(istate->cache_nr);
istate->cache = xcalloc(istate->cache_alloc, sizeof(struct cache_entry *));
istate->initialized = 1;
+ if (istate->version == 4)
+ previous_name = &previous_name_buf;
+ else
+ previous_name = NULL;
+
src_offset = sizeof(*hdr);
for (i = 0; i < istate->cache_nr; i++) {
struct ondisk_cache_entry *disk_ce;
struct cache_entry *ce;
+ unsigned long consumed;
disk_ce = (struct ondisk_cache_entry *)((char *)mmap + src_offset);
- ce = create_from_disk(disk_ce);
+ ce = create_from_disk(disk_ce, &consumed, previous_name);
set_index_entry(istate, i, ce);
- src_offset += ondisk_ce_size(ce);
+ src_offset += consumed;
}
+ strbuf_release(&previous_name_buf);
istate->timestamp.sec = st.st_mtime;
istate->timestamp.nsec = ST_MTIME_NSEC(st);
@@ -1510,13 +1642,10 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
}
}
-static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce)
+/* Copy miscellaneous fields but not the name */
+static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
+ struct cache_entry *ce)
{
- int size = ondisk_ce_size(ce);
- struct ondisk_cache_entry *ondisk = xcalloc(1, size);
- char *name;
- int result;
-
ondisk->ctime.sec = htonl(ce->ce_ctime.sec);
ondisk->mtime.sec = htonl(ce->ce_mtime.sec);
ondisk->ctime.nsec = htonl(ce->ce_ctime.nsec);
@@ -1533,11 +1662,52 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce)
struct ondisk_cache_entry_extended *ondisk2;
ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
ondisk2->flags2 = htons((ce->ce_flags & CE_EXTENDED_FLAGS) >> 16);
- name = ondisk2->name;
+ return ondisk2->name;
+ }
+ else {
+ return ondisk->name;
+ }
+}
+
+static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce,
+ struct strbuf *previous_name)
+{
+ int size;
+ struct ondisk_cache_entry *ondisk;
+ char *name;
+ int result;
+
+ if (!previous_name) {
+ size = ondisk_ce_size(ce);
+ ondisk = xcalloc(1, size);
+ name = copy_cache_entry_to_ondisk(ondisk, ce);
+ memcpy(name, ce->name, ce_namelen(ce));
+ } else {
+ int common, to_remove, prefix_size;
+ unsigned char to_remove_vi[16];
+ for (common = 0;
+ (ce->name[common] &&
+ common < previous_name->len &&
+ ce->name[common] == previous_name->buf[common]);
+ common++)
+ ; /* still matching */
+ to_remove = previous_name->len - common;
+ prefix_size = encode_varint(to_remove, to_remove_vi);
+
+ if (ce->ce_flags & CE_EXTENDED)
+ size = offsetof(struct ondisk_cache_entry_extended, name);
+ else
+ size = offsetof(struct ondisk_cache_entry, name);
+ size += prefix_size + (ce_namelen(ce) - common + 1);
+
+ ondisk = xcalloc(1, size);
+ name = copy_cache_entry_to_ondisk(ondisk, ce);
+ memcpy(name, to_remove_vi, prefix_size);
+ memcpy(name + prefix_size, ce->name + common, ce_namelen(ce) - common);
+
+ strbuf_splice(previous_name, common, to_remove,
+ ce->name + common, ce_namelen(ce) - common);
}
- else
- name = ondisk->name;
- memcpy(name, ce->name, ce_namelen(ce));
result = ce_write(c, fd, ondisk, size);
free(ondisk);
@@ -1573,10 +1743,11 @@ int write_index(struct index_state *istate, int newfd)
{
git_SHA_CTX c;
struct cache_header hdr;
- int i, err, removed, extended;
+ int i, err, removed, extended, hdr_version;
struct cache_entry **cache = istate->cache;
int entries = istate->cache_nr;
struct stat st;
+ struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
for (i = removed = extended = 0; i < entries; i++) {
if (cache[i]->ce_flags & CE_REMOVE)
@@ -1590,24 +1761,34 @@ int write_index(struct index_state *istate, int newfd)
}
}
+ if (!istate->version)
+ istate->version = INDEX_FORMAT_DEFAULT;
+
+ /* demote version 3 to version 2 when the latter suffices */
+ if (istate->version == 3 || istate->version == 2)
+ istate->version = extended ? 3 : 2;
+
+ hdr_version = istate->version;
+
hdr.hdr_signature = htonl(CACHE_SIGNATURE);
- /* for extended format, increase version so older git won't try to read it */
- hdr.hdr_version = htonl(extended ? 3 : 2);
+ hdr.hdr_version = htonl(hdr_version);
hdr.hdr_entries = htonl(entries - removed);
git_SHA1_Init(&c);
if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
return -1;
+ previous_name = (hdr_version == 4) ? &previous_name_buf : NULL;
for (i = 0; i < entries; i++) {
struct cache_entry *ce = cache[i];
if (ce->ce_flags & CE_REMOVE)
continue;
if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce))
ce_smudge_racily_clean_entry(ce);
- if (ce_write_entry(&c, newfd, ce) < 0)
+ if (ce_write_entry(&c, newfd, ce, previous_name) < 0)
return -1;
}
+ strbuf_release(&previous_name_buf);
/* Write extension data here */
if (istate->cache_tree) {
diff --git a/refs.c b/refs.c
index c9f6835351..09322fede0 100644
--- a/refs.c
+++ b/refs.c
@@ -4,18 +4,109 @@
#include "tag.h"
#include "dir.h"
-/* ISSYMREF=0x01, ISPACKED=0x02 and ISBROKEN=0x04 are public interfaces */
-#define REF_KNOWS_PEELED 0x10
+/*
+ * Make sure "ref" is something reasonable to have under ".git/refs/";
+ * We do not like it if:
+ *
+ * - any path component of it begins with ".", or
+ * - it has double dots "..", or
+ * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
+ * - it ends with a "/".
+ * - it ends with ".lock"
+ * - it contains a "\" (backslash)
+ */
-struct ref_entry {
- unsigned char flag; /* ISSYMREF? ISPACKED? */
+/* Return true iff ch is not allowed in reference names. */
+static inline int bad_ref_char(int ch)
+{
+ if (((unsigned) ch) <= ' ' || ch == 0x7f ||
+ ch == '~' || ch == '^' || ch == ':' || ch == '\\')
+ return 1;
+ /* 2.13 Pattern Matching Notation */
+ if (ch == '*' || ch == '?' || ch == '[') /* Unsupported */
+ return 1;
+ return 0;
+}
+
+/*
+ * Try to read one refname component from the front of refname. Return
+ * the length of the component found, or -1 if the component is not
+ * legal.
+ */
+static int check_refname_component(const char *refname, int flags)
+{
+ const char *cp;
+ char last = '\0';
+
+ for (cp = refname; ; cp++) {
+ char ch = *cp;
+ if (ch == '\0' || ch == '/')
+ break;
+ if (bad_ref_char(ch))
+ return -1; /* Illegal character in refname. */
+ if (last == '.' && ch == '.')
+ return -1; /* Refname contains "..". */
+ if (last == '@' && ch == '{')
+ return -1; /* Refname contains "@{". */
+ last = ch;
+ }
+ if (cp == refname)
+ return 0; /* Component has zero length. */
+ if (refname[0] == '.') {
+ if (!(flags & REFNAME_DOT_COMPONENT))
+ return -1; /* Component starts with '.'. */
+ /*
+ * Even if leading dots are allowed, don't allow "."
+ * as a component (".." is prevented by a rule above).
+ */
+ if (refname[1] == '\0')
+ return -1; /* Component equals ".". */
+ }
+ if (cp - refname >= 5 && !memcmp(cp - 5, ".lock", 5))
+ return -1; /* Refname ends with ".lock". */
+ return cp - refname;
+}
+
+int check_refname_format(const char *refname, int flags)
+{
+ int component_len, component_count = 0;
+
+ while (1) {
+ /* We are at the start of a path component. */
+ component_len = check_refname_component(refname, flags);
+ if (component_len <= 0) {
+ if ((flags & REFNAME_REFSPEC_PATTERN) &&
+ refname[0] == '*' &&
+ (refname[1] == '\0' || refname[1] == '/')) {
+ /* Accept one wildcard as a full refname component. */
+ flags &= ~REFNAME_REFSPEC_PATTERN;
+ component_len = 1;
+ } else {
+ return -1;
+ }
+ }
+ component_count++;
+ if (refname[component_len] == '\0')
+ break;
+ /* Skip to next component. */
+ refname += component_len + 1;
+ }
+
+ if (refname[component_len - 1] == '.')
+ return -1; /* Refname ends with '.'. */
+ if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
+ return -1; /* Refname has only one component. */
+ return 0;
+}
+
+struct ref_entry;
+
+struct ref_value {
unsigned char sha1[20];
unsigned char peeled[20];
- /* The full name of the reference (e.g., "refs/heads/master"): */
- char name[FLEX_ARRAY];
};
-struct ref_array {
+struct ref_dir {
int nr, alloc;
/*
@@ -26,41 +117,59 @@ struct ref_array {
*/
int sorted;
- struct ref_entry **refs;
+ struct ref_entry **entries;
};
+/* ISSYMREF=0x01, ISPACKED=0x02, and ISBROKEN=0x04 are public interfaces */
+#define REF_KNOWS_PEELED 0x08
+#define REF_DIR 0x10
+
/*
- * Parse one line from a packed-refs file. Write the SHA1 to sha1.
- * Return a pointer to the refname within the line (null-terminated),
- * or NULL if there was a problem.
+ * A ref_entry represents either a reference or a "subdirectory" of
+ * references. Each directory in the reference namespace is
+ * represented by a ref_entry with (flags & REF_DIR) set and
+ * containing a subdir member that holds the entries in that
+ * directory. References are represented by a ref_entry with (flags &
+ * REF_DIR) unset and a value member that describes the reference's
+ * value. The flag member is at the ref_entry level, but it is also
+ * needed to interpret the contents of the value field (in other
+ * words, a ref_value object is not very much use without the
+ * enclosing ref_entry).
+ *
+ * Reference names cannot end with slash and directories' names are
+ * always stored with a trailing slash (except for the top-level
+ * directory, which is always denoted by ""). This has two nice
+ * consequences: (1) when the entries in each subdir are sorted
+ * lexicographically by name (as they usually are), the references in
+ * a whole tree can be generated in lexicographic order by traversing
+ * the tree in left-to-right, depth-first order; (2) the names of
+ * references and subdirectories cannot conflict, and therefore the
+ * presence of an empty subdirectory does not block the creation of a
+ * similarly-named reference. (The fact that reference names with the
+ * same leading components can conflict *with each other* is a
+ * separate issue that is regulated by is_refname_available().)
+ *
+ * Please note that the name field contains the fully-qualified
+ * reference (or subdirectory) name. Space could be saved by only
+ * storing the relative names. But that would require the full names
+ * to be generated on the fly when iterating in do_for_each_ref(), and
+ * would break callback functions, who have always been able to assume
+ * that the name strings that they are passed will not be freed during
+ * the iteration.
*/
-static const char *parse_ref_line(char *line, unsigned char *sha1)
-{
+struct ref_entry {
+ unsigned char flag; /* ISSYMREF? ISPACKED? */
+ union {
+ struct ref_value value; /* if not (flags&REF_DIR) */
+ struct ref_dir subdir; /* if (flags&REF_DIR) */
+ } u;
/*
- * 42: the answer to everything.
- *
- * In this case, it happens to be the answer to
- * 40 (length of sha1 hex representation)
- * +1 (space in between hex and name)
- * +1 (newline at the end of the line)
+ * The full name of the reference (e.g., "refs/heads/master")
+ * or the full name of the directory with a trailing slash
+ * (e.g., "refs/heads/"):
*/
- int len = strlen(line) - 42;
-
- if (len <= 0)
- return NULL;
- if (get_sha1_hex(line, sha1) < 0)
- return NULL;
- if (!isspace(line[40]))
- return NULL;
- line += 41;
- if (isspace(*line))
- return NULL;
- if (line[len] != '\n')
- return NULL;
- line[len] = 0;
-
- return line;
-}
+ char name[FLEX_ARRAY];
+};
static struct ref_entry *create_ref_entry(const char *refname,
const unsigned char *sha1, int flag,
@@ -74,18 +183,59 @@ static struct ref_entry *create_ref_entry(const char *refname,
die("Reference has invalid format: '%s'", refname);
len = strlen(refname) + 1;
ref = xmalloc(sizeof(struct ref_entry) + len);
- hashcpy(ref->sha1, sha1);
- hashclr(ref->peeled);
+ hashcpy(ref->u.value.sha1, sha1);
+ hashclr(ref->u.value.peeled);
memcpy(ref->name, refname, len);
ref->flag = flag;
return ref;
}
-/* Add a ref_entry to the end of the ref_array (unsorted). */
-static void add_ref(struct ref_array *refs, struct ref_entry *ref)
+static void clear_ref_dir(struct ref_dir *dir);
+
+static void free_ref_entry(struct ref_entry *entry)
+{
+ if (entry->flag & REF_DIR)
+ clear_ref_dir(&entry->u.subdir);
+ free(entry);
+}
+
+/*
+ * Add a ref_entry to the end of dir (unsorted). Entry is always
+ * stored directly in dir; no recursion into subdirectories is
+ * done.
+ */
+static void add_entry_to_dir(struct ref_dir *dir, struct ref_entry *entry)
{
- ALLOC_GROW(refs->refs, refs->nr + 1, refs->alloc);
- refs->refs[refs->nr++] = ref;
+ ALLOC_GROW(dir->entries, dir->nr + 1, dir->alloc);
+ dir->entries[dir->nr++] = entry;
+}
+
+/*
+ * Clear and free all entries in dir, recursively.
+ */
+static void clear_ref_dir(struct ref_dir *dir)
+{
+ int i;
+ for (i = 0; i < dir->nr; i++)
+ free_ref_entry(dir->entries[i]);
+ free(dir->entries);
+ dir->sorted = dir->nr = dir->alloc = 0;
+ dir->entries = NULL;
+}
+
+/*
+ * Create a struct ref_entry object for the specified dirname.
+ * dirname is the name of the directory with a trailing slash (e.g.,
+ * "refs/heads/") or "" for the top-level directory.
+ */
+static struct ref_entry *create_dir_entry(const char *dirname)
+{
+ struct ref_entry *direntry;
+ int len = strlen(dirname);
+ direntry = xcalloc(1, sizeof(struct ref_entry) + len + 1);
+ memcpy(direntry->name, dirname, len + 1);
+ direntry->flag = REF_DIR;
+ return direntry;
}
static int ref_entry_cmp(const void *a, const void *b)
@@ -95,6 +245,102 @@ static int ref_entry_cmp(const void *a, const void *b)
return strcmp(one->name, two->name);
}
+static void sort_ref_dir(struct ref_dir *dir);
+
+/*
+ * Return the entry with the given refname from the ref_dir
+ * (non-recursively), sorting dir if necessary. Return NULL if no
+ * such entry is found.
+ */
+static struct ref_entry *search_ref_dir(struct ref_dir *dir, const char *refname)
+{
+ struct ref_entry *e, **r;
+ int len;
+
+ if (refname == NULL || !dir->nr)
+ return NULL;
+
+ sort_ref_dir(dir);
+
+ len = strlen(refname) + 1;
+ e = xmalloc(sizeof(struct ref_entry) + len);
+ memcpy(e->name, refname, len);
+
+ r = bsearch(&e, dir->entries, dir->nr, sizeof(*dir->entries), ref_entry_cmp);
+
+ free(e);
+
+ if (r == NULL)
+ return NULL;
+
+ return *r;
+}
+
+/*
+ * If refname is a reference name, find the ref_dir within the dir
+ * tree that should hold refname. If refname is a directory name
+ * (i.e., ends in '/'), then return that ref_dir itself. dir must
+ * represent the top-level directory. Sort ref_dirs and recurse into
+ * subdirectories as necessary. If mkdir is set, then create any
+ * missing directories; otherwise, return NULL if the desired
+ * directory cannot be found.
+ */
+static struct ref_dir *find_containing_dir(struct ref_dir *dir,
+ const char *refname, int mkdir)
+{
+ char *refname_copy = xstrdup(refname);
+ char *slash;
+ struct ref_entry *entry;
+ for (slash = strchr(refname_copy, '/'); slash; slash = strchr(slash + 1, '/')) {
+ char tmp = slash[1];
+ slash[1] = '\0';
+ entry = search_ref_dir(dir, refname_copy);
+ if (!entry) {
+ if (!mkdir) {
+ dir = NULL;
+ break;
+ }
+ entry = create_dir_entry(refname_copy);
+ add_entry_to_dir(dir, entry);
+ }
+ slash[1] = tmp;
+ assert(entry->flag & REF_DIR);
+ dir = &entry->u.subdir;
+ }
+
+ free(refname_copy);
+ return dir;
+}
+
+/*
+ * Find the value entry with the given name in dir, sorting ref_dirs
+ * and recursing into subdirectories as necessary. If the name is not
+ * found or it corresponds to a directory entry, return NULL.
+ */
+static struct ref_entry *find_ref(struct ref_dir *dir, const char *refname)
+{
+ struct ref_entry *entry;
+ dir = find_containing_dir(dir, refname, 0);
+ if (!dir)
+ return NULL;
+ entry = search_ref_dir(dir, refname);
+ return (entry && !(entry->flag & REF_DIR)) ? entry : NULL;
+}
+
+/*
+ * Add a ref_entry to the ref_dir (unsorted), recursing into
+ * subdirectories as necessary. dir must represent the top-level
+ * directory. Return 0 on success.
+ */
+static int add_ref(struct ref_dir *dir, struct ref_entry *ref)
+{
+ dir = find_containing_dir(dir, ref->name, 1);
+ if (!dir)
+ return -1;
+ add_entry_to_dir(dir, ref);
+ return 0;
+}
+
/*
* Emit a warning and return true iff ref1 and ref2 have the same name
* and the same sha1. Die if they have the same name but different
@@ -102,69 +348,242 @@ static int ref_entry_cmp(const void *a, const void *b)
*/
static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2)
{
- if (!strcmp(ref1->name, ref2->name)) {
- /* Duplicate name; make sure that the SHA1s match: */
- if (hashcmp(ref1->sha1, ref2->sha1))
- die("Duplicated ref, and SHA1s don't match: %s",
- ref1->name);
- warning("Duplicated ref: %s", ref1->name);
- return 1;
- } else {
+ if (strcmp(ref1->name, ref2->name))
return 0;
- }
+
+ /* Duplicate name; make sure that they don't conflict: */
+
+ if ((ref1->flag & REF_DIR) || (ref2->flag & REF_DIR))
+ /* This is impossible by construction */
+ die("Reference directory conflict: %s", ref1->name);
+
+ if (hashcmp(ref1->u.value.sha1, ref2->u.value.sha1))
+ die("Duplicated ref, and SHA1s don't match: %s", ref1->name);
+
+ warning("Duplicated ref: %s", ref1->name);
+ return 1;
}
/*
- * Sort the entries in array (if they are not already sorted).
+ * Sort the entries in dir non-recursively (if they are not already
+ * sorted) and remove any duplicate entries.
*/
-static void sort_ref_array(struct ref_array *array)
+static void sort_ref_dir(struct ref_dir *dir)
{
int i, j;
+ struct ref_entry *last = NULL;
/*
* This check also prevents passing a zero-length array to qsort(),
* which is a problem on some platforms.
*/
- if (array->sorted == array->nr)
+ if (dir->sorted == dir->nr)
return;
- qsort(array->refs, array->nr, sizeof(*array->refs), ref_entry_cmp);
+ qsort(dir->entries, dir->nr, sizeof(*dir->entries), ref_entry_cmp);
- /* Remove any duplicates from the ref_array */
- i = 0;
- for (j = 1; j < array->nr; j++) {
- if (is_dup_ref(array->refs[i], array->refs[j])) {
- free(array->refs[j]);
- continue;
+ /* Remove any duplicates: */
+ for (i = 0, j = 0; j < dir->nr; j++) {
+ struct ref_entry *entry = dir->entries[j];
+ if (last && is_dup_ref(last, entry))
+ free_ref_entry(entry);
+ else
+ last = dir->entries[i++] = entry;
+ }
+ dir->sorted = dir->nr = i;
+}
+
+#define DO_FOR_EACH_INCLUDE_BROKEN 01
+
+static struct ref_entry *current_ref;
+
+static int do_one_ref(const char *base, each_ref_fn fn, int trim,
+ int flags, void *cb_data, struct ref_entry *entry)
+{
+ int retval;
+ if (prefixcmp(entry->name, base))
+ return 0;
+
+ if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
+ if (entry->flag & REF_ISBROKEN)
+ return 0; /* ignore broken refs e.g. dangling symref */
+ if (!has_sha1_file(entry->u.value.sha1)) {
+ error("%s does not point to a valid object!", entry->name);
+ return 0;
}
- array->refs[++i] = array->refs[j];
}
- array->sorted = array->nr = i + 1;
+ current_ref = entry;
+ retval = fn(entry->name + trim, entry->u.value.sha1, entry->flag, cb_data);
+ current_ref = NULL;
+ return retval;
}
-static struct ref_entry *search_ref_array(struct ref_array *array, const char *refname)
+/*
+ * Call fn for each reference in dir that has index in the range
+ * offset <= index < dir->nr. Recurse into subdirectories that are in
+ * that index range, sorting them before iterating. This function
+ * does not sort dir itself; it should be sorted beforehand.
+ */
+static int do_for_each_ref_in_dir(struct ref_dir *dir, int offset,
+ const char *base,
+ each_ref_fn fn, int trim, int flags, void *cb_data)
{
- struct ref_entry *e, **r;
- int len;
+ int i;
+ assert(dir->sorted == dir->nr);
+ for (i = offset; i < dir->nr; i++) {
+ struct ref_entry *entry = dir->entries[i];
+ int retval;
+ if (entry->flag & REF_DIR) {
+ sort_ref_dir(&entry->u.subdir);
+ retval = do_for_each_ref_in_dir(&entry->u.subdir, 0,
+ base, fn, trim, flags, cb_data);
+ } else {
+ retval = do_one_ref(base, fn, trim, flags, cb_data, entry);
+ }
+ if (retval)
+ return retval;
+ }
+ return 0;
+}
- if (refname == NULL)
- return NULL;
+/*
+ * Call fn for each reference in the union of dir1 and dir2, in order
+ * by refname. Recurse into subdirectories. If a value entry appears
+ * in both dir1 and dir2, then only process the version that is in
+ * dir2. The input dirs must already be sorted, but subdirs will be
+ * sorted as needed.
+ */
+static int do_for_each_ref_in_dirs(struct ref_dir *dir1,
+ struct ref_dir *dir2,
+ const char *base, each_ref_fn fn, int trim,
+ int flags, void *cb_data)
+{
+ int retval;
+ int i1 = 0, i2 = 0;
- if (!array->nr)
- return NULL;
- sort_ref_array(array);
- len = strlen(refname) + 1;
- e = xmalloc(sizeof(struct ref_entry) + len);
- memcpy(e->name, refname, len);
+ assert(dir1->sorted == dir1->nr);
+ assert(dir2->sorted == dir2->nr);
+ while (1) {
+ struct ref_entry *e1, *e2;
+ int cmp;
+ if (i1 == dir1->nr) {
+ return do_for_each_ref_in_dir(dir2, i2,
+ base, fn, trim, flags, cb_data);
+ }
+ if (i2 == dir2->nr) {
+ return do_for_each_ref_in_dir(dir1, i1,
+ base, fn, trim, flags, cb_data);
+ }
+ e1 = dir1->entries[i1];
+ e2 = dir2->entries[i2];
+ cmp = strcmp(e1->name, e2->name);
+ if (cmp == 0) {
+ if ((e1->flag & REF_DIR) && (e2->flag & REF_DIR)) {
+ /* Both are directories; descend them in parallel. */
+ sort_ref_dir(&e1->u.subdir);
+ sort_ref_dir(&e2->u.subdir);
+ retval = do_for_each_ref_in_dirs(
+ &e1->u.subdir, &e2->u.subdir,
+ base, fn, trim, flags, cb_data);
+ i1++;
+ i2++;
+ } else if (!(e1->flag & REF_DIR) && !(e2->flag & REF_DIR)) {
+ /* Both are references; ignore the one from dir1. */
+ retval = do_one_ref(base, fn, trim, flags, cb_data, e2);
+ i1++;
+ i2++;
+ } else {
+ die("conflict between reference and directory: %s",
+ e1->name);
+ }
+ } else {
+ struct ref_entry *e;
+ if (cmp < 0) {
+ e = e1;
+ i1++;
+ } else {
+ e = e2;
+ i2++;
+ }
+ if (e->flag & REF_DIR) {
+ sort_ref_dir(&e->u.subdir);
+ retval = do_for_each_ref_in_dir(
+ &e->u.subdir, 0,
+ base, fn, trim, flags, cb_data);
+ } else {
+ retval = do_one_ref(base, fn, trim, flags, cb_data, e);
+ }
+ }
+ if (retval)
+ return retval;
+ }
+ if (i1 < dir1->nr)
+ return do_for_each_ref_in_dir(dir1, i1,
+ base, fn, trim, flags, cb_data);
+ if (i2 < dir2->nr)
+ return do_for_each_ref_in_dir(dir2, i2,
+ base, fn, trim, flags, cb_data);
+ return 0;
+}
- r = bsearch(&e, array->refs, array->nr, sizeof(*array->refs), ref_entry_cmp);
+/*
+ * Return true iff refname1 and refname2 conflict with each other.
+ * Two reference names conflict if one of them exactly matches the
+ * leading components of the other; e.g., "foo/bar" conflicts with
+ * both "foo" and with "foo/bar/baz" but not with "foo/bar" or
+ * "foo/barbados".
+ */
+static int names_conflict(const char *refname1, const char *refname2)
+{
+ for (; *refname1 && *refname1 == *refname2; refname1++, refname2++)
+ ;
+ return (*refname1 == '\0' && *refname2 == '/')
+ || (*refname1 == '/' && *refname2 == '\0');
+}
- free(e);
+struct name_conflict_cb {
+ const char *refname;
+ const char *oldrefname;
+ const char *conflicting_refname;
+};
- if (r == NULL)
- return NULL;
+static int name_conflict_fn(const char *existingrefname, const unsigned char *sha1,
+ int flags, void *cb_data)
+{
+ struct name_conflict_cb *data = (struct name_conflict_cb *)cb_data;
+ if (data->oldrefname && !strcmp(data->oldrefname, existingrefname))
+ return 0;
+ if (names_conflict(data->refname, existingrefname)) {
+ data->conflicting_refname = existingrefname;
+ return 1;
+ }
+ return 0;
+}
- return *r;
+/*
+ * Return true iff a reference named refname could be created without
+ * conflicting with the name of an existing reference in array. If
+ * oldrefname is non-NULL, ignore potential conflicts with oldrefname
+ * (e.g., because oldrefname is scheduled for deletion in the same
+ * operation).
+ */
+static int is_refname_available(const char *refname, const char *oldrefname,
+ struct ref_dir *dir)
+{
+ struct name_conflict_cb data;
+ data.refname = refname;
+ data.oldrefname = oldrefname;
+ data.conflicting_refname = NULL;
+
+ sort_ref_dir(dir);
+ if (do_for_each_ref_in_dir(dir, 0, "", name_conflict_fn,
+ 0, DO_FOR_EACH_INCLUDE_BROKEN,
+ &data)) {
+ error("'%s' exists; cannot create '%s'",
+ data.conflicting_refname, refname);
+ return 0;
+ }
+ return 1;
}
/*
@@ -175,35 +594,23 @@ static struct ref_cache {
struct ref_cache *next;
char did_loose;
char did_packed;
- struct ref_array loose;
- struct ref_array packed;
+ struct ref_dir loose;
+ struct ref_dir packed;
/* The submodule name, or "" for the main repo. */
char name[FLEX_ARRAY];
} *ref_cache;
-static struct ref_entry *current_ref;
-
-static void clear_ref_array(struct ref_array *array)
-{
- int i;
- for (i = 0; i < array->nr; i++)
- free(array->refs[i]);
- free(array->refs);
- array->sorted = array->nr = array->alloc = 0;
- array->refs = NULL;
-}
-
static void clear_packed_ref_cache(struct ref_cache *refs)
{
if (refs->did_packed)
- clear_ref_array(&refs->packed);
+ clear_ref_dir(&refs->packed);
refs->did_packed = 0;
}
static void clear_loose_ref_cache(struct ref_cache *refs)
{
if (refs->did_loose)
- clear_ref_array(&refs->loose);
+ clear_ref_dir(&refs->loose);
refs->did_loose = 0;
}
@@ -249,7 +656,40 @@ void invalidate_ref_cache(const char *submodule)
clear_loose_ref_cache(refs);
}
-static void read_packed_refs(FILE *f, struct ref_array *array)
+/*
+ * Parse one line from a packed-refs file. Write the SHA1 to sha1.
+ * Return a pointer to the refname within the line (null-terminated),
+ * or NULL if there was a problem.
+ */
+static const char *parse_ref_line(char *line, unsigned char *sha1)
+{
+ /*
+ * 42: the answer to everything.
+ *
+ * In this case, it happens to be the answer to
+ * 40 (length of sha1 hex representation)
+ * +1 (space in between hex and name)
+ * +1 (newline at the end of the line)
+ */
+ int len = strlen(line) - 42;
+
+ if (len <= 0)
+ return NULL;
+ if (get_sha1_hex(line, sha1) < 0)
+ return NULL;
+ if (!isspace(line[40]))
+ return NULL;
+ line += 41;
+ if (isspace(*line))
+ return NULL;
+ if (line[len] != '\n')
+ return NULL;
+ line[len] = 0;
+
+ return line;
+}
+
+static void read_packed_refs(FILE *f, struct ref_dir *dir)
{
struct ref_entry *last = NULL;
char refline[PATH_MAX];
@@ -271,7 +711,7 @@ static void read_packed_refs(FILE *f, struct ref_array *array)
refname = parse_ref_line(refline, sha1);
if (refname) {
last = create_ref_entry(refname, sha1, flag, 1);
- add_ref(array, last);
+ add_ref(dir, last);
continue;
}
if (last &&
@@ -279,11 +719,11 @@ static void read_packed_refs(FILE *f, struct ref_array *array)
strlen(refline) == 42 &&
refline[41] == '\n' &&
!get_sha1_hex(refline + 1, sha1))
- hashcpy(last->peeled, sha1);
+ hashcpy(last->u.value.peeled, sha1);
}
}
-static struct ref_array *get_packed_refs(struct ref_cache *refs)
+static struct ref_dir *get_packed_refs(struct ref_cache *refs)
{
if (!refs->did_packed) {
const char *packed_refs_file;
@@ -310,9 +750,9 @@ void add_packed_ref(const char *refname, const unsigned char *sha1)
}
static void get_ref_dir(struct ref_cache *refs, const char *base,
- struct ref_array *array)
+ struct ref_dir *dir)
{
- DIR *dir;
+ DIR *d;
const char *path;
if (*refs->name)
@@ -320,10 +760,8 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
else
path = git_path("%s", base);
-
- dir = opendir(path);
-
- if (dir) {
+ d = opendir(path);
+ if (d) {
struct dirent *de;
int baselen = strlen(base);
char *refname = xmalloc(baselen + 257);
@@ -332,7 +770,7 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
if (baselen && base[baselen-1] != '/')
refname[baselen++] = '/';
- while ((de = readdir(dir)) != NULL) {
+ while ((de = readdir(d)) != NULL) {
unsigned char sha1[20];
struct stat st;
int flag;
@@ -353,7 +791,7 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
if (stat(refdir, &st) < 0)
continue;
if (S_ISDIR(st.st_mode)) {
- get_ref_dir(refs, refname, array);
+ get_ref_dir(refs, refname, dir);
continue;
}
if (*refs->name) {
@@ -367,48 +805,14 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
hashclr(sha1);
flag |= REF_ISBROKEN;
}
- add_ref(array, create_ref_entry(refname, sha1, flag, 1));
+ add_ref(dir, create_ref_entry(refname, sha1, flag, 1));
}
free(refname);
- closedir(dir);
+ closedir(d);
}
}
-struct warn_if_dangling_data {
- FILE *fp;
- const char *refname;
- const char *msg_fmt;
-};
-
-static int warn_if_dangling_symref(const char *refname, const unsigned char *sha1,
- int flags, void *cb_data)
-{
- struct warn_if_dangling_data *d = cb_data;
- const char *resolves_to;
- unsigned char junk[20];
-
- if (!(flags & REF_ISSYMREF))
- return 0;
-
- resolves_to = resolve_ref_unsafe(refname, junk, 0, NULL);
- if (!resolves_to || strcmp(resolves_to, d->refname))
- return 0;
-
- fprintf(d->fp, d->msg_fmt, refname);
- return 0;
-}
-
-void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
-{
- struct warn_if_dangling_data data;
-
- data.fp = fp;
- data.refname = refname;
- data.msg_fmt = msg_fmt;
- for_each_rawref(warn_if_dangling_symref, &data);
-}
-
-static struct ref_array *get_loose_refs(struct ref_cache *refs)
+static struct ref_dir *get_loose_refs(struct ref_cache *refs)
{
if (!refs->did_loose) {
get_ref_dir(refs, "refs", &refs->loose);
@@ -430,13 +834,13 @@ static int resolve_gitlink_packed_ref(struct ref_cache *refs,
const char *refname, unsigned char *sha1)
{
struct ref_entry *ref;
- struct ref_array *array = get_packed_refs(refs);
+ struct ref_dir *dir = get_packed_refs(refs);
- ref = search_ref_array(array, refname);
+ ref = find_ref(dir, refname);
if (ref == NULL)
return -1;
- memcpy(sha1, ref->sha1, 20);
+ memcpy(sha1, ref->u.value.sha1, 20);
return 0;
}
@@ -503,10 +907,10 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sh
*/
static int get_packed_ref(const char *refname, unsigned char *sha1)
{
- struct ref_array *packed = get_packed_refs(get_ref_cache(NULL));
- struct ref_entry *entry = search_ref_array(packed, refname);
+ struct ref_dir *packed = get_packed_refs(get_ref_cache(NULL));
+ struct ref_entry *entry = find_ref(packed, refname);
if (entry) {
- hashcpy(sha1, entry->sha1);
+ hashcpy(sha1, entry->u.value.sha1);
return 0;
}
return -1;
@@ -645,23 +1049,10 @@ int read_ref(const char *refname, unsigned char *sha1)
return read_ref_full(refname, sha1, 1, NULL);
}
-#define DO_FOR_EACH_INCLUDE_BROKEN 01
-static int do_one_ref(const char *base, each_ref_fn fn, int trim,
- int flags, void *cb_data, struct ref_entry *entry)
+int ref_exists(const char *refname)
{
- if (prefixcmp(entry->name, base))
- return 0;
-
- if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
- if (entry->flag & REF_ISBROKEN)
- return 0; /* ignore broken refs e.g. dangling symref */
- if (!has_sha1_file(entry->sha1)) {
- error("%s does not point to a valid object!", entry->name);
- return 0;
- }
- }
- current_ref = entry;
- return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
+ unsigned char sha1[20];
+ return !!resolve_ref_unsafe(refname, sha1, 1, NULL);
}
static int filter_refs(const char *refname, const unsigned char *sha1, int flags,
@@ -682,10 +1073,10 @@ int peel_ref(const char *refname, unsigned char *sha1)
if (current_ref && (current_ref->name == refname
|| !strcmp(current_ref->name, refname))) {
if (current_ref->flag & REF_KNOWS_PEELED) {
- hashcpy(sha1, current_ref->peeled);
+ hashcpy(sha1, current_ref->u.value.peeled);
return 0;
}
- hashcpy(base, current_ref->sha1);
+ hashcpy(base, current_ref->u.value.sha1);
goto fallback;
}
@@ -693,11 +1084,11 @@ int peel_ref(const char *refname, unsigned char *sha1)
return -1;
if ((flag & REF_ISPACKED)) {
- struct ref_array *array = get_packed_refs(get_ref_cache(NULL));
- struct ref_entry *r = search_ref_array(array, refname);
+ struct ref_dir *dir = get_packed_refs(get_ref_cache(NULL));
+ struct ref_entry *r = find_ref(dir, refname);
if (r != NULL && r->flag & REF_KNOWS_PEELED) {
- hashcpy(sha1, r->peeled);
+ hashcpy(sha1, r->u.value.peeled);
return 0;
}
}
@@ -714,50 +1105,74 @@ fallback:
return -1;
}
+struct warn_if_dangling_data {
+ FILE *fp;
+ const char *refname;
+ const char *msg_fmt;
+};
+
+static int warn_if_dangling_symref(const char *refname, const unsigned char *sha1,
+ int flags, void *cb_data)
+{
+ struct warn_if_dangling_data *d = cb_data;
+ const char *resolves_to;
+ unsigned char junk[20];
+
+ if (!(flags & REF_ISSYMREF))
+ return 0;
+
+ resolves_to = resolve_ref_unsafe(refname, junk, 0, NULL);
+ if (!resolves_to || strcmp(resolves_to, d->refname))
+ return 0;
+
+ fprintf(d->fp, d->msg_fmt, refname);
+ return 0;
+}
+
+void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
+{
+ struct warn_if_dangling_data data;
+
+ data.fp = fp;
+ data.refname = refname;
+ data.msg_fmt = msg_fmt;
+ for_each_rawref(warn_if_dangling_symref, &data);
+}
+
static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn fn,
int trim, int flags, void *cb_data)
{
- int retval = 0, p = 0, l = 0;
struct ref_cache *refs = get_ref_cache(submodule);
- struct ref_array *packed = get_packed_refs(refs);
- struct ref_array *loose = get_loose_refs(refs);
-
- sort_ref_array(packed);
- sort_ref_array(loose);
- while (p < packed->nr && l < loose->nr) {
- struct ref_entry *entry;
- int cmp = strcmp(packed->refs[p]->name, loose->refs[l]->name);
- if (!cmp) {
- p++;
- continue;
- }
- if (cmp > 0) {
- entry = loose->refs[l++];
- } else {
- entry = packed->refs[p++];
- }
- retval = do_one_ref(base, fn, trim, flags, cb_data, entry);
- if (retval)
- goto end_each;
- }
-
- if (l < loose->nr) {
- p = l;
- packed = loose;
- }
+ struct ref_dir *packed_dir = get_packed_refs(refs);
+ struct ref_dir *loose_dir = get_loose_refs(refs);
+ int retval = 0;
- for (; p < packed->nr; p++) {
- retval = do_one_ref(base, fn, trim, flags, cb_data, packed->refs[p]);
- if (retval)
- goto end_each;
+ if (base && *base) {
+ packed_dir = find_containing_dir(packed_dir, base, 0);
+ loose_dir = find_containing_dir(loose_dir, base, 0);
+ }
+
+ if (packed_dir && loose_dir) {
+ sort_ref_dir(packed_dir);
+ sort_ref_dir(loose_dir);
+ retval = do_for_each_ref_in_dirs(
+ packed_dir, loose_dir,
+ base, fn, trim, flags, cb_data);
+ } else if (packed_dir) {
+ sort_ref_dir(packed_dir);
+ retval = do_for_each_ref_in_dir(
+ packed_dir, 0,
+ base, fn, trim, flags, cb_data);
+ } else if (loose_dir) {
+ sort_ref_dir(loose_dir);
+ retval = do_for_each_ref_in_dir(
+ loose_dir, 0,
+ base, fn, trim, flags, cb_data);
}
-end_each:
- current_ref = NULL;
return retval;
}
-
static int do_head_ref(const char *submodule, each_ref_fn fn, void *cb_data)
{
unsigned char sha1[20];
@@ -908,101 +1323,6 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
}
-/*
- * Make sure "ref" is something reasonable to have under ".git/refs/";
- * We do not like it if:
- *
- * - any path component of it begins with ".", or
- * - it has double dots "..", or
- * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
- * - it ends with a "/".
- * - it ends with ".lock"
- * - it contains a "\" (backslash)
- */
-
-/* Return true iff ch is not allowed in reference names. */
-static inline int bad_ref_char(int ch)
-{
- if (((unsigned) ch) <= ' ' || ch == 0x7f ||
- ch == '~' || ch == '^' || ch == ':' || ch == '\\')
- return 1;
- /* 2.13 Pattern Matching Notation */
- if (ch == '*' || ch == '?' || ch == '[') /* Unsupported */
- return 1;
- return 0;
-}
-
-/*
- * Try to read one refname component from the front of refname. Return
- * the length of the component found, or -1 if the component is not
- * legal.
- */
-static int check_refname_component(const char *refname, int flags)
-{
- const char *cp;
- char last = '\0';
-
- for (cp = refname; ; cp++) {
- char ch = *cp;
- if (ch == '\0' || ch == '/')
- break;
- if (bad_ref_char(ch))
- return -1; /* Illegal character in refname. */
- if (last == '.' && ch == '.')
- return -1; /* Refname contains "..". */
- if (last == '@' && ch == '{')
- return -1; /* Refname contains "@{". */
- last = ch;
- }
- if (cp == refname)
- return -1; /* Component has zero length. */
- if (refname[0] == '.') {
- if (!(flags & REFNAME_DOT_COMPONENT))
- return -1; /* Component starts with '.'. */
- /*
- * Even if leading dots are allowed, don't allow "."
- * as a component (".." is prevented by a rule above).
- */
- if (refname[1] == '\0')
- return -1; /* Component equals ".". */
- }
- if (cp - refname >= 5 && !memcmp(cp - 5, ".lock", 5))
- return -1; /* Refname ends with ".lock". */
- return cp - refname;
-}
-
-int check_refname_format(const char *refname, int flags)
-{
- int component_len, component_count = 0;
-
- while (1) {
- /* We are at the start of a path component. */
- component_len = check_refname_component(refname, flags);
- if (component_len < 0) {
- if ((flags & REFNAME_REFSPEC_PATTERN) &&
- refname[0] == '*' &&
- (refname[1] == '\0' || refname[1] == '/')) {
- /* Accept one wildcard as a full refname component. */
- flags &= ~REFNAME_REFSPEC_PATTERN;
- component_len = 1;
- } else {
- return -1;
- }
- }
- component_count++;
- if (refname[component_len] == '\0')
- break;
- /* Skip to next component. */
- refname += component_len + 1;
- }
-
- if (refname[component_len - 1] == '.')
- return -1; /* Refname ends with '.'. */
- if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
- return -1; /* Refname has only one component. */
- return 0;
-}
-
const char *prettify_refname(const char *name)
{
return name + (
@@ -1073,35 +1393,6 @@ static int remove_empty_directories(const char *file)
}
/*
- * Return true iff a reference named refname could be created without
- * conflicting with the name of an existing reference. If oldrefname
- * is non-NULL, ignore potential conflicts with oldrefname (e.g.,
- * because oldrefname is scheduled for deletion in the same
- * operation).
- */
-static int is_refname_available(const char *refname, const char *oldrefname,
- struct ref_array *array)
-{
- int i, namlen = strlen(refname); /* e.g. 'foo/bar' */
- for (i = 0; i < array->nr; i++ ) {
- struct ref_entry *entry = array->refs[i];
- /* entry->name could be 'foo' or 'foo/bar/baz' */
- if (!oldrefname || strcmp(oldrefname, entry->name)) {
- int len = strlen(entry->name);
- int cmplen = (namlen < len) ? namlen : len;
- const char *lead = (namlen < len) ? entry->name : refname;
- if (!strncmp(refname, entry->name, cmplen) &&
- lead[cmplen] == '/') {
- error("'%s' exists; cannot create '%s'",
- entry->name, refname);
- return 0;
- }
- }
- }
- return 1;
-}
-
-/*
* *string and *len will only be substituted, and *string returned (for
* later free()ing) if the string passed in is a magic short-hand form
* to name a branch.
@@ -1286,36 +1577,44 @@ struct ref_lock *lock_any_ref_for_update(const char *refname,
return lock_ref_sha1_basic(refname, old_sha1, flags, NULL);
}
+struct repack_without_ref_sb {
+ const char *refname;
+ int fd;
+};
+
+static int repack_without_ref_fn(const char *refname, const unsigned char *sha1,
+ int flags, void *cb_data)
+{
+ struct repack_without_ref_sb *data = cb_data;
+ char line[PATH_MAX + 100];
+ int len;
+
+ if (!strcmp(data->refname, refname))
+ return 0;
+ len = snprintf(line, sizeof(line), "%s %s\n",
+ sha1_to_hex(sha1), refname);
+ /* this should not happen but just being defensive */
+ if (len > sizeof(line))
+ die("too long a refname '%s'", refname);
+ write_or_die(data->fd, line, len);
+ return 0;
+}
+
static struct lock_file packlock;
static int repack_without_ref(const char *refname)
{
- struct ref_array *packed;
- int fd, i;
-
- packed = get_packed_refs(get_ref_cache(NULL));
- if (search_ref_array(packed, refname) == NULL)
+ struct repack_without_ref_sb data;
+ struct ref_dir *packed = get_packed_refs(get_ref_cache(NULL));
+ if (find_ref(packed, refname) == NULL)
return 0;
- fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
- if (fd < 0) {
+ data.refname = refname;
+ data.fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
+ if (data.fd < 0) {
unable_to_lock_error(git_path("packed-refs"), errno);
return error("cannot delete '%s' from packed refs", refname);
}
-
- for (i = 0; i < packed->nr; i++) {
- char line[PATH_MAX + 100];
- int len;
- struct ref_entry *ref = packed->refs[i];
-
- if (!strcmp(refname, ref->name))
- continue;
- len = snprintf(line, sizeof(line), "%s %s\n",
- sha1_to_hex(ref->sha1), ref->name);
- /* this should not happen but just being defensive */
- if (len > sizeof(line))
- die("too long a refname '%s'", ref->name);
- write_or_die(fd, line, len);
- }
+ do_for_each_ref_in_dir(packed, 0, "", repack_without_ref_fn, 0, 0, &data);
return commit_lock_file(&packlock);
}
@@ -1926,10 +2225,10 @@ int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_dat
static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
{
- DIR *dir = opendir(git_path("logs/%s", base));
+ DIR *d = opendir(git_path("logs/%s", base));
int retval = 0;
- if (dir) {
+ if (d) {
struct dirent *de;
int baselen = strlen(base);
char *log = xmalloc(baselen + 257);
@@ -1938,7 +2237,7 @@ static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
if (baselen && base[baselen-1] != '/')
log[baselen++] = '/';
- while ((de = readdir(dir)) != NULL) {
+ while ((de = readdir(d)) != NULL) {
struct stat st;
int namelen;
@@ -1965,7 +2264,7 @@ static int do_for_each_reflog(const char *base, each_ref_fn fn, void *cb_data)
break;
}
free(log);
- closedir(dir);
+ closedir(d);
}
else if (*base)
return errno;
@@ -2004,12 +2303,6 @@ int update_ref(const char *action, const char *refname,
return 0;
}
-int ref_exists(const char *refname)
-{
- unsigned char sha1[20];
- return !!resolve_ref_unsafe(refname, sha1, 1, NULL);
-}
-
struct ref *find_ref_by_name(const struct ref *list, const char *name)
{
for ( ; list; list = list->next)
diff --git a/refs.h b/refs.h
index 33202b0d4c..d6c2fe2dfb 100644
--- a/refs.h
+++ b/refs.h
@@ -15,8 +15,11 @@ struct ref_lock {
#define REF_ISBROKEN 0x04
/*
- * Calls the specified function for each ref file until it returns nonzero,
- * and returns the value
+ * Calls the specified function for each ref file until it returns
+ * nonzero, and returns the value. Please note that it is not safe to
+ * modify references while an iteration is in progress, unless the
+ * same callback function invocation that modifies the reference also
+ * returns a nonzero value to immediately stop the iteration.
*/
typedef int each_ref_fn(const char *refname, const unsigned char *sha1, int flags, void *cb_data);
extern int head_ref(each_ref_fn, void *);
diff --git a/remote-curl.c b/remote-curl.c
index d159fe7f34..08962214db 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -290,6 +290,7 @@ static void output_refs(struct ref *refs)
struct rpc_state {
const char *service_name;
const char **argv;
+ struct strbuf *stdin_preamble;
char *service_url;
char *hdr_content_type;
char *hdr_accept;
@@ -535,6 +536,7 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
{
const char *svc = rpc->service_name;
struct strbuf buf = STRBUF_INIT;
+ struct strbuf *preamble = rpc->stdin_preamble;
struct child_process client;
int err = 0;
@@ -545,6 +547,8 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
client.argv = rpc->argv;
if (start_command(&client))
exit(1);
+ if (preamble)
+ write_or_die(client.in, preamble->buf, preamble->len);
if (heads)
write_or_die(client.in, heads->buf, heads->len);
@@ -626,13 +630,14 @@ static int fetch_git(struct discovery *heads,
int nr_heads, struct ref **to_fetch)
{
struct rpc_state rpc;
+ struct strbuf preamble = STRBUF_INIT;
char *depth_arg = NULL;
- const char **argv;
int argc = 0, i, err;
+ const char *argv[15];
- argv = xmalloc((15 + nr_heads) * sizeof(char*));
argv[argc++] = "fetch-pack";
argv[argc++] = "--stateless-rpc";
+ argv[argc++] = "--stdin";
argv[argc++] = "--lock-pack";
if (options.followtags)
argv[argc++] = "--include-tag";
@@ -651,24 +656,27 @@ static int fetch_git(struct discovery *heads,
argv[argc++] = depth_arg;
}
argv[argc++] = url;
+ argv[argc++] = NULL;
+
for (i = 0; i < nr_heads; i++) {
struct ref *ref = to_fetch[i];
if (!ref->name || !*ref->name)
die("cannot fetch by sha1 over smart http");
- argv[argc++] = ref->name;
+ packet_buf_write(&preamble, "%s\n", ref->name);
}
- argv[argc++] = NULL;
+ packet_buf_flush(&preamble);
memset(&rpc, 0, sizeof(rpc));
rpc.service_name = "git-upload-pack",
rpc.argv = argv;
+ rpc.stdin_preamble = &preamble;
rpc.gzip_request = 1;
err = rpc_service(&rpc, heads);
if (rpc.result.len)
safe_write(1, rpc.result.buf, rpc.result.len);
strbuf_release(&rpc.result);
- free(argv);
+ strbuf_release(&preamble);
free(depth_arg);
return err;
}
diff --git a/revision.c b/revision.c
index b3554ed11b..935e7a7ba4 100644
--- a/revision.c
+++ b/revision.c
@@ -1715,17 +1715,21 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
submodule = opt->submodule;
/* First, search for "--" */
- seen_dashdash = 0;
- for (i = 1; i < argc; i++) {
- const char *arg = argv[i];
- if (strcmp(arg, "--"))
- continue;
- argv[i] = NULL;
- argc = i;
- if (argv[i + 1])
- append_prune_data(&prune_data, argv + i + 1);
+ if (opt && opt->assume_dashdash) {
seen_dashdash = 1;
- break;
+ } else {
+ seen_dashdash = 0;
+ for (i = 1; i < argc; i++) {
+ const char *arg = argv[i];
+ if (strcmp(arg, "--"))
+ continue;
+ argv[i] = NULL;
+ argc = i;
+ if (argv[i + 1])
+ append_prune_data(&prune_data, argv + i + 1);
+ seen_dashdash = 1;
+ break;
+ }
}
/* Second, deal with arguments and options */
@@ -2062,10 +2066,16 @@ static void set_children(struct rev_info *revs)
}
}
+void reset_revision_walk(void)
+{
+ clear_object_flags(SEEN | ADDED | SHOWN);
+}
+
int prepare_revision_walk(struct rev_info *revs)
{
int nr = revs->pending.nr;
struct object_array_entry *e, *list;
+ struct commit_list **next = &revs->commits;
e = list = revs->pending.objects;
revs->pending.nr = 0;
@@ -2076,11 +2086,12 @@ int prepare_revision_walk(struct rev_info *revs)
if (commit) {
if (!(commit->object.flags & SEEN)) {
commit->object.flags |= SEEN;
- commit_list_insert_by_date(commit, &revs->commits);
+ next = commit_list_append(commit, next);
}
}
e++;
}
+ commit_list_sort_by_date(&revs->commits);
if (!revs->leak_pending)
free(list);
diff --git a/revision.h b/revision.h
index b8e9223954..863f4f6454 100644
--- a/revision.h
+++ b/revision.h
@@ -183,6 +183,7 @@ struct setup_revision_opt {
const char *def;
void (*tweak)(struct rev_info *, struct setup_revision_opt *);
const char *submodule;
+ int assume_dashdash;
};
extern void init_revisions(struct rev_info *revs, const char *prefix);
@@ -192,6 +193,7 @@ extern void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ct
const char * const usagestr[]);
extern int handle_revision_arg(const char *arg, struct rev_info *revs,int flags,int cant_be_filename);
+extern void reset_revision_walk(void);
extern int prepare_revision_walk(struct rev_info *revs);
extern struct commit *get_revision(struct rev_info *revs);
extern char *get_revision_mark(const struct rev_info *revs, const struct commit *commit);
diff --git a/sequencer.c b/sequencer.c
index 4307364b26..f83cdfd637 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -13,6 +13,7 @@
#include "rerere.h"
#include "merge-recursive.h"
#include "refs.h"
+#include "argv-array.h"
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
@@ -234,7 +235,7 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
if (!clean) {
int i;
- strbuf_addstr(msgbuf, "\nConflicts:\n\n");
+ strbuf_addstr(msgbuf, "\nConflicts:\n");
for (i = 0; i < active_nr;) {
struct cache_entry *ce = active_cache[i++];
if (ce_stage(ce)) {
@@ -251,6 +252,30 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
return !clean;
}
+static int is_index_unchanged(void)
+{
+ unsigned char head_sha1[20];
+ struct commit *head_commit;
+
+ if (!resolve_ref_unsafe("HEAD", head_sha1, 1, NULL))
+ return error(_("Could not resolve HEAD commit\n"));
+
+ head_commit = lookup_commit(head_sha1);
+ if (!head_commit || parse_commit(head_commit))
+ return error(_("could not parse commit %s\n"),
+ sha1_to_hex(head_commit->object.sha1));
+
+ if (!active_cache_tree)
+ active_cache_tree = cache_tree();
+
+ if (!cache_tree_fully_valid(active_cache_tree))
+ if (cache_tree_update(active_cache_tree, active_cache,
+ active_nr, 0))
+ return error(_("Unable to update cache tree\n"));
+
+ return !hashcmp(active_cache_tree->sha1, head_commit->tree->object.sha1);
+}
+
/*
* If we are cherry-pick, and if the merge did not result in
* hand-editing, we will hit this commit and inherit the original
@@ -260,21 +285,46 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
*/
static int run_git_commit(const char *defmsg, struct replay_opts *opts)
{
- /* 6 is max possible length of our args array including NULL */
- const char *args[6];
- int i = 0;
+ struct argv_array array;
+ int rc;
+
+ argv_array_init(&array);
+ argv_array_push(&array, "commit");
+ argv_array_push(&array, "-n");
- args[i++] = "commit";
- args[i++] = "-n";
if (opts->signoff)
- args[i++] = "-s";
+ argv_array_push(&array, "-s");
if (!opts->edit) {
- args[i++] = "-F";
- args[i++] = defmsg;
+ argv_array_push(&array, "-F");
+ argv_array_push(&array, defmsg);
+ }
+
+ if (opts->allow_empty)
+ argv_array_push(&array, "--allow-empty");
+
+ rc = run_command_v_opt(array.argv, RUN_GIT_CMD);
+ argv_array_clear(&array);
+ return rc;
+}
+
+static int is_original_commit_empty(struct commit *commit)
+{
+ const unsigned char *ptree_sha1;
+
+ if (parse_commit(commit))
+ return error(_("Could not parse commit %s\n"),
+ sha1_to_hex(commit->object.sha1));
+ if (commit->parents) {
+ struct commit *parent = commit->parents->item;
+ if (parse_commit(parent))
+ return error(_("Could not parse parent commit %s\n"),
+ sha1_to_hex(parent->object.sha1));
+ ptree_sha1 = parent->tree->object.sha1;
+ } else {
+ ptree_sha1 = EMPTY_TREE_SHA1_BIN; /* commit is root */
}
- args[i] = NULL;
- return run_command_v_opt(args, RUN_GIT_CMD);
+ return !hashcmp(ptree_sha1, commit->tree->object.sha1);
}
static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
@@ -286,6 +336,8 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
char *defmsg = NULL;
struct strbuf msgbuf = STRBUF_INIT;
int res;
+ int empty_commit;
+ int index_unchanged;
if (opts->no_commit) {
/*
@@ -411,6 +463,10 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
free_commit_list(remotes);
}
+ empty_commit = is_original_commit_empty(commit);
+ if (empty_commit < 0)
+ return empty_commit;
+
/*
* If the merge was clean or if it failed due to conflict, we write
* CHERRY_PICK_HEAD for the subsequent invocation of commit to use.
@@ -431,6 +487,25 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
print_advice(res == 1, opts);
rerere(opts->allow_rerere_auto);
} else {
+ index_unchanged = is_index_unchanged();
+ /*
+ * If index_unchanged is less than 0, that indicates we either
+ * couldn't parse HEAD or the index, so error out here.
+ */
+ if (index_unchanged < 0)
+ return index_unchanged;
+
+ if (!empty_commit && !opts->keep_redundant_commits && index_unchanged)
+ /*
+ * The head tree and the index match
+ * meaning the commit is empty. Since it wasn't created
+ * empty (based on the previous test), we can conclude
+ * the commit has been made redundant. Since we don't
+ * want to keep redundant commits, we can just return
+ * here, skipping this commit
+ */
+ return 0;
+
if (!opts->no_commit)
res = run_git_commit(defmsg, opts);
}
@@ -468,33 +543,6 @@ static void read_and_refresh_cache(struct replay_opts *opts)
rollback_lock_file(&index_lock);
}
-/*
- * Append a commit to the end of the commit_list.
- *
- * next starts by pointing to the variable that holds the head of an
- * empty commit_list, and is updated to point to the "next" field of
- * the last item on the list as new commits are appended.
- *
- * Usage example:
- *
- * struct commit_list *list;
- * struct commit_list **next = &list;
- *
- * next = commit_list_append(c1, next);
- * next = commit_list_append(c2, next);
- * assert(commit_list_count(list) == 2);
- * return list;
- */
-static struct commit_list **commit_list_append(struct commit *commit,
- struct commit_list **next)
-{
- struct commit_list *new = xmalloc(sizeof(struct commit_list));
- new->item = commit;
- *next = new;
- new->next = NULL;
- return &new->next;
-}
-
static int format_todo(struct strbuf *buf, struct commit_list *todo_list,
struct replay_opts *opts)
{
diff --git a/sequencer.h b/sequencer.h
index bb4b13830e..aa5f17cc30 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -29,6 +29,8 @@ struct replay_opts {
int signoff;
int allow_ff;
int allow_rerere_auto;
+ int allow_empty;
+ int keep_redundant_commits;
int mainline;
diff --git a/setup.c b/setup.c
index 7a3618fab7..731851a4a8 100644
--- a/setup.c
+++ b/setup.c
@@ -569,13 +569,15 @@ static const char *setup_nongit(const char *cwd, int *nongit_ok)
return NULL;
}
-static dev_t get_device_or_die(const char *path, const char *prefix)
+static dev_t get_device_or_die(const char *path, const char *prefix, int prefix_len)
{
struct stat buf;
- if (stat(path, &buf))
- die_errno("failed to stat '%s%s%s'",
+ if (stat(path, &buf)) {
+ die_errno("failed to stat '%*s%s%s'",
+ prefix_len,
prefix ? prefix : "",
prefix ? "/" : "", path);
+ }
return buf.st_dev;
}
@@ -589,7 +591,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
static char cwd[PATH_MAX+1];
const char *gitdirenv, *ret;
char *gitfile;
- int len, offset, ceil_offset;
+ int len, offset, offset_parent, ceil_offset;
dev_t current_device = 0;
int one_filesystem = 1;
@@ -631,7 +633,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
*/
one_filesystem = !git_env_bool("GIT_DISCOVERY_ACROSS_FILESYSTEM", 0);
if (one_filesystem)
- current_device = get_device_or_die(".", NULL);
+ current_device = get_device_or_die(".", NULL, 0);
for (;;) {
gitfile = (char*)read_gitfile(DEFAULT_GIT_DIR_ENVIRONMENT);
if (gitfile)
@@ -653,11 +655,12 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
if (is_git_directory("."))
return setup_bare_git_dir(cwd, offset, len, nongit_ok);
- while (--offset > ceil_offset && cwd[offset] != '/');
- if (offset <= ceil_offset)
+ offset_parent = offset;
+ while (--offset_parent > ceil_offset && cwd[offset_parent] != '/');
+ if (offset_parent <= ceil_offset)
return setup_nongit(cwd, nongit_ok);
if (one_filesystem) {
- dev_t parent_device = get_device_or_die("..", cwd);
+ dev_t parent_device = get_device_or_die("..", cwd, offset);
if (parent_device != current_device) {
if (nongit_ok) {
if (chdir(cwd))
@@ -666,7 +669,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
return NULL;
}
cwd[offset] = '\0';
- die("Not a git repository (or any parent up to mount parent %s)\n"
+ die("Not a git repository (or any parent up to mount point %s)\n"
"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).", cwd);
}
}
@@ -674,6 +677,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
cwd[offset] = '\0';
die_errno("Cannot change to '%s/..'", cwd);
}
+ offset = offset_parent;
}
}
diff --git a/sha1_name.c b/sha1_name.c
index 03ffc2caaa..c6331136d1 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -856,10 +856,22 @@ int interpret_branch_name(const char *name, struct strbuf *buf)
len = cp + tmp_len - name;
cp = xstrndup(name, cp - name);
upstream = branch_get(*cp ? cp : NULL);
- if (!upstream
- || !upstream->merge
- || !upstream->merge[0]->dst)
- return error("No upstream branch found for '%s'", cp);
+ /*
+ * Upstream can be NULL only if cp refers to HEAD and HEAD
+ * points to something different than a branch.
+ */
+ if (!upstream)
+ return error(_("HEAD does not point to a branch"));
+ if (!upstream->merge || !upstream->merge[0]->dst) {
+ if (!ref_exists(upstream->refname))
+ return error(_("No such branch: '%s'"), cp);
+ if (!upstream->merge)
+ return error(_("No upstream configured for branch '%s'"),
+ upstream->name);
+ return error(
+ _("Upstream branch '%s' not stored as a remote-tracking branch"),
+ upstream->merge[0]->src);
+ }
free(cp);
cp = shorten_unambiguous_ref(upstream->merge[0]->dst, 0);
strbuf_reset(buf);
diff --git a/submodule.c b/submodule.c
index 9a28060679..784b58039d 100644
--- a/submodule.c
+++ b/submodule.c
@@ -357,21 +357,19 @@ static void collect_submodules_from_diff(struct diff_queue_struct *q,
void *data)
{
int i;
- int *needs_pushing = data;
+ struct string_list *needs_pushing = data;
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
if (!S_ISGITLINK(p->two->mode))
continue;
- if (submodule_needs_pushing(p->two->path, p->two->sha1)) {
- *needs_pushing = 1;
- break;
- }
+ if (submodule_needs_pushing(p->two->path, p->two->sha1))
+ string_list_insert(needs_pushing, p->two->path);
}
}
-
-static void commit_need_pushing(struct commit *commit, int *needs_pushing)
+static void find_unpushed_submodule_commits(struct commit *commit,
+ struct string_list *needs_pushing)
{
struct rev_info rev;
@@ -382,14 +380,15 @@ static void commit_need_pushing(struct commit *commit, int *needs_pushing)
diff_tree_combined_merge(commit, 1, &rev);
}
-int check_submodule_needs_pushing(unsigned char new_sha1[20], const char *remotes_name)
+int find_unpushed_submodules(unsigned char new_sha1[20],
+ const char *remotes_name, struct string_list *needs_pushing)
{
struct rev_info rev;
struct commit *commit;
const char *argv[] = {NULL, NULL, "--not", "NULL", NULL};
int argc = ARRAY_SIZE(argv) - 1;
char *sha1_copy;
- int needs_pushing = 0;
+
struct strbuf remotes_arg = STRBUF_INIT;
strbuf_addf(&remotes_arg, "--remotes=%s", remotes_name);
@@ -401,13 +400,62 @@ int check_submodule_needs_pushing(unsigned char new_sha1[20], const char *remote
if (prepare_revision_walk(&rev))
die("revision walk setup failed");
- while ((commit = get_revision(&rev)) && !needs_pushing)
- commit_need_pushing(commit, &needs_pushing);
+ while ((commit = get_revision(&rev)) != NULL)
+ find_unpushed_submodule_commits(commit, needs_pushing);
+ reset_revision_walk();
free(sha1_copy);
strbuf_release(&remotes_arg);
- return needs_pushing;
+ return needs_pushing->nr;
+}
+
+static int push_submodule(const char *path)
+{
+ if (add_submodule_odb(path))
+ return 1;
+
+ if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
+ struct child_process cp;
+ const char *argv[] = {"push", NULL};
+
+ memset(&cp, 0, sizeof(cp));
+ cp.argv = argv;
+ cp.env = local_repo_env;
+ cp.git_cmd = 1;
+ cp.no_stdin = 1;
+ cp.dir = path;
+ if (run_command(&cp))
+ return 0;
+ close(cp.out);
+ }
+
+ return 1;
+}
+
+int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name)
+{
+ int i, ret = 1;
+ struct string_list needs_pushing;
+
+ memset(&needs_pushing, 0, sizeof(struct string_list));
+ needs_pushing.strdup_strings = 1;
+
+ if (!find_unpushed_submodules(new_sha1, remotes_name, &needs_pushing))
+ return 1;
+
+ for (i = 0; i < needs_pushing.nr; i++) {
+ const char *path = needs_pushing.items[i].string;
+ fprintf(stderr, "Pushing submodule '%s'\n", path);
+ if (!push_submodule(path)) {
+ fprintf(stderr, "Unable to push submodule '%s'\n", path);
+ ret = 0;
+ }
+ }
+
+ string_list_clear(&needs_pushing, 0);
+
+ return ret;
}
static int is_submodule_commit_present(const char *path, unsigned char sha1[20])
@@ -741,6 +789,7 @@ static int find_first_merges(struct object_array *result, const char *path,
if (in_merge_bases(b, &commit, 1))
add_object_array(o, NULL, &merges);
}
+ reset_revision_walk();
/* Now we've got all merges that contain a and b. Prune all
* merges that contain another found merge and save them in
diff --git a/submodule.h b/submodule.h
index 9c5e5c0c30..e105b0ebe6 100644
--- a/submodule.h
+++ b/submodule.h
@@ -29,6 +29,8 @@ int fetch_populated_submodules(int num_options, const char **options,
unsigned is_submodule_modified(const char *path, int ignore_untracked);
int merge_submodule(unsigned char result[20], const char *path, const unsigned char base[20],
const unsigned char a[20], const unsigned char b[20], int search);
-int check_submodule_needs_pushing(unsigned char new_sha1[20], const char *remotes_name);
+int find_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name,
+ struct string_list *needs_pushing);
+int push_unpushed_submodules(unsigned char new_sha1[20], const char *remotes_name);
#endif
diff --git a/t/lib-git-daemon.sh b/t/lib-git-daemon.sh
index ef2d01f369..87f0ad8f41 100644
--- a/t/lib-git-daemon.sh
+++ b/t/lib-git-daemon.sh
@@ -31,19 +31,19 @@ start_git_daemon() {
>&3 2>git_daemon_output &
GIT_DAEMON_PID=$!
{
- read line
+ read line <&7
echo >&4 "$line"
- cat >&4 &
+ cat <&7 >&4 &
+ } 7<git_daemon_output &&
- # Check expected output
- if test x"$(expr "$line" : "\[[0-9]*\] \(.*\)")" != x"Ready to rumble"
- then
- kill "$GIT_DAEMON_PID"
- wait "$GIT_DAEMON_PID"
- trap 'die' EXIT
- error "git daemon failed to start"
- fi
- } <git_daemon_output
+ # Check expected output
+ if test x"$(expr "$line" : "\[[0-9]*\] \(.*\)")" != x"Ready to rumble"
+ then
+ kill "$GIT_DAEMON_PID"
+ wait "$GIT_DAEMON_PID"
+ trap 'die' EXIT
+ error "git daemon failed to start"
+ fi
}
stop_git_daemon() {
diff --git a/t/lib-git-p4.sh b/t/lib-git-p4.sh
index a870f9a5d2..121e38002b 100644
--- a/t/lib-git-p4.sh
+++ b/t/lib-git-p4.sh
@@ -1,20 +1,18 @@
#
-# Library code for git-p4 tests
+# Library code for git p4 tests
#
. ./test-lib.sh
if ! test_have_prereq PYTHON; then
- skip_all='skipping git-p4 tests; python not available'
+ skip_all='skipping git p4 tests; python not available'
test_done
fi
( p4 -h && p4d -h ) >/dev/null 2>&1 || {
- skip_all='skipping git-p4 tests; no p4 or p4d'
+ skip_all='skipping git p4 tests; no p4 or p4d'
test_done
}
-GITP4="$GIT_BUILD_DIR/contrib/fast-import/git-p4"
-
# Try to pick a unique port: guess a large number, then hope
# no more than one of each test is running.
#
@@ -26,6 +24,7 @@ P4DPORT=$((10669 + ($testid - $git_p4_test_start)))
export P4PORT=localhost:$P4DPORT
export P4CLIENT=client
+export P4EDITOR=:
db="$TRASH_DIRECTORY/db"
cli="$TRASH_DIRECTORY/cli"
diff --git a/t/t0062-revision-walking.sh b/t/t0062-revision-walking.sh
new file mode 100755
index 0000000000..3d98eb847f
--- /dev/null
+++ b/t/t0062-revision-walking.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Heiko Voigt
+#
+
+test_description='Test revision walking api'
+
+. ./test-lib.sh
+
+cat >run_twice_expected <<-EOF
+1st
+ > add b
+ > add a
+2nd
+ > add b
+ > add a
+EOF
+
+test_expect_success 'setup' '
+ echo a > a &&
+ git add a &&
+ git commit -m "add a" &&
+ echo b > b &&
+ git add b &&
+ git commit -m "add b"
+'
+
+test_expect_success 'revision walking can be done twice' '
+ test-revision-walking run-twice > run_twice_actual
+ test_cmp run_twice_expected run_twice_actual
+'
+
+test_done
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 36e227b3bb..a477453e2e 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -550,6 +550,14 @@ EOF
test_expect_success "rename succeeded" "test_cmp expect .git/config"
+test_expect_success 'renaming empty section name is rejected' '
+ test_must_fail git config --rename-section branch.zwei ""
+'
+
+test_expect_success 'renaming to bogus section is rejected' '
+ test_must_fail git config --rename-section branch.zwei "bogus name"
+'
+
cat >> .git/config << EOF
[branch "zwei"] a = 1 [branch "vier"]
EOF
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index 4b1cbaa028..a70707620f 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -29,6 +29,14 @@ test_expect_success 'chained relative paths' '
test_cmp expect actual
'
+test_expect_success 'include paths get tilde-expansion' '
+ echo "[test]one = 1" >one &&
+ echo "[include]path = ~/one" >.gitconfig &&
+ echo 1 >expect &&
+ git config test.one >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'include options can still be examined' '
echo "[test]one = 1" >one &&
echo "[include]path = one" >.gitconfig &&
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index 252fc82837..236b13a3ab 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -100,8 +100,7 @@ test_expect_success setup '
check_fsck &&
- loglen=$(wc -l <.git/logs/refs/heads/master) &&
- test $loglen = 4
+ test_line_count = 4 .git/logs/refs/heads/master
'
test_expect_success rewind '
@@ -117,8 +116,7 @@ test_expect_success rewind '
check_have A B C D E F G H I J K L &&
- loglen=$(wc -l <.git/logs/refs/heads/master) &&
- test $loglen = 5
+ test_line_count = 5 .git/logs/refs/heads/master
'
test_expect_success 'corrupt and check' '
@@ -136,8 +134,7 @@ test_expect_success 'reflog expire --dry-run should not touch reflog' '
--stale-fix \
--all &&
- loglen=$(wc -l <.git/logs/refs/heads/master) &&
- test $loglen = 5 &&
+ test_line_count = 5 .git/logs/refs/heads/master &&
check_fsck "missing blob $F"
'
@@ -150,8 +147,7 @@ test_expect_success 'reflog expire' '
--stale-fix \
--all &&
- loglen=$(wc -l <.git/logs/refs/heads/master) &&
- test $loglen = 2 &&
+ test_line_count = 2 .git/logs/refs/heads/master &&
check_fsck "dangling commit $K"
'
@@ -217,9 +213,7 @@ test_expect_success 'delete' '
test_expect_success 'rewind2' '
test_tick && git reset --hard HEAD~2 &&
- loglen=$(wc -l <.git/logs/refs/heads/master) &&
- test $loglen = 4
-
+ test_line_count = 4 .git/logs/refs/heads/master
'
test_expect_success '--expire=never' '
@@ -228,9 +222,7 @@ test_expect_success '--expire=never' '
--expire=never \
--expire-unreachable=never \
--all &&
- loglen=$(wc -l <.git/logs/refs/heads/master) &&
- test $loglen = 4
-
+ test_line_count = 4 .git/logs/refs/heads/master
'
test_expect_success 'gc.reflogexpire=never' '
@@ -238,8 +230,7 @@ test_expect_success 'gc.reflogexpire=never' '
git config gc.reflogexpire never &&
git config gc.reflogexpireunreachable never &&
git reflog expire --verbose --all &&
- loglen=$(wc -l <.git/logs/refs/heads/master) &&
- test $loglen = 4
+ test_line_count = 4 .git/logs/refs/heads/master
'
test_expect_success 'gc.reflogexpire=false' '
@@ -247,8 +238,7 @@ test_expect_success 'gc.reflogexpire=false' '
git config gc.reflogexpire false &&
git config gc.reflogexpireunreachable false &&
git reflog expire --verbose --all &&
- loglen=$(wc -l <.git/logs/refs/heads/master) &&
- test $loglen = 4 &&
+ test_line_count = 4 .git/logs/refs/heads/master &&
git config --unset gc.reflogexpire &&
git config --unset gc.reflogexpireunreachable
diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh
index e661147c57..8f36aa9fc4 100755
--- a/t/t1501-worktree.sh
+++ b/t/t1501-worktree.sh
@@ -68,7 +68,7 @@ test_expect_success 'inside work tree' '
)
'
-test_expect_failure 'empty prefix is actually written out' '
+test_expect_success 'empty prefix is actually written out' '
echo >expected &&
(
cd work &&
diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh
index a4555510c3..d6e576192f 100755
--- a/t/t1507-rev-parse-upstream.sh
+++ b/t/t1507-rev-parse-upstream.sh
@@ -15,10 +15,18 @@ test_expect_success 'setup' '
test_commit 3 &&
(cd clone &&
test_commit 4 &&
- git branch --track my-side origin/side)
-
+ git branch --track my-side origin/side &&
+ git branch --track local-master master &&
+ git remote add -t master master-only .. &&
+ git fetch master-only &&
+ git branch bad-upstream &&
+ git config branch.bad-upstream.remote master-only &&
+ git config branch.bad-upstream.merge refs/heads/side
+ )
'
+sq="'"
+
full_name () {
(cd clone &&
git rev-parse --symbolic-full-name "$@")
@@ -29,6 +37,11 @@ commit_subject () {
git show -s --pretty=format:%s "$@")
}
+error_message () {
+ (cd clone &&
+ test_must_fail git rev-parse --verify "$@")
+}
+
test_expect_success '@{upstream} resolves to correct full name' '
test refs/remotes/origin/master = "$(full_name @{upstream})"
'
@@ -78,7 +91,6 @@ test_expect_success 'checkout -b new my-side@{u} forks from the same' '
test_expect_success 'merge my-side@{u} records the correct name' '
(
- sq="'\''" &&
cd clone || exit
git checkout master || exit
git branch -D new ;# can fail but is ok
@@ -107,6 +119,69 @@ test_expect_success 'checkout other@{u}' '
test_cmp expect actual
'
+test_expect_success 'branch@{u} works when tracking a local branch' '
+ test refs/heads/master = "$(full_name local-master@{u})"
+'
+
+test_expect_success 'branch@{u} error message when no upstream' '
+ cat >expect <<-EOF &&
+ error: No upstream configured for branch ${sq}non-tracking${sq}
+ fatal: Needed a single revision
+ EOF
+ error_message non-tracking@{u} 2>actual &&
+ test_i18ncmp expect actual
+'
+
+test_expect_success '@{u} error message when no upstream' '
+ cat >expect <<-EOF &&
+ error: No upstream configured for branch ${sq}master${sq}
+ fatal: Needed a single revision
+ EOF
+ test_must_fail git rev-parse --verify @{u} 2>actual &&
+ test_i18ncmp expect actual
+'
+
+test_expect_success 'branch@{u} error message with misspelt branch' '
+ cat >expect <<-EOF &&
+ error: No such branch: ${sq}no-such-branch${sq}
+ fatal: Needed a single revision
+ EOF
+ error_message no-such-branch@{u} 2>actual &&
+ test_i18ncmp expect actual
+'
+
+test_expect_success '@{u} error message when not on a branch' '
+ cat >expect <<-EOF &&
+ error: HEAD does not point to a branch
+ fatal: Needed a single revision
+ EOF
+ git checkout HEAD^0 &&
+ test_must_fail git rev-parse --verify @{u} 2>actual &&
+ test_i18ncmp expect actual
+'
+
+test_expect_success 'branch@{u} error message if upstream branch not fetched' '
+ cat >expect <<-EOF &&
+ error: Upstream branch ${sq}refs/heads/side${sq} not stored as a remote-tracking branch
+ fatal: Needed a single revision
+ EOF
+ error_message bad-upstream@{u} 2>actual &&
+ test_i18ncmp expect actual
+'
+
+test_expect_success 'pull works when tracking a local branch' '
+(
+ cd clone &&
+ git checkout local-master &&
+ git pull
+)
+'
+
+# makes sense if the previous one succeeded
+test_expect_success '@{u} works when tracking a local branch' '
+ test refs/heads/master = "$(full_name @{u})"
+'
+
cat >expect <<EOF
commit 8f489d01d0cc65c3b0f09504ec50b5ed02a70bd5
Reflog: master@{0} (C O Mitter <committer@example.com>)
diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh
index 36cca14d95..0f4b2896af 100755
--- a/t/t2004-checkout-cache-temp.sh
+++ b/t/t2004-checkout-cache-temp.sh
@@ -40,7 +40,7 @@ test_expect_success \
rm -f path* .merge_* out .git/index &&
git read-tree $t1 &&
git checkout-index --temp -- path1 >out &&
-test $(wc -l <out) = 1 &&
+test_line_count = 1 out &&
test $(cut "-d " -f2 out) = path1 &&
p=$(cut "-d " -f1 out) &&
test -f $p &&
@@ -51,7 +51,7 @@ test_expect_success \
rm -f path* .merge_* out .git/index &&
git read-tree $t1 &&
git checkout-index -a --temp >out &&
-test $(wc -l <out) = 5 &&
+test_line_count = 5 out &&
for f in path0 path1 path3 path4 asubdir/path5
do
test $(grep $f out | cut "-d " -f2) = $f &&
@@ -69,7 +69,7 @@ test_expect_success \
'checkout one stage 2 to temporary file' '
rm -f path* .merge_* out &&
git checkout-index --stage=2 --temp -- path1 >out &&
-test $(wc -l <out) = 1 &&
+test_line_count = 1 out &&
test $(cut "-d " -f2 out) = path1 &&
p=$(cut "-d " -f1 out) &&
test -f $p &&
@@ -79,7 +79,7 @@ test_expect_success \
'checkout all stage 2 to temporary files' '
rm -f path* .merge_* out &&
git checkout-index --all --stage=2 --temp >out &&
-test $(wc -l <out) = 3 &&
+test_line_count = 3 out &&
for f in path1 path2 path4
do
test $(grep $f out | cut "-d " -f2) = $f &&
@@ -92,13 +92,13 @@ test_expect_success \
'checkout all stages/one file to nothing' '
rm -f path* .merge_* out &&
git checkout-index --stage=all --temp -- path0 >out &&
-test $(wc -l <out) = 0'
+test_line_count = 0 out'
test_expect_success \
'checkout all stages/one file to temporary files' '
rm -f path* .merge_* out &&
git checkout-index --stage=all --temp -- path1 >out &&
-test $(wc -l <out) = 1 &&
+test_line_count = 1 out &&
test $(cut "-d " -f2 out) = path1 &&
cut "-d " -f1 out | (read s1 s2 s3 &&
test -f $s1 &&
@@ -112,7 +112,7 @@ test_expect_success \
'checkout some stages/one file to temporary files' '
rm -f path* .merge_* out &&
git checkout-index --stage=all --temp -- path2 >out &&
-test $(wc -l <out) = 1 &&
+test_line_count = 1 out &&
test $(cut "-d " -f2 out) = path2 &&
cut "-d " -f1 out | (read s1 s2 s3 &&
test $s1 = . &&
@@ -125,7 +125,7 @@ test_expect_success \
'checkout all stages/all files to temporary files' '
rm -f path* .merge_* out &&
git checkout-index -a --stage=all --temp >out &&
-test $(wc -l <out) = 5'
+test_line_count = 5 out'
test_expect_success \
'-- path0: no entry' '
@@ -185,7 +185,7 @@ test_expect_success \
'checkout --temp within subdir' '
(cd asubdir &&
git checkout-index -a --stage=all >out &&
- test $(wc -l <out) = 1 &&
+ test_line_count = 1 out &&
test $(grep path5 out | cut "-d " -f2) = path5 &&
grep path5 out | cut "-d " -f1 | (read s1 s2 s3 &&
test -f ../$s1 &&
@@ -203,7 +203,7 @@ t4=$(git write-tree) &&
rm -f .git/index &&
git read-tree $t4 &&
git checkout-index --temp -a >out &&
-test $(wc -l <out) = 1 &&
+test_line_count = 1 out &&
test $(cut "-d " -f2 out) = a &&
p=$(cut "-d " -f1 out) &&
test -f $p &&
diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh
index 068fba4c8e..b37ce25c42 100755
--- a/t/t2020-checkout-detach.sh
+++ b/t/t2020-checkout-detach.sh
@@ -148,7 +148,7 @@ test_expect_success 'tracking count is accurate after orphan check' '
git config branch.child.merge refs/heads/master &&
git checkout child^ &&
git checkout child >stdout &&
- test_cmp expect stdout
+ test_i18ncmp expect stdout
'
test_done
diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh
index cb7effe0a3..f2620650ce 100755
--- a/t/t2030-unresolve-info.sh
+++ b/t/t2030-unresolve-info.sh
@@ -113,7 +113,7 @@ 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_line_count = 3 actual
'
test_expect_success 'rerere and rerere forget' '
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index b981572d73..7fd2127625 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -624,8 +624,38 @@ test_expect_success 'submodule rebase -i' '
FAKE_LINES="1 squash 2 3" git rebase -i A
'
+test_expect_success 'submodule conflict setup' '
+ git tag submodule-base &&
+ git checkout HEAD^ &&
+ (
+ cd sub && git checkout HEAD^ && echo 4 >elif &&
+ git add elif && git commit -m "submodule conflict"
+ ) &&
+ git add sub &&
+ test_tick &&
+ git commit -m "Conflict in submodule" &&
+ git tag submodule-topic
+'
+
+test_expect_success 'rebase -i continue with only submodule staged' '
+ test_must_fail git rebase -i submodule-base &&
+ git add sub &&
+ git rebase --continue &&
+ test $(git rev-parse submodule-base) != $(git rev-parse HEAD)
+'
+
+test_expect_success 'rebase -i continue with unstaged submodule' '
+ git checkout submodule-topic &&
+ git reset --hard &&
+ test_must_fail git rebase -i submodule-base &&
+ git reset &&
+ git rebase --continue &&
+ test $(git rev-parse submodule-base) = $(git rev-parse HEAD)
+'
+
test_expect_success 'avoid unnecessary reset' '
git checkout master &&
+ git reset --hard &&
test-chmtime =123456789 file3 &&
git update-index --refresh &&
HEAD=$(git rev-parse HEAD) &&
diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh
index b38be8e937..a1e86c4097 100755
--- a/t/t3415-rebase-autosquash.sh
+++ b/t/t3415-rebase-autosquash.sh
@@ -33,7 +33,7 @@ test_auto_fixup () {
test_tick &&
git rebase $2 -i HEAD^^^ &&
git log --oneline >actual &&
- test 3 = $(wc -l <actual) &&
+ test_line_count = 3 actual &&
git diff --exit-code $1 &&
test 1 = "$(git cat-file blob HEAD^:file1)" &&
test 1 = $(git cat-file commit HEAD^ | grep first | wc -l)
@@ -62,7 +62,7 @@ test_auto_squash () {
test_tick &&
git rebase $2 -i HEAD^^^ &&
git log --oneline >actual &&
- test 3 = $(wc -l <actual) &&
+ test_line_count = 3 actual &&
git diff --exit-code $1 &&
test 1 = "$(git cat-file blob HEAD^:file1)" &&
test 2 = $(git cat-file commit HEAD^ | grep first | wc -l)
@@ -90,7 +90,7 @@ test_expect_success 'misspelled auto squash' '
test_tick &&
git rebase --autosquash -i HEAD^^^ &&
git log --oneline >actual &&
- test 4 = $(wc -l <actual) &&
+ test_line_count = 4 actual &&
git diff --exit-code final-missquash &&
test 0 = $(git rev-list final-missquash...HEAD | wc -l)
'
@@ -109,7 +109,7 @@ test_expect_success 'auto squash that matches 2 commits' '
test_tick &&
git rebase --autosquash -i HEAD~4 &&
git log --oneline >actual &&
- test 4 = $(wc -l <actual) &&
+ test_line_count = 4 actual &&
git diff --exit-code final-multisquash &&
test 1 = "$(git cat-file blob HEAD^^:file1)" &&
test 2 = $(git cat-file commit HEAD^^ | grep first | wc -l) &&
@@ -130,7 +130,7 @@ test_expect_success 'auto squash that matches a commit after the squash' '
test_tick &&
git rebase --autosquash -i HEAD~4 &&
git log --oneline >actual &&
- test 5 = $(wc -l <actual) &&
+ test_line_count = 5 actual &&
git diff --exit-code final-presquash &&
test 0 = "$(git cat-file blob HEAD^^:file1)" &&
test 1 = "$(git cat-file blob HEAD^:file1)" &&
@@ -147,7 +147,7 @@ test_expect_success 'auto squash that matches a sha1' '
test_tick &&
git rebase --autosquash -i HEAD^^^ &&
git log --oneline >actual &&
- test 3 = $(wc -l <actual) &&
+ test_line_count = 3 actual &&
git diff --exit-code final-shasquash &&
test 1 = "$(git cat-file blob HEAD^:file1)" &&
test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l)
@@ -163,7 +163,7 @@ test_expect_success 'auto squash that matches longer sha1' '
test_tick &&
git rebase --autosquash -i HEAD^^^ &&
git log --oneline >actual &&
- test 3 = $(wc -l <actual) &&
+ test_line_count = 3 actual &&
git diff --exit-code final-longshasquash &&
test 1 = "$(git cat-file blob HEAD^:file1)" &&
test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l)
@@ -179,7 +179,7 @@ test_auto_commit_flags () {
test_tick &&
git rebase --autosquash -i HEAD^^^ &&
git log --oneline >actual &&
- test 3 = $(wc -l <actual) &&
+ test_line_count = 3 actual &&
git diff --exit-code final-commit-$1 &&
test 1 = "$(git cat-file blob HEAD^:file1)" &&
test $2 = $(git cat-file commit HEAD^ | grep first | wc -l)
diff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh
index c10b28cf57..92f00cdf84 100755
--- a/t/t3505-cherry-pick-empty.sh
+++ b/t/t3505-cherry-pick-empty.sh
@@ -18,7 +18,12 @@ test_expect_success setup '
echo third >> file1 &&
git add file1 &&
test_tick &&
- git commit --allow-empty-message -m ""
+ git commit --allow-empty-message -m "" &&
+
+ git checkout master &&
+ git checkout -b empty-branch2 &&
+ test_tick &&
+ git commit --allow-empty -m "empty"
'
@@ -48,4 +53,22 @@ test_expect_success 'index lockfile was removed' '
'
+test_expect_success 'cherry pick an empty non-ff commit without --allow-empty' '
+ git checkout master &&
+ echo fourth >>file2 &&
+ git add file2 &&
+ git commit -m "fourth" &&
+ test_must_fail git cherry-pick empty-branch2
+'
+
+test_expect_success 'cherry pick an empty non-ff commit with --allow-empty' '
+ git checkout master &&
+ git cherry-pick --allow-empty empty-branch2
+'
+
+test_expect_success 'cherry pick with --keep-redundant-commits' '
+ git checkout master &&
+ git cherry-pick --keep-redundant-commits HEAD^
+'
+
test_done
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index d48a7c002d..37ddabba2d 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -160,7 +160,7 @@ test_commit_autosquash_flags () {
git config --unset-all i18n.commitencoding &&
git rebase --autosquash -i HEAD^^^ &&
git log --oneline >actual &&
- test 3 = $(wc -l <actual)
+ test_line_count = 3 actual
'
}
diff --git a/t/t4035-diff-quiet.sh b/t/t4035-diff-quiet.sh
index e747e84227..cdb9202f57 100755
--- a/t/t4035-diff-quiet.sh
+++ b/t/t4035-diff-quiet.sh
@@ -15,65 +15,65 @@ test_expect_success 'setup' '
test_expect_success 'git diff-tree HEAD^ HEAD' '
git diff-tree --quiet HEAD^ HEAD >cnt
- test $? = 1 && test $(wc -l <cnt) = 0
+ test $? = 1 && test_line_count = 0 cnt
'
test_expect_success 'git diff-tree HEAD^ HEAD -- a' '
git diff-tree --quiet HEAD^ HEAD -- a >cnt
- test $? = 0 && test $(wc -l <cnt) = 0
+ test $? = 0 && test_line_count = 0 cnt
'
test_expect_success 'git diff-tree HEAD^ HEAD -- b' '
git diff-tree --quiet HEAD^ HEAD -- b >cnt
- test $? = 1 && test $(wc -l <cnt) = 0
+ test $? = 1 && test_line_count = 0 cnt
'
# this diff outputs one line: sha1 of the given head
test_expect_success 'echo HEAD | git diff-tree --stdin' '
echo $(git rev-parse HEAD) | git diff-tree --quiet --stdin >cnt
- test $? = 1 && test $(wc -l <cnt) = 1
+ test $? = 1 && test_line_count = 1 cnt
'
test_expect_success 'git diff-tree HEAD HEAD' '
git diff-tree --quiet HEAD HEAD >cnt
- test $? = 0 && test $(wc -l <cnt) = 0
+ test $? = 0 && test_line_count = 0 cnt
'
test_expect_success 'git diff-files' '
git diff-files --quiet >cnt
- test $? = 0 && test $(wc -l <cnt) = 0
+ test $? = 0 && test_line_count = 0 cnt
'
test_expect_success 'git diff-index --cached HEAD' '
git diff-index --quiet --cached HEAD >cnt
- test $? = 0 && test $(wc -l <cnt) = 0
+ test $? = 0 && test_line_count = 0 cnt
'
test_expect_success 'git diff-index --cached HEAD^' '
git diff-index --quiet --cached HEAD^ >cnt
- test $? = 1 && test $(wc -l <cnt) = 0
+ test $? = 1 && test_line_count = 0 cnt
'
test_expect_success 'git diff-index --cached HEAD^' '
echo text >>b &&
echo 3 >c &&
git add . && {
git diff-index --quiet --cached HEAD^ >cnt
- test $? = 1 && test $(wc -l <cnt) = 0
+ test $? = 1 && test_line_count = 0 cnt
}
'
test_expect_success 'git diff-tree -Stext HEAD^ HEAD -- b' '
git commit -m "text in b" && {
git diff-tree --quiet -Stext HEAD^ HEAD -- b >cnt
- test $? = 1 && test $(wc -l <cnt) = 0
+ test $? = 1 && test_line_count = 0 cnt
}
'
test_expect_success 'git diff-tree -Snot-found HEAD^ HEAD -- b' '
git diff-tree --quiet -Snot-found HEAD^ HEAD -- b >cnt
- test $? = 0 && test $(wc -l <cnt) = 0
+ test $? = 0 && test_line_count = 0 cnt
'
test_expect_success 'git diff-files' '
echo 3 >>c && {
git diff-files --quiet >cnt
- test $? = 1 && test $(wc -l <cnt) = 0
+ test $? = 1 && test_line_count = 0 cnt
}
'
test_expect_success 'git diff-index --cached HEAD' '
git update-index c && {
git diff-index --quiet --cached HEAD >cnt
- test $? = 1 && test $(wc -l <cnt) = 0
+ test $? = 1 && test_line_count = 0 cnt
}
'
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index ccc0280f52..cdafd7e7c1 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -525,9 +525,9 @@ test_expect_success 'am empty-file does not infloop' '
git reset --hard &&
touch empty-file &&
test_tick &&
- { git am empty-file > actual 2>&1 && false || :; } &&
+ test_must_fail git am empty-file 2>actual &&
echo Patch format detection failed. >expected &&
- test_cmp expected actual
+ test_i18ncmp expected actual
'
test_done
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 222f7559e9..32cf0bd218 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -516,4 +516,294 @@ test_expect_success 'show added path under "--follow -M"' '
)
'
+cat >expect <<\EOF
+* commit COMMIT_OBJECT_NAME
+|\ Merge: MERGE_PARENTS
+| | Author: A U Thor <author@example.com>
+| |
+| | Merge HEADS DESCRIPTION
+| |
+| * commit COMMIT_OBJECT_NAME
+| | Author: A U Thor <author@example.com>
+| |
+| | reach
+| | ---
+| | reach.t | 1 +
+| | 1 file changed, 1 insertion(+)
+| |
+| | diff --git a/reach.t b/reach.t
+| | new file mode 100644
+| | index 0000000..10c9591
+| | --- /dev/null
+| | +++ b/reach.t
+| | @@ -0,0 +1 @@
+| | +reach
+| |
+| \
+*-. \ commit COMMIT_OBJECT_NAME
+|\ \ \ Merge: MERGE_PARENTS
+| | | | Author: A U Thor <author@example.com>
+| | | |
+| | | | Merge HEADS DESCRIPTION
+| | | |
+| | * | commit COMMIT_OBJECT_NAME
+| | |/ Author: A U Thor <author@example.com>
+| | |
+| | | octopus-b
+| | | ---
+| | | octopus-b.t | 1 +
+| | | 1 file changed, 1 insertion(+)
+| | |
+| | | diff --git a/octopus-b.t b/octopus-b.t
+| | | new file mode 100644
+| | | index 0000000..d5fcad0
+| | | --- /dev/null
+| | | +++ b/octopus-b.t
+| | | @@ -0,0 +1 @@
+| | | +octopus-b
+| | |
+| * | commit COMMIT_OBJECT_NAME
+| |/ Author: A U Thor <author@example.com>
+| |
+| | octopus-a
+| | ---
+| | octopus-a.t | 1 +
+| | 1 file changed, 1 insertion(+)
+| |
+| | diff --git a/octopus-a.t b/octopus-a.t
+| | new file mode 100644
+| | index 0000000..11ee015
+| | --- /dev/null
+| | +++ b/octopus-a.t
+| | @@ -0,0 +1 @@
+| | +octopus-a
+| |
+* | commit COMMIT_OBJECT_NAME
+|/ Author: A U Thor <author@example.com>
+|
+| seventh
+| ---
+| seventh.t | 1 +
+| 1 file changed, 1 insertion(+)
+|
+| diff --git a/seventh.t b/seventh.t
+| new file mode 100644
+| index 0000000..9744ffc
+| --- /dev/null
+| +++ b/seventh.t
+| @@ -0,0 +1 @@
+| +seventh
+|
+* commit COMMIT_OBJECT_NAME
+|\ Merge: MERGE_PARENTS
+| | Author: A U Thor <author@example.com>
+| |
+| | Merge branch 'tangle'
+| |
+| * commit COMMIT_OBJECT_NAME
+| |\ Merge: MERGE_PARENTS
+| | | Author: A U Thor <author@example.com>
+| | |
+| | | Merge branch 'side' (early part) into tangle
+| | |
+| * | commit COMMIT_OBJECT_NAME
+| |\ \ Merge: MERGE_PARENTS
+| | | | Author: A U Thor <author@example.com>
+| | | |
+| | | | Merge branch 'master' (early part) into tangle
+| | | |
+| * | | commit COMMIT_OBJECT_NAME
+| | | | Author: A U Thor <author@example.com>
+| | | |
+| | | | tangle-a
+| | | | ---
+| | | | tangle-a | 1 +
+| | | | 1 file changed, 1 insertion(+)
+| | | |
+| | | | diff --git a/tangle-a b/tangle-a
+| | | | new file mode 100644
+| | | | index 0000000..7898192
+| | | | --- /dev/null
+| | | | +++ b/tangle-a
+| | | | @@ -0,0 +1 @@
+| | | | +a
+| | | |
+* | | | commit COMMIT_OBJECT_NAME
+|\ \ \ \ Merge: MERGE_PARENTS
+| | | | | Author: A U Thor <author@example.com>
+| | | | |
+| | | | | Merge branch 'side'
+| | | | |
+| * | | | commit COMMIT_OBJECT_NAME
+| | |_|/ Author: A U Thor <author@example.com>
+| |/| |
+| | | | side-2
+| | | | ---
+| | | | 2 | 1 +
+| | | | 1 file changed, 1 insertion(+)
+| | | |
+| | | | diff --git a/2 b/2
+| | | | new file mode 100644
+| | | | index 0000000..0cfbf08
+| | | | --- /dev/null
+| | | | +++ b/2
+| | | | @@ -0,0 +1 @@
+| | | | +2
+| | | |
+| * | | commit COMMIT_OBJECT_NAME
+| | | | Author: A U Thor <author@example.com>
+| | | |
+| | | | side-1
+| | | | ---
+| | | | 1 | 1 +
+| | | | 1 file changed, 1 insertion(+)
+| | | |
+| | | | diff --git a/1 b/1
+| | | | new file mode 100644
+| | | | index 0000000..d00491f
+| | | | --- /dev/null
+| | | | +++ b/1
+| | | | @@ -0,0 +1 @@
+| | | | +1
+| | | |
+* | | | commit COMMIT_OBJECT_NAME
+| | | | Author: A U Thor <author@example.com>
+| | | |
+| | | | Second
+| | | | ---
+| | | | one | 1 +
+| | | | 1 file changed, 1 insertion(+)
+| | | |
+| | | | diff --git a/one b/one
+| | | | new file mode 100644
+| | | | index 0000000..9a33383
+| | | | --- /dev/null
+| | | | +++ b/one
+| | | | @@ -0,0 +1 @@
+| | | | +case
+| | | |
+* | | | commit COMMIT_OBJECT_NAME
+| |_|/ Author: A U Thor <author@example.com>
+|/| |
+| | | sixth
+| | | ---
+| | | a/two | 1 -
+| | | 1 file changed, 1 deletion(-)
+| | |
+| | | diff --git a/a/two b/a/two
+| | | deleted file mode 100644
+| | | index 9245af5..0000000
+| | | --- a/a/two
+| | | +++ /dev/null
+| | | @@ -1 +0,0 @@
+| | | -ni
+| | |
+* | | commit COMMIT_OBJECT_NAME
+| | | Author: A U Thor <author@example.com>
+| | |
+| | | fifth
+| | | ---
+| | | a/two | 1 +
+| | | 1 file changed, 1 insertion(+)
+| | |
+| | | diff --git a/a/two b/a/two
+| | | new file mode 100644
+| | | index 0000000..9245af5
+| | | --- /dev/null
+| | | +++ b/a/two
+| | | @@ -0,0 +1 @@
+| | | +ni
+| | |
+* | | commit COMMIT_OBJECT_NAME
+|/ / Author: A U Thor <author@example.com>
+| |
+| | fourth
+| | ---
+| | ein | 1 +
+| | 1 file changed, 1 insertion(+)
+| |
+| | diff --git a/ein b/ein
+| | new file mode 100644
+| | index 0000000..9d7e69f
+| | --- /dev/null
+| | +++ b/ein
+| | @@ -0,0 +1 @@
+| | +ichi
+| |
+* | commit COMMIT_OBJECT_NAME
+|/ Author: A U Thor <author@example.com>
+|
+| third
+| ---
+| ichi | 1 +
+| one | 1 -
+| 2 files changed, 1 insertion(+), 1 deletion(-)
+|
+| diff --git a/ichi b/ichi
+| new file mode 100644
+| index 0000000..9d7e69f
+| --- /dev/null
+| +++ b/ichi
+| @@ -0,0 +1 @@
+| +ichi
+| diff --git a/one b/one
+| deleted file mode 100644
+| index 9d7e69f..0000000
+| --- a/one
+| +++ /dev/null
+| @@ -1 +0,0 @@
+| -ichi
+|
+* commit COMMIT_OBJECT_NAME
+| Author: A U Thor <author@example.com>
+|
+| second
+| ---
+| one | 2 +-
+| 1 file changed, 1 insertion(+), 1 deletion(-)
+|
+| diff --git a/one b/one
+| index 5626abf..9d7e69f 100644
+| --- a/one
+| +++ b/one
+| @@ -1 +1 @@
+| -one
+| +ichi
+|
+* commit COMMIT_OBJECT_NAME
+ Author: A U Thor <author@example.com>
+
+ initial
+ ---
+ one | 1 +
+ 1 file changed, 1 insertion(+)
+
+ diff --git a/one b/one
+ new file mode 100644
+ index 0000000..5626abf
+ --- /dev/null
+ +++ b/one
+ @@ -0,0 +1 @@
+ +one
+EOF
+
+sanitize_output () {
+ sed -e 's/ *$//' \
+ -e 's/commit [0-9a-f]*$/commit COMMIT_OBJECT_NAME/' \
+ -e 's/Merge: [ 0-9a-f]*$/Merge: MERGE_PARENTS/' \
+ -e 's/Merge tag.*/Merge HEADS DESCRIPTION/' \
+ -e 's/Merge commit.*/Merge HEADS DESCRIPTION/' \
+ -e 's/, 0 deletions(-)//' \
+ -e 's/, 0 insertions(+)//' \
+ -e 's/ 1 files changed, / 1 file changed, /' \
+ -e 's/, 1 deletions(-)/, 1 deletion(-)/' \
+ -e 's/, 1 insertions(+)/, 1 insertion(+)/'
+}
+
+test_expect_success 'log --graph with diff and stats' '
+ git log --graph --pretty=short --stat -p >actual &&
+ sanitize_output >actual.sanitized <actual &&
+ test_cmp expect actual.sanitized
+'
+
test_done
diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh
index ebc36c1758..81904d9ec8 100755
--- a/t/t5100-mailinfo.sh
+++ b/t/t5100-mailinfo.sh
@@ -65,7 +65,7 @@ test_expect_success 'respect NULs' '
git mailsplit -d3 -o. "$TEST_DIRECTORY"/t5100/nul-plain &&
test_cmp "$TEST_DIRECTORY"/t5100/nul-plain 001 &&
(cat 001 | git mailinfo msg patch) &&
- test 4 = $(wc -l < patch)
+ test_line_count = 4 patch
'
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index ce51692bb2..1d1ca98588 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -326,4 +326,70 @@ EOF
test_cmp count7.expected count7.actual
'
+test_expect_success 'setup tests for the --stdin parameter' '
+ for head in C D E F
+ do
+ add $head
+ done &&
+ for head in A B C D E F
+ do
+ git tag $head $head
+ done &&
+ cat >input <<-\EOF
+ refs/heads/C
+ refs/heads/A
+ refs/heads/D
+ refs/tags/C
+ refs/heads/B
+ refs/tags/A
+ refs/heads/E
+ refs/tags/B
+ refs/tags/E
+ refs/tags/D
+ EOF
+ sort <input >expect &&
+ (
+ echo refs/heads/E &&
+ echo refs/tags/E &&
+ cat input
+ ) >input.dup
+'
+
+test_expect_success 'fetch refs from cmdline' '
+ (
+ cd client &&
+ git fetch-pack --no-progress .. $(cat ../input)
+ ) >output &&
+ cut -d " " -f 2 <output | sort >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'fetch refs from stdin' '
+ (
+ cd client &&
+ git fetch-pack --stdin --no-progress .. <../input
+ ) >output &&
+ cut -d " " -f 2 <output | sort >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'fetch mixed refs from cmdline and stdin' '
+ (
+ cd client &&
+ tail -n +5 ../input |
+ git fetch-pack --stdin --no-progress .. $(head -n 4 ../input)
+ ) >output &&
+ cut -d " " -f 2 <output | sort >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'test duplicate refs from stdin' '
+ (
+ cd client &&
+ test_must_fail git fetch-pack --stdin --no-progress .. <../input.dup
+ ) >output &&
+ cut -d " " -f 2 <output | sort >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 308c02ea75..d7a19a1829 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -162,6 +162,36 @@ test_expect_success 'fetch following tags' '
'
+test_expect_success 'fetch uses remote ref names to describe new refs' '
+ cd "$D" &&
+ git init descriptive &&
+ (
+ cd descriptive &&
+ git config remote.o.url .. &&
+ git config remote.o.fetch "refs/heads/*:refs/crazyheads/*" &&
+ git config --add remote.o.fetch "refs/others/*:refs/heads/*" &&
+ git fetch o
+ ) &&
+ git tag -a -m "Descriptive tag" descriptive-tag &&
+ git branch descriptive-branch &&
+ git checkout descriptive-branch &&
+ echo "Nuts" >crazy &&
+ git add crazy &&
+ git commit -a -m "descriptive commit" &&
+ git update-ref refs/others/crazy HEAD &&
+ (
+ cd descriptive &&
+ git fetch o 2>actual &&
+ grep " -> refs/crazyheads/descriptive-branch$" actual |
+ test_i18ngrep "new branch" &&
+ grep " -> descriptive-tag$" actual |
+ test_i18ngrep "new tag" &&
+ grep " -> crazy$" actual |
+ test_i18ngrep "new ref"
+ ) &&
+ git checkout master
+'
+
test_expect_success 'fetch must not resolve short tag name' '
cd "$D" &&
diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh
index 30bec4b5f9..1947c28c64 100755
--- a/t/t5531-deep-submodule-push.sh
+++ b/t/t5531-deep-submodule-push.sh
@@ -119,4 +119,98 @@ test_expect_success 'push succeeds if submodule has no remote and is on the firs
)
'
+test_expect_success 'push unpushed submodules when not needed' '
+ (
+ cd work &&
+ (
+ cd gar/bage &&
+ git checkout master &&
+ >junk5 &&
+ git add junk5 &&
+ git commit -m "Fifth junk" &&
+ git push &&
+ git rev-parse origin/master >../../../expected
+ ) &&
+ git checkout master &&
+ git add gar/bage &&
+ git commit -m "Fifth commit for gar/bage" &&
+ git push --recurse-submodules=on-demand ../pub.git master
+ ) &&
+ (
+ cd submodule.git &&
+ git rev-parse master >../actual
+ ) &&
+ test_cmp expected actual
+'
+
+test_expect_success 'push unpushed submodules when not needed 2' '
+ (
+ cd submodule.git &&
+ git rev-parse master >../expected
+ ) &&
+ (
+ cd work &&
+ (
+ cd gar/bage &&
+ >junk6 &&
+ git add junk6 &&
+ git commit -m "Sixth junk"
+ ) &&
+ >junk2 &&
+ git add junk2 &&
+ git commit -m "Second junk for work" &&
+ git push --recurse-submodules=on-demand ../pub.git master
+ ) &&
+ (
+ cd submodule.git &&
+ git rev-parse master >../actual
+ ) &&
+ test_cmp expected actual
+'
+
+test_expect_success 'push unpushed submodules recursively' '
+ (
+ cd work &&
+ (
+ cd gar/bage &&
+ git checkout master &&
+ > junk7 &&
+ git add junk7 &&
+ git commit -m "Seventh junk" &&
+ git rev-parse master >../../../expected
+ ) &&
+ git checkout master &&
+ git add gar/bage &&
+ git commit -m "Seventh commit for gar/bage" &&
+ git push --recurse-submodules=on-demand ../pub.git master
+ ) &&
+ (
+ cd submodule.git &&
+ git rev-parse master >../actual
+ ) &&
+ test_cmp expected actual
+'
+
+test_expect_success 'push unpushable submodule recursively fails' '
+ (
+ cd work &&
+ (
+ cd gar/bage &&
+ git rev-parse origin/master >../../../expected &&
+ git checkout master~0 &&
+ > junk8 &&
+ git add junk8 &&
+ git commit -m "Eighth junk"
+ ) &&
+ git add gar/bage &&
+ git commit -m "Eighth commit for gar/bage" &&
+ test_must_fail git push --recurse-submodules=on-demand ../pub.git master
+ ) &&
+ (
+ cd submodule.git &&
+ git rev-parse master >../actual
+ ) &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t5550-http-fetch.sh b/t/t5550-http-fetch.sh
index e5e6b8f643..b06f817af3 100755
--- a/t/t5550-http-fetch.sh
+++ b/t/t5550-http-fetch.sh
@@ -13,17 +13,22 @@ LIB_HTTPD_PORT=${LIB_HTTPD_PORT-'5550'}
start_httpd
test_expect_success 'setup repository' '
- echo content >file &&
+ echo content1 >file &&
git add file &&
git commit -m one
+ echo content2 >file &&
+ git add file &&
+ git commit -m two
'
-test_expect_success 'create http-accessible bare repository' '
- mkdir "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+test_expect_success 'create http-accessible bare repository with loose objects' '
+ cp -a .git "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
(cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
- git --bare init &&
+ git config core.bare true &&
+ mkdir -p hooks &&
echo "exec git update-server-info" >hooks/post-update &&
- chmod +x hooks/post-update
+ chmod +x hooks/post-update &&
+ hooks/post-update
) &&
git remote add public "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
git push public master:master
diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh
index 26d355725f..be6094be77 100755
--- a/t/t5551-http-fetch.sh
+++ b/t/t5551-http-fetch.sh
@@ -109,5 +109,36 @@ test_expect_success 'follow redirects (302)' '
git clone $HTTPD_URL/smart-redir-temp/repo.git --quiet repo-t
'
+test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE
+
+test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '
+ (
+ cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ for i in `seq 50000`
+ do
+ echo "commit refs/heads/too-many-refs"
+ echo "mark :$i"
+ echo "committer git <git@example.com> $i +0000"
+ echo "data 0"
+ echo "M 644 inline bla.txt"
+ echo "data 4"
+ echo "bla"
+ # make every commit dangling by always
+ # rewinding the branch after each commit
+ echo "reset refs/heads/too-many-refs"
+ echo "from :1"
+ done | git fast-import --export-marks=marks &&
+
+ # now assign tags to all the dangling commits we created above
+ tag=$(perl -e "print \"bla\" x 30") &&
+ sed -e "s/^:\(.\+\) \(.\+\)$/\2 refs\/tags\/$tag-\1/" <marks >>packed-refs
+ )
+'
+
+test_expect_success EXPENSIVE 'clone the 50,000 tag repo to check OS command line overflow' '
+ git clone $HTTPD_URL/smart/repo.git too-many-refs 2>err &&
+ test_line_count = 0 err
+'
+
stop_httpd
test_done
diff --git a/t/t5700-clone-reference.sh b/t/t5700-clone-reference.sh
index bbc4691bd7..c47d450cc3 100755
--- a/t/t5700-clone-reference.sh
+++ b/t/t5700-clone-reference.sh
@@ -34,7 +34,7 @@ test_expect_success 'cloning with reference (-l -s)' \
cd "$base_dir"
test_expect_success 'existence of info/alternates' \
-'test `wc -l <C/.git/objects/info/alternates` = 2'
+'test_line_count = 2 C/.git/objects/info/alternates'
cd "$base_dir"
@@ -63,7 +63,7 @@ test_expect_success 'fetched no objects' \
cd "$base_dir"
test_expect_success 'existence of info/alternates' \
-'test `wc -l <D/.git/objects/info/alternates` = 1'
+'test_line_count = 1 D/.git/objects/info/alternates'
cd "$base_dir"
diff --git a/t/t5710-info-alternate.sh b/t/t5710-info-alternate.sh
index ef7127c1b3..aa045295de 100755
--- a/t/t5710-info-alternate.sh
+++ b/t/t5710-info-alternate.sh
@@ -18,7 +18,7 @@ reachable_via() {
test_valid_repo() {
git fsck --full > fsck.log &&
- test `wc -l < fsck.log` = 0
+ test_line_count = 0 fsck.log
}
base_dir=`pwd`
diff --git a/t/t5800-remote-helpers.sh b/t/t5800-remote-helpers.sh
index 1c62001fce..5702334510 100755
--- a/t/t5800-remote-helpers.sh
+++ b/t/t5800-remote-helpers.sh
@@ -72,6 +72,19 @@ test_expect_success 'pushing to local repo' '
compare_refs localclone HEAD server HEAD
'
+# Generally, skip this test. It demonstrates a now-fixed race in
+# git-remote-testgit, but is too slow to leave in for general use.
+: test_expect_success 'racily pushing to local repo' '
+ test_when_finished "rm -rf server2 localclone2" &&
+ cp -a server server2 &&
+ git clone "testgit::${PWD}/server2" localclone2 &&
+ (cd localclone2 &&
+ echo content >>file &&
+ git commit -a -m three &&
+ GIT_REMOTE_TESTGIT_SLEEPY=2 git push) &&
+ compare_refs localclone2 HEAD server2 HEAD
+'
+
test_expect_success 'synch with changes from localclone' '
(cd clone &&
git pull)
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 444279077e..a01d244502 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -188,23 +188,23 @@ test_expect_success 'empty email' '
test_expect_success 'del LF before empty (1)' '
git show -s --pretty=format:"%s%n%-b%nThanks%n" HEAD^^ >actual &&
- test $(wc -l <actual) = 2
+ test_line_count = 2 actual
'
test_expect_success 'del LF before empty (2)' '
git show -s --pretty=format:"%s%n%-b%nThanks%n" HEAD >actual &&
- test $(wc -l <actual) = 6 &&
+ test_line_count = 6 actual &&
grep "^$" actual
'
test_expect_success 'add LF before non-empty (1)' '
git show -s --pretty=format:"%s%+b%nThanks%n" HEAD^^ >actual &&
- test $(wc -l <actual) = 2
+ test_line_count = 2 actual
'
test_expect_success 'add LF before non-empty (2)' '
git show -s --pretty=format:"%s%+b%nThanks%n" HEAD >actual &&
- test $(wc -l <actual) = 6 &&
+ test_line_count = 6 actual &&
grep "^$" actual
'
@@ -278,8 +278,9 @@ test_expect_success 'oneline with empty message' '
git commit -m "dummy" --allow-empty &&
git filter-branch --msg-filter "sed -e s/dummy//" HEAD^^.. &&
git rev-list --oneline HEAD >test.txt &&
- test $(git rev-list --oneline HEAD | wc -l) -eq 5 &&
- test $(git rev-list --oneline --graph HEAD | wc -l) -eq 5
+ test_line_count = 5 test.txt &&
+ git rev-list --oneline --graph HEAD >testg.txt &&
+ test_line_count = 5 testg.txt
'
test_done
diff --git a/t/t6028-merge-up-to-date.sh b/t/t6028-merge-up-to-date.sh
index a91644e3b2..c518e9c30c 100755
--- a/t/t6028-merge-up-to-date.sh
+++ b/t/t6028-merge-up-to-date.sh
@@ -16,7 +16,12 @@ test_expect_success setup '
test_tick &&
git commit -m second &&
git tag c1 &&
- git branch test
+ git branch test &&
+ echo third >file &&
+ git add file &&
+ test_tick &&
+ git commit -m third &&
+ git tag c2
'
test_expect_success 'merge -s recursive up-to-date' '
@@ -74,4 +79,14 @@ test_expect_success 'merge -s subtree up-to-date' '
'
+test_expect_success 'merge fast-forward octopus' '
+
+ git reset --hard c0 &&
+ test_tick &&
+ git merge c1 c2
+ expect=$(git rev-parse c2) &&
+ current=$(git rev-parse HEAD) &&
+ test "$expect" = "$current"
+'
+
test_done
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 691e4a4481..72e28ee535 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -480,7 +480,7 @@ test_expect_success 'many merge bases creation' '
git merge -m "merge HASH7 and SIDE_HASH7" "$HASH7" &&
B_HASH=$(git rev-parse --verify HEAD) &&
git merge-base --all "$A_HASH" "$B_HASH" > merge_bases.txt &&
- test $(wc -l < merge_bases.txt) = "2" &&
+ test_line_count = 2 merge_bases.txt &&
grep "$HASH5" merge_bases.txt &&
grep "$SIDE_HASH5" merge_bases.txt
'
diff --git a/t/t6032-merge-large-rename.sh b/t/t6032-merge-large-rename.sh
index 94f010be8a..15beecc3c6 100755
--- a/t/t6032-merge-large-rename.sh
+++ b/t/t6032-merge-large-rename.sh
@@ -97,7 +97,7 @@ test_expect_success 'setup large simple rename' '
test_expect_success 'massive simple rename does not spam added files' '
sane_unset GIT_MERGE_VERBOSITY &&
git merge --no-stat simple-rename | grep -v Removing >output &&
- test 5 -gt "$(wc -l < output)"
+ test_line_count -lt 5 output
'
test_done
diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
index 19272bc551..ec2b516c3f 100755
--- a/t/t6040-tracking-info.sh
+++ b/t/t6040-tracking-info.sh
@@ -71,13 +71,13 @@ test_expect_success 'checkout' '
(
cd test && git checkout b1
) >actual &&
- grep "have 1 and 1 different" actual
+ test_i18ngrep "have 1 and 1 different" actual
'
test_expect_success 'checkout with local tracked branch' '
git checkout master &&
git checkout follower >actual &&
- grep "is ahead of" actual
+ test_i18ngrep "is ahead of" actual
'
test_expect_success 'status' '
@@ -87,14 +87,14 @@ test_expect_success 'status' '
# reports nothing to commit
test_must_fail git commit --dry-run
) >actual &&
- grep "have 1 and 1 different" actual
+ test_i18ngrep "have 1 and 1 different" actual
'
test_expect_success 'fail to track lightweight tags' '
git checkout master &&
git tag light &&
test_must_fail git branch --track lighttrack light >actual &&
- test_must_fail grep "set up to track" actual &&
+ test_i18ngrep ! "set up to track" actual &&
test_must_fail git checkout lighttrack
'
@@ -102,7 +102,7 @@ test_expect_success 'fail to track annotated tags' '
git checkout master &&
git tag -m heavy heavy &&
test_must_fail git branch --track heavytrack heavy >actual &&
- test_must_fail grep "set up to track" actual &&
+ test_i18ngrep ! "set up to track" actual &&
test_must_fail git checkout heavytrack
'
diff --git a/t/t6042-merge-rename-corner-cases.sh b/t/t6042-merge-rename-corner-cases.sh
index 32591f9413..466fa3804b 100755
--- a/t/t6042-merge-rename-corner-cases.sh
+++ b/t/t6042-merge-rename-corner-cases.sh
@@ -104,7 +104,7 @@ test_expect_failure 'conflict caused if rename not detected' '
test 0 -eq $(git ls-files -u | wc -l) &&
test 0 -eq $(git ls-files -o | wc -l) &&
- test 6 -eq $(wc -l < c) &&
+ test_line_count = 6 c &&
test $(git rev-parse HEAD:a) = $(git rev-parse B:a) &&
test $(git rev-parse HEAD:b) = $(git rev-parse A:b)
'
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 07fb53adcb..be9672e5a0 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -229,7 +229,7 @@ test_expect_success 'checkout to detach HEAD (with advice declined)' '
git checkout -f renamer && git clean -f &&
git checkout renamer^ 2>messages &&
test_i18ngrep "HEAD is now at 7329388" messages &&
- test 1 -eq $(wc -l <messages) &&
+ test_line_count = 1 messages &&
H=$(git rev-parse --verify HEAD) &&
M=$(git show-ref -s --verify refs/heads/master) &&
test "z$H" = "z$M" &&
@@ -247,7 +247,7 @@ test_expect_success 'checkout to detach HEAD' '
git checkout -f renamer && git clean -f &&
git checkout renamer^ 2>messages &&
test_i18ngrep "HEAD is now at 7329388" messages &&
- test 1 -lt $(wc -l <messages) &&
+ test_line_count -gt 1 messages &&
H=$(git rev-parse --verify HEAD) &&
M=$(git show-ref -s --verify refs/heads/master) &&
test "z$H" = "z$M" &&
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index b377a7af28..81827e696f 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -234,7 +234,7 @@ EOF
test_expect_success 'status should only print one line' '
git submodule status >lines &&
- test $(wc -l <lines) = 1
+ test_line_count = 1 lines
'
test_expect_success 'setup - fetch commit name from submodule' '
diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh
index ab37c368d0..a45fadc58e 100755
--- a/t/t7408-submodule-reference.sh
+++ b/t/t7408-submodule-reference.sh
@@ -43,7 +43,7 @@ git commit -m B-super-added'
cd "$base_dir"
test_expect_success 'after add: existence of info/alternates' \
-'test `wc -l <super/.git/modules/sub/objects/info/alternates` = 1'
+'test_line_count = 1 super/.git/modules/sub/objects/info/alternates'
cd "$base_dir"
@@ -66,7 +66,7 @@ test_expect_success 'update with reference' \
cd "$base_dir"
test_expect_success 'after update: existence of info/alternates' \
-'test `wc -l <super-clone/.git/modules/sub/objects/info/alternates` = 1'
+'test_line_count = 1 super-clone/.git/modules/sub/objects/info/alternates'
cd "$base_dir"
diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh
index 3f3adc31b9..181456aa9a 100755
--- a/t/t7502-commit.sh
+++ b/t/t7502-commit.sh
@@ -335,7 +335,7 @@ test_expect_success 'A single-liner subject with a token plus colon is not a foo
git reset --hard &&
git commit -s -m "hello: kitty" --allow-empty &&
git cat-file commit HEAD | sed -e "1,/^$/d" >actual &&
- test $(wc -l <actual) = 3
+ test_line_count = 3 actual
'
diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh
index bce0bd37cb..3b72c097ee 100755
--- a/t/t7602-merge-octopus-many.sh
+++ b/t/t7602-merge-octopus-many.sh
@@ -70,16 +70,14 @@ test_expect_success 'merge output uses pretty names' '
'
cat >expected <<\EOF
-Already up-to-date with c4
-Trying simple merge with c5
-Merge made by the 'octopus' strategy.
+Merge made by the 'recursive' strategy.
c5.c | 1 +
1 file changed, 1 insertion(+)
create mode 100644 c5.c
EOF
-test_expect_success 'merge up-to-date output uses pretty names' '
- git merge c4 c5 >actual &&
+test_expect_success 'merge reduces irrelevant remote heads' '
+ GIT_MERGE_VERBOSITY=0 git merge c4 c5 >actual &&
test_i18ncmp expected actual
'
diff --git a/t/t7603-merge-reduce-heads.sh b/t/t7603-merge-reduce-heads.sh
index 7e17eb490d..98948955ae 100755
--- a/t/t7603-merge-reduce-heads.sh
+++ b/t/t7603-merge-reduce-heads.sh
@@ -57,7 +57,36 @@ test_expect_success 'merge c1 with c2, c3, c4, c5' '
test -f c2.c &&
test -f c3.c &&
test -f c4.c &&
- test -f c5.c
+ test -f c5.c &&
+ git show --format=%s -s >actual &&
+ ! grep c1 actual &&
+ grep c2 actual &&
+ grep c3 actual &&
+ ! grep c4 actual &&
+ grep c5 actual
+'
+
+test_expect_success 'pull c2, c3, c4, c5 into c1' '
+ git reset --hard c1 &&
+ git pull . c2 c3 c4 c5 &&
+ test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
+ test "$(git rev-parse c1)" = "$(git rev-parse HEAD^1)" &&
+ test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" &&
+ test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" &&
+ test "$(git rev-parse c5)" = "$(git rev-parse HEAD^4)" &&
+ git diff --exit-code &&
+ test -f c0.c &&
+ test -f c1.c &&
+ test -f c2.c &&
+ test -f c3.c &&
+ test -f c4.c &&
+ test -f c5.c &&
+ git show --format=%s -s >actual &&
+ ! grep c1 actual &&
+ grep c2 actual &&
+ grep c3 actual &&
+ ! grep c4 actual &&
+ grep c5 actual
'
test_expect_success 'setup' '
@@ -113,4 +142,23 @@ test_expect_success 'verify merge result' '
test $(git rev-parse HEAD^1) = $(git rev-parse E2) &&
test $(git rev-parse HEAD^2) = $(git rev-parse I2)
'
+
+test_expect_success 'fast-forward to redundant refs' '
+ git reset --hard c0 &&
+ git merge c4 c5
+'
+
+test_expect_success 'verify merge result' '
+ test $(git rev-parse HEAD) = $(git rev-parse c5)
+'
+
+test_expect_success 'merge up-to-date redundant refs' '
+ git reset --hard c5 &&
+ git merge c0 c4
+'
+
+test_expect_success 'verify merge result' '
+ test $(git rev-parse HEAD) = $(git rev-parse c5)
+'
+
test_done
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index 200ab61278..b8d4cdea8c 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -95,4 +95,18 @@ test_expect_success 'unpacked objects receive timestamp of pack file' '
compare_mtimes < mtimes
'
+test_expect_success 'do not bother loosening old objects' '
+ obj1=$(echo one | git hash-object -w --stdin) &&
+ obj2=$(echo two | git hash-object -w --stdin) &&
+ pack1=$(echo $obj1 | git pack-objects .git/objects/pack/pack) &&
+ pack2=$(echo $obj2 | git pack-objects .git/objects/pack/pack) &&
+ git prune-packed &&
+ git cat-file -p $obj1 &&
+ git cat-file -p $obj2 &&
+ test-chmtime =-86400 .git/objects/pack/pack-$pack2.pack &&
+ git repack -A -d --unpack-unreachable=1.hour.ago &&
+ git cat-file -p $obj1 &&
+ test_must_fail git cat-file -p $obj2
+'
+
test_done
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 0f5b5e5964..7da0e8da7b 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -24,6 +24,13 @@ head_c () {
' - "$1"
}
+verify_packs () {
+ for p in .git/objects/pack/*.pack
+ do
+ git verify-pack "$@" "$p" || return
+ done
+}
+
file2_data='file2
second line of EOF'
@@ -105,9 +112,10 @@ test_expect_success \
'A: create pack from stdin' \
'git fast-import --export-marks=marks.out <input &&
git whatchanged master'
-test_expect_success \
- 'A: verify pack' \
- 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'
+
+test_expect_success 'A: verify pack' '
+ verify_packs
+'
cat >expect <<EOF
author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
@@ -252,9 +260,11 @@ test_expect_success \
'A: verify marks import does not crash' \
'git fast-import --import-marks=marks.out <input &&
git whatchanged verify--import-marks'
-test_expect_success \
- 'A: verify pack' \
- 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'
+
+test_expect_success 'A: verify pack' '
+ verify_packs
+'
+
cat >expect <<EOF
:000000 100755 0000000000000000000000000000000000000000 7123f7f44e39be127c5eb701e5968176ee9d78b1 A copy-of-file2
EOF
@@ -514,9 +524,11 @@ test_expect_success \
'C: incremental import create pack from stdin' \
'git fast-import <input &&
git whatchanged branch'
-test_expect_success \
- 'C: verify pack' \
- 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'
+
+test_expect_success 'C: verify pack' '
+ verify_packs
+'
+
test_expect_success \
'C: validate reuse existing blob' \
'test $newf = `git rev-parse --verify branch:file2/newf` &&
@@ -572,9 +584,10 @@ test_expect_success \
'D: inline data in commit' \
'git fast-import <input &&
git whatchanged branch'
-test_expect_success \
- 'D: verify pack' \
- 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'
+
+test_expect_success 'D: verify pack' '
+ verify_packs
+'
cat >expect <<EOF
:000000 100755 0000000000000000000000000000000000000000 35a59026a33beac1569b1c7f66f3090ce9c09afc A newdir/exec.sh
@@ -618,9 +631,10 @@ test_expect_success 'E: rfc2822 date, --date-format=raw' '
test_expect_success \
'E: rfc2822 date, --date-format=rfc2822' \
'git fast-import --date-format=rfc2822 <input'
-test_expect_success \
- 'E: verify pack' \
- 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'
+
+test_expect_success 'E: verify pack' '
+ verify_packs
+'
cat >expect <<EOF
author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 1170778938 -0500
@@ -669,9 +683,10 @@ test_expect_success \
fi
fi
'
-test_expect_success \
- 'F: verify pack' \
- 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'
+
+test_expect_success 'F: verify pack' '
+ verify_packs
+'
cat >expect <<EOF
tree `git rev-parse branch~1^{tree}`
@@ -705,9 +720,11 @@ INPUT_END
test_expect_success \
'G: non-fast-forward update forced' \
'git fast-import --force <input'
-test_expect_success \
- 'G: verify pack' \
- 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'
+
+test_expect_success 'G: verify pack' '
+ verify_packs
+'
+
test_expect_success \
'G: branch changed, but logged' \
'test $old_branch != `git rev-parse --verify branch^0` &&
@@ -742,9 +759,10 @@ test_expect_success \
'H: deletall, add 1' \
'git fast-import <input &&
git whatchanged H'
-test_expect_success \
- 'H: verify pack' \
- 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'
+
+test_expect_success 'H: verify pack' '
+ verify_packs
+'
cat >expect <<EOF
:100755 000000 f1fb5da718392694d0076d677d6d0e364c79b0bc 0000000000000000000000000000000000000000 D file2/newf
@@ -1857,9 +1875,10 @@ test_expect_success \
'Q: commit notes' \
'git fast-import <input &&
git whatchanged notes-test'
-test_expect_success \
- 'Q: verify pack' \
- 'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'
+
+test_expect_success 'Q: verify pack' '
+ verify_packs
+'
commit1=$(git rev-parse notes-test~2)
commit2=$(git rev-parse notes-test^)
@@ -2616,13 +2635,14 @@ test_expect_success \
'R: blob bigger than threshold' \
'test_create_repo R &&
git --git-dir=R/.git fast-import --big-file-threshold=1 <input'
-test_expect_success \
- 'R: verify created pack' \
- ': >verify &&
- for p in R/.git/objects/pack/*.pack;
- do
- git verify-pack -v $p >>verify || exit;
- done'
+
+test_expect_success 'R: verify created pack' '
+ (
+ cd R &&
+ verify_packs -v > ../verify
+ )
+'
+
test_expect_success \
'R: verify written objects' \
'git --git-dir=R/.git cat-file blob big-file:big1 >actual &&
@@ -2635,4 +2655,291 @@ test_expect_success \
'n=$(grep $a verify | wc -l) &&
test 1 = $n'
+###
+### series S
+###
+#
+# Make sure missing spaces and EOLs after mark references
+# cause errors.
+#
+# Setup:
+#
+# 1--2--4
+# \ /
+# -3-
+#
+# commit marks: 301, 302, 303, 304
+# blob marks: 403, 404, resp.
+# note mark: 202
+#
+# The error message when a space is missing not at the
+# end of the line is:
+#
+# Missing space after ..
+#
+# or when extra characters come after the mark at the end
+# of the line:
+#
+# Garbage after ..
+#
+# or when the dataref is neither "inline " or a known SHA1,
+#
+# Invalid dataref ..
+#
+test_tick
+
+cat >input <<INPUT_END
+commit refs/heads/S
+mark :301
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+commit 1
+COMMIT
+M 100644 inline hello.c
+data <<BLOB
+blob 1
+BLOB
+
+commit refs/heads/S
+mark :302
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+commit 2
+COMMIT
+from :301
+M 100644 inline hello.c
+data <<BLOB
+blob 2
+BLOB
+
+blob
+mark :403
+data <<BLOB
+blob 3
+BLOB
+
+blob
+mark :202
+data <<BLOB
+note 2
+BLOB
+INPUT_END
+
+test_expect_success 'S: initialize for S tests' '
+ git fast-import --export-marks=marks <input
+'
+
+#
+# filemodify, three datarefs
+#
+test_expect_success 'S: filemodify with garbage after mark must fail' '
+ test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
+ commit refs/heads/S
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ commit N
+ COMMIT
+ M 100644 :403x hello.c
+ EOF
+ cat err &&
+ test_i18ngrep "space after mark" err
+'
+
+# inline is misspelled; fast-import thinks it is some unknown dataref
+test_expect_success 'S: filemodify with garbage after inline must fail' '
+ test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
+ commit refs/heads/S
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ commit N
+ COMMIT
+ M 100644 inlineX hello.c
+ data <<BLOB
+ inline
+ BLOB
+ EOF
+ cat err &&
+ test_i18ngrep "nvalid dataref" err
+'
+
+test_expect_success 'S: filemodify with garbage after sha1 must fail' '
+ sha1=$(grep :403 marks | cut -d\ -f2) &&
+ test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
+ commit refs/heads/S
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ commit N
+ COMMIT
+ M 100644 ${sha1}x hello.c
+ EOF
+ cat err &&
+ test_i18ngrep "space after SHA1" err
+'
+
+#
+# notemodify, three ways to say dataref
+#
+test_expect_success 'S: notemodify with garabge after mark dataref must fail' '
+ test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
+ commit refs/heads/S
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ commit S note dataref markref
+ COMMIT
+ N :202x :302
+ EOF
+ cat err &&
+ test_i18ngrep "space after mark" err
+'
+
+test_expect_success 'S: notemodify with garbage after inline dataref must fail' '
+ test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
+ commit refs/heads/S
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ commit S note dataref inline
+ COMMIT
+ N inlineX :302
+ data <<BLOB
+ note blob
+ BLOB
+ EOF
+ cat err &&
+ test_i18ngrep "nvalid dataref" err
+'
+
+test_expect_success 'S: notemodify with garbage after sha1 dataref must fail' '
+ sha1=$(grep :202 marks | cut -d\ -f2) &&
+ test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
+ commit refs/heads/S
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ commit S note dataref sha1
+ COMMIT
+ N ${sha1}x :302
+ EOF
+ cat err &&
+ test_i18ngrep "space after SHA1" err
+'
+
+#
+# notemodify, mark in committish
+#
+test_expect_success 'S: notemodify with garbarge after mark committish must fail' '
+ test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
+ commit refs/heads/Snotes
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ commit S note committish
+ COMMIT
+ N :202 :302x
+ EOF
+ cat err &&
+ test_i18ngrep "after mark" err
+'
+
+#
+# from
+#
+test_expect_success 'S: from with garbage after mark must fail' '
+ # no &&
+ git fast-import --import-marks=marks --export-marks=marks <<-EOF 2>err
+ commit refs/heads/S2
+ mark :303
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ commit 3
+ COMMIT
+ from :301x
+ M 100644 :403 hello.c
+ EOF
+
+ ret=$? &&
+ echo returned $ret &&
+ test $ret -ne 0 && # failed, but it created the commit
+
+ # go create the commit, need it for merge test
+ git fast-import --import-marks=marks --export-marks=marks <<-EOF &&
+ commit refs/heads/S2
+ mark :303
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ commit 3
+ COMMIT
+ from :301
+ M 100644 :403 hello.c
+ EOF
+
+ # now evaluate the error
+ cat err &&
+ test_i18ngrep "after mark" err
+'
+
+
+#
+# merge
+#
+test_expect_success 'S: merge with garbage after mark must fail' '
+ test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
+ commit refs/heads/S
+ mark :304
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ merge 4
+ COMMIT
+ from :302
+ merge :303x
+ M 100644 :403 hello.c
+ EOF
+ cat err &&
+ test_i18ngrep "after mark" err
+'
+
+#
+# tag, from markref
+#
+test_expect_success 'S: tag with garbage after mark must fail' '
+ test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
+ tag refs/tags/Stag
+ from :302x
+ tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<TAG
+ tag S
+ TAG
+ EOF
+ cat err &&
+ test_i18ngrep "after mark" err
+'
+
+#
+# cat-blob markref
+#
+test_expect_success 'S: cat-blob with garbage after mark must fail' '
+ test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
+ cat-blob :403x
+ EOF
+ cat err &&
+ test_i18ngrep "after mark" err
+'
+
+#
+# ls markref
+#
+test_expect_success 'S: ls with garbage after mark must fail' '
+ test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
+ ls :302x hello.c
+ EOF
+ cat err &&
+ test_i18ngrep "space after mark" err
+'
+
+test_expect_success 'S: ls with garbage after sha1 must fail' '
+ sha1=$(grep :302 marks | cut -d\ -f2) &&
+ test_must_fail git fast-import --import-marks=marks <<-EOF 2>err &&
+ ls ${sha1}x hello.c
+ EOF
+ cat err &&
+ test_i18ngrep "space after tree-ish" err
+'
+
test_done
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 950d0ff498..b00196bd23 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -86,7 +86,7 @@ test_expect_success 'import/export-marks' '
git checkout -b marks master &&
git fast-export --export-marks=tmp-marks HEAD &&
test -s tmp-marks &&
- test $(wc -l < tmp-marks) -eq 3 &&
+ test_line_count = 3 tmp-marks &&
test $(
git fast-export --import-marks=tmp-marks\
--export-marks=tmp-marks HEAD |
@@ -101,7 +101,7 @@ test_expect_success 'import/export-marks' '
grep ^commit\ |
wc -l) \
-eq 1 &&
- test $(wc -l < tmp-marks) -eq 4
+ test_line_count = 4 tmp-marks
'
diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh
index 9199550ef4..806623e885 100755
--- a/t/t9400-git-cvsserver-server.sh
+++ b/t/t9400-git-cvsserver-server.sh
@@ -476,14 +476,14 @@ test_expect_success 'cvs status' '
cd cvswork &&
GIT_CONFIG="$git_config" cvs update &&
GIT_CONFIG="$git_config" cvs status | grep "^File: status.file" >../out &&
- test $(wc -l <../out) = 2
+ test_line_count = 2 ../out
'
cd "$WORKDIR"
test_expect_success 'cvs status (nonrecursive)' '
cd cvswork &&
GIT_CONFIG="$git_config" cvs status -l | grep "^File: status.file" >../out &&
- test $(wc -l <../out) = 1
+ test_line_count = 1 ../out
'
cd "$WORKDIR"
@@ -500,8 +500,8 @@ test_expect_success 'cvs status (no subdirs in header)' '
cd "$WORKDIR"
test_expect_success 'cvs co -c (shows module database)' '
GIT_CONFIG="$git_config" cvs co -c > out &&
- grep "^master[ ]\+master$" < out &&
- ! grep -v "^master[ ]\+master$" < out
+ grep "^master[ ][ ]*master$" <out &&
+ ! grep -v "^master[ ][ ]*master$" <out
'
#------------
diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh
index 486c8eeb7e..b2f08697ad 100755
--- a/t/t9800-git-p4-basic.sh
+++ b/t/t9800-git-p4-basic.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-p4 tests'
+test_description='git p4 tests'
. ./lib-git-p4.sh
@@ -20,8 +20,8 @@ test_expect_success 'add p4 files' '
)
'
-test_expect_success 'basic git-p4 clone' '
- "$GITP4" clone --dest="$git" //depot &&
+test_expect_success 'basic git p4 clone' '
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -30,8 +30,8 @@ test_expect_success 'basic git-p4 clone' '
)
'
-test_expect_success 'git-p4 clone @all' '
- "$GITP4" clone --dest="$git" //depot@all &&
+test_expect_success 'git p4 clone @all' '
+ git p4 clone --dest="$git" //depot@all &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -40,12 +40,12 @@ test_expect_success 'git-p4 clone @all' '
)
'
-test_expect_success 'git-p4 sync uninitialized repo' '
+test_expect_success 'git p4 sync uninitialized repo' '
test_create_repo "$git" &&
test_when_finished cleanup_git &&
(
cd "$git" &&
- test_must_fail "$GITP4" sync
+ test_must_fail git p4 sync
)
'
@@ -53,13 +53,13 @@ test_expect_success 'git-p4 sync uninitialized repo' '
# Create a git repo by hand. Add a commit so that HEAD is valid.
# Test imports a new p4 repository into a new git branch.
#
-test_expect_success 'git-p4 sync new branch' '
+test_expect_success 'git p4 sync new branch' '
test_create_repo "$git" &&
test_when_finished cleanup_git &&
(
cd "$git" &&
test_commit head &&
- "$GITP4" sync --branch=refs/remotes/p4/depot //depot@all &&
+ git p4 sync --branch=refs/remotes/p4/depot //depot@all &&
git log --oneline p4/depot >lines &&
test_line_count = 2 lines
)
@@ -76,7 +76,7 @@ test_expect_success 'clone two dirs' '
p4 add sub2/f2 &&
p4 submit -d "sub2/f2"
) &&
- "$GITP4" clone --dest="$git" //depot/sub1 //depot/sub2 &&
+ git p4 clone --dest="$git" //depot/sub1 //depot/sub2 &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -94,7 +94,7 @@ test_expect_success 'clone two dirs, @all' '
p4 add sub1/f3 &&
p4 submit -d "sub1/f3"
) &&
- "$GITP4" clone --dest="$git" //depot/sub1@all //depot/sub2@all &&
+ git p4 clone --dest="$git" //depot/sub1@all //depot/sub2@all &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -112,7 +112,7 @@ test_expect_success 'clone two dirs, @all, conflicting files' '
p4 add sub2/f3 &&
p4 submit -d "sub2/f3"
) &&
- "$GITP4" clone --dest="$git" //depot/sub1@all //depot/sub2@all &&
+ git p4 clone --dest="$git" //depot/sub1@all //depot/sub2@all &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -134,7 +134,7 @@ test_expect_success 'exit when p4 fails to produce marshaled output' '
exit 1
EOF
chmod 755 "$badp4dir"/p4 &&
- PATH="$badp4dir:$PATH" "$GITP4" clone --dest="$git" //depot >errs 2>&1 ; retval=$? &&
+ PATH="$badp4dir:$PATH" git p4 clone --dest="$git" //depot >errs 2>&1 ; retval=$? &&
test $retval -eq 1 &&
test_must_fail grep -q Traceback errs
'
@@ -151,8 +151,8 @@ test_expect_success 'add p4 files with wildcards in the names' '
)
'
-test_expect_success 'wildcard files git-p4 clone' '
- "$GITP4" clone --dest="$git" //depot &&
+test_expect_success 'wildcard files git p4 clone' '
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -164,7 +164,7 @@ test_expect_success 'wildcard files git-p4 clone' '
'
test_expect_success 'clone bare' '
- "$GITP4" clone --dest="$git" --bare //depot &&
+ git p4 clone --dest="$git" --bare //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -209,7 +209,7 @@ test_expect_success 'preserve users' '
p4_add_user alice Alice &&
p4_add_user bob Bob &&
p4_grant_admin alice &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -218,7 +218,7 @@ test_expect_success 'preserve users' '
git commit --author "Alice <alice@localhost>" -m "a change by alice" file1 &&
git commit --author "Bob <bob@localhost>" -m "a change by bob" file2 &&
git config git-p4.skipSubmitEditCheck true &&
- P4EDITOR=touch P4USER=alice P4PASSWD=secret "$GITP4" commit --preserve-user &&
+ P4EDITOR=touch P4USER=alice P4PASSWD=secret git p4 commit --preserve-user &&
p4_check_commit_author file1 alice &&
p4_check_commit_author file2 bob
)
@@ -227,7 +227,7 @@ test_expect_success 'preserve users' '
# Test username support, submitting as bob, who lacks admin rights. Should
# not submit change to p4 (git diff should show deltas).
test_expect_success 'refuse to preserve users without perms' '
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -236,14 +236,14 @@ test_expect_success 'refuse to preserve users without perms' '
git commit --author "Alice <alice@localhost>" -m "perms: a change by alice" file1 &&
P4EDITOR=touch P4USER=bob P4PASSWD=secret &&
export P4EDITOR P4USER P4PASSWD &&
- test_must_fail "$GITP4" commit --preserve-user &&
+ test_must_fail git p4 commit --preserve-user &&
! git diff --exit-code HEAD..p4/master
)
'
# What happens with unknown author? Without allowMissingP4Users it should fail.
test_expect_success 'preserve user where author is unknown to p4' '
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -254,24 +254,24 @@ test_expect_success 'preserve user where author is unknown to p4' '
git commit --author "Charlie <charlie@localhost>" -m "preserve: a change by charlie" file1 &&
P4EDITOR=touch P4USER=alice P4PASSWD=secret &&
export P4EDITOR P4USER P4PASSWD &&
- test_must_fail "$GITP4" commit --preserve-user &&
+ test_must_fail git p4 commit --preserve-user &&
! git diff --exit-code HEAD..p4/master &&
echo "$0: repeat with allowMissingP4Users enabled" &&
git config git-p4.allowMissingP4Users true &&
git config git-p4.preserveUser true &&
- "$GITP4" commit &&
+ git p4 commit &&
git diff --exit-code HEAD..p4/master &&
p4_check_commit_author file1 alice
)
'
-# If we're *not* using --preserve-user, git-p4 should warn if we're submitting
+# If we're *not* using --preserve-user, git p4 should warn if we're submitting
# changes that are not all ours.
# Test: user in p4 and user unknown to p4.
# Test: warning disabled and user is the same.
test_expect_success 'not preserving user with mixed authorship' '
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -281,20 +281,20 @@ test_expect_success 'not preserving user with mixed authorship' '
make_change_by_user usernamefile3 Derek derek@localhost &&
P4EDITOR=cat P4USER=alice P4PASSWD=secret &&
export P4EDITOR P4USER P4PASSWD &&
- "$GITP4" commit |\
+ git p4 commit |\
grep "git author derek@localhost does not match" &&
make_change_by_user usernamefile3 Charlie charlie@localhost &&
- "$GITP4" commit |\
+ git p4 commit |\
grep "git author charlie@localhost does not match" &&
make_change_by_user usernamefile3 alice alice@localhost &&
- "$GITP4" commit |\
+ git p4 commit |\
test_must_fail grep "git author.*does not match" &&
git config git-p4.skipUserNameCheck true &&
make_change_by_user usernamefile3 Charlie charlie@localhost &&
- "$GITP4" commit |\
+ git p4 commit |\
test_must_fail grep "git author.*does not match" &&
p4_check_commit_author usernamefile3 alice
@@ -313,7 +313,7 @@ test_expect_success 'initial import time from top change time' '
p4change=$(p4 -G changes -m 1 //depot/... | marshal_dump change) &&
p4time=$(p4 -G changes -m 1 //depot/... | marshal_dump time) &&
sleep 3 &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -331,16 +331,16 @@ test_expect_success 'initial import time from top change time' '
# Repeat, this time with a smaller threshold and confirm that the rename is
# detected in P4.
test_expect_success 'detect renames' '
- "$GITP4" clone --dest="$git" //depot@all &&
+ git p4 clone --dest="$git" //depot@all &&
test_when_finished cleanup_git &&
(
cd "$git" &&
- git config git-p4.skipSubmitEditCheck true &&
+ git config git-p4.skipSubmitEdit true &&
git mv file1 file4 &&
git commit -a -m "Rename file1 to file4" &&
git diff-tree -r -M HEAD &&
- "$GITP4" submit &&
+ git p4 submit &&
p4 filelog //depot/file4 &&
p4 filelog //depot/file4 | test_must_fail grep -q "branch from" &&
@@ -348,7 +348,7 @@ test_expect_success 'detect renames' '
git commit -a -m "Rename file4 to file5" &&
git diff-tree -r -M HEAD &&
git config git-p4.detectRenames true &&
- "$GITP4" submit &&
+ git p4 submit &&
p4 filelog //depot/file5 &&
p4 filelog //depot/file5 | grep -q "branch from //depot/file4" &&
@@ -360,7 +360,7 @@ test_expect_success 'detect renames' '
level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") &&
test -n "$level" && test "$level" -gt 0 && test "$level" -lt 98 &&
git config git-p4.detectRenames $(($level + 2)) &&
- "$GITP4" submit &&
+ git p4 submit &&
p4 filelog //depot/file6 &&
p4 filelog //depot/file6 | test_must_fail grep -q "branch from" &&
@@ -372,7 +372,7 @@ test_expect_success 'detect renames' '
level=$(git diff-tree -r -M HEAD | sed 1d | cut -f1 | cut -d" " -f5 | sed "s/R0*//") &&
test -n "$level" && test "$level" -gt 2 && test "$level" -lt 100 &&
git config git-p4.detectRenames $(($level - 2)) &&
- "$GITP4" submit &&
+ git p4 submit &&
p4 filelog //depot/file7 &&
p4 filelog //depot/file7 | grep -q "branch from //depot/file6"
)
@@ -390,17 +390,17 @@ test_expect_success 'detect renames' '
# Modify and copy a file, configure a smaller threshold in detectCopies and
# confirm that copy is detected in P4.
test_expect_success 'detect copies' '
- "$GITP4" clone --dest="$git" //depot@all &&
+ git p4 clone --dest="$git" //depot@all &&
test_when_finished cleanup_git &&
(
cd "$git" &&
- git config git-p4.skipSubmitEditCheck true &&
+ git config git-p4.skipSubmitEdit true &&
cp file2 file8 &&
git add file8 &&
git commit -a -m "Copy file2 to file8" &&
git diff-tree -r -C HEAD &&
- "$GITP4" submit &&
+ git p4 submit &&
p4 filelog //depot/file8 &&
p4 filelog //depot/file8 | test_must_fail grep -q "branch from" &&
@@ -409,7 +409,7 @@ test_expect_success 'detect copies' '
git commit -a -m "Copy file2 to file9" &&
git diff-tree -r -C HEAD &&
git config git-p4.detectCopies true &&
- "$GITP4" submit &&
+ git p4 submit &&
p4 filelog //depot/file9 &&
p4 filelog //depot/file9 | test_must_fail grep -q "branch from" &&
@@ -418,7 +418,7 @@ test_expect_success 'detect copies' '
git add file2 file10 &&
git commit -a -m "Modify and copy file2 to file10" &&
git diff-tree -r -C HEAD &&
- "$GITP4" submit &&
+ git p4 submit &&
p4 filelog //depot/file10 &&
p4 filelog //depot/file10 | grep -q "branch from //depot/file" &&
@@ -429,7 +429,7 @@ test_expect_success 'detect copies' '
src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
test "$src" = file10 &&
git config git-p4.detectCopiesHarder true &&
- "$GITP4" submit &&
+ git p4 submit &&
p4 filelog //depot/file11 &&
p4 filelog //depot/file11 | grep -q "branch from //depot/file" &&
@@ -443,7 +443,7 @@ test_expect_success 'detect copies' '
src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
test "$src" = file10 &&
git config git-p4.detectCopies $(($level + 2)) &&
- "$GITP4" submit &&
+ git p4 submit &&
p4 filelog //depot/file12 &&
p4 filelog //depot/file12 | test_must_fail grep -q "branch from" &&
@@ -457,7 +457,7 @@ test_expect_success 'detect copies' '
src=$(git diff-tree -r -C --find-copies-harder HEAD | sed 1d | cut -f2) &&
test "$src" = file10 &&
git config git-p4.detectCopies $(($level - 2)) &&
- "$GITP4" submit &&
+ git p4 submit &&
p4 filelog //depot/file13 &&
p4 filelog //depot/file13 | grep -q "branch from //depot/file"
)
diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh
index d414705416..2859256de3 100755
--- a/t/t9801-git-p4-branch.sh
+++ b/t/t9801-git-p4-branch.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-p4 p4 branching tests'
+test_description='git p4 tests for p4 branches'
. ./lib-git-p4.sh
@@ -63,7 +63,7 @@ test_expect_success 'basic p4 branches' '
test_expect_success 'import main, no branch detection' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot/main@all &&
+ git p4 clone --dest="$git" //depot/main@all &&
(
cd "$git" &&
git log --oneline --graph --decorate --all &&
@@ -74,7 +74,7 @@ test_expect_success 'import main, no branch detection' '
test_expect_success 'import branch1, no branch detection' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot/branch1@all &&
+ git p4 clone --dest="$git" //depot/branch1@all &&
(
cd "$git" &&
git log --oneline --graph --decorate --all &&
@@ -85,7 +85,7 @@ test_expect_success 'import branch1, no branch detection' '
test_expect_success 'import branch2, no branch detection' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot/branch2@all &&
+ git p4 clone --dest="$git" //depot/branch2@all &&
(
cd "$git" &&
git log --oneline --graph --decorate --all &&
@@ -96,7 +96,7 @@ test_expect_success 'import branch2, no branch detection' '
test_expect_success 'import depot, no branch detection' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot@all &&
+ git p4 clone --dest="$git" //depot@all &&
(
cd "$git" &&
git log --oneline --graph --decorate --all &&
@@ -107,7 +107,7 @@ test_expect_success 'import depot, no branch detection' '
test_expect_success 'import depot, branch detection' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" --detect-branches //depot@all &&
+ git p4 clone --dest="$git" --detect-branches //depot@all &&
(
cd "$git" &&
@@ -132,7 +132,7 @@ test_expect_success 'import depot, branch detection, branchList branch definitio
(
cd "$git" &&
git config git-p4.branchList main:branch1 &&
- "$GITP4" clone --dest=. --detect-branches //depot@all &&
+ git p4 clone --dest=. --detect-branches //depot@all &&
git log --oneline --graph --decorate --all &&
@@ -189,15 +189,15 @@ test_expect_success 'add simple p4 branches' '
# Configure branches through git-config and clone them.
# All files are tested to make sure branches were cloned correctly.
# Finally, make an update to branch1 on P4 side to check if it is imported
-# correctly by git-p4.
-test_expect_success 'git-p4 clone simple branches' '
+# correctly by git p4.
+test_expect_success 'git p4 clone simple branches' '
test_when_finished cleanup_git &&
test_create_repo "$git" &&
(
cd "$git" &&
git config git-p4.branchList branch1:branch2 &&
git config --add git-p4.branchList branch1:branch3 &&
- "$GITP4" clone --dest=. --detect-branches //depot@all &&
+ git p4 clone --dest=. --detect-branches //depot@all &&
git log --all --graph --decorate --stat &&
git reset --hard p4/depot/branch1 &&
test -f file1 &&
@@ -221,13 +221,13 @@ test_expect_success 'git-p4 clone simple branches' '
p4 submit -d "update file2 in branch3" &&
cd "$git" &&
git reset --hard p4/depot/branch1 &&
- "$GITP4" rebase &&
+ git p4 rebase &&
grep file2_ file2
)
'
# Create a complex branch structure in P4 depot to check if they are correctly
-# cloned. The branches are created from older changelists to check if git-p4 is
+# cloned. The branches are created from older changelists to check if git p4 is
# able to correctly detect them.
# The final expected structure is:
# `branch1
@@ -248,7 +248,7 @@ test_expect_success 'git-p4 clone simple branches' '
# `- file1
# `- file2
# `- file3
-test_expect_success 'git-p4 add complex branches' '
+test_expect_success 'git p4 add complex branches' '
test_when_finished cleanup_git &&
test_create_repo "$git" &&
(
@@ -263,10 +263,10 @@ test_expect_success 'git-p4 add complex branches' '
)
'
-# Configure branches through git-config and clone them. git-p4 will only be able
+# Configure branches through git-config and clone them. git p4 will only be able
# to clone the original structure if it is able to detect the origin changelist
# of each branch.
-test_expect_success 'git-p4 clone complex branches' '
+test_expect_success 'git p4 clone complex branches' '
test_when_finished cleanup_git &&
test_create_repo "$git" &&
(
@@ -275,7 +275,7 @@ test_expect_success 'git-p4 clone complex branches' '
git config --add git-p4.branchList branch1:branch3 &&
git config --add git-p4.branchList branch1:branch4 &&
git config --add git-p4.branchList branch1:branch5 &&
- "$GITP4" clone --dest=. --detect-branches //depot@all &&
+ git p4 clone --dest=. --detect-branches //depot@all &&
git log --all --graph --decorate --stat &&
git reset --hard p4/depot/branch1 &&
test_path_is_file file1 &&
diff --git a/t/t9802-git-p4-filetype.sh b/t/t9802-git-p4-filetype.sh
index 992bb8cf0b..21924dfd7d 100755
--- a/t/t9802-git-p4-filetype.sh
+++ b/t/t9802-git-p4-filetype.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-p4 p4 filetype tests'
+test_description='git p4 filetype tests'
. ./lib-git-p4.sh
@@ -37,7 +37,7 @@ test_expect_success 'utf-16 file create' '
test_expect_success 'utf-16 file test' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot@all &&
+ git p4 clone --dest="$git" //depot@all &&
(
cd "$git" &&
@@ -84,7 +84,7 @@ test_expect_success 'keyword file test' '
build_smush &&
test_when_finished rm -f k_smush.py ko_smush.py &&
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot@all &&
+ git p4 clone --dest="$git" //depot@all &&
(
cd "$git" &&
@@ -94,7 +94,7 @@ test_expect_success 'keyword file test' '
"$PYTHON_PATH" "$TRASH_DIRECTORY/ko_smush.py" <"$cli/k-text-ko" >cli-k-text-ko-smush &&
test_cmp cli-k-text-ko-smush k-text-ko &&
- # utf16, even though p4 expands keywords, git-p4 does not
+ # utf16, even though p4 expands keywords, git p4 does not
# try to undo that
test_cmp "$cli/k-utf16-k" k-utf16-k &&
test_cmp "$cli/k-utf16-ko" k-utf16-ko
@@ -125,7 +125,7 @@ test_expect_success 'ignore apple' '
p4 submit -d appledouble
) &&
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot@all &&
+ git p4 clone --dest="$git" //depot@all &&
(
cd "$git" &&
test ! -f double.png
diff --git a/t/t9803-git-p4-shell-metachars.sh b/t/t9803-git-p4-shell-metachars.sh
index db670207bd..fbacff34fe 100755
--- a/t/t9803-git-p4-shell-metachars.sh
+++ b/t/t9803-git-p4-shell-metachars.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-p4 transparency to shell metachars in filenames'
+test_description='git p4 transparency to shell metachars in filenames'
. ./lib-git-p4.sh
@@ -18,7 +18,7 @@ test_expect_success 'init depot' '
'
test_expect_success 'shell metachars in filenames' '
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -28,7 +28,7 @@ test_expect_success 'shell metachars in filenames' '
echo f2 >"file with spaces" &&
git add "file with spaces" &&
git commit -m "add files" &&
- P4EDITOR=touch "$GITP4" submit
+ P4EDITOR=touch git p4 submit
) &&
(
cd "$cli" &&
@@ -39,7 +39,7 @@ test_expect_success 'shell metachars in filenames' '
'
test_expect_success 'deleting with shell metachars' '
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -47,7 +47,7 @@ test_expect_success 'deleting with shell metachars' '
git rm foo\$bar &&
git rm file\ with\ spaces &&
git commit -m "remove files" &&
- P4EDITOR=touch "$GITP4" submit
+ P4EDITOR=touch git p4 submit
) &&
(
cd "$cli" &&
@@ -97,7 +97,7 @@ test_expect_success 'branch with shell char' '
cd "$git" &&
git config git-p4.branchList main:branch\$3 &&
- "$GITP4" clone --dest=. --detect-branches //depot@all &&
+ git p4 clone --dest=. --detect-branches //depot@all &&
git log --all --graph --decorate --stat &&
git reset --hard p4/depot/branch\$3 &&
test -f shell_char_branch_file &&
diff --git a/t/t9804-git-p4-label.sh b/t/t9804-git-p4-label.sh
index a9e04efb88..e30f80e617 100755
--- a/t/t9804-git-p4-label.sh
+++ b/t/t9804-git-p4-label.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-p4 p4 label tests'
+test_description='git p4 label tests'
. ./lib-git-p4.sh
@@ -50,7 +50,7 @@ test_expect_success 'basic p4 labels' '
p4 labels ... &&
- "$GITP4" clone --dest="$git" --detect-labels //depot@all &&
+ git p4 clone --dest="$git" --detect-labels //depot@all &&
cd "$git" &&
git tag &&
@@ -89,7 +89,7 @@ test_expect_failure 'two labels on the same changelist' '
p4 labels ... &&
- "$GITP4" clone --dest="$git" --detect-labels //depot@all &&
+ git p4 clone --dest="$git" --detect-labels //depot@all &&
cd "$git" &&
git tag | grep tag_f1 &&
diff --git a/t/t9805-git-p4-skip-submit-edit.sh b/t/t9805-git-p4-skip-submit-edit.sh
index df929e0555..353dcfbe09 100755
--- a/t/t9805-git-p4-skip-submit-edit.sh
+++ b/t/t9805-git-p4-skip-submit-edit.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-p4 skipSubmitEdit config variables'
+test_description='git p4 skipSubmitEdit config variables'
. ./lib-git-p4.sh
@@ -19,33 +19,33 @@ test_expect_success 'init depot' '
# this works because EDITOR is set to :
test_expect_success 'no config, unedited, say yes' '
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
echo line >>file1 &&
git commit -a -m "change 2" &&
- echo y | "$GITP4" submit &&
+ echo y | git p4 submit &&
p4 changes //depot/... >wc &&
test_line_count = 2 wc
)
'
test_expect_success 'no config, unedited, say no' '
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
echo line >>file1 &&
git commit -a -m "change 3 (not really)" &&
- printf "bad response\nn\n" | "$GITP4" submit &&
+ printf "bad response\nn\n" | git p4 submit &&
p4 changes //depot/... >wc &&
test_line_count = 2 wc
)
'
test_expect_success 'skipSubmitEdit' '
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -54,21 +54,21 @@ test_expect_success 'skipSubmitEdit' '
git config core.editor /bin/false &&
echo line >>file1 &&
git commit -a -m "change 3" &&
- "$GITP4" submit &&
+ git p4 submit &&
p4 changes //depot/... >wc &&
test_line_count = 3 wc
)
'
test_expect_success 'skipSubmitEditCheck' '
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
git config git-p4.skipSubmitEditCheck true &&
echo line >>file1 &&
git commit -a -m "change 4" &&
- "$GITP4" submit &&
+ git p4 submit &&
p4 changes //depot/... >wc &&
test_line_count = 4 wc
)
@@ -76,7 +76,7 @@ test_expect_success 'skipSubmitEditCheck' '
# check the normal case, where the template really is edited
test_expect_success 'no config, edited' '
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
test_when_finished cleanup_git &&
ed="$TRASH_DIRECTORY/ed.sh" &&
test_when_finished "rm \"$ed\"" &&
@@ -91,7 +91,7 @@ test_expect_success 'no config, edited' '
cd "$git" &&
echo line >>file1 &&
git commit -a -m "change 5" &&
- EDITOR="\"$ed\"" "$GITP4" submit &&
+ P4EDITOR="" EDITOR="\"$ed\"" git p4 submit &&
p4 changes //depot/... >wc &&
test_line_count = 5 wc
)
diff --git a/t/t9806-git-p4-options.sh b/t/t9806-git-p4-options.sh
index 0571602129..2892367830 100755
--- a/t/t9806-git-p4-options.sh
+++ b/t/t9806-git-p4-options.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-p4 options'
+test_description='git p4 options'
. ./lib-git-p4.sh
@@ -24,11 +24,11 @@ test_expect_success 'init depot' '
'
test_expect_success 'clone no --git-dir' '
- test_must_fail "$GITP4" clone --git-dir=xx //depot
+ test_must_fail git p4 clone --git-dir=xx //depot
'
test_expect_success 'clone --branch' '
- "$GITP4" clone --branch=refs/remotes/p4/sb --dest="$git" //depot &&
+ git p4 clone --branch=refs/remotes/p4/sb --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -42,7 +42,7 @@ test_expect_success 'clone --changesfile' '
cf="$TRASH_DIRECTORY/cf" &&
test_when_finished "rm \"$cf\"" &&
printf "1\n3\n" >"$cf" &&
- "$GITP4" clone --changesfile="$cf" --dest="$git" //depot &&
+ git p4 clone --changesfile="$cf" --dest="$git" //depot &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -58,14 +58,14 @@ test_expect_success 'clone --changesfile, @all' '
cf="$TRASH_DIRECTORY/cf" &&
test_when_finished "rm \"$cf\"" &&
printf "1\n3\n" >"$cf" &&
- test_must_fail "$GITP4" clone --changesfile="$cf" --dest="$git" //depot@all
+ test_must_fail git p4 clone --changesfile="$cf" --dest="$git" //depot@all
'
# imports both master and p4/master in refs/heads
# requires --import-local on sync to find p4 refs/heads
# does not update master on sync, just p4/master
test_expect_success 'clone/sync --import-local' '
- "$GITP4" clone --import-local --dest="$git" //depot@1,2 &&
+ git p4 clone --import-local --dest="$git" //depot@1,2 &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -73,9 +73,9 @@ test_expect_success 'clone/sync --import-local' '
test_line_count = 2 lines &&
git log --oneline refs/heads/p4/master >lines &&
test_line_count = 2 lines &&
- test_must_fail "$GITP4" sync &&
+ test_must_fail git p4 sync &&
- "$GITP4" sync --import-local &&
+ git p4 sync --import-local &&
git log --oneline refs/heads/master >lines &&
test_line_count = 2 lines &&
git log --oneline refs/heads/p4/master >lines &&
@@ -84,7 +84,7 @@ test_expect_success 'clone/sync --import-local' '
'
test_expect_success 'clone --max-changes' '
- "$GITP4" clone --dest="$git" --max-changes 2 //depot@all &&
+ git p4 clone --dest="$git" --max-changes 2 //depot@all &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -101,7 +101,7 @@ test_expect_success 'clone --keep-path' '
p4 add sub/dir/f4 &&
p4 submit -d "change 4"
) &&
- "$GITP4" clone --dest="$git" --keep-path //depot/sub/dir@all &&
+ git p4 clone --dest="$git" --keep-path //depot/sub/dir@all &&
test_when_finished cleanup_git &&
(
cd "$git" &&
@@ -109,7 +109,7 @@ test_expect_success 'clone --keep-path' '
test_path_is_file sub/dir/f4
) &&
cleanup_git &&
- "$GITP4" clone --dest="$git" //depot/sub/dir@all &&
+ git p4 clone --dest="$git" //depot/sub/dir@all &&
(
cd "$git" &&
test_path_is_file f4 &&
@@ -126,7 +126,7 @@ test_expect_success 'clone --use-client-spec' '
(
# big usage message
exec >/dev/null &&
- test_must_fail "$GITP4" clone --dest="$git" --use-client-spec
+ test_must_fail git p4 clone --dest="$git" --use-client-spec
) &&
cli2="$TRASH_DIRECTORY/cli2" &&
mkdir -p "$cli2" &&
@@ -142,7 +142,7 @@ test_expect_success 'clone --use-client-spec' '
) &&
P4CLIENT=client2 &&
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" --use-client-spec //depot/... &&
+ git p4 clone --dest="$git" --use-client-spec //depot/... &&
(
cd "$git" &&
test_path_is_file bus/dir/f4 &&
@@ -156,7 +156,7 @@ test_expect_success 'clone --use-client-spec' '
cd "$git" &&
git init &&
git config git-p4.useClientSpec true &&
- "$GITP4" sync //depot/... &&
+ git p4 sync //depot/... &&
git checkout -b master p4/master &&
test_path_is_file bus/dir/f4 &&
test_path_is_missing file1
diff --git a/t/t9807-git-p4-submit.sh b/t/t9807-git-p4-submit.sh
index b1f61e3db5..15417165e8 100755
--- a/t/t9807-git-p4-submit.sh
+++ b/t/t9807-git-p4-submit.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-p4 submit'
+test_description='git p4 submit'
. ./lib-git-p4.sh
@@ -19,7 +19,7 @@ test_expect_success 'init depot' '
test_expect_success 'submit with no client dir' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
echo file2 >file2 &&
@@ -27,20 +27,20 @@ test_expect_success 'submit with no client dir' '
git commit -m "git commit 2" &&
rm -rf "$cli" &&
git config git-p4.skipSubmitEdit true &&
- "$GITP4" submit
+ git p4 submit
)
'
# make two commits, but tell it to apply only from HEAD^
test_expect_success 'submit --origin' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
test_commit "file3" &&
test_commit "file4" &&
git config git-p4.skipSubmitEdit true &&
- "$GITP4" submit --origin=HEAD^
+ git p4 submit --origin=HEAD^
) &&
(
cd "$cli" &&
@@ -52,30 +52,30 @@ test_expect_success 'submit --origin' '
test_expect_success 'submit with allowSubmit' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
test_commit "file5" &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.allowSubmit "nobranch" &&
- test_must_fail "$GITP4" submit &&
+ test_must_fail git p4 submit &&
git config git-p4.allowSubmit "nobranch,master" &&
- "$GITP4" submit
+ git p4 submit
)
'
test_expect_success 'submit with master branch name from argv' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
test_commit "file6" &&
git config git-p4.skipSubmitEdit true &&
- test_must_fail "$GITP4" submit nobranch &&
+ test_must_fail git p4 submit nobranch &&
git branch otherbranch &&
git reset --hard HEAD^ &&
test_commit "file7" &&
- "$GITP4" submit otherbranch
+ git p4 submit otherbranch
) &&
(
cd "$cli" &&
diff --git a/t/t9808-git-p4-chdir.sh b/t/t9808-git-p4-chdir.sh
index f0022839c7..2f8014a60e 100755
--- a/t/t9808-git-p4-chdir.sh
+++ b/t/t9808-git-p4-chdir.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-p4 relative chdir'
+test_description='git p4 relative chdir'
. ./lib-git-p4.sh
@@ -26,7 +26,7 @@ test_expect_success 'P4CONFIG and absolute dir clone' '
(
P4CONFIG=p4config && export P4CONFIG &&
sane_unset P4PORT P4CLIENT &&
- "$GITP4" clone --verbose --dest="$git" //depot
+ git p4 clone --verbose --dest="$git" //depot
)
'
@@ -38,7 +38,7 @@ test_expect_success 'P4CONFIG and relative dir clone' '
(
P4CONFIG=p4config && export P4CONFIG &&
sane_unset P4PORT P4CLIENT &&
- "$GITP4" clone --verbose --dest="git" //depot
+ git p4 clone --verbose --dest="git" //depot
)
'
diff --git a/t/t9809-git-p4-client-view.sh b/t/t9809-git-p4-client-view.sh
index 773a516ff0..796b02c7f3 100755
--- a/t/t9809-git-p4-client-view.sh
+++ b/t/t9809-git-p4-client-view.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-test_description='git-p4 client view'
+test_description='git p4 client view'
. ./lib-git-p4.sh
@@ -96,25 +96,25 @@ test_expect_success 'init depot' '
test_expect_success 'unsupported view wildcard %%n' '
client_view "//depot/%%%%1/sub/... //client/sub/%%%%1/..." &&
test_when_finished cleanup_git &&
- test_must_fail "$GITP4" clone --use-client-spec --dest="$git" //depot
+ test_must_fail git p4 clone --use-client-spec --dest="$git" //depot
'
test_expect_success 'unsupported view wildcard *' '
client_view "//depot/*/bar/... //client/*/bar/..." &&
test_when_finished cleanup_git &&
- test_must_fail "$GITP4" clone --use-client-spec --dest="$git" //depot
+ test_must_fail git p4 clone --use-client-spec --dest="$git" //depot
'
test_expect_success 'wildcard ... only supported at end of spec 1' '
client_view "//depot/.../file11 //client/.../file11" &&
test_when_finished cleanup_git &&
- test_must_fail "$GITP4" clone --use-client-spec --dest="$git" //depot
+ test_must_fail git p4 clone --use-client-spec --dest="$git" //depot
'
test_expect_success 'wildcard ... only supported at end of spec 2' '
client_view "//depot/.../a/... //client/.../a/..." &&
test_when_finished cleanup_git &&
- test_must_fail "$GITP4" clone --use-client-spec --dest="$git" //depot
+ test_must_fail git p4 clone --use-client-spec --dest="$git" //depot
'
test_expect_success 'basic map' '
@@ -122,7 +122,7 @@ test_expect_success 'basic map' '
files="cli1/file11 cli1/file12" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files
'
@@ -130,7 +130,7 @@ test_expect_success 'client view with no mappings' '
client_view &&
client_verify &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify
'
@@ -139,7 +139,7 @@ test_expect_success 'single file map' '
files="file11" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files
'
@@ -150,7 +150,7 @@ test_expect_success 'later mapping takes precedence (entire repo)' '
cli2/dir2/file21 cli2/dir2/file22" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files
'
@@ -160,7 +160,7 @@ test_expect_success 'later mapping takes precedence (partial repo)' '
files="file21 file22" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files
'
@@ -176,7 +176,7 @@ test_expect_success 'depot path matching rejected client path' '
files="cli12/file21 cli12/file22" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files
'
@@ -187,7 +187,7 @@ test_expect_success 'exclusion wildcard, client rhs same (odd)' '
"-//depot/dir2/... //client/..." &&
client_verify &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify
'
@@ -197,7 +197,7 @@ test_expect_success 'exclusion wildcard, client rhs different (normal)' '
files="dir1/file11 dir1/file12" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files
'
@@ -207,7 +207,7 @@ test_expect_success 'exclusion single file' '
files="dir1/file11 dir1/file12 dir2/file21" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files
'
@@ -217,7 +217,7 @@ test_expect_success 'overlay wildcard' '
files="cli/file11 cli/file12 cli/file21 cli/file22" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files
'
@@ -227,7 +227,7 @@ test_expect_success 'overlay single file' '
files="cli/file11 cli/file12 cli/file21" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files
'
@@ -238,7 +238,7 @@ test_expect_success 'exclusion with later inclusion' '
files="dir1/file11 dir1/file12 dir2incl/file21 dir2incl/file22" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files
'
@@ -246,7 +246,7 @@ test_expect_success 'quotes on rhs only' '
client_view "//depot/dir1/... \"//client/cdir 1/...\"" &&
client_verify "cdir 1/file11" "cdir 1/file12" &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify "cdir 1/file11" "cdir 1/file12"
'
@@ -258,7 +258,7 @@ test_expect_success 'quotes on rhs only' '
test_expect_success 'clone --use-client-spec sets useClientSpec' '
client_view "//depot/... //client/..." &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
(
cd "$git" &&
git config --bool git-p4.useClientSpec >actual &&
@@ -273,7 +273,7 @@ test_expect_success 'subdir clone' '
files="dir1/file11 dir1/file12 dir2/file21 dir2/file22" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
+ git p4 clone --use-client-spec --dest="$git" //depot/dir1 &&
git_verify dir1/file11 dir1/file12
'
@@ -283,14 +283,14 @@ test_expect_success 'subdir clone' '
test_expect_success 'subdir clone, submit modify' '
client_view "//depot/... //client/..." &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
+ git p4 clone --use-client-spec --dest="$git" //depot/dir1 &&
(
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
echo line >>dir1/file12 &&
git add dir1/file12 &&
git commit -m dir1/file12 &&
- "$GITP4" submit
+ git p4 submit
) &&
(
cd "$cli" &&
@@ -302,14 +302,14 @@ test_expect_success 'subdir clone, submit modify' '
test_expect_success 'subdir clone, submit add' '
client_view "//depot/... //client/..." &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
+ git p4 clone --use-client-spec --dest="$git" //depot/dir1 &&
(
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
echo file13 >dir1/file13 &&
git add dir1/file13 &&
git commit -m dir1/file13 &&
- "$GITP4" submit
+ git p4 submit
) &&
(
cd "$cli" &&
@@ -320,13 +320,13 @@ test_expect_success 'subdir clone, submit add' '
test_expect_success 'subdir clone, submit delete' '
client_view "//depot/... //client/..." &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
+ git p4 clone --use-client-spec --dest="$git" //depot/dir1 &&
(
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
git rm dir1/file12 &&
git commit -m "delete dir1/file12" &&
- "$GITP4" submit
+ git p4 submit
) &&
(
cd "$cli" &&
@@ -337,7 +337,7 @@ test_expect_success 'subdir clone, submit delete' '
test_expect_success 'subdir clone, submit copy' '
client_view "//depot/... //client/..." &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
+ git p4 clone --use-client-spec --dest="$git" //depot/dir1 &&
(
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
@@ -345,7 +345,7 @@ test_expect_success 'subdir clone, submit copy' '
cp dir1/file11 dir1/file11a &&
git add dir1/file11a &&
git commit -m "copy to dir1/file11a" &&
- "$GITP4" submit
+ git p4 submit
) &&
(
cd "$cli" &&
@@ -356,14 +356,14 @@ test_expect_success 'subdir clone, submit copy' '
test_expect_success 'subdir clone, submit rename' '
client_view "//depot/... //client/..." &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot/dir1 &&
+ git p4 clone --use-client-spec --dest="$git" //depot/dir1 &&
(
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.detectRenames true &&
git mv dir1/file13 dir1/file13a &&
git commit -m "rename dir1/file13 to dir1/file13a" &&
- "$GITP4" submit
+ git p4 submit
) &&
(
cd "$cli" &&
@@ -419,7 +419,7 @@ test_expect_success 'overlay collision 1 to 2' '
client_verify $files &&
test_cmp actual "$cli"/filecollide &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files &&
test_cmp actual "$git"/filecollide
'
@@ -432,7 +432,7 @@ test_expect_failure 'overlay collision 2 to 1' '
client_verify $files &&
test_cmp actual "$cli"/filecollide &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files &&
test_cmp actual "$git"/filecollide
'
@@ -454,7 +454,7 @@ test_expect_failure 'overlay collision 1 to 2, but 2 deleted' '
files="file11 file12 file21 file22" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files
'
@@ -477,7 +477,7 @@ test_expect_failure 'overlay collision 1 to 2, but 2 deleted, then 1 updated' '
files="file11 file12 file21 file22" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files
'
@@ -533,7 +533,7 @@ test_expect_success 'overlay sync: initial git checkout' '
echo dir1/colA >actual &&
client_verify $files &&
test_cmp actual "$cli"/colA &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files &&
test_cmp actual "$git"/colA
'
@@ -558,7 +558,7 @@ test_expect_success 'overlay sync: colA content switch' '
test_cmp actual "$cli"/colA &&
(
cd "$git" &&
- "$GITP4" sync --use-client-spec &&
+ git p4 sync --use-client-spec &&
git merge --ff-only p4/master
) &&
git_verify $files &&
@@ -585,7 +585,7 @@ test_expect_success 'overlay sync: colB appears' '
test_cmp actual "$cli"/colB &&
(
cd "$git" &&
- "$GITP4" sync --use-client-spec &&
+ git p4 sync --use-client-spec &&
git merge --ff-only p4/master
) &&
git_verify $files &&
@@ -613,7 +613,7 @@ test_expect_success 'overlay sync: colB disappears' '
test_when_finished cleanup_git &&
(
cd "$git" &&
- "$GITP4" sync --use-client-spec &&
+ git p4 sync --use-client-spec &&
git merge --ff-only p4/master
) &&
git_verify $files
@@ -671,7 +671,7 @@ test_expect_success 'overlay sync swap: initial git checkout' '
echo dir1/colA >actual &&
client_verify $files &&
test_cmp actual "$cli"/colA &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify $files &&
test_cmp actual "$git"/colA
'
@@ -696,7 +696,7 @@ test_expect_failure 'overlay sync swap: colA no content switch' '
test_cmp actual "$cli"/colA &&
(
cd "$git" &&
- "$GITP4" sync --use-client-spec &&
+ git p4 sync --use-client-spec &&
git merge --ff-only p4/master
) &&
git_verify $files &&
@@ -723,7 +723,7 @@ test_expect_success 'overlay sync swap: colB appears' '
test_cmp actual "$cli"/colB &&
(
cd "$git" &&
- "$GITP4" sync --use-client-spec &&
+ git p4 sync --use-client-spec &&
git merge --ff-only p4/master
) &&
git_verify $files &&
@@ -753,7 +753,7 @@ test_expect_failure 'overlay sync swap: colB no change' '
test_when_finished cleanup_git &&
(
cd "$git" &&
- "$GITP4" sync --use-client-spec &&
+ git p4 sync --use-client-spec &&
git merge --ff-only p4/master
) &&
git_verify $files &&
@@ -801,7 +801,7 @@ test_expect_success 'quotes on lhs only' '
files="cdir1/file11 cdir1/file12" &&
client_verify $files &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
client_verify $files
'
@@ -809,7 +809,7 @@ test_expect_success 'quotes on both sides' '
client_view "\"//depot/dir 1/...\" \"//client/cdir 1/...\"" &&
client_verify "cdir 1/file11" "cdir 1/file12" &&
test_when_finished cleanup_git &&
- "$GITP4" clone --use-client-spec --dest="$git" //depot &&
+ git p4 clone --use-client-spec --dest="$git" //depot &&
git_verify "cdir 1/file11" "cdir 1/file12"
'
diff --git a/t/t9810-git-p4-rcs.sh b/t/t9810-git-p4-rcs.sh
index 49dfde0616..d8d9ca4679 100755
--- a/t/t9810-git-p4-rcs.sh
+++ b/t/t9810-git-p4-rcs.sh
@@ -84,13 +84,13 @@ scrub_ko_check () {
#
test_expect_success 'edit far away from RCS lines' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
sed -i "s/^line7/line7 edit/" filek &&
git commit -m "filek line7 edit" filek &&
- "$GITP4" submit &&
+ git p4 submit &&
scrub_k_check filek
)
'
@@ -100,14 +100,14 @@ test_expect_success 'edit far away from RCS lines' '
#
test_expect_success 'edit near RCS lines' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.attemptRCSCleanup true &&
sed -i "s/^line4/line4 edit/" filek &&
git commit -m "filek line4 edit" filek &&
- "$GITP4" submit &&
+ git p4 submit &&
scrub_k_check filek
)
'
@@ -117,14 +117,14 @@ test_expect_success 'edit near RCS lines' '
#
test_expect_success 'edit keyword lines' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.attemptRCSCleanup true &&
sed -i "/Revision/d" filek &&
git commit -m "filek remove Revision line" filek &&
- "$GITP4" submit &&
+ git p4 submit &&
scrub_k_check filek
)
'
@@ -134,14 +134,14 @@ test_expect_success 'edit keyword lines' '
#
test_expect_success 'scrub ko files differently' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.attemptRCSCleanup true &&
sed -i "s/^line4/line4 edit/" fileko &&
git commit -m "fileko line4 edit" fileko &&
- "$GITP4" submit &&
+ git p4 submit &&
scrub_ko_check fileko &&
! scrub_k_check fileko
)
@@ -168,7 +168,7 @@ test_expect_success 'cleanup after failure' '
#
test_expect_success 'do not scrub plain text' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
@@ -181,7 +181,7 @@ test_expect_success 'do not scrub plain text' '
sed -i "s/^line5/line5 p4 edit/" file_text &&
p4 submit -d "file5 p4 edit"
) &&
- ! "$GITP4" submit &&
+ ! git p4 submit &&
(
# exepct something like:
# file_text - file(s) not opened on this client
@@ -239,7 +239,7 @@ p4_append_to_file () {
# even though the change itself would otherwise apply cleanly.
test_expect_success 'cope with rcs keyword expansion damage' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
git config git-p4.skipSubmitEdit true &&
@@ -252,10 +252,10 @@ test_expect_success 'cope with rcs keyword expansion damage' '
git add kwfile1.c &&
git commit -m "Zap an RCS kw line" &&
- "$GITP4" submit &&
- "$GITP4" rebase &&
+ git p4 submit &&
+ git p4 rebase &&
git diff p4/master &&
- "$GITP4" commit &&
+ git p4 commit &&
echo "try modifying in both" &&
cd "$cli" &&
p4 edit kwfile1.c &&
@@ -265,8 +265,8 @@ test_expect_success 'cope with rcs keyword expansion damage' '
echo "line from git at the top" | cat - kwfile1.c >kwfile1.c.new &&
mv kwfile1.c.new kwfile1.c &&
git commit -m "Add line in git at the top" kwfile1.c &&
- "$GITP4" rebase &&
- "$GITP4" submit
+ git p4 rebase &&
+ git p4 submit
)
'
@@ -280,7 +280,7 @@ test_expect_success 'cope with rcs keyword file deletion' '
cat kwdelfile.c &&
grep 1 kwdelfile.c
) &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
grep Revision kwdelfile.c &&
@@ -288,7 +288,7 @@ test_expect_success 'cope with rcs keyword file deletion' '
git commit -m "Delete a file containing RCS keywords" &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.attemptRCSCleanup true &&
- "$GITP4" submit
+ git p4 submit
) &&
(
cd "$cli" &&
@@ -301,7 +301,7 @@ test_expect_success 'cope with rcs keyword file deletion' '
# work fine without any special handling.
test_expect_success 'Add keywords in git which match the default p4 values' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
echo "NewKW: \$Revision\$" >>kwfile1.c &&
@@ -309,7 +309,7 @@ test_expect_success 'Add keywords in git which match the default p4 values' '
git commit -m "Adding RCS keywords in git" &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.attemptRCSCleanup true &&
- "$GITP4" submit
+ git p4 submit
) &&
(
cd "$cli" &&
@@ -325,7 +325,7 @@ test_expect_success 'Add keywords in git which match the default p4 values' '
#
test_expect_failure 'Add keywords in git which do not match the default p4 values' '
test_when_finished cleanup_git &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
echo "NewKW2: \$Revision:1\$" >>kwfile1.c &&
@@ -333,7 +333,7 @@ test_expect_failure 'Add keywords in git which do not match the default p4 value
git commit -m "Adding RCS keywords in git" &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.attemptRCSCleanup true &&
- "$GITP4" submit
+ git p4 submit
) &&
(
cd "$cli" &&
@@ -356,7 +356,7 @@ test_expect_success 'merge conflict handling still works' '
p4 add -t ktext merge2.c &&
p4 submit -d "add merge test file"
) &&
- "$GITP4" clone --dest="$git" //depot &&
+ git p4 clone --dest="$git" //depot &&
(
cd "$git" &&
sed -e "/Hello/d" merge2.c >merge2.c.tmp &&
@@ -374,7 +374,7 @@ test_expect_success 'merge conflict handling still works' '
test -f merge2.c &&
git config git-p4.skipSubmitEdit true &&
git config git-p4.attemptRCSCleanup true &&
- !(echo "s" | "$GITP4" submit) &&
+ !(echo "s" | git p4 submit) &&
git rebase --skip &&
! test -f merge2.c
)
diff --git a/t/t9811-git-p4-label-import.sh b/t/t9811-git-p4-label-import.sh
new file mode 100755
index 0000000000..fb00ffab24
--- /dev/null
+++ b/t/t9811-git-p4-label-import.sh
@@ -0,0 +1,202 @@
+#!/bin/sh
+
+test_description='git p4 label tests'
+
+. ./lib-git-p4.sh
+
+test_expect_success 'start p4d' '
+ start_p4d
+'
+
+# Basic p4 label import tests.
+#
+test_expect_success 'basic p4 labels' '
+ test_when_finished cleanup_git &&
+ (
+ cd "$cli" &&
+ mkdir -p main &&
+
+ echo f1 >main/f1 &&
+ p4 add main/f1 &&
+ p4 submit -d "main/f1" &&
+
+ echo f2 >main/f2 &&
+ p4 add main/f2 &&
+ p4 submit -d "main/f2" &&
+
+ echo f3 >main/file_with_\$metachar &&
+ p4 add main/file_with_\$metachar &&
+ p4 submit -d "file with metachar" &&
+
+ p4 tag -l TAG_F1_ONLY main/f1 &&
+ p4 tag -l TAG_WITH\$_SHELL_CHAR main/... &&
+ p4 tag -l this_tag_will_be\ skipped main/... &&
+
+ echo f4 >main/f4 &&
+ p4 add main/f4 &&
+ p4 submit -d "main/f4" &&
+
+ p4 label -i <<-EOF &&
+ Label: TAG_LONG_LABEL
+ Description:
+ A Label first line
+ A Label second line
+ View: //depot/...
+ EOF
+
+ p4 tag -l TAG_LONG_LABEL ... &&
+
+ p4 labels ... &&
+
+ git p4 clone --dest="$git" //depot@all &&
+ cd "$git" &&
+ git config git-p4.labelImportRegexp ".*TAG.*" &&
+ git p4 sync --import-labels --verbose &&
+
+ git tag &&
+ git tag >taglist &&
+ test_line_count = 3 taglist &&
+
+ cd main &&
+ git checkout TAG_F1_ONLY &&
+ ! test -f f2 &&
+ git checkout TAG_WITH\$_SHELL_CHAR &&
+ test -f f1 && test -f f2 && test -f file_with_\$metachar &&
+
+ git show TAG_LONG_LABEL | grep -q "A Label second line"
+ )
+'
+# Test some label corner cases:
+#
+# - two tags on the same file; both should be available
+# - a tag that is only on one file; this kind of tag
+# cannot be imported (at least not easily).
+
+test_expect_success 'two labels on the same changelist' '
+ test_when_finished cleanup_git &&
+ (
+ cd "$cli" &&
+ mkdir -p main &&
+
+ p4 edit main/f1 main/f2 &&
+ echo "hello world" >main/f1 &&
+ echo "not in the tag" >main/f2 &&
+ p4 submit -d "main/f[12]: testing two labels" &&
+
+ p4 tag -l TAG_F1_1 main/... &&
+ p4 tag -l TAG_F1_2 main/... &&
+
+ p4 labels ... &&
+
+ git p4 clone --dest="$git" //depot@all &&
+ cd "$git" &&
+ git p4 sync --import-labels &&
+
+ git tag | grep TAG_F1 &&
+ git tag | grep -q TAG_F1_1 &&
+ git tag | grep -q TAG_F1_2 &&
+
+ cd main &&
+
+ git checkout TAG_F1_1 &&
+ ls &&
+ test -f f1 &&
+
+ git checkout TAG_F1_2 &&
+ ls &&
+ test -f f1
+ )
+'
+
+# Export some git tags to p4
+test_expect_success 'export git tags to p4' '
+ test_when_finished cleanup_git &&
+ git p4 clone --dest="$git" //depot@all &&
+ (
+ cd "$git" &&
+ git tag -m "A tag created in git:xyzzy" GIT_TAG_1 &&
+ echo "hello world" >main/f10 &&
+ git add main/f10 &&
+ git commit -m "Adding file for export test" &&
+ git config git-p4.skipSubmitEdit true &&
+ git p4 submit &&
+ git tag -m "Another git tag" GIT_TAG_2 &&
+ git tag LIGHTWEIGHT_TAG &&
+ git p4 rebase --import-labels --verbose &&
+ git p4 submit --export-labels --verbose
+ ) &&
+ (
+ cd "$cli" &&
+ p4 sync ... &&
+ p4 labels ... | grep GIT_TAG_1 &&
+ p4 labels ... | grep GIT_TAG_2 &&
+ p4 labels ... | grep LIGHTWEIGHT_TAG &&
+ p4 label -o GIT_TAG_1 | grep "tag created in git:xyzzy" &&
+ p4 sync ...@GIT_TAG_1 &&
+ ! test -f main/f10
+ p4 sync ...@GIT_TAG_2 &&
+ test -f main/f10
+ )
+'
+
+# Export a tag from git where an affected file is deleted later on
+# Need to create git tags after rebase, since only then can the
+# git commits be mapped to p4 changelists.
+test_expect_success 'export git tags to p4 with deletion' '
+ test_when_finished cleanup_git &&
+ git p4 clone --dest="$git" //depot@all &&
+ (
+ cd "$git" &&
+ git p4 sync --import-labels &&
+ echo "deleted file" >main/deleted_file &&
+ git add main/deleted_file &&
+ git commit -m "create deleted file" &&
+ git rm main/deleted_file &&
+ echo "new file" >main/f11 &&
+ git add main/f11 &&
+ git commit -m "delete the deleted file" &&
+ git config git-p4.skipSubmitEdit true &&
+ git p4 submit &&
+ git p4 rebase --import-labels --verbose &&
+ git tag -m "tag on deleted file" GIT_TAG_ON_DELETED HEAD~1 &&
+ git tag -m "tag after deletion" GIT_TAG_AFTER_DELETION HEAD &&
+ git p4 submit --export-labels --verbose
+ ) &&
+ (
+ cd "$cli" &&
+ p4 sync ... &&
+ p4 sync ...@GIT_TAG_ON_DELETED &&
+ test -f main/deleted_file &&
+ p4 sync ...@GIT_TAG_AFTER_DELETION &&
+ ! test -f main/deleted_file &&
+ echo "checking label contents" &&
+ p4 label -o GIT_TAG_ON_DELETED | grep "tag on deleted file"
+ )
+'
+
+# Create a tag in git that cannot be exported to p4
+test_expect_success 'tag that cannot be exported' '
+ test_when_finished cleanup_git &&
+ git p4 clone --dest="$git" //depot@all &&
+ (
+ cd "$git" &&
+ git checkout -b a_branch &&
+ echo "hello" >main/f12 &&
+ git add main/f12 &&
+ git commit -m "adding f12" &&
+ git tag -m "tag on a_branch" GIT_TAG_ON_A_BRANCH &&
+ git checkout master &&
+ git p4 submit --export-labels
+ ) &&
+ (
+ cd "$cli" &&
+ p4 sync ... &&
+ !(p4 labels | grep GIT_TAG_ON_A_BRANCH)
+ )
+'
+
+test_expect_success 'kill p4d' '
+ kill_p4d
+'
+
+test_done
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
new file mode 100755
index 0000000000..5bda6b6e18
--- /dev/null
+++ b/t/t9902-completion.sh
@@ -0,0 +1,243 @@
+#!/bin/sh
+#
+# Copyright (c) 2012 Felipe Contreras
+#
+
+if test -n "$BASH" && test -z "$POSIXLY_CORRECT"; then
+ # we are in full-on bash mode
+ true
+elif type bash >/dev/null 2>&1; then
+ # execute in full-on bash mode
+ unset POSIXLY_CORRECT
+ exec bash "$0" "$@"
+else
+ echo '1..0 #SKIP skipping bash completion tests; bash not available'
+ exit 0
+fi
+
+test_description='test bash completion'
+
+. ./test-lib.sh
+
+complete ()
+{
+ # do nothing
+ return 0
+}
+
+. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash"
+
+# We don't need this function to actually join words or do anything special.
+# Also, it's cleaner to avoid touching bash's internal completion variables.
+# So let's override it with a minimal version for testing purposes.
+_get_comp_words_by_ref ()
+{
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ cur)
+ cur=${_words[_cword]}
+ ;;
+ prev)
+ prev=${_words[_cword-1]}
+ ;;
+ words)
+ words=("${_words[@]}")
+ ;;
+ cword)
+ cword=$_cword
+ ;;
+ esac
+ shift
+ done
+}
+
+print_comp ()
+{
+ local IFS=$'\n'
+ echo "${COMPREPLY[*]}" > out
+}
+
+run_completion ()
+{
+ local -a COMPREPLY _words
+ local _cword
+ _words=( $1 )
+ (( _cword = ${#_words[@]} - 1 ))
+ _git && print_comp
+}
+
+test_completion ()
+{
+ test $# -gt 1 && echo "$2" > expected
+ run_completion "$@" &&
+ test_cmp expected out
+}
+
+newline=$'\n'
+
+test_expect_success '__gitcomp - trailing space - options' '
+ sed -e "s/Z$//" >expected <<-\EOF &&
+ --reuse-message=Z
+ --reedit-message=Z
+ --reset-author Z
+ EOF
+ (
+ local -a COMPREPLY &&
+ cur="--re" &&
+ __gitcomp "--dry-run --reuse-message= --reedit-message=
+ --reset-author" &&
+ IFS="$newline" &&
+ echo "${COMPREPLY[*]}" > out
+ ) &&
+ test_cmp expected out
+'
+
+test_expect_success '__gitcomp - trailing space - config keys' '
+ sed -e "s/Z$//" >expected <<-\EOF &&
+ branch.Z
+ branch.autosetupmerge Z
+ branch.autosetuprebase Z
+ browser.Z
+ EOF
+ (
+ local -a COMPREPLY &&
+ cur="br" &&
+ __gitcomp "branch. branch.autosetupmerge
+ branch.autosetuprebase browser." &&
+ IFS="$newline" &&
+ echo "${COMPREPLY[*]}" > out
+ ) &&
+ test_cmp expected out
+'
+
+test_expect_success '__gitcomp - option parameter' '
+ sed -e "s/Z$//" >expected <<-\EOF &&
+ recursive Z
+ resolve Z
+ EOF
+ (
+ local -a COMPREPLY &&
+ cur="--strategy=re" &&
+ __gitcomp "octopus ours recursive resolve subtree
+ " "" "re" &&
+ IFS="$newline" &&
+ echo "${COMPREPLY[*]}" > out
+ ) &&
+ test_cmp expected out
+'
+
+test_expect_success '__gitcomp - prefix' '
+ sed -e "s/Z$//" >expected <<-\EOF &&
+ branch.maint.merge Z
+ branch.maint.mergeoptions Z
+ EOF
+ (
+ local -a COMPREPLY &&
+ cur="branch.me" &&
+ __gitcomp "remote merge mergeoptions rebase
+ " "branch.maint." "me" &&
+ IFS="$newline" &&
+ echo "${COMPREPLY[*]}" > out
+ ) &&
+ test_cmp expected out
+'
+
+test_expect_success '__gitcomp - suffix' '
+ sed -e "s/Z$//" >expected <<-\EOF &&
+ branch.master.Z
+ branch.maint.Z
+ EOF
+ (
+ local -a COMPREPLY &&
+ cur="branch.me" &&
+ __gitcomp "master maint next pu
+ " "branch." "ma" "." &&
+ IFS="$newline" &&
+ echo "${COMPREPLY[*]}" > out
+ ) &&
+ test_cmp expected out
+'
+
+test_expect_success 'basic' '
+ run_completion "git \"\"" &&
+ # built-in
+ grep -q "^add \$" out &&
+ # script
+ grep -q "^filter-branch \$" out &&
+ # plumbing
+ ! grep -q "^ls-files \$" out &&
+
+ run_completion "git f" &&
+ ! grep -q -v "^f" out
+'
+
+test_expect_success 'double dash "git" itself' '
+ sed -e "s/Z$//" >expected <<-\EOF &&
+ --paginate Z
+ --no-pager Z
+ --git-dir=
+ --bare Z
+ --version Z
+ --exec-path Z
+ --exec-path=
+ --html-path Z
+ --info-path Z
+ --work-tree=
+ --namespace=
+ --no-replace-objects Z
+ --help Z
+ EOF
+ test_completion "git --"
+'
+
+test_expect_success 'double dash "git checkout"' '
+ sed -e "s/Z$//" >expected <<-\EOF &&
+ --quiet Z
+ --ours Z
+ --theirs Z
+ --track Z
+ --no-track Z
+ --merge Z
+ --conflict=
+ --orphan Z
+ --patch Z
+ EOF
+ test_completion "git checkout --"
+'
+
+test_expect_success 'general options' '
+ test_completion "git --ver" "--version " &&
+ test_completion "git --hel" "--help " &&
+ sed -e "s/Z$//" >expected <<-\EOF &&
+ --exec-path Z
+ --exec-path=
+ EOF
+ test_completion "git --exe" &&
+ test_completion "git --htm" "--html-path " &&
+ test_completion "git --pag" "--paginate " &&
+ test_completion "git --no-p" "--no-pager " &&
+ test_completion "git --git" "--git-dir=" &&
+ test_completion "git --wor" "--work-tree=" &&
+ test_completion "git --nam" "--namespace=" &&
+ test_completion "git --bar" "--bare " &&
+ test_completion "git --inf" "--info-path " &&
+ test_completion "git --no-r" "--no-replace-objects "
+'
+
+test_expect_success 'general options plus command' '
+ test_completion "git --version check" "checkout " &&
+ test_completion "git --paginate check" "checkout " &&
+ test_completion "git --git-dir=foo check" "checkout " &&
+ test_completion "git --bare check" "checkout " &&
+ test_completion "git --help des" "describe " &&
+ test_completion "git --exec-path=foo check" "checkout " &&
+ test_completion "git --html-path check" "checkout " &&
+ test_completion "git --no-pager check" "checkout " &&
+ test_completion "git --work-tree=foo check" "checkout " &&
+ test_completion "git --namespace=foo check" "checkout " &&
+ test_completion "git --paginate check" "checkout " &&
+ test_completion "git --info-path check" "checkout " &&
+ test_completion "git --no-replace-objects check" "checkout "
+'
+
+test_done
diff --git a/test-mergesort.c b/test-mergesort.c
new file mode 100644
index 0000000000..3f388b4ce0
--- /dev/null
+++ b/test-mergesort.c
@@ -0,0 +1,52 @@
+#include "cache.h"
+#include "mergesort.h"
+
+struct line {
+ char *text;
+ struct line *next;
+};
+
+static void *get_next(const void *a)
+{
+ return ((const struct line *)a)->next;
+}
+
+static void set_next(void *a, void *b)
+{
+ ((struct line *)a)->next = b;
+}
+
+static int compare_strings(const void *a, const void *b)
+{
+ const struct line *x = a, *y = b;
+ return strcmp(x->text, y->text);
+}
+
+int main(int argc, const char **argv)
+{
+ struct line *line, *p = NULL, *lines = NULL;
+ struct strbuf sb = STRBUF_INIT;
+
+ for (;;) {
+ if (strbuf_getwholeline(&sb, stdin, '\n'))
+ break;
+ line = xmalloc(sizeof(struct line));
+ line->text = strbuf_detach(&sb, NULL);
+ if (p) {
+ line->next = p->next;
+ p->next = line;
+ } else {
+ line->next = NULL;
+ lines = line;
+ }
+ p = line;
+ }
+
+ lines = llist_mergesort(lines, get_next, set_next, compare_strings);
+
+ while (lines) {
+ printf("%s", lines->text);
+ lines = lines->next;
+ }
+ return 0;
+}
diff --git a/test-revision-walking.c b/test-revision-walking.c
new file mode 100644
index 0000000000..3ade02c72d
--- /dev/null
+++ b/test-revision-walking.c
@@ -0,0 +1,66 @@
+/*
+ * test-revision-walking.c: test revision walking API.
+ *
+ * (C) 2012 Heiko Voigt <hvoigt@hvoigt.net>
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "cache.h"
+#include "commit.h"
+#include "diff.h"
+#include "revision.h"
+
+static void print_commit(struct commit *commit)
+{
+ struct strbuf sb = STRBUF_INIT;
+ struct pretty_print_context ctx = {0};
+ ctx.date_mode = DATE_NORMAL;
+ format_commit_message(commit, " %m %s", &sb, &ctx);
+ printf("%s\n", sb.buf);
+ strbuf_release(&sb);
+}
+
+static int run_revision_walk(void)
+{
+ struct rev_info rev;
+ struct commit *commit;
+ const char *argv[] = {NULL, "--all", NULL};
+ int argc = ARRAY_SIZE(argv) - 1;
+ int got_revision = 0;
+
+ init_revisions(&rev, NULL);
+ setup_revisions(argc, argv, &rev, NULL);
+ if (prepare_revision_walk(&rev))
+ die("revision walk setup failed");
+
+ while ((commit = get_revision(&rev)) != NULL) {
+ print_commit(commit);
+ got_revision = 1;
+ }
+
+ reset_revision_walk();
+ return got_revision;
+}
+
+int main(int argc, char **argv)
+{
+ if (argc < 2)
+ return 1;
+
+ if (!strcmp(argv[1], "run-twice")) {
+ printf("1st\n");
+ if (!run_revision_walk())
+ return 1;
+ printf("2nd\n");
+ if (!run_revision_walk())
+ return 1;
+
+ return 0;
+ }
+
+ fprintf(stderr, "check usage\n");
+ return 1;
+}
diff --git a/transport.c b/transport.c
index 2dfac700b6..1811b500d9 100644
--- a/transport.c
+++ b/transport.c
@@ -11,6 +11,7 @@
#include "branch.h"
#include "url.h"
#include "submodule.h"
+#include "string-list.h"
/* rsync support */
@@ -1013,6 +1014,25 @@ void transport_set_verbosity(struct transport *transport, int verbosity,
transport->progress = verbosity >= 0 && isatty(2);
}
+static void die_with_unpushed_submodules(struct string_list *needs_pushing)
+{
+ int i;
+
+ fprintf(stderr, "The following submodule paths contain changes that can\n"
+ "not be found on any remote:\n");
+ for (i = 0; i < needs_pushing->nr; i++)
+ printf(" %s\n", needs_pushing->items[i].string);
+ fprintf(stderr, "\nPlease try\n\n"
+ " git push --recurse-submodules=on-demand\n\n"
+ "or cd to the path and use\n\n"
+ " git push\n\n"
+ "to push them to a remote.\n\n");
+
+ string_list_clear(needs_pushing, 0);
+
+ die("Aborting.");
+}
+
int transport_push(struct transport *transport,
int refspec_nr, const char **refspec, int flags,
int *nonfastforward)
@@ -1053,12 +1073,27 @@ int transport_push(struct transport *transport,
flags & TRANSPORT_PUSH_MIRROR,
flags & TRANSPORT_PUSH_FORCE);
- if ((flags & TRANSPORT_RECURSE_SUBMODULES_CHECK) && !is_bare_repository()) {
+ if ((flags & TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND) && !is_bare_repository()) {
struct ref *ref = remote_refs;
for (; ref; ref = ref->next)
if (!is_null_sha1(ref->new_sha1) &&
- check_submodule_needs_pushing(ref->new_sha1,transport->remote->name))
- die("There are unpushed submodules, aborting.");
+ !push_unpushed_submodules(ref->new_sha1,
+ transport->remote->name))
+ die ("Failed to push all needed submodules!");
+ }
+
+ if ((flags & (TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND |
+ TRANSPORT_RECURSE_SUBMODULES_CHECK)) && !is_bare_repository()) {
+ struct ref *ref = remote_refs;
+ struct string_list needs_pushing;
+
+ memset(&needs_pushing, 0, sizeof(struct string_list));
+ needs_pushing.strdup_strings = 1;
+ for (; ref; ref = ref->next)
+ if (!is_null_sha1(ref->new_sha1) &&
+ find_unpushed_submodules(ref->new_sha1,
+ transport->remote->name, &needs_pushing))
+ die_with_unpushed_submodules(&needs_pushing);
}
push_ret = transport->push_refs(transport, remote_refs, flags);
diff --git a/transport.h b/transport.h
index 1631a35ea6..b866c126e6 100644
--- a/transport.h
+++ b/transport.h
@@ -103,6 +103,7 @@ struct transport {
#define TRANSPORT_PUSH_SET_UPSTREAM 32
#define TRANSPORT_RECURSE_SUBMODULES_CHECK 64
#define TRANSPORT_PUSH_PRUNE 128
+#define TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND 256
#define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
diff --git a/unpack-trees.c b/unpack-trees.c
index 36523da22a..1d7393d84c 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -1027,6 +1027,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
o->result.initialized = 1;
o->result.timestamp.sec = o->src_index->timestamp.sec;
o->result.timestamp.nsec = o->src_index->timestamp.nsec;
+ o->result.version = o->src_index->version;
o->merge_size = len;
mark_all_ce_unused(o->src_index);
diff --git a/varint.c b/varint.c
new file mode 100644
index 0000000000..4ed7729496
--- /dev/null
+++ b/varint.c
@@ -0,0 +1,29 @@
+#include "varint.h"
+
+uintmax_t decode_varint(const unsigned char **bufp)
+{
+ const unsigned char *buf = *bufp;
+ unsigned char c = *buf++;
+ uintmax_t val = c & 127;
+ while (c & 128) {
+ val += 1;
+ if (!val || MSB(val, 7))
+ return 0; /* overflow */
+ c = *buf++;
+ val = (val << 7) + (c & 127);
+ }
+ *bufp = buf;
+ return val;
+}
+
+int encode_varint(uintmax_t value, unsigned char *buf)
+{
+ unsigned char varint[16];
+ unsigned pos = sizeof(varint) - 1;
+ varint[pos] = value & 127;
+ while (value >>= 7)
+ varint[--pos] = 128 | (--value & 127);
+ if (buf)
+ memcpy(buf, varint + pos, sizeof(varint) - pos);
+ return sizeof(varint) - pos;
+}
diff --git a/varint.h b/varint.h
new file mode 100644
index 0000000000..0321195796
--- /dev/null
+++ b/varint.h
@@ -0,0 +1,9 @@
+#ifndef VARINT_H
+#define VARINT_H
+
+#include "git-compat-util.h"
+
+extern int encode_varint(uintmax_t, unsigned char *);
+extern uintmax_t decode_varint(const unsigned char **);
+
+#endif /* VARINT_H */