Merge branch 'jk/send-pack-many-refspecs'
authorJunio C Hamano <gitster@pobox.com>
Fri, 19 Sep 2014 18:38:31 +0000 (11:38 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 19 Sep 2014 18:38:31 +0000 (11:38 -0700)
The number of refs that can be pushed at once over smart HTTP was
limited by the command line length. The limitation has been lifted
by passing these refs from the standard input of send-pack.

* jk/send-pack-many-refspecs:
send-pack: take refspecs over stdin

157 files changed:
.gitignore
Documentation/RelNotes/2.2.0.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/git-imap-send.txt
Documentation/git-init.txt
Documentation/git-rebase.txt
Documentation/git-svn.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/pretty-formats.txt
Documentation/technical/api-config.txt
Documentation/technical/api-run-command.txt
Documentation/technical/api-strbuf.txt
Documentation/technical/pack-protocol.txt
GIT-VERSION-GEN
Makefile
RelNotes
abspath.c
advice.c
alias.c
archive-tar.c
archive.c
bisect.c
branch.c
builtin/add.c
builtin/apply.c
builtin/blame.c
builtin/branch.c
builtin/checkout.c
builtin/clean.c
builtin/clone.c
builtin/commit.c
builtin/config.c
builtin/fetch.c
builtin/gc.c
builtin/help.c
builtin/init-db.c
builtin/log.c
builtin/mailsplit.c
builtin/merge.c
builtin/mv.c
builtin/notes.c
builtin/receive-pack.c
builtin/remote-ext.c
builtin/repack.c
builtin/replace.c
builtin/rev-parse.c
builtin/tag.c
builtin/update-ref.c
builtin/verify-pack.c
bundle.c
cache-tree.c
cache-tree.h
cache.h
column.c
combine-diff.c
commit.h
config.c
config.mak.uname
connect.c
connected.c
contrib/completion/git-prompt.sh
contrib/subtree/Makefile
convert.c
credential-cache.c
credential.c
daemon.c
diff.c
diffcore-rename.c
diffcore.h
dir.c
editor.c
exec_cmd.c
fast-import.c
fetch-pack.c
git-compat-util.h
git-pull.sh
git-stash.sh
git-svn.perl
git.c
gpg-interface.c
http-backend.c
http.c
ident.c
imap-send.c
ll-merge.c
lockfile.c
log-tree.c
merge-recursive.c
pager.c
path.c
po/TEAMS
po/de.po
pretty.c
prompt.c
read-cache.c
refs.c
refs.h
remote-curl.c
remote-testsvn.c
remote.c
remote.h
rerere.c
revision.c
run-command.c
run-command.h
send-pack.c
sequencer.c
setup.c
sha1_file.c
sha1_name.c
strbuf.c
strbuf.h
submodule.c
t/t0008-ignores.sh
t/t0081-line-buffer.sh
t/t0090-cache-tree.sh
t/t1020-subdirectory.sh
t/t1050-large.sh
t/t1300-repo-config.sh
t/t1308-config-set.sh [new file with mode: 0755]
t/t1402-check-ref-format.sh
t/t3210-pack-refs.sh
t/t3901-i18n-patch.sh
t/t3903-stash.sh
t/t4055-diff-context.sh
t/t4119-apply-config.sh
t/t4124-apply-ws-rule.sh
t/t4201-shortlog.sh
t/t4205-log-pretty-formats.sh
t/t4210-log-i18n.sh
t/t5004-archive-corner-cases.sh
t/t5601-clone.sh
t/t5704-bundle.sh
t/t7201-co.sh
t/t7515-status-symlinks.sh [new file with mode: 0755]
t/t8005-blame-i18n.sh
t/t9119-git-svn-info.sh
t/t9300-fast-import.sh
t/t9809-git-p4-client-view.sh
t/t9812-git-p4-wildcards.sh
t/t9815-git-p4-submit-fail.sh
t/test-lib.sh
test-config.c [new file with mode: 0644]
test-dump-cache-tree.c
test-run-command.c
test-subprocess.c
trace.c
transport-helper.c
transport.c
unix-socket.c
unpack-trees.c
upload-pack.c
utf8.c
walker.c
wrapper.c
wt-status.c
index 81e12c0621d42b495ab540391e1cd8ece18587b7..5bfb234591a63446d9fccf7665e442f02d1c76b5 100644 (file)
 /gitweb/static/gitweb.min.*
 /test-chmtime
 /test-ctype
+/test-config
 /test-date
 /test-delta
 /test-dump-cache-tree
diff --git a/Documentation/RelNotes/2.2.0.txt b/Documentation/RelNotes/2.2.0.txt
new file mode 100644 (file)
index 0000000..22b7361
--- /dev/null
@@ -0,0 +1,132 @@
+Git v2.2 Release Notes
+======================
+
+Updates since v2.1
+------------------
+
+Ports
+
+ * Building on older MacOS X systems automatically sets
+   the necessary NO_APPLE_COMMON_CRYPTO build-time option.
+
+
+UI, Workflows & Features
+
+ * "git config --edit --global" starts from a skeletal per-user
+   configuration file contents, instead of a total blank, when the
+   user does not already have any.  This immediately reduces the
+   need for a later "Have you forgotten setting core.user?" and we
+   can add more to the template as we gain more experience.
+
+ * "git stash list -p" used to be almost always a no-op because each
+   stash entry is represented as a merge commit.  It learned to show
+   the difference between the base commit version and the working tree
+   version, which is in line with what "git show" gives.
+
+Performance, Internal Implementation, etc.
+
+ * The API to manipulate the "refs" is currently undergoing a revamp
+   to make it more transactional, with the eventual goal to allow
+   all-or-none atomic updates and migrating the storage to something
+   other than the traditional filesystem based one (e.g. databases).
+
+ * We no longer attempt to keep track of individual dependencies to
+   the header files in the build procedure, relying on automated
+   dependency generation support from modern compilers.
+
+ * In tests, we have been using NOT_{MINGW,CYGWIN} test prerequisites
+   long before negated prerequisites e.g. !MINGW were invented.
+   The former has been converted to the latter to avoid confusion.
+
+ * Looking up remotes configuration in a repository with very many
+   remotes defined has been optimized.
+
+ * There are cases where you lock and open to write a file, close it
+   to show the updated contents to external processes, and then have
+   to update the file again while still holding the lock, but the
+   lockfile API lacked support for such an access pattern.
+
+ * The API to allocate the structure to keep track of commit
+   decoration has been updated to make it less cumbersome to use.
+
+ * An in-core caching layer to let us avoid reading the same
+   configuration files number of times has been added.  A few commands
+   have been converted to use this subsystem.
+
+ * Various code paths have been cleaned up and simplified by using
+   "strbuf", "starts_with()", and "skip_prefix()" APIs more.
+
+ * A few codepaths that died when large blobs that would not fit in
+   core are involved in their operation have been taught to punt
+   instead, by e.g. marking too large a blob as not to be diffed.
+
+ * A few more code paths in "commit" and "checkout" have been taught
+   to repopulate the cache-tree in the index, to help speed up later
+   "write-tree" (used in "commit") and "diff-index --cached" (used in
+   "status").
+
+
+Also contains various documentation updates and code clean-ups.
+
+
+Fixes since v2.1
+----------------
+
+Unless otherwise noted, all the fixes since v2.1 in the maintenance
+track are contained in this release (see the maintenance releases'
+notes for details).
+
+ * "git log --pretty/format=" with an empty format string did not
+   mean the more obvious "No output whatsoever" but "Use default
+   format", which was counterintuitive.
+   (merge b9c7d6e jk/pretty-empty-format later to maint).
+
+ * Implementations of "tar" that do not understand an extended pax
+   header would extract the contents of it in a regular file; make
+   sure the permission bits of this file follows the same tar.umask
+   configuration setting.
+
+ * "git -c section.var command" and "git -c section.var= command"
+   should pass the configuration differently (the former should be a
+   boolean true, the latter should be an empty string).
+   (merge a789ca7 jk/command-line-config-empty-string later to maint).
+
+ * Applying a patch not generated by Git in a subdirectory used to
+   check the whitespace breakage using the attributes for incorrect
+   paths. Also whitespace checks were performed even for paths
+   excluded via "git apply --exclude=<path>" mechanism.
+   (merge 477a08a jc/apply-ws-prefix later to maint).
+
+ * "git bundle create" with date-range specification were meant to
+   exclude tags outside the range, but it didn't.
+   (merge 2c8544a lf/bundle-exclusion later to maint).
+
+ * "git add x" where x that used to be a directory has become a
+   symbolic link to a directory misbehaved.
+   (merge ccad42d rs/refresh-beyond-symlink later to maint).
+
+ * The prompt script checked $GIT_DIR/ref/stash file to see if there
+   is a stash, which was a no-no.
+   (merge 0fa7f01 jk/prompt-stash-could-be-packed later to maint).
+
+ * Pack-protocol documentation had a minor typo.
+   (merge 5d146f7 sp/pack-protocol-doc-on-shallow later to maint).
+
+ * "git checkout -m" did not switch to another branch while carrying
+   the local changes forward when a path was deleted from the index.
+   (merge 6a143aa jn/unpack-trees-checkout-m-carry-deletion later to maint).
+
+ * With sufficiently long refnames, "git fast-import" could have
+   overflown an on-stack buffer.
+   (merge c252785 jk/fast-import-fixes later to maint).
+
+ * After "pack-refs --prune" packed refs at the top-level, it failed
+   to prune them.
+   (merge afd11d3 jk/prune-top-level-refs-after-packing later to maint).
+
+ * Progress output from "git gc --auto" was visible in "git fetch -q".
+   (merge 6fceed3 nd/fetch-pass-quiet-to-gc-child-process later to maint).
+
+ * We used to pass -1000 to poll(2), expecting it to also mean "no
+   timeout", which should be spelled as -1.
+   (merge 6c71f8b et/spell-poll-infinite-with-minus-one-only later to maint).
index c55c22ab7be94e798164a48622aca21dd4daa44f..3b5b24aeb7f16c03e06bd6f38fd89e9080011ce7 100644 (file)
@@ -499,7 +499,8 @@ core.bigFileThreshold::
        Files larger than this size are stored deflated, without
        attempting delta compression.  Storing large files without
        delta compression avoids excessive memory usage, at the
-       slight expense of increased disk usage.
+       slight expense of increased disk usage. Additionally files
+       larger than this size are always treated as binary.
 +
 Default is 512 MiB on all platforms.  This should be reasonable
 for most projects as source code and other text files can still
index 875d2831a541170402849e2c8598fabafa42a0df..7d991d919ccf3378fdc924418aede45f8cb38632 100644 (file)
@@ -38,18 +38,17 @@ Variables
 imap.folder::
        The folder to drop the mails into, which is typically the Drafts
        folder. For example: "INBOX.Drafts", "INBOX/Drafts" or
-       "[Gmail]/Drafts". Required to use imap-send.
+       "[Gmail]/Drafts". Required.
 
 imap.tunnel::
        Command used to setup a tunnel to the IMAP server through which
        commands will be piped instead of using a direct network connection
-       to the server. Required when imap.host is not set to use imap-send.
+       to the server. Required when imap.host is not set.
 
 imap.host::
        A URL identifying the server. Use a `imap://` prefix for non-secure
        connections and a `imaps://` prefix for secure connections.
-       Ignored when imap.tunnel is set, but required to use imap-send
-       otherwise.
+       Ignored when imap.tunnel is set, but required otherwise.
 
 imap.user::
        The username to use when logging in to the server.
@@ -76,7 +75,8 @@ imap.preformattedHTML::
 
 imap.authMethod::
        Specify authenticate method for authentication with IMAP server.
-       Current supported method is 'CRAM-MD5' only.
+       Current supported method is 'CRAM-MD5' only. If this is not set
+       then 'git imap-send' uses the basic IMAP plaintext LOGIN command.
 
 Examples
 ~~~~~~~~
index afd721e3a94e377372431254d6c0f3e79a61c099..369f889bb4d5f9f5066552cef74525649477ca9c 100644 (file)
@@ -43,7 +43,7 @@ OPTIONS
 -q::
 --quiet::
 
-Only print error and warning messages, all other output will be suppressed.
+Only print error and warning messages; all other output will be suppressed.
 
 --bare::
 
@@ -57,12 +57,12 @@ DIRECTORY" section below.)
 
 --separate-git-dir=<git dir>::
 
-Instead of initializing the repository where it is supposed to be,
-place a filesytem-agnostic Git symbolic link there, pointing to the
-specified path, and initialize a Git repository at the path. The
-result is Git repository can be separated from working tree. If this
-is reinitialization, the repository will be moved to the specified
-path.
+Instead of initializing the repository as a directory to either `$GIT_DIR` or
+`./.git/`, create a text file there containing the path to the actual
+repository.  This file acts as filesystem-agnostic Git symbolic link to the
+repository.
++
+If this is reinitialization, the repository will be moved to the specified path.
 
 --shared[=(false|true|umask|group|all|world|everybody|0xxx)]::
 
@@ -72,60 +72,65 @@ repository.  When specified, the config variable "core.sharedRepository" is
 set so that files and directories under `$GIT_DIR` are created with the
 requested permissions.  When not specified, Git will use permissions reported
 by umask(2).
-
++
 The option can have the following values, defaulting to 'group' if no value
 is given:
++
+--
+'umask' (or 'false')::
 
- - 'umask' (or 'false'): Use permissions reported by umask(2). The default,
-   when `--shared` is not specified.
+Use permissions reported by umask(2). The default, when `--shared` is not
+specified.
 
- - 'group' (or 'true'): Make the repository group-writable, (and g+sx, since
-   the git group may be not the primary group of all users).
-   This is used to loosen the permissions of an otherwise safe umask(2) value.
-   Note that the umask still applies to the other permission bits (e.g. if
-   umask is '0022', using 'group' will not remove read privileges from other
-   (non-group) users). See '0xxx' for how to exactly specify the repository
-   permissions.
+'group' (or 'true')::
 
- - 'all' (or 'world' or 'everybody'): Same as 'group', but make the repository
-   readable by all users.
+Make the repository group-writable, (and g+sx, since the git group may be not
+the primary group of all users). This is used to loosen the permissions of an
+otherwise safe umask(2) value. Note that the umask still applies to the other
+permission bits (e.g. if umask is '0022', using 'group' will not remove read
+privileges from other (non-group) users). See '0xxx' for how to exactly specify
+the repository permissions.
 
- - '0xxx': '0xxx' is an octal number and each file will have mode '0xxx'.
-   '0xxx' will override users' umask(2) value (and not only loosen permissions
-   as 'group' and 'all' does). '0640' will create a repository which is
-   group-readable, but not group-writable or accessible to others. '0660' will
-   create a repo that is readable and writable to the current user and group,
-   but inaccessible to others.
+'all' (or 'world' or 'everybody')::
 
-By default, the configuration flag receive.denyNonFastForwards is enabled
+Same as 'group', but make the repository readable by all users.
+
+'0xxx'::
+
+'0xxx' is an octal number and each file will have mode '0xxx'. '0xxx' will
+override users' umask(2) value (and not only loosen permissions as 'group' and
+'all' does). '0640' will create a repository which is group-readable, but not
+group-writable or accessible to others. '0660' will create a repo that is
+readable and writable to the current user and group, but inaccessible to others.
+--
+
+By default, the configuration flag `receive.denyNonFastForwards` is enabled
 in shared repositories, so that you cannot force a non fast-forwarding push
 into it.
 
-If you name a (possibly non-existent) directory at the end of the command
-line, the command is run inside the directory (possibly after creating it).
+If you provide a 'directory', the command is run inside it. If this directory
+does not exist, it will be created.
 
 --
 
-
 TEMPLATE DIRECTORY
 ------------------
 
 The template directory contains files and directories that will be copied to
 the `$GIT_DIR` after it is created.
 
-The template directory used will (in order):
+The template directory will be one of the following (in order):
 
- - The argument given with the `--template` option.
+ - the argument given with the `--template` option;
 
- - The contents of the `$GIT_TEMPLATE_DIR` environment variable.
+ - the contents of the `$GIT_TEMPLATE_DIR` environment variable;
 
- - The `init.templatedir` configuration variable.
+ - the `init.templatedir` configuration variable; or
 
- - The default template directory: `/usr/share/git-core/templates`.
+ - the default template directory: `/usr/share/git-core/templates`.
 
-The default template directory includes some directory structure, some
-suggested "exclude patterns", and copies of sample "hook" files.
-The suggested patterns and hook files are all modifiable and extensible.
+The default template directory includes some directory structure, suggested
+"exclude patterns" (see linkgit:gitignore[5]), and sample hook files (see linkgit:githooks[5]).
 
 EXAMPLES
 --------
@@ -136,10 +141,12 @@ Start a new Git repository for an existing code base::
 $ cd /path/to/my/codebase
 $ git init      <1>
 $ git add .     <2>
+$ git commit    <3>
 ----------------
 +
-<1> prepare /path/to/my/codebase/.git directory
-<2> add all existing file to the index
+<1> Create a /path/to/my/codebase/.git directory.
+<2> Add all existing files to the index.
+<3> Record the pristine state as the first commit in the history.
 
 GIT
 ---
index 2a93c645bdb62c28ac9315659b794aa1d3932a4b..f14100a16022306d280221b3cb1ae88f8c5498ce 100644 (file)
@@ -316,11 +316,8 @@ which makes little sense.
 
 -f::
 --force-rebase::
-       Force the rebase even if the current branch is a descendant
-       of the commit you are rebasing onto.  Normally non-interactive rebase will
-       exit with the message "Current branch is up to date" in such a
-       situation.
-       Incompatible with the --interactive option.
+       Force a rebase even if the current branch is up-to-date and
+       the command without `--force` would return without doing anything.
 +
 You may find this (or --no-ff with an interactive rebase) helpful after
 reverting a topic branch merge, as this option recreates the topic branch with
index 44c970ce18143e2a45c9f5364535e26508b50317..ef8ef1c545bbc14366ec71d904ad77b2a74802ff 100644 (file)
@@ -386,11 +386,13 @@ Any other arguments are passed directly to 'git log'
        tree-ish to specify which branch should be searched).  When given a
        tree-ish, returns the corresponding SVN revision number.
 +
+-B;;
 --before;;
        Don't require an exact match if given an SVN revision, instead find
        the commit corresponding to the state of the SVN repository (on the
        current branch) at the specified revision.
 +
+-A;;
 --after;;
        Don't require an exact match if given an SVN revision; if there is
        not an exact match return the closest match searching forward in the
@@ -608,21 +610,6 @@ config key: svn.authorsfile
        Make 'git svn' less verbose. Specify a second time to make it
        even less verbose.
 
---repack[=<n>]::
---repack-flags=<flags>::
-       These should help keep disk usage sane for large fetches with
-       many revisions.
-+
---repack takes an optional argument for the number of revisions
-to fetch before repacking.  This defaults to repacking every
-1000 commits fetched if no argument is specified.
-+
---repack-flags are passed directly to 'git repack'.
-+
-[verse]
-config key: svn.repack
-config key: svn.repackflags
-
 -m::
 --merge::
 -s<strategy>::
index de7b870a35e63e43652be6468e6e5a17d2708a14..26de4dd54804ed6d14f9e568547154996b919bd4 100644 (file)
@@ -452,6 +452,11 @@ example the following invocations are equivalent:
        given will override values from configuration files.
        The <name> is expected in the same format as listed by
        'git config' (subkeys separated by dots).
++
+Note that omitting the `=` in `git -c foo.bar ...` is allowed and sets
+`foo.bar` to the boolean true value (just like `[foo]bar` would in a
+config file). Including the equals but with an empty value (like `git -c
+foo.bar= ...`) sets `foo.bar` to the empty string.
 
 --exec-path[=<path>]::
        Path to wherever your core Git programs are installed.
index 643c1ba9290ff10813eab57b95f7c26d8c43c7e2..9b45bda7485c7e4742b13cdf19272968592b640a 100644 (file)
@@ -440,8 +440,8 @@ Unspecified::
 
        A path to which the `diff` attribute is unspecified
        first gets its contents inspected, and if it looks like
-       text, it is treated as text.  Otherwise it would
-       generate `Binary files differ`.
+       text and is smaller than core.bigFileThreshold, it is treated
+       as text. Otherwise it would generate `Binary files differ`.
 
 String::
 
index 85d63532a3e165110717ca2602e9dd806f10bd9f..eac79096d3d9cb544c9e213d285b5a3158367246 100644 (file)
@@ -122,7 +122,7 @@ The placeholders are:
 - '%ce': committer email
 - '%cE': committer email (respecting .mailmap, see
   linkgit:git-shortlog[1] or linkgit:git-blame[1])
-- '%cd': committer date
+- '%cd': committer date (format respects --date= option)
 - '%cD': committer date, RFC2822 style
 - '%cr': committer date, relative
 - '%ct': committer date, UNIX timestamp
index edd5018e158362fb3ad91c6d797d591eefb46678..0d8b99b368aea13a322382314d88229acda0b1db 100644 (file)
@@ -77,6 +77,99 @@ To read a specific file in git-config format, use
 `git_config_from_file`. This takes the same callback and data parameters
 as `git_config`.
 
+Querying For Specific Variables
+-------------------------------
+
+For programs wanting to query for specific variables in a non-callback
+manner, the config API provides two functions `git_config_get_value`
+and `git_config_get_value_multi`. They both read values from an internal
+cache generated previously from reading the config files.
+
+`int git_config_get_value(const char *key, const char **value)`::
+
+       Finds the highest-priority value for the configuration variable `key`,
+       stores the pointer to it in `value` and returns 0. When the
+       configuration variable `key` is not found, returns 1 without touching
+       `value`. The caller should not free or modify `value`, as it is owned
+       by the cache.
+
+`const struct string_list *git_config_get_value_multi(const char *key)`::
+
+       Finds and returns the value list, sorted in order of increasing priority
+       for the configuration variable `key`. When the configuration variable
+       `key` is not found, returns NULL. The caller should not free or modify
+       the returned pointer, as it is owned by the cache.
+
+`void git_config_clear(void)`::
+
+       Resets and invalidates the config cache.
+
+The config API also provides type specific API functions which do conversion
+as well as retrieval for the queried variable, including:
+
+`int git_config_get_int(const char *key, int *dest)`::
+
+       Finds and parses the value to an integer for the configuration variable
+       `key`. Dies on error; otherwise, stores the value of the parsed integer in
+       `dest` and returns 0. When the configuration variable `key` is not found,
+       returns 1 without touching `dest`.
+
+`int git_config_get_ulong(const char *key, unsigned long *dest)`::
+
+       Similar to `git_config_get_int` but for unsigned longs.
+
+`int git_config_get_bool(const char *key, int *dest)`::
+
+       Finds and parses the value into a boolean value, for the configuration
+       variable `key` respecting keywords like "true" and "false". Integer
+       values are converted into true/false values (when they are non-zero or
+       zero, respectively). Other values cause a die(). If parsing is successful,
+       stores the value of the parsed result in `dest` and returns 0. When the
+       configuration variable `key` is not found, returns 1 without touching
+       `dest`.
+
+`int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest)`::
+
+       Similar to `git_config_get_bool`, except that integers are copied as-is,
+       and `is_bool` flag is unset.
+
+`int git_config_get_maybe_bool(const char *key, int *dest)`::
+
+       Similar to `git_config_get_bool`, except that it returns -1 on error
+       rather than dying.
+
+`int git_config_get_string_const(const char *key, const char **dest)`::
+
+       Allocates and copies the retrieved string into the `dest` parameter for
+       the configuration variable `key`; if NULL string is given, prints an
+       error message and returns -1. When the configuration variable `key` is
+       not found, returns 1 without touching `dest`.
+
+`int git_config_get_string(const char *key, char **dest)`::
+
+       Similar to `git_config_get_string_const`, except that retrieved value
+       copied into the `dest` parameter is a mutable string.
+
+`int git_config_get_pathname(const char *key, const char **dest)`::
+
+       Similar to `git_config_get_string`, but expands `~` or `~user` into
+       the user's home directory when found at the beginning of the path.
+
+`git_die_config(const char *key, const char *err, ...)`::
+
+       First prints the error message specified by the caller in `err` and then
+       dies printing the line number and the file name of the highest priority
+       value for the configuration variable `key`.
+
+`void git_die_config_linenr(const char *key, const char *filename, int linenr)`::
+
+       Helper function which formats the die error message according to the
+       parameters entered. Used by `git_die_config()`. It can be used by callers
+       handling `git_config_get_value_multi()` to print the correct error message
+       for the desired value.
+
+See test-config.c for usage examples.
+
 Value Parsing Helpers
 ---------------------
 
@@ -134,6 +227,68 @@ int read_file_with_include(const char *file, config_fn_t fn, void *data)
 `git_config` respects includes automatically. The lower-level
 `git_config_from_file` does not.
 
+Custom Configsets
+-----------------
+
+A `config_set` can be used to construct an in-memory cache for
+config-like files that the caller specifies (i.e., files like `.gitmodules`,
+`~/.gitconfig` etc.). For example,
+
+---------------------------------------
+struct config_set gm_config;
+git_configset_init(&gm_config);
+int b;
+/* we add config files to the config_set */
+git_configset_add_file(&gm_config, ".gitmodules");
+git_configset_add_file(&gm_config, ".gitmodules_alt");
+
+if (!git_configset_get_bool(gm_config, "submodule.frotz.ignore", &b)) {
+       /* hack hack hack */
+}
+
+/* when we are done with the configset */
+git_configset_clear(&gm_config);
+----------------------------------------
+
+Configset API provides functions for the above mentioned work flow, including:
+
+`void git_configset_init(struct config_set *cs)`::
+
+       Initializes the config_set `cs`.
+
+`int git_configset_add_file(struct config_set *cs, const char *filename)`::
+
+       Parses the file and adds the variable-value pairs to the `config_set`,
+       dies if there is an error in parsing the file. Returns 0 on success, or
+       -1 if the file does not exist or is inaccessible. The user has to decide
+       if he wants to free the incomplete configset or continue using it when
+       the function returns -1.
+
+`int git_configset_get_value(struct config_set *cs, const char *key, const char **value)`::
+
+       Finds the highest-priority value for the configuration variable `key`
+       and config set `cs`, stores the pointer to it in `value` and returns 0.
+       When the configuration variable `key` is not found, returns 1 without
+       touching `value`. The caller should not free or modify `value`, as it
+       is owned by the cache.
+
+`const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key)`::
+
+       Finds and returns the value list, sorted in order of increasing priority
+       for the configuration variable `key` and config set `cs`. When the
+       configuration variable `key` is not found, returns NULL. The caller
+       should not free or modify the returned pointer, as it is owned by the cache.
+
+`void git_configset_clear(struct config_set *cs)`::
+
+       Clears `config_set` structure, removes all saved variable-value pairs.
+
+In addition to above functions, the `config_set` API provides type specific
+functions in the vein of `git_config_get_int` and family but with an extra
+parameter, pointer to struct `config_set`.
+They all behave similarly to the `git_config_get*()` family described in
+"Querying For Specific Variables" above.
+
 Writing Config Files
 --------------------
 
index 69510ae57afcedbe13334160c6a26c52c42e8d54..842b8389eb867b6db654cf7fe29e8f10b92b259e 100644 (file)
@@ -13,6 +13,10 @@ produces in the caller in order to process it.
 Functions
 ---------
 
+`child_process_init`
+
+       Initialize a struct child_process variable.
+
 `start_command`::
 
        Start a sub-process. Takes a pointer to a `struct child_process`
@@ -96,8 +100,8 @@ command to run in a sub-process.
 
 The caller:
 
-1. allocates and clears (memset(&chld, 0, sizeof(chld));) a
-   struct child_process variable;
+1. allocates and clears (using child_process_init() or
+   CHILD_PROCESS_INIT) a struct child_process variable;
 2. initializes the members;
 3. calls start_command();
 4. processes the data;
index f9c06a7573e9294a967d641cdfc2723b86c1c864..430302c2f4ee8c3881d663b1f395234fd8cad0a3 100644 (file)
@@ -307,6 +307,16 @@ same behaviour as well.
        use it unless you need the correct position in the file
        descriptor.
 
+`strbuf_getcwd`::
+
+       Set the buffer to the path of the current working directory.
+
+`strbuf_add_absolute_path`
+
+       Add a path to a buffer, converting a relative path to an
+       absolute one in the process.  Symbolic links are not
+       resolved.
+
 `stripspace`::
 
        Strip whitespace from a buffer. The second parameter controls if
index 18dea8d15fa159b719a38588a0a346e58120ac61..569c48a352b76ab3fc0d31f21f0f1a1bd654f41d 100644 (file)
@@ -467,7 +467,7 @@ references.
 ----
   update-request    =  *shallow command-list [pack-file]
 
-  shallow           =  PKT-LINE("shallow" SP obj-id)
+  shallow           =  PKT-LINE("shallow" SP obj-id LF)
 
   command-list      =  PKT-LINE(command NUL capability-list LF)
                       *PKT-LINE(command LF)
index a4cdfbf7f6b547a45c9c561757c1588fe0fba369..153d55d2b99e1340f92140eb231cd919d3af80c8 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.1.0
+DEF_VER=v2.1.0.GIT
 
 LF='
 '
index 9f984a9e5561d6b67b453124a311963ae8845f6d..e0f15a3df3ae441d33b9d0a0ddadc729ec4773b3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -317,9 +317,6 @@ all::
 # dependency rules.  The default is "auto", which means to use computed header
 # dependencies if your compiler is detected to support it.
 #
-# Define CHECK_HEADER_DEPENDENCIES to check for problems in the hard-coded
-# dependency rules.
-#
 # Define NATIVE_CRLF if your platform uses CRLF for line endings.
 #
 # Define XDL_FAST_HASH to use an alternative line-hashing method in
@@ -432,7 +429,6 @@ XDIFF_OBJS =
 VCSSVN_OBJS =
 GENERATED_H =
 EXTRA_CPPFLAGS =
-LIB_H =
 LIB_OBJS =
 PROGRAM_OBJS =
 PROGRAMS =
@@ -551,6 +547,7 @@ PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
 
 TEST_PROGRAMS_NEED_X += test-chmtime
 TEST_PROGRAMS_NEED_X += test-ctype
+TEST_PROGRAMS_NEED_X += test-config
 TEST_PROGRAMS_NEED_X += test-date
 TEST_PROGRAMS_NEED_X += test-delta
 TEST_PROGRAMS_NEED_X += test-dump-cache-tree
@@ -631,131 +628,11 @@ VCSSVN_LIB = vcs-svn/lib.a
 
 GENERATED_H += common-cmds.h
 
-LIB_H += advice.h
-LIB_H += archive.h
-LIB_H += argv-array.h
-LIB_H += attr.h
-LIB_H += bisect.h
-LIB_H += blob.h
-LIB_H += branch.h
-LIB_H += builtin.h
-LIB_H += bulk-checkin.h
-LIB_H += bundle.h
-LIB_H += cache-tree.h
-LIB_H += cache.h
-LIB_H += color.h
-LIB_H += column.h
-LIB_H += commit.h
-LIB_H += compat/bswap.h
-LIB_H += compat/mingw.h
-LIB_H += compat/obstack.h
-LIB_H += compat/poll/poll.h
-LIB_H += compat/precompose_utf8.h
-LIB_H += compat/terminal.h
-LIB_H += compat/win32/dirent.h
-LIB_H += compat/win32/pthread.h
-LIB_H += compat/win32/syslog.h
-LIB_H += connected.h
-LIB_H += convert.h
-LIB_H += credential.h
-LIB_H += csum-file.h
-LIB_H += decorate.h
-LIB_H += delta.h
-LIB_H += diff.h
-LIB_H += diffcore.h
-LIB_H += dir.h
-LIB_H += exec_cmd.h
-LIB_H += ewah/ewok.h
-LIB_H += ewah/ewok_rlw.h
-LIB_H += fetch-pack.h
-LIB_H += fmt-merge-msg.h
-LIB_H += fsck.h
-LIB_H += gettext.h
-LIB_H += git-compat-util.h
-LIB_H += gpg-interface.h
-LIB_H += graph.h
-LIB_H += grep.h
-LIB_H += hashmap.h
-LIB_H += help.h
-LIB_H += http.h
-LIB_H += kwset.h
-LIB_H += levenshtein.h
-LIB_H += line-log.h
-LIB_H += line-range.h
-LIB_H += list-objects.h
-LIB_H += ll-merge.h
-LIB_H += log-tree.h
-LIB_H += mailmap.h
-LIB_H += merge-blobs.h
-LIB_H += merge-recursive.h
-LIB_H += mergesort.h
-LIB_H += notes-cache.h
-LIB_H += notes-merge.h
-LIB_H += notes-utils.h
-LIB_H += notes.h
-LIB_H += object.h
-LIB_H += pack-objects.h
-LIB_H += pack-revindex.h
-LIB_H += pack.h
-LIB_H += pack-bitmap.h
-LIB_H += parse-options.h
-LIB_H += patch-ids.h
-LIB_H += pathspec.h
-LIB_H += pkt-line.h
-LIB_H += prio-queue.h
-LIB_H += progress.h
-LIB_H += prompt.h
-LIB_H += quote.h
-LIB_H += reachable.h
-LIB_H += reflog-walk.h
-LIB_H += refs.h
-LIB_H += remote.h
-LIB_H += rerere.h
-LIB_H += resolve-undo.h
-LIB_H += revision.h
-LIB_H += run-command.h
-LIB_H += send-pack.h
-LIB_H += sequencer.h
-LIB_H += sha1-array.h
-LIB_H += sha1-lookup.h
-LIB_H += shortlog.h
-LIB_H += sideband.h
-LIB_H += sigchain.h
-LIB_H += strbuf.h
-LIB_H += streaming.h
-LIB_H += string-list.h
-LIB_H += submodule.h
-LIB_H += tag.h
-LIB_H += tar.h
-LIB_H += thread-utils.h
-LIB_H += transport.h
-LIB_H += tree-walk.h
-LIB_H += tree.h
-LIB_H += unpack-trees.h
-LIB_H += unicode_width.h
-LIB_H += url.h
-LIB_H += urlmatch.h
-LIB_H += userdiff.h
-LIB_H += utf8.h
-LIB_H += varint.h
-LIB_H += vcs-svn/fast_export.h
-LIB_H += vcs-svn/line_buffer.h
-LIB_H += vcs-svn/repo_tree.h
-LIB_H += vcs-svn/sliding_window.h
-LIB_H += vcs-svn/svndiff.h
-LIB_H += vcs-svn/svndump.h
-LIB_H += walker.h
-LIB_H += wildmatch.h
-LIB_H += wt-status.h
-LIB_H += xdiff-interface.h
-LIB_H += xdiff/xdiff.h
-LIB_H += xdiff/xdiffi.h
-LIB_H += xdiff/xemit.h
-LIB_H += xdiff/xinclude.h
-LIB_H += xdiff/xmacros.h
-LIB_H += xdiff/xprepare.h
-LIB_H += xdiff/xtypes.h
-LIB_H += xdiff/xutils.h
+LIB_H = $(shell $(FIND) . \
+       -name .git -prune -o \
+       -name t -prune -o \
+       -name Documentation -prune -o \
+       -name '*.h' -print)
 
 LIB_OBJS += abspath.o
 LIB_OBJS += advice.o
@@ -1025,11 +902,6 @@ sysconfdir = etc
 endif
 endif
 
-ifdef CHECK_HEADER_DEPENDENCIES
-COMPUTE_HEADER_DEPENDENCIES = no
-USE_COMPUTED_HEADER_DEPENDENCIES =
-endif
-
 ifndef COMPUTE_HEADER_DEPENDENCIES
 COMPUTE_HEADER_DEPENDENCIES = auto
 endif
@@ -1381,7 +1253,6 @@ ifdef NO_INET_PTON
 endif
 ifndef NO_UNIX_SOCKETS
        LIB_OBJS += unix-socket.o
-       LIB_H += unix-socket.h
        PROGRAM_OBJS += credential-cache.o
        PROGRAM_OBJS += credential-cache--daemon.o
 endif
@@ -1405,12 +1276,10 @@ endif
 ifdef BLK_SHA1
        SHA1_HEADER = "block-sha1/sha1.h"
        LIB_OBJS += block-sha1/sha1.o
-       LIB_H += block-sha1/sha1.h
 else
 ifdef PPC_SHA1
        SHA1_HEADER = "ppc/sha1.h"
        LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o
-       LIB_H += ppc/sha1.h
 else
 ifdef APPLE_COMMON_CRYPTO
        COMPAT_CFLAGS += -DCOMMON_DIGEST_FOR_OPENSSL
@@ -1937,29 +1806,13 @@ $(dep_dirs):
 missing_dep_dirs := $(filter-out $(wildcard $(dep_dirs)),$(dep_dirs))
 dep_file = $(dir $@).depend/$(notdir $@).d
 dep_args = -MF $(dep_file) -MQ $@ -MMD -MP
-ifdef CHECK_HEADER_DEPENDENCIES
-$(error cannot compute header dependencies outside a normal build. \
-Please unset CHECK_HEADER_DEPENDENCIES and try again)
-endif
 endif
 
 ifneq ($(COMPUTE_HEADER_DEPENDENCIES),yes)
-ifndef CHECK_HEADER_DEPENDENCIES
 dep_dirs =
 missing_dep_dirs =
 dep_args =
 endif
-endif
-
-ifdef CHECK_HEADER_DEPENDENCIES
-ifndef PRINT_HEADER_DEPENDENCIES
-missing_deps = $(filter-out $(notdir $^), \
-       $(notdir $(shell $(MAKE) -s $@ \
-               CHECK_HEADER_DEPENDENCIES=YesPlease \
-               USE_COMPUTED_HEADER_DEPENDENCIES=YesPlease \
-               PRINT_HEADER_DEPENDENCIES=YesPlease)))
-endif
-endif
 
 ASM_SRC := $(wildcard $(OBJECTS:o=S))
 ASM_OBJ := $(ASM_SRC:S=o)
@@ -1967,45 +1820,10 @@ C_OBJ := $(filter-out $(ASM_OBJ),$(OBJECTS))
 
 .SUFFIXES:
 
-ifdef PRINT_HEADER_DEPENDENCIES
-$(C_OBJ): %.o: %.c FORCE
-       echo $^
-$(ASM_OBJ): %.o: %.S FORCE
-       echo $^
-
-ifndef CHECK_HEADER_DEPENDENCIES
-$(error cannot print header dependencies during a normal build. \
-Please set CHECK_HEADER_DEPENDENCIES and try again)
-endif
-endif
-
-ifndef PRINT_HEADER_DEPENDENCIES
-ifdef CHECK_HEADER_DEPENDENCIES
-$(C_OBJ): %.o: %.c $(dep_files) FORCE
-       @set -e; echo CHECK $@; \
-       missing_deps="$(missing_deps)"; \
-       if test "$$missing_deps"; \
-       then \
-               echo missing dependencies: $$missing_deps; \
-               false; \
-       fi
-$(ASM_OBJ): %.o: %.S $(dep_files) FORCE
-       @set -e; echo CHECK $@; \
-       missing_deps="$(missing_deps)"; \
-       if test "$$missing_deps"; \
-       then \
-               echo missing dependencies: $$missing_deps; \
-               false; \
-       fi
-endif
-endif
-
-ifndef CHECK_HEADER_DEPENDENCIES
 $(C_OBJ): %.o: %.c GIT-CFLAGS $(missing_dep_dirs)
        $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
 $(ASM_OBJ): %.o: %.S GIT-CFLAGS $(missing_dep_dirs)
        $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
-endif
 
 %.s: %.c GIT-CFLAGS FORCE
        $(QUIET_CC)$(CC) -o $@ -S $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $<
@@ -2132,9 +1950,9 @@ XGETTEXT_FLAGS_C = $(XGETTEXT_FLAGS) --language=C \
 XGETTEXT_FLAGS_SH = $(XGETTEXT_FLAGS) --language=Shell \
        --keyword=gettextln --keyword=eval_gettextln
 XGETTEXT_FLAGS_PERL = $(XGETTEXT_FLAGS) --keyword=__ --language=Perl
-LOCALIZED_C := $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)
-LOCALIZED_SH := $(SCRIPT_SH)
-LOCALIZED_PERL := $(SCRIPT_PERL)
+LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)
+LOCALIZED_SH = $(SCRIPT_SH)
+LOCALIZED_PERL = $(SCRIPT_PERL)
 
 ifdef XGETTEXT_INCLUDE_TESTS
 LOCALIZED_C += t/t0200/test.c
@@ -2142,7 +1960,7 @@ LOCALIZED_SH += t/t0200/test.sh
 LOCALIZED_PERL += t/t0200/test.perl
 endif
 
-po/git.pot: $(LOCALIZED_C)
+po/git.pot: $(GENERATED_H) FORCE
        $(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ $(XGETTEXT_FLAGS_C) $(LOCALIZED_C)
        $(QUIET_XGETTEXT)$(XGETTEXT) -o$@+ --join-existing $(XGETTEXT_FLAGS_SH) \
                $(LOCALIZED_SH)
index bf760914010786c830233effc8b96ddacfb114fd..c473b35ad95f0fc1ff05c19493ded96ca6a48f55 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.1.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.2.0.txt
\ No newline at end of file
index ca33558a91c5259a793fc56b571fa683e16b134f..5edb4e78162ca6646ef42ad2c8abc36872cd75a5 100644 (file)
--- a/abspath.c
+++ b/abspath.c
@@ -33,7 +33,7 @@ int is_directory(const char *path)
  */
 static const char *real_path_internal(const char *path, int die_on_error)
 {
-       static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
+       static struct strbuf sb = STRBUF_INIT;
        char *retval = NULL;
 
        /*
@@ -41,16 +41,14 @@ static const char *real_path_internal(const char *path, int die_on_error)
         * here so that we can chdir() back to it at the end of the
         * function:
         */
-       char cwd[1024] = "";
-
-       int buf_index = 1;
+       struct strbuf cwd = STRBUF_INIT;
 
        int depth = MAXDEPTH;
        char *last_elem = NULL;
        struct stat st;
 
        /* We've already done it */
-       if (path == buf || path == next_buf)
+       if (path == sb.buf)
                return path;
 
        if (!*path) {
@@ -60,41 +58,38 @@ static const char *real_path_internal(const char *path, int die_on_error)
                        goto error_out;
        }
 
-       if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) {
-               if (die_on_error)
-                       die("Too long path: %.*s", 60, path);
-               else
-                       goto error_out;
-       }
+       strbuf_reset(&sb);
+       strbuf_addstr(&sb, path);
 
        while (depth--) {
-               if (!is_directory(buf)) {
-                       char *last_slash = find_last_dir_sep(buf);
+               if (!is_directory(sb.buf)) {
+                       char *last_slash = find_last_dir_sep(sb.buf);
                        if (last_slash) {
                                last_elem = xstrdup(last_slash + 1);
-                               last_slash[1] = '\0';
+                               strbuf_setlen(&sb, last_slash - sb.buf + 1);
                        } else {
-                               last_elem = xstrdup(buf);
-                               *buf = '\0';
+                               last_elem = xmemdupz(sb.buf, sb.len);
+                               strbuf_reset(&sb);
                        }
                }
 
-               if (*buf) {
-                       if (!*cwd && !getcwd(cwd, sizeof(cwd))) {
+               if (sb.len) {
+                       if (!cwd.len && strbuf_getcwd(&cwd)) {
                                if (die_on_error)
                                        die_errno("Could not get current working directory");
                                else
                                        goto error_out;
                        }
 
-                       if (chdir(buf)) {
+                       if (chdir(sb.buf)) {
                                if (die_on_error)
-                                       die_errno("Could not switch to '%s'", buf);
+                                       die_errno("Could not switch to '%s'",
+                                                 sb.buf);
                                else
                                        goto error_out;
                        }
                }
-               if (!getcwd(buf, PATH_MAX)) {
+               if (strbuf_getcwd(&sb)) {
                        if (die_on_error)
                                die_errno("Could not get current working directory");
                        else
@@ -102,48 +97,35 @@ static const char *real_path_internal(const char *path, int die_on_error)
                }
 
                if (last_elem) {
-                       size_t len = strlen(buf);
-                       if (len + strlen(last_elem) + 2 > PATH_MAX) {
-                               if (die_on_error)
-                                       die("Too long path name: '%s/%s'",
-                                           buf, last_elem);
-                               else
-                                       goto error_out;
-                       }
-                       if (len && !is_dir_sep(buf[len - 1]))
-                               buf[len++] = '/';
-                       strcpy(buf + len, last_elem);
+                       if (sb.len && !is_dir_sep(sb.buf[sb.len - 1]))
+                               strbuf_addch(&sb, '/');
+                       strbuf_addstr(&sb, last_elem);
                        free(last_elem);
                        last_elem = NULL;
                }
 
-               if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
-                       ssize_t len = readlink(buf, next_buf, PATH_MAX);
+               if (!lstat(sb.buf, &st) && S_ISLNK(st.st_mode)) {
+                       struct strbuf next_sb = STRBUF_INIT;
+                       ssize_t len = strbuf_readlink(&next_sb, sb.buf, 0);
                        if (len < 0) {
                                if (die_on_error)
-                                       die_errno("Invalid symlink '%s'", buf);
-                               else
-                                       goto error_out;
-                       }
-                       if (PATH_MAX <= len) {
-                               if (die_on_error)
-                                       die("symbolic link too long: %s", buf);
+                                       die_errno("Invalid symlink '%s'",
+                                                 sb.buf);
                                else
                                        goto error_out;
                        }
-                       next_buf[len] = '\0';
-                       buf = next_buf;
-                       buf_index = 1 - buf_index;
-                       next_buf = bufs[buf_index];
+                       strbuf_swap(&sb, &next_sb);
+                       strbuf_release(&next_sb);
                } else
                        break;
        }
 
-       retval = buf;
+       retval = sb.buf;
 error_out:
        free(last_elem);
-       if (*cwd && chdir(cwd))
-               die_errno("Could not change back to '%s'", cwd);
+       if (cwd.len && chdir(cwd.buf))
+               die_errno("Could not change back to '%s'", cwd.buf);
+       strbuf_release(&cwd);
 
        return retval;
 }
@@ -158,54 +140,16 @@ const char *real_path_if_valid(const char *path)
        return real_path_internal(path, 0);
 }
 
-static const char *get_pwd_cwd(void)
-{
-       static char cwd[PATH_MAX + 1];
-       char *pwd;
-       struct stat cwd_stat, pwd_stat;
-       if (getcwd(cwd, PATH_MAX) == NULL)
-               return NULL;
-       pwd = getenv("PWD");
-       if (pwd && strcmp(pwd, cwd)) {
-               stat(cwd, &cwd_stat);
-               if ((cwd_stat.st_dev || cwd_stat.st_ino) &&
-                   !stat(pwd, &pwd_stat) &&
-                   pwd_stat.st_dev == cwd_stat.st_dev &&
-                   pwd_stat.st_ino == cwd_stat.st_ino) {
-                       strlcpy(cwd, pwd, PATH_MAX);
-               }
-       }
-       return cwd;
-}
-
 /*
  * Use this to get an absolute path from a relative one. If you want
  * to resolve links, you should use real_path.
- *
- * If the path is already absolute, then return path. As the user is
- * never meant to free the return value, we're safe.
  */
 const char *absolute_path(const char *path)
 {
-       static char buf[PATH_MAX + 1];
-
-       if (!*path) {
-               die("The empty string is not a valid path");
-       } else if (is_absolute_path(path)) {
-               if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
-                       die("Too long path: %.*s", 60, path);
-       } else {
-               size_t len;
-               const char *fmt;
-               const char *cwd = get_pwd_cwd();
-               if (!cwd)
-                       die_errno("Cannot determine the current working directory");
-               len = strlen(cwd);
-               fmt = (len > 0 && is_dir_sep(cwd[len - 1])) ? "%s%s" : "%s/%s";
-               if (snprintf(buf, PATH_MAX, fmt, cwd, path) >= PATH_MAX)
-                       die("Too long path: %.*s", 60, path);
-       }
-       return buf;
+       static struct strbuf sb = STRBUF_INIT;
+       strbuf_reset(&sb);
+       strbuf_add_absolute_path(&sb, path);
+       return sb.buf;
 }
 
 /*
index 9b420331926c6bf1aa371f973d6a96886f419b06..3b8bf3c6da6afdd5ef4cfcc77131690ccbbf3757 100644 (file)
--- a/advice.c
+++ b/advice.c
@@ -86,8 +86,7 @@ int error_resolve_conflict(const char *me)
                 * other commands doing a merge do.
                 */
                advise(_("Fix them up in the work tree, and then use 'git add/rm <file>'\n"
-                        "as appropriate to mark resolution and make a commit, or use\n"
-                        "'git commit -a'."));
+                        "as appropriate to mark resolution and make a commit."));
        return -1;
 }
 
diff --git a/alias.c b/alias.c
index 758c8671494ad003a6e7e33f8a14b5450311bf54..6aa164a362427ffa5dc8616bcb01aec3f15b462b 100644 (file)
--- a/alias.c
+++ b/alias.c
@@ -1,26 +1,13 @@
 #include "cache.h"
 
-static const char *alias_key;
-static char *alias_val;
-
-static int alias_lookup_cb(const char *k, const char *v, void *cb)
-{
-       const char *name;
-       if (skip_prefix(k, "alias.", &name) && !strcmp(name, alias_key)) {
-               if (!v)
-                       return config_error_nonbool(k);
-               alias_val = xstrdup(v);
-               return 0;
-       }
-       return 0;
-}
-
 char *alias_lookup(const char *alias)
 {
-       alias_key = alias;
-       alias_val = NULL;
-       git_config(alias_lookup_cb, NULL);
-       return alias_val;
+       char *v = NULL;
+       struct strbuf key = STRBUF_INIT;
+       strbuf_addf(&key, "alias.%s", alias);
+       git_config_get_string(key.buf, &v);
+       strbuf_release(&key);
+       return v;
 }
 
 #define SPLIT_CMDLINE_BAD_ENDING 1
index 719b6298e6abf9c9e9e8009ec49dfc76d0d9e49b..df2f4c8a643796ee96a31185f2a49fa7e00ca991 100644 (file)
@@ -192,7 +192,7 @@ static int write_extended_header(struct archiver_args *args,
        unsigned int mode;
        memset(&header, 0, sizeof(header));
        *header.typeflag = TYPEFLAG_EXT_HEADER;
-       mode = 0100666;
+       mode = 0100666 & ~tar_umask;
        sprintf(header.name, "%s.paxheader", sha1_to_hex(sha1));
        prepare_header(args, &header, mode, size);
        write_blocked(&header, sizeof(header));
@@ -300,7 +300,7 @@ static int write_global_extended_header(struct archiver_args *args)
        strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40);
        memset(&header, 0, sizeof(header));
        *header.typeflag = TYPEFLAG_GLOBAL_HEADER;
-       mode = 0100666;
+       mode = 0100666 & ~tar_umask;
        strcpy(header.name, "pax_global_header");
        prepare_header(args, &header, mode, ext_header.len);
        write_blocked(&header, sizeof(header));
@@ -395,7 +395,7 @@ static int write_tar_filter_archive(const struct archiver *ar,
                                    struct archiver_args *args)
 {
        struct strbuf cmd = STRBUF_INIT;
-       struct child_process filter;
+       struct child_process filter = CHILD_PROCESS_INIT;
        const char *argv[2];
        int r;
 
@@ -406,7 +406,6 @@ static int write_tar_filter_archive(const struct archiver *ar,
        if (args->compression_level >= 0)
                strbuf_addf(&cmd, " -%d", args->compression_level);
 
-       memset(&filter, 0, sizeof(filter));
        argv[0] = cmd.buf;
        argv[1] = NULL;
        filter.argv = argv;
index 3fc0fb2928f1007ec5d8763d9d3a9b88152059ad..952a659bcb59ea8b476d6677f2a04d717c6c7dd2 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -402,14 +402,6 @@ static int parse_archive_args(int argc, const char **argv,
        return argc;
 }
 
-static int git_default_archive_config(const char *var, const char *value,
-                                     void *cb)
-{
-       if (!strcmp(var, "uploadarchive.allowunreachable"))
-               remote_allow_unreachable = git_config_bool(var, value);
-       return git_default_config(var, value, cb);
-}
-
 int write_archive(int argc, const char **argv, const char *prefix,
                  int setup_prefix, const char *name_hint, int remote)
 {
@@ -420,7 +412,9 @@ int write_archive(int argc, const char **argv, const char *prefix,
        if (setup_prefix && prefix == NULL)
                prefix = setup_git_directory_gently(&nongit);
 
-       git_config(git_default_archive_config, NULL);
+       git_config_get_bool("uploadarchive.allowunreachable", &remote_allow_unreachable);
+       git_config(git_default_config, NULL);
+
        init_tar_archiver();
        init_zip_archiver();
 
index d6e851d783c3541eb21edd47170ce7a32e082e61..df09cbc8cabe9dcb87a0023445babcf14c3d7691 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -215,11 +215,12 @@ static struct commit_list *best_bisection_sorted(struct commit_list *list, int n
        }
        qsort(array, cnt, sizeof(*array), compare_commit_dist);
        for (p = list, i = 0; i < cnt; i++) {
-               struct name_decoration *r = xmalloc(sizeof(*r) + 100);
+               char buf[100]; /* enough for dist=%d */
                struct object *obj = &(array[i].commit->object);
 
-               sprintf(r->name, "dist=%d", array[i].distance);
-               r->next = add_decoration(&name_decoration, obj, r);
+               snprintf(buf, sizeof(buf), "dist=%d", array[i].distance);
+               add_name_decoration(DECORATION_NONE, buf, obj);
+
                p->item = array[i].commit;
                p = p->next;
        }
index 46e8aa86df1811ff19899869a33ecb48cacb107f..9a2228ebb46df721741db2249ab25cce5dfb4282 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -140,33 +140,17 @@ static int setup_tracking(const char *new_ref, const char *orig_ref,
        return 0;
 }
 
-struct branch_desc_cb {
-       const char *config_name;
-       const char *value;
-};
-
-static int read_branch_desc_cb(const char *var, const char *value, void *cb)
-{
-       struct branch_desc_cb *desc = cb;
-       if (strcmp(desc->config_name, var))
-               return 0;
-       free((char *)desc->value);
-       return git_config_string(&desc->value, var, value);
-}
-
 int read_branch_desc(struct strbuf *buf, const char *branch_name)
 {
-       struct branch_desc_cb cb;
+       char *v = NULL;
        struct strbuf name = STRBUF_INIT;
        strbuf_addf(&name, "branch.%s.description", branch_name);
-       cb.config_name = name.buf;
-       cb.value = NULL;
-       if (git_config(read_branch_desc_cb, &cb) < 0) {
+       if (git_config_get_string(name.buf, &v)) {
                strbuf_release(&name);
                return -1;
        }
-       if (cb.value)
-               strbuf_addstr(buf, cb.value);
+       strbuf_addstr(buf, v);
+       free(v);
        strbuf_release(&name);
        return 0;
 }
@@ -226,7 +210,6 @@ void create_branch(const char *head,
                   int force, int reflog, int clobber_head,
                   int quiet, enum branch_track track)
 {
-       struct ref_lock *lock = NULL;
        struct commit *commit;
        unsigned char sha1[20];
        char *real_ref, msg[PATH_MAX + 20];
@@ -285,15 +268,6 @@ void create_branch(const char *head,
                die(_("Not a valid branch point: '%s'."), start_name);
        hashcpy(sha1, commit->object.sha1);
 
-       if (!dont_change_ref) {
-               lock = lock_any_ref_for_update(ref.buf, NULL, 0, NULL);
-               if (!lock)
-                       die_errno(_("Failed to lock ref for update"));
-       }
-
-       if (reflog)
-               log_all_ref_updates = 1;
-
        if (forcing)
                snprintf(msg, sizeof msg, "branch: Reset to %s",
                         start_name);
@@ -301,13 +275,26 @@ void create_branch(const char *head,
                snprintf(msg, sizeof msg, "branch: Created from %s",
                         start_name);
 
+       if (reflog)
+               log_all_ref_updates = 1;
+
+       if (!dont_change_ref) {
+               struct ref_transaction *transaction;
+               struct strbuf err = STRBUF_INIT;
+
+               transaction = ref_transaction_begin(&err);
+               if (!transaction ||
+                   ref_transaction_update(transaction, ref.buf, sha1,
+                                          null_sha1, 0, !forcing, &err) ||
+                   ref_transaction_commit(transaction, msg, &err))
+                       die("%s", err.buf);
+               ref_transaction_free(transaction);
+               strbuf_release(&err);
+       }
+
        if (real_ref && track)
                setup_tracking(ref.buf + 11, real_ref, track, quiet);
 
-       if (!dont_change_ref)
-               if (write_ref_sha1(lock, sha1, msg) < 0)
-                       die_errno(_("Failed to write ref"));
-
        strbuf_release(&ref);
        free(real_ref);
 }
index 4baf3a563510b10e592ff06ae62df2f405413f6c..352b85e8db19e1b4fa05ca37804f0c625e582912 100644 (file)
@@ -180,7 +180,7 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
        char *file = git_pathdup("ADD_EDIT.patch");
        const char *apply_argv[] = { "apply", "--recount", "--cached",
                NULL, NULL };
-       struct child_process child;
+       struct child_process child = CHILD_PROCESS_INIT;
        struct rev_info rev;
        int out;
        struct stat st;
@@ -214,7 +214,6 @@ static int edit_patch(int argc, const char **argv, const char *prefix)
        if (!st.st_size)
                die(_("Empty patch. Aborted."));
 
-       memset(&child, 0, sizeof(child));
        child.git_cmd = 1;
        child.argv = apply_argv;
        if (run_command(&child))
index be2b4ce2fd91640379b0a65d0aa90238d7edfd64..f204cca5d2df50d8ecb01944927fb756ac387b5e 100644 (file)
@@ -1920,6 +1920,66 @@ static int parse_binary(char *buffer, unsigned long size, struct patch *patch)
        return used;
 }
 
+static void prefix_one(char **name)
+{
+       char *old_name = *name;
+       if (!old_name)
+               return;
+       *name = xstrdup(prefix_filename(prefix, prefix_length, *name));
+       free(old_name);
+}
+
+static void prefix_patch(struct patch *p)
+{
+       if (!prefix || p->is_toplevel_relative)
+               return;
+       prefix_one(&p->new_name);
+       prefix_one(&p->old_name);
+}
+
+/*
+ * include/exclude
+ */
+
+static struct string_list limit_by_name;
+static int has_include;
+static void add_name_limit(const char *name, int exclude)
+{
+       struct string_list_item *it;
+
+       it = string_list_append(&limit_by_name, name);
+       it->util = exclude ? NULL : (void *) 1;
+}
+
+static int use_patch(struct patch *p)
+{
+       const char *pathname = p->new_name ? p->new_name : p->old_name;
+       int i;
+
+       /* Paths outside are not touched regardless of "--include" */
+       if (0 < prefix_length) {
+               int pathlen = strlen(pathname);
+               if (pathlen <= prefix_length ||
+                   memcmp(prefix, pathname, prefix_length))
+                       return 0;
+       }
+
+       /* See if it matches any of exclude/include rule */
+       for (i = 0; i < limit_by_name.nr; i++) {
+               struct string_list_item *it = &limit_by_name.items[i];
+               if (!wildmatch(it->string, pathname, 0, NULL))
+                       return (it->util != NULL);
+       }
+
+       /*
+        * If we had any include, a path that does not match any rule is
+        * not used.  Otherwise, we saw bunch of exclude rules (or none)
+        * and such a path is used.
+        */
+       return !has_include;
+}
+
+
 /*
  * Read the patch text in "buffer" that extends for "size" bytes; stop
  * reading after seeing a single patch (i.e. changes to a single file).
@@ -1935,9 +1995,14 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
        if (offset < 0)
                return offset;
 
-       patch->ws_rule = whitespace_rule(patch->new_name
-                                        ? patch->new_name
-                                        : patch->old_name);
+       prefix_patch(patch);
+
+       if (!use_patch(patch))
+               patch->ws_rule = 0;
+       else
+               patch->ws_rule = whitespace_rule(patch->new_name
+                                                ? patch->new_name
+                                                : patch->old_name);
 
        patchsize = parse_single_patch(buffer + offset + hdrsize,
                                       size - offset - hdrsize, patch);
@@ -4127,64 +4192,6 @@ static int write_out_results(struct patch *list)
 
 static struct lock_file lock_file;
 
-static struct string_list limit_by_name;
-static int has_include;
-static void add_name_limit(const char *name, int exclude)
-{
-       struct string_list_item *it;
-
-       it = string_list_append(&limit_by_name, name);
-       it->util = exclude ? NULL : (void *) 1;
-}
-
-static int use_patch(struct patch *p)
-{
-       const char *pathname = p->new_name ? p->new_name : p->old_name;
-       int i;
-
-       /* Paths outside are not touched regardless of "--include" */
-       if (0 < prefix_length) {
-               int pathlen = strlen(pathname);
-               if (pathlen <= prefix_length ||
-                   memcmp(prefix, pathname, prefix_length))
-                       return 0;
-       }
-
-       /* See if it matches any of exclude/include rule */
-       for (i = 0; i < limit_by_name.nr; i++) {
-               struct string_list_item *it = &limit_by_name.items[i];
-               if (!wildmatch(it->string, pathname, 0, NULL))
-                       return (it->util != NULL);
-       }
-
-       /*
-        * If we had any include, a path that does not match any rule is
-        * not used.  Otherwise, we saw bunch of exclude rules (or none)
-        * and such a path is used.
-        */
-       return !has_include;
-}
-
-
-static void prefix_one(char **name)
-{
-       char *old_name = *name;
-       if (!old_name)
-               return;
-       *name = xstrdup(prefix_filename(prefix, prefix_length, *name));
-       free(old_name);
-}
-
-static void prefix_patches(struct patch *p)
-{
-       if (!prefix || p->is_toplevel_relative)
-               return;
-       for ( ; p; p = p->next) {
-               prefix_one(&p->new_name);
-               prefix_one(&p->old_name);
-       }
-}
-
 #define INACCURATE_EOF (1<<0)
 #define RECOUNT                (1<<1)
 
@@ -4210,8 +4217,6 @@ static int apply_patch(int fd, const char *filename, int options)
                        break;
                if (apply_in_reverse)
                        reverse_patches(patch);
-               if (prefix)
-                       prefix_patches(patch);
                if (use_patch(patch)) {
                        patch_stats(patch);
                        *listp = patch;
@@ -4269,13 +4274,11 @@ static int apply_patch(int fd, const char *filename, int options)
        return 0;
 }
 
-static int git_apply_config(const char *var, const char *value, void *cb)
+static void git_apply_config(void)
 {
-       if (!strcmp(var, "apply.whitespace"))
-               return git_config_string(&apply_default_whitespace, var, value);
-       else if (!strcmp(var, "apply.ignorewhitespace"))
-               return git_config_string(&apply_default_ignorewhitespace, var, value);
-       return git_default_config(var, value, cb);
+       git_config_get_string_const("apply.whitespace", &apply_default_whitespace);
+       git_config_get_string_const("apply.ignorewhitespace", &apply_default_ignorewhitespace);
+       git_config(git_default_config, NULL);
 }
 
 static int option_parse_exclude(const struct option *opt,
@@ -4423,7 +4426,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
 
        prefix = prefix_;
        prefix_length = prefix ? strlen(prefix) : 0;
-       git_config(git_apply_config, NULL);
+       git_apply_config();
        if (apply_default_whitespace)
                parse_whitespace_option(apply_default_whitespace);
        if (apply_default_ignorewhitespace)
index 17d30d00aa3f6c4d0f62cae6603f9003dd2f2395..ca4ba6ff15b91d9cbb6b2ce3783fa3e69d0f3ff1 100644 (file)
@@ -2700,7 +2700,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
         * uninteresting.
         */
        if (prepare_revision_walk(&revs))
-               die("revision walk setup failed");
+               die(_("revision walk setup failed"));
 
        if (is_null_sha1(sb.final->object.sha1)) {
                o = sb.final->util;
index 0591b22a483619ac9a7d889a49e45ffa9d68ab72..ced422b627fc05c462f6be8b6c20ee0ba9ff2628 100644 (file)
@@ -653,7 +653,9 @@ static int print_ref_list(int kinds, int detached, int verbose, int abbrev, stru
                add_pending_object(&ref_list.revs,
                                   (struct object *) filter, "");
                ref_list.revs.limited = 1;
-               prepare_revision_walk(&ref_list.revs);
+
+               if (prepare_revision_walk(&ref_list.revs))
+                       die(_("revision walk setup failed"));
                if (verbose)
                        ref_list.maxwidth = calc_maxwidth(&ref_list);
        }
index f71e74531d2a7d195ff2987f6dca3c69c636aa7c..8afdf2b5c4bfbd53e7315afe9d8ae3d88f93dd57 100644 (file)
@@ -552,6 +552,12 @@ static int merge_working_tree(const struct checkout_opts *opts,
                }
        }
 
+       if (!active_cache_tree)
+               active_cache_tree = cache_tree();
+
+       if (!cache_tree_fully_valid(active_cache_tree))
+               cache_tree_update(&the_index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
+
        if (write_locked_index(&the_index, lock_file, COMMIT_LOCK))
                die(_("unable to write new index file"));
 
index 1032563e5fae880df9256c9eafaa96d60462ecd2..3beeea6ec0fdc3883f2456caf46f3e1c4dadc682 100644 (file)
@@ -67,7 +67,7 @@ struct menu_item {
        char hotkey;
        const char *title;
        int selected;
-       int (*fn)();
+       int (*fn)(void);
 };
 
 enum menu_stuff_type {
index bbd169ceb49b2e09197e469aeb572e9aa54d4b85..dd4092b0509eb9f284118c001d8451a633f9ef7c 100644 (file)
@@ -1004,5 +1004,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        strbuf_release(&key);
        strbuf_release(&value);
        junk_mode = JUNK_LEAVE_ALL;
+
+       free(refspec);
        return err;
 }
index 5ed60364ce5eb1f458e1f5155d76abd7341d24ea..41f481bd030ba96f8883e64517eda95931344545 100644 (file)
@@ -42,7 +42,20 @@ static const char * const builtin_status_usage[] = {
        NULL
 };
 
-static const char implicit_ident_advice[] =
+static const char implicit_ident_advice_noconfig[] =
+N_("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. Run the\n"
+"following command and follow the instructions in your editor to edit\n"
+"your configuration file:\n"
+"\n"
+"    git config --global --edit\n"
+"\n"
+"After doing this, you may fix the identity used for this commit with:\n"
+"\n"
+"    git commit --amend --reset-author\n");
+
+static const char implicit_ident_advice_config[] =
 N_("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"
@@ -340,6 +353,13 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
 
                discard_cache();
                read_cache_from(index_lock.filename);
+               if (update_main_cache_tree(WRITE_TREE_SILENT) == 0) {
+                       if (reopen_lock_file(&index_lock) < 0)
+                               die(_("unable to write index file"));
+                       if (write_locked_index(&the_index, &index_lock, CLOSE_LOCK))
+                               die(_("unable to update temporary index"));
+               } else
+                       warning(_("Failed to update main cache tree"));
 
                commit_style = COMMIT_NORMAL;
                return index_lock.filename;
@@ -380,8 +400,12 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
        if (!only && !pathspec.nr) {
                hold_locked_index(&index_lock, 1);
                refresh_cache_or_die(refresh_flags);
-               if (active_cache_changed) {
+               if (active_cache_changed
+                   || !cache_tree_fully_valid(active_cache_tree)) {
                        update_main_cache_tree(WRITE_TREE_SILENT);
+                       active_cache_changed = 1;
+               }
+               if (active_cache_changed) {
                        if (write_locked_index(&the_index, &index_lock,
                                               COMMIT_LOCK))
                                die(_("unable to write new_index file"));
@@ -431,6 +455,7 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
        hold_locked_index(&index_lock, 1);
        add_remove_files(&partial);
        refresh_cache(REFRESH_QUIET);
+       update_main_cache_tree(WRITE_TREE_SILENT);
        if (write_locked_index(&the_index, &index_lock, CLOSE_LOCK))
                die(_("unable to write new_index file"));
 
@@ -1048,7 +1073,8 @@ static const char *find_author_by_nickname(const char *name)
        revs.mailmap = &mailmap;
        read_mailmap(revs.mailmap, NULL);
 
-       prepare_revision_walk(&revs);
+       if (prepare_revision_walk(&revs))
+               die(_("revision walk setup failed"));
        commit = get_revision(&revs);
        if (commit) {
                struct pretty_print_context ctx = {0};
@@ -1402,6 +1428,24 @@ int cmd_status(int argc, const char **argv, const char *prefix)
        return 0;
 }
 
+static const char *implicit_ident_advice(void)
+{
+       char *user_config = NULL;
+       char *xdg_config = NULL;
+       int config_exists;
+
+       home_config_paths(&user_config, &xdg_config, "config");
+       config_exists = file_exists(user_config) || file_exists(xdg_config);
+       free(user_config);
+       free(xdg_config);
+
+       if (config_exists)
+               return _(implicit_ident_advice_config);
+       else
+               return _(implicit_ident_advice_noconfig);
+
+}
+
 static void print_summary(const char *prefix, const unsigned char *sha1,
                          int initial_commit)
 {
@@ -1440,7 +1484,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1,
                strbuf_addbuf_percentquote(&format, &committer_ident);
                if (advice_implicit_identity) {
                        strbuf_addch(&format, '\n');
-                       strbuf_addstr(&format, _(implicit_ident_advice));
+                       strbuf_addstr(&format, implicit_ident_advice());
                }
        }
        strbuf_release(&author_ident);
@@ -1508,7 +1552,7 @@ static int run_rewrite_hook(const unsigned char *oldsha1,
 {
        /* oldsha1 SP newsha1 LF NUL */
        static char buf[2*40 + 3];
-       struct child_process proc;
+       struct child_process proc = CHILD_PROCESS_INIT;
        const char *argv[3];
        int code;
        size_t n;
@@ -1520,7 +1564,6 @@ static int run_rewrite_hook(const unsigned char *oldsha1,
        argv[1] = "amend";
        argv[2] = NULL;
 
-       memset(&proc, 0, sizeof(proc));
        proc.argv = argv;
        proc.in = -1;
        proc.stdout_to_stderr = 1;
@@ -1620,11 +1663,12 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
        const char *index_file, *reflog_msg;
        char *nl;
        unsigned char sha1[20];
-       struct ref_lock *ref_lock;
        struct commit_list *parents = NULL, **pptr = &parents;
        struct stat statbuf;
        struct commit *current_head = NULL;
        struct commit_extra_header *extra = NULL;
+       struct ref_transaction *transaction;
+       struct strbuf err = STRBUF_INIT;
 
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage_with_options(builtin_commit_usage, builtin_commit_options);
@@ -1746,16 +1790,6 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
        strbuf_release(&author_ident);
        free_commit_extra_headers(extra);
 
-       ref_lock = lock_any_ref_for_update("HEAD",
-                                          !current_head
-                                          ? NULL
-                                          : current_head->object.sha1,
-                                          0, NULL);
-       if (!ref_lock) {
-               rollback_index_files();
-               die(_("cannot lock HEAD ref"));
-       }
-
        nl = strchr(sb.buf, '\n');
        if (nl)
                strbuf_setlen(&sb, nl + 1 - sb.buf);
@@ -1764,10 +1798,17 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
        strbuf_insert(&sb, 0, reflog_msg, strlen(reflog_msg));
        strbuf_insert(&sb, strlen(reflog_msg), ": ", 2);
 
-       if (write_ref_sha1(ref_lock, sha1, sb.buf) < 0) {
+       transaction = ref_transaction_begin(&err);
+       if (!transaction ||
+           ref_transaction_update(transaction, "HEAD", sha1,
+                                  current_head
+                                  ? current_head->object.sha1 : NULL,
+                                  0, !!current_head, &err) ||
+           ref_transaction_commit(transaction, sb.buf, &err)) {
                rollback_index_files();
-               die(_("cannot update HEAD ref"));
+               die("%s", err.buf);
        }
+       ref_transaction_free(transaction);
 
        unlink(git_path("CHERRY_PICK_HEAD"));
        unlink(git_path("REVERT_HEAD"));
@@ -1796,5 +1837,6 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
        if (!quiet)
                print_summary(prefix, sha1, !current_head);
 
+       strbuf_release(&err);
        return 0;
 }
index fcd84747015a3d0a1da048612f5ac119a7e161d1..aba71355f864202932e02bddb804d2fa3c0783d8 100644 (file)
@@ -445,6 +445,20 @@ static int get_urlmatch(const char *var, const char *url)
        return 0;
 }
 
+static char *default_user_config(void)
+{
+       struct strbuf buf = STRBUF_INIT;
+       strbuf_addf(&buf,
+                   _("# This is Git's per-user configuration file.\n"
+                     "[core]\n"
+                     "# Please adapt and uncomment the following lines:\n"
+                     "#        user = %s\n"
+                     "#        email = %s\n"),
+                   ident_default_name(),
+                   ident_default_email());
+       return strbuf_detach(&buf, NULL);
+}
+
 int cmd_config(int argc, const char **argv, const char *prefix)
 {
        int nongit = !startup_info->have_repository;
@@ -551,6 +565,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                }
        }
        else if (actions == ACTION_EDIT) {
+               const char *config_file = given_config_source.file ?
+                       given_config_source.file : git_path("config");
                check_argc(argc, 0, 0);
                if (!given_config_source.file && nongit)
                        die("not in a git directory");
@@ -559,9 +575,18 @@ int cmd_config(int argc, const char **argv, const char *prefix)
                if (given_config_source.blob)
                        die("editing blobs is not supported");
                git_config(git_default_config, NULL);
-               launch_editor(given_config_source.file ?
-                             given_config_source.file : git_path("config"),
-                             NULL, NULL);
+               if (use_global_config) {
+                       int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
+                       if (fd) {
+                               char *content = default_user_config();
+                               write_str_in_full(fd, content);
+                               free(content);
+                               close(fd);
+                       }
+                       else if (errno != EEXIST)
+                               die_errno(_("cannot create configuration file %s"), config_file);
+               }
+               launch_editor(config_file, NULL, NULL);
        }
        else if (actions == ACTION_SET) {
                int ret;
index e8d0cca3e4110e1ae6db82f21c899c44460cb849..159fb7e91614253cf7820b0c4cd7d07407c76762 100644 (file)
@@ -1110,9 +1110,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        struct string_list list = STRING_LIST_INIT_NODUP;
        struct remote *remote;
        int result = 0;
-       static const char *argv_gc_auto[] = {
-               "gc", "--auto", NULL,
-       };
+       struct argv_array argv_gc_auto = ARGV_ARRAY_INIT;
 
        packet_trace_identity("fetch");
 
@@ -1198,7 +1196,11 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        list.strdup_strings = 1;
        string_list_clear(&list, 0);
 
-       run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
+       argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL);
+       if (verbosity < 0)
+               argv_array_push(&argv_gc_auto, "--quiet");
+       run_command_v_opt(argv_gc_auto.argv, RUN_GIT_CMD);
+       argv_array_clear(&argv_gc_auto);
 
        return result;
 }
index 8d219d8c42cb4dfb64468f9b4d82648bff646685..ced1456e1e3b71af05e382fcd505cc269391bb88 100644 (file)
@@ -55,44 +55,33 @@ static void remove_pidfile_on_signal(int signo)
        raise(signo);
 }
 
-static int gc_config(const char *var, const char *value, void *cb)
+static void gc_config(void)
 {
-       if (!strcmp(var, "gc.packrefs")) {
+       const char *value;
+
+       if (!git_config_get_value("gc.packrefs", &value)) {
                if (value && !strcmp(value, "notbare"))
                        pack_refs = -1;
                else
-                       pack_refs = git_config_bool(var, value);
-               return 0;
-       }
-       if (!strcmp(var, "gc.aggressivewindow")) {
-               aggressive_window = git_config_int(var, value);
-               return 0;
-       }
-       if (!strcmp(var, "gc.aggressivedepth")) {
-               aggressive_depth = git_config_int(var, value);
-               return 0;
-       }
-       if (!strcmp(var, "gc.auto")) {
-               gc_auto_threshold = git_config_int(var, value);
-               return 0;
-       }
-       if (!strcmp(var, "gc.autopacklimit")) {
-               gc_auto_pack_limit = git_config_int(var, value);
-               return 0;
+                       pack_refs = git_config_bool("gc.packrefs", value);
        }
-       if (!strcmp(var, "gc.autodetach")) {
-               detach_auto = git_config_bool(var, value);
-               return 0;
-       }
-       if (!strcmp(var, "gc.pruneexpire")) {
-               if (value && strcmp(value, "now")) {
+
+       git_config_get_int("gc.aggressivewindow", &aggressive_window);
+       git_config_get_int("gc.aggressivedepth", &aggressive_depth);
+       git_config_get_int("gc.auto", &gc_auto_threshold);
+       git_config_get_int("gc.autopacklimit", &gc_auto_pack_limit);
+       git_config_get_bool("gc.autodetach", &detach_auto);
+
+       if (!git_config_get_string_const("gc.pruneexpire", &prune_expire)) {
+               if (strcmp(prune_expire, "now")) {
                        unsigned long now = approxidate("now");
-                       if (approxidate(value) >= now)
-                               return error(_("Invalid %s: '%s'"), var, value);
+                       if (approxidate(prune_expire) >= now) {
+                               git_die_config("gc.pruneexpire", _("Invalid gc.pruneexpire: '%s'"),
+                                               prune_expire);
+                       }
                }
-               return git_config_string(&prune_expire, var, value);
        }
-       return git_default_config(var, value, cb);
+       git_config(git_default_config, NULL);
 }
 
 static int too_many_loose_objects(void)
@@ -301,7 +290,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
        argv_array_pushl(&prune, "prune", "--expire", NULL );
        argv_array_pushl(&rerere, "rerere", "gc", NULL);
 
-       git_config(gc_config, NULL);
+       gc_config();
 
        if (pack_refs < 0)
                pack_refs = !is_bare_repository();
index 1fdefeb6867cdd37beaf41c5fa9e113576b19f17..8343b4027d458d77a720f79d64c9a4c116208f84 100644 (file)
@@ -79,12 +79,11 @@ static const char *get_man_viewer_info(const char *name)
 static int check_emacsclient_version(void)
 {
        struct strbuf buffer = STRBUF_INIT;
-       struct child_process ec_process;
+       struct child_process ec_process = CHILD_PROCESS_INIT;
        const char *argv_ec[] = { "emacsclient", "--version", NULL };
        int version;
 
        /* emacsclient prints its version number on stderr */
-       memset(&ec_process, 0, sizeof(ec_process));
        ec_process.argv = argv_ec;
        ec_process.err = -1;
        ec_process.stdout_to_stderr = 1;
index 56f85e239ae0d2607c38e3c46013007ba9e71b12..587a5055ed677c3541c85101d944ffb0a19b1962 100644 (file)
@@ -330,12 +330,12 @@ int set_git_dir_init(const char *git_dir, const char *real_git_dir,
                 * moving the target repo later on in separate_git_dir()
                 */
                git_link = xstrdup(real_path(git_dir));
+               set_git_dir(real_path(real_git_dir));
        }
        else {
-               real_git_dir = real_path(git_dir);
+               set_git_dir(real_path(git_dir));
                git_link = NULL;
        }
-       set_git_dir(real_path(real_git_dir));
        return 0;
 }
 
@@ -426,8 +426,9 @@ int init_db(const char *template_dir, unsigned int flags)
 
 static int guess_repository_type(const char *git_dir)
 {
-       char cwd[PATH_MAX];
        const char *slash;
+       char *cwd;
+       int cwd_is_git_dir;
 
        /*
         * "GIT_DIR=. git init" is always bare.
@@ -435,9 +436,10 @@ static int guess_repository_type(const char *git_dir)
         */
        if (!strcmp(".", git_dir))
                return 1;
-       if (!getcwd(cwd, sizeof(cwd)))
-               die_errno(_("cannot tell cwd"));
-       if (!strcmp(git_dir, cwd))
+       cwd = xgetcwd();
+       cwd_is_git_dir = !strcmp(git_dir, cwd);
+       free(cwd);
+       if (cwd_is_git_dir)
                return 1;
        /*
         * "GIT_DIR=.git or GIT_DIR=something/.git is usually not.
@@ -535,10 +537,9 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
                usage(init_db_usage[0]);
        }
        if (is_bare_repository_cfg == 1) {
-               static char git_dir[PATH_MAX+1];
-
-               setenv(GIT_DIR_ENVIRONMENT,
-                       getcwd(git_dir, sizeof(git_dir)), argc > 0);
+               char *cwd = xgetcwd();
+               setenv(GIT_DIR_ENVIRONMENT, cwd, argc > 0);
+               free(cwd);
        }
 
        if (init_shared_repository != -1)
@@ -572,13 +573,10 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
                        git_work_tree_cfg = xstrdup(real_path(rel));
                        free(rel);
                }
-               if (!git_work_tree_cfg) {
-                       git_work_tree_cfg = xcalloc(PATH_MAX, 1);
-                       if (!getcwd(git_work_tree_cfg, PATH_MAX))
-                               die_errno (_("Cannot access current working directory"));
-               }
+               if (!git_work_tree_cfg)
+                       git_work_tree_cfg = xgetcwd();
                if (work_tree)
-                       set_git_work_tree(real_path(work_tree));
+                       set_git_work_tree(work_tree);
                else
                        set_git_work_tree(git_work_tree_cfg);
                if (access(get_git_work_tree(), X_OK))
@@ -587,7 +585,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
        }
        else {
                if (work_tree)
-                       set_git_work_tree(real_path(work_tree));
+                       set_git_work_tree(work_tree);
        }
 
        set_git_dir_init(git_dir, real_git_dir, 1);
index 4389722b4b1edffce8cd2a63dae52277e022ac99..e4d812208d8844b9155739acfd59ef840f24a4ae 100644 (file)
@@ -864,6 +864,7 @@ static void add_branch_description(struct strbuf *buf, const char *branch_name)
                strbuf_addbuf(buf, &desc);
                strbuf_addch(buf, '\n');
        }
+       strbuf_release(&desc);
 }
 
 static char *find_branch_name(struct rev_info *rev)
index 06296d4bdf607431bfcb38f0bc6720f555d6917a..763cda098cf1e2ac2ccbae45d3602f8bb1093be0 100644 (file)
@@ -53,14 +53,16 @@ static int keep_cr;
  */
 static int split_one(FILE *mbox, const char *name, int allow_bare)
 {
-       FILE *output = NULL;
+       FILE *output;
        int fd;
        int status = 0;
        int is_bare = !is_from_line(buf.buf, buf.len);
 
-       if (is_bare && !allow_bare)
-               goto corrupt;
-
+       if (is_bare && !allow_bare) {
+               unlink(name);
+               fprintf(stderr, "corrupt mailbox\n");
+               exit(1);
+       }
        fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666);
        if (fd < 0)
                die_errno("cannot open output file '%s'", name);
@@ -91,13 +93,6 @@ static int split_one(FILE *mbox, const char *name, int allow_bare)
        }
        fclose(output);
        return status;
-
- corrupt:
-       if (output)
-               fclose(output);
-       unlink(name);
-       fprintf(stderr, "corrupt mailbox\n");
-       exit(1);
 }
 
 static int populate_maildir_list(struct string_list *list, const char *path)
index ce82eb297db3d03394f4e73a9b07574661db7090..9da9e30d9be46a5ed2de06e8545fe61537ba3676 100644 (file)
@@ -237,11 +237,10 @@ static void drop_save(void)
 static int save_state(unsigned char *stash)
 {
        int len;
-       struct child_process cp;
+       struct child_process cp = CHILD_PROCESS_INIT;
        struct strbuf buffer = STRBUF_INIT;
        const char *argv[] = {"stash", "create", NULL};
 
-       memset(&cp, 0, sizeof(cp));
        cp.argv = argv;
        cp.out = -1;
        cp.git_cmd = 1;
index 6ffe540c202f69a41fcf40d443f73073d3ba08bd..bf784cb94361f8db5ea17906d0199284a04be99a 100644 (file)
@@ -61,6 +61,46 @@ static const char *add_slash(const char *path)
 static struct lock_file lock_file;
 #define SUBMODULE_WITH_GITDIR ((const char *)1)
 
+static void prepare_move_submodule(const char *src, int first,
+                                  const char **submodule_gitfile)
+{
+       struct strbuf submodule_dotgit = STRBUF_INIT;
+       if (!S_ISGITLINK(active_cache[first]->ce_mode))
+               die(_("Directory %s is in index and no submodule?"), src);
+       if (!is_staging_gitmodules_ok())
+               die(_("Please stage your changes to .gitmodules or stash them to proceed"));
+       strbuf_addf(&submodule_dotgit, "%s/.git", src);
+       *submodule_gitfile = read_gitfile(submodule_dotgit.buf);
+       if (*submodule_gitfile)
+               *submodule_gitfile = xstrdup(*submodule_gitfile);
+       else
+               *submodule_gitfile = SUBMODULE_WITH_GITDIR;
+       strbuf_release(&submodule_dotgit);
+}
+
+static int index_range_of_same_dir(const char *src, int length,
+                                  int *first_p, int *last_p)
+{
+       const char *src_w_slash = add_slash(src);
+       int first, last, len_w_slash = length + 1;
+
+       first = cache_name_pos(src_w_slash, len_w_slash);
+       if (first >= 0)
+               die(_("%.*s is in index"), len_w_slash, src_w_slash);
+
+       first = -1 - first;
+       for (last = first; last < active_nr; last++) {
+               const char *path = active_cache[last]->name;
+               if (strncmp(path, src_w_slash, len_w_slash))
+                       break;
+       }
+       if (src_w_slash != src)
+               free((char *)src_w_slash);
+       *first_p = first;
+       *last_p = last;
+       return last - first;
+}
+
 int cmd_mv(int argc, const char **argv, const char *prefix)
 {
        int i, gitmodules_modified = 0;
@@ -108,7 +148,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                destination = internal_copy_pathspec(dest_path[0], argv, argc, DUP_BASENAME);
        } else {
                if (argc != 1)
-                       die("destination '%s' is not a directory", dest_path[0]);
+                       die(_("destination '%s' is not a directory"), dest_path[0]);
                destination = dest_path;
        }
 
@@ -131,75 +171,36 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                                && lstat(dst, &st) == 0)
                        bad = _("cannot move directory over file");
                else if (src_is_dir) {
-                       int first = cache_name_pos(src, length);
-                       if (first >= 0) {
-                               struct strbuf submodule_dotgit = STRBUF_INIT;
-                               if (!S_ISGITLINK(active_cache[first]->ce_mode))
-                                       die (_("Huh? Directory %s is in index and no submodule?"), src);
-                               if (!is_staging_gitmodules_ok())
-                                       die (_("Please, stage your changes to .gitmodules or stash them to proceed"));
-                               strbuf_addf(&submodule_dotgit, "%s/.git", src);
-                               submodule_gitfile[i] = read_gitfile(submodule_dotgit.buf);
-                               if (submodule_gitfile[i])
-                                       submodule_gitfile[i] = xstrdup(submodule_gitfile[i]);
-                               else
-                                       submodule_gitfile[i] = SUBMODULE_WITH_GITDIR;
-                               strbuf_release(&submodule_dotgit);
-                       } else {
-                               const char *src_w_slash = add_slash(src);
-                               int last, len_w_slash = length + 1;
+                       int first = cache_name_pos(src, length), last;
 
-                               modes[i] = WORKING_DIRECTORY;
+                       if (first >= 0)
+                               prepare_move_submodule(src, first,
+                                                      submodule_gitfile + i);
+                       else if (index_range_of_same_dir(src, length,
+                                                        &first, &last) < 1)
+                               bad = _("source directory is empty");
+                       else { /* last - first >= 1 */
+                               int j, dst_len, n;
 
-                               first = cache_name_pos(src_w_slash, len_w_slash);
-                               if (first >= 0)
-                                       die (_("Huh? %.*s is in index?"),
-                                                       len_w_slash, src_w_slash);
-
-                               first = -1 - first;
-                               for (last = first; last < active_nr; last++) {
-                                       const char *path = active_cache[last]->name;
-                                       if (strncmp(path, src_w_slash, len_w_slash))
-                                               break;
-                               }
-                               if (src_w_slash != src)
-                                       free((char *)src_w_slash);
-
-                               if (last - first < 1)
-                                       bad = _("source directory is empty");
-                               else {
-                                       int j, dst_len;
-
-                                       if (last - first > 0) {
-                                               source = xrealloc(source,
-                                                               (argc + last - first)
-                                                               * sizeof(char *));
-                                               destination = xrealloc(destination,
-                                                               (argc + last - first)
-                                                               * sizeof(char *));
-                                               modes = xrealloc(modes,
-                                                               (argc + last - first)
-                                                               * sizeof(enum update_mode));
-                                               submodule_gitfile = xrealloc(submodule_gitfile,
-                                                               (argc + last - first)
-                                                               * sizeof(char *));
-                                       }
+                               modes[i] = WORKING_DIRECTORY;
+                               n = argc + last - first;
+                               source = xrealloc(source, n * sizeof(char *));
+                               destination = xrealloc(destination, n * sizeof(char *));
+                               modes = xrealloc(modes, n * sizeof(enum update_mode));
+                               submodule_gitfile = xrealloc(submodule_gitfile, n * sizeof(char *));
 
-                                       dst = add_slash(dst);
-                                       dst_len = strlen(dst);
+                               dst = add_slash(dst);
+                               dst_len = strlen(dst);
 
-                                       for (j = 0; j < last - first; j++) {
-                                               const char *path =
-                                                       active_cache[first + j]->name;
-                                               source[argc + j] = path;
-                                               destination[argc + j] =
-                                                       prefix_path(dst, dst_len,
-                                                               path + length + 1);
-                                               modes[argc + j] = INDEX;
-                                               submodule_gitfile[argc + j] = NULL;
-                                       }
-                                       argc += last - first;
+                               for (j = 0; j < last - first; j++) {
+                                       const char *path = active_cache[first + j]->name;
+                                       source[argc + j] = path;
+                                       destination[argc + j] =
+                                               prefix_path(dst, dst_len, path + length + 1);
+                                       modes[argc + j] = INDEX;
+                                       submodule_gitfile[argc + j] = NULL;
                                }
+                               argc += last - first;
                        }
                } else if (cache_name_pos(src, length) < 0)
                        bad = _("not under version control");
@@ -225,24 +226,22 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                else
                        string_list_insert(&src_for_dst, dst);
 
-               if (bad) {
-                       if (ignore_errors) {
-                               if (--argc > 0) {
-                                       memmove(source + i, source + i + 1,
-                                               (argc - i) * sizeof(char *));
-                                       memmove(destination + i,
-                                               destination + i + 1,
-                                               (argc - i) * sizeof(char *));
-                                       memmove(modes + i, modes + i + 1,
-                                               (argc - i) * sizeof(enum update_mode));
-                                       memmove(submodule_gitfile + i,
-                                               submodule_gitfile + i + 1,
-                                               (argc - i) * sizeof(char *));
-                                       i--;
-                               }
-                       } else
-                               die (_("%s, source=%s, destination=%s"),
-                                    bad, src, dst);
+               if (!bad)
+                       continue;
+               if (!ignore_errors)
+                       die(_("%s, source=%s, destination=%s"),
+                            bad, src, dst);
+               if (--argc > 0) {
+                       int n = argc - i;
+                       memmove(source + i, source + i + 1,
+                               n * sizeof(char *));
+                       memmove(destination + i, destination + i + 1,
+                               n * sizeof(char *));
+                       memmove(modes + i, modes + i + 1,
+                               n * sizeof(enum update_mode));
+                       memmove(submodule_gitfile + i, submodule_gitfile + i + 1,
+                               n * sizeof(char *));
+                       i--;
                }
        }
 
@@ -254,7 +253,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
                        printf(_("Renaming %s to %s\n"), src, dst);
                if (!show_only && mode != INDEX) {
                        if (rename(src, dst) < 0 && !ignore_errors)
-                               die_errno (_("renaming '%s' failed"), src);
+                               die_errno(_("renaming '%s' failed"), src);
                        if (submodule_gitfile[i]) {
                                if (submodule_gitfile[i] != SUBMODULE_WITH_GITDIR)
                                        connect_work_tree_and_git_dir(dst, submodule_gitfile[i]);
@@ -275,10 +274,9 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
        if (gitmodules_modified)
                stage_updated_gitmodules();
 
-       if (active_cache_changed) {
-               if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
-                       die(_("Unable to write new index file"));
-       }
+       if (active_cache_changed &&
+           write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
+               die(_("Unable to write new index file"));
 
        return 0;
 }
index 820c34135cab439e2168dd08947bd79d7ed7ae71..c25a4125103b5bb1c8571864a974105decc1a181 100644 (file)
@@ -122,12 +122,11 @@ static void write_commented_object(int fd, const unsigned char *object)
 {
        const char *show_args[5] =
                {"show", "--stat", "--no-notes", sha1_to_hex(object), NULL};
-       struct child_process show;
+       struct child_process show = CHILD_PROCESS_INIT;
        struct strbuf buf = STRBUF_INIT;
        struct strbuf cbuf = STRBUF_INIT;
 
        /* Invoke "git show --stat --no-notes $object" */
-       memset(&show, 0, sizeof(show));
        show.argv = show_args;
        show.no_stdin = 1;
        show.out = -1;
index f93ac454b4133f5c1e7cb1675a618b4c0b3174cd..afb8d9926496de2bed8bcab793dd79562e575e18 100644 (file)
@@ -255,7 +255,7 @@ static int copy_to_sideband(int in, int out, void *arg)
 typedef int (*feed_fn)(void *, const char **, size_t *);
 static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_state)
 {
-       struct child_process proc;
+       struct child_process proc = CHILD_PROCESS_INIT;
        struct async muxer;
        const char *argv[2];
        int code;
@@ -266,7 +266,6 @@ static int run_and_feed_hook(const char *hook_name, feed_fn feed, void *feed_sta
 
        argv[1] = NULL;
 
-       memset(&proc, 0, sizeof(proc));
        proc.argv = argv;
        proc.in = -1;
        proc.stdout_to_stderr = 1;
@@ -350,7 +349,7 @@ static int run_receive_hook(struct command *commands, const char *hook_name,
 static int run_update_hook(struct command *cmd)
 {
        const char *argv[5];
-       struct child_process proc;
+       struct child_process proc = CHILD_PROCESS_INIT;
        int code;
 
        argv[0] = find_hook("update");
@@ -362,7 +361,6 @@ static int run_update_hook(struct command *cmd)
        argv[3] = sha1_to_hex(cmd->new_sha1);
        argv[4] = NULL;
 
-       memset(&proc, 0, sizeof(proc));
        proc.no_stdin = 1;
        proc.stdout_to_stderr = 1;
        proc.err = use_sideband ? -1 : 0;
@@ -475,7 +473,6 @@ static const char *update(struct command *cmd, struct shallow_info *si)
        const char *namespaced_name;
        unsigned char *old_sha1 = cmd->old_sha1;
        unsigned char *new_sha1 = cmd->new_sha1;
-       struct ref_lock *lock;
 
        /* only refs/... are allowed */
        if (!starts_with(name, "refs/") || check_refname_format(name + 5, 0)) {
@@ -576,19 +573,27 @@ static const char *update(struct command *cmd, struct shallow_info *si)
                return NULL; /* good */
        }
        else {
+               struct strbuf err = STRBUF_INIT;
+               struct ref_transaction *transaction;
+
                if (shallow_update && si->shallow_ref[cmd->index] &&
                    update_shallow_ref(cmd, si))
                        return "shallow error";
 
-               lock = lock_any_ref_for_update(namespaced_name, old_sha1,
-                                              0, NULL);
-               if (!lock) {
-                       rp_error("failed to lock %s", name);
-                       return "failed to lock";
-               }
-               if (write_ref_sha1(lock, new_sha1, "push")) {
-                       return "failed to write"; /* error() already called */
+               transaction = ref_transaction_begin(&err);
+               if (!transaction ||
+                   ref_transaction_update(transaction, namespaced_name,
+                                          new_sha1, old_sha1, 0, 1, &err) ||
+                   ref_transaction_commit(transaction, "push", &err)) {
+                       ref_transaction_free(transaction);
+
+                       rp_error("%s", err.buf);
+                       strbuf_release(&err);
+                       return "failed to update ref";
                }
+
+               ref_transaction_free(transaction);
+               strbuf_release(&err);
                return NULL; /* good */
        }
 }
@@ -598,7 +603,7 @@ static void run_update_post_hook(struct command *commands)
        struct command *cmd;
        int argc;
        const char **argv;
-       struct child_process proc;
+       struct child_process proc = CHILD_PROCESS_INIT;
        char *hook;
 
        hook = find_hook("post-update");
@@ -621,7 +626,6 @@ static void run_update_post_hook(struct command *commands)
        }
        argv[argc] = NULL;
 
-       memset(&proc, 0, sizeof(proc));
        proc.no_stdin = 1;
        proc.stdout_to_stderr = 1;
        proc.err = use_sideband ? -1 : 0;
@@ -911,7 +915,7 @@ static const char *unpack(int err_fd, struct shallow_info *si)
        const char *hdr_err;
        int status;
        char hdr_arg[38];
-       struct child_process child;
+       struct child_process child = CHILD_PROCESS_INIT;
        int fsck_objects = (receive_fsck_objects >= 0
                            ? receive_fsck_objects
                            : transfer_fsck_objects >= 0
@@ -933,7 +937,6 @@ static const char *unpack(int err_fd, struct shallow_info *si)
                argv_array_pushl(&av, "--shallow-file", alt_shallow_file, NULL);
        }
 
-       memset(&child, 0, sizeof(child));
        if (ntohl(hdr.hdr_entries) < unpack_limit) {
                argv_array_pushl(&av, "unpack-objects", hdr_arg, NULL);
                if (quiet)
index 692c834d9dd48615e42b67e3924c64e3397ad903..d699d28e98c7e76e3c0a4943b58a8c88acede988 100644 (file)
@@ -179,9 +179,8 @@ static void send_git_request(int stdin_fd, const char *serv, const char *repo,
 static int run_child(const char *arg, const char *service)
 {
        int r;
-       struct child_process child;
+       struct child_process child = CHILD_PROCESS_INIT;
 
-       memset(&child, 0, sizeof(child));
        child.in = -1;
        child.out = -1;
        child.err = 0;
index a77e743b94036b2d856e6b3f74999170e39b5f17..fc088dbe6aec8b7a8fd23c924d8bc10c426b78ec 100644 (file)
@@ -133,7 +133,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                {".idx"},
                {".bitmap", 1},
        };
-       struct child_process cmd;
+       struct child_process cmd = CHILD_PROCESS_INIT;
        struct string_list_item *item;
        struct argv_array cmd_args = ARGV_ARRAY_INIT;
        struct string_list names = STRING_LIST_INIT_DUP;
@@ -250,7 +250,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
 
        argv_array_push(&cmd_args, packtmp);
 
-       memset(&cmd, 0, sizeof(cmd));
        cmd.argv = cmd_args.argv;
        cmd.git_cmd = 1;
        cmd.out = -1;
index 294b61b97e20ac9b5684bd6a180da37ebef43db9..8020db850092691f55df3815173a6eefce0ca6a0 100644 (file)
@@ -155,7 +155,8 @@ static int replace_object_sha1(const char *object_ref,
        unsigned char prev[20];
        enum object_type obj_type, repl_type;
        char ref[PATH_MAX];
-       struct ref_lock *lock;
+       struct ref_transaction *transaction;
+       struct strbuf err = STRBUF_INIT;
 
        obj_type = sha1_object_info(object, NULL);
        repl_type = sha1_object_info(repl, NULL);
@@ -168,12 +169,13 @@ static int replace_object_sha1(const char *object_ref,
 
        check_ref_valid(object, prev, ref, sizeof(ref), force);
 
-       lock = lock_any_ref_for_update(ref, prev, 0, NULL);
-       if (!lock)
-               die("%s: cannot lock the ref", ref);
-       if (write_ref_sha1(lock, repl, NULL) < 0)
-               die("%s: cannot update the ref", ref);
+       transaction = ref_transaction_begin(&err);
+       if (!transaction ||
+           ref_transaction_update(transaction, ref, repl, prev, 0, 1, &err) ||
+           ref_transaction_commit(transaction, NULL, &err))
+               die("%s", err.buf);
 
+       ref_transaction_free(transaction);
        return 0;
 }
 
@@ -197,7 +199,7 @@ static int replace_object(const char *object_ref, const char *replace_ref, int f
 static void export_object(const unsigned char *sha1, enum object_type type,
                          int raw, const char *filename)
 {
-       struct child_process cmd = { NULL };
+       struct child_process cmd = CHILD_PROCESS_INIT;
        int fd;
 
        fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
@@ -234,7 +236,7 @@ static void import_object(unsigned char *sha1, enum object_type type,
 
        if (!raw && type == OBJ_TREE) {
                const char *argv[] = { "mktree", NULL };
-               struct child_process cmd = { argv };
+               struct child_process cmd = CHILD_PROCESS_INIT;
                struct strbuf result = STRBUF_INIT;
 
                cmd.argv = argv;
index d85e08cc9cc22ee307470dbeb12fdd8d1eea655b..c911b456dedd648e36a876c6175c23e1ef028a43 100644 (file)
@@ -736,7 +736,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                        }
                        if (!strcmp(arg, "--git-dir")) {
                                const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
-                               static char cwd[PATH_MAX];
+                               char *cwd;
                                int len;
                                if (gitdir) {
                                        puts(gitdir);
@@ -746,10 +746,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                                        puts(".git");
                                        continue;
                                }
-                               if (!getcwd(cwd, PATH_MAX))
-                                       die_errno("unable to get current working directory");
+                               cwd = xgetcwd();
                                len = strlen(cwd);
                                printf("%s%s.git\n", cwd, len && cwd[len-1] != '/' ? "/" : "");
+                               free(cwd);
                                continue;
                        }
                        if (!strcmp(arg, "--resolve-git-dir")) {
index 19eb7478208d7e9c88ced92f2620572d2b234974..a81b9e4174c77fc10d9f0a37c547723505208c3c 100644 (file)
@@ -576,7 +576,6 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        struct strbuf ref = STRBUF_INIT;
        unsigned char object[20], prev[20];
        const char *object_ref, *tag;
-       struct ref_lock *lock;
        struct create_tag_options opt;
        char *cleanup_arg = NULL;
        int annotate = 0, force = 0, lines = -1;
@@ -584,6 +583,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        const char *msgfile = NULL, *keyid = NULL;
        struct msg_arg msg = { 0, STRBUF_INIT };
        struct commit_list *with_commit = NULL;
+       struct ref_transaction *transaction;
+       struct strbuf err = STRBUF_INIT;
        struct option options[] = {
                OPT_CMDMODE('l', "list", &cmdmode, N_("list tag names"), 'l'),
                { OPTION_INTEGER, 'n', NULL, &lines, N_("n"),
@@ -729,14 +730,17 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        if (annotate)
                create_tag(object, tag, &buf, &opt, prev, object);
 
-       lock = lock_any_ref_for_update(ref.buf, prev, 0, NULL);
-       if (!lock)
-               die(_("%s: cannot lock the ref"), ref.buf);
-       if (write_ref_sha1(lock, object, NULL) < 0)
-               die(_("%s: cannot update the ref"), ref.buf);
+       transaction = ref_transaction_begin(&err);
+       if (!transaction ||
+           ref_transaction_update(transaction, ref.buf, object, prev,
+                                  0, 1, &err) ||
+           ref_transaction_commit(transaction, NULL, &err))
+               die("%s", err.buf);
+       ref_transaction_free(transaction);
        if (force && !is_null_sha1(prev) && hashcmp(prev, object))
                printf(_("Updated tag '%s' (was %s)\n"), tag, find_unique_abbrev(prev, DEFAULT_ABBREV));
 
+       strbuf_release(&err);
        strbuf_release(&buf);
        strbuf_release(&ref);
        return 0;
index 3067b11310fb01e9e05a1988898566f211601e07..54a48c0cfaab57122fc7ce57c525638c2c95408c 100644 (file)
@@ -12,11 +12,8 @@ static const char * const git_update_ref_usage[] = {
        NULL
 };
 
-static struct ref_transaction *transaction;
-
 static char line_termination = '\n';
 static int update_flags;
-static struct strbuf err = STRBUF_INIT;
 
 /*
  * Parse one whitespace- or NUL-terminated, possibly C-quoted argument
@@ -177,8 +174,10 @@ static int parse_next_sha1(struct strbuf *input, const char **next,
  * depending on how line_termination is set.
  */
 
-static const char *parse_cmd_update(struct strbuf *input, const char *next)
+static const char *parse_cmd_update(struct ref_transaction *transaction,
+                                   struct strbuf *input, const char *next)
 {
+       struct strbuf err = STRBUF_INIT;
        char *refname;
        unsigned char new_sha1[20];
        unsigned char old_sha1[20];
@@ -204,12 +203,15 @@ static const char *parse_cmd_update(struct strbuf *input, const char *next)
 
        update_flags = 0;
        free(refname);
+       strbuf_release(&err);
 
        return next;
 }
 
-static const char *parse_cmd_create(struct strbuf *input, const char *next)
+static const char *parse_cmd_create(struct ref_transaction *transaction,
+                                   struct strbuf *input, const char *next)
 {
+       struct strbuf err = STRBUF_INIT;
        char *refname;
        unsigned char new_sha1[20];
 
@@ -226,16 +228,21 @@ static const char *parse_cmd_create(struct strbuf *input, const char *next)
        if (*next != line_termination)
                die("create %s: extra input: %s", refname, next);
 
-       ref_transaction_create(transaction, refname, new_sha1, update_flags);
+       if (ref_transaction_create(transaction, refname, new_sha1,
+                                  update_flags, &err))
+               die("%s", err.buf);
 
        update_flags = 0;
        free(refname);
+       strbuf_release(&err);
 
        return next;
 }
 
-static const char *parse_cmd_delete(struct strbuf *input, const char *next)
+static const char *parse_cmd_delete(struct ref_transaction *transaction,
+                                   struct strbuf *input, const char *next)
 {
+       struct strbuf err = STRBUF_INIT;
        char *refname;
        unsigned char old_sha1[20];
        int have_old;
@@ -256,17 +263,21 @@ static const char *parse_cmd_delete(struct strbuf *input, const char *next)
        if (*next != line_termination)
                die("delete %s: extra input: %s", refname, next);
 
-       ref_transaction_delete(transaction, refname, old_sha1,
-                              update_flags, have_old);
+       if (ref_transaction_delete(transaction, refname, old_sha1,
+                                  update_flags, have_old, &err))
+               die("%s", err.buf);
 
        update_flags = 0;
        free(refname);
+       strbuf_release(&err);
 
        return next;
 }
 
-static const char *parse_cmd_verify(struct strbuf *input, const char *next)
+static const char *parse_cmd_verify(struct ref_transaction *transaction,
+                                   struct strbuf *input, const char *next)
 {
+       struct strbuf err = STRBUF_INIT;
        char *refname;
        unsigned char new_sha1[20];
        unsigned char old_sha1[20];
@@ -294,6 +305,7 @@ static const char *parse_cmd_verify(struct strbuf *input, const char *next)
 
        update_flags = 0;
        free(refname);
+       strbuf_release(&err);
 
        return next;
 }
@@ -307,7 +319,7 @@ static const char *parse_cmd_option(struct strbuf *input, const char *next)
        return next + 8;
 }
 
-static void update_refs_stdin(void)
+static void update_refs_stdin(struct ref_transaction *transaction)
 {
        struct strbuf input = STRBUF_INIT;
        const char *next;
@@ -322,13 +334,13 @@ static void update_refs_stdin(void)
                else if (isspace(*next))
                        die("whitespace before command: %s", next);
                else if (starts_with(next, "update "))
-                       next = parse_cmd_update(&input, next + 7);
+                       next = parse_cmd_update(transaction, &input, next + 7);
                else if (starts_with(next, "create "))
-                       next = parse_cmd_create(&input, next + 7);
+                       next = parse_cmd_create(transaction, &input, next + 7);
                else if (starts_with(next, "delete "))
-                       next = parse_cmd_delete(&input, next + 7);
+                       next = parse_cmd_delete(transaction, &input, next + 7);
                else if (starts_with(next, "verify "))
-                       next = parse_cmd_verify(&input, next + 7);
+                       next = parse_cmd_verify(transaction, &input, next + 7);
                else if (starts_with(next, "option "))
                        next = parse_cmd_option(&input, next + 7);
                else
@@ -362,15 +374,21 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
                die("Refusing to perform update with empty message.");
 
        if (read_stdin) {
-               transaction = ref_transaction_begin();
+               struct strbuf err = STRBUF_INIT;
+               struct ref_transaction *transaction;
+
+               transaction = ref_transaction_begin(&err);
+               if (!transaction)
+                       die("%s", err.buf);
                if (delete || no_deref || argc > 0)
                        usage_with_options(git_update_ref_usage, options);
                if (end_null)
                        line_termination = '\0';
-               update_refs_stdin();
+               update_refs_stdin(transaction);
                if (ref_transaction_commit(transaction, msg, &err))
                        die("%s", err.buf);
                ref_transaction_free(transaction);
+               strbuf_release(&err);
                return 0;
        }
 
index 972579f33c4b0adfb2240ef90b22980dc042c70a..7747537beb72aba52377a13b9b3d61829f3a2fa8 100644 (file)
@@ -8,7 +8,7 @@
 
 static int verify_one_pack(const char *path, unsigned int flags)
 {
-       struct child_process index_pack;
+       struct child_process index_pack = CHILD_PROCESS_INIT;
        const char *argv[] = {"index-pack", NULL, NULL, NULL };
        struct strbuf arg = STRBUF_INIT;
        int verbose = flags & VERIFY_PACK_VERBOSE;
@@ -32,7 +32,6 @@ static int verify_one_pack(const char *path, unsigned int flags)
                strbuf_addstr(&arg, ".pack");
        argv[2] = arg.buf;
 
-       memset(&index_pack, 0, sizeof(index_pack));
        index_pack.argv = argv;
        index_pack.git_cmd = 1;
 
index 71a21a67fa6bc5ce718dfc6593035f577b2dbc15..b2b89fe8628eb29b613754ee8e837fd56de185da 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -221,8 +221,8 @@ static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
        line = memmem(buf, size, "\ntagger ", 8);
        if (!line++)
                return 1;
-       lineend = memchr(line, buf + size - line, '\n');
-       line = memchr(line, lineend ? lineend - line : buf + size - line, '>');
+       lineend = memchr(line, '\n', buf + size - line);
+       line = memchr(line, '>', lineend ? lineend - line : buf + size - line);
        if (!line++)
                return 1;
        date = strtoul(line, NULL, 10);
@@ -240,7 +240,7 @@ int create_bundle(struct bundle_header *header, const char *path,
        int i, ref_count = 0;
        struct strbuf buf = STRBUF_INIT;
        struct rev_info revs;
-       struct child_process rls;
+       struct child_process rls = CHILD_PROCESS_INIT;
        FILE *rls_fout;
 
        bundle_to_stdout = !strcmp(path, "-");
@@ -258,7 +258,6 @@ int create_bundle(struct bundle_header *header, const char *path,
        init_revisions(&revs, NULL);
 
        /* write prerequisites */
-       memset(&rls, 0, sizeof(rls));
        argv_array_pushl(&rls.args,
                         "rev-list", "--boundary", "--pretty=oneline",
                         NULL);
@@ -417,14 +416,13 @@ int unbundle(struct bundle_header *header, int bundle_fd, int flags)
 {
        const char *argv_index_pack[] = {"index-pack",
                                         "--fix-thin", "--stdin", NULL, NULL};
-       struct child_process ip;
+       struct child_process ip = CHILD_PROCESS_INIT;
 
        if (flags & BUNDLE_VERBOSE)
                argv_index_pack[3] = "-v";
 
        if (verify_bundle(header, 0))
                return -1;
-       memset(&ip, 0, sizeof(ip));
        ip.argv = argv_index_pack;
        ip.in = bundle_fd;
        ip.no_stdout = 1;
index c53f7de2b13acfc1b97c60b04552e57791377442..75a54fdc7232e5693b042aa06540d51a99f01551 100644 (file)
@@ -246,9 +246,12 @@ static int update_one(struct cache_tree *it,
        struct strbuf buffer;
        int missing_ok = flags & WRITE_TREE_MISSING_OK;
        int dryrun = flags & WRITE_TREE_DRY_RUN;
+       int repair = flags & WRITE_TREE_REPAIR;
        int to_invalidate = 0;
        int i;
 
+       assert(!(dryrun && repair));
+
        *skip_count = 0;
 
        if (0 <= it->entry_count && has_sha1_file(it->sha1))
@@ -320,6 +323,7 @@ static int update_one(struct cache_tree *it,
                int pathlen, entlen;
                const unsigned char *sha1;
                unsigned mode;
+               int expected_missing = 0;
 
                path = ce->name;
                pathlen = ce_namelen(ce);
@@ -336,8 +340,10 @@ static int update_one(struct cache_tree *it,
                        i += sub->count;
                        sha1 = sub->cache_tree->sha1;
                        mode = S_IFDIR;
-                       if (sub->cache_tree->entry_count < 0)
+                       if (sub->cache_tree->entry_count < 0) {
                                to_invalidate = 1;
+                               expected_missing = 1;
+                       }
                }
                else {
                        sha1 = ce->sha1;
@@ -347,6 +353,8 @@ static int update_one(struct cache_tree *it,
                }
                if (mode != S_IFGITLINK && !missing_ok && !has_sha1_file(sha1)) {
                        strbuf_release(&buffer);
+                       if (expected_missing)
+                               return -1;
                        return error("invalid object %06o %s for '%.*s'",
                                mode, sha1_to_hex(sha1), entlen+baselen, path);
                }
@@ -381,7 +389,14 @@ static int update_one(struct cache_tree *it,
 #endif
        }
 
-       if (dryrun)
+       if (repair) {
+               unsigned char sha1[20];
+               hash_sha1_file(buffer.buf, buffer.len, tree_type, sha1);
+               if (has_sha1_file(sha1))
+                       hashcpy(it->sha1, sha1);
+               else
+                       to_invalidate = 1;
+       } else if (dryrun)
                hash_sha1_file(buffer.buf, buffer.len, tree_type, it->sha1);
        else if (write_sha1_file(buffer.buf, buffer.len, tree_type, it->sha1)) {
                strbuf_release(&buffer);
index b47ccec7f626d7cda34ed17661c1dc3e4f035d6a..aa7b3e4a0a9d4bbb29574d71e23c05349be4c6fc 100644 (file)
@@ -39,6 +39,7 @@ int update_main_cache_tree(int);
 #define WRITE_TREE_IGNORE_CACHE_TREE 2
 #define WRITE_TREE_DRY_RUN 4
 #define WRITE_TREE_SILENT 8
+#define WRITE_TREE_REPAIR 16
 
 /* error return codes */
 #define WRITE_TREE_UNREADABLE_INDEX (-1)
diff --git a/cache.h b/cache.h
index fcb511db70f7703f2b29dbc89dcf703065c823fe..dfa1a5696d448b407644276df58fb24e25c57113 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -8,6 +8,7 @@
 #include "gettext.h"
 #include "convert.h"
 #include "trace.h"
+#include "string-list.h"
 
 #include SHA1_HEADER
 #ifndef git_SHA_CTX
@@ -585,6 +586,7 @@ extern NORETURN void unable_to_lock_index_die(const char *path, int err);
 extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
 extern int hold_lock_file_for_append(struct lock_file *, const char *path, int);
 extern int commit_lock_file(struct lock_file *);
+extern int reopen_lock_file(struct lock_file *);
 extern void update_index_if_able(struct index_state *, struct lock_file *);
 
 extern int hold_locked_index(struct lock_file *, int);
@@ -1061,6 +1063,7 @@ extern const char *git_author_info(int);
 extern const char *git_committer_info(int);
 extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
 extern const char *fmt_name(const char *name, const char *email);
+extern const char *ident_default_name(void);
 extern const char *ident_default_email(void);
 extern const char *git_editor(void);
 extern const char *git_pager(int stdout_is_tty);
@@ -1294,7 +1297,7 @@ extern int git_config_from_buf(config_fn_t fn, const char *name,
                               const char *buf, size_t len, void *data);
 extern void git_config_push_parameter(const char *text);
 extern int git_config_from_parameters(config_fn_t fn, void *data);
-extern int git_config(config_fn_t fn, void *);
+extern void git_config(config_fn_t fn, void *);
 extern int git_config_with_options(config_fn_t fn, void *,
                                   struct git_config_source *config_source,
                                   int respect_includes);
@@ -1351,6 +1354,69 @@ extern int parse_config_key(const char *var,
                            const char **subsection, int *subsection_len,
                            const char **key);
 
+struct config_set_element {
+       struct hashmap_entry ent;
+       char *key;
+       struct string_list value_list;
+};
+
+struct configset_list_item {
+       struct config_set_element *e;
+       int value_index;
+};
+
+/*
+ * the contents of the list are ordered according to their
+ * position in the config files and order of parsing the files.
+ * (i.e. key-value pair at the last position of .git/config will
+ * be at the last item of the list)
+ */
+struct configset_list {
+       struct configset_list_item *items;
+       unsigned int nr, alloc;
+};
+
+struct config_set {
+       struct hashmap config_hash;
+       int hash_initialized;
+       struct configset_list list;
+};
+
+extern void git_configset_init(struct config_set *cs);
+extern int git_configset_add_file(struct config_set *cs, const char *filename);
+extern int git_configset_get_value(struct config_set *cs, const char *key, const char **value);
+extern const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key);
+extern void git_configset_clear(struct config_set *cs);
+extern int git_configset_get_string_const(struct config_set *cs, const char *key, const char **dest);
+extern int git_configset_get_string(struct config_set *cs, const char *key, char **dest);
+extern int git_configset_get_int(struct config_set *cs, const char *key, int *dest);
+extern int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned long *dest);
+extern int git_configset_get_bool(struct config_set *cs, const char *key, int *dest);
+extern int git_configset_get_bool_or_int(struct config_set *cs, const char *key, int *is_bool, int *dest);
+extern int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest);
+extern int git_configset_get_pathname(struct config_set *cs, const char *key, const char **dest);
+
+extern int git_config_get_value(const char *key, const char **value);
+extern const struct string_list *git_config_get_value_multi(const char *key);
+extern void git_config_clear(void);
+extern void git_config_iter(config_fn_t fn, void *data);
+extern int git_config_get_string_const(const char *key, const char **dest);
+extern int git_config_get_string(const char *key, char **dest);
+extern int git_config_get_int(const char *key, int *dest);
+extern int git_config_get_ulong(const char *key, unsigned long *dest);
+extern int git_config_get_bool(const char *key, int *dest);
+extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
+extern int git_config_get_maybe_bool(const char *key, int *dest);
+extern int git_config_get_pathname(const char *key, const char **dest);
+
+struct key_value_info {
+       const char *filename;
+       int linenr;
+};
+
+extern NORETURN void git_die_config(const char *key, const char *err, ...) __attribute__((format(printf, 2, 3)));
+extern NORETURN void git_die_config_linenr(const char *key, const char *filename, int linenr);
+
 extern int committer_ident_sufficiently_given(void);
 extern int author_ident_sufficiently_given(void);
 
index ca878bcea7a42476a7c2b03e74897a2af87bec3f..76b615db5f2a4ff7567a7d1d9d6514f838f15321 100644 (file)
--- a/column.c
+++ b/column.c
@@ -367,7 +367,7 @@ int parseopt_column_callback(const struct option *opt,
 }
 
 static int fd_out = -1;
-static struct child_process column_process;
+static struct child_process column_process = CHILD_PROCESS_INIT;
 
 int run_column_filter(int colopts, const struct column_options *opts)
 {
index 60cb4f81f9788efeff21d05d48f2183e94765385..91edce58e15b82428fcc5f3b006e23bf5380d38c 100644 (file)
@@ -1407,7 +1407,8 @@ void diff_tree_combined(const unsigned char *sha1,
                show_log(rev);
 
                if (rev->verbose_header && opt->output_format &&
-                   opt->output_format != DIFF_FORMAT_NO_OUTPUT)
+                   opt->output_format != DIFF_FORMAT_NO_OUTPUT &&
+                   !commit_format_is_empty(rev->commit_format))
                        printf("%s%c", diff_line_prefix(opt),
                               opt->line_termination);
        }
index a8cbf52f15ff01778ba61a5a888263d424b2d8d2..a401ddfbc4e5c2e5e4a9d7aeedebc34e6103c9fa 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -26,13 +26,25 @@ extern int save_commit_buffer;
 extern const char *commit_type;
 
 /* While we can decorate any object with a name, it's only used for commits.. */
-extern struct decoration name_decoration;
 struct name_decoration {
        struct name_decoration *next;
        int type;
-       char name[1];
+       char name[FLEX_ARRAY];
 };
 
+enum decoration_type {
+       DECORATION_NONE = 0,
+       DECORATION_REF_LOCAL,
+       DECORATION_REF_REMOTE,
+       DECORATION_REF_TAG,
+       DECORATION_REF_STASH,
+       DECORATION_REF_HEAD,
+       DECORATION_GRAFTED,
+};
+
+void add_name_decoration(enum decoration_type type, const char *name, struct object *obj);
+const struct name_decoration *get_name_decoration(const struct object *obj);
+
 struct commit *lookup_commit(const unsigned char *sha1);
 struct commit *lookup_commit_reference(const unsigned char *sha1);
 struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
@@ -159,6 +171,7 @@ extern void get_commit_format(const char *arg, struct rev_info *);
 extern const char *format_subject(struct strbuf *sb, const char *msg,
                                  const char *line_separator);
 extern void userformat_find_requirements(const char *fmt, struct userformat_want *w);
+extern int commit_format_is_empty(enum cmit_fmt);
 extern void format_commit_message(const struct commit *commit,
                                  const char *format, struct strbuf *sb,
                                  const struct pretty_print_context *context);
index 058505cb8d8d8bb531527b620125b0204732458a..83c913ad0928aba882a86f361170cd256adbd445 100644 (file)
--- a/config.c
+++ b/config.c
@@ -9,6 +9,8 @@
 #include "exec_cmd.h"
 #include "strbuf.h"
 #include "quote.h"
+#include "hashmap.h"
+#include "string-list.h"
 
 struct config_source {
        struct config_source *prev;
@@ -37,6 +39,13 @@ static struct config_source *cf;
 
 static int zlib_compression_seen;
 
+/*
+ * Default config_set that contains key-value pairs from the usual set of config
+ * config files (i.e repo specific .git/config, user wide ~/.gitconfig, XDG
+ * config file and the global /etc/gitconfig)
+ */
+static struct config_set the_config_set;
+
 static int config_file_fgetc(struct config_source *conf)
 {
        return fgetc(conf->u.file);
@@ -162,19 +171,27 @@ void git_config_push_parameter(const char *text)
 int git_config_parse_parameter(const char *text,
                               config_fn_t fn, void *data)
 {
+       const char *value;
        struct strbuf **pair;
+
        pair = strbuf_split_str(text, '=', 2);
        if (!pair[0])
                return error("bogus config parameter: %s", text);
-       if (pair[0]->len && pair[0]->buf[pair[0]->len - 1] == '=')
+
+       if (pair[0]->len && pair[0]->buf[pair[0]->len - 1] == '=') {
                strbuf_setlen(pair[0], pair[0]->len - 1);
+               value = pair[1] ? pair[1]->buf : "";
+       } else {
+               value = NULL;
+       }
+
        strbuf_trim(pair[0]);
        if (!pair[0]->len) {
                strbuf_list_free(pair);
                return error("bogus config parameter: %s", text);
        }
        strbuf_tolower(pair[0]);
-       if (fn(pair[0]->buf, pair[1] ? pair[1]->buf : NULL, data) < 0) {
+       if (fn(pair[0]->buf, value, data) < 0) {
                strbuf_list_free(pair);
                return -1;
        }
@@ -229,6 +246,7 @@ static int get_next_char(void)
                cf->linenr++;
        if (c == EOF) {
                cf->eof = 1;
+               cf->linenr++;
                c = '\n';
        }
        return c;
@@ -304,6 +322,7 @@ static int get_value(config_fn_t fn, void *data, struct strbuf *name)
 {
        int c;
        char *value;
+       int ret;
 
        /* Get the full name */
        for (;;) {
@@ -326,7 +345,15 @@ static int get_value(config_fn_t fn, void *data, struct strbuf *name)
                if (!value)
                        return -1;
        }
-       return fn(name->buf, value, data);
+       /*
+        * We already consumed the \n, but we need linenr to point to
+        * the line we just parsed during the call to fn to get
+        * accurate line number in error messages.
+        */
+       cf->linenr--;
+       ret = fn(name->buf, value, data);
+       cf->linenr++;
+       return ret;
 }
 
 static int get_extended_base_var(struct strbuf *name, int c)
@@ -442,9 +469,9 @@ static int git_parse_source(config_fn_t fn, void *data)
                        break;
        }
        if (cf->die_on_error)
-               die("bad config file line %d in %s", cf->linenr, cf->name);
+               die(_("bad config file line %d in %s"), cf->linenr, cf->name);
        else
-               return error("bad config file line %d in %s", cf->linenr, cf->name);
+               return error(_("bad config file line %d in %s"), cf->linenr, cf->name);
 }
 
 static int parse_unit_factor(const char *end, uintmax_t *val)
@@ -560,9 +587,9 @@ static void die_bad_number(const char *name, const char *value)
                value = "";
 
        if (cf && cf->name)
-               die("bad numeric config value '%s' for '%s' in %s: %s",
+               die(_("bad numeric config value '%s' for '%s' in %s: %s"),
                    value, name, cf->name, reason);
-       die("bad numeric config value '%s' for '%s': %s", value, name, reason);
+       die(_("bad numeric config value '%s' for '%s': %s"), value, name, reason);
 }
 
 int git_config_int(const char *name, const char *value)
@@ -647,7 +674,7 @@ int git_config_pathname(const char **dest, const char *var, const char *value)
                return config_error_nonbool(var);
        *dest = expand_user_path(value);
        if (!*dest)
-               die("Failed to expand user dir in: '%s'", value);
+               die(_("failed to expand user dir in: '%s'"), value);
        return 0;
 }
 
@@ -725,7 +752,7 @@ static int git_default_core_config(const char *var, const char *value)
                if (level == -1)
                        level = Z_DEFAULT_COMPRESSION;
                else if (level < 0 || level > Z_BEST_COMPRESSION)
-                       die("bad zlib compression level %d", level);
+                       die(_("bad zlib compression level %d"), level);
                zlib_compression_level = level;
                zlib_compression_seen = 1;
                return 0;
@@ -736,7 +763,7 @@ static int git_default_core_config(const char *var, const char *value)
                if (level == -1)
                        level = Z_DEFAULT_COMPRESSION;
                else if (level < 0 || level > Z_BEST_COMPRESSION)
-                       die("bad zlib compression level %d", level);
+                       die(_("bad zlib compression level %d"), level);
                core_compression_level = level;
                core_compression_seen = 1;
                if (!zlib_compression_seen)
@@ -858,7 +885,7 @@ static int git_default_core_config(const char *var, const char *value)
                else if (!strcmp(value, "link"))
                        object_creation_mode = OBJECT_CREATION_USES_HARDLINKS;
                else
-                       die("Invalid mode for object creation: %s", value);
+                       die(_("invalid mode for object creation: %s"), value);
                return 0;
        }
 
@@ -1158,7 +1185,7 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
 
        switch (git_config_from_parameters(fn, data)) {
        case -1: /* error */
-               die("unable to parse command-line config");
+               die(_("unable to parse command-line config"));
                break;
        case 0: /* found nothing */
                break;
@@ -1205,9 +1232,365 @@ int git_config_with_options(config_fn_t fn, void *data,
        return ret;
 }
 
-int git_config(config_fn_t fn, void *data)
+static void git_config_raw(config_fn_t fn, void *data)
+{
+       if (git_config_with_options(fn, data, NULL, 1) < 0)
+               /*
+                * git_config_with_options() normally returns only
+                * positive values, as most errors are fatal, and
+                * non-fatal potential errors are guarded by "if"
+                * statements that are entered only when no error is
+                * possible.
+                *
+                * If we ever encounter a non-fatal error, it means
+                * something went really wrong and we should stop
+                * immediately.
+                */
+               die(_("unknown error occured while reading the configuration files"));
+}
+
+static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)
+{
+       int i, value_index;
+       struct string_list *values;
+       struct config_set_element *entry;
+       struct configset_list *list = &cs->list;
+       struct key_value_info *kv_info;
+
+       for (i = 0; i < list->nr; i++) {
+               entry = list->items[i].e;
+               value_index = list->items[i].value_index;
+               values = &entry->value_list;
+               if (fn(entry->key, values->items[value_index].string, data) < 0) {
+                       kv_info = values->items[value_index].util;
+                       git_die_config_linenr(entry->key, kv_info->filename, kv_info->linenr);
+               }
+       }
+}
+
+static void git_config_check_init(void);
+
+void git_config(config_fn_t fn, void *data)
+{
+       git_config_check_init();
+       configset_iter(&the_config_set, fn, data);
+}
+
+static struct config_set_element *configset_find_element(struct config_set *cs, const char *key)
+{
+       struct config_set_element k;
+       struct config_set_element *found_entry;
+       char *normalized_key;
+       int ret;
+       /*
+        * `key` may come from the user, so normalize it before using it
+        * for querying entries from the hashmap.
+        */
+       ret = git_config_parse_key(key, &normalized_key, NULL);
+
+       if (ret)
+               return NULL;
+
+       hashmap_entry_init(&k, strhash(normalized_key));
+       k.key = normalized_key;
+       found_entry = hashmap_get(&cs->config_hash, &k, NULL);
+       free(normalized_key);
+       return found_entry;
+}
+
+static int configset_add_value(struct config_set *cs, const char *key, const char *value)
+{
+       struct config_set_element *e;
+       struct string_list_item *si;
+       struct configset_list_item *l_item;
+       struct key_value_info *kv_info = xmalloc(sizeof(*kv_info));
+
+       e = configset_find_element(cs, key);
+       /*
+        * Since the keys are being fed by git_config*() callback mechanism, they
+        * are already normalized. So simply add them without any further munging.
+        */
+       if (!e) {
+               e = xmalloc(sizeof(*e));
+               hashmap_entry_init(e, strhash(key));
+               e->key = xstrdup(key);
+               string_list_init(&e->value_list, 1);
+               hashmap_add(&cs->config_hash, e);
+       }
+       si = string_list_append_nodup(&e->value_list, value ? xstrdup(value) : NULL);
+
+       ALLOC_GROW(cs->list.items, cs->list.nr + 1, cs->list.alloc);
+       l_item = &cs->list.items[cs->list.nr++];
+       l_item->e = e;
+       l_item->value_index = e->value_list.nr - 1;
+
+       if (cf) {
+               kv_info->filename = strintern(cf->name);
+               kv_info->linenr = cf->linenr;
+       } else {
+               /* for values read from `git_config_from_parameters()` */
+               kv_info->filename = NULL;
+               kv_info->linenr = -1;
+       }
+       si->util = kv_info;
+
+       return 0;
+}
+
+static int config_set_element_cmp(const struct config_set_element *e1,
+                                const struct config_set_element *e2, const void *unused)
+{
+       return strcmp(e1->key, e2->key);
+}
+
+void git_configset_init(struct config_set *cs)
+{
+       hashmap_init(&cs->config_hash, (hashmap_cmp_fn)config_set_element_cmp, 0);
+       cs->hash_initialized = 1;
+       cs->list.nr = 0;
+       cs->list.alloc = 0;
+       cs->list.items = NULL;
+}
+
+void git_configset_clear(struct config_set *cs)
 {
-       return git_config_with_options(fn, data, NULL, 1);
+       struct config_set_element *entry;
+       struct hashmap_iter iter;
+       if (!cs->hash_initialized)
+               return;
+
+       hashmap_iter_init(&cs->config_hash, &iter);
+       while ((entry = hashmap_iter_next(&iter))) {
+               free(entry->key);
+               string_list_clear(&entry->value_list, 1);
+       }
+       hashmap_free(&cs->config_hash, 1);
+       cs->hash_initialized = 0;
+       free(cs->list.items);
+       cs->list.nr = 0;
+       cs->list.alloc = 0;
+       cs->list.items = NULL;
+}
+
+static int config_set_callback(const char *key, const char *value, void *cb)
+{
+       struct config_set *cs = cb;
+       configset_add_value(cs, key, value);
+       return 0;
+}
+
+int git_configset_add_file(struct config_set *cs, const char *filename)
+{
+       return git_config_from_file(config_set_callback, filename, cs);
+}
+
+int git_configset_get_value(struct config_set *cs, const char *key, const char **value)
+{
+       const struct string_list *values = NULL;
+       /*
+        * Follows "last one wins" semantic, i.e., if there are multiple matches for the
+        * queried key in the files of the configset, the value returned will be the last
+        * value in the value list for that key.
+        */
+       values = git_configset_get_value_multi(cs, key);
+
+       if (!values)
+               return 1;
+       assert(values->nr > 0);
+       *value = values->items[values->nr - 1].string;
+       return 0;
+}
+
+const struct string_list *git_configset_get_value_multi(struct config_set *cs, const char *key)
+{
+       struct config_set_element *e = configset_find_element(cs, key);
+       return e ? &e->value_list : NULL;
+}
+
+int git_configset_get_string_const(struct config_set *cs, const char *key, const char **dest)
+{
+       const char *value;
+       if (!git_configset_get_value(cs, key, &value))
+               return git_config_string(dest, key, value);
+       else
+               return 1;
+}
+
+int git_configset_get_string(struct config_set *cs, const char *key, char **dest)
+{
+       return git_configset_get_string_const(cs, key, (const char **)dest);
+}
+
+int git_configset_get_int(struct config_set *cs, const char *key, int *dest)
+{
+       const char *value;
+       if (!git_configset_get_value(cs, key, &value)) {
+               *dest = git_config_int(key, value);
+               return 0;
+       } else
+               return 1;
+}
+
+int git_configset_get_ulong(struct config_set *cs, const char *key, unsigned long *dest)
+{
+       const char *value;
+       if (!git_configset_get_value(cs, key, &value)) {
+               *dest = git_config_ulong(key, value);
+               return 0;
+       } else
+               return 1;
+}
+
+int git_configset_get_bool(struct config_set *cs, const char *key, int *dest)
+{
+       const char *value;
+       if (!git_configset_get_value(cs, key, &value)) {
+               *dest = git_config_bool(key, value);
+               return 0;
+       } else
+               return 1;
+}
+
+int git_configset_get_bool_or_int(struct config_set *cs, const char *key,
+                               int *is_bool, int *dest)
+{
+       const char *value;
+       if (!git_configset_get_value(cs, key, &value)) {
+               *dest = git_config_bool_or_int(key, value, is_bool);
+               return 0;
+       } else
+               return 1;
+}
+
+int git_configset_get_maybe_bool(struct config_set *cs, const char *key, int *dest)
+{
+       const char *value;
+       if (!git_configset_get_value(cs, key, &value)) {
+               *dest = git_config_maybe_bool(key, value);
+               if (*dest == -1)
+                       return -1;
+               return 0;
+       } else
+               return 1;
+}
+
+int git_configset_get_pathname(struct config_set *cs, const char *key, const char **dest)
+{
+       const char *value;
+       if (!git_configset_get_value(cs, key, &value))
+               return git_config_pathname(dest, key, value);
+       else
+               return 1;
+}
+
+static void git_config_check_init(void)
+{
+       if (the_config_set.hash_initialized)
+               return;
+       git_configset_init(&the_config_set);
+       git_config_raw(config_set_callback, &the_config_set);
+}
+
+void git_config_clear(void)
+{
+       if (!the_config_set.hash_initialized)
+               return;
+       git_configset_clear(&the_config_set);
+}
+
+int git_config_get_value(const char *key, const char **value)
+{
+       git_config_check_init();
+       return git_configset_get_value(&the_config_set, key, value);
+}
+
+const struct string_list *git_config_get_value_multi(const char *key)
+{
+       git_config_check_init();
+       return git_configset_get_value_multi(&the_config_set, key);
+}
+
+int git_config_get_string_const(const char *key, const char **dest)
+{
+       int ret;
+       git_config_check_init();
+       ret = git_configset_get_string_const(&the_config_set, key, dest);
+       if (ret < 0)
+               git_die_config(key, NULL);
+       return ret;
+}
+
+int git_config_get_string(const char *key, char **dest)
+{
+       git_config_check_init();
+       return git_config_get_string_const(key, (const char **)dest);
+}
+
+int git_config_get_int(const char *key, int *dest)
+{
+       git_config_check_init();
+       return git_configset_get_int(&the_config_set, key, dest);
+}
+
+int git_config_get_ulong(const char *key, unsigned long *dest)
+{
+       git_config_check_init();
+       return git_configset_get_ulong(&the_config_set, key, dest);
+}
+
+int git_config_get_bool(const char *key, int *dest)
+{
+       git_config_check_init();
+       return git_configset_get_bool(&the_config_set, key, dest);
+}
+
+int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest)
+{
+       git_config_check_init();
+       return git_configset_get_bool_or_int(&the_config_set, key, is_bool, dest);
+}
+
+int git_config_get_maybe_bool(const char *key, int *dest)
+{
+       git_config_check_init();
+       return git_configset_get_maybe_bool(&the_config_set, key, dest);
+}
+
+int git_config_get_pathname(const char *key, const char **dest)
+{
+       int ret;
+       git_config_check_init();
+       ret = git_configset_get_pathname(&the_config_set, key, dest);
+       if (ret < 0)
+               git_die_config(key, NULL);
+       return ret;
+}
+
+NORETURN
+void git_die_config_linenr(const char *key, const char *filename, int linenr)
+{
+       if (!filename)
+               die(_("unable to parse '%s' from command-line config"), key);
+       else
+               die(_("bad config variable '%s' in file '%s' at line %d"),
+                   key, filename, linenr);
+}
+
+NORETURN __attribute__((format(printf, 2, 3)))
+void git_die_config(const char *key, const char *err, ...)
+{
+       const struct string_list *values;
+       struct key_value_info *kv_info;
+
+       if (err) {
+               va_list params;
+               va_start(params, err);
+               vreportf("error: ", err, params);
+               va_end(params);
+       }
+       values = git_config_get_value_multi(key);
+       kv_info = values->items[values->nr - 1].util;
+       git_die_config_linenr(key, kv_info->filename, kv_info->linenr);
 }
 
 /*
@@ -1243,7 +1626,7 @@ static int store_aux(const char *key, const char *value, void *cb)
        case KEY_SEEN:
                if (matches(key, value)) {
                        if (store.seen == 1 && store.multi_replace == 0) {
-                               warning("%s has multiple values", key);
+                               warning(_("%s has multiple values"), key);
                        }
 
                        ALLOC_GROW(store.offset, store.seen + 1,
@@ -1705,6 +2088,9 @@ int git_config_set_multivar_in_file(const char *config_filename,
        lock = NULL;
        ret = 0;
 
+       /* Invalidate the config cache */
+       git_config_clear();
+
 out_free:
        if (lock)
                rollback_lock_file(lock);
index 15ee15e98c2cb232e1e42315dc44f7efd87b4f1c..a2f380fd8dbb852ceeb4933b1b942e0e4803f44a 100644 (file)
@@ -89,8 +89,13 @@ ifeq ($(uname_S),Darwin)
        NEEDS_CRYPTO_WITH_SSL = YesPlease
        NEEDS_SSL_WITH_CRYPTO = YesPlease
        NEEDS_LIBICONV = YesPlease
+       # Note: $(uname_R) gives us the underlying Darwin version.
+       # - MacOS 10.0.* and MacOS 10.1.0 = Darwin 1.*
+       # - MacOS 10.x.* = Darwin (x+4).* for (1 <= x)
+       # i.e. "begins with [15678] and a dot" means "10.4.* or older".
        ifeq ($(shell expr "$(uname_R)" : '[15678]\.'),2)
                OLD_ICONV = UnfortunatelyYes
+               NO_APPLE_COMMON_CRYPTO = YesPlease
        endif
        ifeq ($(shell expr "$(uname_R)" : '[15]\.'),2)
                NO_STRLCPY = YesPlease
index 5047402a1aade7a443f55999550ae4542189ef01..87b52026326e8c0f0296e80d64c784888f719a8e 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -537,7 +537,8 @@ static struct child_process *git_proxy_connect(int fd[2], char *host)
 
        get_host_and_port(&host, &port);
 
-       proxy = xcalloc(1, sizeof(*proxy));
+       proxy = xmalloc(sizeof(*proxy));
+       child_process_init(proxy);
        argv_array_push(&proxy->args, git_proxy_command);
        argv_array_push(&proxy->args, host);
        argv_array_push(&proxy->args, port);
@@ -639,7 +640,7 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
        return protocol;
 }
 
-static struct child_process no_fork;
+static struct child_process no_fork = CHILD_PROCESS_INIT;
 
 /*
  * This returns a dummy child_process if the transport protocol does not
@@ -694,7 +695,8 @@ struct child_process *git_connect(int fd[2], const char *url,
                             target_host, 0);
                free(target_host);
        } else {
-               conn = xcalloc(1, sizeof(*conn));
+               conn = xmalloc(sizeof(*conn));
+               child_process_init(conn);
 
                strbuf_addstr(&cmd, prog);
                strbuf_addch(&cmd, ' ');
index dae9c9972eb3485bd20494efd78d09f1189667cb..299c56090bc38b1572b0ac03ec48532f40de605f 100644 (file)
@@ -25,7 +25,7 @@ static int check_everything_connected_real(sha1_iterate_fn fn,
                                           struct transport *transport,
                                           const char *shallow_file)
 {
-       struct child_process rev_list;
+       struct child_process rev_list = CHILD_PROCESS_INIT;
        const char *argv[9];
        char commit[41];
        unsigned char sha1[20];
@@ -60,7 +60,6 @@ static int check_everything_connected_real(sha1_iterate_fn fn,
                argv[ac++] = "--quiet";
        argv[ac] = NULL;
 
-       memset(&rev_list, 0, sizeof(rev_list));
        rev_list.argv = argv;
        rev_list.git_cmd = 1;
        rev_list.in = -1;
index 9d684b10a67ea663410db3ba68482c1a52bbc367..c5473dc8dba78b372fd95ef2bf5257ff5cdc3baf 100644 (file)
@@ -468,7 +468,8 @@ __git_ps1 ()
                        fi
                fi
                if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ] &&
-                  [ -r "$g/refs/stash" ]; then
+                  git rev-parse --verify --quiet refs/stash >/dev/null
+               then
                        s="$"
                fi
 
index d9a0ce2c6337b906617306f466139b5f486a753d..c2bd703ee3aa0fd734c71dc50c01085455d33773 100644 (file)
@@ -1,3 +1,6 @@
+# The default target of this Makefile is...
+all::
+
 -include ../../config.mak.autogen
 -include ../../config.mak
 
@@ -34,7 +37,7 @@ GIT_SUBTREE_XML := git-subtree.xml
 GIT_SUBTREE_TXT := git-subtree.txt
 GIT_SUBTREE_HTML := git-subtree.html
 
-all: $(GIT_SUBTREE)
+all:: $(GIT_SUBTREE)
 
 $(GIT_SUBTREE): $(GIT_SUBTREE_SH)
        sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' $< >$@
index cb5fbb45ea04cead65316ecf6b44730b17108122..aa7a139bcf7f3d33511e106545e6d8989a0ffe35 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -321,7 +321,7 @@ static int filter_buffer(int in, int out, void *data)
        /*
         * Spawn cmd and feed the buffer contents through its stdin.
         */
-       struct child_process child_process;
+       struct child_process child_process = CHILD_PROCESS_INIT;
        struct filter_params *params = (struct filter_params *)data;
        int write_err, status;
        const char *argv[] = { NULL, NULL };
@@ -344,7 +344,6 @@ static int filter_buffer(int in, int out, void *data)
 
        argv[0] = cmd.buf;
 
-       memset(&child_process, 0, sizeof(child_process));
        child_process.argv = argv;
        child_process.use_shell = 1;
        child_process.in = -1;
index 9a03792c7de109e957a1f01924c4f66ba87b5c87..8689a1519a5635a1d92e9e4106936b4159d2e106 100644 (file)
@@ -37,12 +37,11 @@ static int send_request(const char *socket, const struct strbuf *out)
 
 static void spawn_daemon(const char *socket)
 {
-       struct child_process daemon;
+       struct child_process daemon = CHILD_PROCESS_INIT;
        const char *argv[] = { NULL, NULL, NULL };
        char buf[128];
        int r;
 
-       memset(&daemon, 0, sizeof(daemon));
        argv[0] = "git-credential-cache--daemon";
        argv[1] = socket;
        daemon.argv = argv;
index 4d79d320f89e956aa9233a170120f05b2473ca59..1886ea50b3b3c2a213e34876de691fa3d0a83b6c 100644 (file)
@@ -205,11 +205,10 @@ static int run_credential_helper(struct credential *c,
                                 const char *cmd,
                                 int want_output)
 {
-       struct child_process helper;
+       struct child_process helper = CHILD_PROCESS_INIT;
        const char *argv[] = { NULL, NULL };
        FILE *fp;
 
-       memset(&helper, 0, sizeof(helper));
        argv[0] = cmd;
        helper.argv = argv;
        helper.use_shell = 1;
index e6b51ed9981f2e4084504a2a092a3f28fc7d4c8a..4dcfff9352c8d034bfaec4efa0c36df41e7813a7 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -230,23 +230,6 @@ struct daemon_service {
        int overridable;
 };
 
-static struct daemon_service *service_looking_at;
-static int service_enabled;
-
-static int git_daemon_config(const char *var, const char *value, void *cb)
-{
-       const char *service;
-
-       if (skip_prefix(var, "daemon.", &service) &&
-           !strcmp(service, service_looking_at->config_name)) {
-               service_enabled = git_config_bool(var, value);
-               return 0;
-       }
-
-       /* we are not interested in parsing any other configuration here */
-       return 0;
-}
-
 static int daemon_error(const char *dir, const char *msg)
 {
        if (!informative_errors)
@@ -259,7 +242,7 @@ static const char *access_hook;
 
 static int run_access_hook(struct daemon_service *service, const char *dir, const char *path)
 {
-       struct child_process child;
+       struct child_process child = CHILD_PROCESS_INIT;
        struct strbuf buf = STRBUF_INIT;
        const char *argv[8];
        const char **arg = argv;
@@ -277,7 +260,6 @@ static int run_access_hook(struct daemon_service *service, const char *dir, cons
        *arg = NULL;
 #undef STRARG
 
-       memset(&child, 0, sizeof(child));
        child.use_shell = 1;
        child.argv = argv;
        child.no_stdin = 1;
@@ -324,6 +306,7 @@ static int run_service(const char *dir, struct daemon_service *service)
 {
        const char *path;
        int enabled = service->enabled;
+       struct strbuf var = STRBUF_INIT;
 
        loginfo("Request %s for '%s'", service->name, dir);
 
@@ -354,11 +337,9 @@ static int run_service(const char *dir, struct daemon_service *service)
        }
 
        if (service->overridable) {
-               service_looking_at = service;
-               service_enabled = -1;
-               git_config(git_daemon_config, NULL);
-               if (0 <= service_enabled)
-                       enabled = service_enabled;
+               strbuf_addf(&var, "daemon.%s", service->config_name);
+               git_config_get_bool(var.buf, &enabled);
+               strbuf_release(&var);
        }
        if (!enabled) {
                logerror("'%s': service not enabled for '%s'",
@@ -406,9 +387,8 @@ static void copy_to_log(int fd)
 
 static int run_service_command(const char **argv)
 {
-       struct child_process cld;
+       struct child_process cld = CHILD_PROCESS_INIT;
 
-       memset(&cld, 0, sizeof(cld));
        cld.argv = argv;
        cld.git_cmd = 1;
        cld.err = -1;
@@ -733,7 +713,7 @@ static void check_dead_children(void)
 static char **cld_argv;
 static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
 {
-       struct child_process cld = { NULL };
+       struct child_process cld = CHILD_PROCESS_INIT;
        char addrbuf[300] = "REMOTE_ADDR=", portbuf[300];
        char *env[] = { addrbuf, portbuf, NULL };
 
diff --git a/diff.c b/diff.c
index 867f034b8ffc052d28f28a86fd9f52a5aa5b2c82..d7a5c81bb8545584ce5fe652dc42f2ee8bc1e2fd 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -376,7 +376,7 @@ static unsigned long diff_filespec_size(struct diff_filespec *one)
 {
        if (!DIFF_FILE_VALID(one))
                return 0;
-       diff_populate_filespec(one, 1);
+       diff_populate_filespec(one, CHECK_SIZE_ONLY);
        return one->size;
 }
 
@@ -1910,11 +1910,11 @@ static void show_dirstat(struct diff_options *options)
                        diff_free_filespec_data(p->one);
                        diff_free_filespec_data(p->two);
                } else if (DIFF_FILE_VALID(p->one)) {
-                       diff_populate_filespec(p->one, 1);
+                       diff_populate_filespec(p->one, CHECK_SIZE_ONLY);
                        copied = added = 0;
                        diff_free_filespec_data(p->one);
                } else if (DIFF_FILE_VALID(p->two)) {
-                       diff_populate_filespec(p->two, 1);
+                       diff_populate_filespec(p->two, CHECK_SIZE_ONLY);
                        copied = 0;
                        added = p->two->size;
                        diff_free_filespec_data(p->two);
@@ -2188,8 +2188,8 @@ int diff_filespec_is_binary(struct diff_filespec *one)
                        one->is_binary = one->driver->binary;
                else {
                        if (!one->data && DIFF_FILE_VALID(one))
-                               diff_populate_filespec(one, 0);
-                       if (one->data)
+                               diff_populate_filespec(one, CHECK_BINARY);
+                       if (one->is_binary == -1 && one->data)
                                one->is_binary = buffer_is_binary(one->data,
                                                one->size);
                        if (one->is_binary == -1)
@@ -2324,6 +2324,19 @@ static void builtin_diff(const char *name_a,
        } else if (!DIFF_OPT_TST(o, TEXT) &&
            ( (!textconv_one && diff_filespec_is_binary(one)) ||
              (!textconv_two && diff_filespec_is_binary(two)) )) {
+               if (!one->data && !two->data &&
+                   S_ISREG(one->mode) && S_ISREG(two->mode) &&
+                   !DIFF_OPT_TST(o, BINARY)) {
+                       if (!hashcmp(one->sha1, two->sha1)) {
+                               if (must_show_header)
+                                       fprintf(o->file, "%s", header.buf);
+                               goto free_ab_and_return;
+                       }
+                       fprintf(o->file, "%s", header.buf);
+                       fprintf(o->file, "%sBinary files %s and %s differ\n",
+                               line_prefix, lbl[0], lbl[1]);
+                       goto free_ab_and_return;
+               }
                if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
                        die("unable to read files to diff");
                /* Quite common confusing case */
@@ -2668,8 +2681,9 @@ static int diff_populate_gitlink(struct diff_filespec *s, int size_only)
  * grab the data for the blob (or file) for our own in-core comparison.
  * diff_filespec has data and size fields for this purpose.
  */
-int diff_populate_filespec(struct diff_filespec *s, int size_only)
+int diff_populate_filespec(struct diff_filespec *s, unsigned int flags)
 {
+       int size_only = flags & CHECK_SIZE_ONLY;
        int err = 0;
        /*
         * demote FAIL to WARN to allow inspecting the situation
@@ -2724,6 +2738,11 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
                }
                if (size_only)
                        return 0;
+               if ((flags & CHECK_BINARY) &&
+                   s->size > big_file_threshold && s->is_binary == -1) {
+                       s->is_binary = 1;
+                       return 0;
+               }
                fd = open(s->path, O_RDONLY);
                if (fd < 0)
                        goto err_empty;
@@ -2745,16 +2764,21 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
        }
        else {
                enum object_type type;
-               if (size_only) {
+               if (size_only || (flags & CHECK_BINARY)) {
                        type = sha1_object_info(s->sha1, &s->size);
                        if (type < 0)
                                die("unable to read %s", sha1_to_hex(s->sha1));
-               } else {
-                       s->data = read_sha1_file(s->sha1, &type, &s->size);
-                       if (!s->data)
-                               die("unable to read %s", sha1_to_hex(s->sha1));
-                       s->should_free = 1;
+                       if (size_only)
+                               return 0;
+                       if (s->size > big_file_threshold && s->is_binary == -1) {
+                               s->is_binary = 1;
+                               return 0;
+                       }
                }
+               s->data = read_sha1_file(s->sha1, &type, &s->size);
+               if (!s->data)
+                       die("unable to read %s", sha1_to_hex(s->sha1));
+               s->should_free = 1;
        }
        return 0;
 }
@@ -4688,8 +4712,8 @@ static int diff_filespec_check_stat_unmatch(struct diff_filepair *p)
            !DIFF_FILE_VALID(p->two) ||
            (p->one->sha1_valid && p->two->sha1_valid) ||
            (p->one->mode != p->two->mode) ||
-           diff_populate_filespec(p->one, 1) ||
-           diff_populate_filespec(p->two, 1) ||
+           diff_populate_filespec(p->one, CHECK_SIZE_ONLY) ||
+           diff_populate_filespec(p->two, CHECK_SIZE_ONLY) ||
            (p->one->size != p->two->size) ||
            !diff_filespec_is_identical(p->one, p->two)) /* (2) */
                p->skip_stat_unmatch_result = 1;
@@ -4931,7 +4955,7 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec,
        struct diff_tempfile *temp;
        const char *argv[3];
        const char **arg = argv;
-       struct child_process child;
+       struct child_process child = CHILD_PROCESS_INIT;
        struct strbuf buf = STRBUF_INIT;
        int err = 0;
 
@@ -4940,7 +4964,6 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec,
        *arg++ = temp->name;
        *arg = NULL;
 
-       memset(&child, 0, sizeof(child));
        child.use_shell = 1;
        child.argv = argv;
        child.out = -1;
index 2e44a3745939bb75841730ba0cff78ea872df8d9..4e132f1fdb68ed3c930ca8224a5403c9b406cc3b 100644 (file)
@@ -147,9 +147,11 @@ static int estimate_similarity(struct diff_filespec *src,
         * is a possible size - we really should have a flag to
         * say whether the size is valid or not!)
         */
-       if (!src->cnt_data && diff_populate_filespec(src, 1))
+       if (!src->cnt_data &&
+           diff_populate_filespec(src, CHECK_SIZE_ONLY))
                return 0;
-       if (!dst->cnt_data && diff_populate_filespec(dst, 1))
+       if (!dst->cnt_data &&
+           diff_populate_filespec(dst, CHECK_SIZE_ONLY))
                return 0;
 
        max_size = ((src->size > dst->size) ? src->size : dst->size);
index c876dac71a585abb1e138444eb28258e3bf6d7e8..33ea2de348803b29a08a6713ae4cab1345f874d9 100644 (file)
@@ -55,7 +55,9 @@ extern void free_filespec(struct diff_filespec *);
 extern void fill_filespec(struct diff_filespec *, const unsigned char *,
                          int, unsigned short);
 
-extern int diff_populate_filespec(struct diff_filespec *, int);
+#define CHECK_SIZE_ONLY 1
+#define CHECK_BINARY    2
+extern int diff_populate_filespec(struct diff_filespec *, unsigned int);
 extern void diff_free_filespec_data(struct diff_filespec *);
 extern void diff_free_filespec_blob(struct diff_filespec *);
 extern int diff_filespec_is_binary(struct diff_filespec *);
diff --git a/dir.c b/dir.c
index fcb68729b1f559008e1797ff50f38acf81268d3d..bd274a73f1faaee40bce34024ef17bfd44fbcad7 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -1507,12 +1507,16 @@ int dir_inside_of(const char *subdir, const char *dir)
 
 int is_inside_dir(const char *dir)
 {
-       char cwd[PATH_MAX];
+       char *cwd;
+       int rc;
+
        if (!dir)
                return 0;
-       if (!getcwd(cwd, sizeof(cwd)))
-               die_errno("can't find the current directory");
-       return dir_inside_of(cwd, dir) >= 0;
+
+       cwd = xgetcwd();
+       rc = (dir_inside_of(cwd, dir) >= 0);
+       free(cwd);
+       return rc;
 }
 
 int is_empty_dir(const char *path)
index 0abbd8dc3a0ec91acd0c143b6d9b5ad41ac90417..01c644cddbe8e57e31cc711aa0ca3838cf23c64d 100644 (file)
--- a/editor.c
+++ b/editor.c
@@ -38,10 +38,9 @@ int launch_editor(const char *path, struct strbuf *buffer, const char *const *en
 
        if (strcmp(editor, ":")) {
                const char *args[] = { editor, real_path(path), NULL };
-               struct child_process p;
+               struct child_process p = CHILD_PROCESS_INIT;
                int ret, sig;
 
-               memset(&p, 0, sizeof(p));
                p.argv = args;
                p.env = env;
                p.use_shell = 1;
index 125fa6fabf503d29cb82b2ccbc92359abf95b0e8..698e7526c40749fd333367018c192537cf6b4562 100644 (file)
@@ -86,11 +86,7 @@ const char *git_exec_path(void)
 static void add_path(struct strbuf *out, const char *path)
 {
        if (path && *path) {
-               if (is_absolute_path(path))
-                       strbuf_addstr(out, path);
-               else
-                       strbuf_addstr(out, absolute_path(path));
-
+               strbuf_add_absolute_path(out, path);
                strbuf_addch(out, PATH_SEP);
        }
 }
index d73f58cbe3fe4522fa24d47f9086d927b3296c8b..c071253c90807b6fa98771e9fd046fed12bb7b4b 100644 (file)
@@ -946,10 +946,12 @@ static void unkeep_all_packs(void)
 
 static void end_packfile(void)
 {
-       struct packed_git *old_p = pack_data, *new_p;
+       if (!pack_data)
+               return;
 
        clear_delta_base_cache();
        if (object_count) {
+               struct packed_git *new_p;
                unsigned char cur_pack_sha1[20];
                char *idx_name;
                int i;
@@ -991,10 +993,11 @@ static void end_packfile(void)
                pack_id++;
        }
        else {
-               close(old_p->pack_fd);
-               unlink_or_warn(old_p->pack_name);
+               close(pack_data->pack_fd);
+               unlink_or_warn(pack_data->pack_name);
        }
-       free(old_p);
+       free(pack_data);
+       pack_data = NULL;
 
        /* We can't carry a delta across packfiles. */
        strbuf_release(&last_blob.data);
@@ -1679,8 +1682,9 @@ static int tree_content_get(
 static int update_branch(struct branch *b)
 {
        static const char *msg = "fast-import";
-       struct ref_lock *lock;
+       struct ref_transaction *transaction;
        unsigned char old_sha1[20];
+       struct strbuf err = STRBUF_INIT;
 
        if (read_ref(b->name, old_sha1))
                hashclr(old_sha1);
@@ -1689,29 +1693,33 @@ static int update_branch(struct branch *b)
                        delete_ref(b->name, old_sha1, 0);
                return 0;
        }
-       lock = lock_any_ref_for_update(b->name, old_sha1, 0, NULL);
-       if (!lock)
-               return error("Unable to lock %s", b->name);
        if (!force_update && !is_null_sha1(old_sha1)) {
                struct commit *old_cmit, *new_cmit;
 
                old_cmit = lookup_commit_reference_gently(old_sha1, 0);
                new_cmit = lookup_commit_reference_gently(b->sha1, 0);
-               if (!old_cmit || !new_cmit) {
-                       unlock_ref(lock);
+               if (!old_cmit || !new_cmit)
                        return error("Branch %s is missing commits.", b->name);
-               }
 
                if (!in_merge_bases(old_cmit, new_cmit)) {
-                       unlock_ref(lock);
                        warning("Not updating %s"
                                " (new tip %s does not contain %s)",
                                b->name, sha1_to_hex(b->sha1), sha1_to_hex(old_sha1));
                        return -1;
                }
        }
-       if (write_ref_sha1(lock, b->sha1, msg) < 0)
-               return error("Unable to update %s", b->name);
+       transaction = ref_transaction_begin(&err);
+       if (!transaction ||
+           ref_transaction_update(transaction, b->name, b->sha1, old_sha1,
+                                  0, 1, &err) ||
+           ref_transaction_commit(transaction, msg, &err)) {
+               ref_transaction_free(transaction);
+               error("%s", err.buf);
+               strbuf_release(&err);
+               return -1;
+       }
+       ref_transaction_free(transaction);
+       strbuf_release(&err);
        return 0;
 }
 
@@ -1730,15 +1738,32 @@ static void dump_tags(void)
 {
        static const char *msg = "fast-import";
        struct tag *t;
-       struct ref_lock *lock;
-       char ref_name[PATH_MAX];
+       struct strbuf ref_name = STRBUF_INIT;
+       struct strbuf err = STRBUF_INIT;
+       struct ref_transaction *transaction;
 
+       transaction = ref_transaction_begin(&err);
+       if (!transaction) {
+               failure |= error("%s", err.buf);
+               goto cleanup;
+       }
        for (t = first_tag; t; t = t->next_tag) {
-               sprintf(ref_name, "tags/%s", t->name);
-               lock = lock_ref_sha1(ref_name, NULL);
-               if (!lock || write_ref_sha1(lock, t->sha1, msg) < 0)
-                       failure |= error("Unable to update %s", ref_name);
+               strbuf_reset(&ref_name);
+               strbuf_addf(&ref_name, "refs/tags/%s", t->name);
+
+               if (ref_transaction_update(transaction, ref_name.buf, t->sha1,
+                                          NULL, 0, 0, &err)) {
+                       failure |= error("%s", err.buf);
+                       goto cleanup;
+               }
        }
+       if (ref_transaction_commit(transaction, msg, &err))
+               failure |= error("%s", err.buf);
+
+ cleanup:
+       ref_transaction_free(transaction);
+       strbuf_release(&ref_name);
+       strbuf_release(&err);
 }
 
 static void dump_marks_helper(FILE *f,
@@ -3274,36 +3299,34 @@ static void parse_option(const char *option)
        die("This version of fast-import does not support option: %s", option);
 }
 
-static int git_pack_config(const char *k, const char *v, void *cb)
+static void git_pack_config(void)
 {
-       if (!strcmp(k, "pack.depth")) {
-               max_depth = git_config_int(k, v);
+       int indexversion_value;
+       unsigned long packsizelimit_value;
+
+       if (!git_config_get_ulong("pack.depth", &max_depth)) {
                if (max_depth > MAX_DEPTH)
                        max_depth = MAX_DEPTH;
-               return 0;
        }
-       if (!strcmp(k, "pack.compression")) {
-               int level = git_config_int(k, v);
-               if (level == -1)
-                       level = Z_DEFAULT_COMPRESSION;
-               else if (level < 0 || level > Z_BEST_COMPRESSION)
-                       die("bad pack compression level %d", level);
-               pack_compression_level = level;
+       if (!git_config_get_int("pack.compression", &pack_compression_level)) {
+               if (pack_compression_level == -1)
+                       pack_compression_level = Z_DEFAULT_COMPRESSION;
+               else if (pack_compression_level < 0 ||
+                        pack_compression_level > Z_BEST_COMPRESSION)
+                       git_die_config("pack.compression",
+                                       "bad pack compression level %d", pack_compression_level);
                pack_compression_seen = 1;
-               return 0;
        }
-       if (!strcmp(k, "pack.indexversion")) {
-               pack_idx_opts.version = git_config_int(k, v);
+       if (!git_config_get_int("pack.indexversion", &indexversion_value)) {
+               pack_idx_opts.version = indexversion_value;
                if (pack_idx_opts.version > 2)
-                       die("bad pack.indexversion=%"PRIu32,
-                           pack_idx_opts.version);
-               return 0;
-       }
-       if (!strcmp(k, "pack.packsizelimit")) {
-               max_packsize = git_config_ulong(k, v);
-               return 0;
+                       git_die_config("pack.indexversion",
+                                       "bad pack.indexversion=%"PRIu32, pack_idx_opts.version);
        }
-       return git_default_config(k, v, cb);
+       if (!git_config_get_ulong("pack.packsizelimit", &packsizelimit_value))
+               max_packsize = packsizelimit_value;
+
+       git_config(git_default_config, NULL);
 }
 
 static const char fast_import_usage[] =
@@ -3356,7 +3379,7 @@ int main(int argc, char **argv)
 
        setup_git_directory();
        reset_pack_idx_option(&pack_idx_opts);
-       git_config(git_pack_config, NULL);
+       git_pack_config();
        if (!pack_compression_seen && core_compression_seen)
                pack_compression_level = core_compression_level;
 
index b8a58fa7a542fe166ad71c9b17a4908c81d24a4f..7487aa730630e8b45874e3487db8e71c05e1968c 100644 (file)
@@ -666,7 +666,7 @@ static int get_pack(struct fetch_pack_args *args,
        char hdr_arg[256];
        const char **av, *cmd_name;
        int do_keep = args->keep_pack;
-       struct child_process cmd;
+       struct child_process cmd = CHILD_PROCESS_INIT;
        int ret;
 
        memset(&demux, 0, sizeof(demux));
@@ -685,7 +685,6 @@ static int get_pack(struct fetch_pack_args *args,
        else
                demux.out = xd[0];
 
-       memset(&cmd, 0, sizeof(cmd));
        cmd.argv = argv;
        av = argv;
        *hdr_arg = 0;
@@ -869,34 +868,15 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
        return ref;
 }
 
-static int fetch_pack_config(const char *var, const char *value, void *cb)
+static void fetch_pack_config(void)
 {
-       if (strcmp(var, "fetch.unpacklimit") == 0) {
-               fetch_unpack_limit = git_config_int(var, value);
-               return 0;
-       }
-
-       if (strcmp(var, "transfer.unpacklimit") == 0) {
-               transfer_unpack_limit = git_config_int(var, value);
-               return 0;
-       }
-
-       if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
-               prefer_ofs_delta = git_config_bool(var, value);
-               return 0;
-       }
-
-       if (!strcmp(var, "fetch.fsckobjects")) {
-               fetch_fsck_objects = git_config_bool(var, value);
-               return 0;
-       }
-
-       if (!strcmp(var, "transfer.fsckobjects")) {
-               transfer_fsck_objects = git_config_bool(var, value);
-               return 0;
-       }
+       git_config_get_int("fetch.unpacklimit", &fetch_unpack_limit);
+       git_config_get_int("transfer.unpacklimit", &transfer_unpack_limit);
+       git_config_get_bool("repack.usedeltabaseoffset", &prefer_ofs_delta);
+       git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects);
+       git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects);
 
-       return git_default_config(var, value, cb);
+       git_config(git_default_config, NULL);
 }
 
 static void fetch_pack_setup(void)
@@ -904,7 +884,7 @@ static void fetch_pack_setup(void)
        static int did_setup;
        if (did_setup)
                return;
-       git_config(fetch_pack_config, NULL);
+       fetch_pack_config();
        if (0 <= transfer_unpack_limit)
                unpack_limit = transfer_unpack_limit;
        else if (0 <= fetch_unpack_limit)
index f587749b7cf6a74be376792eb0ad70b7e5e4f597..4e7e3f8726a26a1f7dfbb889fe3531d01d4419b9 100644 (file)
@@ -264,19 +264,35 @@ extern char *gitbasename(char *);
 #endif
 
 #ifndef has_dos_drive_prefix
-#define has_dos_drive_prefix(path) 0
+static inline int git_has_dos_drive_prefix(const char *path)
+{
+       return 0;
+}
+#define has_dos_drive_prefix git_has_dos_drive_prefix
 #endif
 
-#ifndef offset_1st_component
-#define offset_1st_component(path) (is_dir_sep((path)[0]))
+#ifndef is_dir_sep
+static inline int git_is_dir_sep(int c)
+{
+       return c == '/';
+}
+#define is_dir_sep git_is_dir_sep
 #endif
 
-#ifndef is_dir_sep
-#define is_dir_sep(c) ((c) == '/')
+#ifndef offset_1st_component
+static inline int git_offset_1st_component(const char *path)
+{
+       return is_dir_sep(path[0]);
+}
+#define offset_1st_component git_offset_1st_component
 #endif
 
 #ifndef find_last_dir_sep
-#define find_last_dir_sep(path) strrchr(path, '/')
+static inline char *git_find_last_dir_sep(const char *path)
+{
+       return strrchr(path, '/');
+}
+#define find_last_dir_sep git_find_last_dir_sep
 #endif
 
 #if defined(__HP_cc) && (__HP_cc >= 61000)
@@ -593,6 +609,7 @@ extern try_to_free_t set_try_to_free_routine(try_to_free_t);
 extern char *xstrdup(const char *str);
 extern void *xmalloc(size_t size);
 extern void *xmallocz(size_t size);
+extern void *xmallocz_gently(size_t size);
 extern void *xmemdupz(const void *data, size_t len);
 extern char *xstrndup(const char *str, size_t len);
 extern void *xrealloc(void *ptr, size_t size);
@@ -607,6 +624,7 @@ extern int xmkstemp(char *template);
 extern int xmkstemp_mode(char *template, int mode);
 extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
 extern int odb_pack_keep(char *name, size_t namesz, const unsigned char *sha1);
+extern char *xgetcwd(void);
 
 static inline size_t xsize_t(off_t len)
 {
index 18a394fcc4e704621c8b5e8bc92b7cbee2fd21fe..4d4fc77b05648c7d2d76ae932b7d68cdf411d364 100755 (executable)
@@ -20,7 +20,7 @@ die_conflict () {
     if [ $(git config --bool --get advice.resolveConflict || echo true) = "true" ]; then
        die "$(gettext "Pull is not possible because you have unmerged files.
 Please, fix them up in the work tree, and then use 'git add/rm <file>'
-as appropriate to mark resolution, or use 'git commit -a'.")"
+as appropriate to mark resolution and make a commit.")"
     else
        die "$(gettext "Pull is not possible because you have unmerged files.")"
     fi
index bcc757b3900b02595e5b432edcfd590e312b48ce..9c1ba8e4b81a1f118af1967c2c72795ba12d6df0 100755 (executable)
@@ -297,7 +297,7 @@ have_stash () {
 
 list_stash () {
        have_stash || return 0
-       git log --format="%gd: %gs" -g "$@" $ref_stash --
+       git log --format="%gd: %gs" -g --first-parent -m "$@" $ref_stash --
 }
 
 show_stash () {
index 0a323722a601b2cb900385e531d315558b6d3fe9..b6e2186cef0fcddc7c7b82378b07941d9f671a92 100755 (executable)
@@ -260,8 +260,8 @@ sub _req_svn {
                        } ],
        'find-rev' => [ \&cmd_find_rev,
                        "Translate between SVN revision numbers and tree-ish",
-                       { 'before' => \$_before,
-                         'after' => \$_after } ],
+                       { 'B|before' => \$_before,
+                         'A|after' => \$_after } ],
        'rebase' => [ \&cmd_rebase, "Fetch and rebase your working directory",
                        { 'merge|m|M' => \$_merge,
                          'verbose|v' => \$_verbose,
@@ -306,13 +306,16 @@ sub readline {
 }
 package main;
 
-my $term = eval {
-       $ENV{"GIT_SVN_NOTTY"}
-               ? new Term::ReadLine 'git-svn', \*STDIN, \*STDOUT
-               : new Term::ReadLine 'git-svn';
-};
-if ($@) {
-       $term = new FakeTerm "$@: going non-interactive";
+my $term;
+sub term_init {
+       $term = eval {
+               $ENV{"GIT_SVN_NOTTY"}
+                       ? new Term::ReadLine 'git-svn', \*STDIN, \*STDOUT
+                       : new Term::ReadLine 'git-svn';
+       };
+       if ($@) {
+               $term = new FakeTerm "$@: going non-interactive";
+       }
 }
 
 my $cmd;
@@ -424,6 +427,7 @@ sub ask {
        my $default = $arg{default};
        my $resp;
        my $i = 0;
+       term_init() unless $term;
 
        if ( !( defined($term->IN)
             && defined( fileno($term->IN) )
@@ -1161,7 +1165,9 @@ sub cmd_branch {
        ::_req_svn();
 
        my $ctx = SVN::Client->new(
-               auth    => Git::SVN::Ra::_auth_providers(),
+               config => SVN::Core::config_get_config(
+                       $Git::SVN::Ra::config_dir
+               ),
                log_msg => sub {
                        ${ $_[0] } = defined $_message
                                ? $_message
@@ -1475,10 +1481,37 @@ sub cmd_commit_diff {
        }
 }
 
-
 sub cmd_info {
-       my $path = canonicalize_path(defined($_[0]) ? $_[0] : ".");
-       my $fullpath = canonicalize_path($cmd_dir_prefix . $path);
+       my $path_arg = defined($_[0]) ? $_[0] : '.';
+       my $path = $path_arg;
+       if (File::Spec->file_name_is_absolute($path)) {
+               $path = canonicalize_path($path);
+
+               my $toplevel = eval {
+                       my @cmd = qw/rev-parse --show-toplevel/;
+                       command_oneline(\@cmd, STDERR => 0);
+               };
+
+               # remove $toplevel from the absolute path:
+               my ($vol, $dirs, $file) = File::Spec->splitpath($path);
+               my (undef, $tdirs, $tfile) = File::Spec->splitpath($toplevel);
+               my @dirs = File::Spec->splitdir($dirs);
+               my @tdirs = File::Spec->splitdir($tdirs);
+               pop @dirs if $dirs[-1] eq '';
+               pop @tdirs if $tdirs[-1] eq '';
+               push @dirs, $file;
+               push @tdirs, $tfile;
+               while (@tdirs && @dirs && $tdirs[0] eq $dirs[0]) {
+                       shift @dirs;
+                       shift @tdirs;
+               }
+               $dirs = File::Spec->catdir(@dirs);
+               $path = File::Spec->catpath($vol, $dirs);
+
+               $path = canonicalize_path($path);
+       } else {
+               $path = canonicalize_path($cmd_dir_prefix . $path);
+       }
        if (exists $_[1]) {
                die "Too many arguments specified\n";
        }
@@ -1499,14 +1532,14 @@ sub cmd_info {
        # canonicalize_path() will return "" to make libsvn 1.5.x happy,
        $path = "." if $path eq "";
 
-       my $full_url = canonicalize_url( add_path_to_url( $url, $fullpath ) );
+       my $full_url = canonicalize_url( add_path_to_url( $url, $path ) );
 
        if ($_url) {
                print "$full_url\n";
                return;
        }
 
-       my $result = "Path: $path\n";
+       my $result = "Path: $path_arg\n";
        $result .= "Name: " . basename($path) . "\n" if $file_type ne "dir";
        $result .= "URL: $full_url\n";
 
@@ -1537,7 +1570,7 @@ sub cmd_info {
        }
 
        my ($lc_author, $lc_rev, $lc_date_utc);
-       my @args = Git::SVN::Log::git_svn_log_cmd($rev, $rev, "--", $fullpath);
+       my @args = Git::SVN::Log::git_svn_log_cmd($rev, $rev, "--", $path);
        my $log = command_output_pipe(@args);
        my $esc_color = qr/(?:\033\[(?:(?:\d+;)*\d*)?m)*/;
        while (<$log>) {
diff --git a/git.c b/git.c
index 9c495198317bf31ff40785a48bf0a44253548098..210f1ae9d04dda4d16f9f072ef710bf630f6d52e 100644 (file)
--- a/git.c
+++ b/git.c
@@ -20,7 +20,7 @@ const char git_more_info_string[] =
 
 static struct startup_info git_startup_info;
 static int use_pager = -1;
-static char orig_cwd[PATH_MAX];
+static char *orig_cwd;
 static const char *env_names[] = {
        GIT_DIR_ENVIRONMENT,
        GIT_WORK_TREE_ENVIRONMENT,
@@ -36,8 +36,7 @@ static void save_env(void)
        if (saved_environment)
                return;
        saved_environment = 1;
-       if (!getcwd(orig_cwd, sizeof(orig_cwd)))
-               die_errno("cannot getcwd");
+       orig_cwd = xgetcwd();
        for (i = 0; i < ARRAY_SIZE(env_names); i++) {
                orig_env[i] = getenv(env_names[i]);
                if (orig_env[i])
@@ -48,8 +47,9 @@ static void save_env(void)
 static void restore_env(void)
 {
        int i;
-       if (*orig_cwd && chdir(orig_cwd))
+       if (orig_cwd && chdir(orig_cwd))
                die_errno("could not move to %s", orig_cwd);
+       free(orig_cwd);
        for (i = 0; i < ARRAY_SIZE(env_names); i++) {
                if (orig_env[i])
                        setenv(env_names[i], orig_env[i], 1);
@@ -161,9 +161,10 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
                        if (envchanged)
                                *envchanged = 1;
                } else if (!strcmp(cmd, "--bare")) {
-                       static char git_dir[PATH_MAX+1];
+                       char *cwd = xgetcwd();
                        is_bare_repository_cfg = 1;
-                       setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
+                       setenv(GIT_DIR_ENVIRONMENT, cwd, 0);
+                       free(cwd);
                        setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
                        if (envchanged)
                                *envchanged = 1;
index ff07012726ea28daa2551966d0555d2e8efa2375..1ef73fb7dfedd8cd5d3444433218ff177a63111b 100644 (file)
@@ -55,12 +55,11 @@ const char *get_signing_key(void)
  */
 int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key)
 {
-       struct child_process gpg;
+       struct child_process gpg = CHILD_PROCESS_INIT;
        const char *args[4];
        ssize_t len;
        size_t i, j, bottom;
 
-       memset(&gpg, 0, sizeof(gpg));
        gpg.argv = args;
        gpg.in = -1;
        gpg.out = -1;
@@ -116,7 +115,7 @@ int verify_signed_buffer(const char *payload, size_t payload_size,
                         const char *signature, size_t signature_size,
                         struct strbuf *gpg_output, struct strbuf *gpg_status)
 {
-       struct child_process gpg;
+       struct child_process gpg = CHILD_PROCESS_INIT;
        const char *args_gpg[] = {NULL, "--status-fd=1", "--verify", "FILE", "-", NULL};
        char path[PATH_MAX];
        int fd, ret;
@@ -133,7 +132,6 @@ int verify_signed_buffer(const char *payload, size_t payload_size,
                             path, strerror(errno));
        close(fd);
 
-       memset(&gpg, 0, sizeof(gpg));
        gpg.argv = args_gpg;
        gpg.in = -1;
        gpg.out = -1;
index 80790bbaef95a56ac737c7763e48035e3e0754ee..404e682593ecfca218d0aee0634f5c21356ef69c 100644 (file)
@@ -219,29 +219,22 @@ static void get_idx_file(char *name)
        send_local_file("application/x-git-packed-objects-toc", name);
 }
 
-static int http_config(const char *var, const char *value, void *cb)
+static void http_config(void)
 {
-       const char *p;
+       int i, value = 0;
+       struct strbuf var = STRBUF_INIT;
 
-       if (!strcmp(var, "http.getanyfile")) {
-               getanyfile = git_config_bool(var, value);
-               return 0;
-       }
+       git_config_get_bool("http.getanyfile", &getanyfile);
 
-       if (skip_prefix(var, "http.", &p)) {
-               int i;
-
-               for (i = 0; i < ARRAY_SIZE(rpc_service); i++) {
-                       struct rpc_service *svc = &rpc_service[i];
-                       if (!strcmp(p, svc->config_name)) {
-                               svc->enabled = git_config_bool(var, value);
-                               return 0;
-                       }
-               }
+       for (i = 0; i < ARRAY_SIZE(rpc_service); i++) {
+               struct rpc_service *svc = &rpc_service[i];
+               strbuf_addf(&var, "http.%s", svc->config_name);
+               if (!git_config_get_bool(var.buf, &value))
+                       svc->enabled = value;
+               strbuf_reset(&var);
        }
 
-       /* we are not interested in parsing any other configuration here */
-       return 0;
+       strbuf_release(&var);
 }
 
 static struct rpc_service *select_service(const char *name)
@@ -323,7 +316,7 @@ static void run_service(const char **argv)
        const char *host = getenv("REMOTE_ADDR");
        struct argv_array env = ARGV_ARRAY_INIT;
        int gzipped_request = 0;
-       struct child_process cld;
+       struct child_process cld = CHILD_PROCESS_INIT;
 
        if (encoding && !strcmp(encoding, "gzip"))
                gzipped_request = 1;
@@ -341,7 +334,6 @@ static void run_service(const char **argv)
                argv_array_pushf(&env, "GIT_COMMITTER_EMAIL=%s@http.%s",
                                 user, host);
 
-       memset(&cld, 0, sizeof(cld));
        cld.argv = argv;
        cld.env = env.argv;
        if (gzipped_request)
@@ -627,7 +619,7 @@ int main(int argc, char **argv)
            access("git-daemon-export-ok", F_OK) )
                not_found("Repository not exported: '%s'", dir);
 
-       git_config(http_config, NULL);
+       http_config();
        cmd->imp(cmd_arg);
        return 0;
 }
diff --git a/http.c b/http.c
index c8cd50dd0c2b2213a86957cd4b24c03c0d85717d..0adcec4683f997044807a772713d476dd77cf105 100644 (file)
--- a/http.c
+++ b/http.c
@@ -300,6 +300,9 @@ static CURL *get_curl_handle(void)
 {
        CURL *result = curl_easy_init();
 
+       if (!result)
+               die("curl_easy_init failed");
+
        if (!curl_ssl_verify) {
                curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, 0);
                curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 0);
@@ -399,7 +402,8 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
        git_config(urlmatch_config_entry, &config);
        free(normalized_url);
 
-       curl_global_init(CURL_GLOBAL_ALL);
+       if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
+               die("curl_global_init failed");
 
        http_proactive_auth = proactive_auth;
 
@@ -417,10 +421,8 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
        }
 
        curlm = curl_multi_init();
-       if (curlm == NULL) {
-               fprintf(stderr, "Error creating curl multi handle.\n");
-               exit(1);
-       }
+       if (!curlm)
+               die("curl_multi_init failed");
 #endif
 
        if (getenv("GIT_SSL_NO_VERIFY"))
@@ -1332,7 +1334,7 @@ int finish_http_pack_request(struct http_pack_request *preq)
        struct packed_git **lst;
        struct packed_git *p = preq->target;
        char *tmp_idx;
-       struct child_process ip;
+       struct child_process ip = CHILD_PROCESS_INIT;
        const char *ip_argv[8];
 
        close_pack_index(p);
@@ -1355,7 +1357,6 @@ int finish_http_pack_request(struct http_pack_request *preq)
        ip_argv[3] = preq->tmpfile;
        ip_argv[4] = NULL;
 
-       memset(&ip, 0, sizeof(ip));
        ip.argv = ip_argv;
        ip.git_cmd = 1;
        ip.no_stdin = 1;
diff --git a/ident.c b/ident.c
index 1d9b6e770d02d12f77b417e05aca5134eccf1c40..77bc882e59c887e948a1fba4d99805f5dedfa7f7 100644 (file)
--- a/ident.c
+++ b/ident.c
@@ -102,7 +102,7 @@ static void copy_email(const struct passwd *pw, struct strbuf *email)
        add_domainname(email);
 }
 
-static const char *ident_default_name(void)
+const char *ident_default_name(void)
 {
        if (!git_default_name.len) {
                copy_gecos(xgetpwuid_self(), &git_default_name);
index 524fbabc96f450f1faed196c1743d2f8d697b587..f33e56dba1e06cd61448069e3d300e3650477320 100644 (file)
@@ -69,6 +69,7 @@ struct imap_server_conf {
        char *tunnel;
        char *host;
        int port;
+       char *folder;
        char *user;
        char *pass;
        int use_ssl;
@@ -82,6 +83,7 @@ static struct imap_server_conf server = {
        NULL,   /* tunnel */
        NULL,   /* host */
        0,      /* port */
+       NULL,   /* folder */
        NULL,   /* user */
        NULL,   /* pass */
        0,      /* use_ssl */
@@ -128,7 +130,6 @@ struct imap_cmd_cb {
        char *data;
        int dlen;
        int uid;
-       unsigned create:1, trycreate:1;
 };
 
 struct imap_cmd {
@@ -493,9 +494,9 @@ static int nfsnprintf(char *buf, int blen, const char *fmt, ...)
        return ret;
 }
 
-static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
-                                        struct imap_cmd_cb *cb,
-                                        const char *fmt, va_list ap)
+static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx,
+                                      struct imap_cmd_cb *cb,
+                                      const char *fmt, va_list ap)
 {
        struct imap *imap = ctx->imap;
        struct imap_cmd *cmd;
@@ -524,7 +525,7 @@ static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
        if (Verbose) {
                if (imap->num_in_progress)
                        printf("(%d in progress) ", imap->num_in_progress);
-               if (memcmp(cmd->cmd, "LOGIN", 5))
+               if (!starts_with(cmd->cmd, "LOGIN"))
                        printf(">>> %s", buf);
                else
                        printf(">>> %d LOGIN <user> <pass>\n", cmd->tag);
@@ -558,20 +559,6 @@ static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
        return cmd;
 }
 
-__attribute__((format (printf, 3, 4)))
-static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx,
-                                      struct imap_cmd_cb *cb,
-                                      const char *fmt, ...)
-{
-       struct imap_cmd *ret;
-       va_list ap;
-
-       va_start(ap, fmt);
-       ret = v_issue_imap_cmd(ctx, cb, fmt, ap);
-       va_end(ap);
-       return ret;
-}
-
 __attribute__((format (printf, 3, 4)))
 static int imap_exec(struct imap_store *ctx, struct imap_cmd_cb *cb,
                     const char *fmt, ...)
@@ -580,7 +567,7 @@ static int imap_exec(struct imap_store *ctx, struct imap_cmd_cb *cb,
        struct imap_cmd *cmdp;
 
        va_start(ap, fmt);
-       cmdp = v_issue_imap_cmd(ctx, cb, fmt, ap);
+       cmdp = issue_imap_cmd(ctx, cb, fmt, ap);
        va_end(ap);
        if (!cmdp)
                return RESP_BAD;
@@ -596,7 +583,7 @@ static int imap_exec_m(struct imap_store *ctx, struct imap_cmd_cb *cb,
        struct imap_cmd *cmdp;
 
        va_start(ap, fmt);
-       cmdp = v_issue_imap_cmd(ctx, cb, fmt, ap);
+       cmdp = issue_imap_cmd(ctx, cb, fmt, ap);
        va_end(ap);
        if (!cmdp)
                return DRV_STORE_BAD;
@@ -714,8 +701,8 @@ static int parse_response_code(struct imap_store *ctx, struct imap_cmd_cb *cb,
 static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)
 {
        struct imap *imap = ctx->imap;
-       struct imap_cmd *cmdp, **pcmdp, *ncmdp;
-       char *cmd, *arg, *arg1, *p;
+       struct imap_cmd *cmdp, **pcmdp;
+       char *cmd, *arg, *arg1;
        int n, resp, resp2, tag;
 
        for (;;) {
@@ -801,39 +788,17 @@ static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)
                        if (!strcmp("OK", arg))
                                resp = DRV_OK;
                        else {
-                               if (!strcmp("NO", arg)) {
-                                       if (cmdp->cb.create && cmd && (cmdp->cb.trycreate || !memcmp(cmd, "[TRYCREATE]", 11))) { /* SELECT, APPEND or UID COPY */
-                                               p = strchr(cmdp->cmd, '"');
-                                               if (!issue_imap_cmd(ctx, NULL, "CREATE \"%.*s\"", (int)(strchr(p + 1, '"') - p + 1), p)) {
-                                                       resp = RESP_BAD;
-                                                       goto normal;
-                                               }
-                                               /* not waiting here violates the spec, but a server that does not
-                                                  grok this nonetheless violates it too. */
-                                               cmdp->cb.create = 0;
-                                               if (!(ncmdp = issue_imap_cmd(ctx, &cmdp->cb, "%s", cmdp->cmd))) {
-                                                       resp = RESP_BAD;
-                                                       goto normal;
-                                               }
-                                               free(cmdp->cmd);
-                                               free(cmdp);
-                                               if (!tcmd)
-                                                       return 0;       /* ignored */
-                                               if (cmdp == tcmd)
-                                                       tcmd = ncmdp;
-                                               continue;
-                                       }
+                               if (!strcmp("NO", arg))
                                        resp = RESP_NO;
-                               else /*if (!strcmp("BAD", arg))*/
+                               else /*if (!strcmp("BAD", arg))*/
                                        resp = RESP_BAD;
                                fprintf(stderr, "IMAP command '%s' returned response (%s) - %s\n",
-                                        memcmp(cmdp->cmd, "LOGIN", 5) ?
+                                       !starts_with(cmdp->cmd, "LOGIN") ?
                                                        cmdp->cmd : "LOGIN <user> <pass>",
                                                        arg, cmd ? cmd : "");
                        }
                        if ((resp2 = parse_response_code(ctx, &cmdp->cb, cmd)) > resp)
                                resp = resp2;
-               normal:
                        if (cmdp->cb.done)
                                cmdp->cb.done(ctx, cmdp, resp);
                        free(cmdp->cb.data);
@@ -944,7 +909,7 @@ static int auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const cha
        return 0;
 }
 
-static struct imap_store *imap_open_store(struct imap_server_conf *srvc)
+static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *folder)
 {
        struct credential cred = CREDENTIAL_INIT;
        struct imap_store *ctx;
@@ -961,17 +926,16 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc)
        /* open connection to IMAP server */
 
        if (srvc->tunnel) {
-               const char *argv[] = { srvc->tunnel, NULL };
-               struct child_process tunnel = {NULL};
+               struct child_process tunnel = CHILD_PROCESS_INIT;
 
                imap_info("Starting tunnel '%s'... ", srvc->tunnel);
 
-               tunnel.argv = argv;
+               argv_array_push(&tunnel.args, srvc->tunnel);
                tunnel.use_shell = 1;
                tunnel.in = -1;
                tunnel.out = -1;
                if (start_command(&tunnel))
-                       die("cannot start proxy %s", argv[0]);
+                       die("cannot start proxy %s", srvc->tunnel);
 
                imap->buf.sock.fd[0] = tunnel.out;
                imap->buf.sock.fd[1] = tunnel.in;
@@ -1156,6 +1120,25 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc)
                credential_approve(&cred);
        credential_clear(&cred);
 
+       /* check the target mailbox exists */
+       ctx->name = folder;
+       switch (imap_exec(ctx, NULL, "EXAMINE \"%s\"", ctx->name)) {
+       case RESP_OK:
+               /* ok */
+               break;
+       case RESP_BAD:
+               fprintf(stderr, "IMAP error: could not check mailbox\n");
+               goto out;
+       case RESP_NO:
+               if (imap_exec(ctx, NULL, "CREATE \"%s\"", ctx->name) == RESP_OK) {
+                       imap_info("Created missing mailbox\n");
+               } else {
+                       fprintf(stderr, "IMAP error: could not create missing mailbox\n");
+                       goto out;
+               }
+               break;
+       }
+
        ctx->prefix = "";
        return ctx;
 
@@ -1164,6 +1147,7 @@ static struct imap_store *imap_open_store(struct imap_server_conf *srvc)
                credential_reject(&cred);
        credential_clear(&cred);
 
+ out:
        imap_close_store(ctx);
        return NULL;
 }
@@ -1219,7 +1203,6 @@ static int imap_store_msg(struct imap_store *ctx, struct strbuf *msg)
 
        box = ctx->name;
        prefix = !strcmp(box, "INBOX") ? "" : ctx->prefix;
-       cb.create = 0;
        ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" ", prefix, box);
        imap->caps = imap->rcaps;
        if (ret != DRV_OK)
@@ -1324,45 +1307,35 @@ static int split_msg(struct strbuf *all_msgs, struct strbuf *msg, int *ofs)
        return 1;
 }
 
-static char *imap_folder;
-
-static int git_imap_config(const char *key, const char *val, void *cb)
+static void git_imap_config(void)
 {
-       if (!skip_prefix(key, "imap.", &key))
-               return 0;
+       const char *val = NULL;
+
+       git_config_get_bool("imap.sslverify", &server.ssl_verify);
+       git_config_get_bool("imap.preformattedhtml", &server.use_html);
+       git_config_get_string("imap.folder", &server.folder);
 
-       /* check booleans first, and barf on others */
-       if (!strcmp("sslverify", key))
-               server.ssl_verify = git_config_bool(key, val);
-       else if (!strcmp("preformattedhtml", key))
-               server.use_html = git_config_bool(key, val);
-       else if (!val)
-               return config_error_nonbool(key);
-
-       if (!strcmp("folder", key)) {
-               imap_folder = xstrdup(val);
-       } else if (!strcmp("host", key)) {
-               if (starts_with(val, "imap:"))
-                       val += 5;
-               else if (starts_with(val, "imaps:")) {
-                       val += 6;
-                       server.use_ssl = 1;
+       if (!git_config_get_value("imap.host", &val)) {
+               if (!val) {
+                       git_die_config("imap.host", "Missing value for 'imap.host'");
+               } else {
+                       if (starts_with(val, "imap:"))
+                               val += 5;
+                       else if (starts_with(val, "imaps:")) {
+                               val += 6;
+                               server.use_ssl = 1;
+                       }
+                       if (starts_with(val, "//"))
+                               val += 2;
+                       server.host = xstrdup(val);
                }
-               if (starts_with(val, "//"))
-                       val += 2;
-               server.host = xstrdup(val);
-       } else if (!strcmp("user", key))
-               server.user = xstrdup(val);
-       else if (!strcmp("pass", key))
-               server.pass = xstrdup(val);
-       else if (!strcmp("port", key))
-               server.port = git_config_int(key, val);
-       else if (!strcmp("tunnel", key))
-               server.tunnel = xstrdup(val);
-       else if (!strcmp("authmethod", key))
-               server.auth_method = xstrdup(val);
+       }
 
-       return 0;
+       git_config_get_string("imap.user", &server.user);
+       git_config_get_string("imap.pass", &server.pass);
+       git_config_get_int("imap.port", &server.port);
+       git_config_get_string("imap.tunnel", &server.tunnel);
+       git_config_get_string("imap.authmethod", &server.auth_method);
 }
 
 int main(int argc, char **argv)
@@ -1383,12 +1356,12 @@ int main(int argc, char **argv)
                usage(imap_send_usage);
 
        setup_git_directory_gently(&nongit_ok);
-       git_config(git_imap_config, NULL);
+       git_imap_config();
 
        if (!server.port)
                server.port = server.use_ssl ? 993 : 143;
 
-       if (!imap_folder) {
+       if (!server.folder) {
                fprintf(stderr, "no imap store specified\n");
                return 1;
        }
@@ -1418,14 +1391,13 @@ int main(int argc, char **argv)
        }
 
        /* write it to the imap server */
-       ctx = imap_open_store(&server);
+       ctx = imap_open_store(&server, server.folder);
        if (!ctx) {
                fprintf(stderr, "failed to open store\n");
                return 1;
        }
 
        fprintf(stderr, "sending %d message%s\n", total, (total != 1) ? "s" : "");
-       ctx->name = imap_folder;
        while (1) {
                unsigned percent = n * 100 / total;
 
index fb61ea66a13eba3a8e91a05dbe1c37de98cec853..8ea03e536a56655ff48f4fa8a3050c0225d52f38 100644 (file)
@@ -225,11 +225,8 @@ static int read_merge_config(const char *var, const char *value, void *cb)
        const char *key, *name;
        int namelen;
 
-       if (!strcmp(var, "merge.default")) {
-               if (value)
-                       default_ll_merge = xstrdup(value);
-               return 0;
-       }
+       if (!strcmp(var, "merge.default"))
+               return git_config_string(&default_ll_merge, var, value);
 
        /*
         * We are not interested in anything but "merge.<name>.variable";
@@ -254,12 +251,8 @@ static int read_merge_config(const char *var, const char *value, void *cb)
                ll_user_merge_tail = &(fn->next);
        }
 
-       if (!strcmp("name", key)) {
-               if (!value)
-                       return error("%s: lacks value", var);
-               fn->description = xstrdup(value);
-               return 0;
-       }
+       if (!strcmp("name", key))
+               return git_config_string(&fn->description, var, value);
 
        if (!strcmp("driver", key)) {
                if (!value)
@@ -285,12 +278,8 @@ static int read_merge_config(const char *var, const char *value, void *cb)
                return 0;
        }
 
-       if (!strcmp("recursive", key)) {
-               if (!value)
-                       return error("%s: lacks value", var);
-               fn->recursive = xstrdup(value);
-               return 0;
-       }
+       if (!strcmp("recursive", key))
+               return git_config_string(&fn->recursive, var, value);
 
        return 0;
 }
index 2564a7f5447b904585f629f0d1233c8a59483a40..2a800cef33ed7fb1ba7d3499459eccd824ab33e4 100644 (file)
@@ -237,6 +237,16 @@ int close_lock_file(struct lock_file *lk)
        return close(fd);
 }
 
+int reopen_lock_file(struct lock_file *lk)
+{
+       if (0 <= lk->fd)
+               die(_("BUG: reopen a lockfile that is still open"));
+       if (!lk->filename[0])
+               die(_("BUG: reopen a lockfile that has been committed"));
+       lk->fd = open(lk->filename, O_WRONLY);
+       return lk->fd;
+}
+
 int commit_lock_file(struct lock_file *lk)
 {
        char result_file[PATH_MAX];
index 0c53dc11abf5aa10c83b35f07452f3c00a2998d4..bcee7c596696eb1da109b3ff375e09453045a60f 100644 (file)
 #include "sequencer.h"
 #include "line-log.h"
 
-struct decoration name_decoration = { "object names" };
-
-enum decoration_type {
-       DECORATION_NONE = 0,
-       DECORATION_REF_LOCAL,
-       DECORATION_REF_REMOTE,
-       DECORATION_REF_TAG,
-       DECORATION_REF_STASH,
-       DECORATION_REF_HEAD,
-       DECORATION_GRAFTED,
-};
+static struct decoration name_decoration = { "object names" };
 
 static char decoration_colors[][COLOR_MAXLEN] = {
        GIT_COLOR_RESET,
@@ -84,15 +74,20 @@ int parse_decorate_color_config(const char *var, const int ofs, const char *valu
 #define decorate_get_color_opt(o, ix) \
        decorate_get_color((o)->use_color, ix)
 
-static void add_name_decoration(enum decoration_type type, const char *name, struct object *obj)
+void add_name_decoration(enum decoration_type type, const char *name, struct object *obj)
 {
        int nlen = strlen(name);
-       struct name_decoration *res = xmalloc(sizeof(struct name_decoration) + nlen);
+       struct name_decoration *res = xmalloc(sizeof(*res) + nlen + 1);
        memcpy(res->name, name, nlen + 1);
        res->type = type;
        res->next = add_decoration(&name_decoration, obj, res);
 }
 
+const struct name_decoration *get_name_decoration(const struct object *obj)
+{
+       return lookup_decoration(&name_decoration, obj);
+}
+
 static int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
 {
        struct object *obj;
@@ -187,13 +182,13 @@ void format_decorations(struct strbuf *sb,
                        int use_color)
 {
        const char *prefix;
-       struct name_decoration *decoration;
+       const struct name_decoration *decoration;
        const char *color_commit =
                diff_get_color(use_color, DIFF_COMMIT);
        const char *color_reset =
                decorate_get_color(use_color, DECORATION_NONE);
 
-       decoration = lookup_decoration(&name_decoration, &commit->object);
+       decoration = get_name_decoration(&commit->object);
        if (!decoration)
                return;
        prefix = " (";
@@ -649,7 +644,7 @@ void show_log(struct rev_info *opt)
                graph_show_commit_msg(opt->graph, &msgbuf);
        else
                fwrite(msgbuf.buf, sizeof(char), msgbuf.len, stdout);
-       if (opt->use_terminator) {
+       if (opt->use_terminator && !commit_format_is_empty(opt->commit_format)) {
                if (!opt->missing_newline)
                        graph_show_padding(opt->graph);
                putchar(opt->diffopt.line_termination);
@@ -676,7 +671,8 @@ int log_tree_diff_flush(struct rev_info *opt)
                show_log(opt);
                if ((opt->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT) &&
                    opt->verbose_header &&
-                   opt->commit_format != CMIT_FMT_ONELINE) {
+                   opt->commit_format != CMIT_FMT_ONELINE &&
+                   !commit_format_is_empty(opt->commit_format)) {
                        /*
                         * When showing a verbose header (i.e. log message),
                         * and not in --pretty=oneline format, we would want
index 1d332b8bbbf076b819e2052c84874fb0728dae02..8ab944c44cf1afd516505fe9bb80dbc06708d1af 100644 (file)
@@ -2026,22 +2026,12 @@ int merge_recursive_generic(struct merge_options *o,
        return clean ? 0 : 1;
 }
 
-static int merge_recursive_config(const char *var, const char *value, void *cb)
+static void merge_recursive_config(struct merge_options *o)
 {
-       struct merge_options *o = cb;
-       if (!strcmp(var, "merge.verbosity")) {
-               o->verbosity = git_config_int(var, value);
-               return 0;
-       }
-       if (!strcmp(var, "diff.renamelimit")) {
-               o->diff_rename_limit = git_config_int(var, value);
-               return 0;
-       }
-       if (!strcmp(var, "merge.renamelimit")) {
-               o->merge_rename_limit = git_config_int(var, value);
-               return 0;
-       }
-       return git_xmerge_config(var, value, cb);
+       git_config_get_int("merge.verbosity", &o->verbosity);
+       git_config_get_int("diff.renamelimit", &o->diff_rename_limit);
+       git_config_get_int("merge.renamelimit", &o->merge_rename_limit);
+       git_config(git_xmerge_config, NULL);
 }
 
 void init_merge_options(struct merge_options *o)
@@ -2052,7 +2042,7 @@ void init_merge_options(struct merge_options *o)
        o->diff_rename_limit = -1;
        o->merge_rename_limit = -1;
        o->renormalize = 0;
-       git_config(merge_recursive_config, o);
+       merge_recursive_config(o);
        if (getenv("GIT_MERGE_VERBOSITY"))
                o->verbosity =
                        strtol(getenv("GIT_MERGE_VERBOSITY"), NULL, 10);
diff --git a/pager.c b/pager.c
index 8b5cbc56e4fd57a1b9d2cad3e668df4c508a7b17..b2b805af98552061a723f3b8e2ac3093d0b897f7 100644 (file)
--- a/pager.c
+++ b/pager.c
@@ -6,19 +6,13 @@
 #define DEFAULT_PAGER "less"
 #endif
 
-struct pager_config {
-       const char *cmd;
-       int want;
-       char *value;
-};
-
 /*
  * This is split up from the rest of git so that we can do
  * something different on Windows.
  */
 
 static const char *pager_argv[] = { NULL, NULL };
-static struct child_process pager_process;
+static struct child_process pager_process = CHILD_PROCESS_INIT;
 
 static void wait_for_pager(void)
 {
@@ -155,30 +149,22 @@ int decimal_width(int number)
        return width;
 }
 
-static int pager_command_config(const char *var, const char *value, void *data)
+/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
+int check_pager_config(const char *cmd)
 {
-       struct pager_config *c = data;
-       if (starts_with(var, "pager.") && !strcmp(var + 6, c->cmd)) {
-               int b = git_config_maybe_bool(var, value);
+       int want = -1;
+       struct strbuf key = STRBUF_INIT;
+       const char *value = NULL;
+       strbuf_addf(&key, "pager.%s", cmd);
+       if (!git_config_get_value(key.buf, &value)) {
+               int b = git_config_maybe_bool(key.buf, value);
                if (b >= 0)
-                       c->want = b;
+                       want = b;
                else {
-                       c->want = 1;
-                       c->value = xstrdup(value);
+                       want = 1;
+                       pager_program = xstrdup(value);
                }
        }
-       return 0;
-}
-
-/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
-int check_pager_config(const char *cmd)
-{
-       struct pager_config c;
-       c.cmd = cmd;
-       c.want = -1;
-       c.value = NULL;
-       git_config(pager_command_config, &c);
-       if (c.value)
-               pager_program = c.value;
-       return c.want;
+       strbuf_release(&key);
+       return want;
 }
diff --git a/path.c b/path.c
index 3afcdb432a009b5e1c869123139192cf1a688292..f68df0cf888124592db6c771d78d94894ffbacd9 100644 (file)
--- a/path.c
+++ b/path.c
@@ -148,10 +148,12 @@ void home_config_paths(char **global, char **xdg, char *file)
                        *global = mkpathdup("%s/.gitconfig", home);
        }
 
-       if (!xdg_home)
-               *xdg = NULL;
-       else
-               *xdg = mkpathdup("%s/git/%s", xdg_home, file);
+       if (xdg) {
+               if (!xdg_home)
+                       *xdg = NULL;
+               else
+                       *xdg = mkpathdup("%s/git/%s", xdg_home, file);
+       }
 
        free(to_free);
 }
index 52c3d07a5c25975be05baa16a5fecb4c5e4e308f..461cc14354c79da2baa0b1aa8bad0fc61812846b 100644 (file)
--- a/po/TEAMS
+++ b/po/TEAMS
@@ -15,6 +15,8 @@ Leader:               Ralf Thielow <ralf.thielow@googlemail.com>
 Members:       Thomas Rast <tr@thomasrast.ch>
                Jan Krüger <jk@jk.gs>
                Christian Stimming <stimming@tuhh.de>
+               Phillip Szelat <phillip.szelat@gmail.com>
+               Matthias Rüster <matthias.ruester@gmail.com>
 
 Language:      fr (French)
 Repository:    https://github.com/jnavila/git
index 28daddc2271810380c7ce2cad57cf6fb4b4ebb80..e5d2b25f448b5b9847e9bcda5285198afa40930d 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -5,9 +5,9 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: git 2.0.0\n"
+"Project-Id-Version: Git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2014-04-17 12:13+0800\n"
+"POT-Creation-Date: 2014-08-04 14:48+0800\n"
 "PO-Revision-Date: 2013-07-28 18:42+0200\n"
 "Last-Translator: Ralf Thielow <ralf.thielow@gmail.com>\n"
 "Language-Team: German <>\n"
@@ -22,17 +22,15 @@ msgstr ""
 msgid "hint: %.*s\n"
 msgstr "Hinweis: %.*s\n"
 
-#: advice.c:85
+#: advice.c:88
 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'."
+"Fix them up in the work tree, and then use 'git add/rm <file>'\n"
+"as appropriate to mark resolution and make a commit, or use\n"
+"'git commit -a'."
 msgstr ""
-"Korrigieren Sie dies im Arbeitsverzeichnis,\n"
-"und benutzen Sie dann 'git add/rm <Datei>'\n"
-"um die Auflösung entsprechend zu markieren und zu committen,\n"
-"oder benutzen Sie 'git commit -a'."
+"Korrigieren Sie dies im Arbeitsverzeichnis, und benutzen Sie\n"
+"dann 'git add/rm <Datei>' um die Auflösung entsprechend zu markieren\n"
+"und zu committen, oder benutzen Sie 'git commit -a'."
 
 #: archive.c:10
 msgid "git archive [options] <tree-ish> [<path>...]"
@@ -53,7 +51,7 @@ msgstr ""
 msgid "git archive --remote <repo> [--exec <cmd>] --list"
 msgstr "git archive --remote <Repository> [--exec <Programm>] --list"
 
-#: archive.c:243 builtin/add.c:136 builtin/add.c:428 builtin/rm.c:328
+#: archive.c:243 builtin/add.c:136 builtin/add.c:427 builtin/rm.c:328
 #, c-format
 msgid "pathspec '%s' did not match any files"
 msgstr "Pfadspezifikation '%s' stimmt mit keinen Dateien Ã¼berein"
@@ -66,7 +64,7 @@ msgstr "Format"
 msgid "archive format"
 msgstr "Archivformat"
 
-#: archive.c:329 builtin/log.c:1193
+#: archive.c:329 builtin/log.c:1201
 msgid "prefix"
 msgstr "Präfix"
 
@@ -74,9 +72,9 @@ msgstr "Präfix"
 msgid "prepend prefix to each pathname in the archive"
 msgstr "stellt einen Präfix vor jeden Pfadnamen in dem Archiv"
 
-#: archive.c:331 builtin/archive.c:88 builtin/blame.c:2258
-#: builtin/blame.c:2259 builtin/config.c:57 builtin/fast-export.c:680
-#: builtin/fast-export.c:682 builtin/grep.c:714 builtin/hash-object.c:77
+#: archive.c:331 builtin/archive.c:88 builtin/blame.c:2517
+#: builtin/blame.c:2518 builtin/config.c:57 builtin/fast-export.c:709
+#: builtin/fast-export.c:711 builtin/grep.c:712 builtin/hash-object.c:77
 #: builtin/ls-files.c:489 builtin/ls-files.c:492 builtin/notes.c:412
 #: builtin/notes.c:569 builtin/read-tree.c:108 parse-options.h:151
 msgid "file"
@@ -268,7 +266,7 @@ msgstr "'%s' sieht nicht wie eine v2 Paketdatei aus"
 msgid "unrecognized header: %s%s (%d)"
 msgstr "nicht erkannter Kopfbereich: %s%s (%d)"
 
-#: bundle.c:86 builtin/commit.c:706
+#: bundle.c:86 builtin/commit.c:755
 #, c-format
 msgid "could not open '%s'"
 msgstr "Konnte '%s' nicht Ã¶ffnen"
@@ -277,8 +275,8 @@ msgstr "Konnte '%s' nicht Ã¶ffnen"
 msgid "Repository lacks these prerequisite commits:"
 msgstr "Dem Repository fehlen folgende vorausgesetzte Commits:"
 
-#: bundle.c:162 sequencer.c:669 sequencer.c:1123 builtin/log.c:332
-#: builtin/log.c:821 builtin/log.c:1418 builtin/log.c:1644 builtin/merge.c:357
+#: bundle.c:162 sequencer.c:630 sequencer.c:1085 builtin/log.c:330
+#: builtin/log.c:821 builtin/log.c:1428 builtin/log.c:1665 builtin/merge.c:357
 #: builtin/shortlog.c:158
 msgid "revision walk setup failed"
 msgstr "Einrichtung des Revisionsgangs fehlgeschlagen"
@@ -301,47 +299,47 @@ msgid_plural "The bundle requires these %d refs:"
 msgstr[0] "Das Paket benötigt diese Referenz:"
 msgstr[1] "Das Paket benötigt diese %d Referenzen:"
 
-#: bundle.c:293
+#: bundle.c:289
 msgid "rev-list died"
 msgstr "\"rev-list\" abgebrochen"
 
-#: bundle.c:299 builtin/log.c:1329 builtin/shortlog.c:261
+#: bundle.c:295 builtin/log.c:1339 builtin/shortlog.c:261
 #, c-format
 msgid "unrecognized argument: %s"
 msgstr "nicht erkanntes Argument: %s"
 
-#: bundle.c:334
+#: bundle.c:330
 #, c-format
 msgid "ref '%s' is excluded by the rev-list options"
 msgstr "Referenz '%s' wird durch \"rev-list\" Optionen ausgeschlossen"
 
-#: bundle.c:379
+#: bundle.c:375
 msgid "Refusing to create empty bundle."
 msgstr "Erstellung eines leeren Pakets zurückgewiesen."
 
-#: bundle.c:395
+#: bundle.c:390
 msgid "Could not spawn pack-objects"
 msgstr "Konnte Paketobjekte nicht erstellen"
 
-#: bundle.c:413
+#: bundle.c:408
 msgid "pack-objects died"
 msgstr "Erstellung der Paketobjekte abgebrochen"
 
-#: bundle.c:416
+#: bundle.c:411
 #, c-format
 msgid "cannot create '%s'"
 msgstr "kann '%s' nicht erstellen"
 
-#: bundle.c:438
+#: bundle.c:433
 msgid "index-pack died"
 msgstr "Erstellung der Paketindexdatei abgebrochen"
 
-#: commit.c:54
+#: commit.c:40
 #, c-format
 msgid "could not parse %s"
 msgstr "konnte %s nicht parsen"
 
-#: commit.c:56
+#: commit.c:42
 #, c-format
 msgid "%s %s is not a commit!"
 msgstr "%s %s ist kein Commit!"
@@ -437,27 +435,27 @@ msgstr[1] "vor %lu Jahren"
 msgid "failed to read orderfile '%s'"
 msgstr "Fehler beim Lesen der Reihenfolgedatei '%s'."
 
-#: diffcore-rename.c:517
+#: diffcore-rename.c:514
 msgid "Performing inexact rename detection"
 msgstr "Führe Erkennung für ungenaue Umbenennung aus"
 
-#: diff.c:113
+#: diff.c:114
 #, c-format
 msgid "  Failed to parse dirstat cut-off percentage '%s'\n"
 msgstr ""
 "  Fehler beim Parsen des abgeschnittenen \"dirstat\" Prozentsatzes '%s'\n"
 
-#: diff.c:118
+#: diff.c:119
 #, c-format
 msgid "  Unknown dirstat parameter '%s'\n"
 msgstr "  Unbekannter \"dirstat\" Parameter '%s'\n"
 
-#: diff.c:213
+#: diff.c:214
 #, c-format
 msgid "Unknown value for 'diff.submodule' config variable: '%s'"
 msgstr "Unbekannter Wert in Konfigurationsvariable 'diff.dirstat': '%s'"
 
-#: diff.c:263
+#: diff.c:267
 #, c-format
 msgid ""
 "Found errors in 'diff.dirstat' config variable:\n"
@@ -466,7 +464,16 @@ msgstr ""
 "Fehler in 'diff.dirstat' Konfigurationsvariable gefunden:\n"
 "%s"
 
-#: diff.c:3495
+#: diff.c:2934
+#, c-format
+msgid "external diff died, stopping at %s"
+msgstr "externes Diff-Programm unerwartet beendet, angehalten bei %s"
+
+#: diff.c:3329
+msgid "--follow requires exactly one pathspec"
+msgstr "--follow erfordert genau eine Pfadspezifikation"
+
+#: diff.c:3492
 #, c-format
 msgid ""
 "Failed to parse --dirstat/-X option parameter:\n"
@@ -475,58 +482,58 @@ msgstr ""
 "Fehler beim Parsen des --dirstat/-X Optionsparameters:\n"
 "%s"
 
-#: diff.c:3509
+#: diff.c:3506
 #, c-format
 msgid "Failed to parse --submodule option parameter: '%s'"
 msgstr "Fehler beim Parsen des --submodule Optionsparameters: '%s'"
 
-#: gpg-interface.c:59 gpg-interface.c:131
+#: gpg-interface.c:73 gpg-interface.c:145
 msgid "could not run gpg."
 msgstr "konnte gpg nicht ausführen"
 
-#: gpg-interface.c:71
+#: gpg-interface.c:85
 msgid "gpg did not accept the data"
 msgstr "gpg hat die Daten nicht akzeptiert"
 
-#: gpg-interface.c:82
+#: gpg-interface.c:96
 msgid "gpg failed to sign the data"
 msgstr "gpg beim Signieren der Daten fehlgeschlagen"
 
-#: gpg-interface.c:115
+#: gpg-interface.c:129
 #, c-format
 msgid "could not create temporary file '%s': %s"
 msgstr "konnte temporäre Datei '%s' nicht erstellen: %s"
 
-#: gpg-interface.c:118
+#: gpg-interface.c:132
 #, c-format
 msgid "failed writing detached signature to '%s': %s"
 msgstr "Fehler beim Schreiben der Signatur nach '%s': %s"
 
-#: grep.c:1698
+#: grep.c:1703
 #, c-format
 msgid "'%s': unable to read %s"
 msgstr "'%s': konnte nicht lesen %s"
 
-#: grep.c:1715
+#: grep.c:1720
 #, c-format
 msgid "'%s': %s"
 msgstr "'%s': %s"
 
-#: grep.c:1726
+#: grep.c:1731
 #, c-format
 msgid "'%s': short read %s"
 msgstr "'%s': read() zu kurz %s"
 
-#: help.c:209
+#: help.c:207
 #, c-format
 msgid "available git commands in '%s'"
 msgstr "Vorhandene Git-Kommandos in '%s'"
 
-#: help.c:216
+#: help.c:214
 msgid "git commands available from elsewhere on your $PATH"
 msgstr "Vorhandene Git-Kommandos irgendwo in Ihrem $PATH"
 
-#: help.c:232
+#: help.c:230
 msgid "The most commonly used git commands are:"
 msgstr "Die allgemein verwendeten Git-Kommandos sind:"
 
@@ -562,7 +569,7 @@ msgstr "Automatische Ausführung in %0.1f Sekunden..."
 msgid "git: '%s' is not a git command. See 'git --help'."
 msgstr "git: '%s' ist kein Git-Kommando. Siehe 'git --help'."
 
-#: help.c:384 help.c:443
+#: help.c:384 help.c:444
 msgid ""
 "\n"
 "Did you mean this?"
@@ -576,16 +583,16 @@ msgstr[1] ""
 "\n"
 "Haben Sie eines von diesen gemeint?"
 
-#: help.c:439
+#: help.c:440
 #, c-format
 msgid "%s: %s - %s"
 msgstr "%s: %s - %s"
 
-#: merge.c:56
+#: merge.c:40
 msgid "failed to read the cache"
 msgstr "Lesen des Zwischenspeichers fehlgeschlagen"
 
-#: merge.c:110 builtin/checkout.c:357 builtin/checkout.c:558
+#: merge.c:93 builtin/checkout.c:356 builtin/checkout.c:556
 #: builtin/clone.c:661
 msgid "unable to write new index file"
 msgstr "Konnte neue Staging-Area-Datei nicht schreiben."
@@ -595,7 +602,7 @@ msgstr "Konnte neue Staging-Area-Datei nicht schreiben."
 msgid "(bad commit)\n"
 msgstr "(ungültiger Commit)\n"
 
-#: merge-recursive.c:208
+#: merge-recursive.c:210
 #, c-format
 msgid "addinfo_cache failed for path '%s'"
 msgstr "addinfo_cache für Pfad '%s' fehlgeschlagen"
@@ -604,64 +611,64 @@ msgstr "addinfo_cache für Pfad '%s' fehlgeschlagen"
 msgid "error building trees"
 msgstr "Fehler beim Erstellen der \"Tree\"-Objekte"
 
-#: merge-recursive.c:675
+#: merge-recursive.c:692
 #, c-format
 msgid "failed to create path '%s'%s"
 msgstr "Fehler beim Erstellen des Pfades '%s'%s"
 
-#: merge-recursive.c:686
+#: merge-recursive.c:703
 #, c-format
 msgid "Removing %s to make room for subdirectory\n"
 msgstr "Entferne %s um Platz für Unterverzeichnis zu schaffen\n"
 
-#: merge-recursive.c:700 merge-recursive.c:721
+#: merge-recursive.c:717 merge-recursive.c:738
 msgid ": perhaps a D/F conflict?"
 msgstr ": vielleicht ein Verzeichnis/Datei-Konflikt?"
 
-#: merge-recursive.c:711
+#: merge-recursive.c:728
 #, c-format
 msgid "refusing to lose untracked file at '%s'"
 msgstr "verweigere, da unbeobachtete Dateien in '%s' verloren gehen würden"
 
-#: merge-recursive.c:751
+#: merge-recursive.c:768
 #, c-format
 msgid "cannot read object %s '%s'"
 msgstr "kann Objekt %s '%s' nicht lesen"
 
-#: merge-recursive.c:753
+#: merge-recursive.c:770
 #, c-format
 msgid "blob expected for %s '%s'"
 msgstr "Blob erwartet für %s '%s'"
 
-#: merge-recursive.c:776 builtin/clone.c:317
+#: merge-recursive.c:793 builtin/clone.c:317
 #, c-format
 msgid "failed to open '%s'"
 msgstr "Fehler beim Ã–ffnen von '%s'"
 
-#: merge-recursive.c:784
+#: merge-recursive.c:801
 #, c-format
 msgid "failed to symlink '%s'"
 msgstr "Fehler beim Erstellen eines symbolischen Verweises für '%s'"
 
-#: merge-recursive.c:787
+#: merge-recursive.c:804
 #, c-format
 msgid "do not know what to do with %06o %s '%s'"
 msgstr "weiß nicht was mit %06o %s '%s' zu machen ist"
 
-#: merge-recursive.c:925
+#: merge-recursive.c:942
 msgid "Failed to execute internal merge"
 msgstr "Fehler bei Ausführung des internen Merges"
 
-#: merge-recursive.c:929
+#: merge-recursive.c:946
 #, c-format
 msgid "Unable to add %s to database"
 msgstr "Konnte %s nicht zur Datenbank hinzufügen"
 
-#: merge-recursive.c:945
+#: merge-recursive.c:962
 msgid "unsupported object type in the tree"
 msgstr "nicht unterstützter Objekttyp im Verzeichnis"
 
-#: merge-recursive.c:1024 merge-recursive.c:1038
+#: merge-recursive.c:1037 merge-recursive.c:1051
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
@@ -670,7 +677,7 @@ msgstr ""
 "KONFLIKT (%s/löschen): %s gelöscht in %s und %s in %s. Stand %s von %s wurde "
 "im Arbeitsbereich gelassen."
 
-#: merge-recursive.c:1030 merge-recursive.c:1043
+#: merge-recursive.c:1043 merge-recursive.c:1056
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
@@ -679,20 +686,20 @@ msgstr ""
 "KONFLIKT (%s/löschen): %s gelöscht in %s und %s in %s. Stand %s von %s wurde "
 "im Arbeitsbereich bei %s gelassen."
 
-#: merge-recursive.c:1084
+#: merge-recursive.c:1097
 msgid "rename"
 msgstr "umbenennen"
 
-#: merge-recursive.c:1084
+#: merge-recursive.c:1097
 msgid "renamed"
 msgstr "umbenannt"
 
-#: merge-recursive.c:1140
+#: merge-recursive.c:1153
 #, c-format
 msgid "%s is a directory in %s adding as %s instead"
 msgstr "%s ist ein Verzeichnis in %s, füge es stattdessen als %s hinzu"
 
-#: merge-recursive.c:1162
+#: merge-recursive.c:1175
 #, c-format
 msgid ""
 "CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s"
@@ -701,162 +708,162 @@ msgstr ""
 "KONFLIKT (umbenennen/umbenennen): Benenne um \"%s\"->\"%s\" in Branch \"%s\" "
 "und \"%s\"->\"%s\" in Branch \"%s\"%s"
 
-#: merge-recursive.c:1167
+#: merge-recursive.c:1180
 msgid " (left unresolved)"
 msgstr " (bleibt unaufgelöst)"
 
-#: merge-recursive.c:1221
+#: merge-recursive.c:1234
 #, c-format
 msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s"
 msgstr ""
 "KONFLIKT (umbenennen/umbenennen): Benenne um %s->%s in %s. Benenne um %s->%s "
 "in %s"
 
-#: merge-recursive.c:1251
+#: merge-recursive.c:1264
 #, c-format
 msgid "Renaming %s to %s and %s to %s instead"
 msgstr "Benenne stattdessen %s nach %s und %s nach %s um"
 
-#: merge-recursive.c:1450
+#: merge-recursive.c:1463
 #, c-format
 msgid "CONFLICT (rename/add): Rename %s->%s in %s. %s added in %s"
 msgstr ""
 "KONFLIKT (umbenennen/hinzufügen): Benenne um %s->%s in %s. %s hinzugefügt in "
 "%s"
 
-#: merge-recursive.c:1460
+#: merge-recursive.c:1473
 #, c-format
 msgid "Adding merged %s"
 msgstr "Füge zusammengeführte Datei %s hinzu"
 
-#: merge-recursive.c:1465 merge-recursive.c:1663
+#: merge-recursive.c:1478 merge-recursive.c:1676
 #, c-format
 msgid "Adding as %s instead"
 msgstr "Füge stattdessen als %s hinzu"
 
-#: merge-recursive.c:1516
+#: merge-recursive.c:1529
 #, c-format
 msgid "cannot read object %s"
 msgstr "kann Objekt %s nicht lesen"
 
-#: merge-recursive.c:1519
+#: merge-recursive.c:1532
 #, c-format
 msgid "object %s is not a blob"
 msgstr "Objekt %s ist kein Blob"
 
-#: merge-recursive.c:1567
+#: merge-recursive.c:1580
 msgid "modify"
 msgstr "ändern"
 
-#: merge-recursive.c:1567
+#: merge-recursive.c:1580
 msgid "modified"
 msgstr "geändert"
 
-#: merge-recursive.c:1577
+#: merge-recursive.c:1590
 msgid "content"
 msgstr "Inhalt"
 
-#: merge-recursive.c:1584
+#: merge-recursive.c:1597
 msgid "add/add"
 msgstr "hinzufügen/hinzufügen"
 
-#: merge-recursive.c:1618
+#: merge-recursive.c:1631
 #, c-format
 msgid "Skipped %s (merged same as existing)"
 msgstr "%s ausgelassen (Ergebnis des Merges existiert bereits)"
 
-#: merge-recursive.c:1632
+#: merge-recursive.c:1645
 #, c-format
 msgid "Auto-merging %s"
 msgstr "automatischer Merge von %s"
 
-#: merge-recursive.c:1636 git-submodule.sh:1149
+#: merge-recursive.c:1649 git-submodule.sh:1150
 msgid "submodule"
 msgstr "Submodul"
 
-#: merge-recursive.c:1637
+#: merge-recursive.c:1650
 #, c-format
 msgid "CONFLICT (%s): Merge conflict in %s"
 msgstr "KONFLIKT (%s): Merge-Konflikt in %s"
 
-#: merge-recursive.c:1727
+#: merge-recursive.c:1740
 #, c-format
 msgid "Removing %s"
 msgstr "Entferne %s"
 
-#: merge-recursive.c:1752
+#: merge-recursive.c:1765
 msgid "file/directory"
 msgstr "Datei/Verzeichnis"
 
-#: merge-recursive.c:1758
+#: merge-recursive.c:1771
 msgid "directory/file"
 msgstr "Verzeichnis/Datei"
 
-#: merge-recursive.c:1763
+#: merge-recursive.c:1776
 #, c-format
 msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s"
 msgstr ""
 "KONFLIKT (%s): Es existiert bereits ein Verzeichnis %s in %s. Füge %s als %s "
 "hinzu."
 
-#: merge-recursive.c:1773
+#: merge-recursive.c:1786
 #, c-format
 msgid "Adding %s"
 msgstr "Füge %s hinzu"
 
-#: merge-recursive.c:1790
+#: merge-recursive.c:1803
 msgid "Fatal merge failure, shouldn't happen."
 msgstr "Fataler Merge-Fehler. Sollte nicht passieren."
 
-#: merge-recursive.c:1809
+#: merge-recursive.c:1822
 msgid "Already up-to-date!"
 msgstr "Bereits aktuell!"
 
-#: merge-recursive.c:1818
+#: merge-recursive.c:1831
 #, c-format
 msgid "merging of trees %s and %s failed"
 msgstr "Zusammenführen der \"Tree\"-Objekte %s und %s fehlgeschlagen"
 
-#: merge-recursive.c:1848
+#: merge-recursive.c:1861
 #, c-format
 msgid "Unprocessed path??? %s"
 msgstr "unverarbeiteter Pfad??? %s"
 
-#: merge-recursive.c:1893
+#: merge-recursive.c:1906
 msgid "Merging:"
 msgstr "Merge:"
 
-#: merge-recursive.c:1906
+#: merge-recursive.c:1919
 #, c-format
 msgid "found %u common ancestor:"
 msgid_plural "found %u common ancestors:"
 msgstr[0] "%u gemeinsamen Vorgänger-Commit gefunden"
 msgstr[1] "%u gemeinsame Vorgänger-Commits gefunden"
 
-#: merge-recursive.c:1943
+#: merge-recursive.c:1956
 msgid "merge returned no commit"
 msgstr "Merge hat keinen Commit zurückgegeben"
 
-#: merge-recursive.c:2000
+#: merge-recursive.c:2013
 #, c-format
 msgid "Could not parse object '%s'"
 msgstr "Konnte Objekt '%s' nicht parsen."
 
-#: merge-recursive.c:2012 builtin/merge.c:668
+#: merge-recursive.c:2024 builtin/merge.c:666
 msgid "Unable to write index."
 msgstr "Konnte Staging-Area nicht schreiben."
 
-#: notes-utils.c:40
+#: notes-utils.c:41
 msgid "Cannot commit uninitialized/unreferenced notes tree"
 msgstr ""
 "Kann uninitialisiertes/unreferenzierte Notiz-Verzeichnis nicht committen."
 
-#: notes-utils.c:81
+#: notes-utils.c:83
 #, c-format
 msgid "Bad notes.rewriteMode value: '%s'"
 msgstr "Ungültiger notes.rewriteMode Wert: '%s'"
 
-#: notes-utils.c:91
+#: notes-utils.c:93
 #, c-format
 msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
 msgstr ""
@@ -864,38 +871,38 @@ msgstr ""
 
 #. TRANSLATORS: The first %s is the name of the
 #. environment variable, the second %s is its value
-#: notes-utils.c:118
+#: notes-utils.c:120
 #, c-format
 msgid "Bad %s value: '%s'"
 msgstr "Ungültiger %s Wert: '%s'"
 
-#: object.c:229
+#: object.c:234
 #, c-format
 msgid "unable to parse object: %s"
 msgstr "Konnte Objekt '%s' nicht parsen."
 
-#: parse-options.c:532
+#: parse-options.c:534
 msgid "..."
 msgstr "..."
 
-#: parse-options.c:550
+#: parse-options.c:552
 #, c-format
 msgid "usage: %s"
 msgstr "Verwendung: %s"
 
 #. TRANSLATORS: the colon here should align with the
 #. one in "usage: %s" translation
-#: parse-options.c:554
+#: parse-options.c:556
 #, c-format
 msgid "   or: %s"
 msgstr "      oder: %s"
 
-#: parse-options.c:557
+#: parse-options.c:559
 #, c-format
 msgid "    %s"
 msgstr "    %s"
 
-#: parse-options.c:591
+#: parse-options.c:593
 msgid "-NUM"
 msgstr "-NUM"
 
@@ -953,12 +960,12 @@ msgid "%s: pathspec magic not supported by this command: %s"
 msgstr ""
 "%s: Pfadspezifikationsangabe wird von diesem Kommando nicht unterstützt: %s"
 
-#: pathspec.c:433
+#: pathspec.c:432
 #, c-format
 msgid "pathspec '%s' is beyond a symbolic link"
 msgstr "Pfadspezifikation '%s' ist hinter einem symbolischen Verweis"
 
-#: pathspec.c:442
+#: pathspec.c:441
 msgid ""
 "There is nothing to exclude from by :(exclude) patterns.\n"
 "Perhaps you forgot to add either ':/' or '.' ?"
@@ -966,11 +973,11 @@ msgstr ""
 ":(exclude) Muster, aber keine anderen Pfadspezifikationen angegeben.\n"
 "Vielleicht haben Sie vergessen entweder ':/' oder '.' hinzuzufügen?"
 
-#: progress.c:224
+#: progress.c:225
 msgid "done"
 msgstr "Fertig"
 
-#: read-cache.c:1238
+#: read-cache.c:1260
 #, c-format
 msgid ""
 "index.version set, but the value is invalid.\n"
@@ -979,7 +986,7 @@ msgstr ""
 "index.version gesetzt, aber Wert ungültig.\n"
 "Verwende Version %i"
 
-#: read-cache.c:1248
+#: read-cache.c:1270
 #, c-format
 msgid ""
 "GIT_INDEX_VERSION set, but the value is invalid.\n"
@@ -988,51 +995,51 @@ msgstr ""
 "GIT_INDEX_VERSION gesetzt, aber Wert ungültig.\n"
 "Verwende Version %i"
 
-#: remote.c:758
+#: remote.c:753
 #, c-format
 msgid "Cannot fetch both %s and %s to %s"
 msgstr "Kann 'fetch' nicht für sowohl %s als auch %s nach %s ausführen."
 
-#: remote.c:762
+#: remote.c:757
 #, c-format
 msgid "%s usually tracks %s, not %s"
 msgstr "%s folgt Ã¼blicherweise %s, nicht %s"
 
-#: remote.c:766
+#: remote.c:761
 #, c-format
 msgid "%s tracks both %s and %s"
 msgstr "%s folgt sowohl %s als auch %s"
 
-#: remote.c:774
+#: remote.c:769
 msgid "Internal error"
 msgstr "Interner Fehler"
 
-#: remote.c:1948
+#: remote.c:1943
 #, c-format
 msgid "Your branch is based on '%s', but the upstream is gone.\n"
 msgstr "Ihr Branch basiert auf '%s', aber Upstream-Branch wurde entfernt.\n"
 
-#: remote.c:1952
+#: remote.c:1947
 msgid "  (use \"git branch --unset-upstream\" to fixup)\n"
 msgstr "  (benutzen Sie \"git branch --unset-upstream\" zum Beheben)\n"
 
-#: remote.c:1955
+#: remote.c:1950
 #, c-format
 msgid "Your branch is up-to-date with '%s'.\n"
 msgstr "Ihr Branch ist auf dem selben Stand wie '%s'.\n"
 
-#: remote.c:1959
+#: remote.c:1954
 #, 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] "Ihr Branch ist vor '%s' um %d Commit.\n"
 msgstr[1] "Ihr Branch ist vor '%s' um %d Commits.\n"
 
-#: remote.c:1965
+#: remote.c:1960
 msgid "  (use \"git push\" to publish your local commits)\n"
 msgstr "  (benutzen Sie \"git push\" um lokale Commits zu publizieren)\n"
 
-#: remote.c:1968
+#: remote.c:1963
 #, c-format
 msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
 msgid_plural ""
@@ -1042,12 +1049,12 @@ msgstr[0] ""
 msgstr[1] ""
 "Ihr Branch ist zu '%s' um %d Commits hinterher, und kann vorgespult werden.\n"
 
-#: remote.c:1976
+#: remote.c:1971
 msgid "  (use \"git pull\" to update your local branch)\n"
 msgstr ""
 "  (benutzen Sie \"git pull\" um Ihren lokalen Branch zu aktualisieren)\n"
 
-#: remote.c:1979
+#: remote.c:1974
 #, c-format
 msgid ""
 "Your branch and '%s' have diverged,\n"
@@ -1062,7 +1069,7 @@ msgstr[1] ""
 "Ihr Branch und '%s' sind divergiert,\n"
 "und haben jeweils %d und %d unterschiedliche Commits.\n"
 
-#: remote.c:1989
+#: remote.c:1984
 msgid "  (use \"git pull\" to merge the remote branch into yours)\n"
 msgstr ""
 "  (benutzen Sie \"git pull\" um Ihren Branch mit dem Remote-Branch "
@@ -1077,19 +1084,19 @@ msgstr "Öffnen von /dev/null fehlgeschlagen"
 msgid "dup2(%d,%d) failed"
 msgstr "dup2(%d,%d) fehlgeschlagen"
 
-#: sequencer.c:206 builtin/merge.c:786 builtin/merge.c:899
-#: builtin/merge.c:1009 builtin/merge.c:1019
+#: sequencer.c:171 builtin/merge.c:782 builtin/merge.c:893
+#: builtin/merge.c:1003 builtin/merge.c:1013
 #, c-format
 msgid "Could not open '%s' for writing"
 msgstr "Konnte '%s' nicht zum Schreiben Ã¶ffnen."
 
-#: sequencer.c:208 builtin/merge.c:343 builtin/merge.c:789
-#: builtin/merge.c:1011 builtin/merge.c:1024
+#: sequencer.c:173 builtin/merge.c:343 builtin/merge.c:785
+#: builtin/merge.c:1005 builtin/merge.c:1018
 #, c-format
 msgid "Could not write to '%s'"
 msgstr "Konnte nicht nach '%s' schreiben."
 
-#: sequencer.c:229
+#: sequencer.c:194
 msgid ""
 "after resolving the conflicts, mark the corrected paths\n"
 "with 'git add <paths>' or 'git rm <paths>'"
@@ -1097,7 +1104,7 @@ msgstr ""
 "nach Auflösung der Konflikte, markieren Sie die korrigierten Pfade\n"
 "mit 'git add <Pfade>' oder 'git rm <Pfade>'"
 
-#: sequencer.c:232
+#: sequencer.c:197
 msgid ""
 "after resolving the conflicts, mark the corrected paths\n"
 "with 'git add <paths>' or 'git rm <paths>'\n"
@@ -1107,222 +1114,226 @@ msgstr ""
 "mit 'git add <Pfade>' oder 'git rm <Pfade>'und tragen Sie das Ergebnis mit\n"
 "'git commit' ein"
 
-#: sequencer.c:245 sequencer.c:879 sequencer.c:962
+#: sequencer.c:210 sequencer.c:841 sequencer.c:924
 #, c-format
 msgid "Could not write to %s"
 msgstr "Konnte nicht nach %s schreiben"
 
-#: sequencer.c:248
+#: sequencer.c:213
 #, c-format
 msgid "Error wrapping up %s"
 msgstr "Fehler bei Nachbereitung von %s"
 
-#: sequencer.c:263
+#: sequencer.c:228
 msgid "Your local changes would be overwritten by cherry-pick."
 msgstr ""
 "Ihre lokalen Ã„nderungen würden von \"cherry-pick\" Ã¼berschrieben werden."
 
-#: sequencer.c:265
+#: sequencer.c:230
 msgid "Your local changes would be overwritten by revert."
 msgstr "Ihre lokalen Ã„nderungen würden von \"revert\" Ã¼berschrieben werden."
 
-#: sequencer.c:268
+#: sequencer.c:233
 msgid "Commit your changes or stash them to proceed."
 msgstr ""
 "Tragen Sie Ihre Ã„nderungen ein oder benutzen Sie \"stash\" um fortzufahren."
 
+#: sequencer.c:250
+msgid "Failed to lock HEAD during fast_forward_to"
+msgstr "Fehler beim Sperren von HEAD während fast_forward_to"
+
 #. TRANSLATORS: %s will be "revert" or "cherry-pick"
-#: sequencer.c:325
+#: sequencer.c:293
 #, c-format
 msgid "%s: Unable to write new index file"
 msgstr "%s: Konnte neue Staging-Area-Datei nicht schreiben"
 
-#: sequencer.c:356
+#: sequencer.c:324
 msgid "Could not resolve HEAD commit\n"
 msgstr "Konnte Commit von HEAD nicht auflösen\n"
 
-#: sequencer.c:378
+#: sequencer.c:344
 msgid "Unable to update cache tree\n"
 msgstr "Konnte Cache-Verzeichnis nicht aktualisieren\n"
 
-#: sequencer.c:430
+#: sequencer.c:391
 #, c-format
 msgid "Could not parse commit %s\n"
 msgstr "Konnte Commit %s nicht parsen\n"
 
-#: sequencer.c:435
+#: sequencer.c:396
 #, c-format
 msgid "Could not parse parent commit %s\n"
 msgstr "Konnte Eltern-Commit %s nicht parsen\n"
 
-#: sequencer.c:501
+#: sequencer.c:462
 msgid "Your index file is unmerged."
 msgstr "Ihre Staging-Area-Datei ist nicht zusammengeführt."
 
-#: sequencer.c:520
+#: sequencer.c:481
 #, c-format
 msgid "Commit %s is a merge but no -m option was given."
 msgstr "Commit %s ist ein Merge, aber die Option -m wurde nicht angegeben."
 
-#: sequencer.c:528
+#: sequencer.c:489
 #, c-format
 msgid "Commit %s does not have parent %d"
 msgstr "Commit %s hat keinen Elternteil %d"
 
-#: sequencer.c:532
+#: sequencer.c:493
 #, c-format
 msgid "Mainline was specified but commit %s is not a merge."
 msgstr "Hauptlinie wurde spezifiziert, aber Commit %s ist kein Merge."
 
 #. TRANSLATORS: The first %s will be "revert" or
 #. "cherry-pick", the second %s a SHA1
-#: sequencer.c:545
+#: sequencer.c:506
 #, c-format
 msgid "%s: cannot parse parent commit %s"
 msgstr "%s: kann Eltern-Commit %s nicht parsen"
 
-#: sequencer.c:549
+#: sequencer.c:510
 #, c-format
 msgid "Cannot get commit message for %s"
 msgstr "Kann keine Commit-Beschreibung für %s bekommen"
 
-#: sequencer.c:635
+#: sequencer.c:596
 #, c-format
 msgid "could not revert %s... %s"
 msgstr "Konnte \"revert\" nicht auf %s ausführen... %s"
 
-#: sequencer.c:636
+#: sequencer.c:597
 #, c-format
 msgid "could not apply %s... %s"
 msgstr "Konnte %s nicht anwenden... %s"
 
-#: sequencer.c:672
+#: sequencer.c:633
 msgid "empty commit set passed"
 msgstr "leere Menge von Commits Ã¼bergeben"
 
-#: sequencer.c:680
+#: sequencer.c:641
 #, c-format
 msgid "git %s: failed to read the index"
 msgstr "git %s: Fehler beim Lesen der Staging-Area"
 
-#: sequencer.c:685
+#: sequencer.c:645
 #, c-format
 msgid "git %s: failed to refresh the index"
 msgstr "git %s: Fehler beim Aktualisieren der Staging-Area"
 
-#: sequencer.c:743
+#: sequencer.c:705
 #, c-format
 msgid "Cannot %s during a %s"
 msgstr "Kann %s nicht während eines %s durchführen"
 
-#: sequencer.c:765
+#: sequencer.c:727
 #, c-format
 msgid "Could not parse line %d."
 msgstr "Konnte Zeile %d nicht parsen."
 
-#: sequencer.c:770
+#: sequencer.c:732
 msgid "No commits parsed."
 msgstr "Keine Commits geparst."
 
-#: sequencer.c:783
+#: sequencer.c:745
 #, c-format
 msgid "Could not open %s"
 msgstr "Konnte %s nicht Ã¶ffnen"
 
-#: sequencer.c:787
+#: sequencer.c:749
 #, c-format
 msgid "Could not read %s."
 msgstr "Konnte %s nicht lesen."
 
-#: sequencer.c:794
+#: sequencer.c:756
 #, c-format
 msgid "Unusable instruction sheet: %s"
 msgstr "Unbenutzbares Instruktionsblatt: %s"
 
-#: sequencer.c:824
+#: sequencer.c:786
 #, c-format
 msgid "Invalid key: %s"
 msgstr "Ungültiger Schlüssel: %s"
 
-#: sequencer.c:827
+#: sequencer.c:789
 #, c-format
 msgid "Invalid value for %s: %s"
 msgstr "Ungültiger Wert für %s: %s"
 
-#: sequencer.c:839
+#: sequencer.c:801
 #, c-format
 msgid "Malformed options sheet: %s"
 msgstr "Fehlerhaftes Optionsblatt: %s"
 
-#: sequencer.c:860
+#: sequencer.c:822
 msgid "a cherry-pick or revert is already in progress"
 msgstr "\"cherry-pick\" oder \"revert\" ist bereits im Gang"
 
-#: sequencer.c:861
+#: sequencer.c:823
 msgid "try \"git cherry-pick (--continue | --quit | --abort)\""
 msgstr "versuchen Sie \"git cherry-pick (--continue | --quit | --abort)\""
 
-#: sequencer.c:865
+#: sequencer.c:827
 #, c-format
 msgid "Could not create sequencer directory %s"
 msgstr "Konnte \"sequencer\"-Verzeichnis %s nicht erstellen"
 
-#: sequencer.c:881 sequencer.c:966
+#: sequencer.c:843 sequencer.c:928
 #, c-format
 msgid "Error wrapping up %s."
 msgstr "Fehler beim Einpacken von %s."
 
-#: sequencer.c:900 sequencer.c:1036
+#: sequencer.c:862 sequencer.c:998
 msgid "no cherry-pick or revert in progress"
 msgstr "kein \"cherry-pick\" oder \"revert\" im Gang"
 
-#: sequencer.c:902
+#: sequencer.c:864
 msgid "cannot resolve HEAD"
 msgstr "kann HEAD nicht auflösen"
 
-#: sequencer.c:904
+#: sequencer.c:866
 msgid "cannot abort from a branch yet to be born"
 msgstr "kann nicht abbrechen: bin auf einem Branch, der noch geboren wird"
 
-#: sequencer.c:926 builtin/apply.c:4061
+#: sequencer.c:888 builtin/apply.c:4062
 #, c-format
 msgid "cannot open %s: %s"
 msgstr "Kann %s nicht Ã¶ffnen: %s"
 
-#: sequencer.c:929
+#: sequencer.c:891
 #, c-format
 msgid "cannot read %s: %s"
 msgstr "Kann %s nicht lesen: %s"
 
-#: sequencer.c:930
+#: sequencer.c:892
 msgid "unexpected end of file"
 msgstr "Unerwartetes Dateiende"
 
-#: sequencer.c:936
+#: sequencer.c:898
 #, c-format
 msgid "stored pre-cherry-pick HEAD file '%s' is corrupt"
 msgstr "gespeicherte \"pre-cherry-pick\" HEAD Datei '%s' ist beschädigt"
 
-#: sequencer.c:959
+#: sequencer.c:921
 #, c-format
 msgid "Could not format %s."
 msgstr "Konnte %s nicht formatieren."
 
-#: sequencer.c:1104
+#: sequencer.c:1066
 #, c-format
 msgid "%s: can't cherry-pick a %s"
 msgstr "%s: %s kann nicht in \"cherry-pick\" benutzt werden"
 
-#: sequencer.c:1107
+#: sequencer.c:1069
 #, c-format
 msgid "%s: bad revision"
 msgstr "%s: ungültiger Commit"
 
-#: sequencer.c:1141
+#: sequencer.c:1103
 msgid "Can't revert as initial commit"
 msgstr "Kann nicht als allerersten Commit einen Revert ausführen."
 
-#: sequencer.c:1142
+#: sequencer.c:1104
 msgid "Can't cherry-pick into empty head"
 msgstr "Kann nicht als allerersten Commit einen Cherry-Pick ausführen."
 
@@ -1351,21 +1362,21 @@ msgstr ""
 "indem Sie \"git config advice.objectNameWarning false\"\n"
 "ausführen."
 
-#: sha1_name.c:1072
+#: sha1_name.c:1060
 msgid "HEAD does not point to a branch"
 msgstr "HEAD zeigt auf keinen Branch"
 
-#: sha1_name.c:1075
+#: sha1_name.c:1063
 #, c-format
 msgid "No such branch: '%s'"
 msgstr "Kein solcher Branch '%s'"
 
-#: sha1_name.c:1077
+#: sha1_name.c:1065
 #, c-format
 msgid "No upstream configured for branch '%s'"
 msgstr "Kein Upstream-Branch für Branch '%s' konfiguriert."
 
-#: sha1_name.c:1081
+#: sha1_name.c:1069
 #, c-format
 msgid "Upstream branch '%s' not stored as a remote-tracking branch"
 msgstr "Upstream-Branch '%s' ist nicht als Remote-Tracking-Branch gespeichert"
@@ -1395,17 +1406,17 @@ msgstr "Konnte Eintrag '%s' nicht aus .gitmodules entfernen"
 msgid "staging updated .gitmodules failed"
 msgstr "Konnte aktualisierte .gitmodules-Datei nicht zum Commit vormerken"
 
-#: submodule.c:1121 builtin/init-db.c:363
+#: submodule.c:1118 builtin/init-db.c:363
 #, c-format
 msgid "Could not create git link %s"
 msgstr "Konnte git-Verweis %s nicht erstellen"
 
-#: submodule.c:1132
+#: submodule.c:1129
 #, c-format
 msgid "Could not set core.worktree in %s"
 msgstr "Konnte core.worktree in '%s' nicht setzen."
 
-#: unpack-trees.c:206
+#: unpack-trees.c:202
 msgid "Checking out files"
 msgstr "Checke Dateien aus"
 
@@ -1438,22 +1449,22 @@ msgstr "ungültige Portnummer"
 msgid "invalid '..' path segment"
 msgstr "ungültiges '..' Pfadsegment"
 
-#: wrapper.c:422
+#: wrapper.c:460
 #, c-format
 msgid "unable to access '%s': %s"
 msgstr "konnte nicht auf '%s' zugreifen: %s"
 
-#: wrapper.c:443
+#: wrapper.c:481
 #, c-format
 msgid "unable to access '%s'"
 msgstr "konnte nicht auf '%s' zugreifen"
 
-#: wrapper.c:454
+#: wrapper.c:492
 #, c-format
 msgid "unable to look up current user in the passwd file: %s"
 msgstr "konnte aktuellen Benutzer nicht in Passwort-Datei finden: %s"
 
-#: wrapper.c:455
+#: wrapper.c:493
 msgid "no such user"
 msgstr "kein solcher Benutzer"
 
@@ -1612,15 +1623,15 @@ msgstr "unbeobachteter Inhalt, "
 msgid "bug: unhandled diff status %c"
 msgstr "Fehler: unbehandelter Differenz-Status %c"
 
-#: wt-status.c:765
+#: wt-status.c:764
 msgid "Submodules changed but not updated:"
 msgstr "Submodule geändert, aber nicht aktualisiert:"
 
-#: wt-status.c:767
+#: wt-status.c:766
 msgid "Submodule changes to be committed:"
 msgstr "Änderungen in Submodul zum Committen:"
 
-#: wt-status.c:846
+#: wt-status.c:845
 msgid ""
 "Do not touch the line above.\n"
 "Everything below will be removed."
@@ -1628,75 +1639,75 @@ msgstr ""
 "Ändern Sie nicht die obige Zeile.\n"
 "Alles unterhalb von ihr wird entfernt."
 
-#: wt-status.c:937
+#: wt-status.c:936
 msgid "You have unmerged paths."
 msgstr "Sie haben nicht zusammengeführte Pfade."
 
-#: wt-status.c:940
+#: wt-status.c:939
 msgid "  (fix conflicts and run \"git commit\")"
 msgstr " (beheben Sie die Konflikte und führen Sie \"git commit\" aus)"
 
-#: wt-status.c:943
+#: wt-status.c:942
 msgid "All conflicts fixed but you are still merging."
 msgstr "Alle Konflikte sind behoben, aber Sie sind immer noch beim Merge."
 
-#: wt-status.c:946
+#: wt-status.c:945
 msgid "  (use \"git commit\" to conclude merge)"
 msgstr "  (benutzen Sie \"git commit\" um den Merge abzuschließen)"
 
-#: wt-status.c:956
+#: wt-status.c:955
 msgid "You are in the middle of an am session."
 msgstr "Eine \"am\"-Sitzung ist im Gange."
 
-#: wt-status.c:959
+#: wt-status.c:958
 msgid "The current patch is empty."
 msgstr "Der aktuelle Patch ist leer."
 
-#: wt-status.c:963
+#: wt-status.c:962
 msgid "  (fix conflicts and then run \"git am --continue\")"
 msgstr ""
 "  (beheben Sie die Konflikte und führen Sie dann \"git am --continue\" aus)"
 
-#: wt-status.c:965
+#: wt-status.c:964
 msgid "  (use \"git am --skip\" to skip this patch)"
 msgstr "  (benutzen Sie \"git am --skip\" um diesen Patch auszulassen)"
 
-#: wt-status.c:967
+#: wt-status.c:966
 msgid "  (use \"git am --abort\" to restore the original branch)"
 msgstr ""
 "  (benutzen Sie \"git am --abort\" um den ursprünglichen Branch "
 "wiederherzustellen)"
 
-#: wt-status.c:1027 wt-status.c:1044
+#: wt-status.c:1026 wt-status.c:1043
 #, c-format
 msgid "You are currently rebasing branch '%s' on '%s'."
 msgstr "Sie sind gerade beim Rebase von Branch '%s' auf '%s'."
 
-#: wt-status.c:1032 wt-status.c:1049
+#: wt-status.c:1031 wt-status.c:1048
 msgid "You are currently rebasing."
 msgstr "Sie sind gerade beim Rebase."
 
-#: wt-status.c:1035
+#: wt-status.c:1034
 msgid "  (fix conflicts and then run \"git rebase --continue\")"
 msgstr ""
 "  (beheben Sie die Konflikte und führen Sie dann \"git rebase --continue\" "
 "aus)"
 
-#: wt-status.c:1037
+#: wt-status.c:1036
 msgid "  (use \"git rebase --skip\" to skip this patch)"
 msgstr "  (benutzen Sie \"git rebase --skip\" um diesen Patch auszulassen)"
 
-#: wt-status.c:1039
+#: wt-status.c:1038
 msgid "  (use \"git rebase --abort\" to check out the original branch)"
 msgstr ""
 "  (benutzen Sie \"git rebase --abort\" um den ursprünglichen Branch "
 "auszuchecken)"
 
-#: wt-status.c:1052
+#: wt-status.c:1051
 msgid "  (all conflicts fixed: run \"git rebase --continue\")"
 msgstr "  (alle Konflikte behoben: führen Sie \"git rebase --continue\" aus)"
 
-#: wt-status.c:1056
+#: wt-status.c:1055
 #, c-format
 msgid ""
 "You are currently splitting a commit while rebasing branch '%s' on '%s'."
@@ -1704,129 +1715,129 @@ msgstr ""
 "Sie teilen gerade einen Commit auf, während ein Rebase von Branch '%s' auf "
 "'%s' im Gange ist."
 
-#: wt-status.c:1061
+#: wt-status.c:1060
 msgid "You are currently splitting a commit during a rebase."
 msgstr "Sie teilen gerade einen Commit während eines Rebase auf."
 
-#: wt-status.c:1064
+#: wt-status.c:1063
 msgid "  (Once your working directory is clean, run \"git rebase --continue\")"
 msgstr ""
 "  (Sobald Ihr Arbeitsverzeichnis unverändert ist, führen Sie \"git rebase --"
 "continue\" aus)"
 
-#: wt-status.c:1068
+#: wt-status.c:1067
 #, c-format
 msgid "You are currently editing a commit while rebasing branch '%s' on '%s'."
 msgstr ""
 "Sie editieren gerade einen Commit während eines Rebase von Branch '%s' auf "
 "'%s'."
 
-#: wt-status.c:1073
+#: wt-status.c:1072
 msgid "You are currently editing a commit during a rebase."
 msgstr "Sie editieren gerade einen Commit während eines Rebase."
 
-#: wt-status.c:1076
+#: wt-status.c:1075
 msgid "  (use \"git commit --amend\" to amend the current commit)"
 msgstr ""
 "  (benutzen Sie \"git commit --amend\" um den aktuellen Commit nachzubessern)"
 
-#: wt-status.c:1078
+#: wt-status.c:1077
 msgid ""
 "  (use \"git rebase --continue\" once you are satisfied with your changes)"
 msgstr ""
 "  (benutzen Sie \"git rebase --continue\" sobald Ihre Ã„nderungen "
 "abgeschlossen sind)"
 
-#: wt-status.c:1088
+#: wt-status.c:1087
 #, c-format
 msgid "You are currently cherry-picking commit %s."
 msgstr "Sie führen gerade \"cherry-pick\" von Commit %s aus."
 
-#: wt-status.c:1093
+#: wt-status.c:1092
 msgid "  (fix conflicts and run \"git cherry-pick --continue\")"
 msgstr ""
 "  (beheben Sie die Konflikte und führen Sie dann \"git cherry-pick --continue"
 "\" aus)"
 
-#: wt-status.c:1096
+#: wt-status.c:1095
 msgid "  (all conflicts fixed: run \"git cherry-pick --continue\")"
 msgstr ""
 "  (alle Konflikte behoben: führen Sie \"git cherry-pick --continue\" aus)"
 
-#: wt-status.c:1098
+#: wt-status.c:1097
 msgid "  (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"
 msgstr ""
 "  (benutzen Sie \"git cherry-pick --abort\" um die Cherry-Pick-Operation "
 "abzubrechen)"
 
-#: wt-status.c:1107
+#: wt-status.c:1106
 #, c-format
 msgid "You are currently reverting commit %s."
 msgstr "Sie sind gerade an einem Revert von Commit '%s'."
 
-#: wt-status.c:1112
+#: wt-status.c:1111
 msgid "  (fix conflicts and run \"git revert --continue\")"
 msgstr ""
 "  (beheben Sie die Konflikte und führen Sie dann \"git revert --continue\" "
 "aus)"
 
-#: wt-status.c:1115
+#: wt-status.c:1114
 msgid "  (all conflicts fixed: run \"git revert --continue\")"
 msgstr "  (alle Konflikte behoben: führen Sie \"git revert --continue\" aus)"
 
-#: wt-status.c:1117
+#: wt-status.c:1116
 msgid "  (use \"git revert --abort\" to cancel the revert operation)"
 msgstr ""
 "  (benutzen Sie \"git revert --abort\" um die Revert-Operation abzubrechen)"
 
-#: wt-status.c:1128
+#: wt-status.c:1127
 #, c-format
 msgid "You are currently bisecting, started from branch '%s'."
 msgstr "Sie sind gerade bei einer binären Suche, gestartet von Branch '%s'."
 
-#: wt-status.c:1132
+#: wt-status.c:1131
 msgid "You are currently bisecting."
 msgstr "Sie sind gerade bei einer binären Suche."
 
-#: wt-status.c:1135
+#: wt-status.c:1134
 msgid "  (use \"git bisect reset\" to get back to the original branch)"
 msgstr ""
 "  (benutzen Sie \"git bisect reset\" um zum ursprünglichen Branch "
 "zurückzukehren)"
 
-#: wt-status.c:1310
+#: wt-status.c:1309
 msgid "On branch "
 msgstr "Auf Branch "
 
-#: wt-status.c:1317
+#: wt-status.c:1316
 msgid "rebase in progress; onto "
 msgstr "Rebase im Gange; auf "
 
-#: wt-status.c:1324
+#: wt-status.c:1323
 msgid "HEAD detached at "
 msgstr "HEAD losgelöst bei "
 
-#: wt-status.c:1326
+#: wt-status.c:1325
 msgid "HEAD detached from "
 msgstr "HEAD losgelöst von "
 
-#: wt-status.c:1329
+#: wt-status.c:1328
 msgid "Not currently on any branch."
 msgstr "Im Moment auf keinem Branch."
 
-#: wt-status.c:1346
+#: wt-status.c:1345
 msgid "Initial commit"
 msgstr "Initialer Commit"
 
-#: wt-status.c:1360
+#: wt-status.c:1359
 msgid "Untracked files"
 msgstr "Unbeobachtete Dateien"
 
-#: wt-status.c:1362
+#: wt-status.c:1361
 msgid "Ignored files"
 msgstr "Ignorierte Dateien"
 
-#: wt-status.c:1366
+#: wt-status.c:1365
 #, c-format
 msgid ""
 "It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
@@ -1837,32 +1848,32 @@ msgstr ""
 "'status -uno' könnte das beschleunigen, aber Sie müssen darauf achten,\n"
 "neue Dateien selbstständig hinzuzufügen (siehe 'git help status')."
 
-#: wt-status.c:1372
+#: wt-status.c:1371
 #, c-format
 msgid "Untracked files not listed%s"
 msgstr "Unbeobachtete Dateien nicht aufgelistet%s"
 
-#: wt-status.c:1374
+#: wt-status.c:1373
 msgid " (use -u option to show untracked files)"
 msgstr " (benutzen Sie die Option -u um unbeobachteten Dateien anzuzeigen)"
 
-#: wt-status.c:1380
+#: wt-status.c:1379
 msgid "No changes"
 msgstr "Keine Ã„nderungen"
 
-#: wt-status.c:1385
+#: wt-status.c:1384
 #, c-format
 msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
 msgstr ""
 "keine Ã„nderungen zum Commit vorgemerkt (benutzen Sie \"git add\" und/oder "
 "\"git commit -a\")\n"
 
-#: wt-status.c:1388
+#: wt-status.c:1387
 #, c-format
 msgid "no changes added to commit\n"
 msgstr "keine Ã„nderungen zum Commit vorgemerkt\n"
 
-#: wt-status.c:1391
+#: wt-status.c:1390
 #, c-format
 msgid ""
 "nothing added to commit but untracked files present (use \"git add\" to "
@@ -1871,48 +1882,48 @@ msgstr ""
 "nichts zum Commit vorgemerkt, aber es gibt unbeobachtete Dateien (benutzen "
 "Sie \"git add\" zum Beobachten)\n"
 
-#: wt-status.c:1394
+#: wt-status.c:1393
 #, c-format
 msgid "nothing added to commit but untracked files present\n"
 msgstr "nichts zum Commit vorgemerkt, aber es gibt unbeobachtete Dateien\n"
 
-#: wt-status.c:1397
+#: wt-status.c:1396
 #, c-format
 msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
 msgstr ""
 "nichts zu committen (Erstellen/Kopieren Sie Dateien und benutzen Sie \"git "
 "add\" zum Beobachten)\n"
 
-#: wt-status.c:1400 wt-status.c:1405
+#: wt-status.c:1399 wt-status.c:1404
 #, c-format
 msgid "nothing to commit\n"
 msgstr "nichts zu committen\n"
 
-#: wt-status.c:1403
+#: wt-status.c:1402
 #, c-format
 msgid "nothing to commit (use -u to show untracked files)\n"
 msgstr ""
 "nichts zu committen (benutzen Sie die Option -u, um unbeobachtete Dateien "
 "anzuzeigen)\n"
 
-#: wt-status.c:1407
+#: wt-status.c:1406
 #, c-format
 msgid "nothing to commit, working directory clean\n"
 msgstr "nichts zu committen, Arbeitsverzeichnis unverändert\n"
 
-#: wt-status.c:1516
+#: wt-status.c:1515
 msgid "HEAD (no branch)"
 msgstr "HEAD (kein Branch)"
 
-#: wt-status.c:1522
+#: wt-status.c:1521
 msgid "Initial commit on "
 msgstr "Initialer Commit auf "
 
-#: wt-status.c:1554
+#: wt-status.c:1553
 msgid "gone"
 msgstr "entfernt"
 
-#: wt-status.c:1556 wt-status.c:1564
+#: wt-status.c:1555 wt-status.c:1563
 msgid "behind "
 msgstr "hinterher "
 
@@ -1944,7 +1955,7 @@ msgid "Unstaged changes after refreshing the index:"
 msgstr ""
 "Nicht zum Commit vorgemerkte Ã„nderungen nach Aktualisierung der Staging-Area:"
 
-#: builtin/add.c:193
+#: builtin/add.c:193 builtin/rev-parse.c:781
 msgid "Could not read the index"
 msgstr "Konnte die Staging-Area nicht lesen"
 
@@ -1977,15 +1988,15 @@ msgstr ""
 "Die folgenden Pfade werden durch eine Ihrer \".gitignore\" Dateien "
 "ignoriert:\n"
 
-#: builtin/add.c:248 builtin/clean.c:876 builtin/fetch.c:93 builtin/mv.c:70
-#: builtin/prune-packed.c:77 builtin/push.c:489 builtin/remote.c:1344
+#: builtin/add.c:248 builtin/clean.c:875 builtin/fetch.c:108 builtin/mv.c:70
+#: builtin/prune-packed.c:77 builtin/push.c:488 builtin/remote.c:1367
 #: builtin/rm.c:269
 msgid "dry run"
 msgstr "Probelauf"
 
-#: builtin/add.c:249 builtin/apply.c:4410 builtin/check-ignore.c:19
-#: builtin/commit.c:1256 builtin/count-objects.c:95 builtin/fsck.c:612
-#: builtin/log.c:1592 builtin/mv.c:69 builtin/read-tree.c:113
+#: builtin/add.c:249 builtin/apply.c:4411 builtin/check-ignore.c:19
+#: builtin/commit.c:1328 builtin/count-objects.c:95 builtin/fsck.c:606
+#: builtin/log.c:1613 builtin/mv.c:69 builtin/read-tree.c:113
 msgid "be verbose"
 msgstr "erweiterte Ausgaben"
 
@@ -1993,7 +2004,7 @@ msgstr "erweiterte Ausgaben"
 msgid "interactive picking"
 msgstr "interaktives Auswählen"
 
-#: builtin/add.c:252 builtin/checkout.c:1108 builtin/reset.c:283
+#: builtin/add.c:252 builtin/checkout.c:1102 builtin/reset.c:285
 msgid "select hunks interactively"
 msgstr "Blöcke interaktiv auswählen"
 
@@ -2049,31 +2060,31 @@ msgstr "keine Dateien hinzugefügt"
 msgid "adding files failed"
 msgstr "Hinzufügen von Dateien fehlgeschlagen"
 
-#: builtin/add.c:330
+#: builtin/add.c:329
 msgid "-A and -u are mutually incompatible"
 msgstr "Die Optionen -A und -u sind zueinander inkompatibel."
 
-#: builtin/add.c:337
+#: builtin/add.c:336
 msgid "Option --ignore-missing can only be used together with --dry-run"
 msgstr ""
 "Die Option --ignore-missing kann nur zusammen mit --dry-run verwendet werden."
 
-#: builtin/add.c:358
+#: builtin/add.c:357
 #, c-format
 msgid "Nothing specified, nothing added.\n"
 msgstr "Nichts spezifiziert, nichts hinzugefügt.\n"
 
-#: builtin/add.c:359
+#: builtin/add.c:358
 #, c-format
 msgid "Maybe you wanted to say 'git add .'?\n"
 msgstr "Wollten Sie vielleicht 'git add .' sagen?\n"
 
-#: builtin/add.c:364 builtin/check-ignore.c:172 builtin/clean.c:920
-#: builtin/commit.c:320 builtin/mv.c:90 builtin/reset.c:234 builtin/rm.c:299
+#: builtin/add.c:363 builtin/check-ignore.c:172 builtin/clean.c:919
+#: builtin/commit.c:319 builtin/mv.c:90 builtin/reset.c:234 builtin/rm.c:299
 msgid "index file corrupt"
 msgstr "Staging-Area-Datei beschädigt"
 
-#: builtin/add.c:448 builtin/apply.c:4506 builtin/mv.c:280 builtin/rm.c:432
+#: builtin/add.c:446 builtin/apply.c:4506 builtin/mv.c:280 builtin/rm.c:431
 msgid "Unable to write new index file"
 msgstr "Konnte neue Staging-Area-Datei nicht schreiben."
 
@@ -2091,41 +2102,41 @@ msgstr "nicht erkannte Whitespace-Option: '%s'"
 msgid "unrecognized whitespace ignore option '%s'"
 msgstr "nicht erkannte Option zum Ignorieren von Whitespace: '%s'"
 
-#: builtin/apply.c:823
+#: builtin/apply.c:825
 #, c-format
 msgid "Cannot prepare timestamp regexp %s"
 msgstr "Kann regulären Ausdruck für Zeitstempel %s nicht verarbeiten"
 
-#: builtin/apply.c:832
+#: builtin/apply.c:834
 #, c-format
 msgid "regexec returned %d for input: %s"
 msgstr "Ausführung des regulären Ausdrucks gab %d zurück. Eingabe: %s"
 
-#: builtin/apply.c:913
+#: builtin/apply.c:915
 #, c-format
 msgid "unable to find filename in patch at line %d"
 msgstr "Konnte keinen Dateinamen in Zeile %d des Patches finden."
 
-#: builtin/apply.c:945
+#: builtin/apply.c:947
 #, c-format
 msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d"
 msgstr ""
 "git apply: ungültiges 'git-diff' - erwartete /dev/null, erhielt %s in Zeile "
 "%d"
 
-#: builtin/apply.c:949
+#: builtin/apply.c:951
 #, c-format
 msgid "git apply: bad git-diff - inconsistent new filename on line %d"
 msgstr ""
 "git apply: ungültiges 'git-diff' - Inkonsistenter neuer Dateiname in Zeile %d"
 
-#: builtin/apply.c:950
+#: builtin/apply.c:952
 #, c-format
 msgid "git apply: bad git-diff - inconsistent old filename on line %d"
 msgstr ""
 "git apply: ungültiges 'git-diff' - Inkonsistenter alter Dateiname in Zeile %d"
 
-#: builtin/apply.c:957
+#: builtin/apply.c:959
 #, c-format
 msgid "git apply: bad git-diff - expected /dev/null on line %d"
 msgstr "git apply: ungültiges 'git-diff' - erwartete /dev/null in Zeile %d"
@@ -2240,18 +2251,18 @@ msgstr ""
 msgid "missing binary patch data for '%s'"
 msgstr "keine Daten in Binär-Patch für '%s'"
 
-#: builtin/apply.c:2946
+#: builtin/apply.c:2944
 #, c-format
 msgid "binary patch does not apply to '%s'"
 msgstr "Konnte Binär-Patch nicht auf '%s' anwenden"
 
-#: builtin/apply.c:2952
+#: builtin/apply.c:2950
 #, c-format
 msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)"
 msgstr ""
 "Binär-Patch für '%s' erzeugt falsches Ergebnis (erwartete %s, bekam %s)"
 
-#: builtin/apply.c:2973
+#: builtin/apply.c:2971
 #, c-format
 msgid "patch failed: %s:%ld"
 msgstr "Anwendung des Patches fehlgeschlagen: %s:%ld"
@@ -2340,230 +2351,230 @@ msgstr "make_cache_entry für Pfad '%s' fehlgeschlagen"
 msgid "unable to remove %s from index"
 msgstr "konnte %s nicht aus der Staging-Area entfernen"
 
-#: builtin/apply.c:3851
+#: builtin/apply.c:3852
 #, c-format
 msgid "corrupt patch for submodule %s"
 msgstr "fehlerhafter Patch für Submodul %s"
 
-#: builtin/apply.c:3855
+#: builtin/apply.c:3856
 #, c-format
 msgid "unable to stat newly created file '%s'"
 msgstr "konnte neu erstellte Datei '%s' nicht lesen"
 
-#: builtin/apply.c:3860
+#: builtin/apply.c:3861
 #, c-format
 msgid "unable to create backing store for newly created file %s"
 msgstr "kann internen Speicher für eben erstellte Datei %s nicht erzeugen"
 
-#: builtin/apply.c:3863 builtin/apply.c:3971
+#: builtin/apply.c:3864 builtin/apply.c:3972
 #, c-format
 msgid "unable to add cache entry for %s"
 msgstr "kann für %s keinen Eintrag in den Zwischenspeicher hinzufügen"
 
-#: builtin/apply.c:3896
+#: builtin/apply.c:3897
 #, c-format
 msgid "closing file '%s'"
 msgstr "schließe Datei '%s'"
 
-#: builtin/apply.c:3945
+#: builtin/apply.c:3946
 #, c-format
 msgid "unable to write file '%s' mode %o"
 msgstr "konnte Datei '%s' mit Modus %o nicht schreiben"
 
-#: builtin/apply.c:4032
+#: builtin/apply.c:4033
 #, c-format
 msgid "Applied patch %s cleanly."
 msgstr "Patch %s sauber angewendet"
 
-#: builtin/apply.c:4040
+#: builtin/apply.c:4041
 msgid "internal error"
 msgstr "interner Fehler"
 
-#: builtin/apply.c:4043
+#: builtin/apply.c:4044
 #, c-format
 msgid "Applying patch %%s with %d reject..."
 msgid_plural "Applying patch %%s with %d rejects..."
 msgstr[0] "Wende Patch %%s mit %d Zurückweisung an..."
 msgstr[1] "Wende Patch %%s mit %d Zurückweisungen an..."
 
-#: builtin/apply.c:4053
+#: builtin/apply.c:4054
 #, c-format
 msgid "truncating .rej filename to %.*s.rej"
 msgstr "Verkürze Name von .rej Datei zu %.*s.rej"
 
-#: builtin/apply.c:4074
+#: builtin/apply.c:4075
 #, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr "Patch-Bereich #%d sauber angewendet."
 
-#: builtin/apply.c:4077
+#: builtin/apply.c:4078
 #, c-format
 msgid "Rejected hunk #%d."
 msgstr "Patch-Block #%d zurückgewiesen."
 
-#: builtin/apply.c:4227
+#: builtin/apply.c:4228
 msgid "unrecognized input"
 msgstr "nicht erkannte Eingabe"
 
-#: builtin/apply.c:4238
+#: builtin/apply.c:4239
 msgid "unable to read index file"
 msgstr "Konnte Staging-Area-Datei nicht lesen"
 
-#: builtin/apply.c:4357 builtin/apply.c:4360 builtin/clone.c:90
-#: builtin/fetch.c:78
+#: builtin/apply.c:4358 builtin/apply.c:4361 builtin/clone.c:90
+#: builtin/fetch.c:93
 msgid "path"
 msgstr "Pfad"
 
-#: builtin/apply.c:4358
+#: builtin/apply.c:4359
 msgid "don't apply changes matching the given path"
 msgstr "wendet keine Ã„nderungen im angegebenen Pfad an"
 
-#: builtin/apply.c:4361
+#: builtin/apply.c:4362
 msgid "apply changes matching the given path"
 msgstr "wendet Ã„nderungen nur im angegebenen Pfad an"
 
-#: builtin/apply.c:4363
+#: builtin/apply.c:4364
 msgid "num"
 msgstr "Anzahl"
 
-#: builtin/apply.c:4364
+#: builtin/apply.c:4365
 msgid "remove <num> leading slashes from traditional diff paths"
 msgstr ""
 "entfernt <Anzahl> vorangestellte Schrägstriche von herkömmlichen "
 "Differenzpfaden"
 
-#: builtin/apply.c:4367
+#: builtin/apply.c:4368
 msgid "ignore additions made by the patch"
 msgstr "ignoriert hinzugefügte Zeilen des Patches"
 
-#: builtin/apply.c:4369
+#: builtin/apply.c:4370
 msgid "instead of applying the patch, output diffstat for the input"
 msgstr ""
 "anstatt der Anwendung des Patches, wird der \"diffstat\" für die Eingabe "
 "ausgegeben"
 
-#: builtin/apply.c:4373
+#: builtin/apply.c:4374
 msgid "show number of added and deleted lines in decimal notation"
 msgstr ""
 "zeigt die Anzahl von hinzugefügten/entfernten Zeilen in Dezimalnotation"
 
-#: builtin/apply.c:4375
+#: builtin/apply.c:4376
 msgid "instead of applying the patch, output a summary for the input"
 msgstr ""
 "anstatt der Anwendung des Patches, wird eine Zusammenfassung für die Eingabe "
 "ausgegeben"
 
-#: builtin/apply.c:4377
+#: builtin/apply.c:4378
 msgid "instead of applying the patch, see if the patch is applicable"
 msgstr ""
 "anstatt der Anwendung des Patches, zeige ob Patch angewendet werden kann"
 
-#: builtin/apply.c:4379
+#: builtin/apply.c:4380
 msgid "make sure the patch is applicable to the current index"
 msgstr ""
 "stellt sicher, dass der Patch in der aktuellen Staging-Area angewendet "
 "werden kann"
 
-#: builtin/apply.c:4381
+#: builtin/apply.c:4382
 msgid "apply a patch without touching the working tree"
 msgstr ""
 "wendet einen Patch an, ohne Ã„nderungen im Arbeitsverzeichnis vorzunehmen"
 
-#: builtin/apply.c:4383
+#: builtin/apply.c:4384
 msgid "also apply the patch (use with --stat/--summary/--check)"
 msgstr "wendet den Patch an (Benutzung mit --stat/--summary/--check)"
 
-#: builtin/apply.c:4385
+#: builtin/apply.c:4386
 msgid "attempt three-way merge if a patch does not apply"
 msgstr "versucht 3-Wege-Merge, wenn der Patch nicht angewendet werden konnte"
 
-#: builtin/apply.c:4387
+#: builtin/apply.c:4388
 msgid "build a temporary index based on embedded index information"
 msgstr ""
 "erstellt eine temporäre Staging-Area basierend auf den integrierten Staging-"
 "Area-Informationen"
 
-#: builtin/apply.c:4389 builtin/checkout-index.c:197 builtin/ls-files.c:455
+#: builtin/apply.c:4390 builtin/checkout-index.c:198 builtin/ls-files.c:455
 msgid "paths are separated with NUL character"
 msgstr "Pfade sind getrennt durch NUL Zeichen"
 
-#: builtin/apply.c:4392
+#: builtin/apply.c:4393
 msgid "ensure at least <n> lines of context match"
 msgstr "stellt sicher, dass mindestens <n> Zeilen des Kontextes Ã¼bereinstimmen"
 
-#: builtin/apply.c:4393
+#: builtin/apply.c:4394
 msgid "action"
 msgstr "Aktion"
 
-#: builtin/apply.c:4394
+#: builtin/apply.c:4395
 msgid "detect new or modified lines that have whitespace errors"
 msgstr "ermittelt neue oder geänderte Zeilen die Whitespace-Fehler haben"
 
-#: builtin/apply.c:4397 builtin/apply.c:4400
+#: builtin/apply.c:4398 builtin/apply.c:4401
 msgid "ignore changes in whitespace when finding context"
 msgstr "ignoriert Ã„nderungen im Whitespace bei der Suche des Kontextes"
 
-#: builtin/apply.c:4403
+#: builtin/apply.c:4404
 msgid "apply the patch in reverse"
 msgstr "wendet den Patch in umgekehrter Reihenfolge an"
 
-#: builtin/apply.c:4405
+#: builtin/apply.c:4406
 msgid "don't expect at least one line of context"
 msgstr "erwartet keinen Kontext"
 
-#: builtin/apply.c:4407
+#: builtin/apply.c:4408
 msgid "leave the rejected hunks in corresponding *.rej files"
 msgstr ""
 "hinterlässt zurückgewiesene Patch-Blöcke in entsprechenden *.rej Dateien"
 
-#: builtin/apply.c:4409
+#: builtin/apply.c:4410
 msgid "allow overlapping hunks"
 msgstr "erlaubt sich Ã¼berlappende Patch-Blöcke"
 
-#: builtin/apply.c:4412
+#: builtin/apply.c:4413
 msgid "tolerate incorrectly detected missing new-line at the end of file"
 msgstr "toleriert fehlerhaft erkannten fehlenden Zeilenumbruch am Dateiende"
 
-#: builtin/apply.c:4415
+#: builtin/apply.c:4416
 msgid "do not trust the line counts in the hunk headers"
 msgstr "vertraut nicht den Zeilennummern im Kopf des Patch-Blocks"
 
-#: builtin/apply.c:4417
+#: builtin/apply.c:4418
 msgid "root"
 msgstr "Wurzelverzeichnis"
 
-#: builtin/apply.c:4418
+#: builtin/apply.c:4419
 msgid "prepend <root> to all filenames"
 msgstr "stellt <Wurzelverzeichnis> vor alle Dateinamen"
 
-#: builtin/apply.c:4440
+#: builtin/apply.c:4441
 msgid "--3way outside a repository"
 msgstr ""
 "Die Option --3way kann nicht außerhalb eines Repositories verwendet werden."
 
-#: builtin/apply.c:4448
+#: builtin/apply.c:4449
 msgid "--index outside a repository"
 msgstr ""
 "Die Option --index kann nicht außerhalb eines Repositories verwendet werden."
 
-#: builtin/apply.c:4451
+#: builtin/apply.c:4452
 msgid "--cached outside a repository"
 msgstr ""
 "Die Option --cached kann nicht außerhalb eines Repositories verwendet werden."
 
-#: builtin/apply.c:4467
+#: builtin/apply.c:4468
 #, c-format
 msgid "can't open patch '%s'"
 msgstr "kann Patch '%s' nicht Ã¶ffnen"
 
-#: builtin/apply.c:4481
+#: builtin/apply.c:4482
 #, c-format
 msgid "squelched %d whitespace error"
 msgid_plural "squelched %d whitespace errors"
 msgstr[0] "unterdrückte %d Whitespace-Fehler"
 msgstr[1] "unterdrückte %d Whitespace-Fehler"
 
-#: builtin/apply.c:4487 builtin/apply.c:4497
+#: builtin/apply.c:4488 builtin/apply.c:4498
 #, c-format
 msgid "%d line adds whitespace errors."
 msgid_plural "%d lines add whitespace errors."
@@ -2617,107 +2628,117 @@ msgstr "führt 'git bisect next' aus"
 msgid "update BISECT_HEAD instead of checking out the current commit"
 msgstr "aktualisiert BISECT_HEAD, anstatt den aktuellen Commit auszuchecken"
 
-#: builtin/blame.c:27
+#: builtin/blame.c:30
 msgid "git blame [options] [rev-opts] [rev] [--] file"
 msgstr "git blame [Optionen] [rev-opts] [rev] [--] Datei"
 
-#: builtin/blame.c:32
+#: builtin/blame.c:35
 msgid "[rev-opts] are documented in git-rev-list(1)"
 msgstr "[rev-opts] sind dokumentiert in git-rev-list(1)"
 
-#: builtin/blame.c:2242
+#: builtin/blame.c:2501
 msgid "Show blame entries as we find them, incrementally"
 msgstr "Zeigt \"blame\"-Einträge schrittweise, während wir sie generieren"
 
-#: builtin/blame.c:2243
+#: builtin/blame.c:2502
 msgid "Show blank SHA-1 for boundary commits (Default: off)"
 msgstr "Zeigt leere SHA-1 für Grenz-Commits (Standard: aus)"
 
-#: builtin/blame.c:2244
+#: builtin/blame.c:2503
 msgid "Do not treat root commits as boundaries (Default: off)"
 msgstr "Behandelt Ursprungs-Commit nicht als Grenzen (Standard: aus)"
 
-#: builtin/blame.c:2245
+#: builtin/blame.c:2504
 msgid "Show work cost statistics"
 msgstr "Zeigt Statistiken zum Arbeitsaufwand"
 
-#: builtin/blame.c:2246
+#: builtin/blame.c:2505
 msgid "Show output score for blame entries"
 msgstr "Zeigt Ausgabebewertung für \"blame\"-Einträge"
 
-#: builtin/blame.c:2247
+#: builtin/blame.c:2506
 msgid "Show original filename (Default: auto)"
 msgstr "Zeigt ursprünglichen Dateinamen (Standard: auto)"
 
-#: builtin/blame.c:2248
+#: builtin/blame.c:2507
 msgid "Show original linenumber (Default: off)"
 msgstr "Zeigt ursprüngliche Zeilennummer (Standard: aus)"
 
-#: builtin/blame.c:2249
+#: builtin/blame.c:2508
 msgid "Show in a format designed for machine consumption"
 msgstr "Anzeige in einem Format für maschinelle Auswertung"
 
-#: builtin/blame.c:2250
+#: builtin/blame.c:2509
 msgid "Show porcelain format with per-line commit information"
 msgstr ""
 "Anzeige in Format für Fremdprogramme mit Commit-Informationen pro Zeile"
 
-#: builtin/blame.c:2251
+#: builtin/blame.c:2510
 msgid "Use the same output mode as git-annotate (Default: off)"
 msgstr "Benutzt den gleichen Ausgabemodus wie \"git-annotate\" (Standard: aus)"
 
-#: builtin/blame.c:2252
+#: builtin/blame.c:2511
 msgid "Show raw timestamp (Default: off)"
 msgstr "Zeigt unbearbeiteten Zeitstempel (Standard: aus)"
 
-#: builtin/blame.c:2253
+#: builtin/blame.c:2512
 msgid "Show long commit SHA1 (Default: off)"
 msgstr "Zeigt langen Commit-SHA1 (Standard: aus)"
 
-#: builtin/blame.c:2254
+#: builtin/blame.c:2513
 msgid "Suppress author name and timestamp (Default: off)"
 msgstr "Unterdrückt den Namen des Autors und den Zeitstempel (Standard: aus)"
 
-#: builtin/blame.c:2255
+#: builtin/blame.c:2514
 msgid "Show author email instead of name (Default: off)"
 msgstr "Zeigt anstatt des Namens die Email-Adresse des Autors (Standard: aus)"
 
-#: builtin/blame.c:2256
+#: builtin/blame.c:2515
 msgid "Ignore whitespace differences"
 msgstr "Ignoriert Unterschiede im Whitespace"
 
-#: builtin/blame.c:2257
+#: builtin/blame.c:2516
 msgid "Spend extra cycles to find better match"
 msgstr "arbeite länger, um bessere Ãœbereinstimmungen zu finden"
 
-#: builtin/blame.c:2258
+#: builtin/blame.c:2517
 msgid "Use revisions from <file> instead of calling git-rev-list"
 msgstr "Benutzt Commits von <Datei> anstatt \"git-rev-list\" aufzurufen"
 
-#: builtin/blame.c:2259
+#: builtin/blame.c:2518
 msgid "Use <file>'s contents as the final image"
 msgstr "Benutzt Inhalte der <Datei>en als entgültiges Abbild"
 
-#: builtin/blame.c:2260 builtin/blame.c:2261
+#: builtin/blame.c:2519 builtin/blame.c:2520
 msgid "score"
 msgstr "Bewertung"
 
-#: builtin/blame.c:2260
+#: builtin/blame.c:2519
 msgid "Find line copies within and across files"
 msgstr "Findet kopierte Zeilen innerhalb oder zwischen Dateien"
 
-#: builtin/blame.c:2261
+#: builtin/blame.c:2520
 msgid "Find line movements within and across files"
 msgstr "Findet verschobene Zeilen innerhalb oder zwischen Dateien"
 
-#: builtin/blame.c:2262
+#: builtin/blame.c:2521
 msgid "n,m"
 msgstr "n,m"
 
-#: builtin/blame.c:2262
+#: builtin/blame.c:2521
 msgid "Process only line range n,m, counting from 1"
 msgstr "Verarbeitet nur Zeilen im Bereich n,m, gezählt von 1"
 
+#. TRANSLATORS: This string is used to tell us the maximum
+#. display width for a relative timestamp in "git blame"
+#. output.  For C locale, "4 years, 11 months ago", which
+#. takes 22 places, is the longest among various forms of
+#. relative timestamps, but your language may need more or
+#. fewer display columns.
+#: builtin/blame.c:2599
+msgid "4 years, 11 months ago"
+msgstr "vor 4 Jahren, und 11 Monaten"
+
 #: builtin/branch.c:24
 msgid "git branch [options] [-r | -a] [--merged | --no-merged]"
 msgstr "git branch [Optionen] [-r | -a] [--merged | --no-merged]"
@@ -2961,9 +2982,9 @@ msgid "act on remote-tracking branches"
 msgstr "wirkt auf Remote-Tracking-Branches"
 
 #: builtin/branch.c:817 builtin/branch.c:823 builtin/branch.c:844
-#: builtin/branch.c:850 builtin/commit.c:1494 builtin/commit.c:1495
-#: builtin/commit.c:1496 builtin/commit.c:1497 builtin/tag.c:527
-#: builtin/tag.c:533
+#: builtin/branch.c:850 builtin/commit.c:1573 builtin/commit.c:1574
+#: builtin/commit.c:1575 builtin/commit.c:1576 builtin/tag.c:615
+#: builtin/tag.c:621
 msgid "commit"
 msgstr "Commit"
 
@@ -3028,7 +3049,7 @@ msgstr "listet Branches in Spalten auf"
 msgid "Failed to resolve HEAD as a valid ref."
 msgstr "Konnte HEAD nicht als gültige Referenz auflösen."
 
-#: builtin/branch.c:872 builtin/clone.c:635
+#: builtin/branch.c:872 builtin/clone.c:636
 msgid "HEAD not found below refs/heads!"
 msgstr "HEAD wurde nicht unter \"refs/heads\" gefunden!"
 
@@ -3221,7 +3242,7 @@ msgstr "liest Dateinamen von der Standard-Eingabe"
 msgid "terminate input and output records by a NUL character"
 msgstr "schließt Einträge von Ein- und Ausgabe mit NUL-Zeichen ab"
 
-#: builtin/check-ignore.c:18 builtin/checkout.c:1089 builtin/gc.c:271
+#: builtin/check-ignore.c:18 builtin/checkout.c:1083 builtin/gc.c:285
 msgid "suppress progress reporting"
 msgstr "unterdrückt Fortschrittsanzeige"
 
@@ -3279,46 +3300,46 @@ msgstr "keine Kontakte angegeben"
 msgid "git checkout-index [options] [--] [<file>...]"
 msgstr "git checkout-index [Optionen] [--] [<Datei>...]"
 
-#: builtin/checkout-index.c:187
+#: builtin/checkout-index.c:188
 msgid "check out all files in the index"
 msgstr "checkt alle Dateien in der Staging-Area aus"
 
-#: builtin/checkout-index.c:188
+#: builtin/checkout-index.c:189
 msgid "force overwrite of existing files"
 msgstr "erzwingt das Ãœberschreiben bereits existierender Dateien"
 
-#: builtin/checkout-index.c:190
+#: builtin/checkout-index.c:191
 msgid "no warning for existing files and files not in index"
 msgstr ""
 "keine Warnung für existierende Dateien, und Dateien, die sich nicht in der "
 "Staging-Area befinden"
 
-#: builtin/checkout-index.c:192
+#: builtin/checkout-index.c:193
 msgid "don't checkout new files"
 msgstr "checkt keine neuen Dateien aus"
 
-#: builtin/checkout-index.c:194
+#: builtin/checkout-index.c:195
 msgid "update stat information in the index file"
 msgstr "aktualisiert Dateiinformationen in der Staging-Area-Datei"
 
-#: builtin/checkout-index.c:200
+#: builtin/checkout-index.c:201
 msgid "read list of paths from the standard input"
 msgstr "liest eine Liste von Pfaden von der Standard-Eingabe"
 
-#: builtin/checkout-index.c:202
+#: builtin/checkout-index.c:203
 msgid "write the content to temporary files"
 msgstr "schreibt den Inhalt in temporäre Dateien"
 
-#: builtin/checkout-index.c:203 builtin/column.c:30
+#: builtin/checkout-index.c:204 builtin/column.c:30
 msgid "string"
 msgstr "Zeichenkette"
 
-#: builtin/checkout-index.c:204
+#: builtin/checkout-index.c:205
 msgid "when creating files, prepend <string>"
 msgstr ""
 "wenn Dateien erzeugt werden, stelle <Zeichenkette> dem Dateinamen voran"
 
-#: builtin/checkout-index.c:207
+#: builtin/checkout-index.c:208
 msgid "copy out the files from named stage"
 msgstr "kopiert Dateien von dem benannten Stand"
 
@@ -3360,76 +3381,76 @@ msgstr "Pfad '%s': kann nicht zusammenführen"
 msgid "Unable to add merge result for '%s'"
 msgstr "Konnte Merge-Ergebnis von '%s' nicht hinzufügen."
 
-#: builtin/checkout.c:232 builtin/checkout.c:235 builtin/checkout.c:238
-#: builtin/checkout.c:241
+#: builtin/checkout.c:231 builtin/checkout.c:234 builtin/checkout.c:237
+#: builtin/checkout.c:240
 #, c-format
 msgid "'%s' cannot be used with updating paths"
 msgstr "'%s' kann nicht mit Pfaden verwendet werden"
 
-#: builtin/checkout.c:244 builtin/checkout.c:247
+#: builtin/checkout.c:243 builtin/checkout.c:246
 #, c-format
 msgid "'%s' cannot be used with %s"
 msgstr "'%s' kann nicht mit '%s' verwendet werden"
 
-#: builtin/checkout.c:250
+#: builtin/checkout.c:249
 #, c-format
 msgid "Cannot update paths and switch to branch '%s' at the same time."
 msgstr ""
 "Kann nicht gleichzeitig Pfade aktualisieren und zu Branch '%s' wechseln"
 
-#: builtin/checkout.c:261 builtin/checkout.c:450
+#: builtin/checkout.c:260 builtin/checkout.c:449
 msgid "corrupt index file"
 msgstr "beschädigte Staging-Area-Datei"
 
-#: builtin/checkout.c:321 builtin/checkout.c:328
+#: builtin/checkout.c:320 builtin/checkout.c:327
 #, c-format
 msgid "path '%s' is unmerged"
 msgstr "Pfad '%s' ist nicht zusammengeführt."
 
-#: builtin/checkout.c:472
+#: builtin/checkout.c:471
 msgid "you need to resolve your current index first"
 msgstr "Sie müssen zuerst Ihre aktuelle Staging-Area auflösen."
 
-#: builtin/checkout.c:593
+#: builtin/checkout.c:591
 #, c-format
 msgid "Can not do reflog for '%s'\n"
 msgstr "Konnte \"reflog\" für '%s' nicht durchführen\n"
 
-#: builtin/checkout.c:631
+#: builtin/checkout.c:629
 msgid "HEAD is now at"
 msgstr "HEAD ist jetzt bei"
 
-#: builtin/checkout.c:638
+#: builtin/checkout.c:636
 #, c-format
 msgid "Reset branch '%s'\n"
 msgstr "Setze Branch '%s' neu\n"
 
-#: builtin/checkout.c:641
+#: builtin/checkout.c:639
 #, c-format
 msgid "Already on '%s'\n"
 msgstr "Bereits auf '%s'\n"
 
-#: builtin/checkout.c:645
+#: builtin/checkout.c:643
 #, c-format
 msgid "Switched to and reset branch '%s'\n"
 msgstr "Zu umgesetztem Branch '%s' gewechselt\n"
 
-#: builtin/checkout.c:647 builtin/checkout.c:1032
+#: builtin/checkout.c:645 builtin/checkout.c:1026
 #, c-format
 msgid "Switched to a new branch '%s'\n"
 msgstr "Zu neuem Branch '%s' gewechselt\n"
 
-#: builtin/checkout.c:649
+#: builtin/checkout.c:647
 #, c-format
 msgid "Switched to branch '%s'\n"
 msgstr "Zu Branch '%s' gewechselt\n"
 
-#: builtin/checkout.c:705
+#: builtin/checkout.c:699
 #, c-format
 msgid " ... and %d more.\n"
 msgstr " ... und %d weitere.\n"
 
-#: builtin/checkout.c:711
+#: builtin/checkout.c:705
 #, c-format
 msgid ""
 "Warning: you are leaving %d commit behind, not connected to\n"
@@ -3452,7 +3473,7 @@ msgstr[1] ""
 "\n"
 "%s\n"
 
-#: builtin/checkout.c:729
+#: builtin/checkout.c:723
 #, c-format
 msgid ""
 "If you want to keep them by creating a new branch, this may be a good time\n"
@@ -3467,139 +3488,139 @@ msgstr ""
 " git branch neuer_branch_name %s\n"
 "\n"
 
-#: builtin/checkout.c:759
+#: builtin/checkout.c:753
 msgid "internal error in revision walk"
 msgstr "interner Fehler im Revisionsgang"
 
-#: builtin/checkout.c:763
+#: builtin/checkout.c:757
 msgid "Previous HEAD position was"
 msgstr "Vorherige Position von HEAD war"
 
-#: builtin/checkout.c:790 builtin/checkout.c:1027
+#: builtin/checkout.c:784 builtin/checkout.c:1021
 msgid "You are on a branch yet to be born"
 msgstr "Sie sind auf einem Branch, der noch geboren wird"
 
-#: builtin/checkout.c:934
+#: builtin/checkout.c:928
 #, c-format
 msgid "only one reference expected, %d given."
 msgstr "nur eine Referenz erwartet, %d gegeben."
 
-#: builtin/checkout.c:973
+#: builtin/checkout.c:967
 #, c-format
 msgid "invalid reference: %s"
 msgstr "Ungültige Referenz: %s"
 
-#: builtin/checkout.c:1002
+#: builtin/checkout.c:996
 #, c-format
 msgid "reference is not a tree: %s"
 msgstr "Referenz ist kein \"Tree\"-Objekt: %s"
 
-#: builtin/checkout.c:1041
+#: builtin/checkout.c:1035
 msgid "paths cannot be used with switching branches"
 msgstr "Pfade können nicht beim Wechseln von Branches verwendet werden"
 
-#: builtin/checkout.c:1044 builtin/checkout.c:1048
+#: builtin/checkout.c:1038 builtin/checkout.c:1042
 #, c-format
 msgid "'%s' cannot be used with switching branches"
 msgstr "'%s' kann nicht beim Wechseln von Branches verwendet werden"
 
-#: builtin/checkout.c:1052 builtin/checkout.c:1055 builtin/checkout.c:1060
-#: builtin/checkout.c:1063
+#: builtin/checkout.c:1046 builtin/checkout.c:1049 builtin/checkout.c:1054
+#: builtin/checkout.c:1057
 #, c-format
 msgid "'%s' cannot be used with '%s'"
 msgstr "'%s' kann nicht mit '%s' verwendet werden"
 
-#: builtin/checkout.c:1068
+#: builtin/checkout.c:1062
 #, c-format
 msgid "Cannot switch branch to a non-commit '%s'"
 msgstr "Kann Branch nicht zu Nicht-Commit '%s' wechseln"
 
-#: builtin/checkout.c:1090 builtin/checkout.c:1092 builtin/clone.c:88
+#: builtin/checkout.c:1084 builtin/checkout.c:1086 builtin/clone.c:88
 #: builtin/remote.c:159 builtin/remote.c:161
 msgid "branch"
 msgstr "Branch"
 
-#: builtin/checkout.c:1091
+#: builtin/checkout.c:1085
 msgid "create and checkout a new branch"
 msgstr "erzeugt und checkt einen neuen Branch aus"
 
-#: builtin/checkout.c:1093
+#: builtin/checkout.c:1087
 msgid "create/reset and checkout a branch"
 msgstr "erzeugt/setzt um und checkt einen Branch aus"
 
-#: builtin/checkout.c:1094
+#: builtin/checkout.c:1088
 msgid "create reflog for new branch"
 msgstr "erzeugt das Reflog für den neuen Branch"
 
-#: builtin/checkout.c:1095
+#: builtin/checkout.c:1089
 msgid "detach the HEAD at named commit"
 msgstr "setzt HEAD zu benanntem Commit"
 
-#: builtin/checkout.c:1096
+#: builtin/checkout.c:1090
 msgid "set upstream info for new branch"
 msgstr "setzt Informationen zum Upstream-Branch für den neuen Branch"
 
-#: builtin/checkout.c:1098
+#: builtin/checkout.c:1092
 msgid "new-branch"
 msgstr "neuer Branch"
 
-#: builtin/checkout.c:1098
+#: builtin/checkout.c:1092
 msgid "new unparented branch"
 msgstr "neuer Branch ohne Eltern-Commit"
 
-#: builtin/checkout.c:1099
+#: builtin/checkout.c:1093
 msgid "checkout our version for unmerged files"
 msgstr "checkt unsere Variante für nicht zusammengeführte Dateien aus"
 
-#: builtin/checkout.c:1101
+#: builtin/checkout.c:1095
 msgid "checkout their version for unmerged files"
 msgstr "checkt ihre Variante für nicht zusammengeführte Dateien aus"
 
-#: builtin/checkout.c:1103
+#: builtin/checkout.c:1097
 msgid "force checkout (throw away local modifications)"
 msgstr "erzwingt Auschecken (verwirft lokale Ã„nderungen)"
 
-#: builtin/checkout.c:1104
+#: builtin/checkout.c:1098
 msgid "perform a 3-way merge with the new branch"
 msgstr "führt einen 3-Wege-Merge mit dem neuen Branch aus"
 
-#: builtin/checkout.c:1105 builtin/merge.c:225
+#: builtin/checkout.c:1099 builtin/merge.c:225
 msgid "update ignored files (default)"
 msgstr "aktualisiert ignorierte Dateien (Standard)"
 
-#: builtin/checkout.c:1106 builtin/log.c:1228 parse-options.h:245
+#: builtin/checkout.c:1100 builtin/log.c:1236 parse-options.h:245
 msgid "style"
 msgstr "Stil"
 
-#: builtin/checkout.c:1107
+#: builtin/checkout.c:1101
 msgid "conflict style (merge or diff3)"
 msgstr "Konfliktstil (merge oder diff3)"
 
-#: builtin/checkout.c:1110
+#: builtin/checkout.c:1104
 msgid "do not limit pathspecs to sparse entries only"
 msgstr "Pfadspezifikationen ignorieren Einstellungen zum partiellen Auschecken"
 
-#: builtin/checkout.c:1112
+#: builtin/checkout.c:1106
 msgid "second guess 'git checkout no-such-branch'"
 msgstr "second guess 'git checkout no-such-branch'"
 
-#: builtin/checkout.c:1135
+#: builtin/checkout.c:1129
 msgid "-b, -B and --orphan are mutually exclusive"
 msgstr "Die Optionen -b, -B und --orphan schließen sich gegenseitig aus."
 
-#: builtin/checkout.c:1152
+#: builtin/checkout.c:1146
 msgid "--track needs a branch name"
 msgstr "Bei der Option --track muss ein Branchname angegeben werden."
 
-#: builtin/checkout.c:1159
+#: builtin/checkout.c:1153
 msgid "Missing branch name; try -b"
 msgstr "Vermisse Branchnamen; versuchen Sie -b"
 
-#: builtin/checkout.c:1196
+#: builtin/checkout.c:1190
 msgid "invalid path specification"
 msgstr "ungültige Pfadspezifikation"
 
-#: builtin/checkout.c:1203
+#: builtin/checkout.c:1197
 #, c-format
 msgid ""
 "Cannot update paths and switch to branch '%s' at the same time.\n"
@@ -3609,12 +3630,12 @@ msgstr ""
 "Haben Sie beabsichtigt '%s' auszuchecken, welcher nicht als Commit aufgelöst "
 "werden kann?"
 
-#: builtin/checkout.c:1208
+#: builtin/checkout.c:1202
 #, c-format
 msgid "git checkout: --detach does not take a path argument '%s'"
 msgstr "git checkout: --detach nimmt kein Pfad-Argument '%s'"
 
-#: builtin/checkout.c:1212
+#: builtin/checkout.c:1206
 msgid ""
 "git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
 "checking out of the index."
@@ -3690,30 +3711,30 @@ msgstr ""
 msgid "Huh (%s)?"
 msgstr "Wie bitte (%s)?"
 
-#: builtin/clean.c:660
+#: builtin/clean.c:659
 #, c-format
 msgid "Input ignore patterns>> "
 msgstr "Ignorier-Muster eingeben>> "
 
-#: builtin/clean.c:697
+#: builtin/clean.c:696
 #, c-format
 msgid "WARNING: Cannot find items matched by: %s"
 msgstr "WARNUNG: Kann keine Einträge finden die Muster entsprechen: %s"
 
-#: builtin/clean.c:718
+#: builtin/clean.c:717
 msgid "Select items to delete"
 msgstr "Wählen Sie Einträge zum Löschen"
 
-#: builtin/clean.c:758
+#: builtin/clean.c:757
 #, c-format
 msgid "remove %s? "
 msgstr "'%s' löschen? "
 
-#: builtin/clean.c:783
+#: builtin/clean.c:782
 msgid "Bye."
 msgstr "Tschüss."
 
-#: builtin/clean.c:791
+#: builtin/clean.c:790
 msgid ""
 "clean               - start cleaning\n"
 "filter by pattern   - exclude items from deletion\n"
@@ -3731,62 +3752,62 @@ msgstr ""
 "help                - diese Meldung anzeigen\n"
 "?                   - Hilfe zur Auswahl mittels Eingabe anzeigen"
 
-#: builtin/clean.c:818
+#: builtin/clean.c:817
 msgid "*** Commands ***"
 msgstr "*** Kommandos ***"
 
-#: builtin/clean.c:819
+#: builtin/clean.c:818
 msgid "What now"
 msgstr "Was nun"
 
-#: builtin/clean.c:827
+#: builtin/clean.c:826
 msgid "Would remove the following item:"
 msgid_plural "Would remove the following items:"
 msgstr[0] "Würde das folgende Element entfernen:"
 msgstr[1] "Würde die folgenden Elemente entfernen:"
 
-#: builtin/clean.c:844
+#: builtin/clean.c:843
 msgid "No more files to clean, exiting."
 msgstr "Keine Dateien mehr zum Löschen, beende."
 
-#: builtin/clean.c:875
+#: builtin/clean.c:874
 msgid "do not print names of files removed"
 msgstr "gibt keine Namen von gelöschten Dateien aus"
 
-#: builtin/clean.c:877
+#: builtin/clean.c:876
 msgid "force"
 msgstr "erzwingt Aktion"
 
-#: builtin/clean.c:878
+#: builtin/clean.c:877
 msgid "interactive cleaning"
 msgstr "interaktives Clean"
 
-#: builtin/clean.c:880
+#: builtin/clean.c:879
 msgid "remove whole directories"
 msgstr "löscht ganze Verzeichnisse"
 
-#: builtin/clean.c:881 builtin/describe.c:415 builtin/grep.c:716
-#: builtin/ls-files.c:486 builtin/name-rev.c:314 builtin/show-ref.c:185
+#: builtin/clean.c:880 builtin/describe.c:406 builtin/grep.c:714
+#: builtin/ls-files.c:486 builtin/name-rev.c:311 builtin/show-ref.c:185
 msgid "pattern"
 msgstr "Muster"
 
-#: builtin/clean.c:882
+#: builtin/clean.c:881
 msgid "add <pattern> to ignore rules"
 msgstr "fügt <Muster> zu den Regeln für ignorierte Pfade hinzu"
 
-#: builtin/clean.c:883
+#: builtin/clean.c:882
 msgid "remove ignored files, too"
 msgstr "löscht auch ignorierte Dateien"
 
-#: builtin/clean.c:885
+#: builtin/clean.c:884
 msgid "remove only ignored files"
 msgstr "löscht nur ignorierte Dateien"
 
-#: builtin/clean.c:903
+#: builtin/clean.c:902
 msgid "-x and -X cannot be used together"
 msgstr "Die Optionen -x und -X können nicht gemeinsam verwendet werden."
 
-#: builtin/clean.c:907
+#: builtin/clean.c:906
 msgid ""
 "clean.requireForce set to true and neither -i, -n, nor -f given; refusing to "
 "clean"
@@ -3794,7 +3815,7 @@ msgstr ""
 "clean.requireForce auf \"true\" gesetzt und weder -i, -n noch -f gegeben; "
 "\"clean\" verweigert"
 
-#: builtin/clean.c:910
+#: builtin/clean.c:909
 msgid ""
 "clean.requireForce defaults to true and neither -i, -n, nor -f given; "
 "refusing to clean"
@@ -3806,8 +3827,8 @@ msgstr ""
 msgid "git clone [options] [--] <repo> [<dir>]"
 msgstr "git clone [Optionen] [--] <Repository> [<Verzeichnis>]"
 
-#: builtin/clone.c:64 builtin/fetch.c:97 builtin/merge.c:222
-#: builtin/push.c:504
+#: builtin/clone.c:64 builtin/fetch.c:112 builtin/merge.c:222
+#: builtin/push.c:503
 msgid "force progress reporting"
 msgstr "erzwingt Fortschrittsanzeige"
 
@@ -3867,7 +3888,7 @@ msgstr "checkt <Branch> aus, anstatt HEAD des Remote-Repositories"
 msgid "path to git-upload-pack on the remote"
 msgstr "Pfad zu \"git-upload-pack\" auf der Gegenseite"
 
-#: builtin/clone.c:92 builtin/fetch.c:98 builtin/grep.c:661
+#: builtin/clone.c:92 builtin/fetch.c:113 builtin/grep.c:659
 msgid "depth"
 msgstr "Tiefe"
 
@@ -3973,100 +3994,100 @@ msgstr "Prüfe Konnektivität... "
 msgid "remote did not send all necessary objects"
 msgstr "Remote-Repository hat nicht alle erforderlichen Objekte gesendet."
 
-#: builtin/clone.c:626
+#: builtin/clone.c:627
 msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n"
 msgstr ""
 "Externer HEAD bezieht sich auf eine nicht existierende Referenz und kann "
 "nicht ausgecheckt werden.\n"
 
-#: builtin/clone.c:657
+#: builtin/clone.c:658
 msgid "unable to checkout working tree"
 msgstr "Arbeitsverzeichnis konnte nicht ausgecheckt werden"
 
-#: builtin/clone.c:765
+#: builtin/clone.c:768
 msgid "Too many arguments."
 msgstr "Zu viele Argumente."
 
-#: builtin/clone.c:769
+#: builtin/clone.c:772
 msgid "You must specify a repository to clone."
 msgstr "Sie müssen ein Repository zum Klonen angeben."
 
-#: builtin/clone.c:780
+#: builtin/clone.c:783
 #, c-format
 msgid "--bare and --origin %s options are incompatible."
 msgstr "Die Optionen --bare und --origin %s sind inkompatibel."
 
-#: builtin/clone.c:783
+#: builtin/clone.c:786
 msgid "--bare and --separate-git-dir are incompatible."
 msgstr "Die Optionen --bare und --separate-git-dir sind inkompatibel."
 
-#: builtin/clone.c:796
+#: builtin/clone.c:799
 #, c-format
 msgid "repository '%s' does not exist"
 msgstr "Repository '%s' existiert nicht."
 
-#: builtin/clone.c:802
-msgid "--depth is ignored in local clones; use file:// instead."
-msgstr ""
-"Die Option --depth wird in lokalen Klonen ignoriert; benutzen Sie "
-"stattdessen file://"
-
-#: builtin/clone.c:805
-msgid "source repository is shallow, ignoring --local"
-msgstr ""
-"Quelle ist ein Repository mit unvollständiger Historie (shallow),ignoriere --"
-"local"
-
-#: builtin/clone.c:810
-msgid "--local is ignored"
-msgstr "--local wird ignoriert"
-
-#: builtin/clone.c:814 builtin/fetch.c:1119
+#: builtin/clone.c:805 builtin/fetch.c:1143
 #, c-format
 msgid "depth %s is not a positive number"
 msgstr "Tiefe %s ist keine positive Zahl"
 
-#: builtin/clone.c:824
+#: builtin/clone.c:815
 #, 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:834
+#: builtin/clone.c:825
 #, c-format
 msgid "working tree '%s' already exists."
 msgstr "Arbeitsverzeichnis '%s' existiert bereits."
 
-#: builtin/clone.c:847 builtin/clone.c:859
+#: builtin/clone.c:838 builtin/clone.c:850
 #, c-format
 msgid "could not create leading directories of '%s'"
 msgstr "Konnte führende Verzeichnisse von '%s' nicht erstellen."
 
-#: builtin/clone.c:850
+#: builtin/clone.c:841
 #, c-format
 msgid "could not create work tree dir '%s'."
 msgstr "Konnte Arbeitsverzeichnis '%s' nicht erstellen."
 
-#: builtin/clone.c:869
+#: builtin/clone.c:860
 #, c-format
 msgid "Cloning into bare repository '%s'...\n"
 msgstr "Klone in Bare-Repository '%s'...\n"
 
-#: builtin/clone.c:871
+#: builtin/clone.c:862
 #, c-format
 msgid "Cloning into '%s'...\n"
 msgstr "Klone nach '%s'...\n"
 
+#: builtin/clone.c:898
+msgid "--depth is ignored in local clones; use file:// instead."
+msgstr ""
+"Die Option --depth wird in lokalen Klonen ignoriert; benutzen Sie "
+"stattdessen file://"
+
+#: builtin/clone.c:901
+msgid "source repository is shallow, ignoring --local"
+msgstr ""
+"Quelle ist ein Repository mit unvollständiger Historie (shallow),ignoriere --"
+"local"
+
 #: builtin/clone.c:906
+msgid "--local is ignored"
+msgstr "--local wird ignoriert"
+
+#: builtin/clone.c:910
 #, c-format
 msgid "Don't know how to clone %s"
 msgstr "Weiß nicht wie %s zu klonen ist."
 
-#: builtin/clone.c:957 builtin/clone.c:965
+#: builtin/clone.c:961 builtin/clone.c:969
 #, c-format
 msgid "Remote branch %s not found in upstream %s"
 msgstr "Remote-Branch %s nicht im Upstream-Repository %s gefunden"
 
-#: builtin/clone.c:968
+#: builtin/clone.c:972
 msgid "You appear to have cloned an empty repository."
 msgstr "Sie scheinen ein leeres Repository geklont zu haben."
 
@@ -4185,90 +4206,99 @@ msgstr ""
 msgid "failed to unpack HEAD tree object"
 msgstr "Fehler beim Entpacken des \"Tree\"-Objektes von HEAD."
 
-#: builtin/commit.c:330
+#: builtin/commit.c:328
 msgid "unable to create temporary index"
 msgstr "Konnte temporäre Staging-Area nicht erstellen."
 
-#: builtin/commit.c:336
+#: builtin/commit.c:334
 msgid "interactive add failed"
 msgstr "interaktives Hinzufügen fehlgeschlagen"
 
-#: builtin/commit.c:369 builtin/commit.c:390 builtin/commit.c:440
+#: builtin/commit.c:366 builtin/commit.c:387 builtin/commit.c:435
 msgid "unable to write new_index file"
 msgstr "Konnte new_index Datei nicht schreiben"
 
-#: builtin/commit.c:421
+#: builtin/commit.c:418
 msgid "cannot do a partial commit during a merge."
 msgstr "Kann keinen Teil-Commit durchführen, während ein Merge im Gange ist."
 
-#: builtin/commit.c:423
+#: builtin/commit.c:420
 msgid "cannot do a partial commit during a cherry-pick."
 msgstr ""
 "Kann keinen Teil-Commit durchführen, während \"cherry-pick\" im Gange ist."
 
-#: builtin/commit.c:433
+#: builtin/commit.c:429
 msgid "cannot read the index"
 msgstr "Kann Staging-Area nicht lesen"
 
-#: builtin/commit.c:453
+#: builtin/commit.c:447
 msgid "unable to write temporary index file"
 msgstr "Konnte temporäre Staging-Area-Datei nicht schreiben."
 
-#: builtin/commit.c:544 builtin/commit.c:550
+#: builtin/commit.c:557 builtin/commit.c:563
 #, c-format
 msgid "invalid commit: %s"
 msgstr "Ungültiger Commit: %s"
 
-#: builtin/commit.c:572
+#: builtin/commit.c:585
 msgid "malformed --author parameter"
 msgstr "Fehlerhafter --author Parameter"
 
 #: builtin/commit.c:592
 #, c-format
+msgid "invalid date format: %s"
+msgstr "Ungültiges Datumsformat: %s"
+
+#: builtin/commit.c:609
+#, c-format
 msgid "Malformed ident string: '%s'"
 msgstr "Fehlerhafter Ident-String: '%s'"
 
-#: builtin/commit.c:629 builtin/commit.c:663 builtin/commit.c:1014
+#: builtin/commit.c:642
+msgid ""
+"unable to select a comment character that is not used\n"
+"in the current commit message"
+msgstr ""
+"Konnte kein Kommentar-Zeichen auswählen, das nicht in\n"
+"der aktuellen Commit-Beschreibung verwendet wird."
+
+#: builtin/commit.c:679 builtin/commit.c:712 builtin/commit.c:1086
 #, c-format
 msgid "could not lookup commit %s"
 msgstr "Konnte Commit %s nicht nachschlagen"
 
-#: builtin/commit.c:641 builtin/shortlog.c:273
+#: builtin/commit.c:691 builtin/shortlog.c:273
 #, c-format
 msgid "(reading log message from standard input)\n"
 msgstr "(lese Log-Nachricht von Standard-Eingabe)\n"
 
-#: builtin/commit.c:643
+#: builtin/commit.c:693
 msgid "could not read log from standard input"
 msgstr "Konnte Log nicht von Standard-Eingabe lesen."
 
-#: builtin/commit.c:647
+#: builtin/commit.c:697
 #, c-format
 msgid "could not read log file '%s'"
 msgstr "Konnte Log-Datei '%s' nicht lesen"
 
-#: builtin/commit.c:654
-msgid "commit has empty message"
-msgstr "Commit hat eine leere Beschreibung"
-
-#: builtin/commit.c:670
+#: builtin/commit.c:719
 msgid "could not read MERGE_MSG"
 msgstr "Konnte MERGE_MSG nicht lesen"
 
-#: builtin/commit.c:674
+#: builtin/commit.c:723
 msgid "could not read SQUASH_MSG"
 msgstr "Konnte SQUASH_MSG nicht lesen"
 
-#: builtin/commit.c:678
+#: builtin/commit.c:727
 #, c-format
 msgid "could not read '%s'"
 msgstr "Konnte '%s' nicht lesen"
 
-#: builtin/commit.c:749
+#: builtin/commit.c:798
 msgid "could not write commit template"
 msgstr "Konnte Commit-Vorlage nicht schreiben"
 
-#: builtin/commit.c:764
+#: builtin/commit.c:816
 #, c-format
 msgid ""
 "\n"
@@ -4283,7 +4313,7 @@ msgstr ""
 "\t%s\n"
 "und versuchen Sie es erneut.\n"
 
-#: builtin/commit.c:769
+#: builtin/commit.c:821
 #, c-format
 msgid ""
 "\n"
@@ -4298,7 +4328,7 @@ msgstr ""
 "\t%s\n"
 "und versuchen Sie es erneut.\n"
 
-#: builtin/commit.c:782
+#: builtin/commit.c:834
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -4308,7 +4338,7 @@ msgstr ""
 "die mit '%c' beginnen, werden ignoriert, und eine leere Beschreibung\n"
 "bricht den Commit ab.\n"
 
-#: builtin/commit.c:789
+#: builtin/commit.c:841
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -4321,150 +4351,155 @@ msgstr ""
 "entfernen.\n"
 "Eine leere Beschreibung bricht den Commit ab.\n"
 
-#: builtin/commit.c:802
+#: builtin/commit.c:855
 #, c-format
-msgid "%sAuthor:    %s"
-msgstr "%sAutor:    %s"
+msgid "%sAuthor:    %.*s <%.*s>"
+msgstr  "%sAutor:           %.*s <%.*s>"
 
-#: builtin/commit.c:809
+#: builtin/commit.c:863
 #, c-format
-msgid "%sCommitter: %s"
-msgstr "%sCommit-Ersteller: %s"
+msgid "%sDate:      %s"
+msgstr "%sDatum:            %s"
 
-#: builtin/commit.c:829
+#: builtin/commit.c:870
+#, c-format
+msgid "%sCommitter: %.*s <%.*s>"
+msgstr "%sCommit-Ersteller: %.*s <%.*s>"
+
+#: builtin/commit.c:888
 msgid "Cannot read index"
 msgstr "Kann Staging-Area nicht lesen"
 
-#: builtin/commit.c:872
+#: builtin/commit.c:945
 msgid "Error building trees"
 msgstr "Fehler beim Erzeugen der \"Tree\"-Objekte"
 
-#: builtin/commit.c:887 builtin/tag.c:391
+#: builtin/commit.c:960 builtin/tag.c:495
 #, c-format
 msgid "Please supply the message using either -m or -F option.\n"
 msgstr ""
 "Bitte liefern Sie eine Beschreibung entweder mit der Option -m oder -F.\n"
 
-#: builtin/commit.c:989
+#: builtin/commit.c:1061
 #, c-format
 msgid "No existing author found with '%s'"
 msgstr "Kein existierender Autor mit '%s' gefunden."
 
-#: builtin/commit.c:1004 builtin/commit.c:1244
+#: builtin/commit.c:1076 builtin/commit.c:1316
 #, c-format
 msgid "Invalid untracked files mode '%s'"
 msgstr "Ungültiger Modus '%s' für unbeobachtete Dateien"
 
-#: builtin/commit.c:1041
+#: builtin/commit.c:1113
 msgid "--long and -z are incompatible"
 msgstr "Die Optionen --long und -z sind inkompatibel."
 
-#: builtin/commit.c:1071
+#: builtin/commit.c:1143
 msgid "Using both --reset-author and --author does not make sense"
 msgstr ""
 "Die Optionen --reset-author und --author können nicht gemeinsam verwendet "
 "werden."
 
-#: builtin/commit.c:1080
+#: builtin/commit.c:1152
 msgid "You have nothing to amend."
 msgstr "Sie haben nichts für \"--amend\"."
 
-#: builtin/commit.c:1083
+#: builtin/commit.c:1155
 msgid "You are in the middle of a merge -- cannot amend."
 msgstr "Ein Merge ist im Gange -- kann \"--amend\" nicht ausführen."
 
-#: builtin/commit.c:1085
+#: builtin/commit.c:1157
 msgid "You are in the middle of a cherry-pick -- cannot amend."
 msgstr "\"cherry-pick\" ist im Gange -- kann \"--amend\" nicht ausführen."
 
-#: builtin/commit.c:1088
+#: builtin/commit.c:1160
 msgid "Options --squash and --fixup cannot be used together"
 msgstr ""
 "Die Optionen --squash und --fixup können nicht gemeinsam verwendet werden."
 
-#: builtin/commit.c:1098
+#: builtin/commit.c:1170
 msgid "Only one of -c/-C/-F/--fixup can be used."
 msgstr "Es kann nur eine Option von -c/-C/-F/--fixup verwendet werden."
 
-#: builtin/commit.c:1100
+#: builtin/commit.c:1172
 msgid "Option -m cannot be combined with -c/-C/-F/--fixup."
 msgstr "Die Option -m kann nicht mit -c/-C/-F/--fixup kombiniert werden."
 
-#: builtin/commit.c:1108
+#: builtin/commit.c:1180
 msgid "--reset-author can be used only with -C, -c or --amend."
 msgstr ""
 "Die Option --reset--author kann nur mit -C, -c oder --amend verwendet werden."
 
-#: builtin/commit.c:1125
+#: builtin/commit.c:1197
 msgid "Only one of --include/--only/--all/--interactive/--patch can be used."
 msgstr ""
 "Es kann nur eine Option von --include/--only/--all/--interactive/--patch "
 "verwendet werden."
 
-#: builtin/commit.c:1127
+#: builtin/commit.c:1199
 msgid "No paths with --include/--only does not make sense."
 msgstr ""
 "Die Optionen --include und --only können nur mit der Angabe von Pfaden "
 "verwendet werden."
 
-#: builtin/commit.c:1129
+#: builtin/commit.c:1201
 msgid "Clever... amending the last one with dirty index."
 msgstr ""
 "Klug... den letzten Commit mit einer geänderten Staging-Area nachbessern."
 
-#: builtin/commit.c:1131
+#: builtin/commit.c:1203
 msgid "Explicit paths specified without -i or -o; assuming --only paths..."
 msgstr "Explizite Pfade ohne -i oder -o angegeben; nehme --only an"
 
-#: builtin/commit.c:1143 builtin/tag.c:639
+#: builtin/commit.c:1215 builtin/tag.c:727
 #, c-format
 msgid "Invalid cleanup mode %s"
 msgstr "Ungültiger \"cleanup\" Modus %s"
 
-#: builtin/commit.c:1148
+#: builtin/commit.c:1220
 msgid "Paths with -a does not make sense."
 msgstr "Die Option -a kann nur mit der Angabe von Pfaden verwendet werden."
 
-#: builtin/commit.c:1258 builtin/commit.c:1516
+#: builtin/commit.c:1330 builtin/commit.c:1595
 msgid "show status concisely"
 msgstr "zeigt Status im Kurzformat"
 
-#: builtin/commit.c:1260 builtin/commit.c:1518
+#: builtin/commit.c:1332 builtin/commit.c:1597
 msgid "show branch information"
 msgstr "zeigt Branchinformationen"
 
-#: builtin/commit.c:1262 builtin/commit.c:1520 builtin/push.c:490
+#: builtin/commit.c:1334 builtin/commit.c:1599 builtin/push.c:489
 msgid "machine-readable output"
 msgstr "maschinenlesbare Ausgabe"
 
-#: builtin/commit.c:1265 builtin/commit.c:1522
+#: builtin/commit.c:1337 builtin/commit.c:1601
 msgid "show status in long format (default)"
 msgstr "zeigt Status im Langformat (Standard)"
 
-#: builtin/commit.c:1268 builtin/commit.c:1525
+#: builtin/commit.c:1340 builtin/commit.c:1604
 msgid "terminate entries with NUL"
 msgstr "schließt Einträge mit NUL-Zeichen ab"
 
-#: builtin/commit.c:1270 builtin/commit.c:1528 builtin/fast-export.c:674
-#: builtin/fast-export.c:677 builtin/tag.c:514
+#: builtin/commit.c:1342 builtin/commit.c:1607 builtin/fast-export.c:703
+#: builtin/fast-export.c:706 builtin/tag.c:602
 msgid "mode"
 msgstr "Modus"
 
-#: builtin/commit.c:1271 builtin/commit.c:1528
+#: builtin/commit.c:1343 builtin/commit.c:1607
 msgid "show untracked files, optional modes: all, normal, no. (Default: all)"
 msgstr ""
 "zeigt nicht beobachtete Dateien, optionale Modi: all, normal, no. (Standard: "
 "all)"
 
-#: builtin/commit.c:1274
+#: builtin/commit.c:1346
 msgid "show ignored files"
 msgstr "zeigt ignorierte Dateien"
 
-#: builtin/commit.c:1275 parse-options.h:153
+#: builtin/commit.c:1347 parse-options.h:153
 msgid "when"
 msgstr "wann"
 
-#: builtin/commit.c:1276
+#: builtin/commit.c:1348
 msgid ""
 "ignore changes to submodules, optional when: all, dirty, untracked. "
 "(Default: all)"
@@ -4472,219 +4507,219 @@ msgstr ""
 "ignoriert Ã„nderungen in Submodulen, optional wenn: all, dirty, untracked. "
 "(Standard: all)"
 
-#: builtin/commit.c:1278
+#: builtin/commit.c:1350
 msgid "list untracked files in columns"
 msgstr "listet unbeobachtete Dateien in Spalten auf"
 
-#: builtin/commit.c:1347
+#: builtin/commit.c:1419
 msgid "couldn't look up newly created commit"
 msgstr "Konnte neu erstellten Commit nicht nachschlagen."
 
-#: builtin/commit.c:1349
+#: builtin/commit.c:1421
 msgid "could not parse newly created commit"
 msgstr "Konnte neulich erstellten Commit nicht analysieren."
 
-#: builtin/commit.c:1390
+#: builtin/commit.c:1469
 msgid "detached HEAD"
 msgstr "losgelöster HEAD"
 
-#: builtin/commit.c:1392
+#: builtin/commit.c:1471
 msgid " (root-commit)"
 msgstr " (Basis-Commit)"
 
-#: builtin/commit.c:1486
+#: builtin/commit.c:1565
 msgid "suppress summary after successful commit"
 msgstr "unterdrückt Zusammenfassung nach erfolgreichem Commit"
 
-#: builtin/commit.c:1487
+#: builtin/commit.c:1566
 msgid "show diff in commit message template"
 msgstr "zeigt Unterschiede in Commit-Beschreibungsvorlage an"
 
-#: builtin/commit.c:1489
+#: builtin/commit.c:1568
 msgid "Commit message options"
 msgstr "Optionen für Commit-Beschreibung"
 
-#: builtin/commit.c:1490 builtin/tag.c:512
+#: builtin/commit.c:1569 builtin/tag.c:600
 msgid "read message from file"
 msgstr "liest Beschreibung von Datei"
 
-#: builtin/commit.c:1491
+#: builtin/commit.c:1570
 msgid "author"
 msgstr "Autor"
 
-#: builtin/commit.c:1491
+#: builtin/commit.c:1570
 msgid "override author for commit"
 msgstr "überschreibt Autor eines Commits"
 
-#: builtin/commit.c:1492 builtin/gc.c:272
+#: builtin/commit.c:1571 builtin/gc.c:286
 msgid "date"
 msgstr "Datum"
 
-#: builtin/commit.c:1492
+#: builtin/commit.c:1571
 msgid "override date for commit"
 msgstr "überschreibt Datum eines Commits"
 
-#: builtin/commit.c:1493 builtin/merge.c:216 builtin/notes.c:409
-#: builtin/notes.c:566 builtin/tag.c:510
+#: builtin/commit.c:1572 builtin/merge.c:216 builtin/notes.c:409
+#: builtin/notes.c:566 builtin/tag.c:598
 msgid "message"
 msgstr "Beschreibung"
 
-#: builtin/commit.c:1493
+#: builtin/commit.c:1572
 msgid "commit message"
 msgstr "Commit-Beschreibung"
 
-#: builtin/commit.c:1494
+#: builtin/commit.c:1573
 msgid "reuse and edit message from specified commit"
 msgstr "verwendet wieder und editiert Beschreibung des angegebenen Commits"
 
-#: builtin/commit.c:1495
+#: builtin/commit.c:1574
 msgid "reuse message from specified commit"
 msgstr "verwendet Beschreibung des angegebenen Commits wieder"
 
-#: builtin/commit.c:1496
+#: builtin/commit.c:1575
 msgid "use autosquash formatted message to fixup specified commit"
 msgstr ""
 "verwendet eine automatisch zusammengesetzte Beschreibung zum Nachbessern des "
 "angegebenen Commits"
 
-#: builtin/commit.c:1497
+#: builtin/commit.c:1576
 msgid "use autosquash formatted message to squash specified commit"
 msgstr ""
 "verwendet eine automatisch zusammengesetzte Beschreibung beim \"squash\" des "
 "angegebenen Commits"
 
-#: builtin/commit.c:1498
+#: builtin/commit.c:1577
 msgid "the commit is authored by me now (used with -C/-c/--amend)"
 msgstr "Setzt Sie als Autor des Commits (verwendet mit -C/-c/--amend)"
 
-#: builtin/commit.c:1499 builtin/log.c:1180 builtin/revert.c:86
+#: builtin/commit.c:1578 builtin/log.c:1188 builtin/revert.c:86
 msgid "add Signed-off-by:"
 msgstr "fügt 'Signed-off-by:'-Zeile hinzu"
 
-#: builtin/commit.c:1500
+#: builtin/commit.c:1579
 msgid "use specified template file"
 msgstr "verwendet angegebene Vorlagendatei"
 
-#: builtin/commit.c:1501
+#: builtin/commit.c:1580
 msgid "force edit of commit"
 msgstr "erzwingt Bearbeitung des Commits"
 
-#: builtin/commit.c:1502
+#: builtin/commit.c:1581
 msgid "default"
 msgstr "Standard"
 
-#: builtin/commit.c:1502 builtin/tag.c:515
+#: builtin/commit.c:1581 builtin/tag.c:603
 msgid "how to strip spaces and #comments from message"
 msgstr ""
 "wie Leerzeichen und #Kommentare von der Beschreibung getrennt werden sollen"
 
-#: builtin/commit.c:1503
+#: builtin/commit.c:1582
 msgid "include status in commit message template"
 msgstr "fügt Status in die Commit-Beschreibungsvorlage ein"
 
-#: builtin/commit.c:1504 builtin/merge.c:223 builtin/revert.c:92
-#: builtin/tag.c:516
+#: builtin/commit.c:1583 builtin/merge.c:223 builtin/revert.c:92
+#: builtin/tag.c:604
 msgid "key-id"
 msgstr "GPG-Schlüsselkennung"
 
-#: builtin/commit.c:1505 builtin/merge.c:224 builtin/revert.c:93
+#: builtin/commit.c:1584 builtin/merge.c:224 builtin/revert.c:93
 msgid "GPG sign commit"
 msgstr "signiert Commit mit GPG"
 
-#: builtin/commit.c:1508
+#: builtin/commit.c:1587
 msgid "Commit contents options"
 msgstr "Optionen für Commit-Inhalt"
 
-#: builtin/commit.c:1509
+#: builtin/commit.c:1588
 msgid "commit all changed files"
 msgstr "committet alle geänderten Dateien"
 
-#: builtin/commit.c:1510
+#: builtin/commit.c:1589
 msgid "add specified files to index for commit"
 msgstr "merkt die angegebenen Dateien zusätzlich zum Commit vor"
 
-#: builtin/commit.c:1511
+#: builtin/commit.c:1590
 msgid "interactively add files"
 msgstr "interaktives Hinzufügen von Dateien"
 
-#: builtin/commit.c:1512
+#: builtin/commit.c:1591
 msgid "interactively add changes"
 msgstr "interaktives Hinzufügen von Ã„nderungen"
 
-#: builtin/commit.c:1513
+#: builtin/commit.c:1592
 msgid "commit only specified files"
 msgstr "committet nur die angegebenen Dateien"
 
-#: builtin/commit.c:1514
+#: builtin/commit.c:1593
 msgid "bypass pre-commit hook"
 msgstr "umgeht \"pre-commit hook\""
 
-#: builtin/commit.c:1515
+#: builtin/commit.c:1594
 msgid "show what would be committed"
 msgstr "zeigt an, was committet werden würde"
 
-#: builtin/commit.c:1526
+#: builtin/commit.c:1605
 msgid "amend previous commit"
 msgstr "ändert vorherigen Commit"
 
-#: builtin/commit.c:1527
+#: builtin/commit.c:1606
 msgid "bypass post-rewrite hook"
 msgstr "umgeht \"post-rewrite hook\""
 
-#: builtin/commit.c:1532
+#: builtin/commit.c:1611
 msgid "ok to record an empty change"
 msgstr "erlaubt Aufzeichnung einer leeren Ã„nderung"
 
-#: builtin/commit.c:1534
+#: builtin/commit.c:1613
 msgid "ok to record a change with an empty message"
 msgstr "erlaubt Aufzeichnung einer Ã„nderung mit einer leeren Beschreibung"
 
-#: builtin/commit.c:1562
+#: builtin/commit.c:1641
 msgid "could not parse HEAD commit"
 msgstr "Konnte Commit von HEAD nicht analysieren."
 
-#: builtin/commit.c:1601 builtin/merge.c:518
+#: builtin/commit.c:1680 builtin/merge.c:518
 #, c-format
 msgid "could not open '%s' for reading"
 msgstr "Konnte '%s' nicht zum Lesen Ã¶ffnen."
 
-#: builtin/commit.c:1608
+#: builtin/commit.c:1687
 #, c-format
 msgid "Corrupt MERGE_HEAD file (%s)"
 msgstr "Beschädigte MERGE_HEAD-Datei (%s)"
 
-#: builtin/commit.c:1615
+#: builtin/commit.c:1694
 msgid "could not read MERGE_MODE"
 msgstr "Konnte MERGE_MODE nicht lesen"
 
-#: builtin/commit.c:1634
+#: builtin/commit.c:1713
 #, c-format
 msgid "could not read commit message: %s"
 msgstr "Konnte Commit-Beschreibung nicht lesen: %s"
 
-#: builtin/commit.c:1645
+#: builtin/commit.c:1724
 #, c-format
 msgid "Aborting commit; you did not edit the message.\n"
 msgstr "Commit abgebrochen; Sie haben die Beschreibung nicht editiert.\n"
 
-#: builtin/commit.c:1650
+#: builtin/commit.c:1729
 #, c-format
 msgid "Aborting commit due to empty commit message.\n"
 msgstr "Commit aufgrund leerer Beschreibung abgebrochen.\n"
 
-#: builtin/commit.c:1665 builtin/merge.c:857 builtin/merge.c:882
+#: builtin/commit.c:1744 builtin/merge.c:851 builtin/merge.c:876
 msgid "failed to write commit object"
 msgstr "Fehler beim Schreiben des Commit-Objektes."
 
-#: builtin/commit.c:1686
+#: builtin/commit.c:1756
 msgid "cannot lock HEAD ref"
 msgstr "Kann Referenz von HEAD nicht sperren."
 
-#: builtin/commit.c:1690
+#: builtin/commit.c:1769
 msgid "cannot update HEAD ref"
 msgstr "Kann Referenz von HEAD nicht aktualisieren."
 
-#: builtin/commit.c:1701
+#: builtin/commit.c:1780
 msgid ""
 "Repository has been updated, but unable to write\n"
 "new_index file. Check that disk is not full or quota is\n"
@@ -4839,47 +4874,47 @@ msgstr "git describe [Optionen] <commit-ish>*"
 msgid "git describe [options] --dirty"
 msgstr "git describe [Optionen] --dirty"
 
-#: builtin/describe.c:225
+#: builtin/describe.c:216
 #, c-format
 msgid "annotated tag %s not available"
 msgstr "annotiertes Tag %s ist nicht verfügbar"
 
-#: builtin/describe.c:229
+#: builtin/describe.c:220
 #, c-format
 msgid "annotated tag %s has no embedded name"
 msgstr "annotiertes Tag %s hat keinen eingebetteten Namen"
 
-#: builtin/describe.c:231
+#: builtin/describe.c:222
 #, c-format
 msgid "tag '%s' is really '%s' here"
 msgstr "Tag '%s' ist eigentlich '%s' hier"
 
-#: builtin/describe.c:258
+#: builtin/describe.c:249
 #, c-format
 msgid "Not a valid object name %s"
 msgstr "%s ist kein gültiger Objekt-Name"
 
-#: builtin/describe.c:261
+#: builtin/describe.c:252
 #, c-format
 msgid "%s is not a valid '%s' object"
 msgstr "%s ist kein gültiges '%s' Objekt"
 
-#: builtin/describe.c:278
+#: builtin/describe.c:269
 #, c-format
 msgid "no tag exactly matches '%s'"
 msgstr "kein Tag entspricht exakt '%s'"
 
-#: builtin/describe.c:280
+#: builtin/describe.c:271
 #, c-format
 msgid "searching to describe %s\n"
 msgstr "suche zur Beschreibung von %s\n"
 
-#: builtin/describe.c:327
+#: builtin/describe.c:318
 #, c-format
 msgid "finished search at %s\n"
 msgstr "beendete Suche bei %s\n"
 
-#: builtin/describe.c:354
+#: builtin/describe.c:345
 #, c-format
 msgid ""
 "No annotated tags can describe '%s'.\n"
@@ -4888,7 +4923,7 @@ msgstr ""
 "Keine annotierten Tags können '%s' beschreiben.\n"
 "Jedoch gab es nicht-annotierte Tags: versuchen Sie --tags."
 
-#: builtin/describe.c:358
+#: builtin/describe.c:349
 #, c-format
 msgid ""
 "No tags can describe '%s'.\n"
@@ -4897,12 +4932,12 @@ msgstr ""
 "Keine Tags können '%s' beschreiben.\n"
 "Versuchen Sie --always oder erstellen Sie einige Tags."
 
-#: builtin/describe.c:379
+#: builtin/describe.c:370
 #, c-format
 msgid "traversed %lu commits\n"
 msgstr "%lu Commits durchlaufen\n"
 
-#: builtin/describe.c:382
+#: builtin/describe.c:373
 #, c-format
 msgid ""
 "more than %i tags found; listed %i most recent\n"
@@ -4911,65 +4946,65 @@ msgstr ""
 "mehr als %i Tags gefunden; Führe die ersten %i auf\n"
 "Suche bei %s aufgegeben\n"
 
-#: builtin/describe.c:404
+#: builtin/describe.c:395
 msgid "find the tag that comes after the commit"
 msgstr "findet das Tag, das nach Commit kommt"
 
-#: builtin/describe.c:405
+#: builtin/describe.c:396
 msgid "debug search strategy on stderr"
 msgstr "protokolliert die Suchstrategie in der Standard-Fehlerausgabe"
 
-#: builtin/describe.c:406
+#: builtin/describe.c:397
 msgid "use any ref"
 msgstr "verwendet alle Referenzen"
 
-#: builtin/describe.c:407
+#: builtin/describe.c:398
 msgid "use any tag, even unannotated"
 msgstr "verwendet jedes Tag, auch nicht-annotierte"
 
-#: builtin/describe.c:408
+#: builtin/describe.c:399
 msgid "always use long format"
 msgstr "verwendet immer langes Format"
 
-#: builtin/describe.c:409
+#: builtin/describe.c:400
 msgid "only follow first parent"
 msgstr "folgt nur erstem Elternteil"
 
-#: builtin/describe.c:412
+#: builtin/describe.c:403
 msgid "only output exact matches"
 msgstr "gibt nur exakte Ãœbereinstimmungen aus"
 
-#: builtin/describe.c:414
+#: builtin/describe.c:405
 msgid "consider <n> most recent tags (default: 10)"
 msgstr "betrachtet die jüngsten <n> Tags (Standard: 10)"
 
-#: builtin/describe.c:416
+#: builtin/describe.c:407
 msgid "only consider tags matching <pattern>"
 msgstr "betrachtet nur Tags die <Muster> entsprechen"
 
-#: builtin/describe.c:418 builtin/name-rev.c:321
+#: builtin/describe.c:409 builtin/name-rev.c:318
 msgid "show abbreviated commit object as fallback"
 msgstr "zeigt gekürztes Commit-Objekt, wenn sonst nichts zutrifft"
 
-#: builtin/describe.c:419
+#: builtin/describe.c:410
 msgid "mark"
 msgstr "Kennzeichen"
 
-#: builtin/describe.c:420
+#: builtin/describe.c:411
 msgid "append <mark> on dirty working tree (default: \"-dirty\")"
 msgstr ""
 "fügt <Kennzeichen> bei geändertem Arbeitsverzeichnis hinzu (Standard: \"-"
 "dirty\")"
 
-#: builtin/describe.c:438
+#: builtin/describe.c:429
 msgid "--long is incompatible with --abbrev=0"
 msgstr "Die Optionen --long und --abbrev=0 sind inkompatibel."
 
-#: builtin/describe.c:464
+#: builtin/describe.c:455
 msgid "No names found, cannot describe anything."
 msgstr "Keine Namen gefunden, kann nichts beschreiben."
 
-#: builtin/describe.c:484
+#: builtin/describe.c:475
 msgid "--dirty is incompatible with commit-ishes"
 msgstr "Die Option --dirty kann nicht mit Commits verwendet werden."
 
@@ -5002,46 +5037,54 @@ msgstr "Mehr als zwei Blobs angegeben: '%s'"
 msgid "unhandled object '%s' given."
 msgstr "unbehandeltes Objekt '%s' angegeben"
 
-#: builtin/fast-export.c:22
+#: builtin/fast-export.c:23
 msgid "git fast-export [rev-list-opts]"
 msgstr "git fast-export [rev-list-opts]"
 
-#: builtin/fast-export.c:673
+#: builtin/fast-export.c:702
 msgid "show progress after <n> objects"
 msgstr "zeigt Fortschritt nach <n> Objekten an"
 
-#: builtin/fast-export.c:675
+#: builtin/fast-export.c:704
 msgid "select handling of signed tags"
 msgstr "wählt Behandlung von signierten Tags"
 
-#: builtin/fast-export.c:678
+#: builtin/fast-export.c:707
 msgid "select handling of tags that tag filtered objects"
 msgstr "wählt Behandlung von Tags, die gefilterte Objekte markieren"
 
-#: builtin/fast-export.c:681
+#: builtin/fast-export.c:710
 msgid "Dump marks to this file"
 msgstr "Schreibt Kennzeichen in diese Datei"
 
-#: builtin/fast-export.c:683
+#: builtin/fast-export.c:712
 msgid "Import marks from this file"
 msgstr "Importiert Kennzeichen von dieser Datei"
 
-#: builtin/fast-export.c:685
+#: builtin/fast-export.c:714
 msgid "Fake a tagger when tags lack one"
 msgstr "erzeugt künstlich einen Tag-Ersteller, wenn das Tag keinen hat"
 
-#: builtin/fast-export.c:687
+#: builtin/fast-export.c:716
 msgid "Output full tree for each commit"
 msgstr "gibt für jeden Commit das gesamte Verzeichnis aus"
 
-#: builtin/fast-export.c:689
+#: builtin/fast-export.c:718
 msgid "Use the done feature to terminate the stream"
 msgstr "Benutzt die \"done\"-Funktion um den Strom abzuschließen"
 
-#: builtin/fast-export.c:690
+#: builtin/fast-export.c:719
 msgid "Skip output of blob data"
 msgstr "Ãœberspringt Ausgabe von Blob-Daten"
 
+#: builtin/fast-export.c:720
+msgid "refspec"
+msgstr "Refspec"
+
+#: builtin/fast-export.c:721
+msgid "Apply refspec to exported refs"
+msgstr "Wendet Refspec auf exportierte Referenzen an"
+
 #: builtin/fetch.c:20
 msgid "git fetch [<options>] [<repository> [<refspec>...]]"
 msgstr "git fetch [<Optionen>] [<Repository> [<Refspec>...]]"
@@ -5058,159 +5101,167 @@ msgstr "git fetch --multiple [<Optionen>] [(<Repository> | <Gruppe>)...]"
 msgid "git fetch --all [<options>]"
 msgstr "git fetch --all [<Optionen>]"
 
-#: builtin/fetch.c:75
+#: builtin/fetch.c:90
 msgid "fetch from all remotes"
 msgstr "fordert von allen Remote-Repositories an"
 
-#: builtin/fetch.c:77
+#: builtin/fetch.c:92
 msgid "append to .git/FETCH_HEAD instead of overwriting"
 msgstr "hängt an .git/FETCH_HEAD an, anstatt zu Ã¼berschreiben"
 
-#: builtin/fetch.c:79
+#: builtin/fetch.c:94
 msgid "path to upload pack on remote end"
 msgstr "Pfad des Programms zum Hochladen von Paketen auf der Gegenseite"
 
-#: builtin/fetch.c:80
+#: builtin/fetch.c:95
 msgid "force overwrite of local branch"
 msgstr "erzwingt das Ãœberschreiben von lokalen Branches"
 
-#: builtin/fetch.c:82
+#: builtin/fetch.c:97
 msgid "fetch from multiple remotes"
 msgstr "fordert von mehreren Remote-Repositories an"
 
-#: builtin/fetch.c:84
+#: builtin/fetch.c:99
 msgid "fetch all tags and associated objects"
 msgstr "fordert alle Tags und verbundene Objekte an"
 
-#: builtin/fetch.c:86
+#: builtin/fetch.c:101
 msgid "do not fetch all tags (--no-tags)"
 msgstr "fordert nicht alle Tags an (--no-tags)"
 
-#: builtin/fetch.c:88
+#: builtin/fetch.c:103
 msgid "prune remote-tracking branches no longer on remote"
 msgstr ""
 "entfernt Remote-Tracking-Branches, die sich nicht mehr im Remote-Repository "
 "befinden"
 
-#: builtin/fetch.c:89
+#: builtin/fetch.c:104
 msgid "on-demand"
 msgstr "bei-Bedarf"
 
-#: builtin/fetch.c:90
+#: builtin/fetch.c:105
 msgid "control recursive fetching of submodules"
 msgstr "kontrolliert rekursive Anforderungen von Submodulen"
 
-#: builtin/fetch.c:94
+#: builtin/fetch.c:109
 msgid "keep downloaded pack"
 msgstr "behält heruntergeladenes Paket"
 
-#: builtin/fetch.c:96
+#: builtin/fetch.c:111
 msgid "allow updating of HEAD ref"
 msgstr "erlaubt Aktualisierung der \"HEAD\"-Referenz"
 
-#: builtin/fetch.c:99
+#: builtin/fetch.c:114
 msgid "deepen history of shallow clone"
 msgstr ""
 "vertieft die Historie eines Klons mit unvollständiger Historie (shallow)"
 
-#: builtin/fetch.c:101
+#: builtin/fetch.c:116
 msgid "convert to a complete repository"
 msgstr "konvertiert zu einem vollständigen Repository"
 
-#: builtin/fetch.c:103 builtin/log.c:1197
+#: builtin/fetch.c:118 builtin/log.c:1205
 msgid "dir"
 msgstr "Verzeichnis"
 
-#: builtin/fetch.c:104
+#: builtin/fetch.c:119
 msgid "prepend this to submodule path output"
 msgstr "stellt dies an die Ausgabe der Submodul-Pfade voran"
 
-#: builtin/fetch.c:107
+#: builtin/fetch.c:122
 msgid "default mode for recursion"
 msgstr "Standard-Modus für Rekursion"
 
-#: builtin/fetch.c:109
+#: builtin/fetch.c:124
 msgid "accept refs that update .git/shallow"
 msgstr "akzeptiert Referenzen die .git/shallow aktualisieren"
 
-#: builtin/fetch.c:347
+#: builtin/fetch.c:125
+msgid "refmap"
+msgstr "Refmap"
+
+#: builtin/fetch.c:126
+msgid "specify fetch refmap"
+msgstr "Angabe der Refmap für 'fetch'"
+
+#: builtin/fetch.c:376
 msgid "Couldn't find remote ref HEAD"
 msgstr "Konnte Remote-Referenz von HEAD nicht finden."
 
-#: builtin/fetch.c:411
+#: builtin/fetch.c:440
 #, c-format
 msgid "object %s not found"
 msgstr "Objekt %s nicht gefunden"
 
-#: builtin/fetch.c:416
+#: builtin/fetch.c:445
 msgid "[up to date]"
 msgstr "[aktuell]"
 
-#: builtin/fetch.c:430
+#: builtin/fetch.c:459
 #, c-format
 msgid "! %-*s %-*s -> %s  (can't fetch in current branch)"
 msgstr ""
 "! %-*s %-*s -> %s  (kann \"fetch\" im aktuellen Branch nicht ausführen)"
 
-#: builtin/fetch.c:431 builtin/fetch.c:517
+#: builtin/fetch.c:460 builtin/fetch.c:546
 msgid "[rejected]"
 msgstr "[zurückgewiesen]"
 
-#: builtin/fetch.c:442
+#: builtin/fetch.c:471
 msgid "[tag update]"
 msgstr "[Tag Aktualisierung]"
 
-#: builtin/fetch.c:444 builtin/fetch.c:479 builtin/fetch.c:497
+#: builtin/fetch.c:473 builtin/fetch.c:508 builtin/fetch.c:526
 msgid "  (unable to update local ref)"
 msgstr "  (kann lokale Referenz nicht aktualisieren)"
 
-#: builtin/fetch.c:462
+#: builtin/fetch.c:491
 msgid "[new tag]"
 msgstr "[neues Tag]"
 
-#: builtin/fetch.c:465
+#: builtin/fetch.c:494
 msgid "[new branch]"
 msgstr "[neuer Branch]"
 
-#: builtin/fetch.c:468
+#: builtin/fetch.c:497
 msgid "[new ref]"
 msgstr "[neue Referenz]"
 
-#: builtin/fetch.c:513
+#: builtin/fetch.c:542
 msgid "unable to update local ref"
 msgstr "kann lokale Referenz nicht aktualisieren"
 
-#: builtin/fetch.c:513
+#: builtin/fetch.c:542
 msgid "forced update"
 msgstr "Aktualisierung erzwungen"
 
-#: builtin/fetch.c:519
+#: builtin/fetch.c:548
 msgid "(non-fast-forward)"
 msgstr "(kein Vorspulen)"
 
-#: builtin/fetch.c:552 builtin/fetch.c:785
+#: builtin/fetch.c:581 builtin/fetch.c:814
 #, c-format
 msgid "cannot open %s: %s\n"
 msgstr "kann %s nicht Ã¶ffnen: %s\n"
 
-#: builtin/fetch.c:561
+#: builtin/fetch.c:590
 #, c-format
 msgid "%s did not send all necessary objects\n"
 msgstr "%s hat nicht alle erforderlichen Objekte gesendet\n"
 
-#: builtin/fetch.c:579
+#: builtin/fetch.c:608
 #, c-format
 msgid "reject %s because shallow roots are not allowed to be updated"
 msgstr ""
 "%s wurde zurückgewiesen, da Ursprungs-Commits von Repositoriesmit "
 "unvollständiger Historie (shallow) nicht aktualisiert werden dürfen."
 
-#: builtin/fetch.c:667 builtin/fetch.c:750
+#: builtin/fetch.c:696 builtin/fetch.c:779
 #, c-format
 msgid "From %.*s\n"
 msgstr "Von %.*s\n"
 
-#: builtin/fetch.c:678
+#: builtin/fetch.c:707
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -5219,57 +5270,57 @@ msgstr ""
 "Einige lokale Referenzen konnten nicht aktualisiert werden; versuchen Sie\n"
 "'git remote prune %s' um jeden Ã¤lteren, widersprüchlichen Branch zu löschen."
 
-#: builtin/fetch.c:730
+#: builtin/fetch.c:759
 #, c-format
 msgid "   (%s will become dangling)"
 msgstr "   (%s wird unreferenziert)"
 
-#: builtin/fetch.c:731
+#: builtin/fetch.c:760
 #, c-format
 msgid "   (%s has become dangling)"
 msgstr "   (%s wurde unreferenziert)"
 
-#: builtin/fetch.c:755
+#: builtin/fetch.c:784
 msgid "[deleted]"
 msgstr "[gelöscht]"
 
-#: builtin/fetch.c:756 builtin/remote.c:1050
+#: builtin/fetch.c:785 builtin/remote.c:1059
 msgid "(none)"
 msgstr "(nichts)"
 
-#: builtin/fetch.c:775
+#: builtin/fetch.c:804
 #, c-format
 msgid "Refusing to fetch into current branch %s of non-bare repository"
 msgstr ""
 "Der \"fetch\" in den aktuellen Branch %s von einem nicht-Bare-Repository "
 "wurde verweigert."
 
-#: builtin/fetch.c:794
+#: builtin/fetch.c:823
 #, 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:797
+#: builtin/fetch.c:826
 #, c-format
 msgid "Option \"%s\" is ignored for %s\n"
 msgstr "Option \"%s\" wird ignoriert für %s\n"
 
-#: builtin/fetch.c:853
+#: builtin/fetch.c:882
 #, c-format
 msgid "Don't know how to fetch from %s"
 msgstr "Weiß nicht wie von %s angefordert wird."
 
-#: builtin/fetch.c:1015
+#: builtin/fetch.c:1044
 #, c-format
 msgid "Fetching %s\n"
 msgstr "Fordere an von %s\n"
 
-#: builtin/fetch.c:1017 builtin/remote.c:90
+#: builtin/fetch.c:1046 builtin/remote.c:90
 #, c-format
 msgid "Could not fetch %s"
 msgstr "Konnte nicht von %s anfordern"
 
-#: builtin/fetch.c:1035
+#: builtin/fetch.c:1064
 msgid ""
 "No remote repository specified.  Please, specify either a URL or a\n"
 "remote name from which new revisions should be fetched."
@@ -5278,35 +5329,35 @@ msgstr ""
 "oder den Namen des Remote-Repositories an, von welchem neue\n"
 "Commits angefordert werden sollen."
 
-#: builtin/fetch.c:1059
+#: builtin/fetch.c:1087
 msgid "You need to specify a tag name."
 msgstr "Sie müssen den Namen des Tags angeben."
 
-#: builtin/fetch.c:1107
+#: builtin/fetch.c:1131
 msgid "--depth and --unshallow cannot be used together"
 msgstr ""
 "Die Optionen --depth und --unshallow können nicht gemeinsam verwendet werden."
 
-#: builtin/fetch.c:1109
+#: builtin/fetch.c:1133
 msgid "--unshallow on a complete repository does not make sense"
 msgstr ""
 "Die Option --unshallow kann nicht in einem Repository mit unvollständiger "
 "Historie verwendet werden."
 
-#: builtin/fetch.c:1132
+#: builtin/fetch.c:1156
 msgid "fetch --all does not take a repository argument"
 msgstr "fetch --all akzeptiert kein Repository als Argument"
 
-#: builtin/fetch.c:1134
+#: builtin/fetch.c:1158
 msgid "fetch --all does not make sense with refspecs"
 msgstr "fetch --all kann nicht mit Refspecs verwendet werden."
 
-#: builtin/fetch.c:1145
+#: builtin/fetch.c:1169
 #, c-format
 msgid "No such remote or remote group: %s"
 msgstr "Kein Remote-Repository (einzeln oder Gruppe): %s"
 
-#: builtin/fetch.c:1153
+#: builtin/fetch.c:1177
 msgid "Fetching a group and specifying refspecs does not make sense"
 msgstr ""
 "Das Abholen einer Gruppe von Remote-Repositories kann nicht mit der Angabe\n"
@@ -5317,9 +5368,9 @@ msgid "git fmt-merge-msg [-m <message>] [--log[=<n>]|--no-log] [--file <file>]"
 msgstr ""
 "git fmt-merge-msg [-m <Beschreibung>] [--log[=<n>]|--no-log] [--file <Datei>]"
 
-#: builtin/fmt-merge-msg.c:663 builtin/fmt-merge-msg.c:666 builtin/grep.c:700
-#: builtin/merge.c:196 builtin/repack.c:175 builtin/repack.c:179
-#: builtin/show-branch.c:654 builtin/show-ref.c:178 builtin/tag.c:501
+#: builtin/fmt-merge-msg.c:663 builtin/fmt-merge-msg.c:666 builtin/grep.c:698
+#: builtin/merge.c:196 builtin/repack.c:179 builtin/repack.c:183
+#: builtin/show-branch.c:654 builtin/show-ref.c:178 builtin/tag.c:589
 #: parse-options.h:132 parse-options.h:239
 msgid "n"
 msgstr "Anzahl"
@@ -5344,43 +5395,43 @@ msgstr "verwendet <Text> als Beschreibungsanfang"
 msgid "file to read from"
 msgstr "Datei zum Einlesen"
 
-#: builtin/for-each-ref.c:1063
+#: builtin/for-each-ref.c:1051
 msgid "git for-each-ref [options] [<pattern>]"
 msgstr "git for-each-ref [Optionen] [<Muster>]"
 
-#: builtin/for-each-ref.c:1078
+#: builtin/for-each-ref.c:1066
 msgid "quote placeholders suitably for shells"
 msgstr "formatiert Platzhalter als Shell-String"
 
-#: builtin/for-each-ref.c:1080
+#: builtin/for-each-ref.c:1068
 msgid "quote placeholders suitably for perl"
 msgstr "formatiert Platzhalter als Perl-String"
 
-#: builtin/for-each-ref.c:1082
+#: builtin/for-each-ref.c:1070
 msgid "quote placeholders suitably for python"
 msgstr "formatiert Platzhalter als Python-String"
 
-#: builtin/for-each-ref.c:1084
+#: builtin/for-each-ref.c:1072
 msgid "quote placeholders suitably for tcl"
 msgstr "formatiert Platzhalter als TCL-String"
 
-#: builtin/for-each-ref.c:1087
+#: builtin/for-each-ref.c:1075
 msgid "show only <n> matched refs"
 msgstr "zeigt nur <n> passende Referenzen"
 
-#: builtin/for-each-ref.c:1088 builtin/replace.c:177
+#: builtin/for-each-ref.c:1076 builtin/replace.c:435
 msgid "format"
 msgstr "Format"
 
-#: builtin/for-each-ref.c:1088
+#: builtin/for-each-ref.c:1076
 msgid "format to use for the output"
 msgstr "für die Ausgabe zu verwendendes Format"
 
-#: builtin/for-each-ref.c:1089
+#: builtin/for-each-ref.c:1077
 msgid "key"
 msgstr "Schüssel"
 
-#: builtin/for-each-ref.c:1090
+#: builtin/for-each-ref.c:1078
 msgid "field name to sort on"
 msgstr "sortiere nach diesem Feld"
 
@@ -5388,55 +5439,55 @@ msgstr "sortiere nach diesem Feld"
 msgid "Checking connectivity"
 msgstr "Prüfe Konnektivität"
 
-#: builtin/fsck.c:544
+#: builtin/fsck.c:538
 msgid "Checking object directories"
 msgstr "Prüfe Objekt-Verzeichnisse"
 
-#: builtin/fsck.c:607
+#: builtin/fsck.c:601
 msgid "git fsck [options] [<object>...]"
 msgstr "git fsck [Optionen] [<Objekt>...]"
 
-#: builtin/fsck.c:613
+#: builtin/fsck.c:607
 msgid "show unreachable objects"
 msgstr "zeigt unerreichbare Objekte"
 
-#: builtin/fsck.c:614
+#: builtin/fsck.c:608
 msgid "show dangling objects"
 msgstr "zeigt unreferenzierte Objekte"
 
-#: builtin/fsck.c:615
+#: builtin/fsck.c:609
 msgid "report tags"
 msgstr "meldet Tags"
 
-#: builtin/fsck.c:616
+#: builtin/fsck.c:610
 msgid "report root nodes"
 msgstr "meldet Hauptwurzeln"
 
-#: builtin/fsck.c:617
+#: builtin/fsck.c:611
 msgid "make index objects head nodes"
 msgstr "prüft Objekte in der Staging-Area"
 
-#: builtin/fsck.c:618
+#: builtin/fsck.c:612
 msgid "make reflogs head nodes (default)"
 msgstr "prüft die Reflogs (Standard)"
 
-#: builtin/fsck.c:619
+#: builtin/fsck.c:613
 msgid "also consider packs and alternate objects"
 msgstr ""
 
-#: builtin/fsck.c:620
+#: builtin/fsck.c:614
 msgid "enable more strict checking"
 msgstr "aktiviert genauere Prüfung"
 
-#: builtin/fsck.c:622
+#: builtin/fsck.c:616
 msgid "write dangling objects in .git/lost-found"
 msgstr "schreibt unreferenzierte Objekte nach .git/lost-found"
 
-#: builtin/fsck.c:623 builtin/prune.c:144
+#: builtin/fsck.c:617 builtin/prune.c:144
 msgid "show progress"
 msgstr "zeigt Fortschrittsanzeige"
 
-#: builtin/fsck.c:673
+#: builtin/fsck.c:667
 msgid "Checking objects"
 msgstr "Prüfe Objekte"
 
@@ -5444,54 +5495,54 @@ msgstr "Prüfe Objekte"
 msgid "git gc [options]"
 msgstr "git gc [Optionen]"
 
-#: builtin/gc.c:90
+#: builtin/gc.c:91
 #, c-format
 msgid "Invalid %s: '%s'"
 msgstr "Ungültiger %s: '%s'"
 
-#: builtin/gc.c:117
+#: builtin/gc.c:118
 #, c-format
 msgid "insanely long object directory %.*s"
 msgstr "zu langes Objekt-Verzeichnis %.*s"
 
-#: builtin/gc.c:273
+#: builtin/gc.c:287
 msgid "prune unreferenced objects"
 msgstr "entfernt unreferenzierte Objekte"
 
-#: builtin/gc.c:275
+#: builtin/gc.c:289
 msgid "be more thorough (increased runtime)"
 msgstr "mehr Gründlichkeit (erhöht Laufzeit)"
 
-#: builtin/gc.c:276
+#: builtin/gc.c:290
 msgid "enable auto-gc mode"
 msgstr "aktiviert \"auto-gc\" Modus"
 
-#: builtin/gc.c:277
+#: builtin/gc.c:291
 msgid "force running gc even if there may be another gc running"
 msgstr ""
 "erzwingt Ausführung von \"git gc\" selbst wenn ein anderes\n"
 "\"git gc\" bereits ausgeführt wird"
 
-#: builtin/gc.c:318
+#: builtin/gc.c:332
 #, c-format
 msgid "Auto packing the repository in background for optimum performance.\n"
 msgstr ""
 "Die Datenbank des Repositories wird für eine optimale Performance im\n"
 "Hintergrund komprimiert.\n"
 
-#: builtin/gc.c:320
+#: builtin/gc.c:334
 #, c-format
 msgid "Auto packing the repository for optimum performance.\n"
 msgstr ""
 "Die Datenbank des Projektarchivs wird für eine optimale Performance "
 "komprimiert.\n"
 
-#: builtin/gc.c:321
+#: builtin/gc.c:335
 #, c-format
 msgid "See \"git help gc\" for manual housekeeping.\n"
 msgstr "Siehe \"git help gc\" für manuelles Aufräumen.\n"
 
-#: builtin/gc.c:336
+#: builtin/gc.c:353
 #, c-format
 msgid ""
 "gc is already running on machine '%s' pid %<PRIuMAX> (use --force if not)"
@@ -5499,7 +5550,7 @@ msgstr ""
 "\"git gc\" wird bereits auf Maschine '%s' pid %<PRIuMAX> ausgeführt\n"
 "(benutzen Sie --force falls nicht)"
 
-#: builtin/gc.c:361
+#: builtin/gc.c:375
 msgid ""
 "There are too many unreachable loose objects; run 'git prune' to remove them."
 msgstr ""
@@ -5515,235 +5566,230 @@ msgstr "git grep [Optionen] [-e] <Muster> [<Commit>...] [[--] <Pfad>...]"
 msgid "grep: failed to create thread: %s"
 msgstr "grep: Fehler beim Erzeugen eines Thread: %s"
 
-#: builtin/grep.c:365
-#, c-format
-msgid "Failed to chdir: %s"
-msgstr "Fehler beim Verzeichniswechsel: %s"
-
-#: builtin/grep.c:443 builtin/grep.c:478
+#: builtin/grep.c:441 builtin/grep.c:476
 #, c-format
 msgid "unable to read tree (%s)"
 msgstr "konnte \"Tree\"-Objekt (%s) nicht lesen"
 
-#: builtin/grep.c:493
+#: builtin/grep.c:491
 #, c-format
 msgid "unable to grep from object of type %s"
 msgstr "kann \"grep\" nicht mit Objekten des Typs %s durchführen"
 
-#: builtin/grep.c:549
+#: builtin/grep.c:547
 #, c-format
 msgid "switch `%c' expects a numerical value"
 msgstr "Schalter '%c' erwartet einen numerischen Wert"
 
-#: builtin/grep.c:566
+#: builtin/grep.c:564
 #, c-format
 msgid "cannot open '%s'"
 msgstr "kann '%s' nicht Ã¶ffnen"
 
-#: builtin/grep.c:640
+#: builtin/grep.c:638
 msgid "search in index instead of in the work tree"
 msgstr "sucht in der Staging-Area anstatt im Arbeitsverzeichnis"
 
-#: builtin/grep.c:642
+#: builtin/grep.c:640
 msgid "find in contents not managed by git"
 msgstr "findet auch in Inhalten, die nicht von Git verwaltet werden"
 
-#: builtin/grep.c:644
+#: builtin/grep.c:642
 msgid "search in both tracked and untracked files"
 msgstr "sucht in beobachteten und unbeobachteten Dateien"
 
-#: builtin/grep.c:646
+#: builtin/grep.c:644
 msgid "search also in ignored files"
 msgstr "sucht auch in ignorierten Dateien"
 
-#: builtin/grep.c:649
+#: builtin/grep.c:647
 msgid "show non-matching lines"
 msgstr "zeigt Zeilen ohne Ãœbereinstimmungen"
 
-#: builtin/grep.c:651
+#: builtin/grep.c:649
 msgid "case insensitive matching"
 msgstr "findet Ãœbereinstimmungen unabhängig von Groß- und Kleinschreibung"
 
-#: builtin/grep.c:653
+#: builtin/grep.c:651
 msgid "match patterns only at word boundaries"
 msgstr "sucht nur ganze Wörter"
 
-#: builtin/grep.c:655
+#: builtin/grep.c:653
 msgid "process binary files as text"
 msgstr "verarbeitet binäre Dateien als Text"
 
-#: builtin/grep.c:657
+#: builtin/grep.c:655
 msgid "don't match patterns in binary files"
 msgstr "findet keine Muster in Binärdateien"
 
-#: builtin/grep.c:660
+#: builtin/grep.c:658
 msgid "process binary files with textconv filters"
 msgstr "verarbeitet binäre Dateien mit \"textconv\"-Filtern"
 
-#: builtin/grep.c:662
+#: builtin/grep.c:660
 msgid "descend at most <depth> levels"
 msgstr "durchläuft höchstens <Tiefe> Ebenen"
 
-#: builtin/grep.c:666
+#: builtin/grep.c:664
 msgid "use extended POSIX regular expressions"
 msgstr "verwendet erweiterte reguläre Ausdrücke aus POSIX"
 
-#: builtin/grep.c:669
+#: builtin/grep.c:667
 msgid "use basic POSIX regular expressions (default)"
 msgstr "verwendet grundlegende reguläre Ausdrücke aus POSIX (Standard)"
 
-#: builtin/grep.c:672
+#: builtin/grep.c:670
 msgid "interpret patterns as fixed strings"
 msgstr "interpretiert Muster als feste Zeichenketten"
 
-#: builtin/grep.c:675
+#: builtin/grep.c:673
 msgid "use Perl-compatible regular expressions"
 msgstr "verwendet Perl-kompatible reguläre Ausdrücke"
 
-#: builtin/grep.c:678
+#: builtin/grep.c:676
 msgid "show line numbers"
 msgstr "zeigt Zeilennummern"
 
-#: builtin/grep.c:679
+#: builtin/grep.c:677
 msgid "don't show filenames"
 msgstr "zeigt keine Dateinamen"
 
-#: builtin/grep.c:680
+#: builtin/grep.c:678
 msgid "show filenames"
 msgstr "zeigt Dateinamen"
 
-#: builtin/grep.c:682
+#: builtin/grep.c:680
 msgid "show filenames relative to top directory"
 msgstr "zeigt Dateinamen relativ zum Projektverzeichnis"
 
-#: builtin/grep.c:684
+#: builtin/grep.c:682
 msgid "show only filenames instead of matching lines"
 msgstr "zeigt nur Dateinamen anstatt Ã¼bereinstimmende Zeilen"
 
-#: builtin/grep.c:686
+#: builtin/grep.c:684
 msgid "synonym for --files-with-matches"
 msgstr "Synonym für --files-with-matches"
 
-#: builtin/grep.c:689
+#: builtin/grep.c:687
 msgid "show only the names of files without match"
 msgstr "zeigt nur die Dateinamen ohne Ãœbereinstimmungen"
 
-#: builtin/grep.c:691
+#: builtin/grep.c:689
 msgid "print NUL after filenames"
 msgstr "gibt NUL-Zeichen nach Dateinamen aus"
 
-#: builtin/grep.c:693
+#: builtin/grep.c:691
 msgid "show the number of matches instead of matching lines"
 msgstr "zeigt, anstatt der Zeilen, die Anzahl der Ã¼bereinstimmenden Zeilen"
 
-#: builtin/grep.c:694
+#: builtin/grep.c:692
 msgid "highlight matches"
 msgstr "hebt Ãœbereinstimmungen hervor"
 
-#: builtin/grep.c:696
+#: builtin/grep.c:694
 msgid "print empty line between matches from different files"
 msgstr ""
 "gibt eine Leerzeile zwischen Ãœbereinstimmungen in verschiedenen Dateien aus"
 
-#: builtin/grep.c:698
+#: builtin/grep.c:696
 msgid "show filename only once above matches from same file"
 msgstr ""
 "zeigt den Dateinamen nur einmal oberhalb der Ãœbereinstimmungen aus dieser "
 "Datei an"
 
-#: builtin/grep.c:701
+#: builtin/grep.c:699
 msgid "show <n> context lines before and after matches"
 msgstr "zeigt <n> Zeilen vor und nach den Ãœbereinstimmungen an"
 
-#: builtin/grep.c:704
+#: builtin/grep.c:702
 msgid "show <n> context lines before matches"
 msgstr "zeigt <n> Zeilen vor den Ãœbereinstimmungen an"
 
-#: builtin/grep.c:706
+#: builtin/grep.c:704
 msgid "show <n> context lines after matches"
 msgstr "zeigt <n> Zeilen nach den Ãœbereinstimmungen an"
 
-#: builtin/grep.c:707
+#: builtin/grep.c:705
 msgid "shortcut for -C NUM"
 msgstr "Kurzform für -C NUM"
 
-#: builtin/grep.c:710
+#: builtin/grep.c:708
 msgid "show a line with the function name before matches"
 msgstr "zeigt eine Zeile mit dem Funktionsnamen vor Ãœbereinstimmungen an"
 
-#: builtin/grep.c:712
+#: builtin/grep.c:710
 msgid "show the surrounding function"
 msgstr "zeigt die umgebende Funktion an"
 
-#: builtin/grep.c:715
+#: builtin/grep.c:713
 msgid "read patterns from file"
 msgstr "liest Muster von einer Datei"
 
-#: builtin/grep.c:717
+#: builtin/grep.c:715
 msgid "match <pattern>"
 msgstr "findet <Muster>"
 
-#: builtin/grep.c:719
+#: builtin/grep.c:717
 msgid "combine patterns specified with -e"
 msgstr "kombiniert Muster, die mit -e angegeben wurden"
 
-#: builtin/grep.c:731
+#: builtin/grep.c:729
 msgid "indicate hit with exit status without output"
 msgstr "zeigt Ãœbereinstimmungen nur durch Beendigungsstatus an"
 
-#: builtin/grep.c:733
+#: builtin/grep.c:731
 msgid "show only matches from files that match all patterns"
 msgstr "zeigt nur Ãœbereinstimmungen von Dateien, die allen Mustern entsprechen"
 
-#: builtin/grep.c:735
+#: builtin/grep.c:733
 msgid "show parse tree for grep expression"
 msgstr "zeigt geparstes Verzeichnis für \"grep\"-Ausdruck"
 
-#: builtin/grep.c:739
+#: builtin/grep.c:737
 msgid "pager"
 msgstr "Anzeigeprogramm"
 
-#: builtin/grep.c:739
+#: builtin/grep.c:737
 msgid "show matching files in the pager"
 msgstr "zeigt Dateien mit Ãœbereinstimmungen im Anzeigeprogramm"
 
-#: builtin/grep.c:742
+#: builtin/grep.c:740
 msgid "allow calling of grep(1) (ignored by this build)"
 msgstr "erlaubt den Aufruf von grep(1) (von dieser Programmversion ignoriert)"
 
-#: builtin/grep.c:743 builtin/show-ref.c:187
+#: builtin/grep.c:741 builtin/show-ref.c:187
 msgid "show usage"
 msgstr "zeigt Verwendung"
 
-#: builtin/grep.c:810
+#: builtin/grep.c:808
 msgid "no pattern given."
 msgstr "keine Muster angegeben"
 
-#: builtin/grep.c:868
+#: builtin/grep.c:866
 msgid "--open-files-in-pager only works on the worktree"
 msgstr ""
 "Die Option --open-files-in-pager kann nur innerhalb des "
 "Arbeitsverzeichnisses verwendet werden."
 
-#: builtin/grep.c:891
+#: builtin/grep.c:892
 msgid "--cached or --untracked cannot be used with --no-index."
 msgstr ""
 "Die Optionen --cached und --untracked können nicht mit --no-index verwendet "
 "werden."
 
-#: builtin/grep.c:896
+#: builtin/grep.c:897
 msgid "--no-index or --untracked cannot be used with revs."
 msgstr ""
 "Die Optionen --no-index und --untracked können nicht mit Commits verwendet "
 "werden."
 
-#: builtin/grep.c:899
+#: builtin/grep.c:900
 msgid "--[no-]exclude-standard cannot be used for tracked contents."
 msgstr ""
 "Die Option --[no-]exclude-standard kann nicht mit beobachteten Inhalten "
 "verwendet werden."
 
-#: builtin/grep.c:907
+#: builtin/grep.c:908
 msgid "both --cached and trees are given."
 msgstr "Die Option --cached kann nicht mit \"Tree\"-Objekten verwendet werden."
 
@@ -5759,7 +5805,7 @@ msgstr ""
 msgid "git hash-object  --stdin-paths < <list-of-paths>"
 msgstr "git hash-object  --stdin-paths < <Liste-von-Pfaden>"
 
-#: builtin/hash-object.c:72 builtin/tag.c:521
+#: builtin/hash-object.c:72 builtin/tag.c:609
 msgid "type"
 msgstr "Art"
 
@@ -5903,281 +5949,292 @@ msgstr "Verwendung: %s%s"
 msgid "`git %s' is aliased to `%s'"
 msgstr "für `git %s' wurde der Alias `%s' angelegt"
 
-#: builtin/index-pack.c:184
+#: builtin/index-pack.c:145
+#, c-format
+msgid "unable to open %s"
+msgstr "kann %s nicht Ã¶ffnen"
+
+#: builtin/index-pack.c:191
 #, c-format
 msgid "object type mismatch at %s"
 msgstr "Objekt-Typen passen bei %s nicht zusammen"
 
-#: builtin/index-pack.c:204
-msgid "object of unexpected type"
-msgstr "Objekt hat unerwarteten Typ"
+#: builtin/index-pack.c:211
+#, c-format
+msgid "did not receive expected object %s"
+msgstr "konnte erwartetes Objekt %s nicht empfangen"
 
-#: builtin/index-pack.c:244
+#: builtin/index-pack.c:214
+#, c-format
+msgid "object %s: expected type %s, found %s"
+msgstr "Objekt %s: erwarteter Typ %s, %s gefunden"
+
+#: builtin/index-pack.c:256
 #, c-format
 msgid "cannot fill %d byte"
 msgid_plural "cannot fill %d bytes"
 msgstr[0] "kann %d Byte nicht lesen"
 msgstr[1] "kann %d Bytes nicht lesen"
 
-#: builtin/index-pack.c:254
+#: builtin/index-pack.c:266
 msgid "early EOF"
 msgstr "zu frühes Dateiende"
 
-#: builtin/index-pack.c:255
+#: builtin/index-pack.c:267
 msgid "read error on input"
 msgstr "Fehler beim Lesen der Eingabe"
 
-#: builtin/index-pack.c:267
+#: builtin/index-pack.c:279
 msgid "used more bytes than were available"
 msgstr "verwendete mehr Bytes als verfügbar waren"
 
-#: builtin/index-pack.c:274
+#: builtin/index-pack.c:286
 msgid "pack too large for current definition of off_t"
 msgstr "Paket ist zu groß für die aktuelle Definition von off_t"
 
-#: builtin/index-pack.c:290
+#: builtin/index-pack.c:302
 #, c-format
 msgid "unable to create '%s'"
 msgstr "konnte '%s' nicht erstellen"
 
-#: builtin/index-pack.c:295
+#: builtin/index-pack.c:307
 #, c-format
 msgid "cannot open packfile '%s'"
 msgstr "Kann Paketdatei '%s' nicht Ã¶ffnen"
 
-#: builtin/index-pack.c:309
+#: builtin/index-pack.c:321
 msgid "pack signature mismatch"
 msgstr "Paketsignatur stimmt nicht Ã¼berein"
 
-#: builtin/index-pack.c:311
+#: builtin/index-pack.c:323
 #, c-format
 msgid "pack version %<PRIu32> unsupported"
 msgstr "Paketversion %<PRIu32> nicht unterstützt"
 
-#: builtin/index-pack.c:329
+#: builtin/index-pack.c:341
 #, c-format
 msgid "pack has bad object at offset %lu: %s"
 msgstr "Paket hat ein ungültiges Objekt bei Versatz %lu: %s"
 
-#: builtin/index-pack.c:451
+#: builtin/index-pack.c:462
 #, c-format
 msgid "inflate returned %d"
 msgstr "Dekomprimierung gab %d zurück"
 
-#: builtin/index-pack.c:500
+#: builtin/index-pack.c:511
 msgid "offset value overflow for delta base object"
 msgstr "Wert für Versatz bei Differenzobjekt Ã¼bergelaufen"
 
-#: builtin/index-pack.c:508
+#: builtin/index-pack.c:519
 msgid "delta base offset is out of bound"
 msgstr ""
 "Wert für Versatz bei Differenzobjekt liegt außerhalb des gültigen Bereichs"
 
-#: builtin/index-pack.c:516
+#: builtin/index-pack.c:527
 #, c-format
 msgid "unknown object type %d"
 msgstr "Unbekannter Objekt-Typ %d"
 
-#: builtin/index-pack.c:547
+#: builtin/index-pack.c:558
 msgid "cannot pread pack file"
 msgstr "Kann Paketdatei %s nicht lesen"
 
-#: builtin/index-pack.c:549
+#: builtin/index-pack.c:560
 #, c-format
 msgid "premature end of pack file, %lu byte missing"
 msgid_plural "premature end of pack file, %lu bytes missing"
 msgstr[0] "frühzeitiges Ende der Paketdatei, vermisse %lu Byte"
 msgstr[1] "frühzeitiges Ende der Paketdatei, vermisse %lu Bytes"
 
-#: builtin/index-pack.c:575
+#: builtin/index-pack.c:586
 msgid "serious inflate inconsistency"
 msgstr "ernsthafte Inkonsistenz nach Dekomprimierung"
 
-#: builtin/index-pack.c:666 builtin/index-pack.c:672 builtin/index-pack.c:695
-#: builtin/index-pack.c:729 builtin/index-pack.c:738
+#: builtin/index-pack.c:677 builtin/index-pack.c:683 builtin/index-pack.c:706
+#: builtin/index-pack.c:740 builtin/index-pack.c:749
 #, c-format
 msgid "SHA1 COLLISION FOUND WITH %s !"
 msgstr "SHA1 KOLLISION MIT %s GEFUNDEN !"
 
-#: builtin/index-pack.c:669 builtin/pack-objects.c:162
+#: builtin/index-pack.c:680 builtin/pack-objects.c:162
 #: builtin/pack-objects.c:254
 #, c-format
 msgid "unable to read %s"
 msgstr "kann %s nicht lesen"
 
-#: builtin/index-pack.c:735
+#: builtin/index-pack.c:746
 #, c-format
 msgid "cannot read existing object %s"
 msgstr "Kann existierendes Objekt %s nicht lesen."
 
-#: builtin/index-pack.c:749
+#: builtin/index-pack.c:760
 #, c-format
 msgid "invalid blob object %s"
 msgstr "ungültiges Blob-Objekt %s"
 
-#: builtin/index-pack.c:763
+#: builtin/index-pack.c:774
 #, c-format
 msgid "invalid %s"
 msgstr "Ungültiger Objekt-Typ %s"
 
-#: builtin/index-pack.c:766
+#: builtin/index-pack.c:777
 msgid "Error in object"
 msgstr "Fehler in Objekt"
 
-#: builtin/index-pack.c:768
+#: builtin/index-pack.c:779
 #, c-format
 msgid "Not all child objects of %s are reachable"
 msgstr "Nicht alle Kind-Objekte von %s sind erreichbar"
 
-#: builtin/index-pack.c:839 builtin/index-pack.c:869
+#: builtin/index-pack.c:851 builtin/index-pack.c:881
 msgid "failed to apply delta"
 msgstr "Konnte Dateiunterschied nicht anwenden"
 
-#: builtin/index-pack.c:1010
+#: builtin/index-pack.c:1022
 msgid "Receiving objects"
 msgstr "Empfange Objekte"
 
-#: builtin/index-pack.c:1010
+#: builtin/index-pack.c:1022
 msgid "Indexing objects"
 msgstr "Indiziere Objekte"
 
-#: builtin/index-pack.c:1036
+#: builtin/index-pack.c:1048
 msgid "pack is corrupted (SHA1 mismatch)"
 msgstr "Paket ist beschädigt (SHA1 unterschiedlich)"
 
-#: builtin/index-pack.c:1041
+#: builtin/index-pack.c:1053
 msgid "cannot fstat packfile"
 msgstr "kann Paketdatei nicht lesen"
 
-#: builtin/index-pack.c:1044
+#: builtin/index-pack.c:1056
 msgid "pack has junk at the end"
 msgstr "Paketende enthält nicht verwendbaren Inhalt"
 
-#: builtin/index-pack.c:1055
+#: builtin/index-pack.c:1067
 msgid "confusion beyond insanity in parse_pack_objects()"
 msgstr "Fehler beim Ausführen von \"parse_pack_objects()\""
 
-#: builtin/index-pack.c:1078
+#: builtin/index-pack.c:1090
 msgid "Resolving deltas"
 msgstr "Löse Unterschiede auf"
 
-#: builtin/index-pack.c:1088
+#: builtin/index-pack.c:1100
 #, c-format
 msgid "unable to create thread: %s"
 msgstr "kann Thread nicht erzeugen: %s"
 
-#: builtin/index-pack.c:1130
+#: builtin/index-pack.c:1142
 msgid "confusion beyond insanity"
 msgstr "Fehler beim Auflösen der Unterschiede"
 
-#: builtin/index-pack.c:1138
+#: builtin/index-pack.c:1150
 #, c-format
 msgid "completed with %d local objects"
 msgstr "abgeschlossen mit %d lokalen Objekten"
 
-#: builtin/index-pack.c:1148
+#: builtin/index-pack.c:1160
 #, c-format
 msgid "Unexpected tail checksum for %s (disk corruption?)"
 msgstr "Unerwartete Prüfsumme für %s (Festplattenfehler?)"
 
-#: builtin/index-pack.c:1152
+#: builtin/index-pack.c:1164
 #, c-format
 msgid "pack has %d unresolved delta"
 msgid_plural "pack has %d unresolved deltas"
 msgstr[0] "Paket hat %d unaufgelöste Unterschied"
 msgstr[1] "Paket hat %d unaufgelöste Unterschiede"
 
-#: builtin/index-pack.c:1177
+#: builtin/index-pack.c:1189
 #, c-format
 msgid "unable to deflate appended object (%d)"
 msgstr "Konnte angehängtes Objekt (%d) nicht komprimieren"
 
-#: builtin/index-pack.c:1256
+#: builtin/index-pack.c:1268
 #, c-format
 msgid "local object %s is corrupt"
 msgstr "lokales Objekt %s ist beschädigt"
 
-#: builtin/index-pack.c:1280
+#: builtin/index-pack.c:1292
 msgid "error while closing pack file"
 msgstr "Fehler beim Schließen der Paketdatei"
 
-#: builtin/index-pack.c:1293
+#: builtin/index-pack.c:1305
 #, c-format
 msgid "cannot write keep file '%s'"
 msgstr "Kann Paketbeschreibungsdatei '%s' nicht schreiben"
 
-#: builtin/index-pack.c:1301
+#: builtin/index-pack.c:1313
 #, c-format
 msgid "cannot close written keep file '%s'"
 msgstr "Kann eben erstellte Paketbeschreibungsdatei '%s' nicht schließen"
 
-#: builtin/index-pack.c:1314
+#: builtin/index-pack.c:1326
 msgid "cannot store pack file"
 msgstr "Kann Paketdatei nicht speichern"
 
-#: builtin/index-pack.c:1325
+#: builtin/index-pack.c:1337
 msgid "cannot store index file"
 msgstr "Kann Indexdatei nicht speichern"
 
-#: builtin/index-pack.c:1358
+#: builtin/index-pack.c:1370
 #, c-format
 msgid "bad pack.indexversion=%<PRIu32>"
 msgstr "\"pack.indexversion=%<PRIu32>\" ist ungültig"
 
-#: builtin/index-pack.c:1364
+#: builtin/index-pack.c:1376
 #, c-format
 msgid "invalid number of threads specified (%d)"
 msgstr "ungültige Anzahl von Threads angegeben (%d)"
 
-#: builtin/index-pack.c:1368 builtin/index-pack.c:1546
+#: builtin/index-pack.c:1380 builtin/index-pack.c:1559
 #, c-format
 msgid "no threads support, ignoring %s"
 msgstr "keine Unterstützung von Threads, '%s' wird ignoriert"
 
-#: builtin/index-pack.c:1426
+#: builtin/index-pack.c:1438
 #, c-format
 msgid "Cannot open existing pack file '%s'"
 msgstr "Kann existierende Paketdatei '%s' nicht Ã¶ffnen"
 
-#: builtin/index-pack.c:1428
+#: builtin/index-pack.c:1440
 #, c-format
 msgid "Cannot open existing pack idx file for '%s'"
 msgstr "Kann existierende Indexdatei für Paket '%s' nicht Ã¶ffnen"
 
-#: builtin/index-pack.c:1475
+#: builtin/index-pack.c:1487
 #, c-format
 msgid "non delta: %d object"
 msgid_plural "non delta: %d objects"
 msgstr[0] "kein Unterschied: %d Objekt"
 msgstr[1] "kein Unterschied: %d Objekte"
 
-#: builtin/index-pack.c:1482
+#: builtin/index-pack.c:1494
 #, c-format
 msgid "chain length = %d: %lu object"
 msgid_plural "chain length = %d: %lu objects"
 msgstr[0] "Länge der Objekt-Liste = %d: %lu Objekt"
 msgstr[1] "Länge der Objekt-Liste = %d: %lu Objekte"
 
-#: builtin/index-pack.c:1510
+#: builtin/index-pack.c:1523
 msgid "Cannot come back to cwd"
 msgstr "Kann nicht zurück zu Arbeitsverzeichnis wechseln"
 
-#: builtin/index-pack.c:1558 builtin/index-pack.c:1561
-#: builtin/index-pack.c:1573 builtin/index-pack.c:1577
+#: builtin/index-pack.c:1571 builtin/index-pack.c:1574
+#: builtin/index-pack.c:1586 builtin/index-pack.c:1590
 #, c-format
 msgid "bad %s"
 msgstr "%s ist ungültig"
 
-#: builtin/index-pack.c:1591
+#: builtin/index-pack.c:1604
 msgid "--fix-thin cannot be used without --stdin"
 msgstr "Die Option --fix-thin kann nicht ohne --stdin verwendet werden."
 
-#: builtin/index-pack.c:1595 builtin/index-pack.c:1605
+#: builtin/index-pack.c:1608 builtin/index-pack.c:1617
 #, c-format
 msgid "packfile name '%s' does not end with '.pack'"
 msgstr "Name der Paketdatei '%s' endet nicht mit '.pack'"
 
-#: builtin/index-pack.c:1614
+#: builtin/index-pack.c:1625
 msgid "--verify with no packfile name given"
 msgstr "Die Option --verify wurde ohne Namen der Paketdatei angegeben."
 
@@ -6292,11 +6349,11 @@ msgstr "kann aktuelles Arbeitsverzeichnis nicht ermitteln"
 
 #: builtin/init-db.c:465
 msgid ""
-"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared"
-"[=<permissions>]] [directory]"
+"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--"
+"shared[=<permissions>]] [directory]"
 msgstr ""
-"git init [-q | --quiet] [--bare] [--template=<Vorlagenverzeichnis>] [--shared"
-"[=<Berechtigungen>]] [Verzeichnis]"
+"git init [-q | --quiet] [--bare] [--template=<Vorlagenverzeichnis>] [--"
+"shared[=<Berechtigungen>]] [Verzeichnis]"
 
 #: builtin/init-db.c:488
 msgid "permissions"
@@ -6306,7 +6363,7 @@ msgstr "Berechtigungen"
 msgid "specify that the git repository is to be shared amongst several users"
 msgstr "gibt an, dass das Git-Repository mit mehreren Benutzern geteilt wird"
 
-#: builtin/init-db.c:491 builtin/prune-packed.c:79 builtin/repack.c:168
+#: builtin/init-db.c:491 builtin/prune-packed.c:79 builtin/repack.c:172
 msgid "be quiet"
 msgstr "weniger Ausgaben"
 
@@ -6346,38 +6403,38 @@ msgstr "git log [<Optionen>] [Commitbereich>] [[--] <Pfad>...]\n"
 msgid "   or: git show [options] <object>..."
 msgstr "   oder: git show [Optionen] <Objekt>..."
 
-#: builtin/log.c:125
+#: builtin/log.c:127
 msgid "suppress diff output"
 msgstr "unterdrückt Ausgabe der Unterschiede"
 
-#: builtin/log.c:126
+#: builtin/log.c:128
 msgid "show source"
 msgstr "zeigt Quelle"
 
-#: builtin/log.c:127
+#: builtin/log.c:129
 msgid "Use mail map file"
 msgstr "verwendet \"mailmap\"-Datei"
 
-#: builtin/log.c:128
+#: builtin/log.c:130
 msgid "decorate options"
 msgstr "decorate-Optionen"
 
-#: builtin/log.c:231
+#: builtin/log.c:229
 #, c-format
 msgid "Final output: %d %s\n"
 msgstr "letzte Ausgabe: %d %s\n"
 
-#: builtin/log.c:473 builtin/log.c:565
+#: builtin/log.c:470 builtin/log.c:562
 #, c-format
 msgid "Could not read object %s"
 msgstr "Kann Objekt %s nicht lesen."
 
-#: builtin/log.c:589
+#: builtin/log.c:586
 #, c-format
 msgid "Unknown type: %d"
 msgstr "Unbekannter Typ: %d"
 
-#: builtin/log.c:689
+#: builtin/log.c:687
 msgid "format.headers without value"
 msgstr "format.headers ohne Wert"
 
@@ -6398,197 +6455,206 @@ msgstr "Brauche genau einen Commit-Bereich."
 msgid "Not a range."
 msgstr "Kein Commit-Bereich."
 
-#: builtin/log.c:911
+#: builtin/log.c:916
 msgid "Cover letter needs email format"
 msgstr "Anschreiben benötigt E-Mail-Format"
 
-#: builtin/log.c:987
+#: builtin/log.c:995
 #, c-format
 msgid "insane in-reply-to: %s"
 msgstr "ungültiges in-reply-to: %s"
 
-#: builtin/log.c:1015
+#: builtin/log.c:1023
 msgid "git format-patch [options] [<since> | <revision range>]"
 msgstr "git format-patch [Optionen] [<seit> | <Commitbereich>]"
 
-#: builtin/log.c:1060
+#: builtin/log.c:1068
 msgid "Two output directories?"
 msgstr "Zwei Ausgabeverzeichnisse?"
 
-#: builtin/log.c:1175
+#: builtin/log.c:1183
 msgid "use [PATCH n/m] even with a single patch"
 msgstr "verwendet [PATCH n/m] auch mit einzelnem Patch"
 
-#: builtin/log.c:1178
+#: builtin/log.c:1186
 msgid "use [PATCH] even with multiple patches"
 msgstr "verwendet [PATCH] auch mit mehreren Patches"
 
-#: builtin/log.c:1182
+#: builtin/log.c:1190
 msgid "print patches to standard out"
 msgstr "Ausgabe der Patches in Standard-Ausgabe"
 
-#: builtin/log.c:1184
+#: builtin/log.c:1192
 msgid "generate a cover letter"
 msgstr "erzeugt ein Deckblatt"
 
-#: builtin/log.c:1186
+#: builtin/log.c:1194
 msgid "use simple number sequence for output file names"
 msgstr "verwendet einfache Nummernfolge für die Namen der Ausgabedateien"
 
-#: builtin/log.c:1187
+#: builtin/log.c:1195
 msgid "sfx"
 msgstr "Dateiendung"
 
-#: builtin/log.c:1188
+#: builtin/log.c:1196
 msgid "use <sfx> instead of '.patch'"
 msgstr "verwendet <Dateiendung> anstatt '.patch'"
 
-#: builtin/log.c:1190
+#: builtin/log.c:1198
 msgid "start numbering patches at <n> instead of 1"
 msgstr "beginnt die Nummerierung der Patches bei <n> anstatt bei 1"
 
-#: builtin/log.c:1192
+#: builtin/log.c:1200
 msgid "mark the series as Nth re-roll"
 msgstr "kennzeichnet die Serie als n-te Fassung"
 
-#: builtin/log.c:1194
+#: builtin/log.c:1202
 msgid "Use [<prefix>] instead of [PATCH]"
 msgstr "verwendet [<Präfix>] anstatt [PATCH]"
 
-#: builtin/log.c:1197
+#: builtin/log.c:1205
 msgid "store resulting files in <dir>"
 msgstr "speichert erzeugte Dateien in <Verzeichnis>"
 
-#: builtin/log.c:1200
+#: builtin/log.c:1208
 msgid "don't strip/add [PATCH]"
 msgstr "[PATCH] wird nicht entfernt/hinzugefügt"
 
-#: builtin/log.c:1203
+#: builtin/log.c:1211
 msgid "don't output binary diffs"
 msgstr "gibt keine binären Unterschiede aus"
 
-#: builtin/log.c:1205
+#: builtin/log.c:1213
 msgid "don't include a patch matching a commit upstream"
 msgstr ""
 "schließt keine Patches ein, die einem Commit im Upstream-Branch entsprechen"
 
-#: builtin/log.c:1207
+#: builtin/log.c:1215
 msgid "show patch format instead of default (patch + stat)"
 msgstr "zeigt Patchformat anstatt des Standards (Patch + Zusammenfassung)"
 
-#: builtin/log.c:1209
+#: builtin/log.c:1217
 msgid "Messaging"
 msgstr "Email-Einstellungen"
 
-#: builtin/log.c:1210
+#: builtin/log.c:1218
 msgid "header"
 msgstr "Header"
 
-#: builtin/log.c:1211
+#: builtin/log.c:1219
 msgid "add email header"
 msgstr "fügt Email-Header hinzu"
 
-#: builtin/log.c:1212 builtin/log.c:1214
+#: builtin/log.c:1220 builtin/log.c:1222
 msgid "email"
 msgstr "Email"
 
-#: builtin/log.c:1212
+#: builtin/log.c:1220
 msgid "add To: header"
 msgstr "fügt  \"To:\"-Header hinzu"
 
-#: builtin/log.c:1214
+#: builtin/log.c:1222
 msgid "add Cc: header"
 msgstr "fügt \"Cc:\"-Header hinzu"
 
-#: builtin/log.c:1216
+#: builtin/log.c:1224
 msgid "ident"
 msgstr "Ident"
 
-#: builtin/log.c:1217
+#: builtin/log.c:1225
 msgid "set From address to <ident> (or committer ident if absent)"
 msgstr ""
 "setzt \"From\"-Adresse auf <Ident> (oder Ident des Commit-Erstellers,wenn "
 "fehlend)"
 
-#: builtin/log.c:1219
+#: builtin/log.c:1227
 msgid "message-id"
 msgstr "message-id"
 
-#: builtin/log.c:1220
+#: builtin/log.c:1228
 msgid "make first mail a reply to <message-id>"
 msgstr "macht aus erster Email eine Antwort zu <message-id>"
 
-#: builtin/log.c:1221 builtin/log.c:1224
+#: builtin/log.c:1229 builtin/log.c:1232
 msgid "boundary"
 msgstr "Grenze"
 
-#: builtin/log.c:1222
+#: builtin/log.c:1230
 msgid "attach the patch"
 msgstr "hängt einen Patch an"
 
-#: builtin/log.c:1225
+#: builtin/log.c:1233
 msgid "inline the patch"
 msgstr "fügt den Patch direkt in die Nachricht ein"
 
-#: builtin/log.c:1229
+#: builtin/log.c:1237
 msgid "enable message threading, styles: shallow, deep"
 msgstr "aktiviert Nachrichtenverkettung, Stile: shallow, deep"
 
-#: builtin/log.c:1231
+#: builtin/log.c:1239
 msgid "signature"
 msgstr "Signatur"
 
-#: builtin/log.c:1232
+#: builtin/log.c:1240
 msgid "add a signature"
 msgstr "fügt eine Signatur hinzu"
 
-#: builtin/log.c:1233
+#: builtin/log.c:1242
+msgid "add a signature from a file"
+msgstr "fügt eine Signatur aus einer Datei hinzu"
+
+#: builtin/log.c:1243
 msgid "don't print the patch filenames"
 msgstr "zeigt keine Dateinamen der Patches"
 
-#: builtin/log.c:1307
+#: builtin/log.c:1317
 #, c-format
 msgid "invalid ident line: %s"
 msgstr "Ungültige Identifikationszeile: %s"
 
-#: builtin/log.c:1322
+#: builtin/log.c:1332
 msgid "-n and -k are mutually exclusive."
 msgstr "Die Optionen -n und -k schließen sich gegenseitig aus."
 
-#: builtin/log.c:1324
+#: builtin/log.c:1334
 msgid "--subject-prefix and -k are mutually exclusive."
 msgstr "Die Optionen --subject-prefix und -k schließen sich gegenseitig aus."
 
-#: builtin/log.c:1332
+#: builtin/log.c:1342
 msgid "--name-only does not make sense"
 msgstr "Die Option --name-only kann nicht verwendet werden."
 
-#: builtin/log.c:1334
+#: builtin/log.c:1344
 msgid "--name-status does not make sense"
 msgstr "Die Option --name-status kann nicht verwendet werden."
 
-#: builtin/log.c:1336
+#: builtin/log.c:1346
 msgid "--check does not make sense"
 msgstr "Die Option --check kann nicht verwendet werden."
 
-#: builtin/log.c:1359
+#: builtin/log.c:1369
 msgid "standard output, or directory, which one?"
 msgstr "Standard-Ausgabe oder Verzeichnis, welches von beidem?"
 
-#: builtin/log.c:1361
+#: builtin/log.c:1371
 #, c-format
 msgid "Could not create directory '%s'"
 msgstr "Konnte Verzeichnis '%s' nicht erstellen."
 
-#: builtin/log.c:1509
+#: builtin/log.c:1468
+#, c-format
+msgid "unable to read signature file '%s'"
+msgstr "Konnte Signatur-Datei '%s' nicht lesen"
+
+#: builtin/log.c:1531
 msgid "Failed to create output files"
 msgstr "Fehler beim Erstellen der Ausgabedateien."
 
-#: builtin/log.c:1558
+#: builtin/log.c:1579
 msgid "git cherry [-v] [<upstream> [<head> [<limit>]]]"
 msgstr "git cherry [-v] [<Upstream> [<Branch> [<Limit>]]]"
 
-#: builtin/log.c:1613
+#: builtin/log.c:1634
 #, c-format
 msgid ""
 "Could not find a tracked remote branch, please specify <upstream> manually.\n"
@@ -6596,7 +6662,7 @@ msgstr ""
 "Konnte gefolgten Remote-Branch nicht finden, bitte geben Sie <Upstream> "
 "manuell an.\n"
 
-#: builtin/log.c:1626 builtin/log.c:1628 builtin/log.c:1640
+#: builtin/log.c:1647 builtin/log.c:1649 builtin/log.c:1661
 #, c-format
 msgid "Unknown commit %s"
 msgstr "Unbekannter Commit %s"
@@ -6889,33 +6955,33 @@ msgstr "Ungültiger branch.%s.mergeoptions String: %s"
 msgid "git write-tree failed to write a tree"
 msgstr "\"git write-tree\" schlug beim Schreiben eines \"Tree\"-Objektes fehl"
 
-#: builtin/merge.c:681
+#: builtin/merge.c:678
 msgid "Not handling anything other than two heads merge."
 msgstr "Es wird nur der Merge von zwei Branches behandelt."
 
-#: builtin/merge.c:695
+#: builtin/merge.c:692
 #, c-format
 msgid "Unknown option for merge-recursive: -X%s"
 msgstr "Unbekannte Option für merge-recursive: -X%s"
 
-#: builtin/merge.c:709
+#: builtin/merge.c:705
 #, c-format
 msgid "unable to write %s"
 msgstr "konnte %s nicht schreiben"
 
-#: builtin/merge.c:798
+#: builtin/merge.c:794
 #, c-format
 msgid "Could not read from '%s'"
 msgstr "konnte nicht von '%s' lesen"
 
-#: builtin/merge.c:807
+#: builtin/merge.c:803
 #, c-format
 msgid "Not committing merge; use 'git commit' to complete the merge.\n"
 msgstr ""
 "Merge wurde nicht committet; benutzen Sie 'git commit' um den Merge "
 "abzuschließen.\n"
 
-#: builtin/merge.c:813
+#: builtin/merge.c:809
 #, c-format
 msgid ""
 "Please enter a commit message to explain why this merge is necessary,\n"
@@ -6931,50 +6997,50 @@ msgstr ""
 "Zeilen beginnend mit '%c' werden ignoriert, und eine leere Beschreibung\n"
 "bricht den Commit ab.\n"
 
-#: builtin/merge.c:837
+#: builtin/merge.c:833
 msgid "Empty commit message."
 msgstr "Leere Commit-Beschreibung"
 
-#: builtin/merge.c:849
+#: builtin/merge.c:845
 #, c-format
 msgid "Wonderful.\n"
 msgstr "Wunderbar.\n"
 
-#: builtin/merge.c:914
+#: builtin/merge.c:908
 #, c-format
 msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
 msgstr ""
 "Automatischer Merge fehlgeschlagen; beheben Sie die Konflikte und committen "
 "Sie dann das Ergebnis.\n"
 
-#: builtin/merge.c:930
+#: builtin/merge.c:924
 #, c-format
 msgid "'%s' is not a commit"
 msgstr "'%s' ist kein Commit"
 
-#: builtin/merge.c:971
+#: builtin/merge.c:965
 msgid "No current branch."
 msgstr "Sie befinden sich auf keinem Branch."
 
-#: builtin/merge.c:973
+#: builtin/merge.c:967
 msgid "No remote for the current branch."
 msgstr "Kein Remote-Repository für den aktuellen Branch."
 
-#: builtin/merge.c:975
+#: builtin/merge.c:969
 msgid "No default upstream defined for the current branch."
 msgstr ""
 "Es ist kein Standard-Upstream-Branch für den aktuellen Branch definiert."
 
-#: builtin/merge.c:980
+#: builtin/merge.c:974
 #, c-format
 msgid "No remote-tracking branch for %s from %s"
 msgstr "Kein Remote-Tracking-Branch für %s von %s"
 
-#: builtin/merge.c:1136
+#: builtin/merge.c:1130
 msgid "There is no merge to abort (MERGE_HEAD missing)."
 msgstr "Es gibt keinen Merge zum Abbrechen (vermisse MERGE_HEAD)"
 
-#: builtin/merge.c:1152 git-pull.sh:31
+#: builtin/merge.c:1146 git-pull.sh:31
 msgid ""
 "You have not concluded your merge (MERGE_HEAD exists).\n"
 "Please, commit your changes before you can merge."
@@ -6982,11 +7048,11 @@ msgstr ""
 "Sie haben Ihren Merge nicht abgeschlossen (MERGE_HEAD existiert).\n"
 "Bitte committen Sie Ihre Ã„nderungen, bevor Sie \"merge\" ausführen können."
 
-#: builtin/merge.c:1155 git-pull.sh:34
+#: builtin/merge.c:1149 git-pull.sh:34
 msgid "You have not concluded your merge (MERGE_HEAD exists)."
 msgstr "Sie haben Ihren Merge nicht abgeschlossen (MERGE_HEAD existiert)."
 
-#: builtin/merge.c:1159
+#: builtin/merge.c:1153
 msgid ""
 "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
 "Please, commit your changes before you can merge."
@@ -6994,105 +7060,105 @@ msgstr ""
 "Sie haben \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert).\n"
 "Bitte committen Sie Ihre Ã„nderungen, bevor Sie \"merge\" ausführen können."
 
-#: builtin/merge.c:1162
+#: builtin/merge.c:1156
 msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
 msgstr ""
 "Sie haben \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert)."
 
-#: builtin/merge.c:1171
+#: builtin/merge.c:1165
 msgid "You cannot combine --squash with --no-ff."
 msgstr "Sie können --squash nicht mit --no-ff kombinieren."
 
-#: builtin/merge.c:1180
+#: builtin/merge.c:1174
 msgid "No commit specified and merge.defaultToUpstream not set."
 msgstr "Kein Commit angegeben und merge.defaultToUpstream ist nicht gesetzt."
 
-#: builtin/merge.c:1212
+#: builtin/merge.c:1206
 msgid "Can merge only exactly one commit into empty head"
 msgstr "Kann nur exakt einen Commit in einem leeren Branch zusammenführen."
 
-#: builtin/merge.c:1215
+#: builtin/merge.c:1209
 msgid "Squash commit into empty head not supported yet"
 msgstr ""
 "Bin auf einem Commit, der noch geboren wird; kann \"squash\" nicht ausführen."
 
-#: builtin/merge.c:1217
+#: builtin/merge.c:1211
 msgid "Non-fast-forward commit does not make sense into an empty head"
 msgstr ""
 "Nicht vorzuspulender Commit kann nicht in einem leeren Branch verwendet "
 "werden."
 
-#: builtin/merge.c:1222
+#: builtin/merge.c:1216
 #, c-format
 msgid "%s - not something we can merge"
 msgstr "%s - nichts was wir zusammenführen können"
 
-#: builtin/merge.c:1273
+#: builtin/merge.c:1267
 #, c-format
 msgid "Commit %s has an untrusted GPG signature, allegedly by %s."
 msgstr ""
 "Commit %s hat eine nicht vertrauenswürdige GPG-Signatur, angeblich von %s."
 
-#: builtin/merge.c:1276
+#: builtin/merge.c:1270
 #, c-format
 msgid "Commit %s has a bad GPG signature allegedly by %s."
 msgstr "Commit %s hat eine ungültige GPG-Signatur, angeblich von %s."
 
-#: builtin/merge.c:1279
+#: builtin/merge.c:1273
 #, c-format
 msgid "Commit %s does not have a GPG signature."
 msgstr "Commit %s hat keine GPG-Signatur."
 
-#: builtin/merge.c:1282
+#: builtin/merge.c:1276
 #, c-format
 msgid "Commit %s has a good GPG signature by %s\n"
 msgstr "Commit %s hat eine gültige GPG-Signatur von %s\n"
 
-#: builtin/merge.c:1366
+#: builtin/merge.c:1357
 #, c-format
 msgid "Updating %s..%s\n"
 msgstr "Aktualisiere %s..%s\n"
 
-#: builtin/merge.c:1405
+#: builtin/merge.c:1396
 #, c-format
 msgid "Trying really trivial in-index merge...\n"
 msgstr "Probiere wirklich trivialen \"in-index\"-Merge...\n"
 
-#: builtin/merge.c:1412
+#: builtin/merge.c:1403
 #, c-format
 msgid "Nope.\n"
 msgstr "Nein.\n"
 
-#: builtin/merge.c:1444
+#: builtin/merge.c:1435
 msgid "Not possible to fast-forward, aborting."
 msgstr "Vorspulen nicht möglich, breche ab."
 
-#: builtin/merge.c:1467 builtin/merge.c:1546
+#: builtin/merge.c:1458 builtin/merge.c:1537
 #, c-format
 msgid "Rewinding the tree to pristine...\n"
 msgstr "Rücklauf des Verzeichnisses bis zum Ursprung...\n"
 
-#: builtin/merge.c:1471
+#: builtin/merge.c:1462
 #, c-format
 msgid "Trying merge strategy %s...\n"
 msgstr "Probiere Merge-Strategie %s...\n"
 
-#: builtin/merge.c:1537
+#: builtin/merge.c:1528
 #, c-format
 msgid "No merge strategy handled the merge.\n"
 msgstr "Keine Merge-Strategie behandelt diesen Merge.\n"
 
-#: builtin/merge.c:1539
+#: builtin/merge.c:1530
 #, c-format
 msgid "Merge with strategy %s failed.\n"
 msgstr "Merge mit Strategie %s fehlgeschlagen.\n"
 
-#: builtin/merge.c:1548
+#: builtin/merge.c:1539
 #, c-format
 msgid "Using the %s to prepare resolving by hand.\n"
 msgstr "Benutzen Sie \"%s\" um die Auflösung per Hand vorzubereiten.\n"
 
-#: builtin/merge.c:1560
+#: builtin/merge.c:1551
 #, c-format
 msgid "Automatic merge went well; stopped before committing as requested\n"
 msgstr ""
@@ -7248,79 +7314,79 @@ msgstr "Quellverzeichnis ist leer"
 msgid "not under version control"
 msgstr "nicht unter Versionskontrolle"
 
-#: builtin/mv.c:207
+#: builtin/mv.c:208
 msgid "destination exists"
 msgstr "Ziel existiert bereits"
 
-#: builtin/mv.c:215
+#: builtin/mv.c:216
 #, c-format
 msgid "overwriting '%s'"
 msgstr "überschreibe '%s'"
 
-#: builtin/mv.c:218
+#: builtin/mv.c:219
 msgid "Cannot overwrite"
 msgstr "Kann nicht Ã¼berschreiben"
 
-#: builtin/mv.c:221
+#: builtin/mv.c:222
 msgid "multiple sources for the same target"
 msgstr "mehrere Quellen für das selbe Ziel"
 
-#: builtin/mv.c:223
+#: builtin/mv.c:224
 msgid "destination directory does not exist"
 msgstr "Zielverzeichnis existiert nicht"
 
-#: builtin/mv.c:243
+#: builtin/mv.c:244
 #, c-format
 msgid "%s, source=%s, destination=%s"
 msgstr "%s, Quelle=%s, Ziel=%s"
 
-#: builtin/mv.c:253
+#: builtin/mv.c:254
 #, c-format
 msgid "Renaming %s to %s\n"
 msgstr "Benenne %s nach %s um\n"
 
-#: builtin/mv.c:256 builtin/remote.c:726 builtin/repack.c:355
+#: builtin/mv.c:257 builtin/remote.c:725 builtin/repack.c:358
 #, c-format
 msgid "renaming '%s' failed"
 msgstr "Umbenennung von '%s' fehlgeschlagen"
 
-#: builtin/name-rev.c:258
+#: builtin/name-rev.c:255
 msgid "git name-rev [options] <commit>..."
 msgstr "git name-rev [Optionen] <Commit>..."
 
-#: builtin/name-rev.c:259
+#: builtin/name-rev.c:256
 msgid "git name-rev [options] --all"
 msgstr "git name-rev [Optionen] --all"
 
-#: builtin/name-rev.c:260
+#: builtin/name-rev.c:257
 msgid "git name-rev [options] --stdin"
 msgstr "git name-rev [Optionen] --stdin"
 
-#: builtin/name-rev.c:312
+#: builtin/name-rev.c:309
 msgid "print only names (no SHA-1)"
 msgstr "zeigt nur Namen an (keine SHA-1)"
 
-#: builtin/name-rev.c:313
+#: builtin/name-rev.c:310
 msgid "only use tags to name the commits"
 msgstr "verwendet nur Tags um die Commits zu benennen"
 
-#: builtin/name-rev.c:315
+#: builtin/name-rev.c:312
 msgid "only use refs matching <pattern>"
 msgstr "verwendet nur Referenzen die <Muster> entsprechen"
 
-#: builtin/name-rev.c:317
+#: builtin/name-rev.c:314
 msgid "list all commits reachable from all refs"
 msgstr "listet alle Commits auf, die von allen Referenzen erreichbar sind"
 
-#: builtin/name-rev.c:318
+#: builtin/name-rev.c:315
 msgid "read from stdin"
 msgstr "liest von der Standard-Eingabe"
 
-#: builtin/name-rev.c:319
+#: builtin/name-rev.c:316
 msgid "allow to print `undefined` names (default)"
 msgstr "erlaubt Ausgabe von `undefinierten` Namen (Standard)"
 
-#: builtin/name-rev.c:325
+#: builtin/name-rev.c:322
 msgid "dereference tags in the input (internal use)"
 msgstr "dereferenziert Tags in der Eingabe (interne Verwendung)"
 
@@ -7450,7 +7516,7 @@ msgstr "Konnte Ausgabe von 'show' nicht lesen."
 msgid "failed to finish 'show' for object '%s'"
 msgstr "konnte 'show' für Objekt '%s' nicht abschließen"
 
-#: builtin/notes.c:167 builtin/tag.c:373
+#: builtin/notes.c:167 builtin/tag.c:477
 #, c-format
 msgid "could not create file '%s'"
 msgstr "konnte Datei '%s' nicht erstellen"
@@ -7474,12 +7540,12 @@ msgstr "Konnte Notiz-Objekt nicht schreiben"
 msgid "The note contents has been left in %s"
 msgstr "Die Notiz-Inhalte wurden in %s belassen"
 
-#: builtin/notes.c:248 builtin/tag.c:604
+#: builtin/notes.c:248 builtin/tag.c:692
 #, c-format
 msgid "cannot read '%s'"
 msgstr "kann '%s' nicht lesen"
 
-#: builtin/notes.c:250 builtin/tag.c:607
+#: builtin/notes.c:250 builtin/tag.c:695
 #, c-format
 msgid "could not open or read '%s'"
 msgstr "konnte '%s' nicht Ã¶ffnen oder lesen"
@@ -7487,7 +7553,7 @@ msgstr "konnte '%s' nicht Ã¶ffnen oder lesen"
 #: builtin/notes.c:269 builtin/notes.c:320 builtin/notes.c:322
 #: builtin/notes.c:382 builtin/notes.c:436 builtin/notes.c:519
 #: builtin/notes.c:524 builtin/notes.c:599 builtin/notes.c:641
-#: builtin/notes.c:843 builtin/tag.c:620
+#: builtin/notes.c:843 builtin/tag.c:708
 #, c-format
 msgid "Failed to resolve '%s' as a valid ref."
 msgstr "Konnte '%s' nicht als gültige Referenz auflösen."
@@ -7532,7 +7598,7 @@ msgid "note contents in a file"
 msgstr "Notizinhalte in einer Datei"
 
 #: builtin/notes.c:415 builtin/notes.c:418 builtin/notes.c:572
-#: builtin/notes.c:575 builtin/tag.c:539
+#: builtin/notes.c:575 builtin/tag.c:627
 msgid "object"
 msgstr "Objekt"
 
@@ -7654,7 +7720,7 @@ msgstr "Notiz-Referenz"
 msgid "use notes from <notes_ref>"
 msgstr "verwendet Notizen von <Notiz-Referenz>"
 
-#: builtin/notes.c:978 builtin/remote.c:1593
+#: builtin/notes.c:978 builtin/remote.c:1616
 #, c-format
 msgid "Unknown subcommand: %s"
 msgstr "Unbekanntes Unterkommando: %s"
@@ -7680,167 +7746,169 @@ msgstr "Schreibe Objekte"
 
 #: builtin/pack-objects.c:1012
 msgid "disabling bitmap writing, as some objects are not being packed"
-msgstr "Deaktiviere Schreiben des Bitmap-Index, da einige Objekte nicht in\n"
+msgstr ""
+"Deaktiviere Schreiben des Bitmap-Index, da einige Objekte nicht in\n"
 "eine Pack-Datei geschrieben wurden"
 
 #: builtin/pack-objects.c:2174
 msgid "Compressing objects"
 msgstr "Komprimiere Objekte"
 
-#: builtin/pack-objects.c:2530
+#: builtin/pack-objects.c:2526
 #, c-format
 msgid "unsupported index version %s"
 msgstr "Nicht unterstützte Staging-Area-Version %s"
 
-#: builtin/pack-objects.c:2534
+#: builtin/pack-objects.c:2530
 #, c-format
 msgid "bad index version '%s'"
 msgstr "Ungültige Staging-Area-Version '%s'"
 
-#: builtin/pack-objects.c:2557
+#: builtin/pack-objects.c:2553
 #, c-format
 msgid "option %s does not accept negative form"
 msgstr "Option %s akzeptiert keine negative Form"
 
-#: builtin/pack-objects.c:2561
+#: builtin/pack-objects.c:2557
 #, c-format
 msgid "unable to parse value '%s' for option %s"
 msgstr "konnte Wert '%s' für Option %s nicht parsen"
 
-#: builtin/pack-objects.c:2580
+#: builtin/pack-objects.c:2576
 msgid "do not show progress meter"
 msgstr "zeigt keine Fortschrittsanzeige"
 
-#: builtin/pack-objects.c:2582
+#: builtin/pack-objects.c:2578
 msgid "show progress meter"
 msgstr "zeigt Fortschrittsanzeige"
 
-#: builtin/pack-objects.c:2584
+#: builtin/pack-objects.c:2580
 msgid "show progress meter during object writing phase"
 msgstr "zeigt Forschrittsanzeige während der Phase des Schreibens der Objekte"
 
-#: builtin/pack-objects.c:2587
+#: builtin/pack-objects.c:2583
 msgid "similar to --all-progress when progress meter is shown"
 msgstr "ähnlich zu --all-progress wenn Fortschrittsanzeige darstellt wird"
 
-#: builtin/pack-objects.c:2588
+#: builtin/pack-objects.c:2584
 msgid "version[,offset]"
 msgstr "version[,offset]"
 
-#: builtin/pack-objects.c:2589
+#: builtin/pack-objects.c:2585
 msgid "write the pack index file in the specified idx format version"
 msgstr ""
 "schreibt die Index-Datei des Paketes in der angegebenen Indexformat-Version"
 
-#: builtin/pack-objects.c:2592
+#: builtin/pack-objects.c:2588
 msgid "maximum size of each output pack file"
 msgstr "maximale Größe für jede ausgegebene Paketdatei"
 
-#: builtin/pack-objects.c:2594
+#: builtin/pack-objects.c:2590
 msgid "ignore borrowed objects from alternate object store"
 msgstr "ignoriert geliehene Objekte von alternativem Objektspeicher"
 
-#: builtin/pack-objects.c:2596
+#: builtin/pack-objects.c:2592
 msgid "ignore packed objects"
 msgstr "ignoriert gepackte Objekte"
 
-#: builtin/pack-objects.c:2598
+#: builtin/pack-objects.c:2594
 msgid "limit pack window by objects"
 msgstr "begrenzt Paketfenster durch Objekte"
 
-#: builtin/pack-objects.c:2600
+#: builtin/pack-objects.c:2596
 msgid "limit pack window by memory in addition to object limit"
 msgstr "begrenzt Paketfenster, zusätzlich zur Objektbegrenzung, durch Speicher"
 
-#: builtin/pack-objects.c:2602
+#: builtin/pack-objects.c:2598
 msgid "maximum length of delta chain allowed in the resulting pack"
 msgstr ""
 "maximale Länge der erlaubten Differenzverkettung im resultierenden Paket"
 
-#: builtin/pack-objects.c:2604
+#: builtin/pack-objects.c:2600
 msgid "reuse existing deltas"
 msgstr "verwendet existierende Unterschiede wieder"
 
-#: builtin/pack-objects.c:2606
+#: builtin/pack-objects.c:2602
 msgid "reuse existing objects"
 msgstr "verwendet existierende Objekte wieder"
 
-#: builtin/pack-objects.c:2608
+#: builtin/pack-objects.c:2604
 msgid "use OFS_DELTA objects"
 msgstr "verwendet OFS_DELTA Objekte"
 
-#: builtin/pack-objects.c:2610
+#: builtin/pack-objects.c:2606
 msgid "use threads when searching for best delta matches"
 msgstr ""
 "verwendet Threads bei der Suche nach den besten Ãœbereinstimmungen bei "
 "Unterschieden"
 
-#: builtin/pack-objects.c:2612
+#: builtin/pack-objects.c:2608
 msgid "do not create an empty pack output"
 msgstr "erzeugt keine leeren Pakete"
 
-#: builtin/pack-objects.c:2614
+#: builtin/pack-objects.c:2610
 msgid "read revision arguments from standard input"
 msgstr "liest Argumente bezüglich Commits von der Standard-Eingabe"
 
-#: builtin/pack-objects.c:2616
+#: builtin/pack-objects.c:2612
 msgid "limit the objects to those that are not yet packed"
 msgstr "begrenzt die Objekte zu solchen, die noch nicht gepackt wurden"
 
-#: builtin/pack-objects.c:2619
+#: builtin/pack-objects.c:2615
 msgid "include objects reachable from any reference"
 msgstr "schließt Objekte ein, die von jeder Referenz erreichbar sind"
 
-#: builtin/pack-objects.c:2622
+#: builtin/pack-objects.c:2618
 msgid "include objects referred by reflog entries"
 msgstr ""
 "schließt Objekte ein, die von Einträgen des Reflogs referenziert werden"
 
-#: builtin/pack-objects.c:2625
+#: builtin/pack-objects.c:2621
 msgid "output pack to stdout"
 msgstr "schreibt Paket in die Standard-Ausgabe"
 
-#: builtin/pack-objects.c:2627
+#: builtin/pack-objects.c:2623
 msgid "include tag objects that refer to objects to be packed"
 msgstr "schließt Tag-Objekte ein, die auf gepackte Objekte referenzieren"
 
-#: builtin/pack-objects.c:2629
+#: builtin/pack-objects.c:2625
 msgid "keep unreachable objects"
 msgstr "behält nicht erreichbare Objekte"
 
-#: builtin/pack-objects.c:2630 parse-options.h:140
+#: builtin/pack-objects.c:2626 parse-options.h:140
 msgid "time"
 msgstr "Zeit"
 
-#: builtin/pack-objects.c:2631
+#: builtin/pack-objects.c:2627
 msgid "unpack unreachable objects newer than <time>"
 msgstr "entpackt nicht erreichbare Objekte, die neuer als <Zeit> sind"
 
-#: builtin/pack-objects.c:2634
+#: builtin/pack-objects.c:2630
 msgid "create thin packs"
 msgstr "erzeugt dünnere Pakete"
 
-#: builtin/pack-objects.c:2636
+#: builtin/pack-objects.c:2632
 msgid "ignore packs that have companion .keep file"
 msgstr "ignoriert Pakete die .keep Dateien haben"
 
-#: builtin/pack-objects.c:2638
+#: builtin/pack-objects.c:2634
 msgid "pack compression level"
 msgstr "Komprimierungsgrad für Paketierung"
 
-#: builtin/pack-objects.c:2640
+#: builtin/pack-objects.c:2636
 msgid "do not hide commits by grafts"
 msgstr "verbirgt keine künstlichen Vorgänger-Commits (\"grafts\")"
 
-#: builtin/pack-objects.c:2642
+#: builtin/pack-objects.c:2638
 msgid "use a bitmap index if available to speed up counting objects"
-msgstr "benutzt Bitmap-Index (falls verfügbar) zur Optimierung der Objektzählung"
+msgstr ""
+"benutzt Bitmap-Index (falls verfügbar) zur Optimierung der Objektzählung"
 
-#: builtin/pack-objects.c:2644
+#: builtin/pack-objects.c:2640
 msgid "write a bitmap index together with the pack index"
 msgstr "schreibt Bitmap-Index zusammen mit Pack-Index"
 
-#: builtin/pack-objects.c:2723
+#: builtin/pack-objects.c:2719
 msgid "Counting objects"
 msgstr "Zähle Objekte"
 
@@ -7892,7 +7960,7 @@ msgstr "Kurzschrift für Tag ohne <Tag>"
 msgid "--delete only accepts plain target ref names"
 msgstr "Die Option --delete akzeptiert nur reine Referenznamen als Ziel."
 
-#: builtin/push.c:140
+#: builtin/push.c:139
 msgid ""
 "\n"
 "To choose either option permanently, see push.default in 'git help config'."
@@ -7901,7 +7969,7 @@ msgstr ""
 "Um eine Variante permanent zu verwenden, siehe push.default in 'git help "
 "config'."
 
-#: builtin/push.c:143
+#: builtin/push.c:142
 #, c-format
 msgid ""
 "The upstream branch of your current branch does not match\n"
@@ -7927,7 +7995,7 @@ msgstr ""
 "    git push %s %s\n"
 "%s"
 
-#: builtin/push.c:158
+#: builtin/push.c:157
 #, c-format
 msgid ""
 "You are not currently on a branch.\n"
@@ -7942,7 +8010,7 @@ msgstr ""
 "\n"
 "    git push %s HEAD:<Name-des-Remote-Branches>\n"
 
-#: builtin/push.c:172
+#: builtin/push.c:171
 #, c-format
 msgid ""
 "The current branch %s has no upstream branch.\n"
@@ -7956,13 +8024,13 @@ msgstr ""
 "\n"
 "    git push --set-upstream %s %s\n"
 
-#: builtin/push.c:180
+#: builtin/push.c:179
 #, c-format
 msgid "The current branch %s has multiple upstream branches, refusing to push."
 msgstr ""
 "Der aktuelle Branch %s hat mehrere Upstream-Branches, \"push\" verweigert."
 
-#: builtin/push.c:183
+#: builtin/push.c:182
 #, c-format
 msgid ""
 "You are pushing to remote '%s', which is not the upstream of\n"
@@ -7973,7 +8041,7 @@ msgstr ""
 "Branches '%s' ist, ohne anzugeben, was versendet werden soll, um welchen\n"
 "Remote-Branch zu aktualisieren."
 
-#: builtin/push.c:206
+#: builtin/push.c:205
 msgid ""
 "push.default is unset; its implicit value has changed in\n"
 "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
@@ -8024,14 +8092,14 @@ msgstr ""
 "von\n"
 "Git benutzen.)"
 
-#: builtin/push.c:273
+#: builtin/push.c:272
 msgid ""
 "You didn't specify any refspecs to push, and push.default is \"nothing\"."
 msgstr ""
 "Sie haben keine Refspec für \"push\" angegeben, und push.default ist "
 "\"nothing\"."
 
-#: builtin/push.c:280
+#: builtin/push.c:279
 msgid ""
 "Updates were rejected because the tip of your current branch is behind\n"
 "its remote counterpart. Integrate the remote changes (e.g.\n"
@@ -8045,7 +8113,7 @@ msgstr ""
 "Siehe auch die Sektion 'Note about fast-forwards' in 'git push --help'\n"
 "für weitere Details."
 
-#: builtin/push.c:286
+#: builtin/push.c:285
 msgid ""
 "Updates were rejected because a pushed branch tip is behind its remote\n"
 "counterpart. Check out this branch and integrate the remote changes\n"
@@ -8059,7 +8127,7 @@ msgstr ""
 "Siehe auch die Sektion 'Note about fast-forwards' in 'git push --help'\n"
 "für weitere Details."
 
-#: builtin/push.c:292
+#: builtin/push.c:291
 msgid ""
 "Updates were rejected because the remote contains work that you do\n"
 "not have locally. This is usually caused by another repository pushing\n"
@@ -8078,13 +8146,13 @@ msgstr ""
 "Siehe auch die Sektion 'Note about fast-forwards' in 'git push --help'\n"
 "für weitere Details."
 
-#: builtin/push.c:299
+#: builtin/push.c:298
 msgid "Updates were rejected because the tag already exists in the remote."
 msgstr ""
 "Aktualisierungen wurden zurückgewiesen, weil das Tag bereits\n"
 "im Remote-Repository existiert."
 
-#: builtin/push.c:302
+#: builtin/push.c:301
 msgid ""
 "You cannot update a remote ref that points at a non-commit object,\n"
 "or update a remote ref to make it point at a non-commit object,\n"
@@ -8094,22 +8162,22 @@ msgstr ""
 "das kein Commit ist, oder es auf ein solches Objekt zeigen lassen, ohne\n"
 "die Option '--force' zu verwenden.\n"
 
-#: builtin/push.c:361
+#: builtin/push.c:360
 #, c-format
 msgid "Pushing to %s\n"
 msgstr "Versende nach %s\n"
 
-#: builtin/push.c:365
+#: builtin/push.c:364
 #, c-format
 msgid "failed to push some refs to '%s'"
 msgstr "Fehler beim Versenden einiger Referenzen nach '%s'"
 
-#: builtin/push.c:395
+#: builtin/push.c:394
 #, c-format
 msgid "bad repository '%s'"
 msgstr "ungültiges Repository '%s'"
 
-#: builtin/push.c:396
+#: builtin/push.c:395
 msgid ""
 "No configured push destination.\n"
 "Either specify the URL from the command-line or configure a remote "
@@ -8131,95 +8199,95 @@ msgstr ""
 "\n"
 "    git push <Name>\n"
 
-#: builtin/push.c:411
+#: builtin/push.c:410
 msgid "--all and --tags are incompatible"
 msgstr "Die Optionen --all und --tags sind inkompatibel."
 
-#: builtin/push.c:412
+#: builtin/push.c:411
 msgid "--all can't be combined with refspecs"
 msgstr "Die Option --all kann nicht mit Refspecs kombiniert werden."
 
-#: builtin/push.c:417
+#: builtin/push.c:416
 msgid "--mirror and --tags are incompatible"
 msgstr "Die Optionen --mirror und --tags sind inkompatibel."
 
-#: builtin/push.c:418
+#: builtin/push.c:417
 msgid "--mirror can't be combined with refspecs"
 msgstr "Die Option --mirror kann nicht mit Refspecs kombiniert werden."
 
-#: builtin/push.c:423
+#: builtin/push.c:422
 msgid "--all and --mirror are incompatible"
 msgstr "Die Optionen --all und --mirror sind inkompatibel."
 
-#: builtin/push.c:483
+#: builtin/push.c:482
 msgid "repository"
 msgstr "Repository"
 
-#: builtin/push.c:484
+#: builtin/push.c:483
 msgid "push all refs"
 msgstr "versendet alle Referenzen"
 
-#: builtin/push.c:485
+#: builtin/push.c:484
 msgid "mirror all refs"
 msgstr "spiegelt alle Referenzen"
 
-#: builtin/push.c:487
+#: builtin/push.c:486
 msgid "delete refs"
 msgstr "löscht Referenzen"
 
-#: builtin/push.c:488
+#: builtin/push.c:487
 msgid "push tags (can't be used with --all or --mirror)"
 msgstr "versendet Tags (kann nicht mit --all oder --mirror verwendet werden)"
 
-#: builtin/push.c:491
+#: builtin/push.c:490
 msgid "force updates"
 msgstr "erzwingt Aktualisierung"
 
-#: builtin/push.c:493
+#: builtin/push.c:492
 msgid "refname>:<expect"
 msgstr "Referenzname>:<Erwartungswert"
 
-#: builtin/push.c:494
+#: builtin/push.c:493
 msgid "require old value of ref to be at this value"
 msgstr "Referenz muss sich auf dem angegebenen Wert befinden"
 
-#: builtin/push.c:496
+#: builtin/push.c:495
 msgid "check"
 msgstr ""
 
-#: builtin/push.c:497
+#: builtin/push.c:496
 msgid "control recursive pushing of submodules"
 msgstr "steuert rekursiven \"push\" von Submodulen"
 
-#: builtin/push.c:499
+#: builtin/push.c:498
 msgid "use thin pack"
 msgstr "verwendet kleinere Pakete"
 
-#: builtin/push.c:500 builtin/push.c:501
+#: builtin/push.c:499 builtin/push.c:500
 msgid "receive pack program"
 msgstr "'receive pack' Programm"
 
-#: builtin/push.c:502
+#: builtin/push.c:501
 msgid "set upstream for git pull/status"
 msgstr "setzt Upstream für \"git pull/status\""
 
-#: builtin/push.c:505
+#: builtin/push.c:504
 msgid "prune locally removed refs"
 msgstr "entfernt lokal gelöschte Referenzen"
 
-#: builtin/push.c:507
+#: builtin/push.c:506
 msgid "bypass pre-push hook"
 msgstr "umgeht \"pre-push hook\""
 
-#: builtin/push.c:508
+#: builtin/push.c:507
 msgid "push missing but relevant tags"
 msgstr "versendet fehlende, aber relevante Tags"
 
-#: builtin/push.c:518
+#: builtin/push.c:517
 msgid "--delete is incompatible with --all, --mirror and --tags"
 msgstr "Die Option --delete ist inkompatibel mit --all, --mirror und --tags."
 
-#: builtin/push.c:520
+#: builtin/push.c:519
 msgid "--delete doesn't make sense without any refs"
 msgstr "Die Option --delete kann nur mit Referenzen verwendet werden."
 
@@ -8450,12 +8518,12 @@ msgstr ""
 "Die Angabe von zu folgenden Branches kann nur mit dem Anfordern von "
 "Spiegelarchiven verwendet werden."
 
-#: builtin/remote.c:185 builtin/remote.c:641
+#: builtin/remote.c:185 builtin/remote.c:640
 #, c-format
 msgid "remote %s already exists."
 msgstr "externes Repository %s existiert bereits"
 
-#: builtin/remote.c:189 builtin/remote.c:645
+#: builtin/remote.c:189 builtin/remote.c:644
 #, c-format
 msgid "'%s' is not a valid remote name"
 msgstr "'%s' ist kein gültiger Name für ein Remote-Repository"
@@ -8465,45 +8533,45 @@ msgstr "'%s' ist kein gültiger Name für ein Remote-Repository"
 msgid "Could not setup master '%s'"
 msgstr "Konnte symbolische Referenz für Hauptbranch von '%s' nicht einrichten"
 
-#: builtin/remote.c:289
+#: builtin/remote.c:288
 #, c-format
 msgid "more than one %s"
 msgstr "mehr als ein %s"
 
-#: builtin/remote.c:334
+#: builtin/remote.c:333
 #, c-format
 msgid "Could not get fetch map for refspec %s"
 msgstr "Konnte Fetch-Map für Refspec %s nicht bekommen"
 
-#: builtin/remote.c:435 builtin/remote.c:443
+#: builtin/remote.c:434 builtin/remote.c:442
 msgid "(matching)"
 msgstr "(übereinstimmend)"
 
-#: builtin/remote.c:447
+#: builtin/remote.c:446
 msgid "(delete)"
 msgstr "(lösche)"
 
-#: builtin/remote.c:590 builtin/remote.c:596 builtin/remote.c:602
+#: builtin/remote.c:589 builtin/remote.c:595 builtin/remote.c:601
 #, c-format
 msgid "Could not append '%s' to '%s'"
 msgstr "Konnte '%s' nicht an '%s' anhängen."
 
-#: builtin/remote.c:634 builtin/remote.c:787 builtin/remote.c:885
+#: builtin/remote.c:633 builtin/remote.c:794 builtin/remote.c:894
 #, c-format
 msgid "No such remote: %s"
 msgstr "Kein solches Remote-Repository: %s"
 
-#: builtin/remote.c:651
+#: builtin/remote.c:650
 #, c-format
 msgid "Could not rename config section '%s' to '%s'"
 msgstr "Konnte Sektion '%s' in Konfiguration nicht nach '%s' umbenennen"
 
-#: builtin/remote.c:657 builtin/remote.c:794
+#: builtin/remote.c:656 builtin/remote.c:846
 #, c-format
 msgid "Could not remove config section '%s'"
 msgstr "Konnte Sektion '%s' nicht aus Konfiguration entfernen"
 
-#: builtin/remote.c:672
+#: builtin/remote.c:671
 #, c-format
 msgid ""
 "Not updating non-default fetch refspec\n"
@@ -8514,32 +8582,32 @@ msgstr ""
 "\t%s\n"
 "\tBitte aktualisieren Sie, falls notwendig, die Konfiguration manuell."
 
-#: builtin/remote.c:678
+#: builtin/remote.c:677
 #, c-format
 msgid "Could not append '%s'"
 msgstr "Konnte '%s' nicht anhängen."
 
-#: builtin/remote.c:689
+#: builtin/remote.c:688
 #, c-format
 msgid "Could not set '%s'"
 msgstr "Konnte '%s' nicht setzen"
 
-#: builtin/remote.c:711
+#: builtin/remote.c:710
 #, c-format
 msgid "deleting '%s' failed"
 msgstr "Konnte '%s' nicht löschen"
 
-#: builtin/remote.c:745
+#: builtin/remote.c:744
 #, c-format
 msgid "creating '%s' failed"
 msgstr "Konnte '%s' nicht erstellen"
 
-#: builtin/remote.c:759
+#: builtin/remote.c:765
 #, c-format
 msgid "Could not remove branch %s"
 msgstr "Konnte Branch %s nicht löschen"
 
-#: builtin/remote.c:829
+#: builtin/remote.c:832
 msgid ""
 "Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
 "to delete it, use:"
@@ -8555,120 +8623,120 @@ msgstr[1] ""
 "entfernt;\n"
 "um diese zu entfernen, benutzen Sie:"
 
-#: builtin/remote.c:938
+#: builtin/remote.c:947
 #, c-format
 msgid " new (next fetch will store in remotes/%s)"
 msgstr " neu (wird bei nächstem \"fetch\" in remotes/%s gespeichert)"
 
-#: builtin/remote.c:941
+#: builtin/remote.c:950
 msgid " tracked"
 msgstr " gefolgt"
 
-#: builtin/remote.c:943
+#: builtin/remote.c:952
 msgid " stale (use 'git remote prune' to remove)"
 msgstr " veraltet (benutzen Sie 'git remote prune' zum Löschen)"
 
-#: builtin/remote.c:945
+#: builtin/remote.c:954
 msgid " ???"
 msgstr " ???"
 
-#: builtin/remote.c:986
+#: builtin/remote.c:995
 #, c-format
 msgid "invalid branch.%s.merge; cannot rebase onto > 1 branch"
 msgstr "ungültiges branch.%s.merge; kann Rebase nicht auf > 1 Branch ausführen"
 
-#: builtin/remote.c:993
+#: builtin/remote.c:1002
 #, c-format
 msgid "rebases onto remote %s"
 msgstr "Rebase auf Remote-Branch %s"
 
-#: builtin/remote.c:996
+#: builtin/remote.c:1005
 #, c-format
 msgid " merges with remote %s"
 msgstr " führt mit Remote-Branch %s zusammen"
 
-#: builtin/remote.c:997
+#: builtin/remote.c:1006
 msgid "    and with remote"
 msgstr "    und mit Remote-Branch"
 
-#: builtin/remote.c:999
+#: builtin/remote.c:1008
 #, c-format
 msgid "merges with remote %s"
 msgstr "führt mit Remote-Branch %s zusammen"
 
-#: builtin/remote.c:1000
+#: builtin/remote.c:1009
 msgid "   and with remote"
 msgstr "   und mit Remote-Branch"
 
-#: builtin/remote.c:1046
+#: builtin/remote.c:1055
 msgid "create"
 msgstr "erstellt"
 
-#: builtin/remote.c:1049
+#: builtin/remote.c:1058
 msgid "delete"
 msgstr "gelöscht"
 
-#: builtin/remote.c:1053
+#: builtin/remote.c:1062
 msgid "up to date"
 msgstr "aktuell"
 
-#: builtin/remote.c:1056
+#: builtin/remote.c:1065
 msgid "fast-forwardable"
 msgstr "vorspulbar"
 
-#: builtin/remote.c:1059
+#: builtin/remote.c:1068
 msgid "local out of date"
 msgstr "lokal nicht aktuell"
 
-#: builtin/remote.c:1066
+#: builtin/remote.c:1075
 #, c-format
 msgid "    %-*s forces to %-*s (%s)"
 msgstr "    %-*s erzwingt Versandt nach %-*s (%s)"
 
-#: builtin/remote.c:1069
+#: builtin/remote.c:1078
 #, c-format
 msgid "    %-*s pushes to %-*s (%s)"
 msgstr "    %-*s versendet nach %-*s (%s)"
 
-#: builtin/remote.c:1073
+#: builtin/remote.c:1082
 #, c-format
 msgid "    %-*s forces to %s"
 msgstr "    %-*s erzwingt Versand nach %s"
 
-#: builtin/remote.c:1076
+#: builtin/remote.c:1085
 #, c-format
 msgid "    %-*s pushes to %s"
 msgstr "    %-*s versendet nach %s"
 
-#: builtin/remote.c:1144
+#: builtin/remote.c:1153
 msgid "do not query remotes"
 msgstr "keine Abfrage von Remote-Repositories"
 
-#: builtin/remote.c:1171
+#: builtin/remote.c:1180
 #, c-format
 msgid "* remote %s"
 msgstr "* Remote-Repository %s"
 
-#: builtin/remote.c:1172
+#: builtin/remote.c:1181
 #, c-format
 msgid "  Fetch URL: %s"
 msgstr "  URL zum Abholen: %s"
 
-#: builtin/remote.c:1173 builtin/remote.c:1318
+#: builtin/remote.c:1182 builtin/remote.c:1329
 msgid "(no URL)"
 msgstr "(keine URL)"
 
-#: builtin/remote.c:1182 builtin/remote.c:1184
+#: builtin/remote.c:1191 builtin/remote.c:1193
 #, c-format
 msgid "  Push  URL: %s"
 msgstr "  URL zum Versenden: %s"
 
-#: builtin/remote.c:1186 builtin/remote.c:1188 builtin/remote.c:1190
+#: builtin/remote.c:1195 builtin/remote.c:1197 builtin/remote.c:1199
 #, c-format
 msgid "  HEAD branch: %s"
 msgstr "  Hauptbranch: %s"
 
-#: builtin/remote.c:1192
+#: builtin/remote.c:1201
 #, c-format
 msgid ""
 "  HEAD branch (remote HEAD is ambiguous, may be one of the following):\n"
@@ -8676,249 +8744,308 @@ msgstr ""
 "  Hauptbranch (externer HEAD ist mehrdeutig, könnte einer der folgenden "
 "sein):\n"
 
-#: builtin/remote.c:1204
+#: builtin/remote.c:1213
 #, c-format
 msgid "  Remote branch:%s"
 msgid_plural "  Remote branches:%s"
 msgstr[0] "  Remote-Branch:%s"
 msgstr[1] "  Remote-Branches:%s"
 
-#: builtin/remote.c:1207 builtin/remote.c:1234
+#: builtin/remote.c:1216 builtin/remote.c:1243
 msgid " (status not queried)"
 msgstr " (Zustand nicht abgefragt)"
 
-#: builtin/remote.c:1216
+#: builtin/remote.c:1225
 msgid "  Local branch configured for 'git pull':"
 msgid_plural "  Local branches configured for 'git pull':"
 msgstr[0] "  Lokaler Branch konfiguriert für 'git pull':"
 msgstr[1] "  Lokale Branches konfiguriert für 'git pull':"
 
-#: builtin/remote.c:1224
+#: builtin/remote.c:1233
 msgid "  Local refs will be mirrored by 'git push'"
 msgstr "  Lokale Referenzen werden von 'git push' gespiegelt"
 
-#: builtin/remote.c:1231
+#: builtin/remote.c:1240
 #, c-format
 msgid "  Local ref configured for 'git push'%s:"
 msgid_plural "  Local refs configured for 'git push'%s:"
 msgstr[0] "  Lokale Referenz konfiguriert für 'git push'%s:"
 msgstr[1] "  Lokale Referenzen konfiguriert für 'git push'%s:"
 
-#: builtin/remote.c:1252
+#: builtin/remote.c:1261
 msgid "set refs/remotes/<name>/HEAD according to remote"
 msgstr "setzt refs/remotes/<Name>/HEAD gemäß dem Remote-Repository"
 
-#: builtin/remote.c:1254
+#: builtin/remote.c:1263
 msgid "delete refs/remotes/<name>/HEAD"
 msgstr "entfernt refs/remotes/<Name>/HEAD"
 
-#: builtin/remote.c:1269
+#: builtin/remote.c:1278
 msgid "Cannot determine remote HEAD"
 msgstr "Kann HEAD des Remote-Repositories nicht bestimmen"
 
-#: builtin/remote.c:1271
+#: builtin/remote.c:1280
 msgid "Multiple remote HEAD branches. Please choose one explicitly with:"
 msgstr ""
 "Mehrere Hauptbranches im Remote-Repository. Bitte wählen Sie explizit einen "
 "aus mit:"
 
-#: builtin/remote.c:1281
+#: builtin/remote.c:1290
 #, c-format
 msgid "Could not delete %s"
 msgstr "Konnte %s nicht entfernen"
 
-#: builtin/remote.c:1289
+#: builtin/remote.c:1298
 #, c-format
 msgid "Not a valid ref: %s"
 msgstr "keine gültige Referenz: %s"
 
-#: builtin/remote.c:1291
+#: builtin/remote.c:1300
 #, c-format
 msgid "Could not setup %s"
 msgstr "Konnte %s nicht einrichten"
 
-#: builtin/remote.c:1307
+#: builtin/remote.c:1318
 #, c-format
 msgid " %s will become dangling!"
 msgstr " %s wird unreferenziert!"
 
-#: builtin/remote.c:1308
+#: builtin/remote.c:1319
 #, c-format
 msgid " %s has become dangling!"
 msgstr " %s wurde unreferenziert!"
 
-#: builtin/remote.c:1314
+#: builtin/remote.c:1325
 #, c-format
 msgid "Pruning %s"
 msgstr "entferne veraltete Branches von %s"
 
-#: builtin/remote.c:1315
+#: builtin/remote.c:1326
 #, c-format
 msgid "URL: %s"
 msgstr "URL: %s"
 
-#: builtin/remote.c:1328
+#: builtin/remote.c:1349
 #, c-format
 msgid " * [would prune] %s"
 msgstr " * [würde veralteten Branch entfernen] %s"
 
-#: builtin/remote.c:1331
+#: builtin/remote.c:1352
 #, c-format
 msgid " * [pruned] %s"
 msgstr "* [veralteten Branch entfernt] %s"
 
-#: builtin/remote.c:1374
+#: builtin/remote.c:1397
 msgid "prune remotes after fetching"
 msgstr "entfernt veraltete Branches im Remote-Repository nach \"fetch\""
 
-#: builtin/remote.c:1440 builtin/remote.c:1514
+#: builtin/remote.c:1463 builtin/remote.c:1537
 #, c-format
 msgid "No such remote '%s'"
 msgstr "Kein solches Remote-Repository '%s'"
 
-#: builtin/remote.c:1460
+#: builtin/remote.c:1483
 msgid "add branch"
 msgstr "fügt Branch hinzu"
 
-#: builtin/remote.c:1467
+#: builtin/remote.c:1490
 msgid "no remote specified"
 msgstr "kein Remote-Repository angegeben"
 
-#: builtin/remote.c:1489
+#: builtin/remote.c:1512
 msgid "manipulate push URLs"
 msgstr "manipuliert URLs für \"push\""
 
-#: builtin/remote.c:1491
+#: builtin/remote.c:1514
 msgid "add URL"
 msgstr "fügt URL hinzu"
 
-#: builtin/remote.c:1493
+#: builtin/remote.c:1516
 msgid "delete URLs"
 msgstr "löscht URLs"
 
-#: builtin/remote.c:1500
+#: builtin/remote.c:1523
 msgid "--add --delete doesn't make sense"
 msgstr ""
 "Die Optionen --add und --delete können nicht gemeinsam verwendet werden."
 
-#: builtin/remote.c:1540
+#: builtin/remote.c:1563
 #, c-format
 msgid "Invalid old URL pattern: %s"
 msgstr "ungültiges altes URL Format: %s"
 
-#: builtin/remote.c:1548
+#: builtin/remote.c:1571
 #, c-format
 msgid "No such URL found: %s"
 msgstr "Keine solche URL gefunden: %s"
 
-#: builtin/remote.c:1550
+#: builtin/remote.c:1573
 msgid "Will not delete all non-push URLs"
 msgstr "Werde keine URLs entfernen, die nicht für \"push\" bestimmt sind"
 
-#: builtin/remote.c:1564
+#: builtin/remote.c:1587
 msgid "be verbose; must be placed before a subcommand"
 msgstr "erweiterte Ausgaben; muss vor einem Unterkommando angegeben werden"
 
-#: builtin/repack.c:16
+#: builtin/repack.c:17
 msgid "git repack [options]"
 msgstr "git repack [Optionen]"
 
-#: builtin/repack.c:156
+#: builtin/repack.c:160
 msgid "pack everything in a single pack"
 msgstr "packt alles in eine einzige Pack-Datei"
 
-#: builtin/repack.c:158
+#: builtin/repack.c:162
 msgid "same as -a, and turn unreachable objects loose"
 msgstr "genau wie -a, unerreichbare Objekte werden aber nicht gelöscht"
 
-#: builtin/repack.c:161
+#: builtin/repack.c:165
 msgid "remove redundant packs, and run git-prune-packed"
 msgstr "entfernt redundante Pakete und führt \"git-prune-packed\" aus"
 
-#: builtin/repack.c:163
+#: builtin/repack.c:167
 msgid "pass --no-reuse-delta to git-pack-objects"
 msgstr "übergibt --no-reuse-delta an git-pack-objects"
 
-#: builtin/repack.c:165
+#: builtin/repack.c:169
 msgid "pass --no-reuse-object to git-pack-objects"
 msgstr "übergibt --no-reuse-object an git-pack-objects"
 
-#: builtin/repack.c:167
+#: builtin/repack.c:171
 msgid "do not run git-update-server-info"
 msgstr "git-update-server-info nicht ausführen"
 
-#: builtin/repack.c:170
+#: builtin/repack.c:174
 msgid "pass --local to git-pack-objects"
 msgstr "übergibt --local an git-pack-objects"
 
-#: builtin/repack.c:172
+#: builtin/repack.c:176
 msgid "write bitmap index"
 msgstr "schreibt Bitmap-Index"
 
-#: builtin/repack.c:173
+#: builtin/repack.c:177
 msgid "approxidate"
 msgstr "Datumsangabe"
 
-#: builtin/repack.c:174
+#: builtin/repack.c:178
 msgid "with -A, do not loosen objects older than this"
 msgstr "mit -A, löscht keine Objekte Ã¤lter als dieses Datum"
 
-#: builtin/repack.c:176
+#: builtin/repack.c:180
 msgid "size of the window used for delta compression"
 msgstr "Größe des Fensters für die Delta-Kompression"
 
-#: builtin/repack.c:177 builtin/repack.c:181
+#: builtin/repack.c:181 builtin/repack.c:185
 msgid "bytes"
 msgstr "Bytes"
 
-#: builtin/repack.c:178
+#: builtin/repack.c:182
 msgid "same as the above, but limit memory size instead of entries count"
 msgstr ""
 "gleiches wie oben, limitiert aber die Speichergröße anstatt der\n"
 "Anzahl der Einträge"
 
-#: builtin/repack.c:180
+#: builtin/repack.c:184
 msgid "limits the maximum delta depth"
 msgstr "limitiert die maximale Delta-Tiefe"
 
-#: builtin/repack.c:182
+#: builtin/repack.c:186
 msgid "maximum size of each packfile"
 msgstr "maximale Größe für jede Paketdatei"
 
-#: builtin/repack.c:184
+#: builtin/repack.c:188
 msgid "repack objects in packs marked with .keep"
-msgstr "packt Objekte um, die sich in mit .keep markierten Pack-Dateien befinden"
+msgstr ""
+"packt Objekte um, die sich in mit .keep markierten Pack-Dateien befinden"
 
-#: builtin/repack.c:371
+#: builtin/repack.c:374
 #, c-format
 msgid "removing '%s' failed"
 msgstr "Löschen von '%s' fehlgeschlagen"
 
-#: builtin/replace.c:17
+#: builtin/replace.c:19
 msgid "git replace [-f] <object> <replacement>"
 msgstr "git replace [-f] <Objekt> <Ersetzung>"
 
-#: builtin/replace.c:18
+#: builtin/replace.c:20
+msgid "git replace [-f] --edit <object>"
+msgstr "git replace [-f] --edit <Objekt>"
+
+#: builtin/replace.c:21
+msgid "git replace [-f] --graft <commit> [<parent>...]"
+msgstr "git replace [-f] --graft <Commit> [<Eltern-Commit>...]"
+
+#: builtin/replace.c:22
 msgid "git replace -d <object>..."
 msgstr "git replace -d <Objekt>..."
 
-#: builtin/replace.c:19
+#: builtin/replace.c:23
 msgid "git replace [--format=<format>] [-l [<pattern>]]"
 msgstr "git replace [--format=<Format>] [-l [<Muster>]]"
 
-#: builtin/replace.c:174
+#: builtin/replace.c:322 builtin/replace.c:360 builtin/replace.c:388
+#, c-format
+msgid "Not a valid object name: '%s'"
+msgstr "Ungültiger Objekt-Name: '%s'"
+
+#: builtin/replace.c:352
+#, c-format
+msgid "bad mergetag in commit '%s'"
+msgstr "ungültiger Merge-Tag in Commit '%s'"
+
+#: builtin/replace.c:354
+#, c-format
+msgid "malformed mergetag in commit '%s'"
+msgstr "fehlerhafter Merge-Tag in Commit '%s'"
+
+#: builtin/replace.c:365
+#, c-format
+msgid ""
+"original commit '%s' contains mergetag '%s' that is discarded; use --edit "
+"instead of --graft"
+msgstr ""
+"Der ursprüngliche Commit '%s' enthält Merge-Tag '%s', der verworfen\n"
+"wird; benutzen Sie --edit anstatt --graft"
+
+#: builtin/replace.c:398
+#, c-format
+msgid "the original commit '%s' has a gpg signature."
+msgstr "Der ursprüngliche Commit '%s' hat eine GPG-Signatur."
+
+#: builtin/replace.c:399
+msgid "the signature will be removed in the replacement commit!"
+msgstr "Die Signatur wird in dem Ersetzungs-Commit entfernt!"
+
+#: builtin/replace.c:405
+#, c-format
+msgid "could not write replacement commit for: '%s'"
+msgstr "Konnte Ersetzungs-Commit für '%s' nicht schreiben"
+
+#: builtin/replace.c:429
 msgid "list replace refs"
 msgstr "listet ersetzende Referenzen auf"
 
-#: builtin/replace.c:175
+#: builtin/replace.c:430
 msgid "delete replace refs"
 msgstr "löscht ersetzende Referenzen"
 
-#: builtin/replace.c:176
+#: builtin/replace.c:431
+msgid "edit existing object"
+msgstr "bearbeitet existierendes Objekt"
+
+#: builtin/replace.c:432
+msgid "change a commit's parents"
+msgstr "ändert Eltern-Commits eines Commits"
+
+#: builtin/replace.c:433
 msgid "replace the ref if it exists"
 msgstr "ersetzt die Referenz, wenn sie existiert"
 
-#: builtin/replace.c:177
+#: builtin/replace.c:434
+msgid "do not pretty-print contents for --edit"
+msgstr "keine ansprechende Anzeige des Objektinhaltes für --edit"
+
+#: builtin/replace.c:435
 msgid "use this format"
 msgstr "benutzt das angegebene Format"
 
@@ -8987,100 +9114,100 @@ msgstr "HEAD ist jetzt bei %s"
 msgid "Cannot do a %s reset in the middle of a merge."
 msgstr "Kann keinen '%s'-Reset durchführen, während ein Merge im Gange ist."
 
-#: builtin/reset.c:273
+#: builtin/reset.c:275
 msgid "be quiet, only report errors"
 msgstr "weniger Ausgaben, meldet nur Fehler"
 
-#: builtin/reset.c:275
+#: builtin/reset.c:277
 msgid "reset HEAD and index"
 msgstr "setzt HEAD und Staging-Area um"
 
-#: builtin/reset.c:276
+#: builtin/reset.c:278
 msgid "reset only HEAD"
 msgstr "setzt nur HEAD um"
 
-#: builtin/reset.c:278 builtin/reset.c:280
+#: builtin/reset.c:280 builtin/reset.c:282
 msgid "reset HEAD, index and working tree"
 msgstr "setzt HEAD, Staging-Area und Arbeitsverzeichnis um"
 
-#: builtin/reset.c:282
+#: builtin/reset.c:284
 msgid "reset HEAD but keep local changes"
 msgstr "setzt HEAD um, behält aber lokale Ã„nderungen"
 
-#: builtin/reset.c:285
+#: builtin/reset.c:287
 msgid "record only the fact that removed paths will be added later"
 msgstr "speichert nur, dass gelöschte Pfade später hinzugefügt werden sollen"
 
-#: builtin/reset.c:302
+#: builtin/reset.c:304
 #, c-format
 msgid "Failed to resolve '%s' as a valid revision."
 msgstr "Konnte '%s' nicht als gültigen Commit auflösen."
 
-#: builtin/reset.c:305 builtin/reset.c:313
+#: builtin/reset.c:307 builtin/reset.c:315
 #, c-format
 msgid "Could not parse object '%s'."
 msgstr "Konnte Objekt '%s' nicht parsen."
 
-#: builtin/reset.c:310
+#: builtin/reset.c:312
 #, c-format
 msgid "Failed to resolve '%s' as a valid tree."
 msgstr "Konnte '%s' nicht als gültiges \"Tree\"-Objekt auflösen."
 
-#: builtin/reset.c:319
+#: builtin/reset.c:321
 msgid "--patch is incompatible with --{hard,mixed,soft}"
 msgstr "--patch ist inkompatibel mit --{hard,mixed,soft}"
 
-#: builtin/reset.c:328
+#: builtin/reset.c:330
 msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
 msgstr ""
 "--mixed mit Pfaden ist veraltet; benutzen Sie stattdessen 'git reset -- "
 "<Pfade>'."
 
-#: builtin/reset.c:330
+#: builtin/reset.c:332
 #, c-format
 msgid "Cannot do %s reset with paths."
 msgstr "Ein '%s'-Reset mit Pfaden ist nicht möglich."
 
-#: builtin/reset.c:340
+#: builtin/reset.c:342
 #, c-format
 msgid "%s reset is not allowed in a bare repository"
 msgstr "'%s'-Reset ist in einem Bare-Repository nicht erlaubt"
 
-#: builtin/reset.c:344
+#: builtin/reset.c:346
 msgid "-N can only be used with --mixed"
 msgstr "-N kann nur mit -mixed benutzt werden"
 
-#: builtin/reset.c:361
+#: builtin/reset.c:363
 msgid "Unstaged changes after reset:"
 msgstr "Nicht zum Commit vorgemerkte Ã„nderungen nach Zurücksetzung:"
 
-#: builtin/reset.c:367
+#: builtin/reset.c:369
 #, c-format
 msgid "Could not reset index file to revision '%s'."
 msgstr "Konnte Staging-Area-Datei nicht zu Commit '%s' setzen."
 
-#: builtin/reset.c:372
+#: builtin/reset.c:373
 msgid "Could not write new index file."
 msgstr "Konnte neue Staging-Area-Datei nicht schreiben."
 
-#: builtin/rev-parse.c:359
+#: builtin/rev-parse.c:360
 msgid "git rev-parse --parseopt [options] -- [<args>...]"
 msgstr "git rev-parse --parseopt [Optionen] -- [<Argumente>...]"
 
-#: builtin/rev-parse.c:364
+#: builtin/rev-parse.c:365
 msgid "keep the `--` passed as an arg"
 msgstr "lässt `--` als Argument"
 
-#: builtin/rev-parse.c:366
+#: builtin/rev-parse.c:367
 msgid "stop parsing after the first non-option argument"
 msgstr "stoppt das Parsen nach dem ersten Argument was keine Option ist"
 
-#: builtin/rev-parse.c:369
+#: builtin/rev-parse.c:370
 msgid "output in stuck long form"
 msgstr ""
 "Ausgabe in Langform mit Argumenten an den Optionen (getrennt durch '=')"
 
-#: builtin/rev-parse.c:497
+#: builtin/rev-parse.c:498
 msgid ""
 "git rev-parse --parseopt [options] -- [<args>...]\n"
 "   or: git rev-parse --sq-quote [<arg>...]\n"
@@ -9396,11 +9523,11 @@ msgstr "zeigt die <n> jüngsten Einträge im Reflog beginnend an der Basis"
 
 #: builtin/show-ref.c:10
 msgid ""
-"git show-ref [-q|--quiet] [--verify] [--head] [-d|--dereference] [-s|--hash"
-"[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [pattern*] "
+"git show-ref [-q|--quiet] [--verify] [--head] [-d|--dereference] [-s|--"
+"hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [pattern*] "
 msgstr ""
-"git show-ref [-q|--quiet] [--verify] [--head] [-d|--dereference] [-s|--hash"
-"[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [pattern*] "
+"git show-ref [-q|--quiet] [--verify] [--head] [-d|--dereference] [-s|--"
+"hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [pattern*] "
 
 #: builtin/show-ref.c:11
 msgid "git show-ref --exclude-existing[=pattern] < ref-list"
@@ -9462,11 +9589,11 @@ msgstr "löscht symbolische Referenzen"
 msgid "shorten ref output"
 msgstr "verkürzte Ausgabe der Referenzen"
 
-#: builtin/symbolic-ref.c:43 builtin/update-ref.c:255
+#: builtin/symbolic-ref.c:43 builtin/update-ref.c:349
 msgid "reason"
 msgstr "Grund"
 
-#: builtin/symbolic-ref.c:43 builtin/update-ref.c:255
+#: builtin/symbolic-ref.c:43 builtin/update-ref.c:349
 msgid "reason of the update"
 msgstr "Grund für die Aktualisierung"
 
@@ -9493,203 +9620,212 @@ msgstr ""
 msgid "git tag -v <tagname>..."
 msgstr "git tag -v <Tagname>..."
 
-#: builtin/tag.c:67
+#: builtin/tag.c:69
 #, c-format
 msgid "malformed object at '%s'"
 msgstr "fehlerhaftes Objekt bei '%s'"
 
-#: builtin/tag.c:239
+#: builtin/tag.c:301
 #, c-format
 msgid "tag name too long: %.*s..."
 msgstr "Tagname zu lang: %.*s..."
 
-#: builtin/tag.c:244
+#: builtin/tag.c:306
 #, c-format
 msgid "tag '%s' not found."
 msgstr "Tag '%s' nicht gefunden."
 
-#: builtin/tag.c:259
+#: builtin/tag.c:321
 #, c-format
 msgid "Deleted tag '%s' (was %s)\n"
 msgstr "Tag '%s' gelöscht (war %s)\n"
 
-#: builtin/tag.c:271
+#: builtin/tag.c:333
 #, c-format
 msgid "could not verify the tag '%s'"
 msgstr "Konnte Tag '%s' nicht verifizieren"
 
-#: builtin/tag.c:281
+#: builtin/tag.c:343
 #, c-format
 msgid ""
 "\n"
-"Write a tag message\n"
+"Write a message for tag:\n"
+"  %s\n"
 "Lines starting with '%c' will be ignored.\n"
 msgstr ""
 "\n"
-"Geben Sie eine Tag-Beschreibung ein.\n"
-"Zeilen, die mit '%c' beginnen, werden ignoriert.\n"
+"Geben Sie eine Beschreibung für Tag\n"
+"  %s\n"
+"ein. Zeilen, die mit '%c' beginnen, werden ignoriert.\n"
 
-#: builtin/tag.c:285
+#: builtin/tag.c:347
 #, c-format
 msgid ""
 "\n"
-"Write a tag message\n"
+"Write a message for tag:\n"
+"  %s\n"
 "Lines starting with '%c' will be kept; you may remove them yourself if you "
 "want to.\n"
 msgstr ""
 "\n"
-"Geben Sie eine Tag-Beschreibung ein.\n"
-"Zeilen, die mit '%c' beginnen, werden behalten; Sie dürfen diese\n"
+"Geben Sie eine Beschreibung für Tag\n"
+"  %s\n"
+"ein. Zeilen, die mit '%c' beginnen, werden behalten; Sie dürfen diese\n"
 "selbst entfernen wenn Sie möchten.\n"
 
-#: builtin/tag.c:324
+#: builtin/tag.c:371
+#, c-format
+msgid "unsupported sort specification '%s'"
+msgstr "Nicht unterstützte Angabe für \"--sort\" '%s'"
+
+#: builtin/tag.c:373
+#, c-format
+msgid "unsupported sort specification '%s' in variable '%s'"
+msgstr "Nicht unterstützte Angabe für \"--sort\" '%s' in Variable '%s'"
+
+#: builtin/tag.c:428
 msgid "unable to sign the tag"
 msgstr "konnte Tag nicht signieren"
 
-#: builtin/tag.c:326
+#: builtin/tag.c:430
 msgid "unable to write tag file"
 msgstr "konnte Tag-Datei nicht schreiben"
 
-#: builtin/tag.c:351
+#: builtin/tag.c:455
 msgid "bad object type."
 msgstr "ungültiger Objekt-Typ"
 
-#: builtin/tag.c:364
+#: builtin/tag.c:468
 msgid "tag header too big."
 msgstr "Tag-Kopf zu groß."
 
-#: builtin/tag.c:400
+#: builtin/tag.c:504
 msgid "no tag message?"
 msgstr "keine Tag-Beschreibung?"
 
-#: builtin/tag.c:406
+#: builtin/tag.c:510
 #, c-format
 msgid "The tag message has been left in %s\n"
 msgstr "Die Tag-Beschreibung wurde gelassen in %s\n"
 
-#: builtin/tag.c:455
+#: builtin/tag.c:559
 msgid "switch 'points-at' requires an object"
 msgstr "Option 'points-at' erfordert ein Objekt"
 
-#: builtin/tag.c:457
+#: builtin/tag.c:561
 #, c-format
 msgid "malformed object name '%s'"
 msgstr "fehlerhafter Objekt-Name '%s'"
 
-#: builtin/tag.c:480
-#, c-format
-msgid "unsupported sort specification %s"
-msgstr "Nicht unterstützte Angabe für \"--sort\": %s"
-
-#: builtin/tag.c:500
+#: builtin/tag.c:588
 msgid "list tag names"
 msgstr "listet Tagnamen auf"
 
-#: builtin/tag.c:502
+#: builtin/tag.c:590
 msgid "print <n> lines of each tag message"
 msgstr "zeigt <n> Zeilen jeder Tag-Beschreibung"
 
-#: builtin/tag.c:504
+#: builtin/tag.c:592
 msgid "delete tags"
 msgstr "löscht Tags"
 
-#: builtin/tag.c:505
+#: builtin/tag.c:593
 msgid "verify tags"
 msgstr "überprüft Tags"
 
-#: builtin/tag.c:507
+#: builtin/tag.c:595
 msgid "Tag creation options"
 msgstr "Optionen für Erstellung von Tags"
 
-#: builtin/tag.c:509
+#: builtin/tag.c:597
 msgid "annotated tag, needs a message"
 msgstr "annotiertes Tag, benötigt eine Beschreibung"
 
-#: builtin/tag.c:511
+#: builtin/tag.c:599
 msgid "tag message"
 msgstr "Tag-Beschreibung"
 
-#: builtin/tag.c:513
+#: builtin/tag.c:601
 msgid "annotated and GPG-signed tag"
 msgstr "annotiertes und GPG-signiertes Tag"
 
-#: builtin/tag.c:517
+#: builtin/tag.c:605
 msgid "use another key to sign the tag"
 msgstr "verwendet einen anderen Schlüssel um das Tag zu signieren"
 
-#: builtin/tag.c:518
+#: builtin/tag.c:606
 msgid "replace the tag if exists"
 msgstr "ersetzt das Tag, wenn es existiert"
 
-#: builtin/tag.c:519
+#: builtin/tag.c:607
 msgid "show tag list in columns"
 msgstr "zeigt Liste der Tags in Spalten"
 
-#: builtin/tag.c:521
+#: builtin/tag.c:609
 msgid "sort tags"
 msgstr "sortiert Tags"
 
-#: builtin/tag.c:525
+#: builtin/tag.c:613
 msgid "Tag listing options"
 msgstr "Optionen für Auflistung der Tags"
 
-#: builtin/tag.c:528 builtin/tag.c:534
+#: builtin/tag.c:616 builtin/tag.c:622
 msgid "print only tags that contain the commit"
 msgstr "gibt nur Tags aus, die diesen Commit beinhalten"
 
-#: builtin/tag.c:540
+#: builtin/tag.c:628
 msgid "print only tags of the object"
 msgstr "gibt nur Tags von dem Objekt aus"
 
-#: builtin/tag.c:566
+#: builtin/tag.c:654
 msgid "--column and -n are incompatible"
 msgstr "--column und -n sind inkompatibel"
 
-#: builtin/tag.c:578
+#: builtin/tag.c:666
 msgid "--sort and -n are incompatible"
 msgstr "--sort und -n sind inkompatibel"
 
-#: builtin/tag.c:585
+#: builtin/tag.c:673
 msgid "-n option is only allowed with -l."
 msgstr "-n Option ist nur erlaubt mit -l."
 
-#: builtin/tag.c:587
+#: builtin/tag.c:675
 msgid "--contains option is only allowed with -l."
 msgstr "--contains Option ist nur erlaubt mit -l."
 
-#: builtin/tag.c:589
+#: builtin/tag.c:677
 msgid "--points-at option is only allowed with -l."
 msgstr "--points-at Option ist nur erlaubt mit -l."
 
-#: builtin/tag.c:597
+#: builtin/tag.c:685
 msgid "only one -F or -m option is allowed."
 msgstr "nur eine -F oder -m Option ist erlaubt."
 
-#: builtin/tag.c:617
+#: builtin/tag.c:705
 msgid "too many params"
 msgstr "zu viele Parameter"
 
-#: builtin/tag.c:623
+#: builtin/tag.c:711
 #, c-format
 msgid "'%s' is not a valid tag name."
 msgstr "'%s' ist kein gültiger Tagname."
 
-#: builtin/tag.c:628
+#: builtin/tag.c:716
 #, c-format
 msgid "tag '%s' already exists"
 msgstr "Tag '%s' existiert bereits"
 
-#: builtin/tag.c:646
+#: builtin/tag.c:734
 #, c-format
 msgid "%s: cannot lock the ref"
 msgstr "%s: kann Referenz nicht sperren"
 
-#: builtin/tag.c:648
+#: builtin/tag.c:736
 #, c-format
 msgid "%s: cannot update the ref"
 msgstr "%s: kann Referenz nicht aktualisieren"
 
-#: builtin/tag.c:650
+#: builtin/tag.c:738
 #, c-format
 msgid "Updated tag '%s' (was %s)\n"
 msgstr "Tag '%s' aktualisiert (war %s)\n"
@@ -9698,126 +9834,130 @@ msgstr "Tag '%s' aktualisiert (war %s)\n"
 msgid "Unpacking objects"
 msgstr "Entpacke Objekte"
 
-#: builtin/update-index.c:399
+#: builtin/update-index.c:402
 msgid "git update-index [options] [--] [<file>...]"
 msgstr "git update-index [Optionen] [--] [<Datei>...]"
 
-#: builtin/update-index.c:748
+#: builtin/update-index.c:755
 msgid "continue refresh even when index needs update"
 msgstr ""
 "Aktualisierung fortsetzen, auch wenn die Staging-Area aktualisiert werden "
 "muss"
 
-#: builtin/update-index.c:751
+#: builtin/update-index.c:758
 msgid "refresh: ignore submodules"
 msgstr "Aktualisierung: ignoriert Submodule"
 
-#: builtin/update-index.c:754
+#: builtin/update-index.c:761
 msgid "do not ignore new files"
 msgstr "ignoriert keine neuen Dateien"
 
-#: builtin/update-index.c:756
+#: builtin/update-index.c:763
 msgid "let files replace directories and vice-versa"
 msgstr "lässt Dateien Verzeichnisse ersetzen, und umgedreht"
 
-#: builtin/update-index.c:758
+#: builtin/update-index.c:765
 msgid "notice files missing from worktree"
 msgstr "beachtet fehlende Dateien im Arbeitsverzeichnis"
 
-#: builtin/update-index.c:760
+#: builtin/update-index.c:767
 msgid "refresh even if index contains unmerged entries"
 msgstr ""
 "aktualisiert, auch wenn die Staging-Area nicht zusammengeführte Einträge "
 "beinhaltet"
 
-#: builtin/update-index.c:763
+#: builtin/update-index.c:770
 msgid "refresh stat information"
 msgstr "aktualisiert Dateiinformationen"
 
-#: builtin/update-index.c:767
+#: builtin/update-index.c:774
 msgid "like --refresh, but ignore assume-unchanged setting"
 msgstr "wie --refresh, ignoriert aber \"assume-unchanged\" Einstellung"
 
-#: builtin/update-index.c:771
+#: builtin/update-index.c:778
 msgid "<mode>,<object>,<path>"
 msgstr "<Modus>,<Objekt>,<Pfad>"
 
-#: builtin/update-index.c:772
+#: builtin/update-index.c:779
 msgid "add the specified entry to the index"
 msgstr "merkt den angegebenen Eintrag zum Commit vor"
 
-#: builtin/update-index.c:776
+#: builtin/update-index.c:783
 msgid "(+/-)x"
 msgstr "(+/-)x"
 
-#: builtin/update-index.c:777
+#: builtin/update-index.c:784
 msgid "override the executable bit of the listed files"
 msgstr "überschreibt das \"ausführbar\"-Bit der aufgelisteten Dateien"
 
-#: builtin/update-index.c:781
+#: builtin/update-index.c:788
 msgid "mark files as \"not changing\""
 msgstr "betrachte diese Datei immer als unverändert"
 
-#: builtin/update-index.c:784
+#: builtin/update-index.c:791
 msgid "clear assumed-unchanged bit"
 msgstr "löscht \"assumed-unchanged\"-Bit"
 
-#: builtin/update-index.c:787
+#: builtin/update-index.c:794
 msgid "mark files as \"index-only\""
 msgstr "markiert Dateien als \"index-only\""
 
-#: builtin/update-index.c:790
+#: builtin/update-index.c:797
 msgid "clear skip-worktree bit"
 msgstr "löscht \"skip-worktree\"-Bit"
 
-#: builtin/update-index.c:793
+#: builtin/update-index.c:800
 msgid "add to index only; do not add content to object database"
 msgstr ""
 "merkt die Ã„nderungen nur zum Commit vor; Inhalt wird nicht der Objekt-"
 "Datenbank hinzugefügt"
 
-#: builtin/update-index.c:795
+#: builtin/update-index.c:802
 msgid "remove named paths even if present in worktree"
 msgstr ""
 "löscht benannte Pfade, auch wenn sie sich im Arbeitsverzeichnis befinden"
 
-#: builtin/update-index.c:797
+#: builtin/update-index.c:804
 msgid "with --stdin: input lines are terminated by null bytes"
 msgstr "mit --stdin: eingegebene Zeilen sind durch NUL-Bytes abgeschlossen"
 
-#: builtin/update-index.c:799
+#: builtin/update-index.c:806
 msgid "read list of paths to be updated from standard input"
 msgstr "liest Liste der zu aktualisierenden Pfade von der Standard-Eingabe"
 
-#: builtin/update-index.c:803
+#: builtin/update-index.c:810
 msgid "add entries from standard input to the index"
 msgstr "merkt Einträge von der Standard-Eingabe zum Commit vor"
 
-#: builtin/update-index.c:807
+#: builtin/update-index.c:814
 msgid "repopulate stages #2 and #3 for the listed paths"
 msgstr ""
 "wiederholtes Einpflegen der Zustände #2 und #3 für die aufgelisteten Pfade"
 
-#: builtin/update-index.c:811
+#: builtin/update-index.c:818
 msgid "only update entries that differ from HEAD"
 msgstr "aktualisiert nur Einträge, die unterschiedlich zu HEAD sind"
 
-#: builtin/update-index.c:815
+#: builtin/update-index.c:822
 msgid "ignore files missing from worktree"
 msgstr "ignoriert fehlende Dateien im Arbeitsverzeichnis"
 
-#: builtin/update-index.c:818
+#: builtin/update-index.c:825
 msgid "report actions to standard output"
 msgstr "gibt die Aktionen in der Standard-Ausgabe aus"
 
-#: builtin/update-index.c:820
+#: builtin/update-index.c:827
 msgid "(for porcelains) forget saved unresolved conflicts"
 msgstr "(für Fremdprogramme) keine gespeicherten, nicht aufgelöste Konflikte"
 
-#: builtin/update-index.c:824
+#: builtin/update-index.c:831
 msgid "write index in this format"
 msgstr "schreibt Staging-Area-Datei in diesem Format"
 
+#: builtin/update-index.c:833
+msgid "enable or disable split index"
+msgstr "Aktivierung oder Deaktivierung des Splittings der Staging-Area"
+
 #: builtin/update-ref.c:9
 msgid "git update-ref [options] -d <refname> [<oldval>]"
 msgstr "git update-ref [Optionen] -d <Referenzname> [<alterWert>]"
@@ -9830,19 +9970,19 @@ msgstr "git update-ref [Optionen]    <Referenzname> <neuerWert> [<alterWert>]"
 msgid "git update-ref [options] --stdin [-z]"
 msgstr "git update-ref [Optionen] --stdin [-z]"
 
-#: builtin/update-ref.c:256
+#: builtin/update-ref.c:350
 msgid "delete the reference"
 msgstr "löscht diese Referenz"
 
-#: builtin/update-ref.c:258
+#: builtin/update-ref.c:352
 msgid "update <refname> not the one it points to"
 msgstr "aktualisiert <Referenzname>, nicht den Verweis"
 
-#: builtin/update-ref.c:259
+#: builtin/update-ref.c:353
 msgid "stdin has NUL-terminated arguments"
 msgstr "Standard-Eingabe hat durch NUL-Zeichen abgeschlossene Argumente"
 
-#: builtin/update-ref.c:260
+#: builtin/update-ref.c:354
 msgid "read updates from stdin"
 msgstr "liest Aktualisierungen von der Standard-Eingabe"
 
@@ -9854,15 +9994,23 @@ msgstr "git update-server-info [--force]"
 msgid "update the info files from scratch"
 msgstr "aktualisiert die Informationsdateien von Grund auf"
 
-#: builtin/verify-pack.c:56
+#: builtin/verify-commit.c:17
+msgid "git verify-commit [-v|--verbose] <commit>..."
+msgstr "git verify-commit [-v|--verbose] <Commit>..."
+
+#: builtin/verify-commit.c:75
+msgid "print commit contents"
+msgstr "gibt Commit-Inhalte aus"
+
+#: builtin/verify-pack.c:55
 msgid "git verify-pack [-v|--verbose] [-s|--stat-only] <pack>..."
 msgstr "git verify-pack [-v|--verbose] [-s|--stat-only] <Paket>..."
 
-#: builtin/verify-pack.c:66
+#: builtin/verify-pack.c:65
 msgid "verbose"
 msgstr "erweiterte Ausgaben"
 
-#: builtin/verify-pack.c:68
+#: builtin/verify-pack.c:67
 msgid "show statistics only"
 msgstr "zeigt nur Statistiken"
 
@@ -10375,13 +10523,13 @@ msgid "Pull is not possible because you have unmerged files."
 msgstr ""
 "\"pull\" ist nicht möglich, weil Sie nicht zusammengeführte Dateien haben."
 
-#: git-pull.sh:247
+#: git-pull.sh:245
 msgid "updating an unborn branch with changes added to the index"
 msgstr ""
 "Aktualisiere einen ungeborenen Branch mit Ã„nderungen, die zum Commit "
 "vorgemerkt sind"
 
-#: git-pull.sh:271
+#: git-pull.sh:269
 #, sh-format
 msgid ""
 "Warning: fetch updated the current branch head.\n"
@@ -10391,11 +10539,11 @@ msgstr ""
 "Warnung: \"fetch\" aktualisierte die Spitze des aktuellen Branches.\n"
 "Warnung: Spule Ihr Arbeitsverzeichnis von Commit $orig_head vor."
 
-#: git-pull.sh:296
+#: git-pull.sh:294
 msgid "Cannot merge multiple branches into empty head"
 msgstr "Kann nicht mehrere Branches in einen ungeborenen Branch zusammenführen"
 
-#: git-pull.sh:300
+#: git-pull.sh:298
 msgid "Cannot rebase onto multiple branches"
 msgstr "kann Rebase nicht auf mehrere Branches ausführen"
 
@@ -10413,16 +10561,16 @@ msgstr ""
 "Um den ursprünglichen Branch wiederherzustellen und den Rebase abzubrechen,\n"
 "führen Sie \"git rebase --abort\" aus."
 
-#: git-rebase.sh:164
+#: git-rebase.sh:165
 msgid "Applied autostash."
 msgstr "\"autostash\" angewendet."
 
-#: git-rebase.sh:167
+#: git-rebase.sh:168
 #, sh-format
 msgid "Cannot store $stash_sha1"
 msgstr "Kann $stash_sha1 nicht speichern."
 
-#: git-rebase.sh:168
+#: git-rebase.sh:169
 msgid ""
 "Applying autostash resulted in conflicts.\n"
 "Your changes are safe in the stash.\n"
@@ -10432,33 +10580,33 @@ msgstr ""
 "Ihre Ã„nderungen sind im Stash sicher.\n"
 "Sie können jederzeit \"git stash pop\" oder \"git stash drop\" ausführen.\n"
 
-#: git-rebase.sh:207
+#: git-rebase.sh:208
 msgid "The pre-rebase hook refused to rebase."
 msgstr "Der \"pre-rebase hook\" hat den Rebase zurückgewiesen."
 
-#: git-rebase.sh:212
+#: git-rebase.sh:213
 msgid "It looks like git-am is in progress. Cannot rebase."
 msgstr "\"git-am\" scheint im Gange zu sein. Kann Rebase nicht durchführen."
 
-#: git-rebase.sh:350
+#: git-rebase.sh:351
 msgid "The --exec option must be used with the --interactive option"
 msgstr "Die Option --exec muss mit --interactive verwendet werden."
 
-#: git-rebase.sh:355
+#: git-rebase.sh:356
 msgid "No rebase in progress?"
 msgstr "Kein Rebase im Gange?"
 
-#: git-rebase.sh:366
+#: git-rebase.sh:367
 msgid "The --edit-todo action can only be used during interactive rebase."
 msgstr ""
 "Die --edit-todo Aktion kann nur während eines interaktiven Rebase verwendet "
 "werden."
 
-#: git-rebase.sh:373
+#: git-rebase.sh:374
 msgid "Cannot read HEAD"
 msgstr "Kann HEAD nicht lesen"
 
-#: git-rebase.sh:376
+#: git-rebase.sh:377
 msgid ""
 "You must edit all merge conflicts and then\n"
 "mark them as resolved using git add"
@@ -10466,12 +10614,12 @@ msgstr ""
 "Sie müssen alle Merge-Konflikte editieren und diese dann\n"
 "mittels \"git add\" als aufgelöst markieren"
 
-#: git-rebase.sh:394
+#: git-rebase.sh:395
 #, sh-format
 msgid "Could not move back to $head_name"
 msgstr "Konnte nicht zu $head_name zurückgehen"
 
-#: git-rebase.sh:413
+#: git-rebase.sh:414
 #, sh-format
 msgid ""
 "It seems that there is already a $state_dir_base directory, and\n"
@@ -10492,67 +10640,67 @@ msgstr ""
 "und führen Sie dieses Kommando nochmal aus. Es wird angehalten, falls noch\n"
 "etwas Schützenswertes vorhanden ist."
 
-#: git-rebase.sh:464
+#: git-rebase.sh:465
 #, sh-format
 msgid "invalid upstream $upstream_name"
 msgstr "ungültiger Upstream-Branch $upstream_name"
 
-#: git-rebase.sh:488
+#: git-rebase.sh:489
 #, sh-format
 msgid "$onto_name: there are more than one merge bases"
 msgstr "$onto_name: es gibt mehr als eine Merge-Basis"
 
-#: git-rebase.sh:491 git-rebase.sh:495
+#: git-rebase.sh:492 git-rebase.sh:496
 #, sh-format
 msgid "$onto_name: there is no merge base"
 msgstr "$onto_name: es gibt keine Merge-Basis"
 
-#: git-rebase.sh:500
+#: git-rebase.sh:501
 #, sh-format
 msgid "Does not point to a valid commit: $onto_name"
 msgstr "$onto_name zeigt auf keinen gültigen Commit"
 
-#: git-rebase.sh:523
+#: git-rebase.sh:524
 #, sh-format
 msgid "fatal: no such branch: $branch_name"
 msgstr "fatal: Branch $branch_name nicht gefunden"
 
-#: git-rebase.sh:556
+#: git-rebase.sh:557
 msgid "Cannot autostash"
 msgstr "Kann \"autostash\" nicht ausführen."
 
-#: git-rebase.sh:561
+#: git-rebase.sh:562
 #, sh-format
 msgid "Created autostash: $stash_abbrev"
 msgstr "\"autostash\" erzeugt: $stash_abbrev"
 
-#: git-rebase.sh:565
+#: git-rebase.sh:566
 msgid "Please commit or stash them."
 msgstr "Bitte committen Sie die Ã„nderungen oder benutzen Sie \"stash\"."
 
-#: git-rebase.sh:585
+#: git-rebase.sh:586
 #, sh-format
 msgid "Current branch $branch_name is up to date."
 msgstr "Aktueller Branch $branch_name ist auf dem neuesten Stand."
 
-#: git-rebase.sh:589
+#: git-rebase.sh:590
 #, sh-format
 msgid "Current branch $branch_name is up to date, rebase forced."
 msgstr ""
 "Aktueller Branch $branch_name ist auf dem neuesten Stand, Rebase erzwungen."
 
-#: git-rebase.sh:600
+#: git-rebase.sh:601
 #, sh-format
 msgid "Changes from $mb to $onto:"
 msgstr "Änderungen von $mb zu $onto:"
 
-#: git-rebase.sh:609
+#: git-rebase.sh:610
 msgid "First, rewinding head to replay your work on top of it..."
 msgstr ""
 "Zunächst wird der Branch zurückgespult, um Ihre Ã„nderungen\n"
 "darauf neu anzuwenden..."
 
-#: git-rebase.sh:619
+#: git-rebase.sh:620
 #, sh-format
 msgid "Fast-forwarded $branch_name to $onto_name."
 msgstr "$branch_name zu $onto_name vorgespult."
@@ -10569,23 +10717,23 @@ msgstr "Sie haben bisher noch keinen initialen Commit"
 msgid "Cannot save the current index state"
 msgstr "Kann den aktuellen Zustand der Staging-Area nicht speichern"
 
-#: git-stash.sh:123 git-stash.sh:136
+#: git-stash.sh:124 git-stash.sh:137
 msgid "Cannot save the current worktree state"
 msgstr "Kann den aktuellen Zustand des Arbeitsverzeichnisses nicht speichern"
 
-#: git-stash.sh:140
+#: git-stash.sh:141
 msgid "No changes selected"
 msgstr "Keine Ã„nderungen ausgewählt"
 
-#: git-stash.sh:143
+#: git-stash.sh:144
 msgid "Cannot remove temporary index (can't happen)"
 msgstr "Kann temporäre Staging-Area nicht löschen (kann nicht passieren)"
 
-#: git-stash.sh:156
+#: git-stash.sh:157
 msgid "Cannot record working tree state"
 msgstr "Kann Zustand des Arbeitsverzeichnisses nicht aufzeichnen"
 
-#: git-stash.sh:190
+#: git-stash.sh:191
 #, sh-format
 msgid "Cannot update $ref_stash with $w_commit"
 msgstr "Kann $ref_stash nicht mit $w_commit aktualisieren."
@@ -10600,7 +10748,7 @@ msgstr "Kann $ref_stash nicht mit $w_commit aktualisieren."
 #. $ 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'
-#: git-stash.sh:237
+#: git-stash.sh:238
 #, sh-format
 msgid ""
 "error: unknown option for 'stash save': $option\n"
@@ -10610,85 +10758,85 @@ msgstr ""
 "        Um eine Beschreibung anzugeben, benutzen Sie \"git stash save -- "
 "'$option'\""
 
-#: git-stash.sh:258
+#: git-stash.sh:259
 msgid "No local changes to save"
 msgstr "Keine lokalen Ã„nderungen zum Speichern"
 
-#: git-stash.sh:262
+#: git-stash.sh:263
 msgid "Cannot initialize stash"
 msgstr "Kann \"stash\" nicht initialisieren"
 
-#: git-stash.sh:266
+#: git-stash.sh:267
 msgid "Cannot save the current status"
 msgstr "Kann den aktuellen Status nicht speichern"
 
-#: git-stash.sh:284
+#: git-stash.sh:285
 msgid "Cannot remove worktree changes"
 msgstr "Kann Ã„nderungen im Arbeitsverzeichnis nicht löschen"
 
-#: git-stash.sh:383
+#: git-stash.sh:384
 msgid "No stash found."
 msgstr "Kein \"stash\" gefunden."
 
-#: git-stash.sh:390
+#: git-stash.sh:391
 #, sh-format
 msgid "Too many revisions specified: $REV"
 msgstr "Zu viele Commits angegeben: $REV"
 
-#: git-stash.sh:396
+#: git-stash.sh:397
 #, sh-format
 msgid "$reference is not valid reference"
 msgstr "$reference ist keine gültige Referenz"
 
-#: git-stash.sh:424
+#: git-stash.sh:425
 #, sh-format
 msgid "'$args' is not a stash-like commit"
 msgstr "'$args' ist kein \"stash\"-artiger Commit"
 
-#: git-stash.sh:435
+#: git-stash.sh:436
 #, sh-format
 msgid "'$args' is not a stash reference"
 msgstr "'$args' ist keine \"stash\"-Referenz"
 
-#: git-stash.sh:443
+#: git-stash.sh:444
 msgid "unable to refresh index"
 msgstr "unfähig die Staging-Area zu aktualisieren"
 
-#: git-stash.sh:447
+#: git-stash.sh:448
 msgid "Cannot apply a stash in the middle of a merge"
 msgstr "Kann \"stash\" nicht anwenden, solang ein Merge im Gange ist"
 
-#: git-stash.sh:455
+#: git-stash.sh:456
 msgid "Conflicts in index. Try without --index."
 msgstr "Konflikte in der Staging-Area. Versuchen Sie es ohne --index."
 
-#: git-stash.sh:457
+#: git-stash.sh:458
 msgid "Could not save index tree"
 msgstr "Konnte Staging-Area-Verzeichnis nicht speichern"
 
-#: git-stash.sh:491
+#: git-stash.sh:492
 msgid "Cannot unstage modified files"
 msgstr "Kann geänderte Dateien nicht aus der Staging-Area entfernen"
 
-#: git-stash.sh:506
+#: git-stash.sh:507
 msgid "Index was not unstashed."
 msgstr "Staging-Area wurde nicht aus dem Stash zurückgeladen."
 
-#: git-stash.sh:529
+#: git-stash.sh:530
 #, sh-format
 msgid "Dropped ${REV} ($s)"
 msgstr "Gelöscht ${REV} ($s)"
 
-#: git-stash.sh:530
+#: git-stash.sh:531
 #, sh-format
 msgid "${REV}: Could not drop stash entry"
 msgstr "${REV}: Konnte \"stash\"-Eintrag nicht löschen"
 
-#: git-stash.sh:537
+#: git-stash.sh:538
 msgid "No branch name specified"
 msgstr "Kein Branchname spezifiziert"
 
-#: git-stash.sh:609
+#: git-stash.sh:610
 msgid "(To restore them type \"git stash apply\")"
 msgstr "(Zur Wiederherstellung geben Sie \"git stash apply\" ein)"
 
@@ -10707,28 +10855,28 @@ msgstr "Keine Submodul-Zuordnung in .gitmodules für Pfad '$sm_path' gefunden"
 msgid "Clone of '$url' into submodule path '$sm_path' failed"
 msgstr "Klonen von '$url' in Submodul-Pfad '$sm_path' fehlgeschlagen"
 
-#: git-submodule.sh:299
+#: git-submodule.sh:296
 #, sh-format
 msgid "Gitdir '$a' is part of the submodule path '$b' or vice versa"
 msgstr "Git-Verzeichnis '$a' ist Teil des Submodul-Pfades '$b', oder umgekehrt"
 
-#: git-submodule.sh:409
+#: git-submodule.sh:406
 msgid "Relative path can only be used from the toplevel of the working tree"
 msgstr ""
 "Relative Pfade können nur von der obersten Ebene des Arbeitsverzeichnisses "
 "benutzt werden."
 
-#: git-submodule.sh:419
+#: git-submodule.sh:416
 #, 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:436
+#: git-submodule.sh:433
 #, sh-format
 msgid "'$sm_path' already exists in the index"
 msgstr "'$sm_path' ist bereits zum Commit vorgemerkt"
 
-#: git-submodule.sh:440
+#: git-submodule.sh:437
 #, sh-format
 msgid ""
 "The following path is ignored by one of your .gitignore files:\n"
@@ -10739,24 +10887,24 @@ msgstr ""
 "$sm_path\n"
 "Benutzen Sie -f wenn Sie diesen wirklich hinzufügen möchten."
 
-#: git-submodule.sh:458
+#: git-submodule.sh:455
 #, sh-format
 msgid "Adding existing repo at '$sm_path' to the index"
 msgstr "Füge existierendes Repository in '$sm_path' der Staging-Area hinzu."
 
-#: git-submodule.sh:460
+#: git-submodule.sh:457
 #, 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-Repository"
 
-#: git-submodule.sh:468
+#: git-submodule.sh:465
 #, sh-format
 msgid "A git directory for '$sm_name' is found locally with remote(s):"
 msgstr ""
 "Ein Git-Verzeichnis für '$sm_name' wurde lokal gefunden mit den Remote-"
 "Repositories:"
 
-#: git-submodule.sh:470
+#: git-submodule.sh:467
 #, sh-format
 msgid ""
 "If you want to reuse this local git directory instead of cloning again from"
@@ -10764,7 +10912,7 @@ msgstr ""
 "Wenn Sie dieses lokale Git-Verzeichnis wiederverwenden möchtest, anstatt "
 "erneut zu klonen"
 
-#: git-submodule.sh:472
+#: git-submodule.sh:469
 #, sh-format
 msgid ""
 "use the '--force' option. If the local git directory is not the correct repo"
@@ -10772,7 +10920,7 @@ msgstr ""
 "benutzen Sie die Option '--force'. Wenn das lokale Git-Verzeichnis nicht das "
 "korrekte Repository ist"
 
-#: git-submodule.sh:473
+#: git-submodule.sh:470
 #, sh-format
 msgid ""
 "or you are unsure what this means choose another name with the '--name' "
@@ -10781,77 +10929,77 @@ msgstr ""
 "oder Sie sich unsicher sind, was das bedeutet, wählen Sie einen anderen "
 "Namenmit der Option '--name'."
 
-#: git-submodule.sh:475
+#: git-submodule.sh:472
 #, sh-format
 msgid "Reactivating local git directory for submodule '$sm_name'."
 msgstr "Reaktiviere lokales Git-Verzeichnis für Submodul '$sm_name'."
 
-#: git-submodule.sh:487
+#: git-submodule.sh:484
 #, sh-format
 msgid "Unable to checkout submodule '$sm_path'"
 msgstr "Kann Submodul '$sm_path' nicht auschecken"
 
-#: git-submodule.sh:492
+#: git-submodule.sh:489
 #, sh-format
 msgid "Failed to add submodule '$sm_path'"
 msgstr "Hinzufügen von Submodul '$sm_path' fehlgeschlagen"
 
-#: git-submodule.sh:501
+#: git-submodule.sh:498
 #, sh-format
 msgid "Failed to register submodule '$sm_path'"
 msgstr "Fehler beim Eintragen von Submodul '$sm_path' in die Konfiguration."
 
-#: git-submodule.sh:545
+#: git-submodule.sh:542
 #, sh-format
 msgid "Entering '$prefix$displaypath'"
 msgstr "Betrete '$prefix$displaypath'"
 
-#: git-submodule.sh:565
+#: git-submodule.sh:562
 #, sh-format
 msgid "Stopping at '$prefix$displaypath'; script returned non-zero status."
 msgstr "Stoppe bei '$prefix$displaypath'; Skript gab nicht-Null Status zurück."
 
-#: git-submodule.sh:611
+#: git-submodule.sh:608
 #, sh-format
 msgid "No url found for submodule path '$displaypath' in .gitmodules"
 msgstr "Keine URL für Submodul-Pfad '$displaypath' in .gitmodules gefunden"
 
-#: git-submodule.sh:620
+#: git-submodule.sh:617
 #, sh-format
 msgid "Failed to register url for submodule path '$displaypath'"
 msgstr ""
 "Fehler beim Eintragen der URL für Submodul-Pfad '$displaypath' in die "
 "Konfiguration."
 
-#: git-submodule.sh:622
+#: git-submodule.sh:619
 #, sh-format
 msgid "Submodule '$name' ($url) registered for path '$displaypath'"
 msgstr ""
 "Submodul '$name' ($url) für Pfad '$displaypath' in die Konfiguration "
 "eingetragen."
 
-#: git-submodule.sh:639
+#: git-submodule.sh:636
 #, sh-format
 msgid "Failed to register update mode for submodule path '$displaypath'"
 msgstr ""
 "Fehler bei Ã„nderung des Aktualisierungsmodus für Submodul-Pfad "
 "'$displaypath' in der Konfiguration."
 
-#: git-submodule.sh:677
+#: git-submodule.sh:674
 #, sh-format
 msgid "Use '.' if you really want to deinitialize all submodules"
 msgstr ""
 "Verwenden Sie '.' wenn Sie wirklich alle Submodule\n"
 "deinitialisieren möchten."
 
-#: git-submodule.sh:694
+#: git-submodule.sh:691
 #, sh-format
 msgid "Submodule work tree '$displaypath' contains a .git directory"
 msgstr ""
 "Arbeitsverzeichnis des Submoduls in '$displaypath' enthält ein .git-"
 "Verzeichnis"
 
-#: git-submodule.sh:695
+#: git-submodule.sh:692
 #, sh-format
 msgid ""
 "(use 'rm -rf' if you really want to remove it including all of its history)"
@@ -10859,7 +11007,7 @@ msgstr ""
 "(benutzen Sie 'rm -rf' wenn Sie dieses Submodul wirklich mitsamt\n"
 "seiner Historie löschen möchten)"
 
-#: git-submodule.sh:701
+#: git-submodule.sh:698
 #, sh-format
 msgid ""
 "Submodule work tree '$displaypath' contains local modifications; use '-f' to "
@@ -10868,31 +11016,31 @@ msgstr ""
 "Arbeitsverzeichnis von Submodul in '$displaypath' enthält lokale Ã„nderungen; "
 "verwenden Sie '-f' um diese zu verwerfen"
 
-#: git-submodule.sh:704
+#: git-submodule.sh:701
 #, sh-format
 msgid "Cleared directory '$displaypath'"
 msgstr "Verzeichnis '$displaypath' bereinigt."
 
-#: git-submodule.sh:705
+#: git-submodule.sh:702
 #, sh-format
 msgid "Could not remove submodule work tree '$displaypath'"
 msgstr ""
 "Konnte Arbeitsverzeichnis des Submoduls in '$displaypath' nicht löschen."
 
-#: git-submodule.sh:708
+#: git-submodule.sh:705
 #, sh-format
 msgid "Could not create empty submodule directory '$displaypath'"
 msgstr ""
 "Konnte kein leeres Verzeichnis für Submodul in '$displaypath' erstellen."
 
-#: git-submodule.sh:717
+#: git-submodule.sh:714
 #, sh-format
 msgid "Submodule '$name' ($url) unregistered for path '$displaypath'"
 msgstr ""
 "Submodul '$name' ($url) für Pfad '$displaypath' wurde aus der Konfiguration "
 "entfernt."
 
-#: git-submodule.sh:833
+#: git-submodule.sh:830
 #, sh-format
 msgid ""
 "Submodule path '$displaypath' not initialized\n"
@@ -10901,52 +11049,52 @@ msgstr ""
 "Submodul-Pfad '$displaypath' ist nicht initialisiert.\n"
 "Vielleicht möchten Sie 'update --init' benutzen?"
 
-#: git-submodule.sh:846
+#: git-submodule.sh:843
 #, sh-format
 msgid "Unable to find current revision in submodule path '$displaypath'"
 msgstr "Konnte aktuellen Commit in Submodul-Pfad '$displaypath' nicht finden."
 
-#: git-submodule.sh:855
+#: git-submodule.sh:852
 #, sh-format
 msgid "Unable to fetch in submodule path '$sm_path'"
 msgstr "Konnte \"fetch\" in Submodul-Pfad '$sm_path' nicht ausführen"
 
-#: git-submodule.sh:879
+#: git-submodule.sh:876
 #, sh-format
 msgid "Unable to fetch in submodule path '$displaypath'"
 msgstr "Konnte \"fetch\" in Submodul-Pfad '$displaypath' nicht ausführen"
 
-#: git-submodule.sh:893
+#: git-submodule.sh:890
 #, sh-format
 msgid "Unable to checkout '$sha1' in submodule path '$displaypath'"
 msgstr "Konnte '$sha1' in Submodul-Pfad '$displaypath' nicht auschecken."
 
-#: git-submodule.sh:894
+#: git-submodule.sh:891
 #, sh-format
 msgid "Submodule path '$displaypath': checked out '$sha1'"
 msgstr "Submodul-Pfad: '$displaypath': '$sha1' ausgecheckt"
 
-#: git-submodule.sh:898
+#: git-submodule.sh:895
 #, sh-format
 msgid "Unable to rebase '$sha1' in submodule path '$displaypath'"
 msgstr "Rebase auf '$sha1' in Submodul-Pfad '$displaypath' nicht möglich"
 
-#: git-submodule.sh:899
+#: git-submodule.sh:896
 #, sh-format
 msgid "Submodule path '$displaypath': rebased into '$sha1'"
 msgstr "Submodul-Pfad '$displaypath': Rebase auf '$sha1'"
 
-#: git-submodule.sh:904
+#: git-submodule.sh:901
 #, sh-format
 msgid "Unable to merge '$sha1' in submodule path '$displaypath'"
 msgstr "Merge von '$sha1' in Submodul-Pfad '$displaypath' fehlgeschlagen"
 
-#: git-submodule.sh:905
+#: git-submodule.sh:902
 #, sh-format
 msgid "Submodule path '$displaypath': merged in '$sha1'"
 msgstr "Submodul-Pfad '$displaypath': zusammengeführt in '$sha1'"
 
-#: git-submodule.sh:910
+#: git-submodule.sh:907
 #, sh-format
 msgid ""
 "Execution of '$command $sha1' failed in submodule  path '$prefix$sm_path'"
@@ -10954,56 +11102,62 @@ msgstr ""
 "Ausführung von '$command $sha1' in Submodul-Pfad '$prefix$sm_path' "
 "fehlgeschlagen"
 
-#: git-submodule.sh:911
+#: git-submodule.sh:908
 #, sh-format
 msgid "Submodule path '$prefix$sm_path': '$command $sha1'"
 msgstr "Submodul-Pfad '$prefix$sm_path': '$command $sha1'"
 
-#: git-submodule.sh:941
+#: git-submodule.sh:938
 #, sh-format
 msgid "Failed to recurse into submodule path '$displaypath'"
 msgstr "Fehler bei Rekursion in Submodul-Pfad '$displaypath'"
 
-#: git-submodule.sh:1049
+#: git-submodule.sh:1046
 msgid "The --cached option cannot be used with the --files option"
 msgstr ""
 "Die Optionen --cached und --files können nicht gemeinsam verwendet werden."
 
-#: git-submodule.sh:1097
+#: git-submodule.sh:1098
 #, sh-format
 msgid "unexpected mode $mod_dst"
 msgstr "unerwarteter Modus $mod_dst"
 
-#: git-submodule.sh:1117
+#: git-submodule.sh:1118
 #, sh-format
 msgid "  Warn: $display_name doesn't contain commit $sha1_src"
 msgstr "  Warnung: $display_name beinhaltet nicht Commit $sha1_src"
 
-#: git-submodule.sh:1120
+#: git-submodule.sh:1121
 #, sh-format
 msgid "  Warn: $display_name doesn't contain commit $sha1_dst"
 msgstr "  Warnung: $display_name beinhaltet nicht Commit $sha1_dst"
 
-#: git-submodule.sh:1123
+#: git-submodule.sh:1124
 #, sh-format
 msgid "  Warn: $display_name doesn't contain commits $sha1_src and $sha1_dst"
 msgstr ""
 "  Warnung: $display_name beinhaltet nicht die Commits $sha1_src und $sha1_dst"
 
-#: git-submodule.sh:1148
+#: git-submodule.sh:1149
 msgid "blob"
 msgstr "Blob"
 
-#: git-submodule.sh:1262
+#: git-submodule.sh:1267
 #, sh-format
 msgid "Failed to recurse into submodule path '$sm_path'"
 msgstr "Fehler bei Rekursion in Submodul-Pfad '$sm_path'"
 
-#: git-submodule.sh:1326
+#: git-submodule.sh:1331
 #, sh-format
 msgid "Synchronizing submodule url for '$displaypath'"
 msgstr "Synchronisiere Submodul-URL für '$displaypath'"
 
+#~ msgid "commit has empty message"
+#~ msgstr "Commit hat eine leere Beschreibung"
+
+#~ msgid "Failed to chdir: %s"
+#~ msgstr "Fehler beim Verzeichniswechsel: %s"
+
 #~ msgid "key id"
 #~ msgstr "Schlüssel-ID"
 
index 3a1da6fd329efe1723bdb906a907ce4160c4633a..44b9f643725c68325a9caf92dff819e22e38e3ad 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -24,6 +24,11 @@ static size_t commit_formats_len;
 static size_t commit_formats_alloc;
 static struct cmt_fmt_map *find_commit_format(const char *sought);
 
+int commit_format_is_empty(enum cmit_fmt fmt)
+{
+       return fmt == CMIT_FMT_USERFORMAT && !*user_format;
+}
+
 static void save_user_format(struct rev_info *rev, const char *cp, int is_tformat)
 {
        free(user_format);
@@ -65,7 +70,9 @@ static int git_pretty_formats_config(const char *var, const char *value, void *c
 
        commit_format->name = xstrdup(name);
        commit_format->format = CMIT_FMT_USERFORMAT;
-       git_config_string(&fmt, var, value);
+       if (git_config_string(&fmt, var, value))
+               return -1;
+
        if (starts_with(fmt, "format:") || starts_with(fmt, "tformat:")) {
                commit_format->is_tformat = fmt[0] == 't';
                fmt = strchr(fmt, ':') + 1;
@@ -146,7 +153,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)
        struct cmt_fmt_map *commit_format;
 
        rev->use_terminator = 0;
-       if (!arg || !*arg) {
+       if (!arg) {
                rev->commit_format = CMIT_FMT_DEFAULT;
                return;
        }
@@ -155,7 +162,7 @@ void get_commit_format(const char *arg, struct rev_info *rev)
                return;
        }
 
-       if (strchr(arg, '%')) {
+       if (!*arg || strchr(arg, '%')) {
                save_user_format(rev, arg, 1);
                return;
        }
index d7bb17cb663c2f47ad59d34ecea17c6cc977e815..e5b4938efcf329eb4f25b6f90231c35abeacbbd3 100644 (file)
--- a/prompt.c
+++ b/prompt.c
@@ -6,7 +6,7 @@
 
 static char *do_askpass(const char *cmd, const char *prompt)
 {
-       struct child_process pass;
+       struct child_process pass = CHILD_PROCESS_INIT;
        const char *args[3];
        static struct strbuf buffer = STRBUF_INIT;
        int err = 0;
@@ -15,7 +15,6 @@ static char *do_askpass(const char *cmd, const char *prompt)
        args[1] = prompt;
        args[2] = NULL;
 
-       memset(&pass, 0, sizeof(pass));
        pass.argv = args;
        pass.out = -1;
 
index 5d3c8bd4aaffda9915a3fd62d9d9800f4ac8baff..b5917e0c0743af3c831f9571e19e269e8a1f6014 100644 (file)
@@ -1064,6 +1064,14 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
                return ce;
        }
 
+       if (has_symlink_leading_path(ce->name, ce_namelen(ce))) {
+               if (ignore_missing)
+                       return ce;
+               if (err)
+                       *err = ENOENT;
+               return NULL;
+       }
+
        if (lstat(ce->name, &st) < 0) {
                if (ignore_missing && errno == ENOENT)
                        return ce;
@@ -1238,24 +1246,16 @@ static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
 
 #define INDEX_FORMAT_DEFAULT 3
 
-static int index_format_config(const char *var, const char *value, void *cb)
-{
-       unsigned int *version = cb;
-       if (!strcmp(var, "index.version")) {
-               *version = git_config_int(var, value);
-               return 0;
-       }
-       return 1;
-}
-
 static unsigned int get_index_format_default(void)
 {
        char *envversion = getenv("GIT_INDEX_VERSION");
        char *endp;
+       int value;
        unsigned int version = INDEX_FORMAT_DEFAULT;
 
        if (!envversion) {
-               git_config(index_format_config, &version);
+               if (!git_config_get_int("index.version", &value))
+                       version = value;
                if (version < INDEX_FORMAT_LB || INDEX_FORMAT_UB < version) {
                        warning(_("index.version set, but the value is invalid.\n"
                                  "Using version %i"), INDEX_FORMAT_DEFAULT);
diff --git a/refs.c b/refs.c
index 27927f2319130cc0575817542dfd47c37cc5149b..2ce5d690907d33bda557f66150ef1317f39b4f93 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -24,6 +24,11 @@ static unsigned char refname_disposition[256] = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
 };
 
+/*
+ * Used as a flag to ref_transaction_delete when a loose ref is being
+ * pruned.
+ */
+#define REF_ISPRUNING  0x0100
 /*
  * Try to read one refname component from the front of refname.
  * Return the length of the component found, or -1 if the component is
@@ -2068,7 +2073,10 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
        return logs_found;
 }
 
-/* This function should make sure errno is meaningful on error */
+/*
+ * Locks a "refs/" ref returning the lock on success and NULL on failure.
+ * On failure errno is set to something meaningful.
+ */
 static struct ref_lock *lock_ref_sha1_basic(const char *refname,
                                            const unsigned char *old_sha1,
                                            int flags, int *type_p)
@@ -2169,15 +2177,6 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
        return NULL;
 }
 
-struct ref_lock *lock_ref_sha1(const char *refname, const unsigned char *old_sha1)
-{
-       char refpath[PATH_MAX];
-       if (check_refname_format(refname, 0))
-               return NULL;
-       strcpy(refpath, mkpath("refs/%s", refname));
-       return lock_ref_sha1_basic(refpath, old_sha1, 0, NULL);
-}
-
 struct ref_lock *lock_any_ref_for_update(const char *refname,
                                         const unsigned char *old_sha1,
                                         int flags, int *type_p)
@@ -2387,13 +2386,25 @@ static void try_remove_empty_parents(char *name)
 /* make sure nobody touched the ref, and unlink */
 static void prune_ref(struct ref_to_prune *r)
 {
-       struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1);
+       struct ref_transaction *transaction;
+       struct strbuf err = STRBUF_INIT;
 
-       if (lock) {
-               unlink_or_warn(git_path("%s", r->name));
-               unlock_ref(lock);
-               try_remove_empty_parents(r->name);
+       if (check_refname_format(r->name, 0))
+               return;
+
+       transaction = ref_transaction_begin(&err);
+       if (!transaction ||
+           ref_transaction_delete(transaction, r->name, r->sha1,
+                                  REF_ISPRUNING, 1, &err) ||
+           ref_transaction_commit(transaction, NULL, &err)) {
+               ref_transaction_free(transaction);
+               error("%s", err.buf);
+               strbuf_release(&err);
+               return;
        }
+       ref_transaction_free(transaction);
+       strbuf_release(&err);
+       try_remove_empty_parents(r->name);
 }
 
 static void prune_refs(struct ref_to_prune *r)
@@ -2536,11 +2547,6 @@ int repack_without_refs(const char **refnames, int n, struct strbuf *err)
        return ret;
 }
 
-static int repack_without_ref(const char *refname)
-{
-       return repack_without_refs(&refname, 1, NULL);
-}
-
 static int delete_ref_loose(struct ref_lock *lock, int flag)
 {
        if (!(flag & REF_ISPACKED) || flag & REF_ISSYMREF) {
@@ -2558,24 +2564,22 @@ static int delete_ref_loose(struct ref_lock *lock, int flag)
 
 int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
 {
-       struct ref_lock *lock;
-       int ret = 0, flag = 0;
-
-       lock = lock_ref_sha1_basic(refname, sha1, delopt, &flag);
-       if (!lock)
+       struct ref_transaction *transaction;
+       struct strbuf err = STRBUF_INIT;
+
+       transaction = ref_transaction_begin(&err);
+       if (!transaction ||
+           ref_transaction_delete(transaction, refname, sha1, delopt,
+                                  sha1 && !is_null_sha1(sha1), &err) ||
+           ref_transaction_commit(transaction, NULL, &err)) {
+               error("%s", err.buf);
+               ref_transaction_free(transaction);
+               strbuf_release(&err);
                return 1;
-       ret |= delete_ref_loose(lock, flag);
-
-       /* removing the loose one could have resurrected an earlier
-        * packed one.  Also, if it was not loose we need to repack
-        * without it.
-        */
-       ret |= repack_without_ref(lock->ref_name);
-
-       unlink_or_warn(git_path("logs/%s", lock->ref_name));
-       clear_loose_ref_cache(&ref_cache);
-       unlock_ref(lock);
-       return ret;
+       }
+       ref_transaction_free(transaction);
+       strbuf_release(&err);
+       return 0;
 }
 
 /*
@@ -3332,43 +3336,6 @@ int for_each_reflog(each_ref_fn fn, void *cb_data)
        return retval;
 }
 
-static struct ref_lock *update_ref_lock(const char *refname,
-                                       const unsigned char *oldval,
-                                       int flags, int *type_p,
-                                       enum action_on_err onerr)
-{
-       struct ref_lock *lock;
-       lock = lock_any_ref_for_update(refname, oldval, flags, type_p);
-       if (!lock) {
-               const char *str = "Cannot lock the ref '%s'.";
-               switch (onerr) {
-               case UPDATE_REFS_MSG_ON_ERR: error(str, refname); break;
-               case UPDATE_REFS_DIE_ON_ERR: die(str, refname); break;
-               case UPDATE_REFS_QUIET_ON_ERR: break;
-               }
-       }
-       return lock;
-}
-
-static int update_ref_write(const char *action, const char *refname,
-                           const unsigned char *sha1, struct ref_lock *lock,
-                           struct strbuf *err, enum action_on_err onerr)
-{
-       if (write_ref_sha1(lock, sha1, action) < 0) {
-               const char *str = "Cannot update the ref '%s'.";
-               if (err)
-                       strbuf_addf(err, str, refname);
-
-               switch (onerr) {
-               case UPDATE_REFS_MSG_ON_ERR: error(str, refname); break;
-               case UPDATE_REFS_DIE_ON_ERR: die(str, refname); break;
-               case UPDATE_REFS_QUIET_ON_ERR: break;
-               }
-               return 1;
-       }
-       return 0;
-}
-
 /**
  * Information needed for a single ref update.  Set new_sha1 to the
  * new value or to zero to delete the ref.  To check the old value
@@ -3385,6 +3352,21 @@ struct ref_update {
        const char refname[FLEX_ARRAY];
 };
 
+/*
+ * Transaction states.
+ * OPEN:   The transaction is in a valid state and can accept new updates.
+ *         An OPEN transaction can be committed.
+ * CLOSED: A closed transaction is no longer active and no other operations
+ *         than free can be used on it in this state.
+ *         A transaction can either become closed by successfully committing
+ *         an active transaction or if there is a failure while building
+ *         the transaction thus rendering it failed/inactive.
+ */
+enum ref_transaction_state {
+       REF_TRANSACTION_OPEN   = 0,
+       REF_TRANSACTION_CLOSED = 1
+};
+
 /*
  * Data structure for holding a reference transaction, which can
  * consist of checks and updates to multiple references, carried out
@@ -3394,9 +3376,10 @@ struct ref_transaction {
        struct ref_update **updates;
        size_t alloc;
        size_t nr;
+       enum ref_transaction_state state;
 };
 
-struct ref_transaction *ref_transaction_begin(void)
+struct ref_transaction *ref_transaction_begin(struct strbuf *err)
 {
        return xcalloc(1, sizeof(struct ref_transaction));
 }
@@ -3436,6 +3419,9 @@ int ref_transaction_update(struct ref_transaction *transaction,
 {
        struct ref_update *update;
 
+       if (transaction->state != REF_TRANSACTION_OPEN)
+               die("BUG: update called for transaction that is not open");
+
        if (have_old && !old_sha1)
                die("BUG: have_old is true but old_sha1 is NULL");
 
@@ -3448,44 +3434,84 @@ int ref_transaction_update(struct ref_transaction *transaction,
        return 0;
 }
 
-void ref_transaction_create(struct ref_transaction *transaction,
-                           const char *refname,
-                           const unsigned char *new_sha1,
-                           int flags)
+int ref_transaction_create(struct ref_transaction *transaction,
+                          const char *refname,
+                          const unsigned char *new_sha1,
+                          int flags,
+                          struct strbuf *err)
 {
-       struct ref_update *update = add_update(transaction, refname);
+       struct ref_update *update;
+
+       if (transaction->state != REF_TRANSACTION_OPEN)
+               die("BUG: create called for transaction that is not open");
+
+       if (!new_sha1 || is_null_sha1(new_sha1))
+               die("BUG: create ref with null new_sha1");
+
+       update = add_update(transaction, refname);
 
-       assert(!is_null_sha1(new_sha1));
        hashcpy(update->new_sha1, new_sha1);
        hashclr(update->old_sha1);
        update->flags = flags;
        update->have_old = 1;
+       return 0;
 }
 
-void ref_transaction_delete(struct ref_transaction *transaction,
-                           const char *refname,
-                           const unsigned char *old_sha1,
-                           int flags, int have_old)
+int ref_transaction_delete(struct ref_transaction *transaction,
+                          const char *refname,
+                          const unsigned char *old_sha1,
+                          int flags, int have_old,
+                          struct strbuf *err)
 {
-       struct ref_update *update = add_update(transaction, refname);
+       struct ref_update *update;
 
+       if (transaction->state != REF_TRANSACTION_OPEN)
+               die("BUG: delete called for transaction that is not open");
+
+       if (have_old && !old_sha1)
+               die("BUG: have_old is true but old_sha1 is NULL");
+
+       update = add_update(transaction, refname);
        update->flags = flags;
        update->have_old = have_old;
        if (have_old) {
                assert(!is_null_sha1(old_sha1));
                hashcpy(update->old_sha1, old_sha1);
        }
+       return 0;
 }
 
 int update_ref(const char *action, const char *refname,
               const unsigned char *sha1, const unsigned char *oldval,
               int flags, enum action_on_err onerr)
 {
-       struct ref_lock *lock;
-       lock = update_ref_lock(refname, oldval, flags, NULL, onerr);
-       if (!lock)
+       struct ref_transaction *t;
+       struct strbuf err = STRBUF_INIT;
+
+       t = ref_transaction_begin(&err);
+       if (!t ||
+           ref_transaction_update(t, refname, sha1, oldval, flags,
+                                  !!oldval, &err) ||
+           ref_transaction_commit(t, action, &err)) {
+               const char *str = "update_ref failed for ref '%s': %s";
+
+               ref_transaction_free(t);
+               switch (onerr) {
+               case UPDATE_REFS_MSG_ON_ERR:
+                       error(str, refname, err.buf);
+                       break;
+               case UPDATE_REFS_DIE_ON_ERR:
+                       die(str, refname, err.buf);
+                       break;
+               case UPDATE_REFS_QUIET_ON_ERR:
+                       break;
+               }
+               strbuf_release(&err);
                return 1;
-       return update_ref_write(action, refname, sha1, lock, NULL, onerr);
+       }
+       strbuf_release(&err);
+       ref_transaction_free(t);
+       return 0;
 }
 
 static int ref_update_compare(const void *r1, const void *r2)
@@ -3519,8 +3545,13 @@ int ref_transaction_commit(struct ref_transaction *transaction,
        int n = transaction->nr;
        struct ref_update **updates = transaction->updates;
 
-       if (!n)
+       if (transaction->state != REF_TRANSACTION_OPEN)
+               die("BUG: commit called for transaction that is not open");
+
+       if (!n) {
+               transaction->state = REF_TRANSACTION_CLOSED;
                return 0;
+       }
 
        /* Allocate work space */
        delnames = xmalloc(sizeof(*delnames) * n);
@@ -3535,12 +3566,12 @@ int ref_transaction_commit(struct ref_transaction *transaction,
        for (i = 0; i < n; i++) {
                struct ref_update *update = updates[i];
 
-               update->lock = update_ref_lock(update->refname,
-                                              (update->have_old ?
-                                               update->old_sha1 : NULL),
-                                              update->flags,
-                                              &update->type,
-                                              UPDATE_REFS_QUIET_ON_ERR);
+               update->lock = lock_any_ref_for_update(update->refname,
+                                                      (update->have_old ?
+                                                       update->old_sha1 :
+                                                       NULL),
+                                                      update->flags,
+                                                      &update->type);
                if (!update->lock) {
                        if (err)
                                strbuf_addf(err, "Cannot lock the ref '%s'.",
@@ -3555,14 +3586,15 @@ int ref_transaction_commit(struct ref_transaction *transaction,
                struct ref_update *update = updates[i];
 
                if (!is_null_sha1(update->new_sha1)) {
-                       ret = update_ref_write(msg,
-                                              update->refname,
-                                              update->new_sha1,
-                                              update->lock, err,
-                                              UPDATE_REFS_QUIET_ON_ERR);
-                       update->lock = NULL; /* freed by update_ref_write */
-                       if (ret)
+                       ret = write_ref_sha1(update->lock, update->new_sha1,
+                                            msg);
+                       update->lock = NULL; /* freed by write_ref_sha1 */
+                       if (ret) {
+                               if (err)
+                                       strbuf_addf(err, "Cannot update the ref '%s'.",
+                                                   update->refname);
                                goto cleanup;
+                       }
                }
        }
 
@@ -3571,8 +3603,9 @@ int ref_transaction_commit(struct ref_transaction *transaction,
                struct ref_update *update = updates[i];
 
                if (update->lock) {
-                       delnames[delnum++] = update->lock->ref_name;
                        ret |= delete_ref_loose(update->lock, update->type);
+                       if (!(update->flags & REF_ISPRUNING))
+                               delnames[delnum++] = update->lock->ref_name;
                }
        }
 
@@ -3582,6 +3615,8 @@ int ref_transaction_commit(struct ref_transaction *transaction,
        clear_loose_ref_cache(&ref_cache);
 
 cleanup:
+       transaction->state = REF_TRANSACTION_CLOSED;
+
        for (i = 0; i < n; i++)
                if (updates[i]->lock)
                        unlock_ref(updates[i]->lock);
diff --git a/refs.h b/refs.h
index ec46acdde7b67d3531a4c0e18d33901d2a4f307a..68c57701646f05a44dd0da95d981787653ae032d 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -10,6 +10,38 @@ struct ref_lock {
        int force_write;
 };
 
+/*
+ * A ref_transaction represents a collection of ref updates
+ * that should succeed or fail together.
+ *
+ * Calling sequence
+ * ----------------
+ * - Allocate and initialize a `struct ref_transaction` by calling
+ *   `ref_transaction_begin()`.
+ *
+ * - List intended ref updates by calling functions like
+ *   `ref_transaction_update()` and `ref_transaction_create()`.
+ *
+ * - Call `ref_transaction_commit()` to execute the transaction.
+ *   If this succeeds, the ref updates will have taken place and
+ *   the transaction cannot be rolled back.
+ *
+ * - At any time call `ref_transaction_free()` to discard the
+ *   transaction and free associated resources.  In particular,
+ *   this rolls back the transaction if it has not been
+ *   successfully committed.
+ *
+ * Error handling
+ * --------------
+ *
+ * On error, transaction functions append a message about what
+ * went wrong to the 'err' argument.  The message mentions what
+ * ref was being updated (if any) when the error occurred so it
+ * can be passed to 'die' or 'error' as-is.
+ *
+ * The message is appended to err without first clearing err.
+ * err will not be '\n' terminated.
+ */
 struct ref_transaction;
 
 /*
@@ -141,14 +173,17 @@ extern int is_branch(const char *refname);
 extern int peel_ref(const char *refname, unsigned char *sha1);
 
 /*
- * Locks a "refs/" ref returning the lock on success and NULL on failure.
- * On failure errno is set to something meaningful.
+ * Flags controlling lock_any_ref_for_update(), ref_transaction_update(),
+ * ref_transaction_create(), etc.
+ * REF_NODEREF: act on the ref directly, instead of dereferencing
+ *              symbolic references.
+ *
+ * Flags >= 0x100 are reserved for internal use.
  */
-extern struct ref_lock *lock_ref_sha1(const char *refname, const unsigned char *old_sha1);
-
-/** Locks any ref (for 'HEAD' type refs). */
 #define REF_NODEREF    0x01
-/* errno is set to something meaningful on failure */
+/*
+ * This function sets errno to something meaningful on failure.
+ */
 extern struct ref_lock *lock_any_ref_for_update(const char *refname,
                                                const unsigned char *old_sha1,
                                                int flags, int *type_p);
@@ -232,7 +267,7 @@ enum action_on_err {
  * Begin a reference transaction.  The reference transaction must
  * be freed by calling ref_transaction_free().
  */
-struct ref_transaction *ref_transaction_begin(void);
+struct ref_transaction *ref_transaction_begin(struct strbuf *err);
 
 /*
  * The following functions add a reference check or update to a
@@ -250,7 +285,7 @@ struct ref_transaction *ref_transaction_begin(void);
  * it must not have existed beforehand.
  * Function returns 0 on success and non-zero on failure. A failure to update
  * means that the transaction as a whole has failed and will need to be
- * rolled back. On failure the err buffer will be updated.
+ * rolled back.
  */
 int ref_transaction_update(struct ref_transaction *transaction,
                           const char *refname,
@@ -264,28 +299,34 @@ int ref_transaction_update(struct ref_transaction *transaction,
  * that the reference should have after the update; it must not be the
  * null SHA-1.  It is verified that the reference does not exist
  * already.
+ * Function returns 0 on success and non-zero on failure. A failure to create
+ * means that the transaction as a whole has failed and will need to be
+ * rolled back.
  */
-void ref_transaction_create(struct ref_transaction *transaction,
-                           const char *refname,
-                           const unsigned char *new_sha1,
-                           int flags);
+int ref_transaction_create(struct ref_transaction *transaction,
+                          const char *refname,
+                          const unsigned char *new_sha1,
+                          int flags,
+                          struct strbuf *err);
 
 /*
  * Add a reference deletion to transaction.  If have_old is true, then
  * old_sha1 holds the value that the reference should have had before
  * the update (which must not be the null SHA-1).
+ * Function returns 0 on success and non-zero on failure. A failure to delete
+ * means that the transaction as a whole has failed and will need to be
+ * rolled back.
  */
-void ref_transaction_delete(struct ref_transaction *transaction,
-                           const char *refname,
-                           const unsigned char *old_sha1,
-                           int flags, int have_old);
+int ref_transaction_delete(struct ref_transaction *transaction,
+                          const char *refname,
+                          const unsigned char *old_sha1,
+                          int flags, int have_old,
+                          struct strbuf *err);
 
 /*
  * Commit all of the changes that have been queued in transaction, as
  * atomically as possible.  Return a nonzero value if there is a
  * problem.
- * If err is non-NULL we will add an error string to it to explain why
- * the transaction failed. The string does not end in newline.
  */
 int ref_transaction_commit(struct ref_transaction *transaction,
                           const char *msg, struct strbuf *err);
index 558b9fecdf5bca1deb2577a51b1e8473e3350911..645872a4f204a51e915eecdf951613ac09277e8b 100644 (file)
@@ -623,10 +623,9 @@ 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;
+       struct child_process client = CHILD_PROCESS_INIT;
        int err = 0;
 
-       memset(&client, 0, sizeof(client));
        client.in = -1;
        client.out = -1;
        client.git_cmd = 1;
index 686e07d317bf157461f0ce680958a466675c80bc..48bf6eb93b361a736d96e701749c16bae8d169a8 100644 (file)
@@ -175,7 +175,7 @@ static int cmd_import(const char *line)
        char *note_msg;
        unsigned char head_sha1[20];
        unsigned int startrev;
-       struct child_process svndump_proc;
+       struct child_process svndump_proc = CHILD_PROCESS_INIT;
        const char *command = "svnrdump";
 
        if (read_ref(private_ref, head_sha1))
@@ -200,7 +200,6 @@ static int cmd_import(const char *line)
                if(dumpin_fd < 0)
                        die_errno("Couldn't open svn dump file %s.", url);
        } else {
-               memset(&svndump_proc, 0, sizeof(struct child_process));
                svndump_proc.out = -1;
                argv_array_push(&svndump_proc.args, command);
                argv_array_push(&svndump_proc.args, "dump");
index 3d6c86a36f26406305d58505b10db3f747a2546c..35e62ee0f55cf6c44c0ad94761249ef12b7c19c5 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -42,6 +42,7 @@ struct rewrites {
 static struct remote **remotes;
 static int remotes_alloc;
 static int remotes_nr;
+static struct hashmap remotes_hash;
 
 static struct branch **branches;
 static int branches_alloc;
@@ -136,26 +137,51 @@ static void add_url_alias(struct remote *remote, const char *url)
        add_pushurl_alias(remote, url);
 }
 
+struct remotes_hash_key {
+       const char *str;
+       int len;
+};
+
+static int remotes_hash_cmp(const struct remote *a, const struct remote *b, const struct remotes_hash_key *key)
+{
+       if (key)
+               return strncmp(a->name, key->str, key->len) || a->name[key->len];
+       else
+               return strcmp(a->name, b->name);
+}
+
+static inline void init_remotes_hash(void)
+{
+       if (!remotes_hash.cmpfn)
+               hashmap_init(&remotes_hash, (hashmap_cmp_fn)remotes_hash_cmp, 0);
+}
+
 static struct remote *make_remote(const char *name, int len)
 {
-       struct remote *ret;
-       int i;
+       struct remote *ret, *replaced;
+       struct remotes_hash_key lookup;
+       struct hashmap_entry lookup_entry;
 
-       for (i = 0; i < remotes_nr; i++) {
-               if (len ? (!strncmp(name, remotes[i]->name, len) &&
-                          !remotes[i]->name[len]) :
-                   !strcmp(name, remotes[i]->name))
-                       return remotes[i];
-       }
+       if (!len)
+               len = strlen(name);
+
+       init_remotes_hash();
+       lookup.str = name;
+       lookup.len = len;
+       hashmap_entry_init(&lookup_entry, memhash(name, len));
+
+       if ((ret = hashmap_get(&remotes_hash, &lookup_entry, &lookup)) != NULL)
+               return ret;
 
        ret = xcalloc(1, sizeof(struct remote));
        ret->prune = -1;  /* unspecified */
        ALLOC_GROW(remotes, remotes_nr + 1, remotes_alloc);
        remotes[remotes_nr++] = ret;
-       if (len)
-               ret->name = xstrndup(name, len);
-       else
-               ret->name = xstrdup(name);
+       ret->name = xstrndup(name, len);
+
+       hashmap_entry_init(ret, lookup_entry.hash);
+       replaced = hashmap_put(&remotes_hash, ret);
+       assert(replaced == NULL);  /* no previous entry overwritten */
        return ret;
 }
 
@@ -717,13 +743,16 @@ struct remote *pushremote_get(const char *name)
 
 int remote_is_configured(const char *name)
 {
-       int i;
+       struct remotes_hash_key lookup;
+       struct hashmap_entry lookup_entry;
        read_config();
 
-       for (i = 0; i < remotes_nr; i++)
-               if (!strcmp(name, remotes[i]->name))
-                       return 1;
-       return 0;
+       init_remotes_hash();
+       lookup.str = name;
+       lookup.len = strlen(name);
+       hashmap_entry_init(&lookup_entry, memhash(name, lookup.len));
+
+       return hashmap_get(&remotes_hash, &lookup_entry, &lookup) != NULL;
 }
 
 int for_each_remote(each_remote_fn fn, void *priv)
@@ -1893,7 +1922,8 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs)
 
        init_revisions(&revs, NULL);
        setup_revisions(rev_argc, rev_argv, &revs, NULL);
-       prepare_revision_walk(&revs);
+       if (prepare_revision_walk(&revs))
+               die("revision walk setup failed");
 
        /* ... and count the commits on each side. */
        *num_ours = 0;
@@ -1920,7 +1950,7 @@ int stat_tracking_info(struct branch *branch, int *num_ours, int *num_theirs)
 int format_tracking_info(struct branch *branch, struct strbuf *sb)
 {
        int ours, theirs;
-       const char *base;
+       char *base;
        int upstream_is_gone = 0;
 
        switch (stat_tracking_info(branch, &ours, &theirs)) {
@@ -1936,8 +1966,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb)
                break;
        }
 
-       base = branch->merge[0]->dst;
-       base = shorten_unambiguous_ref(base, 0);
+       base = shorten_unambiguous_ref(branch->merge[0]->dst, 0);
        if (upstream_is_gone) {
                strbuf_addf(sb,
                        _("Your branch is based on '%s', but the upstream is gone.\n"),
@@ -1983,6 +2012,7 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb)
                        strbuf_addf(sb,
                                _("  (use \"git pull\" to merge the remote branch into yours)\n"));
        }
+       free(base);
        return 1;
 }
 
index 917d383a80ddbfa377f10c3d1a4e132336065c2c..8b62efd2adcb74c7e46d3f918a25658d6f6ce16f 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -2,6 +2,7 @@
 #define REMOTE_H
 
 #include "parse-options.h"
+#include "hashmap.h"
 
 enum {
        REMOTE_CONFIG,
@@ -10,6 +11,8 @@ enum {
 };
 
 struct remote {
+       struct hashmap_entry ent;  /* must be first */
+
        const char *name;
        int origin;
 
index d84b495895bc6d42980c388ed03c560174604f92..20b18add42d2551a227eaac8125fe806006d2856 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -573,15 +573,11 @@ static int do_plain_rerere(struct string_list *rr, int fd)
        return write_rr(rr, fd);
 }
 
-static int git_rerere_config(const char *var, const char *value, void *cb)
+static void git_rerere_config(void)
 {
-       if (!strcmp(var, "rerere.enabled"))
-               rerere_enabled = git_config_bool(var, value);
-       else if (!strcmp(var, "rerere.autoupdate"))
-               rerere_autoupdate = git_config_bool(var, value);
-       else
-               return git_default_config(var, value, cb);
-       return 0;
+       git_config_get_bool("rerere.enabled", &rerere_enabled);
+       git_config_get_bool("rerere.autoupdate", &rerere_autoupdate);
+       git_config(git_default_config, NULL);
 }
 
 static int is_rerere_enabled(void)
@@ -606,7 +602,7 @@ int setup_rerere(struct string_list *merge_rr, int flags)
 {
        int fd;
 
-       git_config(git_rerere_config, NULL);
+       git_rerere_config();
        if (!is_rerere_enabled())
                return -1;
 
@@ -699,24 +695,6 @@ static void unlink_rr_item(const char *name)
        rmdir(git_path("rr-cache/%s", name));
 }
 
-struct rerere_gc_config_cb {
-       int cutoff_noresolve;
-       int cutoff_resolve;
-};
-
-static int git_rerere_gc_config(const char *var, const char *value, void *cb)
-{
-       struct rerere_gc_config_cb *cf = cb;
-
-       if (!strcmp(var, "gc.rerereresolved"))
-               cf->cutoff_resolve = git_config_int(var, value);
-       else if (!strcmp(var, "gc.rerereunresolved"))
-               cf->cutoff_noresolve = git_config_int(var, value);
-       else
-               return git_default_config(var, value, cb);
-       return 0;
-}
-
 void rerere_gc(struct string_list *rr)
 {
        struct string_list to_remove = STRING_LIST_INIT_DUP;
@@ -724,9 +702,12 @@ void rerere_gc(struct string_list *rr)
        struct dirent *e;
        int i, cutoff;
        time_t now = time(NULL), then;
-       struct rerere_gc_config_cb cf = { 15, 60 };
+       int cutoff_noresolve = 15;
+       int cutoff_resolve = 60;
 
-       git_config(git_rerere_gc_config, &cf);
+       git_config_get_int("gc.rerereresolved", &cutoff_resolve);
+       git_config_get_int("gc.rerereunresolved", &cutoff_noresolve);
+       git_config(git_default_config, NULL);
        dir = opendir(git_path("rr-cache"));
        if (!dir)
                die_errno("unable to open rr-cache directory");
@@ -736,12 +717,12 @@ void rerere_gc(struct string_list *rr)
 
                then = rerere_last_used_at(e->d_name);
                if (then) {
-                       cutoff = cf.cutoff_resolve;
+                       cutoff = cutoff_resolve;
                } else {
                        then = rerere_created_at(e->d_name);
                        if (!then)
                                continue;
-                       cutoff = cf.cutoff_noresolve;
+                       cutoff = cutoff_noresolve;
                }
                if (then < now - cutoff * 86400)
                        string_list_append(&to_remove, e->d_name);
index 2571ada6bf66ce6e945c539be4b0123e5b9648a9..0d3e4171ef73f0cfb58a4f396e17717f3b0bb5a3 100644 (file)
@@ -473,7 +473,7 @@ static int rev_compare_tree(struct rev_info *revs,
                 * If we are simplifying by decoration, then the commit
                 * is worth showing if it has a tag pointing at it.
                 */
-               if (lookup_decoration(&name_decoration, &commit->object))
+               if (get_name_decoration(&commit->object))
                        return REV_TREE_DIFFERENT;
                /*
                 * A commit that is not pointed by a tag is uninteresting
@@ -1825,7 +1825,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        } else if (!strcmp(arg, "--pretty")) {
                revs->verbose_header = 1;
                revs->pretty_given = 1;
-               get_commit_format(arg+8, revs);
+               get_commit_format(NULL, revs);
        } else if (starts_with(arg, "--pretty=") || starts_with(arg, "--format=")) {
                /*
                 * Detached form ("--pretty X" as opposed to "--pretty=X")
index 35a3ebf07b1792ac7b0ecef30781223591413093..761f0fde40c91a3cc910c092c5aa9ad56f2f0042 100644 (file)
@@ -8,6 +8,12 @@
 # define SHELL_PATH "/bin/sh"
 #endif
 
+void child_process_init(struct child_process *child)
+{
+       memset(child, 0, sizeof(*child));
+       argv_array_init(&child->args);
+}
+
 struct child_to_clean {
        pid_t pid;
        struct child_to_clean *next;
@@ -555,31 +561,21 @@ int run_command(struct child_process *cmd)
        return finish_command(cmd);
 }
 
-static void prepare_run_command_v_opt(struct child_process *cmd,
-                                     const char **argv,
-                                     int opt)
-{
-       memset(cmd, 0, sizeof(*cmd));
-       cmd->argv = argv;
-       cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
-       cmd->git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
-       cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
-       cmd->silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0;
-       cmd->use_shell = opt & RUN_USING_SHELL ? 1 : 0;
-       cmd->clean_on_exit = opt & RUN_CLEAN_ON_EXIT ? 1 : 0;
-}
-
 int run_command_v_opt(const char **argv, int opt)
 {
-       struct child_process cmd;
-       prepare_run_command_v_opt(&cmd, argv, opt);
-       return run_command(&cmd);
+       return run_command_v_opt_cd_env(argv, opt, NULL, NULL);
 }
 
 int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const char *const *env)
 {
-       struct child_process cmd;
-       prepare_run_command_v_opt(&cmd, argv, opt);
+       struct child_process cmd = CHILD_PROCESS_INIT;
+       cmd.argv = argv;
+       cmd.no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
+       cmd.git_cmd = opt & RUN_GIT_CMD ? 1 : 0;
+       cmd.stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
+       cmd.silent_exec_failure = opt & RUN_SILENT_EXEC_FAILURE ? 1 : 0;
+       cmd.use_shell = opt & RUN_USING_SHELL ? 1 : 0;
+       cmd.clean_on_exit = opt & RUN_CLEAN_ON_EXIT ? 1 : 0;
        cmd.dir = dir;
        cmd.env = env;
        return run_command(&cmd);
@@ -763,14 +759,13 @@ char *find_hook(const char *name)
 
 int run_hook_ve(const char *const *env, const char *name, va_list args)
 {
-       struct child_process hook;
+       struct child_process hook = CHILD_PROCESS_INIT;
        const char *p;
 
        p = find_hook(name);
        if (!p)
                return 0;
 
-       memset(&hook, 0, sizeof(hook));
        argv_array_push(&hook.args, p);
        while ((p = va_arg(args, const char *)))
                argv_array_push(&hook.args, p);
index ea73de309bc65c3d00bb34ad84824ba72d85cbfe..1b135d1c960aa58e2fa4ad44ecc195835daac69a 100644 (file)
@@ -44,6 +44,9 @@ struct child_process {
        unsigned clean_on_exit:1;
 };
 
+#define CHILD_PROCESS_INIT { NULL, ARGV_ARRAY_INIT }
+void child_process_init(struct child_process *);
+
 int start_command(struct child_process *);
 int finish_command(struct child_process *);
 int run_command(struct child_process *);
index 6129b0fd8e8e1961ab4c74de4f421c41c7786b42..8b4cbf049c243b8cdc1add94ddf1bf50bcbd8df9 100644 (file)
@@ -47,7 +47,7 @@ static int pack_objects(int fd, struct ref *refs, struct sha1_array *extra, stru
                NULL,
                NULL,
        };
-       struct child_process po;
+       struct child_process po = CHILD_PROCESS_INIT;
        int i;
 
        i = 4;
@@ -59,7 +59,6 @@ static int pack_objects(int fd, struct ref *refs, struct sha1_array *extra, stru
                argv[i++] = "-q";
        if (args->progress)
                argv[i++] = "--progress";
-       memset(&po, 0, sizeof(po));
        po.argv = argv;
        po.in = -1;
        po.out = args->stateless_rpc ? -1 : fd;
index 3c060e054720b7b17f9a868cabb1a0ef62aa1b50..5e8a207474bc6971a0de4f9ff6160a5681ac7b6d 100644 (file)
@@ -237,23 +237,33 @@ static int error_dirty_index(struct replay_opts *opts)
 static int fast_forward_to(const unsigned char *to, const unsigned char *from,
                        int unborn, struct replay_opts *opts)
 {
-       struct ref_lock *ref_lock;
+       struct ref_transaction *transaction;
        struct strbuf sb = STRBUF_INIT;
-       int ret;
+       struct strbuf err = STRBUF_INIT;
 
        read_cache();
        if (checkout_fast_forward(from, to, 1))
                exit(128); /* the callee should have complained already */
-       ref_lock = lock_any_ref_for_update("HEAD", unborn ? null_sha1 : from,
-                                          0, NULL);
-       if (!ref_lock)
-               return error(_("Failed to lock HEAD during fast_forward_to"));
 
        strbuf_addf(&sb, "%s: fast-forward", action_name(opts));
-       ret = write_ref_sha1(ref_lock, to, sb.buf);
+
+       transaction = ref_transaction_begin(&err);
+       if (!transaction ||
+           ref_transaction_update(transaction, "HEAD",
+                                  to, unborn ? null_sha1 : from,
+                                  0, 1, &err) ||
+           ref_transaction_commit(transaction, sb.buf, &err)) {
+               ref_transaction_free(transaction);
+               error("%s", err.buf);
+               strbuf_release(&sb);
+               strbuf_release(&err);
+               return -1;
+       }
 
        strbuf_release(&sb);
-       return ret;
+       strbuf_release(&err);
+       ref_transaction_free(transaction);
+       return 0;
 }
 
 static int do_recursive_merge(struct commit *base, struct commit *next,
diff --git a/setup.c b/setup.c
index 0a22f8bd1d631fe5f0afe1d84162ca4064a00e4f..979b13f0c6cd6bc3c265187e8ea79628bfe99f87 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -387,7 +387,7 @@ const char *read_gitfile(const char *path)
 }
 
 static const char *setup_explicit_git_dir(const char *gitdirenv,
-                                         char *cwd, int len,
+                                         struct strbuf *cwd,
                                          int *nongit_ok)
 {
        const char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);
@@ -434,16 +434,16 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
                if (is_absolute_path(git_work_tree_cfg))
                        set_git_work_tree(git_work_tree_cfg);
                else {
-                       char core_worktree[PATH_MAX];
+                       char *core_worktree;
                        if (chdir(gitdirenv))
                                die_errno("Could not chdir to '%s'", gitdirenv);
                        if (chdir(git_work_tree_cfg))
                                die_errno("Could not chdir to '%s'", git_work_tree_cfg);
-                       if (!getcwd(core_worktree, PATH_MAX))
-                               die_errno("Could not get directory '%s'", git_work_tree_cfg);
-                       if (chdir(cwd))
+                       core_worktree = xgetcwd();
+                       if (chdir(cwd->buf))
                                die_errno("Could not come back to cwd");
                        set_git_work_tree(core_worktree);
+                       free(core_worktree);
                }
        }
        else if (!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, 1)) {
@@ -459,21 +459,20 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
        worktree = get_git_work_tree();
 
        /* both get_git_work_tree() and cwd are already normalized */
-       if (!strcmp(cwd, worktree)) { /* cwd == worktree */
+       if (!strcmp(cwd->buf, worktree)) { /* cwd == worktree */
                set_git_dir(gitdirenv);
                free(gitfile);
                return NULL;
        }
 
-       offset = dir_inside_of(cwd, worktree);
+       offset = dir_inside_of(cwd->buf, worktree);
        if (offset >= 0) {      /* cwd inside worktree? */
                set_git_dir(real_path(gitdirenv));
                if (chdir(worktree))
                        die_errno("Could not chdir to '%s'", worktree);
-               cwd[len++] = '/';
-               cwd[len] = '\0';
+               strbuf_addch(cwd, '/');
                free(gitfile);
-               return cwd + offset;
+               return cwd->buf + offset;
        }
 
        /* cwd outside worktree */
@@ -483,7 +482,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
 }
 
 static const char *setup_discovered_git_dir(const char *gitdir,
-                                           char *cwd, int offset, int len,
+                                           struct strbuf *cwd, int offset,
                                            int *nongit_ok)
 {
        if (check_repository_format_gently(gitdir, nongit_ok))
@@ -491,17 +490,17 @@ static const char *setup_discovered_git_dir(const char *gitdir,
 
        /* --work-tree is set without --git-dir; use discovered one */
        if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
-               if (offset != len && !is_absolute_path(gitdir))
+               if (offset != cwd->len && !is_absolute_path(gitdir))
                        gitdir = xstrdup(real_path(gitdir));
-               if (chdir(cwd))
+               if (chdir(cwd->buf))
                        die_errno("Could not come back to cwd");
-               return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
+               return setup_explicit_git_dir(gitdir, cwd, nongit_ok);
        }
 
        /* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
        if (is_bare_repository_cfg > 0) {
-               set_git_dir(offset == len ? gitdir : real_path(gitdir));
-               if (chdir(cwd))
+               set_git_dir(offset == cwd->len ? gitdir : real_path(gitdir));
+               if (chdir(cwd->buf))
                        die_errno("Could not come back to cwd");
                return NULL;
        }
@@ -512,18 +511,18 @@ static const char *setup_discovered_git_dir(const char *gitdir,
                set_git_dir(gitdir);
        inside_git_dir = 0;
        inside_work_tree = 1;
-       if (offset == len)
+       if (offset == cwd->len)
                return NULL;
 
        /* Make "offset" point to past the '/', and add a '/' at the end */
        offset++;
-       cwd[len++] = '/';
-       cwd[len] = 0;
-       return cwd + offset;
+       strbuf_addch(cwd, '/');
+       return cwd->buf + offset;
 }
 
 /* #16.1, #17.1, #20.1, #21.1, #22.1 (see t1510) */
-static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongit_ok)
+static const char *setup_bare_git_dir(struct strbuf *cwd, int offset,
+                                     int *nongit_ok)
 {
        int root_len;
 
@@ -536,20 +535,20 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi
        if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
                const char *gitdir;
 
-               gitdir = offset == len ? "." : xmemdupz(cwd, offset);
-               if (chdir(cwd))
+               gitdir = offset == cwd->len ? "." : xmemdupz(cwd->buf, offset);
+               if (chdir(cwd->buf))
                        die_errno("Could not come back to cwd");
-               return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
+               return setup_explicit_git_dir(gitdir, cwd, nongit_ok);
        }
 
        inside_git_dir = 1;
        inside_work_tree = 0;
-       if (offset != len) {
-               if (chdir(cwd))
+       if (offset != cwd->len) {
+               if (chdir(cwd->buf))
                        die_errno("Cannot come back to cwd");
-               root_len = offset_1st_component(cwd);
-               cwd[offset > root_len ? offset : root_len] = '\0';
-               set_git_dir(cwd);
+               root_len = offset_1st_component(cwd->buf);
+               strbuf_setlen(cwd, offset > root_len ? offset : root_len);
+               set_git_dir(cwd->buf);
        }
        else
                set_git_dir(".");
@@ -617,13 +616,22 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
 {
        const char *env_ceiling_dirs = getenv(CEILING_DIRECTORIES_ENVIRONMENT);
        struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
-       static char cwd[PATH_MAX + 1];
+       static struct strbuf cwd = STRBUF_INIT;
        const char *gitdirenv, *ret;
        char *gitfile;
-       int len, offset, offset_parent, ceil_offset = -1;
+       int offset, offset_parent, ceil_offset = -1;
        dev_t current_device = 0;
        int one_filesystem = 1;
 
+       /*
+        * We may have read an incomplete configuration before
+        * setting-up the git directory. If so, clear the cache so
+        * that the next queries to the configuration reload complete
+        * configuration (including the per-repo config file that we
+        * ignored previously).
+        */
+       git_config_clear();
+
        /*
         * Let's assume that we are in a git repository.
         * If it turns out later that we are somewhere else, the value will be
@@ -632,9 +640,9 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
        if (nongit_ok)
                *nongit_ok = 0;
 
-       if (!getcwd(cwd, sizeof(cwd) - 1))
+       if (strbuf_getcwd(&cwd))
                die_errno("Unable to read current working directory");
-       offset = len = strlen(cwd);
+       offset = cwd.len;
 
        /*
         * If GIT_DIR is set explicitly, we're not going
@@ -643,7 +651,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
         */
        gitdirenv = getenv(GIT_DIR_ENVIRONMENT);
        if (gitdirenv)
-               return setup_explicit_git_dir(gitdirenv, cwd, len, nongit_ok);
+               return setup_explicit_git_dir(gitdirenv, &cwd, nongit_ok);
 
        if (env_ceiling_dirs) {
                int empty_entry_found = 0;
@@ -651,11 +659,11 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
                string_list_split(&ceiling_dirs, env_ceiling_dirs, PATH_SEP, -1);
                filter_string_list(&ceiling_dirs, 0,
                                   canonicalize_ceiling_entry, &empty_entry_found);
-               ceil_offset = longest_ancestor_length(cwd, &ceiling_dirs);
+               ceil_offset = longest_ancestor_length(cwd.buf, &ceiling_dirs);
                string_list_clear(&ceiling_dirs, 0);
        }
 
-       if (ceil_offset < 0 && has_dos_drive_prefix(cwd))
+       if (ceil_offset < 0 && has_dos_drive_prefix(cwd.buf))
                ceil_offset = 1;
 
        /*
@@ -683,7 +691,7 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
 
                if (gitdirenv) {
                        ret = setup_discovered_git_dir(gitdirenv,
-                                                      cwd, offset, len,
+                                                      &cwd, offset,
                                                       nongit_ok);
                        free(gitfile);
                        return ret;
@@ -691,29 +699,31 @@ static const char *setup_git_directory_gently_1(int *nongit_ok)
                free(gitfile);
 
                if (is_git_directory("."))
-                       return setup_bare_git_dir(cwd, offset, len, nongit_ok);
+                       return setup_bare_git_dir(&cwd, offset, nongit_ok);
 
                offset_parent = offset;
-               while (--offset_parent > ceil_offset && cwd[offset_parent] != '/');
+               while (--offset_parent > ceil_offset && cwd.buf[offset_parent] != '/');
                if (offset_parent <= ceil_offset)
-                       return setup_nongit(cwd, nongit_ok);
+                       return setup_nongit(cwd.buf, nongit_ok);
                if (one_filesystem) {
-                       dev_t parent_device = get_device_or_die("..", cwd, offset);
+                       dev_t parent_device = get_device_or_die("..", cwd.buf,
+                                                               offset);
                        if (parent_device != current_device) {
                                if (nongit_ok) {
-                                       if (chdir(cwd))
+                                       if (chdir(cwd.buf))
                                                die_errno("Cannot come back to cwd");
                                        *nongit_ok = 1;
                                        return NULL;
                                }
-                               cwd[offset] = '\0';
+                               strbuf_setlen(&cwd, offset);
                                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);
+                               "Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set).",
+                                   cwd.buf);
                        }
                }
                if (chdir("..")) {
-                       cwd[offset] = '\0';
-                       die_errno("Cannot change to '%s/..'", cwd);
+                       strbuf_setlen(&cwd, offset);
+                       die_errno("Cannot change to '%s/..'", cwd.buf);
                }
                offset = offset_parent;
        }
index 3f70b1d86aaa8e0648d8a3c6ebb6aca701ae7475..c08c0cbea805b38104504b9b51266949affb6991 100644 (file)
@@ -350,7 +350,7 @@ static void link_alt_odb_entries(const char *alt, int len, int sep,
                return;
        }
 
-       strbuf_addstr(&objdirbuf, absolute_path(get_object_directory()));
+       strbuf_add_absolute_path(&objdirbuf, get_object_directory());
        normalize_path_copy(objdirbuf.buf, objdirbuf.buf);
 
        alt_copy = xmemdupz(alt, len);
@@ -1923,7 +1923,9 @@ static void *unpack_compressed_entry(struct packed_git *p,
        git_zstream stream;
        unsigned char *buffer, *in;
 
-       buffer = xmallocz(size);
+       buffer = xmallocz_gently(size);
+       if (!buffer)
+               return NULL;
        memset(&stream, 0, sizeof(stream));
        stream.next_out = buffer;
        stream.avail_out = size + 1;
index 63ee66fedd617e2cacfae7a763f43ee600d15273..7098b10e3db0caef02ae2daef8f0624e641aada4 100644 (file)
@@ -839,7 +839,7 @@ static int handle_one_ref(const char *path,
        }
        if (object->type != OBJ_COMMIT)
                return 0;
-       commit_list_insert_by_date((struct commit *)object, list);
+       commit_list_insert((struct commit *)object, list);
        return 0;
 }
 
@@ -1366,6 +1366,7 @@ static int get_sha1_with_context_1(const char *name,
                if (!only_to_die && namelen > 2 && name[1] == '/') {
                        struct commit_list *list = NULL;
                        for_each_ref(handle_one_ref, &list);
+                       commit_list_sort_by_date(&list);
                        return get_sha1_oneline(name + 2, sha1, list);
                }
                if (namelen < 3 ||
index 33018d847f08424211c02cff8002680f5a2f02e9..4d3144308feaf3fdc541b582ed589962c6c459c1 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -406,6 +406,27 @@ int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
        return -1;
 }
 
+int strbuf_getcwd(struct strbuf *sb)
+{
+       size_t oldalloc = sb->alloc;
+       size_t guessed_len = 128;
+
+       for (;; guessed_len *= 2) {
+               strbuf_grow(sb, guessed_len);
+               if (getcwd(sb->buf, sb->alloc)) {
+                       strbuf_setlen(sb, strlen(sb->buf));
+                       return 0;
+               }
+               if (errno != ERANGE)
+                       break;
+       }
+       if (oldalloc == 0)
+               strbuf_release(sb);
+       else
+               strbuf_reset(sb);
+       return -1;
+}
+
 int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
 {
        int ch;
@@ -555,6 +576,31 @@ void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes)
        }
 }
 
+void strbuf_add_absolute_path(struct strbuf *sb, const char *path)
+{
+       if (!*path)
+               die("The empty string is not a valid path");
+       if (!is_absolute_path(path)) {
+               struct stat cwd_stat, pwd_stat;
+               size_t orig_len = sb->len;
+               char *cwd = xgetcwd();
+               char *pwd = getenv("PWD");
+               if (pwd && strcmp(pwd, cwd) &&
+                   !stat(cwd, &cwd_stat) &&
+                   (cwd_stat.st_dev || cwd_stat.st_ino) &&
+                   !stat(pwd, &pwd_stat) &&
+                   pwd_stat.st_dev == cwd_stat.st_dev &&
+                   pwd_stat.st_ino == cwd_stat.st_ino)
+                       strbuf_addstr(sb, pwd);
+               else
+                       strbuf_addstr(sb, cwd);
+               if (sb->len > orig_len && !is_dir_sep(sb->buf[sb->len - 1]))
+                       strbuf_addch(sb, '/');
+               free(cwd);
+       }
+       strbuf_addstr(sb, path);
+}
+
 int printf_ln(const char *fmt, ...)
 {
        int ret;
index a7c0192e9ee392bd232b325692a9111b3e160e84..7bdc1da50732bacad3ba33526ba10ee8f7e200a4 100644 (file)
--- a/strbuf.h
+++ b/strbuf.h
@@ -174,6 +174,7 @@ extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
 extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);
 extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);
 extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);
+extern int strbuf_getcwd(struct strbuf *sb);
 
 extern int strbuf_getwholeline(struct strbuf *, FILE *, int);
 extern int strbuf_getline(struct strbuf *, FILE *, int);
@@ -189,6 +190,8 @@ extern void strbuf_addstr_urlencode(struct strbuf *, const char *,
                                    int reserved);
 extern void strbuf_humanise_bytes(struct strbuf *buf, off_t bytes);
 
+extern void strbuf_add_absolute_path(struct strbuf *sb, const char *path);
+
 __attribute__((format (printf,1,2)))
 extern int printf_ln(const char *fmt, ...);
 __attribute__((format (printf,2,3)))
index c3a61e70f9f72eced2530d425717972881b947c8..0690dc50d07e9fd30242e41afe149476a34fc105 100644 (file)
@@ -433,13 +433,12 @@ static int submodule_needs_pushing(const char *path, const unsigned char sha1[20
                return 0;
 
        if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
-               struct child_process cp;
+               struct child_process cp = CHILD_PROCESS_INIT;
                const char *argv[] = {"rev-list", NULL, "--not", "--remotes", "-n", "1" , NULL};
                struct strbuf buf = STRBUF_INIT;
                int needs_pushing = 0;
 
                argv[1] = sha1_to_hex(sha1);
-               memset(&cp, 0, sizeof(cp));
                cp.argv = argv;
                cp.env = local_repo_env;
                cp.git_cmd = 1;
@@ -524,10 +523,9 @@ static int push_submodule(const char *path)
                return 1;
 
        if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
-               struct child_process cp;
+               struct child_process cp = CHILD_PROCESS_INIT;
                const char *argv[] = {"push", NULL};
 
-               memset(&cp, 0, sizeof(cp));
                cp.argv = argv;
                cp.env = local_repo_env;
                cp.git_cmd = 1;
@@ -569,12 +567,11 @@ static int is_submodule_commit_present(const char *path, unsigned char sha1[20])
        if (!add_submodule_odb(path) && lookup_commit_reference(sha1)) {
                /* Even if the submodule is checked out and the commit is
                 * present, make sure it is reachable from a ref. */
-               struct child_process cp;
+               struct child_process cp = CHILD_PROCESS_INIT;
                const char *argv[] = {"rev-list", "-n", "1", NULL, "--not", "--all", NULL};
                struct strbuf buf = STRBUF_INIT;
 
                argv[3] = sha1_to_hex(sha1);
-               memset(&cp, 0, sizeof(cp));
                cp.argv = argv;
                cp.env = local_repo_env;
                cp.git_cmd = 1;
@@ -695,7 +692,7 @@ int fetch_populated_submodules(const struct argv_array *options,
                               int quiet)
 {
        int i, result = 0;
-       struct child_process cp;
+       struct child_process cp = CHILD_PROCESS_INIT;
        struct argv_array argv = ARGV_ARRAY_INIT;
        struct string_list_item *name_for_path;
        const char *work_tree = get_git_work_tree();
@@ -711,7 +708,6 @@ int fetch_populated_submodules(const struct argv_array *options,
        argv_array_push(&argv, "--recurse-submodules-default");
        /* default value, "--submodule-prefix" and its value are added later */
 
-       memset(&cp, 0, sizeof(cp));
        cp.env = local_repo_env;
        cp.git_cmd = 1;
        cp.no_stdin = 1;
@@ -794,7 +790,7 @@ int fetch_populated_submodules(const struct argv_array *options,
 unsigned is_submodule_modified(const char *path, int ignore_untracked)
 {
        ssize_t len;
-       struct child_process cp;
+       struct child_process cp = CHILD_PROCESS_INIT;
        const char *argv[] = {
                "status",
                "--porcelain",
@@ -821,7 +817,6 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
        if (ignore_untracked)
                argv[2] = "-uno";
 
-       memset(&cp, 0, sizeof(cp));
        cp.argv = argv;
        cp.env = local_repo_env;
        cp.git_cmd = 1;
@@ -862,7 +857,7 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
 
 int submodule_uses_gitfile(const char *path)
 {
-       struct child_process cp;
+       struct child_process cp = CHILD_PROCESS_INIT;
        const char *argv[] = {
                "submodule",
                "foreach",
@@ -883,7 +878,6 @@ int submodule_uses_gitfile(const char *path)
        strbuf_release(&buf);
 
        /* Now test that all nested submodules use a gitfile too */
-       memset(&cp, 0, sizeof(cp));
        cp.argv = argv;
        cp.env = local_repo_env;
        cp.git_cmd = 1;
@@ -901,7 +895,7 @@ int ok_to_remove_submodule(const char *path)
 {
        struct stat st;
        ssize_t len;
-       struct child_process cp;
+       struct child_process cp = CHILD_PROCESS_INIT;
        const char *argv[] = {
                "status",
                "--porcelain",
@@ -918,7 +912,6 @@ int ok_to_remove_submodule(const char *path)
        if (!submodule_uses_gitfile(path))
                return 0;
 
-       memset(&cp, 0, sizeof(cp));
        cp.argv = argv;
        cp.env = local_repo_env;
        cp.git_cmd = 1;
index 39e55a13c885399150094f9a2774f85e0acd63a6..8dc6939b9049baa32aca1200e36378e6e2296e9d 100755 (executable)
@@ -806,7 +806,7 @@ test_expect_success !MINGW 'quoting allows trailing whitespace' '
        test_cmp err.expect err
 '
 
-test_expect_success NOT_MINGW,NOT_CYGWIN 'correct handling of backslashes' '
+test_expect_success !MINGW,!CYGWIN 'correct handling of backslashes' '
        rm -rf whitespace &&
        mkdir whitespace &&
        >"whitespace/trailing 1  " &&
index 25dba008f3e4904cfe3100d9745a9b324622d779..ce92e6acad41712d6bc82b057858e7030c7ccde0 100755 (executable)
@@ -29,7 +29,7 @@ test_expect_success '0-length read, send along greeting' '
        test_cmp expect actual
 '
 
-test_expect_success NOT_MINGW 'read from file descriptor' '
+test_expect_success !MINGW 'read from file descriptor' '
        rm -f input &&
        echo hello >expect &&
        echo hello >input &&
index 6c33e28ee8df4d239dd6d1c1d98c324b01c70ed3..f9648a86426470785159b5132305a256c80b5ca4 100755 (executable)
@@ -8,7 +8,7 @@ cache-tree extension.
  . ./test-lib.sh
 
 cmp_cache_tree () {
-       test-dump-cache-tree >actual &&
+       test-dump-cache-tree | sed -e '/#(ref)/d' >actual &&
        sed "s/$_x40/SHA/" <actual >filtered &&
        test_cmp "$1" filtered
 }
@@ -16,15 +16,40 @@ cmp_cache_tree () {
 # We don't bother with actually checking the SHA1:
 # test-dump-cache-tree already verifies that all existing data is
 # correct.
-test_shallow_cache_tree () {
-       printf "SHA  (%d entries, 0 subtrees)\n" $(git ls-files|wc -l) >expect &&
+generate_expected_cache_tree_rec () {
+       dir="$1${1:+/}" &&
+       parent="$2" &&
+       # ls-files might have foo/bar, foo/bar/baz, and foo/bar/quux
+       # We want to count only foo because it's the only direct child
+       subtrees=$(git ls-files|grep /|cut -d / -f 1|uniq) &&
+       subtree_count=$(echo "$subtrees"|awk '$1 {++c} END {print c}') &&
+       entries=$(git ls-files|wc -l) &&
+       printf "SHA $dir (%d entries, %d subtrees)\n" "$entries" "$subtree_count" &&
+       for subtree in $subtrees
+       do
+               cd "$subtree"
+               generate_expected_cache_tree_rec "$dir$subtree" "$dir" || return 1
+               cd ..
+       done &&
+       dir=$parent
+}
+
+generate_expected_cache_tree () {
+       (
+               generate_expected_cache_tree_rec
+       )
+}
+
+test_cache_tree () {
+       generate_expected_cache_tree >expect &&
        cmp_cache_tree expect
 }
 
 test_invalid_cache_tree () {
-       echo "invalid                                   (0 subtrees)" >expect &&
-       printf "SHA #(ref)  (%d entries, 0 subtrees)\n" $(git ls-files|wc -l) >>expect &&
-       cmp_cache_tree expect
+       printf "invalid                                  %s ()\n" "" "$@" >expect &&
+       test-dump-cache-tree |
+       sed -n -e "s/[0-9]* subtrees//" -e '/#(ref)/d' -e '/^invalid /p' >actual &&
+       test_cmp expect actual
 }
 
 test_no_cache_tree () {
@@ -32,26 +57,59 @@ test_no_cache_tree () {
        cmp_cache_tree expect
 }
 
-test_expect_failure 'initial commit has cache-tree' '
+test_expect_success 'initial commit has cache-tree' '
        test_commit foo &&
-       test_shallow_cache_tree
+       test_cache_tree
 '
 
 test_expect_success 'read-tree HEAD establishes cache-tree' '
        git read-tree HEAD &&
-       test_shallow_cache_tree
+       test_cache_tree
 '
 
 test_expect_success 'git-add invalidates cache-tree' '
        test_when_finished "git reset --hard; git read-tree HEAD" &&
-       echo "I changed this file" > foo &&
+       echo "I changed this file" >foo &&
        git add foo &&
        test_invalid_cache_tree
 '
 
+test_expect_success 'git-add in subdir invalidates cache-tree' '
+       test_when_finished "git reset --hard; git read-tree HEAD" &&
+       mkdir dirx &&
+       echo "I changed this file" >dirx/foo &&
+       git add dirx/foo &&
+       test_invalid_cache_tree
+'
+
+cat >before <<\EOF
+SHA  (3 entries, 2 subtrees)
+SHA dir1/ (1 entries, 0 subtrees)
+SHA dir2/ (1 entries, 0 subtrees)
+EOF
+
+cat >expect <<\EOF
+invalid                                   (2 subtrees)
+invalid                                  dir1/ (0 subtrees)
+SHA dir2/ (1 entries, 0 subtrees)
+EOF
+
+test_expect_success 'git-add in subdir does not invalidate sibling cache-tree' '
+       git tag no-children &&
+       test_when_finished "git reset --hard no-children; git read-tree HEAD" &&
+       mkdir dir1 dir2 &&
+       test_commit dir1/a &&
+       test_commit dir2/b &&
+       echo "I changed this file" >dir1/a &&
+       cmp_cache_tree before &&
+       echo "I changed this file" >dir1/a &&
+       git add dir1/a &&
+       cmp_cache_tree expect
+'
+
 test_expect_success 'update-index invalidates cache-tree' '
        test_when_finished "git reset --hard; git read-tree HEAD" &&
-       echo "I changed this file" > foo &&
+       echo "I changed this file" >foo &&
        git update-index --add foo &&
        test_invalid_cache_tree
 '
@@ -59,7 +117,7 @@ test_expect_success 'update-index invalidates cache-tree' '
 test_expect_success 'write-tree establishes cache-tree' '
        test-scrap-cache-tree &&
        git write-tree &&
-       test_shallow_cache_tree
+       test_cache_tree
 '
 
 test_expect_success 'test-scrap-cache-tree works' '
@@ -70,24 +128,94 @@ test_expect_success 'test-scrap-cache-tree works' '
 
 test_expect_success 'second commit has cache-tree' '
        test_commit bar &&
-       test_shallow_cache_tree
+       test_cache_tree
+'
+
+test_expect_success 'commit --interactive gives cache-tree on partial commit' '
+       cat <<-\EOT >foo.c &&
+       int foo()
+       {
+               return 42;
+       }
+       int bar()
+       {
+               return 42;
+       }
+       EOT
+       git add foo.c &&
+       test_invalid_cache_tree &&
+       git commit -m "add a file" &&
+       test_cache_tree &&
+       cat <<-\EOT >foo.c &&
+       int foo()
+       {
+               return 43;
+       }
+       int bar()
+       {
+               return 44;
+       }
+       EOT
+       (echo p; echo 1; echo; echo s; echo n; echo y; echo q) |
+       git commit --interactive -m foo &&
+       test_cache_tree
+'
+
+test_expect_success 'commit in child dir has cache-tree' '
+       mkdir dir &&
+       >dir/child.t &&
+       git add dir/child.t &&
+       git commit -m dir/child.t &&
+       test_cache_tree
 '
 
 test_expect_success 'reset --hard gives cache-tree' '
        test-scrap-cache-tree &&
        git reset --hard &&
-       test_shallow_cache_tree
+       test_cache_tree
 '
 
 test_expect_success 'reset --hard without index gives cache-tree' '
        rm -f .git/index &&
        git reset --hard &&
-       test_shallow_cache_tree
+       test_cache_tree
 '
 
-test_expect_failure 'checkout gives cache-tree' '
+test_expect_success 'checkout gives cache-tree' '
+       git tag current &&
        git checkout HEAD^ &&
-       test_shallow_cache_tree
+       test_cache_tree
+'
+
+test_expect_success 'checkout -b gives cache-tree' '
+       git checkout current &&
+       git checkout -b prev HEAD^ &&
+       test_cache_tree
+'
+
+test_expect_success 'checkout -B gives cache-tree' '
+       git checkout current &&
+       git checkout -B prev HEAD^ &&
+       test_cache_tree
+'
+
+test_expect_success 'partial commit gives cache-tree' '
+       git checkout -b partial no-children &&
+       test_commit one &&
+       test_commit two &&
+       echo "some change" >one.t &&
+       git add one.t &&
+       echo "some other change" >two.t &&
+       git commit two.t -m partial &&
+       test_cache_tree
+'
+
+test_expect_success 'no phantom error when switching trees' '
+       mkdir newdir &&
+       >newdir/one &&
+       git add newdir/one &&
+       git checkout 2>errors &&
+       ! test -s errors
 '
 
 test_done
index 62c0d25af4ca1c8ef5d0d63b6e3ea329a6d75205..2edb4f2de5cc32d0f8847790d06a8de0c98d99c3 100755 (executable)
@@ -118,7 +118,7 @@ test_expect_success 'alias expansion' '
        )
 '
 
-test_expect_success NOT_MINGW '!alias expansion' '
+test_expect_success !MINGW '!alias expansion' '
        pwd >expect &&
        (
                git config alias.test-alias-directory !pwd &&
index aea493646e4400e733749768e48f2a3d1a470299..05a1e1d270d2f6254658607541f1b114299533e5 100755 (executable)
@@ -112,6 +112,20 @@ test_expect_success 'diff --raw' '
        git diff --raw HEAD^
 '
 
+test_expect_success 'diff --stat' '
+       git diff --stat HEAD^ HEAD
+'
+
+test_expect_success 'diff' '
+       git diff HEAD^ HEAD >actual &&
+       grep "Binary files.*differ" actual
+'
+
+test_expect_success 'diff --cached' '
+       git diff --cached HEAD^ >actual &&
+       grep "Binary files.*differ" actual
+'
+
 test_expect_success 'hash-object' '
        git hash-object large1
 '
@@ -163,4 +177,10 @@ test_expect_success 'zip achiving, deflate' '
        git archive --format=zip HEAD >/dev/null
 '
 
+test_expect_success 'fsck' '
+       test_must_fail git fsck 2>err &&
+       n=$(grep "error: attempting to allocate .* over limit" err | wc -l) &&
+       test "$n" -gt 1
+'
+
 test_done
index 3f80ff0c14c47b87bbbecb74d1951a1abe6bc5ba..938fc8bfd76c9889ebb2129642f878c9449acc9f 100755 (executable)
@@ -824,14 +824,14 @@ cat >expect <<\EOF
        trailingtilde = foo~
 EOF
 
-test_expect_success NOT_MINGW 'set --path' '
+test_expect_success !MINGW 'set --path' '
        rm -f .git/config &&
        git config --path path.home "~/" &&
        git config --path path.normal "/dev/null" &&
        git config --path path.trailingtilde "foo~" &&
        test_cmp expect .git/config'
 
-if test_have_prereq NOT_MINGW && test "${HOME+set}"
+if test_have_prereq !MINGW && test "${HOME+set}"
 then
        test_set_prereq HOMEVAR
 fi
@@ -854,7 +854,7 @@ cat >expect <<\EOF
 foo~
 EOF
 
-test_expect_success NOT_MINGW 'get --path copes with unset $HOME' '
+test_expect_success !MINGW 'get --path copes with unset $HOME' '
        (
                unset HOME;
                test_must_fail git config --get --path path.home \
@@ -1010,6 +1010,17 @@ test_expect_success 'git -c "key=value" support' '
        test_must_fail git -c name=value config core.name
 '
 
+# We just need a type-specifier here that cares about the
+# distinction internally between a NULL boolean and a real
+# string (because most of git's internal parsers do care).
+# Using "--path" works, but we do not otherwise care about
+# its semantics.
+test_expect_success 'git -c can represent empty string' '
+       echo >expect &&
+       git -c foo.empty= config --path foo.empty >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'key sanity-checking' '
        test_must_fail git config foo=bar &&
        test_must_fail git config foo=.bar &&
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
new file mode 100755 (executable)
index 0000000..ea0bce2
--- /dev/null
@@ -0,0 +1,221 @@
+#!/bin/sh
+
+test_description='Test git config-set API in different settings'
+
+. ./test-lib.sh
+
+# 'check_config get_* section.key value' verifies that the entry for
+# section.key is 'value'
+check_config () {
+       if test "$1" = expect_code
+       then
+               expect_code="$2" && shift && shift
+       else
+               expect_code=0
+       fi &&
+       op=$1 key=$2 && shift && shift &&
+       if test $# != 0
+       then
+               printf "%s\n" "$@"
+       fi >expect &&
+       test_expect_code $expect_code test-config "$op" "$key" >actual &&
+       test_cmp expect actual
+}
+
+test_expect_success 'setup default config' '
+       cat >.git/config <<\EOF
+       [case]
+               penguin = very blue
+               Movie = BadPhysics
+               UPPERCASE = true
+               MixedCase = true
+               my =
+               foo
+               baz = sam
+       [Cores]
+               WhatEver = Second
+               baz = bar
+       [cores]
+               baz = bat
+       [CORES]
+               baz = ball
+       [my "Foo bAr"]
+               hi = mixed-case
+       [my "FOO BAR"]
+               hi = upper-case
+       [my "foo bar"]
+               hi = lower-case
+       [case]
+               baz = bat
+               baz = hask
+       [lamb]
+               chop = 65
+               head = none
+       [goat]
+               legs = 4
+               head = true
+               skin = false
+               nose = 1
+               horns
+       EOF
+'
+
+test_expect_success 'get value for a simple key' '
+       check_config get_value case.penguin "very blue"
+'
+
+test_expect_success 'get value for a key with value as an empty string' '
+       check_config get_value case.my ""
+'
+
+test_expect_success 'get value for a key with value as NULL' '
+       check_config get_value case.foo "(NULL)"
+'
+
+test_expect_success 'upper case key' '
+       check_config get_value case.UPPERCASE "true" &&
+       check_config get_value case.uppercase "true"
+'
+
+test_expect_success 'mixed case key' '
+       check_config get_value case.MixedCase "true" &&
+       check_config get_value case.MIXEDCASE "true" &&
+       check_config get_value case.mixedcase "true"
+'
+
+test_expect_success 'key and value with mixed case' '
+       check_config get_value case.Movie "BadPhysics"
+'
+
+test_expect_success 'key with case sensitive subsection' '
+       check_config get_value "my.Foo bAr.hi" "mixed-case" &&
+       check_config get_value "my.FOO BAR.hi" "upper-case" &&
+       check_config get_value "my.foo bar.hi" "lower-case"
+'
+
+test_expect_success 'key with case insensitive section header' '
+       check_config get_value cores.baz "ball" &&
+       check_config get_value Cores.baz "ball" &&
+       check_config get_value CORES.baz "ball" &&
+       check_config get_value coreS.baz "ball"
+'
+
+test_expect_success 'key with case insensitive section header & variable' '
+       check_config get_value CORES.BAZ "ball" &&
+       check_config get_value cores.baz "ball" &&
+       check_config get_value cores.BaZ "ball" &&
+       check_config get_value cOreS.bAz "ball"
+'
+
+test_expect_success 'find value with misspelled key' '
+       check_config expect_code 1 get_value "my.fOo Bar.hi" "Value not found for \"my.fOo Bar.hi\""
+'
+
+test_expect_success 'find value with the highest priority' '
+       check_config get_value case.baz "hask"
+'
+
+test_expect_success 'find integer value for a key' '
+       check_config get_int lamb.chop 65
+'
+
+test_expect_success 'find string value for a key' '
+       check_config get_string case.baz hask &&
+       check_config expect_code 1 get_string case.ba "Value not found for \"case.ba\""
+'
+
+test_expect_success 'check line error when NULL string is queried' '
+       test_expect_code 128 test-config get_string case.foo 2>result &&
+       test_i18ngrep "fatal: .*case\.foo.*\.git/config.*line 7" result
+'
+
+test_expect_success 'find integer if value is non parse-able' '
+       check_config expect_code 128 get_int lamb.head
+'
+
+test_expect_success 'find bool value for the entered key' '
+       check_config get_bool goat.head 1 &&
+       check_config get_bool goat.skin 0 &&
+       check_config get_bool goat.nose 1 &&
+       check_config get_bool goat.horns 1 &&
+       check_config get_bool goat.legs 1
+'
+
+test_expect_success 'find multiple values' '
+       check_config get_value_multi case.baz sam bat hask
+'
+
+test_expect_success 'find value from a configset' '
+       cat >config2 <<-\EOF &&
+       [case]
+               baz = lama
+       [my]
+               new = silk
+       [case]
+               baz = ball
+       EOF
+       echo silk >expect &&
+       test-config configset_get_value my.new config2 .git/config >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'find value with highest priority from a configset' '
+       echo hask >expect &&
+       test-config configset_get_value case.baz config2 .git/config >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'find value_list for a key from a configset' '
+       cat >except <<-\EOF &&
+       sam
+       bat
+       hask
+       lama
+       ball
+       EOF
+       test-config configset_get_value case.baz config2 .git/config >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'proper error on non-existent files' '
+       echo "Error (-1) reading configuration file non-existent-file." >expect &&
+       test_expect_code 2 test-config configset_get_value foo.bar non-existent-file 2>actual &&
+       test_cmp expect actual
+'
+
+test_expect_success POSIXPERM,SANITY 'proper error on non-accessible files' '
+       chmod -r .git/config &&
+       test_when_finished "chmod +r .git/config" &&
+       echo "Error (-1) reading configuration file .git/config." >expect &&
+       test_expect_code 2 test-config configset_get_value foo.bar .git/config 2>actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'proper error on error in default config files' '
+       cp .git/config .git/config.old &&
+       test_when_finished "mv .git/config.old .git/config" &&
+       echo "[" >>.git/config &&
+       echo "fatal: bad config file line 35 in .git/config" >expect &&
+       test_expect_code 128 test-config get_value foo.bar 2>actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'proper error on error in custom config files' '
+       echo "[" >>syntax-error &&
+       echo "fatal: bad config file line 1 in syntax-error" >expect &&
+       test_expect_code 128 test-config configset_get_value foo.bar syntax-error 2>actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'check line errors for malformed values' '
+       mv .git/config .git/config.old &&
+       test_when_finished "mv .git/config.old .git/config" &&
+       cat >.git/config <<-\EOF &&
+       [alias]
+               br
+       EOF
+       test_expect_code 128 git br 2>result &&
+       test_i18ngrep "fatal: .*alias\.br.*\.git/config.*line 2" result
+'
+
+test_done
index 4bc7141226c802ca049a76e978b6196f9e9fd7ff..e5dc62e9efbf9c26bad93c7384f9fb9fa6a970e8 100755 (executable)
@@ -7,7 +7,7 @@ test_description='Test git check-ref-format'
 valid_ref() {
        prereq=
        case $1 in
-       [A-Z]*)
+       [A-Z!]*)
                prereq=$1
                shift
        esac
@@ -19,7 +19,7 @@ valid_ref() {
 invalid_ref() {
        prereq=
        case $1 in
-       [A-Z]*)
+       [A-Z!]*)
                prereq=$1
                shift
        esac
@@ -30,17 +30,17 @@ invalid_ref() {
 }
 
 invalid_ref ''
-invalid_ref NOT_MINGW '/'
-invalid_ref NOT_MINGW '/' --allow-onelevel
-invalid_ref NOT_MINGW '/' --normalize
-invalid_ref NOT_MINGW '/' '--allow-onelevel --normalize'
+invalid_ref !MINGW '/'
+invalid_ref !MINGW '/' --allow-onelevel
+invalid_ref !MINGW '/' --normalize
+invalid_ref !MINGW '/' '--allow-onelevel --normalize'
 valid_ref 'foo/bar/baz'
 valid_ref 'foo/bar/baz' --normalize
 invalid_ref 'refs///heads/foo'
 valid_ref 'refs///heads/foo' --normalize
 invalid_ref 'heads/foo/'
-invalid_ref NOT_MINGW '/heads/foo'
-valid_ref NOT_MINGW '/heads/foo' --normalize
+invalid_ref !MINGW '/heads/foo'
+valid_ref !MINGW '/heads/foo' --normalize
 invalid_ref '///heads/foo'
 valid_ref '///heads/foo' --normalize
 invalid_ref './foo'
@@ -120,14 +120,14 @@ invalid_ref "$ref" --refspec-pattern
 invalid_ref "$ref" '--refspec-pattern --allow-onelevel'
 
 ref='/foo'
-invalid_ref NOT_MINGW "$ref"
-invalid_ref NOT_MINGW "$ref" --allow-onelevel
-invalid_ref NOT_MINGW "$ref" --refspec-pattern
-invalid_ref NOT_MINGW "$ref" '--refspec-pattern --allow-onelevel'
-invalid_ref NOT_MINGW "$ref" --normalize
-valid_ref NOT_MINGW "$ref" '--allow-onelevel --normalize'
-invalid_ref NOT_MINGW "$ref" '--refspec-pattern --normalize'
-valid_ref NOT_MINGW "$ref" '--refspec-pattern --allow-onelevel --normalize'
+invalid_ref !MINGW "$ref"
+invalid_ref !MINGW "$ref" --allow-onelevel
+invalid_ref !MINGW "$ref" --refspec-pattern
+invalid_ref !MINGW "$ref" '--refspec-pattern --allow-onelevel'
+invalid_ref !MINGW "$ref" --normalize
+valid_ref !MINGW "$ref" '--allow-onelevel --normalize'
+invalid_ref !MINGW "$ref" '--refspec-pattern --normalize'
+valid_ref !MINGW "$ref" '--refspec-pattern --allow-onelevel --normalize'
 
 test_expect_success "check-ref-format --branch @{-1}" '
        T=$(git write-tree) &&
@@ -162,7 +162,7 @@ test_expect_success 'check-ref-format --branch from subdir' '
 valid_ref_normalized() {
        prereq=
        case $1 in
-       [A-Z]*)
+       [A-Z!]*)
                prereq=$1
                shift
        esac
@@ -174,7 +174,7 @@ valid_ref_normalized() {
 invalid_ref_normalized() {
        prereq=
        case $1 in
-       [A-Z]*)
+       [A-Z!]*)
                prereq=$1
                shift
        esac
@@ -185,10 +185,10 @@ invalid_ref_normalized() {
 
 valid_ref_normalized 'heads/foo' 'heads/foo'
 valid_ref_normalized 'refs///heads/foo' 'refs/heads/foo'
-valid_ref_normalized NOT_MINGW '/heads/foo' 'heads/foo'
+valid_ref_normalized !MINGW '/heads/foo' 'heads/foo'
 valid_ref_normalized '///heads/foo' 'heads/foo'
 invalid_ref_normalized 'foo'
-invalid_ref_normalized NOT_MINGW '/foo'
+invalid_ref_normalized !MINGW '/foo'
 invalid_ref_normalized 'heads/foo/../bar'
 invalid_ref_normalized 'heads/./foo'
 invalid_ref_normalized 'heads\foo'
index 1a2080e3dca272b6ed40739a7539f01f4f6ae65c..3a017bf437395526cf54403d4ea1db36a3cff0b3 100755 (executable)
@@ -151,4 +151,11 @@ test_expect_success 'delete ref while another dangling packed ref' '
        test_cmp /dev/null result
 '
 
+test_expect_success 'pack ref directly below refs/' '
+       git update-ref refs/top HEAD &&
+       git pack-refs --all --prune &&
+       grep refs/top .git/packed-refs &&
+       test_path_is_missing .git/refs/top
+'
+
 test_done
index 55c8a2f57677085fe1185cd2e3e6d9a2021fd744..a392f3d1d66757361ff9fc4e26f4125da5ab0a4f 100755 (executable)
@@ -54,7 +54,7 @@ test_expect_success setup '
        git add yours &&
        git commit -s -m "Second on side" &&
 
-       if test_have_prereq NOT_MINGW
+       if test_have_prereq !MINGW
        then
                # the second one on the side branch is ISO-8859-1
                git config i18n.commitencoding ISO8859-1 &&
@@ -122,7 +122,7 @@ test_expect_success 'rebase (U/L)' '
        check_encoding 2
 '
 
-test_expect_success NOT_MINGW 'rebase (L/L)' '
+test_expect_success !MINGW 'rebase (L/L)' '
        # In this test we want ISO-8859-1 encoded commits as the result
        git config i18n.commitencoding ISO8859-1 &&
        git config i18n.logoutputencoding ISO8859-1 &&
@@ -134,7 +134,7 @@ test_expect_success NOT_MINGW 'rebase (L/L)' '
        check_encoding 2 8859
 '
 
-test_expect_success NOT_MINGW 'rebase (L/U)' '
+test_expect_success !MINGW 'rebase (L/U)' '
        # This is pathological -- use UTF-8 as intermediate form
        # to get ISO-8859-1 results.
        git config i18n.commitencoding ISO8859-1 &&
@@ -162,7 +162,7 @@ test_expect_success 'cherry-pick(U/U)' '
        check_encoding 3
 '
 
-test_expect_success NOT_MINGW 'cherry-pick(L/L)' '
+test_expect_success !MINGW 'cherry-pick(L/L)' '
        # Both the commitencoding and logoutputencoding is set to ISO-8859-1
 
        git config i18n.commitencoding ISO8859-1 &&
@@ -192,7 +192,7 @@ test_expect_success 'cherry-pick(U/L)' '
        check_encoding 3
 '
 
-test_expect_success NOT_MINGW 'cherry-pick(L/U)' '
+test_expect_success !MINGW 'cherry-pick(L/U)' '
        # Again, the commitencoding is set to ISO-8859-1 but
        # logoutputencoding is set to UTF-8.
 
index 5b79b216e2e3bb837e58828a2e9a292cb2d7cc53..1e29962fad30edb263cd07b6586f1b1a962c88cf 100755 (executable)
@@ -685,4 +685,46 @@ test_expect_success 'handle stash specification with spaces' '
        grep pig file
 '
 
+test_expect_success 'setup stash with index and worktree changes' '
+       git stash clear &&
+       git reset --hard &&
+       echo index >file &&
+       git add file &&
+       echo working >file &&
+       git stash
+'
+
+test_expect_success 'stash list implies --first-parent -m' '
+       cat >expect <<-\EOF &&
+       stash@{0}: WIP on master: b27a2bc subdir
+
+       diff --git a/file b/file
+       index 257cc56..d26b33d 100644
+       --- a/file
+       +++ b/file
+       @@ -1 +1 @@
+       -foo
+       +working
+       EOF
+       git stash list -p >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'stash list --cc shows combined diff' '
+       cat >expect <<-\EOF &&
+       stash@{0}: WIP on master: b27a2bc subdir
+
+       diff --cc file
+       index 257cc56,9015a7a..d26b33d
+       --- a/file
+       +++ b/file
+       @@@ -1,1 -1,1 +1,1 @@@
+       - foo
+        -index
+       ++working
+       EOF
+       git stash list -p --cc >actual &&
+       test_cmp expect actual
+'
+
 test_done
index cd0454356a6ea26c630f76748dd2c4f73bed8526..741e0803c1ac0a418c98c7eee9cb449a7c60da06 100755 (executable)
@@ -79,7 +79,7 @@ test_expect_success 'non-integer config parsing' '
 test_expect_success 'negative integer config parsing' '
        git config diff.context -1 &&
        test_must_fail git diff 2>output &&
-       test_i18ngrep "bad config file" output
+       test_i18ngrep "bad config variable" output
 '
 
 test_expect_success '-U0 is valid, so is diff.context=0' '
index c393be691be42a0b0a982c07ffeee489d4075bce..a9a05838119c85bc017f1404b134d393029843b2 100755 (executable)
@@ -159,4 +159,21 @@ test_expect_success 'same but with traditional patch input of depth 2' '
        check_result sub/file1
 '
 
+test_expect_success 'in subdir with traditional patch input' '
+       cd "$D" &&
+       git config apply.whitespace strip &&
+       cat >.gitattributes <<-EOF &&
+       /* whitespace=blank-at-eol
+       sub/* whitespace=-blank-at-eol
+       EOF
+       rm -f sub/file1 &&
+       cp saved sub/file1 &&
+       git update-index --refresh &&
+
+       cd sub &&
+       git apply ../gpatch.file &&
+       echo "B " >expect &&
+       test_cmp expect file1
+'
+
 test_done
index 5d0c5983381b4072d915de0f8d75053b19172d66..c6474de4c8c30eba9b5375f6c4e176e67c1fd001 100755 (executable)
@@ -512,4 +512,15 @@ test_expect_success 'whitespace=fix to expand' '
        git -c core.whitespace=tab-in-indent apply --whitespace=fix patch
 '
 
+test_expect_success 'whitespace check skipped for excluded paths' '
+       git config core.whitespace blank-at-eol &&
+       >used &&
+       >unused &&
+       git add used unused &&
+       echo "used" >used &&
+       echo "unused " >unused &&
+       git diff-files -p used unused >patch &&
+       git apply --include=used --stat --whitespace=error <patch
+'
+
 test_done
index 565c020c45434bf151d7a142ebe1a1cca3299ab4..7600a3e3e8f4fab47abd68a29bb06defb6bbce02 100755 (executable)
@@ -93,7 +93,7 @@ test_expect_success 'output from user-defined format is re-wrapped' '
        test_cmp expect log.predictable
 '
 
-test_expect_success NOT_MINGW 'shortlog wrapping' '
+test_expect_success !MINGW 'shortlog wrapping' '
        cat >expect <<\EOF &&
 A U Thor (5):
       Test
@@ -114,7 +114,7 @@ EOF
        test_cmp expect out
 '
 
-test_expect_success NOT_MINGW 'shortlog from non-git directory' '
+test_expect_success !MINGW 'shortlog from non-git directory' '
        git log HEAD >log &&
        GIT_DIR=non-existing git shortlog -w <log >out &&
        test_cmp expect out
@@ -159,7 +159,7 @@ $DSCHO (2):
 
 EOF
 
-test_expect_success NOT_MINGW 'shortlog encoding' '
+test_expect_success !MINGW 'shortlog encoding' '
        git reset --hard "$commit" &&
        git config --unset i18n.commitencoding &&
        echo 2 > a1 &&
index 349c531989326eacfe1e1448bfed740d7fd4bd8e..de0cc4a0fd5fe37bb36a3268182d95de3589f4b4 100755 (executable)
@@ -431,6 +431,13 @@ EOF
        test_cmp expected actual
 '
 
+test_expect_success 'strbuf_utf8_replace() not producing NUL' '
+       git log --color --pretty="tformat:%<(10,trunc)%s%>>(10,ltrunc)%C(auto)%d" |
+               test_decode_color |
+               nul_to_q >actual &&
+       ! grep Q actual
+'
+
 # get new digests (with no abbreviations)
 head1=$(git rev-parse --verify HEAD~0) &&
 head2=$(git rev-parse --verify HEAD~1) &&
index 9110404e55eaacd10a73d7d4b2bae7f288a031b1..e585fe6129b7af264427d8af46de21cb08efad7f 100755 (executable)
@@ -34,7 +34,7 @@ test_expect_success 'log --grep searches in log output encoding (utf8)' '
        test_cmp expect actual
 '
 
-test_expect_success NOT_MINGW 'log --grep searches in log output encoding (latin1)' '
+test_expect_success !MINGW 'log --grep searches in log output encoding (latin1)' '
        cat >expect <<-\EOF &&
        latin1
        utf8
@@ -43,7 +43,7 @@ test_expect_success NOT_MINGW 'log --grep searches in log output encoding (latin
        test_cmp expect actual
 '
 
-test_expect_success NOT_MINGW 'log --grep does not find non-reencoded values (utf8)' '
+test_expect_success !MINGW 'log --grep does not find non-reencoded values (utf8)' '
        >expect &&
        git log --encoding=utf8 --format=%s --grep=$latin1_e >actual &&
        test_cmp expect actual
index 305bcac6b765111106887d4d24d99657c0554b5b..83d20c4ba9640fff27777917da0342940c33e0e3 100755 (executable)
@@ -113,4 +113,9 @@ test_expect_success 'archive empty subtree by direct pathspec' '
        check_dir extract sub
 '
 
+test_expect_success 'archive applies umask even for pax headers' '
+       git archive --format=tar HEAD >archive.tar &&
+       ! grep 0666 archive.tar
+'
+
 test_done
index 5e67035be800b5cbec5a99dd9e3e458a343440df..e4f10c0f68b94bfa719c3d208f622541506c86b3 100755 (executable)
@@ -318,7 +318,7 @@ test_expect_success 'clone myhost:src uses ssh' '
        expect_ssh myhost src
 '
 
-test_expect_success NOT_MINGW,NOT_CYGWIN 'clone local path foo:bar' '
+test_expect_success !MINGW,!CYGWIN 'clone local path foo:bar' '
        cp -R src "foo:bar" &&
        git clone "foo:bar" foobar &&
        expect_ssh none
@@ -339,7 +339,7 @@ test_clone_url () {
        expect_ssh "$2" "$3"
 }
 
-test_expect_success NOT_MINGW 'clone c:temp is ssl' '
+test_expect_success !MINGW 'clone c:temp is ssl' '
        test_clone_url c:temp c temp
 '
 
index a45c31692e17218988e6619742c366043e426039..348d9b3bc7ad3ea512f68b6200481c9f6b90d792 100755 (executable)
@@ -14,7 +14,10 @@ test_expect_success 'setup' '
        git tag -d third
 '
 
-test_expect_success 'tags can be excluded by rev-list options' '
+test_expect_success 'annotated tags can be excluded by rev-list options' '
+       git bundle create bundle --all --since=7.Apr.2005.15:14:00.-0700 &&
+       git ls-remote bundle > output &&
+       grep tag output &&
        git bundle create bundle --all --since=7.Apr.2005.15:16:00.-0700 &&
        git ls-remote bundle > output &&
        ! grep tag output
index 0c9ec0ad44ef4e3239e67a0c9e9ecc1340dcee8a..eae9e5a937150d60002620c8b29293f4d7ed122f 100755 (executable)
@@ -223,6 +223,23 @@ test_expect_success 'checkout --merge --conflict=diff3 <branch>' '
        test_cmp two expect
 '
 
+test_expect_success 'switch to another branch while carrying a deletion' '
+
+       git checkout -f master && git reset --hard && git clean -f &&
+       git rm two &&
+
+       test_must_fail git checkout simple 2>errs &&
+       test_i18ngrep overwritten errs &&
+
+       git checkout --merge simple 2>errs &&
+       test_i18ngrep ! overwritten errs &&
+       git ls-files -u &&
+       test_must_fail git cat-file -t :0:two &&
+       test "$(git cat-file -t :1:two)" = blob &&
+       test "$(git cat-file -t :2:two)" = blob &&
+       test_must_fail git cat-file -t :3:two
+'
+
 test_expect_success 'checkout to detach HEAD (with advice declined)' '
 
        git config advice.detachedHead false &&
diff --git a/t/t7515-status-symlinks.sh b/t/t7515-status-symlinks.sh
new file mode 100755 (executable)
index 0000000..9f989be
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+test_description='git status and symlinks'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       echo .gitignore >.gitignore &&
+       echo actual >>.gitignore &&
+       echo expect >>.gitignore &&
+       mkdir dir &&
+       echo x >dir/file1 &&
+       echo y >dir/file2 &&
+       git add dir &&
+       git commit -m initial &&
+       git tag initial
+'
+
+test_expect_success SYMLINKS 'symlink to a directory' '
+       test_when_finished "rm symlink" &&
+       ln -s dir symlink &&
+       echo "?? symlink" >expect &&
+       git status --porcelain >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success SYMLINKS 'symlink replacing a directory' '
+       test_when_finished "rm -rf copy && git reset --hard initial" &&
+       mkdir copy &&
+       cp dir/file1 copy/file1 &&
+       echo "changed in copy" >copy/file2 &&
+       git add copy &&
+       git commit -m second &&
+       rm -rf copy &&
+       ln -s dir copy &&
+       echo " D copy/file1" >expect &&
+       echo " D copy/file2" >>expect &&
+       echo "?? copy" >>expect &&
+       git status --porcelain >actual &&
+       test_cmp expect actual
+'
+
+test_done
index a6e73d063544a5856647d5cb9dc1260a0454f7ff..847d098c094566aafd8dd05fd3962e28f113360e 100755 (executable)
@@ -33,7 +33,7 @@ author $SJIS_NAME
 summary $SJIS_MSG
 EOF
 
-test_expect_success NOT_MINGW \
+test_expect_success !MINGW \
        'blame respects i18n.commitencoding' '
        git blame --incremental file | \
                egrep "^(author|summary) " > actual &&
@@ -49,7 +49,7 @@ author $EUC_JAPAN_NAME
 summary $EUC_JAPAN_MSG
 EOF
 
-test_expect_success NOT_MINGW \
+test_expect_success !MINGW \
        'blame respects i18n.logoutputencoding' '
        git config i18n.logoutputencoding eucJP &&
        git blame --incremental file | \
@@ -66,7 +66,7 @@ author $UTF8_NAME
 summary $UTF8_MSG
 EOF
 
-test_expect_success NOT_MINGW \
+test_expect_success !MINGW \
        'blame respects --encoding=UTF-8' '
        git blame --incremental --encoding=UTF-8 file | \
                egrep "^(author|summary) " > actual &&
@@ -82,7 +82,7 @@ author $UTF8_NAME
 summary $UTF8_MSG
 EOF
 
-test_expect_success NOT_MINGW \
+test_expect_success !MINGW \
        'blame respects --encoding=none' '
        git blame --incremental --encoding=none file | \
                egrep "^(author|summary) " > actual &&
index ff19695e776f803aef03a18e70067c89aa3be218..f16f3234a1acb9953ba33578b6cb689e2583ea80 100755 (executable)
@@ -74,6 +74,36 @@ test_expect_success 'info .' "
        test_cmp_info expected.info-dot actual.info-dot
        "
 
+test_expect_success 'info $(pwd)' '
+       (cd svnwc; svn info "$(pwd)") >expected.info-pwd &&
+       (cd gitwc; git svn info "$(pwd)") >actual.info-pwd &&
+       grep -v ^Path: <expected.info-pwd >expected.info-np &&
+       grep -v ^Path: <actual.info-pwd >actual.info-np &&
+       test_cmp_info expected.info-np actual.info-np &&
+       test "$(sed -ne \"/^Path:/ s!/svnwc!!\" <expected.info-pwd)" = \
+            "$(sed -ne \"/^Path:/ s!/gitwc!!\" <actual.info-pwd)"
+       '
+
+test_expect_success 'info $(pwd)/../___wc' '
+       (cd svnwc; svn info "$(pwd)/../svnwc") >expected.info-pwd &&
+       (cd gitwc; git svn info "$(pwd)/../gitwc") >actual.info-pwd &&
+       grep -v ^Path: <expected.info-pwd >expected.info-np &&
+       grep -v ^Path: <actual.info-pwd >actual.info-np &&
+       test_cmp_info expected.info-np actual.info-np &&
+       test "$(sed -ne \"/^Path:/ s!/svnwc!!\" <expected.info-pwd)" = \
+            "$(sed -ne \"/^Path:/ s!/gitwc!!\" <actual.info-pwd)"
+       '
+
+test_expect_success 'info $(pwd)/../___wc//file' '
+       (cd svnwc; svn info "$(pwd)/../svnwc//file") >expected.info-pwd &&
+       (cd gitwc; git svn info "$(pwd)/../gitwc//file") >actual.info-pwd &&
+       grep -v ^Path: <expected.info-pwd >expected.info-np &&
+       grep -v ^Path: <actual.info-pwd >actual.info-np &&
+       test_cmp_info expected.info-np actual.info-np &&
+       test "$(sed -ne \"/^Path:/ s!/svnwc!!\" <expected.info-pwd)" = \
+            "$(sed -ne \"/^Path:/ s!/gitwc!!\" <actual.info-pwd)"
+       '
+
 test_expect_success 'info --url .' '
        test "$(cd gitwc; git svn info --url .)" = "$quoted_svnrepo"
        '
index 5fc9ef262ac1297d9442ed08208cb183ecc0e5c1..99f51614ad9ec3de8abf272d6fc6a778707a2292 100755 (executable)
@@ -2336,7 +2336,7 @@ test_expect_success 'R: cat-blob-fd must be a nonnegative integer' '
        test_must_fail git fast-import --cat-blob-fd=-1 </dev/null
 '
 
-test_expect_success NOT_MINGW 'R: print old blob' '
+test_expect_success !MINGW 'R: print old blob' '
        blob=$(echo "yes it can" | git hash-object -w --stdin) &&
        cat >expect <<-EOF &&
        ${blob} blob 11
@@ -2348,7 +2348,7 @@ test_expect_success NOT_MINGW 'R: print old blob' '
        test_cmp expect actual
 '
 
-test_expect_success NOT_MINGW 'R: in-stream cat-blob-fd not respected' '
+test_expect_success !MINGW 'R: in-stream cat-blob-fd not respected' '
        echo hello >greeting &&
        blob=$(git hash-object -w greeting) &&
        cat >expect <<-EOF &&
@@ -2369,7 +2369,7 @@ test_expect_success NOT_MINGW 'R: in-stream cat-blob-fd not respected' '
        test_cmp expect actual.1
 '
 
-test_expect_success NOT_MINGW 'R: print new blob' '
+test_expect_success !MINGW 'R: print new blob' '
        blob=$(echo "yep yep yep" | git hash-object --stdin) &&
        cat >expect <<-EOF &&
        ${blob} blob 12
@@ -2387,7 +2387,7 @@ test_expect_success NOT_MINGW 'R: print new blob' '
        test_cmp expect actual
 '
 
-test_expect_success NOT_MINGW 'R: print new blob by sha1' '
+test_expect_success !MINGW 'R: print new blob by sha1' '
        blob=$(echo "a new blob named by sha1" | git hash-object --stdin) &&
        cat >expect <<-EOF &&
        ${blob} blob 25
index 23a827fa77d0a5d527cef29a15a205ee14d68e27..897b3c3034efcab3af88d8eddc4670e274361dd5 100755 (executable)
@@ -365,7 +365,7 @@ test_expect_success 'wildcard files submit back to p4, client-spec case' '
        (
                cd "$git" &&
                echo git-wild-hash >dir1/git-wild#hash &&
-               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               if test_have_prereq !MINGW,!CYGWIN
                then
                        echo git-wild-star >dir1/git-wild\*star
                fi &&
@@ -379,7 +379,7 @@ test_expect_success 'wildcard files submit back to p4, client-spec case' '
        (
                cd "$cli" &&
                test_path_is_file dir1/git-wild#hash &&
-               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               if test_have_prereq !MINGW,!CYGWIN
                then
                        test_path_is_file dir1/git-wild\*star
                fi &&
index c7472cbf54584c7610094677693114d41b422afe..0206771fbb91b734a626e628b21786805ebcfa22 100755 (executable)
@@ -14,7 +14,7 @@ test_expect_success 'add p4 files with wildcards in the names' '
                printf "file2\nhas\nsome\nrandom\ntext\n" >file2 &&
                p4 add file2 &&
                echo file-wild-hash >file-wild#hash &&
-               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               if test_have_prereq !MINGW,!CYGWIN
                then
                        echo file-wild-star >file-wild\*star
                fi &&
@@ -31,7 +31,7 @@ test_expect_success 'wildcard files git p4 clone' '
        (
                cd "$git" &&
                test -f file-wild#hash &&
-               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               if test_have_prereq !MINGW,!CYGWIN
                then
                        test -f file-wild\*star
                fi &&
@@ -46,7 +46,7 @@ test_expect_success 'wildcard files submit back to p4, add' '
        (
                cd "$git" &&
                echo git-wild-hash >git-wild#hash &&
-               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               if test_have_prereq !MINGW,!CYGWIN
                then
                        echo git-wild-star >git-wild\*star
                fi &&
@@ -60,7 +60,7 @@ test_expect_success 'wildcard files submit back to p4, add' '
        (
                cd "$cli" &&
                test_path_is_file git-wild#hash &&
-               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               if test_have_prereq !MINGW,!CYGWIN
                then
                        test_path_is_file git-wild\*star
                fi &&
@@ -75,7 +75,7 @@ test_expect_success 'wildcard files submit back to p4, modify' '
        (
                cd "$git" &&
                echo new-line >>git-wild#hash &&
-               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               if test_have_prereq !MINGW,!CYGWIN
                then
                        echo new-line >>git-wild\*star
                fi &&
@@ -89,7 +89,7 @@ test_expect_success 'wildcard files submit back to p4, modify' '
        (
                cd "$cli" &&
                test_line_count = 2 git-wild#hash &&
-               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               if test_have_prereq !MINGW,!CYGWIN
                then
                        test_line_count = 2 git-wild\*star
                fi &&
@@ -152,7 +152,7 @@ test_expect_success 'wildcard files submit back to p4, delete' '
        (
                cd "$cli" &&
                test_path_is_missing git-wild#hash &&
-               if test_have_prereq NOT_MINGW NOT_CYGWIN
+               if test_have_prereq !MINGW,!CYGWIN
                then
                        test_path_is_missing git-wild\*star
                fi &&
index 1243d96092ad5c6a66d66ee9debc399649ffa0a2..4cff6a760fc27b4f4f87c5f0387e34b3039e5518 100755 (executable)
@@ -417,7 +417,7 @@ test_expect_success 'cleanup chmod after submit cancel' '
                ! p4 fstat -T action text &&
                test_path_is_file text+x &&
                ! p4 fstat -T action text+x &&
-               if test_have_prereq NOT_CYGWIN
+               if test_have_prereq !CYGWIN
                then
                        stat --format=%A text | egrep ^-r-- &&
                        stat --format=%A text+x | egrep ^-r-x
index b1bc65bfb564ca85d35c42071f825360d1998392..2b525a8e1d19cd11fea0ba06372111306ce7bf41 100644 (file)
@@ -870,7 +870,6 @@ case $(uname -s) in
        # backslashes in pathspec are converted to '/'
        # exec does not inherit the PID
        test_set_prereq MINGW
-       test_set_prereq NOT_CYGWIN
        test_set_prereq SED_STRIPS_CR
        test_set_prereq GREP_STRIPS_CR
        GIT_TEST_CMP=mingw_test_cmp
@@ -878,7 +877,6 @@ case $(uname -s) in
 *CYGWIN*)
        test_set_prereq POSIXPERM
        test_set_prereq EXECKEEPSPID
-       test_set_prereq NOT_MINGW
        test_set_prereq CYGWIN
        test_set_prereq SED_STRIPS_CR
        test_set_prereq GREP_STRIPS_CR
@@ -887,8 +885,6 @@ case $(uname -s) in
        test_set_prereq POSIXPERM
        test_set_prereq BSLASHPSPEC
        test_set_prereq EXECKEEPSPID
-       test_set_prereq NOT_MINGW
-       test_set_prereq NOT_CYGWIN
        ;;
 esac
 
diff --git a/test-config.c b/test-config.c
new file mode 100644 (file)
index 0000000..6a77552
--- /dev/null
@@ -0,0 +1,152 @@
+#include "cache.h"
+#include "string-list.h"
+
+/*
+ * This program exposes the C API of the configuration mechanism
+ * as a set of simple commands in order to facilitate testing.
+ *
+ * Reads stdin and prints result of command to stdout:
+ *
+ * get_value -> prints the value with highest priority for the entered key
+ *
+ * get_value_multi -> prints all values for the entered key in increasing order
+ *                  of priority
+ *
+ * get_int -> print integer value for the entered key or die
+ *
+ * get_bool -> print bool value for the entered key or die
+ *
+ * get_string -> print string value for the entered key or die
+ *
+ * configset_get_value -> returns value with the highest priority for the entered key
+ *                     from a config_set constructed from files entered as arguments.
+ *
+ * configset_get_value_multi -> returns value_list for the entered key sorted in
+ *                             ascending order of priority from a config_set
+ *                             constructed from files entered as arguments.
+ *
+ * Examples:
+ *
+ * To print the value with highest priority for key "foo.bAr Baz.rock":
+ *     test-config get_value "foo.bAr Baz.rock"
+ *
+ */
+
+
+int main(int argc, char **argv)
+{
+       int i, val;
+       const char *v;
+       const struct string_list *strptr;
+       struct config_set cs;
+       git_configset_init(&cs);
+
+       if (argc < 2) {
+               fprintf(stderr, "Please, provide a command name on the command-line\n");
+               goto exit1;
+       } else if (argc == 3 && !strcmp(argv[1], "get_value")) {
+               if (!git_config_get_value(argv[2], &v)) {
+                       if (!v)
+                               printf("(NULL)\n");
+                       else
+                               printf("%s\n", v);
+                       goto exit0;
+               } else {
+                       printf("Value not found for \"%s\"\n", argv[2]);
+                       goto exit1;
+               }
+       } else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
+               strptr = git_config_get_value_multi(argv[2]);
+               if (strptr) {
+                       for (i = 0; i < strptr->nr; i++) {
+                               v = strptr->items[i].string;
+                               if (!v)
+                                       printf("(NULL)\n");
+                               else
+                                       printf("%s\n", v);
+                       }
+                       goto exit0;
+               } else {
+                       printf("Value not found for \"%s\"\n", argv[2]);
+                       goto exit1;
+               }
+       } else if (argc == 3 && !strcmp(argv[1], "get_int")) {
+               if (!git_config_get_int(argv[2], &val)) {
+                       printf("%d\n", val);
+                       goto exit0;
+               } else {
+                       printf("Value not found for \"%s\"\n", argv[2]);
+                       goto exit1;
+               }
+       } else if (argc == 3 && !strcmp(argv[1], "get_bool")) {
+               if (!git_config_get_bool(argv[2], &val)) {
+                       printf("%d\n", val);
+                       goto exit0;
+               } else {
+                       printf("Value not found for \"%s\"\n", argv[2]);
+                       goto exit1;
+               }
+       } else if (argc == 3 && !strcmp(argv[1], "get_string")) {
+               if (!git_config_get_string_const(argv[2], &v)) {
+                       printf("%s\n", v);
+                       goto exit0;
+               } else {
+                       printf("Value not found for \"%s\"\n", argv[2]);
+                       goto exit1;
+               }
+       } else if (!strcmp(argv[1], "configset_get_value")) {
+               for (i = 3; i < argc; i++) {
+                       int err;
+                       if ((err = git_configset_add_file(&cs, argv[i]))) {
+                               fprintf(stderr, "Error (%d) reading configuration file %s.\n", err, argv[i]);
+                               goto exit2;
+                       }
+               }
+               if (!git_configset_get_value(&cs, argv[2], &v)) {
+                       if (!v)
+                               printf("(NULL)\n");
+                       else
+                               printf("%s\n", v);
+                       goto exit0;
+               } else {
+                       printf("Value not found for \"%s\"\n", argv[2]);
+                       goto exit1;
+               }
+       } else if (!strcmp(argv[1], "configset_get_value_multi")) {
+               for (i = 3; i < argc; i++) {
+                       int err;
+                       if ((err = git_configset_add_file(&cs, argv[i]))) {
+                               fprintf(stderr, "Error (%d) reading configuration file %s.\n", err, argv[i]);
+                               goto exit2;
+                       }
+               }
+               strptr = git_configset_get_value_multi(&cs, argv[2]);
+               if (strptr) {
+                       for (i = 0; i < strptr->nr; i++) {
+                               v = strptr->items[i].string;
+                               if (!v)
+                                       printf("(NULL)\n");
+                               else
+                                       printf("%s\n", v);
+                       }
+                       goto exit0;
+               } else {
+                       printf("Value not found for \"%s\"\n", argv[2]);
+                       goto exit1;
+               }
+       }
+
+       die("%s: Please check the syntax and the function name", argv[0]);
+
+exit0:
+       git_configset_clear(&cs);
+       return 0;
+
+exit1:
+       git_configset_clear(&cs);
+       return 1;
+
+exit2:
+       git_configset_clear(&cs);
+       return 2;
+}
index 330ba4f4dd23e2cf21acbe8a7023eaca4ec09afe..54c0872fcb18edb4ca28a63fdfd4be3a17df388e 100644 (file)
@@ -26,16 +26,16 @@ static int dump_cache_tree(struct cache_tree *it,
                return 0;
 
        if (it->entry_count < 0) {
+               /* invalid */
                dump_one(it, pfx, "");
                dump_one(ref, pfx, "#(ref) ");
-               if (it->subtree_nr != ref->subtree_nr)
-                       errs = 1;
        }
        else {
                dump_one(it, pfx, "");
                if (hashcmp(it->sha1, ref->sha1) ||
                    ref->entry_count != it->entry_count ||
                    ref->subtree_nr != it->subtree_nr) {
+                       /* claims to be valid but is lying */
                        dump_one(ref, pfx, "#(ref) ");
                        errs = 1;
                }
index 37918e15f5ce06d0079ce09ae1a7be7b14533c48..89c7de2c600ce2781ce666324e703d555937740a 100644 (file)
@@ -15,9 +15,7 @@
 
 int main(int argc, char **argv)
 {
-       struct child_process proc;
-
-       memset(&proc, 0, sizeof(proc));
+       struct child_process proc = CHILD_PROCESS_INIT;
 
        if (argc < 3)
                return 1;
index 93525eb7be48eb11c242200827a7f6f0706ee241..56881a032471752ca16880d98ea1510e16d38eed 100644 (file)
@@ -3,7 +3,7 @@
 
 int main(int argc, char **argv)
 {
-       struct child_process cp;
+       struct child_process cp = CHILD_PROCESS_INIT;
        int nogit = 0;
 
        setup_git_directory_gently(&nogit);
@@ -13,7 +13,6 @@ int main(int argc, char **argv)
                setup_work_tree();
                argv++;
        }
-       memset(&cp, 0, sizeof(cp));
        cp.git_cmd = 1;
        cp.argv = (const char **)argv + 1;
        return run_command(&cp);
diff --git a/trace.c b/trace.c
index e583dc63bb8d7062f8b735e701978574e9fcbf25..54aaee58183f880365caa1986824054a4533797e 100644 (file)
--- a/trace.c
+++ b/trace.c
@@ -298,13 +298,12 @@ void trace_repo_setup(const char *prefix)
 {
        static struct trace_key key = TRACE_KEY_INIT(SETUP);
        const char *git_work_tree;
-       char cwd[PATH_MAX];
+       char *cwd;
 
        if (!trace_want(&key))
                return;
 
-       if (!getcwd(cwd, PATH_MAX))
-               die("Unable to get current working directory");
+       cwd = xgetcwd();
 
        if (!(git_work_tree = get_git_work_tree()))
                git_work_tree = "(null)";
@@ -316,6 +315,8 @@ void trace_repo_setup(const char *prefix)
        trace_printf_key(&key, "setup: worktree: %s\n", quote_crnl(git_work_tree));
        trace_printf_key(&key, "setup: cwd: %s\n", quote_crnl(cwd));
        trace_printf_key(&key, "setup: prefix: %s\n", quote_crnl(prefix));
+
+       free(cwd);
 }
 
 int trace_want(struct trace_key *key)
index 3d8fe7d801293a338f13dfd01ba352e84c658813..080a7a6ae23e6915c425a3e471fd641aabafba90 100644 (file)
@@ -118,7 +118,8 @@ static struct child_process *get_helper(struct transport *transport)
        if (data->helper)
                return data->helper;
 
-       helper = xcalloc(1, sizeof(*helper));
+       helper = xmalloc(sizeof(*helper));
+       child_process_init(helper);
        helper->in = -1;
        helper->out = -1;
        helper->err = 0;
@@ -395,7 +396,7 @@ static int get_importer(struct transport *transport, struct child_process *fasti
        struct child_process *helper = get_helper(transport);
        struct helper_data *data = transport->data;
        int cat_blob_fd, code;
-       memset(fastimport, 0, sizeof(*fastimport));
+       child_process_init(fastimport);
        fastimport->in = helper->out;
        argv_array_push(&fastimport->args, "fast-import");
        argv_array_push(&fastimport->args, debug ? "--stats" : "--quiet");
index 662421bb5e076177f0fc320330287d3da50303a5..7388bb87dae96514801bcd604b74d31f54955f9a 100644 (file)
@@ -201,7 +201,7 @@ static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
 {
        struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
        struct ref dummy = {NULL}, *tail = &dummy;
-       struct child_process rsync;
+       struct child_process rsync = CHILD_PROCESS_INIT;
        const char *args[5];
        int temp_dir_len;
 
@@ -218,7 +218,6 @@ static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
        strbuf_addstr(&buf, rsync_url(transport->url));
        strbuf_addstr(&buf, "/refs");
 
-       memset(&rsync, 0, sizeof(rsync));
        rsync.argv = args;
        rsync.stdout_to_stderr = 1;
        args[0] = "rsync";
@@ -263,9 +262,8 @@ static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
 static int fetch_objs_via_rsync(struct transport *transport,
                                int nr_objs, struct ref **to_fetch)
 {
-       struct child_process rsync;
+       struct child_process rsync = CHILD_PROCESS_INIT;
 
-       memset(&rsync, 0, sizeof(rsync));
        rsync.stdout_to_stderr = 1;
        argv_array_push(&rsync.args, "rsync");
        argv_array_push(&rsync.args, (transport->verbose > 1) ? "-rv" : "-r");
@@ -327,7 +325,7 @@ static int rsync_transport_push(struct transport *transport,
 {
        struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
        int result = 0, i;
-       struct child_process rsync;
+       struct child_process rsync = CHILD_PROCESS_INIT;
        const char *args[10];
 
        if (flags & TRANSPORT_PUSH_MIRROR)
@@ -338,7 +336,6 @@ static int rsync_transport_push(struct transport *transport,
        strbuf_addstr(&buf, rsync_url(transport->url));
        strbuf_addch(&buf, '/');
 
-       memset(&rsync, 0, sizeof(rsync));
        rsync.argv = args;
        rsync.stdout_to_stderr = 1;
        i = 0;
@@ -1056,7 +1053,7 @@ static int run_pre_push_hook(struct transport *transport,
 {
        int ret = 0, x;
        struct ref *r;
-       struct child_process proc;
+       struct child_process proc = CHILD_PROCESS_INIT;
        struct strbuf buf;
        const char *argv[4];
 
@@ -1067,7 +1064,6 @@ static int run_pre_push_hook(struct transport *transport,
        argv[2] = transport->url;
        argv[3] = NULL;
 
-       memset(&proc, 0, sizeof(proc));
        proc.argv = argv;
        proc.in = -1;
 
index 91bd6b89d4946bbd80a0b9e9e7d6af21d6a2f61a..19ed48be9902f321285bfbec3feaf8357fd5e9b9 100644 (file)
@@ -18,12 +18,12 @@ static int chdir_len(const char *orig, int len)
 }
 
 struct unix_sockaddr_context {
-       char orig_dir[PATH_MAX];
+       char *orig_dir;
 };
 
 static void unix_sockaddr_cleanup(struct unix_sockaddr_context *ctx)
 {
-       if (!ctx->orig_dir[0])
+       if (!ctx->orig_dir)
                return;
        /*
         * If we fail, we can't just return an error, since we have
@@ -32,6 +32,7 @@ static void unix_sockaddr_cleanup(struct unix_sockaddr_context *ctx)
         */
        if (chdir(ctx->orig_dir) < 0)
                die("unable to restore original working directory");
+       free(ctx->orig_dir);
 }
 
 static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path,
@@ -39,10 +40,11 @@ static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path,
 {
        int size = strlen(path) + 1;
 
-       ctx->orig_dir[0] = '\0';
+       ctx->orig_dir = NULL;
        if (size > sizeof(sa->sun_path)) {
                const char *slash = find_last_dir_sep(path);
                const char *dir;
+               struct strbuf cwd = STRBUF_INIT;
 
                if (!slash) {
                        errno = ENAMETOOLONG;
@@ -56,11 +58,9 @@ static int unix_sockaddr_init(struct sockaddr_un *sa, const char *path,
                        errno = ENAMETOOLONG;
                        return -1;
                }
-
-               if (!getcwd(ctx->orig_dir, sizeof(ctx->orig_dir))) {
-                       errno = ENAMETOOLONG;
+               if (strbuf_getcwd(&cwd))
                        return -1;
-               }
+               ctx->orig_dir = strbuf_detach(&cwd, NULL);
                if (chdir_len(dir, slash - dir) < 0)
                        return -1;
        }
index c6aa8fb993aa4bd92e4269d7a85c6b45fe9801e8..629c658c46a1b4f4bcd8bbe9770d7fd767ae2216 100644 (file)
@@ -1176,7 +1176,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 static int reject_merge(const struct cache_entry *ce,
                        struct unpack_trees_options *o)
 {
-       return add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce->name);
+       return o->gently ? -1 :
+               add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce->name);
 }
 
 static int same(const struct cache_entry *a, const struct cache_entry *b)
@@ -1631,7 +1632,7 @@ int threeway_merge(const struct cache_entry * const *stages,
        /* #14, #14ALT, #2ALT */
        if (remote && !df_conflict_head && head_match && !remote_match) {
                if (index && !same(index, remote) && !same(index, head))
-                       return o->gently ? -1 : reject_merge(index, o);
+                       return reject_merge(index, o);
                return merged_entry(remote, index, o);
        }
        /*
@@ -1639,7 +1640,7 @@ int threeway_merge(const struct cache_entry * const *stages,
         * make sure that it matches head.
         */
        if (index && !same(index, head))
-               return o->gently ? -1 : reject_merge(index, o);
+               return reject_merge(index, o);
 
        if (head) {
                /* #5ALT, #15 */
@@ -1768,9 +1769,8 @@ int twoway_merge(const struct cache_entry * const *src,
                                else
                                        return merged_entry(newtree, current, o);
                        }
-                       return o->gently ? -1 : reject_merge(current, o);
-               }
-               else if ((!oldtree && !newtree) || /* 4 and 5 */
+                       return reject_merge(current, o);
+               } else if ((!oldtree && !newtree) || /* 4 and 5 */
                         (!oldtree && newtree &&
                          same(current, newtree)) || /* 6 and 7 */
                         (oldtree && newtree &&
@@ -1779,26 +1779,15 @@ int twoway_merge(const struct cache_entry * const *src,
                          !same(oldtree, newtree) && /* 18 and 19 */
                          same(current, newtree))) {
                        return keep_entry(current, o);
-               }
-               else if (oldtree && !newtree && same(current, oldtree)) {
+               } else if (oldtree && !newtree && same(current, oldtree)) {
                        /* 10 or 11 */
                        return deleted_entry(oldtree, current, o);
-               }
-               else if (oldtree && newtree &&
+               } else if (oldtree && newtree &&
                         same(current, oldtree) && !same(current, newtree)) {
                        /* 20 or 21 */
                        return merged_entry(newtree, current, o);
-               }
-               else {
-                       /* all other failures */
-                       if (oldtree)
-                               return o->gently ? -1 : reject_merge(oldtree, o);
-                       if (current)
-                               return o->gently ? -1 : reject_merge(current, o);
-                       if (newtree)
-                               return o->gently ? -1 : reject_merge(newtree, o);
-                       return -1;
-               }
+               } else
+                       return reject_merge(current, o);
        }
        else if (newtree) {
                if (oldtree && !o->initial_checkout) {
index 01de944a0a23f752364de51d7f5a5be6480575e8..c789ec00507696b4e52b081b66cc0e7c8cba42f9 100644 (file)
@@ -80,7 +80,7 @@ static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
 
 static void create_pack_file(void)
 {
-       struct child_process pack_objects;
+       struct child_process pack_objects = CHILD_PROCESS_INIT;
        char data[8193], progress[128];
        char abort_msg[] = "aborting due to possible repository "
                "corruption on the remote side.";
@@ -108,7 +108,6 @@ static void create_pack_file(void)
                argv[arg++] = "--include-tag";
        argv[arg++] = NULL;
 
-       memset(&pack_objects, 0, sizeof(pack_objects));
        pack_objects.in = -1;
        pack_objects.out = -1;
        pack_objects.err = -1;
@@ -167,7 +166,9 @@ static void create_pack_file(void)
                if (!pollsize)
                        break;
 
-               ret = poll(pfd, pollsize, 1000 * keepalive);
+               ret = poll(pfd, pollsize,
+                       keepalive < 0 ? -1 : 1000 * keepalive);
+
                if (ret < 0) {
                        if (errno != EINTR) {
                                error("poll failed, resuming: %s",
@@ -448,7 +449,7 @@ static void check_non_tip(void)
        static const char *argv[] = {
                "rev-list", "--stdin", NULL,
        };
-       static struct child_process cmd;
+       static struct child_process cmd = CHILD_PROCESS_INIT;
        struct object *o;
        char namebuf[42]; /* ^ + SHA-1 + LF */
        int i;
diff --git a/utf8.c b/utf8.c
index b30790d043aa4b01da00686654dfb615a92e75b6..401a6a509e8b4221a539cec6ad67721fc620d64e 100644 (file)
--- a/utf8.c
+++ b/utf8.c
@@ -382,6 +382,9 @@ void strbuf_utf8_replace(struct strbuf *sb_src, int pos, int width,
                        dst += n;
                }
 
+               if (src >= end)
+                       break;
+
                old = src;
                n = utf8_width((const char**)&src, NULL);
                if (!src)       /* broken utf-8, do nothing */
index 014826464e07c93374868c61673cfe308961dfb7..f8d370913a8dcfb87d62ab994b4823dc84157f8b 100644 (file)
--- a/walker.c
+++ b/walker.c
@@ -205,7 +205,7 @@ static int mark_complete(const char *path, const unsigned char *sha1, int flag,
        struct commit *commit = lookup_commit_reference_gently(sha1, 1);
        if (commit) {
                commit->object.flags |= COMPLETE;
-               commit_list_insert_by_date(commit, &complete);
+               commit_list_insert(commit, &complete);
        }
        return 0;
 }
@@ -251,64 +251,76 @@ void walker_targets_free(int targets, char **target, const char **write_ref)
 int walker_fetch(struct walker *walker, int targets, char **target,
                 const char **write_ref, const char *write_ref_log_details)
 {
-       struct ref_lock **lock = xcalloc(targets, sizeof(struct ref_lock *));
+       struct strbuf refname = STRBUF_INIT;
+       struct strbuf err = STRBUF_INIT;
+       struct ref_transaction *transaction = NULL;
        unsigned char *sha1 = xmalloc(targets * 20);
-       const char *msg;
-       char *to_free = NULL;
-       int ret;
-       int i;
+       char *msg = NULL;
+       int i, ret = -1;
 
        save_commit_buffer = 0;
 
-       for (i = 0; i < targets; i++) {
-               if (!write_ref || !write_ref[i])
-                       continue;
-
-               lock[i] = lock_ref_sha1(write_ref[i], NULL);
-               if (!lock[i]) {
-                       error("Can't lock ref %s", write_ref[i]);
-                       goto unlock_and_fail;
+       if (write_ref) {
+               transaction = ref_transaction_begin(&err);
+               if (!transaction) {
+                       error("%s", err.buf);
+                       goto done;
                }
        }
 
-       if (!walker->get_recover)
+       if (!walker->get_recover) {
                for_each_ref(mark_complete, NULL);
+               commit_list_sort_by_date(&complete);
+       }
 
        for (i = 0; i < targets; i++) {
                if (interpret_target(walker, target[i], &sha1[20 * i])) {
                        error("Could not interpret response from server '%s' as something to pull", target[i]);
-                       goto unlock_and_fail;
+                       goto done;
                }
                if (process(walker, lookup_unknown_object(&sha1[20 * i])))
-                       goto unlock_and_fail;
+                       goto done;
        }
 
        if (loop(walker))
-               goto unlock_and_fail;
-
-       if (write_ref_log_details)
-               msg = to_free = xstrfmt("fetch from %s", write_ref_log_details);
-       else
-               msg = "fetch (unknown)";
+               goto done;
+       if (!write_ref) {
+               ret = 0;
+               goto done;
+       }
+       if (write_ref_log_details) {
+               msg = xstrfmt("fetch from %s", write_ref_log_details);
+       } else {
+               msg = NULL;
+       }
        for (i = 0; i < targets; i++) {
-               if (!write_ref || !write_ref[i])
+               if (!write_ref[i])
                        continue;
-               ret = write_ref_sha1(lock[i], &sha1[20 * i], msg);
-               lock[i] = NULL;
-               if (ret)
-                       goto unlock_and_fail;
+               strbuf_reset(&refname);
+               strbuf_addf(&refname, "refs/%s", write_ref[i]);
+               if (ref_transaction_update(transaction, refname.buf,
+                                          &sha1[20 * i], NULL, 0, 0,
+                                          &err)) {
+                       error("%s", err.buf);
+                       goto done;
+               }
+       }
+       if (ref_transaction_commit(transaction,
+                                  msg ? msg : "fetch (unknown)",
+                                  &err)) {
+               error("%s", err.buf);
+               goto done;
        }
-       free(to_free);
-
-       return 0;
 
-unlock_and_fail:
-       for (i = 0; i < targets; i++)
-               if (lock[i])
-                       unlock_ref(lock[i]);
-       free(to_free);
+       ret = 0;
 
-       return -1;
+done:
+       ref_transaction_free(transaction);
+       free(msg);
+       free(sha1);
+       strbuf_release(&err);
+       strbuf_release(&refname);
+       return ret;
 }
 
 void walker_free(struct walker *walker)
index bc1bfb86003cb4133cc4ce3ce6423ce780ed7c84..25074d71b6ce72066efc02abda74ddfb10f71d6c 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -9,16 +9,23 @@ static void do_nothing(size_t size)
 
 static void (*try_to_free_routine)(size_t size) = do_nothing;
 
-static void memory_limit_check(size_t size)
+static int memory_limit_check(size_t size, int gentle)
 {
        static int limit = -1;
        if (limit == -1) {
                const char *env = getenv("GIT_ALLOC_LIMIT");
                limit = env ? atoi(env) * 1024 : 0;
        }
-       if (limit && size > limit)
-               die("attempting to allocate %"PRIuMAX" over limit %d",
-                   (intmax_t)size, limit);
+       if (limit && size > limit) {
+               if (gentle) {
+                       error("attempting to allocate %"PRIuMAX" over limit %d",
+                             (intmax_t)size, limit);
+                       return -1;
+               } else
+                       die("attempting to allocate %"PRIuMAX" over limit %d",
+                           (intmax_t)size, limit);
+       }
+       return 0;
 }
 
 try_to_free_t set_try_to_free_routine(try_to_free_t routine)
@@ -42,11 +49,12 @@ char *xstrdup(const char *str)
        return ret;
 }
 
-void *xmalloc(size_t size)
+static void *do_xmalloc(size_t size, int gentle)
 {
        void *ret;
 
-       memory_limit_check(size);
+       if (memory_limit_check(size, gentle))
+               return NULL;
        ret = malloc(size);
        if (!ret && !size)
                ret = malloc(1);
@@ -55,9 +63,16 @@ void *xmalloc(size_t size)
                ret = malloc(size);
                if (!ret && !size)
                        ret = malloc(1);
-               if (!ret)
-                       die("Out of memory, malloc failed (tried to allocate %lu bytes)",
-                           (unsigned long)size);
+               if (!ret) {
+                       if (!gentle)
+                               die("Out of memory, malloc failed (tried to allocate %lu bytes)",
+                                   (unsigned long)size);
+                       else {
+                               error("Out of memory, malloc failed (tried to allocate %lu bytes)",
+                                     (unsigned long)size);
+                               return NULL;
+                       }
+               }
        }
 #ifdef XMALLOC_POISON
        memset(ret, 0xA5, size);
@@ -65,16 +80,37 @@ void *xmalloc(size_t size)
        return ret;
 }
 
-void *xmallocz(size_t size)
+void *xmalloc(size_t size)
+{
+       return do_xmalloc(size, 0);
+}
+
+static void *do_xmallocz(size_t size, int gentle)
 {
        void *ret;
-       if (unsigned_add_overflows(size, 1))
-               die("Data too large to fit into virtual memory space.");
-       ret = xmalloc(size + 1);
-       ((char*)ret)[size] = 0;
+       if (unsigned_add_overflows(size, 1)) {
+               if (gentle) {
+                       error("Data too large to fit into virtual memory space.");
+                       return NULL;
+               } else
+                       die("Data too large to fit into virtual memory space.");
+       }
+       ret = do_xmalloc(size + 1, gentle);
+       if (ret)
+               ((char*)ret)[size] = 0;
        return ret;
 }
 
+void *xmallocz(size_t size)
+{
+       return do_xmallocz(size, 0);
+}
+
+void *xmallocz_gently(size_t size)
+{
+       return do_xmallocz(size, 1);
+}
+
 /*
  * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
  * "data" to the allocated memory, zero terminates the allocated memory,
@@ -96,7 +132,7 @@ void *xrealloc(void *ptr, size_t size)
 {
        void *ret;
 
-       memory_limit_check(size);
+       memory_limit_check(size, 0);
        ret = realloc(ptr, size);
        if (!ret && !size)
                ret = realloc(ptr, 1);
@@ -115,7 +151,7 @@ void *xcalloc(size_t nmemb, size_t size)
 {
        void *ret;
 
-       memory_limit_check(size * nmemb);
+       memory_limit_check(size * nmemb, 0);
        ret = calloc(nmemb, size);
        if (!ret && (!nmemb || !size))
                ret = calloc(1, 1);
@@ -493,3 +529,11 @@ struct passwd *xgetpwuid_self(void)
                    errno ? strerror(errno) : _("no such user"));
        return pw;
 }
+
+char *xgetcwd(void)
+{
+       struct strbuf sb = STRBUF_INIT;
+       if (strbuf_getcwd(&sb))
+               die_errno(_("unable to get current working directory"));
+       return strbuf_detach(&sb, NULL);
+}
index 27da5296be253844e0f2bc8d5996faf343192828..1bf5d725453f726f6a6179f9706a50f3c8c9dbb5 100644 (file)
@@ -725,7 +725,7 @@ static void wt_status_print_changed(struct wt_status *s)
 
 static void wt_status_print_submodule_summary(struct wt_status *s, int uncommitted)
 {
-       struct child_process sm_summary;
+       struct child_process sm_summary = CHILD_PROCESS_INIT;
        struct argv_array env = ARGV_ARRAY_INIT;
        struct argv_array argv = ARGV_ARRAY_INIT;
        struct strbuf cmd_stdout = STRBUF_INIT;
@@ -744,7 +744,6 @@ static void wt_status_print_submodule_summary(struct wt_status *s, int uncommitt
        if (!uncommitted)
                argv_array_push(&argv, s->amend ? "HEAD^" : "HEAD");
 
-       memset(&sm_summary, 0, sizeof(sm_summary));
        sm_summary.argv = argv.argv;
        sm_summary.env = env.argv;
        sm_summary.git_cmd = 1;