Git development
 help / color / mirror / Atom feed
* RE: [PATCH 0/5] A series of performance enhancements in the memihash and name-cache area
From: Jeff Hostetler @ 2017-02-19  0:02 UTC (permalink / raw)
  To: Junio C Hamano, Jeff King
  Cc: Jeff Hostetler, Johannes Schindelin, git@vger.kernel.org,
	Jeff Hostetler
In-Reply-To: <xmqqvas8m499.fsf@gitster.mtv.corp.google.com>



From: Junio C Hamano [mailto:jch2355@gmail.com] On Behalf Of Junio C Hamano
> Jeff King <peff@peff.net> writes:
>> On Wed, Feb 15, 2017 at 09:27:53AM -0500, Jeff Hostetler wrote:
>>
>>> I have some informal numbers in a spreadsheet.  I was seeing
>>> a 8-9% speed up on a status on my gigantic repo.
>>> 
>>> I'll try to put together a before/after perf-test to better
>>> demonstrate this.
>>
>> Thanks. What I'm mostly curious about is how much each individual step
>> buys. Sometimes when doing a long optimization series, I find that some
>> of the optimizations make other ones somewhat redundant (e.g., if patch
>> 2 causes us to call the optimized code from patch 3 less often).
>
> I am curious too.
>
> To me 1/5 (reduction of redundant calls), 4/5 (correctly size the
> hash that would grow to a known size anyway) and 5/5 (take advantage
> of the fact that adjacent cache entries are often in the same
> directory) look like no brainers to take, regardless of the others
> (including themselves). 

agreed.

> It is not clear to me if 3/5 (preload-index uses available cores to
> compute hashes) is an unconditional win (an operation that is
> pathspec limited may need hashes for only a small fraction of the
> index---would it still be a win to compute the hash for all entries
> upon loading the index, even if we are using otherwise-idel cores?).

I'm not sure about pathspec cases.  What I was seeing was that during
the call to lazy_name_init_hash() was taking 30% of the time in
"git status" and 40% in "git add <one_file>".  (Again this was on my
giant repo with a 450MB index).
 
> Of course 2/5 is a prerequisite step for 3/5 and 5/5, so if we want
> either of the latter two, we cannot avoid it.

jeff


^ permalink raw reply

* Re: [PATCH] git-check-ref-format: fix typo in man page
From: Jacob Keller @ 2017-02-19  0:17 UTC (permalink / raw)
  To: Damien Regad; +Cc: Git mailing list
In-Reply-To: <c27d7861-b161-a3eb-fcfc-bf766fc7b20b@gmail.com>

On Sat, Feb 18, 2017 at 2:47 PM, Damien Regad <dregad@mantisbt.org> wrote:
>
> ---
>  Documentation/git-check-ref-format.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/Documentation/git-check-ref-format.txt
> b/Documentation/git-check-ref-format.txt
> index 8611a99..377c85a 100644
> --- a/Documentation/git-check-ref-format.txt
> +++ b/Documentation/git-check-ref-format.txt
> @@ -100,7 +100,7 @@ OPTIONS
>  --normalize::
>         Normalize 'refname' by removing any leading slash (`/`)
>         characters and collapsing runs of adjacent slashes between
> -       name components into a single slash.  Iff the normalized
> +       name components into a single slash.  If the normalized

I think this is a good change, but I do know in some contexts, "Iff"
is used intentionally to mean "If and only if". It's somewhat unlikely
that's what was going on here, and I don't think we need to be that
pedantic in our help documentation anyway.

Thanks,
Jake

>         refname is valid then print it to standard output and exit
>         with a status of 0.  (`--print` is a deprecated way to spell
>         `--normalize`.)
> --
> 2.7.4
>
>

^ permalink raw reply

* RE: [PATCH 3/5] name-hash: precompute hash values during preload-index
From: Jeff Hostetler @ 2017-02-19  0:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git@vger.kernel.org, Johannes Schindelin, Jeff Hostetler
In-Reply-To: <xmqq37fcnj7v.fsf@gitster.mtv.corp.google.com>



From: Junio C Hamano [mailto:jch2355@gmail.com] On Behalf Of Junio C Hamano
> 
> The fact that each preload_thread() still walks the index in-order
> makes me wonder if it may allow us to further optimize the "dir"
> part of the hash by passing the previous ce for which we already
> precomputed hash values.  While the loop is iterating over the paths
> in the same directory, .dir component from the previous ce can be
> reused and .name component can "continue", no?
> 
> It's possible that you already tried such an optimization and
> rejected it after finding that the cost of comparison of pathnames
> to tell if ce and previous ce are still in the same directory is
> more than unconditionally memihash() the directory part, and I am in
> no way saying that I found a missed optimization opportunity you
> must pursue.  I am just being curious.

I looked at doing this, but I didn't think the complexity and overhead to
forward search for peers at the current level didn't warrant the limited gains.
(I was just looking at the complexity of clear_ce_flags_1() in unpack-trees.c
and how hard it has to look to find the end of the current directory and the
effect that that has on the recursion and it felt like too much work for the
potential gain.)

Whereas remembering the previous one was basically free.  Granted, it only
helps us for adjacent files in the index, so it's not perfect, but gives us the
best bang for the buck.

Jeff


^ permalink raw reply

* Re: [PATCH] git-check-ref-format: fix typo in man page
From: Philip Oakley @ 2017-02-19  0:20 UTC (permalink / raw)
  To: Damien Regad, git
In-Reply-To: <c27d7861-b161-a3eb-fcfc-bf766fc7b20b@gmail.com>

From: "Damien Regad" <dregad@mantisbt.org>
> ---
> Documentation/git-check-ref-format.txt | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/Documentation/git-check-ref-format.txt
> b/Documentation/git-check-ref-format.txt
> index 8611a99..377c85a 100644
> --- a/Documentation/git-check-ref-format.txt
> +++ b/Documentation/git-check-ref-format.txt
> @@ -100,7 +100,7 @@ OPTIONS
> --normalize::
>  Normalize 'refname' by removing any leading slash (`/`)
>  characters and collapsing runs of adjacent slashes between
> - name components into a single slash.  Iff the normalized
> + name components into a single slash.  If the normalized
>  refname is valid then print it to standard output and exit
>  with a status of 0.  (`--print` is a deprecated way to spell
>  `--normalize`.)
> -- 

Could that be an 'iff' == 'If and only if' (which is common in mathematics)? 
Still could be spelling error though.
--
Philip 


^ permalink raw reply

* Re: [PATCH] fetch: print an error when declining to request an unadvertised object
From: Matt McCutchen @ 2017-02-19  2:07 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <xmqq60kfezr9.fsf@gitster.mtv.corp.google.com>

On Sun, 2017-02-12 at 15:49 -0800, Junio C Hamano wrote:
> The fact that we have the above two choices tells me that a two-step
> approach may be an appropriate approach. [...]

> Even if you did only the first step, as long as the second step can
> be done without reverting what the first step did [*4*] by somebody
> who cares the "specific error" deeply enough, I am OK with that.  Of
> course if you did both steps, that is fine by me as well ;-)

I appreciate the flexibility, but now that I've spent the time to
understand all the code involved, it would be a pity not to go for the
complete solution.  New patch coming.

Matt

^ permalink raw reply

* [PATCH] fetch: print an error when declining to request an unadvertised object
From: Matt McCutchen @ 2017-02-19  1:55 UTC (permalink / raw)
  To: git
In-Reply-To: <xmqq60kfezr9.fsf@gitster.mtv.corp.google.com>

Currently "git fetch REMOTE SHA1" silently exits 1 if the server doesn't
allow requests for unadvertised objects by sha1.  The more common case
of requesting a nonexistent ref normally triggers a die() in
get_fetch_map, so "git fetch" wasn't bothering to check after the fetch
that it got all the refs it sought, like "git fetch-pack" does near the
end of cmd_fetch_pack.

Move the code from cmd_fetch_pack to a new function,
report_unmatched_refs, that is called by fetch_refs_via_pack as part of
"git fetch".  Also, change filter_refs (which checks whether a request
for an unadvertised object should be sent to the server) to set a new
match status on the "struct ref" when the request is not allowed, and
have report_unmatched_refs check for this status and print a special
error message, "Server does not allow request for unadvertised object".

Finally, add a simple test case for "git fetch REMOTE SHA1".

Signed-off-by: Matt McCutchen <matt@mattmccutchen.net>
---
 builtin/fetch-pack.c  |  7 +------
 fetch-pack.c          | 51 ++++++++++++++++++++++++++++++++++++++-------------
 fetch-pack.h          |  9 +++++++++
 remote.h              |  9 +++++++--
 t/t5516-fetch-push.sh |  3 ++-
 transport.c           | 14 +++++++++-----
 6 files changed, 66 insertions(+), 27 deletions(-)

diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index cfe9e44..2a1c1c2 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -219,12 +219,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 	 * remote no-such-ref' would silently succeed without issuing
 	 * an error.
 	 */
-	for (i = 0; i < nr_sought; i++) {
-		if (!sought[i] || sought[i]->matched)
-			continue;
-		error("no such remote ref %s", sought[i]->name);
-		ret = 1;
-	}
+	ret |= report_unmatched_refs(sought, nr_sought);
 
 	while (ref) {
 		printf("%s %s\n",
diff --git a/fetch-pack.c b/fetch-pack.c
index 601f077..f12bfcd 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -578,7 +578,7 @@ static void filter_refs(struct fetch_pack_args *args,
 					break; /* definitely do not have it */
 				else if (cmp == 0) {
 					keep = 1; /* definitely have it */
-					sought[i]->matched = 1;
+					sought[i]->match_status = REF_MATCHED;
 				}
 				i++;
 			}
@@ -598,22 +598,24 @@ static void filter_refs(struct fetch_pack_args *args,
 	}
 
 	/* Append unmatched requests to the list */
-	if ((allow_unadvertised_object_request &
-	    (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
-		for (i = 0; i < nr_sought; i++) {
-			unsigned char sha1[20];
+	for (i = 0; i < nr_sought; i++) {
+		unsigned char sha1[20];
 
-			ref = sought[i];
-			if (ref->matched)
-				continue;
-			if (get_sha1_hex(ref->name, sha1) ||
-			    ref->name[40] != '\0' ||
-			    hashcmp(sha1, ref->old_oid.hash))
-				continue;
+		ref = sought[i];
+		if (ref->match_status != REF_NOT_MATCHED)
+			continue;
+		if (get_sha1_hex(ref->name, sha1) ||
+		    ref->name[40] != '\0' ||
+		    hashcmp(sha1, ref->old_oid.hash))
+			continue;
 
-			ref->matched = 1;
+		if ((allow_unadvertised_object_request &
+		    (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1))) {
+			ref->match_status = REF_MATCHED;
 			*newtail = copy_ref(ref);
 			newtail = &(*newtail)->next;
+		} else {
+			ref->match_status = REF_UNADVERTISED_NOT_ALLOWED;
 		}
 	}
 	*refs = newlist;
@@ -1094,3 +1096,26 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
 	clear_shallow_info(&si);
 	return ref_cpy;
 }
+
+int report_unmatched_refs(struct ref **sought, int nr_sought)
+{
+	int i, ret = 0;
+
+	for (i = 0; i < nr_sought; i++) {
+		if (!sought[i])
+			continue;
+		switch (sought[i]->match_status) {
+		case REF_MATCHED:
+			continue;
+		case REF_NOT_MATCHED:
+			error(_("no such remote ref %s"), sought[i]->name);
+			break;
+		case REF_UNADVERTISED_NOT_ALLOWED:
+			error(_("Server does not allow request for unadvertised object %s"),
+			      sought[i]->name);
+			break;
+		}
+		ret = 1;
+	}
+	return ret;
+}
diff --git a/fetch-pack.h b/fetch-pack.h
index c912e3d..fd4d80e 100644
--- a/fetch-pack.h
+++ b/fetch-pack.h
@@ -45,4 +45,13 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
 		       struct sha1_array *shallow,
 		       char **pack_lockfile);
 
+/*
+ * Print an appropriate error message for each sought ref that wasn't
+ * matched.  Return 0 if all sought refs were matched, otherwise 1.
+ *
+ * The type of "sought" should be "const struct ref *const *" but for
+ * http://stackoverflow.com/questions/5055655/double-pointer-const-correctness-warnings-in-c .
+ */
+int report_unmatched_refs(struct ref **sought, int nr_sought);
+
 #endif
diff --git a/remote.h b/remote.h
index 9248811..0b9d8c4 100644
--- a/remote.h
+++ b/remote.h
@@ -89,8 +89,13 @@ struct ref {
 		force:1,
 		forced_update:1,
 		expect_old_sha1:1,
-		deletion:1,
-		matched:1;
+		deletion:1;
+
+	enum {
+		REF_NOT_MATCHED = 0, /* initial value */
+		REF_MATCHED,
+		REF_UNADVERTISED_NOT_ALLOWED
+	} match_status;
 
 	/*
 	 * Order is important here, as we write to FETCH_HEAD
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 26b2caf..78f3b8e 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1098,7 +1098,8 @@ test_expect_success 'fetch exact SHA1' '
 		test_must_fail git cat-file -t $the_commit &&
 
 		# fetching the hidden object should fail by default
-		test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy &&
+		test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err &&
+		test_i18ngrep "Server does not allow request for unadvertised object" err &&
 		test_must_fail git rev-parse --verify refs/heads/copy &&
 
 		# the server side can allow it to succeed
diff --git a/transport.c b/transport.c
index 04e5d66..c377907 100644
--- a/transport.c
+++ b/transport.c
@@ -204,6 +204,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
 static int fetch_refs_via_pack(struct transport *transport,
 			       int nr_heads, struct ref **to_fetch)
 {
+	int ret = 0;
 	struct git_transport_data *data = transport->data;
 	struct ref *refs;
 	char *dest = xstrdup(transport->url);
@@ -241,19 +242,22 @@ static int fetch_refs_via_pack(struct transport *transport,
 			  &transport->pack_lockfile);
 	close(data->fd[0]);
 	close(data->fd[1]);
-	if (finish_connect(data->conn)) {
-		free_refs(refs);
-		refs = NULL;
-	}
+	if (finish_connect(data->conn))
+		ret = -1;
 	data->conn = NULL;
 	data->got_remote_heads = 0;
 	data->options.self_contained_and_connected =
 		args.self_contained_and_connected;
 
+	if (refs == NULL)
+		ret = -1;
+	if (report_unmatched_refs(to_fetch, nr_heads))
+		ret = -1;
+
 	free_refs(refs_tmp);
 	free_refs(refs);
 	free(dest);
-	return (refs ? 0 : -1);
+	return ret;
 }
 
 static int push_had_errors(struct ref *ref)
-- 
2.9.3



^ permalink raw reply related

* Re: [PATCH] fixup! bisect--helper: `bisect_next_check` & bisect_voc shell function in C
From: Junio C Hamano @ 2017-02-19  2:06 UTC (permalink / raw)
  To: git; +Cc: René Scharfe, Johannes Schindelin, Pranit Bauva
In-Reply-To: <xmqqinodewdr.fsf@gitster.mtv.corp.google.com>

Junio C Hamano <gitster@pobox.com> writes:

> ...
> So, let's give Pranit a concrete "here is what we want to see
> squashed in", while you guys discuss peculiarity with various
> platforms and their system headers, which admittedly is a more
> interesting tangent ;-)
>
> There are early returns with "goto finish" even before _syn
> variables are first assigned to, so they would need to be
> initialized to NULL.  The other two get their initial values
> right at the beginning, so they are OK.
>
>  builtin/bisect--helper.c | 14 +++++---------
>  1 file changed, 5 insertions(+), 9 deletions(-)

While we are waiting for the topic to be fixed, I've tentatively
applied this on top to update 'pu', so Travis should now be happy
with 'pu' on Mac, too.


^ permalink raw reply

* Re: [PATCH] git-check-ref-format: fix typo in man page
From: Jeff King @ 2017-02-19  2:27 UTC (permalink / raw)
  To: Philip Oakley; +Cc: Michael Haggerty, Damien Regad, git
In-Reply-To: <2116CBFFB78A482D8FA176BC680B3B9C@PhilipOakley>

On Sun, Feb 19, 2017 at 12:20:33AM -0000, Philip Oakley wrote:

> >  Normalize 'refname' by removing any leading slash (`/`)
> >  characters and collapsing runs of adjacent slashes between
> > - name components into a single slash.  Iff the normalized
> > + name components into a single slash.  If the normalized
> >  refname is valid then print it to standard output and exit
> >  with a status of 0.  (`--print` is a deprecated way to spell
> >  `--normalize`.)
> > -- 
> 
> Could that be an 'iff' == 'If and only if' (which is common in mathematics)?
> Still could be spelling error though.

When we're not sure what the intent of a change is, a good first step is
to dig up the original commit via `git blame` or similar. In this case,
it comes from a40e6fb67 (Change check_refname_format() to reject
unnormalized refnames, 2011-09-15).

The commit message doesn't mention it (not that I really expected it
to), but it does tell you who the author is. And a good second step is
to cc them on the patch. :)

I suspect it _was_ intended as "iff" here. In my opinion, we probably
don't need to be so rigorous in this instance. However, I note that we
do not describe the "else" half of that "if". So maybe an overall
improvement would be something like:

  If the normalized refname is valid then print it to standard output
  and exit with a status of 0. Otherwise, exit with a non-zero status.

-Peff

^ permalink raw reply

* Re: difflame improvements
From: Edmundo Carmona Antoranz @ 2017-02-19  6:35 UTC (permalink / raw)
  To: Jeff King; +Cc: Git List
In-Reply-To: <CAOc6etZxkspqafifjPTbRDoVBt0XuOLbhiuY9bFTD2Wjtxw-HQ@mail.gmail.com>

On Fri, Feb 17, 2017 at 1:01 AM, Edmundo Carmona Antoranz
<eantoranz@gmail.com> wrote:
> On Thu, Feb 16, 2017 at 11:17 PM, Jeff King <peff@peff.net> wrote:
>
>> This isn't difflame's fault; that's what "git blame" tells you about
>> that line. But since I already told difflame "v2.6.5..HEAD", it would
>> probably make sense to similarly limit the blame to that range. That
>> turns up a boundary commit for the line. Which is _also_ not helpful,
>> but at least the tool is telling me that the line came from before
>> v2.6.5, and I don't really need to care much about it.
>
>
> I'm running my own tests on difflame and I have a theory about "when"
> it breaks.... at least one of the cases when it breaks:
>
> Analysis for deleted lines is being driven by git blame --reverse.
> What I have noticed is that it "breaks" when blame --reverse drives
> the analysis into revisions where "treeish1" is not part of their
> history (like, bringing analysis "to the sides" of treeish1 instead of
> keeping analysis in revisions in the history of treeish2 that have
> treeish1 as one of their ancestors.... which is definitely a valid
> case for analysis, anyway). In this case, blame --reverse stops being
> helpful.
>

At the cost of being slower, I just pushed to master the best results yet.

The workaround I developed for the case I described on the previous
mail ended up providing much better results overall so I ended up
replacing the whole merge-analysis logic with it.

Thanks for your kind help and comments, Peff. Let me know how it goes.

^ permalink raw reply

* Re: [PATCH v5 3/6] stash: refactor stash_create
From: Thomas Gummerer @ 2017-02-19  9:17 UTC (permalink / raw)
  To: Jeff King
  Cc: git, Junio C Hamano, Johannes Schindelin, Øyvind A . Holm,
	Jakub Narębski, Matthieu Moy
In-Reply-To: <20170217234805.glvhyfbxab6nwgb7@sigill.intra.peff.net>

On 02/17, Jeff King wrote:
> On Fri, Feb 17, 2017 at 10:41:38PM +0000, Thomas Gummerer wrote:
> 
> > Refactor the internal stash_create function to use a -m flag for
> > specifying the message and -u flag to indicate whether untracked files
> > should be added to the stash.
> > 
> > This makes it easier to pass a pathspec argument to stash_create in the
> > next patch.
> > 
> > The user interface for git stash create stays the same.
> 
> Sounds good, but...
> 
> > diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
> > index 2e9cef06e6..d93c47446a 100644
> > --- a/Documentation/git-stash.txt
> > +++ b/Documentation/git-stash.txt
> > @@ -17,6 +17,7 @@ SYNOPSIS
> >  	     [-u|--include-untracked] [-a|--all] [<message>]]
> >  'git stash' clear
> >  'git stash' create [<message>]
> > +'git stash' create [-m <message>] [-u|--include-untracked <untracked|all>]
> >  'git stash' store [-m|--message <message>] [-q|--quiet] <commit>
> 
> Should this hunk be dropped from the manpage, then?
> 
> I think there is a similar one in the next patch that adds the
> "pathspec" argument, and should be dropped, too.

Argh yes I should have been more careful.  Thanks for catching.

> -Peff

^ permalink raw reply

* Re: [PATCH v5 6/6] stash: allow pathspecs in the no verb form
From: Thomas Gummerer @ 2017-02-19  9:18 UTC (permalink / raw)
  To: Jeff King
  Cc: git, Junio C Hamano, Johannes Schindelin, Øyvind A . Holm,
	Jakub Narębski, Matthieu Moy
In-Reply-To: <20170217234647.bqhzzm533oruhr5e@sigill.intra.peff.net>

On 02/17, Jeff King wrote:
> On Fri, Feb 17, 2017 at 10:41:41PM +0000, Thomas Gummerer wrote:
> 
> > Now that stash_push is used in the no verb form of stash, allow
> > specifying the command line for this form as well.  Always use -- to
> > disambiguate pathspecs from other non-option arguments.
> 
> I think that makes sense.
> 
> > Also make git stash -p an alias for git stash push -p.  This allows
> > users to use git stash -p <pathspec>.
> 
> And I think of all the options we discussed for handling "-p", I think
> this one makes the most sense.
> 
> It may be worth calling out in the documentation that this is how it
> works though, so people do not think that:
> 
>   git stash -k -p <path>
> 
> would work ("git stash -k -p" _does_ happen to work due to the old
> options-only rule, but I think we should advertise the general form as
> "-p is an alias for "push -p").

Yeah, I think adding something about this in the documentation would
be good.  I'll add a paragraph about this in the re-roll.

> -Peff


^ permalink raw reply

* [PATCH v6 5/6] stash: use stash_push for no verb form
From: Thomas Gummerer @ 2017-02-19 11:03 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Johannes Schindelin,
	Øyvind A. Holm, Jakub Narębski, Matthieu Moy,
	Thomas Gummerer
In-Reply-To: <20170219110313.24070-1-t.gummerer@gmail.com>

Now that we have stash_push, which accepts pathspec arguments, use
it instead of stash_save in git stash without any additional verbs.

Previously we allowed git stash -- -message, which is no longer allowed
after this patch.  Messages starting with a hyphen was allowed since
3c2eb80f, ("stash: simplify defaulting to "save" and reject unknown
options").  However it was never the intent to allow that, but rather it
was allowed accidentally.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 Documentation/git-stash.txt |  8 ++++----
 git-stash.sh                | 16 ++++++++--------
 t/t3903-stash.sh            |  4 +---
 3 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index b7db939a06..3f7fa88ddc 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -13,11 +13,11 @@ SYNOPSIS
 'git stash' drop [-q|--quiet] [<stash>]
 'git stash' ( pop | apply ) [--index] [-q|--quiet] [<stash>]
 'git stash' branch <branchname> [<stash>]
-'git stash' [save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
-	     [-u|--include-untracked] [-a|--all] [<message>]]
-'git stash' push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
+'git stash' save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
+	     [-u|--include-untracked] [-a|--all] [<message>]
+'git stash' [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
 	     [-u|--include-untracked] [-a|--all] [-m|--message <message>]]
-	     [--] [<pathspec>...]
+	     [--] [<pathspec>...]]
 'git stash' clear
 'git stash' create [<message>]
 'git stash' store [-m|--message <message>] [-q|--quiet] <commit>
diff --git a/git-stash.sh b/git-stash.sh
index b55983d1fd..1e55cd5fdd 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -7,11 +7,11 @@ USAGE="list [<options>]
    or: $dashless drop [-q|--quiet] [<stash>]
    or: $dashless ( pop | apply ) [--index] [-q|--quiet] [<stash>]
    or: $dashless branch <branchname> [<stash>]
-   or: $dashless [save [--patch] [-k|--[no-]keep-index] [-q|--quiet]
-		       [-u|--include-untracked] [-a|--all] [<message>]]
-   or: $dashless push [--patch] [-k|--[no-]keep-index] [-q|--quiet]
-		      [-u|--include-untracked] [-a|--all] [-m <message>]
-		      [-- <pathspec>...]
+   or: $dashless save [--patch] [-k|--[no-]keep-index] [-q|--quiet]
+		      [-u|--include-untracked] [-a|--all] [<message>]
+   or: $dashless [push [--patch] [-k|--[no-]keep-index] [-q|--quiet]
+		       [-u|--include-untracked] [-a|--all] [-m <message>]
+		       [-- <pathspec>...]]
    or: $dashless clear"
 
 SUBDIRECTORY_OK=Yes
@@ -667,7 +667,7 @@ apply_to_branch () {
 }
 
 PARSE_CACHE='--not-parsed'
-# The default command is "save" if nothing but options are given
+# The default command is "push" if nothing but options are given
 seen_non_option=
 for opt
 do
@@ -677,7 +677,7 @@ do
 	esac
 done
 
-test -n "$seen_non_option" || set "save" "$@"
+test -n "$seen_non_option" || set "push" "$@"
 
 # Main command set
 case "$1" in
@@ -728,7 +728,7 @@ branch)
 *)
 	case $# in
 	0)
-		save_stash &&
+		push_stash &&
 		say "$(gettext "(To restore them type \"git stash apply\")")"
 		;;
 	*)
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 4fb800eec8..7f90a247b4 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -274,9 +274,7 @@ test_expect_success 'stash --invalid-option' '
 	git add file2 &&
 	test_must_fail git stash --invalid-option &&
 	test_must_fail git stash save --invalid-option &&
-	test bar5,bar6 = $(cat file),$(cat file2) &&
-	git stash -- -message-starting-with-dash &&
-	test bar,bar2 = $(cat file),$(cat file2)
+	test bar5,bar6 = $(cat file),$(cat file2)
 '
 
 test_expect_success 'stash an added file' '
-- 
2.12.0.rc2.399.g0ca89a282


^ permalink raw reply related

* [PATCH v6 0/6] stash: support pathspec argument
From: Thomas Gummerer @ 2017-02-19 11:03 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Johannes Schindelin,
	Øyvind A. Holm, Jakub Narębski, Matthieu Moy,
	Thomas Gummerer
In-Reply-To: <20170217224141.19183-1-t.gummerer@gmail.com>

Thanks Junio and Peff for comments on the last round.

Changes since then:

- removed mention of the "new form" of git stash create from the
  Documentation.
- Changed documentation for git stash without a verb, mentioning
  stash -p now being an alias for git stash push -p and that -- can be
  used as disambiguation for for pathspecs
- Fixed ${1-...} which should have been ${1?...}
- Removed unused new_style variable from create_stash, which was a
  leftover from perious rounds.

Interdiff below:

diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 97194576ef..369bfae33d 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -20,8 +20,6 @@ SYNOPSIS
 	     [--] [<pathspec>...]]
 'git stash' clear
 'git stash' create [<message>]
-'git stash' create [-m <message>] [-u|--include-untracked <untracked|all>]
-	     [-- <pathspec>...]
 'git stash' store [-m|--message <message>] [-q|--quiet] <commit>
 
 DESCRIPTION
@@ -55,10 +53,13 @@ push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q
 
 	Save your local modifications to a new 'stash', and run `git reset
 	--hard` to revert them.  The <message> part is optional and gives
-	the description along with the stashed state.  For quickly making
-	a snapshot, you can omit _both_ "save" and <message>, but giving
-	only <message> does not trigger this action to prevent a misspelled
-	subcommand from making an unwanted stash.
+	the description along with the stashed state.
++
+For quickly making a snapshot, you can omit "push".  In this mode,
+non-option arguments are not allowed to prevent a misspelled
+subcommand from making an unwanted stash.  The two exceptions to this
+are `stash -p` which acts as alias for `stash push -p` and pathspecs,
+which are allowed after a double hyphen `--` for disambiguation.
 +
 When pathspec is given to 'git stash push', the new stash records the
 modified states only for the files that match the pathspec.  The index
diff --git a/git-stash.sh b/git-stash.sh
index 1446fbe2e8..18aba1346f 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -61,17 +61,16 @@ clear_stash () {
 create_stash () {
 	stash_msg=
 	untracked=
-	new_style=
 	while test $# != 0
 	do
 		case "$1" in
 		-m|--message)
 			shift
-			stash_msg=${1-"BUG: create_stash () -m requires an argument"}
+			stash_msg=${1?"BUG: create_stash () -m requires an argument"}
 			;;
 		-u|--include-untracked)
 			shift
-			untracked=${1-"BUG: create_stash () -u requires an argument"}
+			untracked=${1?"BUG: create_stash () -u requires an argument"}
 			;;
 		--)
 			shift

Thomas Gummerer (6):
  stash: introduce push verb
  stash: add test for the create command line arguments
  stash: refactor stash_create
  stash: teach 'push' (and 'create_stash') to honor pathspec
  stash: use stash_push for no verb form
  stash: allow pathspecs in the no verb form

 Documentation/git-stash.txt        |  27 ++++++--
 git-stash.sh                       | 127 ++++++++++++++++++++++++++++++-------
 t/t3903-stash.sh                   | 118 +++++++++++++++++++++++++++++++++-
 t/t3905-stash-include-untracked.sh |  26 ++++++++
 4 files changed, 267 insertions(+), 31 deletions(-)

-- 
2.12.0.rc2.399.g0ca89a282


^ permalink raw reply related

* [PATCH v6 2/6] stash: add test for the create command line arguments
From: Thomas Gummerer @ 2017-02-19 11:03 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Johannes Schindelin,
	Øyvind A. Holm, Jakub Narębski, Matthieu Moy,
	Thomas Gummerer
In-Reply-To: <20170219110313.24070-1-t.gummerer@gmail.com>

Currently there is no test showing the expected behaviour of git stash
create's command line arguments.  Add a test for that to show the
current expected behaviour and to make sure future refactorings don't
break those expectations.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 t/t3903-stash.sh | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 3577115807..ffe3549ea5 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -784,4 +784,22 @@ test_expect_success 'push -m shows right message' '
 	test_cmp expect actual
 '
 
+test_expect_success 'create stores correct message' '
+	>foo &&
+	git add foo &&
+	STASH_ID=$(git stash create "create test message") &&
+	echo "On master: create test message" >expect &&
+	git show --pretty=%s -s ${STASH_ID} >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'create with multiple arguments for the message' '
+	>foo &&
+	git add foo &&
+	STASH_ID=$(git stash create test untracked) &&
+	echo "On master: test untracked" >expect &&
+	git show --pretty=%s -s ${STASH_ID} >actual &&
+	test_cmp expect actual
+'
+
 test_done
-- 
2.12.0.rc2.399.g0ca89a282


^ permalink raw reply related

* [PATCH v6 3/6] stash: refactor stash_create
From: Thomas Gummerer @ 2017-02-19 11:03 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Johannes Schindelin,
	Øyvind A. Holm, Jakub Narębski, Matthieu Moy,
	Thomas Gummerer
In-Reply-To: <20170219110313.24070-1-t.gummerer@gmail.com>

Refactor the internal stash_create function to use a -m flag for
specifying the message and -u flag to indicate whether untracked files
should be added to the stash.

This makes it easier to pass a pathspec argument to stash_create in the
next patch.

The user interface for git stash create stays the same.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 git-stash.sh | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/git-stash.sh b/git-stash.sh
index 8365ebba2a..ef5d1b45be 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -58,8 +58,22 @@ clear_stash () {
 }
 
 create_stash () {
-	stash_msg="$1"
-	untracked="$2"
+	stash_msg=
+	untracked=
+	while test $# != 0
+	do
+		case "$1" in
+		-m|--message)
+			shift
+			stash_msg=${1?"BUG: create_stash () -m requires an argument"}
+			;;
+		-u|--include-untracked)
+			shift
+			untracked=${1?"BUG: create_stash () -u requires an argument"}
+			;;
+		esac
+		shift
+	done
 
 	git update-index -q --refresh
 	if no_changes
@@ -268,7 +282,7 @@ push_stash () {
 	git reflog exists $ref_stash ||
 		clear_stash || die "$(gettext "Cannot initialize stash")"
 
-	create_stash "$stash_msg" $untracked
+	create_stash -m "$stash_msg" -u "$untracked"
 	store_stash -m "$stash_msg" -q $w_commit ||
 	die "$(gettext "Cannot save the current status")"
 	say "$(eval_gettext "Saved working directory and index state \$stash_msg")"
@@ -667,7 +681,7 @@ clear)
 	;;
 create)
 	shift
-	create_stash "$*" && echo "$w_commit"
+	create_stash -m "$*" && echo "$w_commit"
 	;;
 store)
 	shift
-- 
2.12.0.rc2.399.g0ca89a282


^ permalink raw reply related

* [PATCH v6 1/6] stash: introduce push verb
From: Thomas Gummerer @ 2017-02-19 11:03 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Johannes Schindelin,
	Øyvind A. Holm, Jakub Narębski, Matthieu Moy,
	Thomas Gummerer
In-Reply-To: <20170219110313.24070-1-t.gummerer@gmail.com>

Introduce a new git stash push verb in addition to git stash save.  The
push verb is used to transition from the current command line arguments
to a more conventional way, in which the message is given as an argument
to the -m option.

This allows us to have pathspecs at the end of the command line
arguments like other Git commands do, so that the user can say which
subset of paths to stash (and leave others behind).

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 Documentation/git-stash.txt |  3 +++
 git-stash.sh                | 46 ++++++++++++++++++++++++++++++++++++++++++---
 t/t3903-stash.sh            |  9 +++++++++
 3 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 2e9cef06e6..0f602ea0c8 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -15,6 +15,8 @@ SYNOPSIS
 'git stash' branch <branchname> [<stash>]
 'git stash' [save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
 	     [-u|--include-untracked] [-a|--all] [<message>]]
+'git stash' push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
+	     [-u|--include-untracked] [-a|--all] [-m|--message <message>]]
 'git stash' clear
 'git stash' create [<message>]
 'git stash' store [-m|--message <message>] [-q|--quiet] <commit>
@@ -46,6 +48,7 @@ OPTIONS
 -------
 
 save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
+push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>]::
 
 	Save your local modifications to a new 'stash', and run `git reset
 	--hard` to revert them.  The <message> part is optional and gives
diff --git a/git-stash.sh b/git-stash.sh
index 10c284d1aa..8365ebba2a 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -9,6 +9,8 @@ USAGE="list [<options>]
    or: $dashless branch <branchname> [<stash>]
    or: $dashless [save [--patch] [-k|--[no-]keep-index] [-q|--quiet]
 		       [-u|--include-untracked] [-a|--all] [<message>]]
+   or: $dashless push [--patch] [-k|--[no-]keep-index] [-q|--quiet]
+		      [-u|--include-untracked] [-a|--all] [-m <message>]
    or: $dashless clear"
 
 SUBDIRECTORY_OK=Yes
@@ -189,10 +191,11 @@ store_stash () {
 	return $ret
 }
 
-save_stash () {
+push_stash () {
 	keep_index=
 	patch_mode=
 	untracked=
+	stash_msg=
 	while test $# != 0
 	do
 		case "$1" in
@@ -216,6 +219,11 @@ save_stash () {
 		-a|--all)
 			untracked=all
 			;;
+		-m|--message)
+			shift
+			test -z ${1+x} && usage
+			stash_msg=$1
+			;;
 		--help)
 			show_help
 			;;
@@ -251,8 +259,6 @@ save_stash () {
 		die "$(gettext "Can't use --patch and --include-untracked or --all at the same time")"
 	fi
 
-	stash_msg="$*"
-
 	git update-index -q --refresh
 	if no_changes
 	then
@@ -291,6 +297,36 @@ save_stash () {
 	fi
 }
 
+save_stash () {
+	push_options=
+	while test $# != 0
+	do
+		case "$1" in
+		--)
+			shift
+			break
+			;;
+		-*)
+			# pass all options through to push_stash
+			push_options="$push_options $1"
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+
+	stash_msg="$*"
+
+	if test -z "$stash_msg"
+	then
+		push_stash $push_options
+	else
+		push_stash $push_options -m "$stash_msg"
+	fi
+}
+
 have_stash () {
 	git rev-parse --verify --quiet $ref_stash >/dev/null
 }
@@ -617,6 +653,10 @@ save)
 	shift
 	save_stash "$@"
 	;;
+push)
+	shift
+	push_stash "$@"
+	;;
 apply)
 	shift
 	apply_stash "$@"
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 2de3e18ce6..3577115807 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -775,4 +775,13 @@ test_expect_success 'stash is not confused by partial renames' '
 	test_path_is_missing file
 '
 
+test_expect_success 'push -m shows right message' '
+	>foo &&
+	git add foo &&
+	git stash push -m "test message" &&
+	echo "stash@{0}: On master: test message" >expect &&
+	git stash list -1 >actual &&
+	test_cmp expect actual
+'
+
 test_done
-- 
2.12.0.rc2.399.g0ca89a282


^ permalink raw reply related

* [PATCH v6 4/6] stash: teach 'push' (and 'create_stash') to honor pathspec
From: Thomas Gummerer @ 2017-02-19 11:03 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Johannes Schindelin,
	Øyvind A. Holm, Jakub Narębski, Matthieu Moy,
	Thomas Gummerer
In-Reply-To: <20170219110313.24070-1-t.gummerer@gmail.com>

While working on a repository, it's often helpful to stash the changes
of a single or multiple files, and leave others alone.  Unfortunately
git currently offers no such option.  git stash -p can be used to work
around this, but it's often impractical when there are a lot of changes
over multiple files.

Allow 'git stash push' to take pathspec to specify which paths to stash.

Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 Documentation/git-stash.txt        |  9 ++++-
 git-stash.sh                       | 48 +++++++++++++++++++------
 t/t3903-stash.sh                   | 72 ++++++++++++++++++++++++++++++++++++++
 t/t3905-stash-include-untracked.sh | 26 ++++++++++++++
 4 files changed, 143 insertions(+), 12 deletions(-)

diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 0f602ea0c8..b7db939a06 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -17,6 +17,7 @@ SYNOPSIS
 	     [-u|--include-untracked] [-a|--all] [<message>]]
 'git stash' push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
 	     [-u|--include-untracked] [-a|--all] [-m|--message <message>]]
+	     [--] [<pathspec>...]
 'git stash' clear
 'git stash' create [<message>]
 'git stash' store [-m|--message <message>] [-q|--quiet] <commit>
@@ -48,7 +49,7 @@ OPTIONS
 -------
 
 save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
-push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>]::
+push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--] [<pathspec>...]::
 
 	Save your local modifications to a new 'stash', and run `git reset
 	--hard` to revert them.  The <message> part is optional and gives
@@ -57,6 +58,12 @@ push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q
 	only <message> does not trigger this action to prevent a misspelled
 	subcommand from making an unwanted stash.
 +
+When pathspec is given to 'git stash push', the new stash records the
+modified states only for the files that match the pathspec.  The index
+entries and working tree files are then rolled back to the state in
+HEAD only for these files, too, leaving files that do not match the
+pathspec intact.
++
 If the `--keep-index` option is used, all changes already added to the
 index are left intact.
 +
diff --git a/git-stash.sh b/git-stash.sh
index ef5d1b45be..b55983d1fd 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -11,6 +11,7 @@ USAGE="list [<options>]
 		       [-u|--include-untracked] [-a|--all] [<message>]]
    or: $dashless push [--patch] [-k|--[no-]keep-index] [-q|--quiet]
 		      [-u|--include-untracked] [-a|--all] [-m <message>]
+		      [-- <pathspec>...]
    or: $dashless clear"
 
 SUBDIRECTORY_OK=Yes
@@ -35,15 +36,15 @@ else
 fi
 
 no_changes () {
-	git diff-index --quiet --cached HEAD --ignore-submodules -- &&
-	git diff-files --quiet --ignore-submodules &&
+	git diff-index --quiet --cached HEAD --ignore-submodules -- "$@" &&
+	git diff-files --quiet --ignore-submodules -- "$@" &&
 	(test -z "$untracked" || test -z "$(untracked_files)")
 }
 
 untracked_files () {
 	excl_opt=--exclude-standard
 	test "$untracked" = "all" && excl_opt=
-	git ls-files -o -z $excl_opt
+	git ls-files -o -z $excl_opt -- "$@"
 }
 
 clear_stash () {
@@ -71,12 +72,16 @@ create_stash () {
 			shift
 			untracked=${1?"BUG: create_stash () -u requires an argument"}
 			;;
+		--)
+			shift
+			break
+			;;
 		esac
 		shift
 	done
 
 	git update-index -q --refresh
-	if no_changes
+	if no_changes "$@"
 	then
 		exit 0
 	fi
@@ -108,7 +113,7 @@ create_stash () {
 		# Untracked files are stored by themselves in a parentless commit, for
 		# ease of unpacking later.
 		u_commit=$(
-			untracked_files | (
+			untracked_files "$@" | (
 				GIT_INDEX_FILE="$TMPindex" &&
 				export GIT_INDEX_FILE &&
 				rm -f "$TMPindex" &&
@@ -131,7 +136,7 @@ create_stash () {
 			git read-tree --index-output="$TMPindex" -m $i_tree &&
 			GIT_INDEX_FILE="$TMPindex" &&
 			export GIT_INDEX_FILE &&
-			git diff-index --name-only -z HEAD -- >"$TMP-stagenames" &&
+			git diff-index --name-only -z HEAD -- "$@" >"$TMP-stagenames" &&
 			git update-index -z --add --remove --stdin <"$TMP-stagenames" &&
 			git write-tree &&
 			rm -f "$TMPindex"
@@ -145,7 +150,7 @@ create_stash () {
 
 		# find out what the user wants
 		GIT_INDEX_FILE="$TMP-index" \
-			git add--interactive --patch=stash -- &&
+			git add--interactive --patch=stash -- "$@" &&
 
 		# state of the working tree
 		w_tree=$(GIT_INDEX_FILE="$TMP-index" git write-tree) ||
@@ -274,7 +279,7 @@ push_stash () {
 	fi
 
 	git update-index -q --refresh
-	if no_changes
+	if no_changes "$@"
 	then
 		say "$(gettext "No local changes to save")"
 		exit 0
@@ -282,18 +287,39 @@ push_stash () {
 	git reflog exists $ref_stash ||
 		clear_stash || die "$(gettext "Cannot initialize stash")"
 
-	create_stash -m "$stash_msg" -u "$untracked"
+	create_stash -m "$stash_msg" -u "$untracked" -- "$@"
 	store_stash -m "$stash_msg" -q $w_commit ||
 	die "$(gettext "Cannot save the current status")"
 	say "$(eval_gettext "Saved working directory and index state \$stash_msg")"
 
 	if test -z "$patch_mode"
 	then
-		git reset --hard ${GIT_QUIET:+-q}
+		if test $# != 0
+		then
+			saved_untracked=
+			if test -n "$(git ls-files --others -- "$@")"
+			then
+				saved_untracked=$(
+					git ls-files -z --others -- "$@" |
+					    xargs -0 git stash create -u all --)
+			fi
+			git ls-files -z -- "$@" | xargs -0 git reset ${GIT_QUIET:+-q} --
+			git ls-files -z --modified -- "$@" | xargs -0 git checkout ${GIT_QUIET:+-q} HEAD --
+			if test -n "$(git ls-files -z --others -- "$@")"
+			then
+				git ls-files -z --others -- "$@" | xargs -0 git clean --force -d ${GIT_QUIET:+-q} --
+			fi
+			if test -n "$saved_untracked"
+			then
+				git stash pop -q $saved_untracked
+			fi
+		else
+			git reset --hard ${GIT_QUIET:+-q}
+		fi
 		test "$untracked" = "all" && CLEAN_X_OPTION=-x || CLEAN_X_OPTION=
 		if test -n "$untracked"
 		then
-			git clean --force --quiet -d $CLEAN_X_OPTION
+			git clean --force --quiet -d $CLEAN_X_OPTION -- "$@"
 		fi
 
 		if test "$keep_index" = "t" && test -n "$i_tree"
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index ffe3549ea5..4fb800eec8 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -802,4 +802,76 @@ test_expect_success 'create with multiple arguments for the message' '
 	test_cmp expect actual
 '
 
+test_expect_success 'stash -- <filename> stashes and restores the file' '
+	>foo &&
+	>bar &&
+	git add foo bar &&
+	git stash push -- foo &&
+	test_path_is_file bar &&
+	test_path_is_missing foo &&
+	git stash pop &&
+	test_path_is_file foo &&
+	test_path_is_file bar
+'
+
+test_expect_success 'stash with multiple filename arguments' '
+	>foo &&
+	>bar &&
+	>extra &&
+	git add foo bar extra &&
+	git stash push -- foo bar &&
+	test_path_is_missing bar &&
+	test_path_is_missing foo &&
+	test_path_is_file extra &&
+	git stash pop &&
+	test_path_is_file foo &&
+	test_path_is_file bar &&
+	test_path_is_file extra
+'
+
+test_expect_success 'stash with file including $IFS character' '
+	>"foo bar" &&
+	>foo &&
+	>bar &&
+	git add foo* &&
+	git stash push -- "foo b*" &&
+	test_path_is_missing "foo bar" &&
+	test_path_is_file foo &&
+	test_path_is_file bar &&
+	git stash pop &&
+	test_path_is_file "foo bar" &&
+	test_path_is_file foo &&
+	test_path_is_file bar
+'
+
+test_expect_success 'stash push -p with pathspec shows no changes only onece' '
+	>file &&
+	git add file &&
+	git stash push -p not-file >actual &&
+	echo "No local changes to save" >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'stash push with pathspec shows no changes when there are none' '
+	>file &&
+	git add file &&
+	git stash push not-file >actual &&
+	echo "No local changes to save" >expect &&
+	test_cmp expect actual
+'
+
+test_expect_success 'untracked file is not removed when using pathspecs' '
+	>untracked &&
+	git stash push untracked &&
+	test_path_is_file untracked
+'
+
+test_expect_success 'untracked files are left in place when -u is not given' '
+	>file &&
+	git add file &&
+	>untracked &&
+	git stash push file &&
+	test_path_is_file untracked
+'
+
 test_done
diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh
index f372fc8ca8..193adc7b68 100755
--- a/t/t3905-stash-include-untracked.sh
+++ b/t/t3905-stash-include-untracked.sh
@@ -185,4 +185,30 @@ test_expect_success 'stash save --all is stash poppable' '
 	test -s .gitignore
 '
 
+test_expect_success 'stash push --include-untracked with pathspec' '
+	>foo &&
+	>bar &&
+	git stash push --include-untracked -- foo &&
+	test_path_is_file bar &&
+	test_path_is_missing foo &&
+	git stash pop &&
+	test_path_is_file bar &&
+	test_path_is_file foo
+'
+
+test_expect_success 'stash push with $IFS character' '
+	>"foo bar" &&
+	>foo &&
+	>bar &&
+	git add foo* &&
+	git stash push --include-untracked -- "foo b*" &&
+	test_path_is_missing "foo bar" &&
+	test_path_is_file foo &&
+	test_path_is_file bar &&
+	git stash pop &&
+	test_path_is_file "foo bar" &&
+	test_path_is_file foo &&
+	test_path_is_file bar
+'
+
 test_done
-- 
2.12.0.rc2.399.g0ca89a282


^ permalink raw reply related

* [PATCH v6 6/6] stash: allow pathspecs in the no verb form
From: Thomas Gummerer @ 2017-02-19 11:03 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Jeff King, Johannes Schindelin,
	Øyvind A. Holm, Jakub Narębski, Matthieu Moy,
	Thomas Gummerer
In-Reply-To: <20170219110313.24070-1-t.gummerer@gmail.com>

Now that stash_push is used in the no verb form of stash, allow
specifying the command line for this form as well.  Always use -- to
disambiguate pathspecs from other non-option arguments.

Also make git stash -p an alias for git stash push -p.  This allows
users to use git stash -p <pathspec>.

Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 Documentation/git-stash.txt | 11 +++++++----
 git-stash.sh                |  3 +++
 t/t3903-stash.sh            | 15 +++++++++++++++
 3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 3f7fa88ddc..369bfae33d 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -53,10 +53,13 @@ push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q
 
 	Save your local modifications to a new 'stash', and run `git reset
 	--hard` to revert them.  The <message> part is optional and gives
-	the description along with the stashed state.  For quickly making
-	a snapshot, you can omit _both_ "save" and <message>, but giving
-	only <message> does not trigger this action to prevent a misspelled
-	subcommand from making an unwanted stash.
+	the description along with the stashed state.
++
+For quickly making a snapshot, you can omit "push".  In this mode,
+non-option arguments are not allowed to prevent a misspelled
+subcommand from making an unwanted stash.  The two exceptions to this
+are `stash -p` which acts as alias for `stash push -p` and pathspecs,
+which are allowed after a double hyphen `--` for disambiguation.
 +
 When pathspec is given to 'git stash push', the new stash records the
 modified states only for the files that match the pathspec.  The index
diff --git a/git-stash.sh b/git-stash.sh
index 1e55cd5fdd..18aba1346f 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -666,12 +666,15 @@ apply_to_branch () {
 	}
 }
 
+test "$1" = "-p" && set "push" "$@"
+
 PARSE_CACHE='--not-parsed'
 # The default command is "push" if nothing but options are given
 seen_non_option=
 for opt
 do
 	case "$opt" in
+	--) break ;;
 	-*) ;;
 	*) seen_non_option=t; break ;;
 	esac
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 7f90a247b4..c0ae41e724 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -872,4 +872,19 @@ test_expect_success 'untracked files are left in place when -u is not given' '
 	test_path_is_file untracked
 '
 
+test_expect_success 'stash without verb with pathspec' '
+	>"foo bar" &&
+	>foo &&
+	>bar &&
+	git add foo* &&
+	git stash -- "foo b*" &&
+	test_path_is_missing "foo bar" &&
+	test_path_is_file foo &&
+	test_path_is_file bar &&
+	git stash pop &&
+	test_path_is_file "foo bar" &&
+	test_path_is_file foo &&
+	test_path_is_file bar
+'
+
 test_done
-- 
2.12.0.rc2.399.g0ca89a282


^ permalink raw reply related

* Re: Git bisect does not find commit introducing the bug
From: Alex Hoffman @ 2017-02-19 11:32 UTC (permalink / raw)
  To: Christian Couder; +Cc: Johannes Sixt, Stephan Beyer, git
In-Reply-To: <CAP8UFD3ngMvVy2XLzYNn9OFbS+zQpWTW=pravpHhA-0PcDVhfg@mail.gmail.com>

> At the end of the git-bisect man page (in the SEE ALSO section) there
> is a link to https://github.com/git/git/blob/master/Documentation/git-bisect-lk2009.txt
> which has a lot of details about how bisect works.
>

Thanks for pointing out the SEE ALSO section. I think it makes sense
to include/describe the entire algorithm in the man page itself,
although I am not sure whether the graphs would be always correctly
visually represented in the man page format.

> The goal is to find the first bad commit, which is a commit that has
> only good parents.

OK, bisect's mission is more exact than I thought, which is good. M

> As o1 is an ancestor of G, then o1 is considered good by the bisect algorithm.
> If it was bad, it would means that there is a transition from bad to
> good between o1 and G.
> But when a good commit is an ancestor of the bad commit, git bisect
> makes the assumption that there is no transition from bad to good in
> the graph.

The assumption that there is no transition from bad to good in the
graph did not hold in my example and it does not hold when a feature
was recently introduced and gets broken relative shortly afterwards.
But I consider it is easy to change the algorithm not to assume, but
rather to check it.

> git bisect makes some assumptions that are true most of the time, so
> in practice it works well most of the time.

Whatever the definition of "most of the time" everyone might have, I
think there is room for improvement. Below I am trying to make a small
change to the current algorithm in order to deal with the assumption
that sometimes does not hold (e.g in my example), by explicitly
validating the check.

> --o1--o2--o3--G--X1
>     \                \
>      x1--x2--x3--x4--X2--B--
>       \              /
>        y1--y2--y3

Step 1a. (Unchanged) keep only the commits that:

        a) are ancestor of the "bad" commit (including the "bad" commit itself),
        b) are not ancestor of a "good" commit (excluding the "good" commits).

The following graph results:
      x1--x2--x3--x4--X2--B--
       \              /
        y1--y2--y3

Step 1b. (New) Mark all root commits of the resulting graph (i.e
commits without parents) as unconfirmed (unconfirmed=node that has
only bad parents). Remove all root commits that user already confirmed
(e.g if user already marked its parent as good right before starting
bisect run). For every unconfirmed root commit check if it has any
good parents. In the example above check whether x1 has good parents.
     If the current root element has any parents and none of them is
good, we can delete all paths from it until to the next commit that
has a parent in the ancestors of GOOD. In the example above to delete
the path x1-x3 and x1-y3. Also add new resulting root commits to the
list of unconfirmed commits (commit x4).
     Otherwise mark it as confirmed.

Step2. Continue the existing algorithm.


If this improvement works (i.e you do not find any bugs in it and it
is feasible to implement, which seems to me) the following would be
its advantages:
1. An assumption less, as we explicitly check the assumption.
2. It might be quicker, because we delete parts of graph that cannot
contain transitions.
3. It returns more exact results.

VG

^ permalink raw reply

* Re: Git bisect does not find commit introducing the bug
From: Alex Hoffman @ 2017-02-19 12:43 UTC (permalink / raw)
  To: Christian Couder; +Cc: Johannes Sixt, Stephan Beyer, git
In-Reply-To: <CAMX8fZVeAEJ5tfCO_4Pebnq=rysaJ2xDMjH-9pjmPeF4FziLFw@mail.gmail.com>

Below is a correction of the first proposed algorithm:

>--o1--o2--o3--G --X1
>    \                \
>     x1--x2--x3--x4--X2--B--
>      \              /
>       y1--y2--y3
>
Step 1a. (Unchanged) keep only the commits that:

        a) are ancestor of the "bad" commit (including the "bad" commit itself),
        b) are not ancestor of a "good" commit (excluding the "good" commits).

The following graph results:
      x1--x2--x3--x4--X2--B--
       \              /
        y1--y2--y3

Step 1b. (New) Mark all commits of the resulting graph as unconfirmed
(unconfirmed=node without good ancestors).
Mark as confirmed all descendants of commits that user marked
explicitly as good (e.g if user already marked its parent/grand
parent/... as good right before starting bisect run).
Step 1c. From all unconfirmed root commits build a set SET_GOOD of
those with any good parents in the original graph (root commit =
commit without parents in the resulting graph) and one SET_BAD for
commits with only BAD parents. To build a set means to ask explicitly
the user (or the command passed in git bisect run) whether any of its
parents is good. In the example above find out whether x1 has any good
parents or no parent at all and if so add it to SET_GOOD, otherwise to
SET_BAD.
Mark as confirmed each commit in SET_GOOD and all its descendants.
For every commit in SET_BAD delete all paths from it until to the next
confirmed commit. In the example above if x1 is in SET_BAD delete the
path x1-x3 and x1-y3. If any new root commits result (commit x4), redo
step 1c with them.


Step2. Continue the existing algorithm.

If this improvement works (i.e you do not find any bugs in it and it
is feasible to implement, which seems to me) the following would be
its advantages:
1. An assumption less, as we explicitly check the assumption.
2. It might be quicker, because we delete parts of graph that cannot
contain transitions.
3. It returns more exact results.

VG

^ permalink raw reply

* Re: Git bisect does not find commit introducing the bug
From: Christian Couder @ 2017-02-19 13:07 UTC (permalink / raw)
  To: Alex Hoffman; +Cc: Johannes Sixt, Stephan Beyer, git
In-Reply-To: <CAMX8fZVeAEJ5tfCO_4Pebnq=rysaJ2xDMjH-9pjmPeF4FziLFw@mail.gmail.com>

On Sun, Feb 19, 2017 at 12:32 PM, Alex Hoffman <spec@gal.ro> wrote:
>> At the end of the git-bisect man page (in the SEE ALSO section) there
>> is a link to https://github.com/git/git/blob/master/Documentation/git-bisect-lk2009.txt
>> which has a lot of details about how bisect works.
>
> Thanks for pointing out the SEE ALSO section. I think it makes sense
> to include/describe the entire algorithm in the man page itself,
> although I am not sure whether the graphs would be always correctly
> visually represented in the man page format.

It would possibly be very long to describe the entire algorithm, as it
can be quite complex in some cases and it is difficult to understand
without graphs. Maybe we could describe it, or some parts of it, in a
separate document and provide links at different places in the man
page.
Anyway feel free to send patches.

>> The goal is to find the first bad commit, which is a commit that has
>> only good parents.
>
> OK, bisect's mission is more exact than I thought, which is good. M

Good that you seem to agree with this goal.

>> As o1 is an ancestor of G, then o1 is considered good by the bisect algorithm.
>> If it was bad, it would means that there is a transition from bad to
>> good between o1 and G.
>> But when a good commit is an ancestor of the bad commit, git bisect
>> makes the assumption that there is no transition from bad to good in
>> the graph.
>
> The assumption that there is no transition from bad to good in the
> graph did not hold in my example and it does not hold when a feature
> was recently introduced and gets broken relative shortly afterwards.
> But I consider it is easy to change the algorithm not to assume, but
> rather to check it.

I don't think the default algorithm will change soon, but there have
been discussions for a long time about adding options to use different
algorithms.

For example people have been discussing a "--first-parent" option for
many years as well as recently. It would bisect only along the first
parents of the involved commits, and it could help find the merge
commit that introduced a bug in the mainline.

>> git bisect makes some assumptions that are true most of the time, so
>> in practice it works well most of the time.
>
> Whatever the definition of "most of the time" everyone might have, I
> think there is room for improvement.

So feel free to send patches that would implement an option with the
improvements you want.

> Below I am trying to make a small
> change to the current algorithm in order to deal with the assumption
> that sometimes does not hold (e.g in my example), by explicitly
> validating the check.
>
>> --o1--o2--o3--G--X1
>>     \                \
>>      x1--x2--x3--x4--X2--B--
>>       \              /
>>        y1--y2--y3
>
> Step 1a. (Unchanged) keep only the commits that:
>
>         a) are ancestor of the "bad" commit (including the "bad" commit itself),
>         b) are not ancestor of a "good" commit (excluding the "good" commits).
>
> The following graph results:
>       x1--x2--x3--x4--X2--B--
>        \              /
>         y1--y2--y3

I would say that the above graph is missing X1.

> Step 1b. (New) Mark all root commits of the resulting graph (i.e
> commits without parents) as unconfirmed (unconfirmed=node that has
> only bad parents). Remove all root commits that user already confirmed
> (e.g if user already marked its parent as good right before starting
> bisect run). For every unconfirmed root commit check if it has any
> good parents. In the example above check whether x1 has good parents.

I think I understand the above...

>      If the current root element has any parents and none of them is
> good, we can delete all paths from it until to the next commit that
> has a parent in the ancestors of GOOD. In the example above to delete
> the path x1-x3 and x1-y3. Also add new resulting root commits to the
> list of unconfirmed commits (commit x4).
>      Otherwise mark it as confirmed.

... but I don't understand the logic of the above. If the root element
has a bad parent, then it means that the "first bad commit" is either
the bad parent or one of its ancestors, so it is not logical to delete
it. In your example if x1 has one bad parent, this bad parent and its
ancestors should be included in the search of the first bad commit.

Otherwise the goal is not any more to find the first bad commit.

PS: I saw that you have just sent another version of the algorithm,
but I don't want to take a look at it right now. Anyway I am keeping
my above comments as they might still be useful.

> Step2. Continue the existing algorithm.
>
>
> If this improvement works (i.e you do not find any bugs in it and it
> is feasible to implement, which seems to me)

As you describe it, I don't think it is compatible with the goal of
finding the first bad commit.
Also there are many things that are feasible to implement, but it
doesn't mean that someone will soon make the effort to implement them
in a way that looks good enough to be deemed worth merging into the
current code base.

> the following would be
> its advantages:
> 1. An assumption less, as we explicitly check the assumption.

Checking can be costly. If the probability that the check will fail is
very low, while the cost of checking is high, it is less costly on
average to not check.

> 2. It might be quicker, because we delete parts of graph that cannot
> contain transitions.

I don't agree that it's a good idea to delete what you suggest above.
Or if you think that the goal should not be to find the "first bad
commit" in the above case, then you should explain what the goal
should be.

> 3. It returns more exact results.

Yeah, but checking every commit related to the good and bad commits
would also return more exact results. (This can probably be done using
`git rebase --exec ...` by the way.) One could even print a nice graph
with all the good and bad commits. The problem is that it would not be
efficient. If git bisect makes some assumptions, it is because they
have been deemed reasonable and they have worked well in practice.
It's also because the goal of git bisect is to be efficient, otherwise
there would be no point in using a binary search algorithm in the
first place.

^ permalink raw reply

* Re: Git bisect does not find commit introducing the bug
From: Johannes Sixt @ 2017-02-19 14:13 UTC (permalink / raw)
  To: Alex Hoffman; +Cc: Christian Couder, Stephan Beyer, git
In-Reply-To: <CAMX8fZVeAEJ5tfCO_4Pebnq=rysaJ2xDMjH-9pjmPeF4FziLFw@mail.gmail.com>

Am 19.02.2017 um 12:32 schrieb Alex Hoffman:
> The assumption that there is no transition from bad to good in the
> graph did not hold in my example and it does not hold when a feature
> was recently introduced and gets broken relative shortly afterwards.

Then you must adjust your definition of "good": All commits that do not 
have the feature, yet, are "good": since they do not have the feature in 
the first place, they cannot have the breakage that you found in the 
feature.

That is exactly the situation in your original example! But you 
constructed the condition of goodness in such a simplistic way 
(depending on the presence of a string), that it was impossible to 
distinguish between "does not have the feature at all" and "has the 
feature, but it is broken".

-- Hannes


^ permalink raw reply

* Re: [PATCH] l10n: de.po: translate 241 messages
From: Ralf Thielow @ 2017-02-19 18:10 UTC (permalink / raw)
  To: Phillip Sz
  Cc: git, Thomas Rast, Jan Krüger, Christian Stimming,
	Matthias Rüster, Magnus Görlitz
In-Reply-To: <0d720395-9e92-e6e8-2f88-aff8192ae946@gmail.com>

Hi Phillip,

thanks for review!

Am 17. Februar 2017 um 22:56 schrieb Phillip Sz <phillip.szelat@gmail.com>:
>>  #: remote.c:2092
>>  #, 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"
>> +msgstr[0] "Ihr Branch ist %2$d Commit vor '%1$s'.\n"
>> +msgstr[1] "Ihr Branch ist %2$d Commits vor '%1$s'.\n"
>>
>
> Does this "%2$d" works and why not use '%s'?
>

With this syntax you can reorder the format specifiers.  In the orignal
message, the branch name comes first and then the number of commits.
Despite "%2$d" is the first specifier in the message, it tells that it is the
second in the format arguments and therefore gets replaced with the
number of commits instead of the branch name.

>>  #: sequencer.c:840
>> -#, fuzzy
>>  msgid "could not read HEAD's commit message"
>> -msgstr "Konnte Commit-Beschreibung nicht lesen: %s"
>> +msgstr "Konnte Commit-Beschreibung von HEAD nicht lesen"
>>
>
>>  #: sequencer.c:846
>> -#, fuzzy, c-format
>> +#, c-format
>>  msgid "cannot write '%s'"
>> -msgstr "kann '%s' nicht erstellen"
>> +msgstr "kann '%s' nicht schreiben"
>
> I think we should either use "kann" or "konnte".
> We have used both and maybe we should unify it? What do you think?
>

Sure.  It's a good idea to unify the translation.  I'd prefer "kann".

>>  #: sequencer.c:1341
>> -#, fuzzy
>>  msgid "please fix this using 'git rebase --edit-todo'."
>>  msgstr "Bitte beheben Sie das, indem Sie 'git rebase --edit-todo' ausführen."
>
> Maybe: "Bitte beheben Sie dieses, indem Sie 'git rebase --edit-todo'
> ausführen."
>
>>  #: git-add--interactive.perl:1074
>>  #, perl-format
>>  msgid ""
>>  "---\n"
>>  "To remove '%s' lines, make them ' ' lines (context).\n"
>>  "To remove '%s' lines, delete them.\n"
>>  "Lines starting with %s will be removed.\n"
>>  msgstr ""
>> +"---\n"
>> +"Um '%s' Zeilen zu entfernen, machen Sie aus diesen ' ' Zeilen (Kontext).\n"
>> +"Um '%s' Zeilen zu entferenen, löschen Sie diese.\n"
>> +"Zeilen, die mit %s beginnen, werden entfernt.\n"
>>
>
> "Um '%s' Zeilen zu entfernen, löschen Sie diese.\n"
>
> Anyway thanks a lot for your awesome work!
>
>         Phillip

Ralf

^ permalink raw reply

* [PATCH v2] l10n: de.po: translate 241 messages
From: Ralf Thielow @ 2017-02-19 18:11 UTC (permalink / raw)
  To: git, Phillip Szelat
  Cc: Thomas Rast, Jan Krüger, Christian Stimming,
	Matthias Rüster, Magnus Görlitz, Ralf Thielow
In-Reply-To: <20170217174132.8816-1-ralf.thielow@gmail.com>

Translate 241 messages came from git.pot update in 673bfad09
(l10n: git.pot: v2.12.0 round 1 (239 new, 15 removed)) and a4d94835a
(l10n: git.pot: v2.12.0 round 2 (2 new)).

Signed-off-by: Ralf Thielow <ralf.thielow@gmail.com>
---
 po/de.po | 750 ++++++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 409 insertions(+), 341 deletions(-)

diff --git a/po/de.po b/po/de.po
index 2326da1fd..e9c86f548 100644
--- a/po/de.po
+++ b/po/de.po
@@ -913,20 +913,20 @@ msgstr ""
 
 #: bisect.c:742
 #, c-format
 msgid ""
 "The merge base %s is %s.\n"
 "This means the first '%s' commit is between %s and [%s].\n"
 msgstr ""
 "Die Merge-Basis %s ist %s.\n"
-"Das bedeutet, der erste '%s' Commit befindet sich zwischen %s und [%s]\n"
+"Das bedeutet, der erste '%s' Commit befindet sich zwischen %s und [%s].\n"
 
 #: bisect.c:750
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "Some %s revs are not ancestors of the %s rev.\n"
 "git bisect cannot work properly in this case.\n"
 "Maybe you mistook %s and %s revs?\n"
 msgstr ""
 "Manche %s Commits sind keine Vorgänger des %s Commits.\n"
 "git bisect kann in diesem Fall nicht richtig arbeiten.\n"
 "Vielleicht verwechselten Sie %s und %s Commits?\n"
@@ -1343,19 +1343,19 @@ msgid "bad zlib compression level %d"
 msgstr "ungültiger zlib Komprimierungsgrad %d"
 
 #: config.c:993
 #, c-format
 msgid "invalid mode for object creation: %s"
 msgstr "Ungültiger Modus für Objekterstellung: %s"
 
 #: config.c:1149
-#, fuzzy, c-format
+#, c-format
 msgid "bad pack compression level %d"
-msgstr "Komprimierungsgrad für Paketierung"
+msgstr "ungültiger Komprimierungsgrad (%d) für Paketierung"
 
 #: config.c:1339
 msgid "unable to parse command-line config"
 msgstr ""
 "Konnte die über die Befehlszeile angegebene Konfiguration nicht parsen."
 
 #: config.c:1389
 msgid "unknown error occurred while reading the configuration files"
@@ -1375,19 +1375,19 @@ msgid "bad config variable '%s' in file '%s' at line %d"
 msgstr "ungültige Konfigurationsvariable '%s' in Datei '%s' bei Zeile %d"
 
 #: config.c:1804
 #, c-format
 msgid "%s has multiple values"
 msgstr "%s hat mehrere Werte"
 
 #: config.c:2225 config.c:2450
-#, fuzzy, c-format
+#, c-format
 msgid "fstat on %s failed"
-msgstr "\"stash\" fehlgeschlagen"
+msgstr "fstat auf %s fehlgeschlagen"
 
 #: config.c:2343
 #, c-format
 msgid "could not set '%s' to '%s'"
 msgstr "Konnte '%s' nicht zu '%s' setzen."
 
 #: config.c:2345
 #, c-format
@@ -1616,19 +1616,19 @@ msgstr "Fehler beim Sammeln von Namen und Informationen zum Kernel"
 
 #: dir.c:1981
 msgid "Untracked cache is disabled on this system or location."
 msgstr ""
 "Cache für unversionierte Dateien ist auf diesem System oder\n"
 "für dieses Verzeichnis deaktiviert."
 
 #: dir.c:2759
-#, fuzzy, c-format
+#, c-format
 msgid "could not migrate git directory from '%s' to '%s'"
-msgstr "Konnte Verzeichnis '%s' nicht erstellen."
+msgstr "Konnte Git-Verzeichnis nicht von '%s' nach '%s' migrieren."
 
 #: fetch-pack.c:213
 msgid "git fetch-pack: expected shallow list"
 msgstr "git fetch-pack: erwartete shallow-Liste"
 
 #: fetch-pack.c:225
 msgid "git fetch-pack: expected ACK/NAK, got EOF"
 msgstr "git fetch-pack: ACK/NAK erwartet, EOF bekommen"
@@ -1803,17 +1803,17 @@ msgstr "konnte temporäre Datei nicht erstellen"
 #: gpg-interface.c:217
 #, c-format
 msgid "failed writing detached signature to '%s'"
 msgstr "Fehler beim Schreiben der losgelösten Signatur nach '%s'"
 
 #: graph.c:96
 #, c-format
 msgid "ignore invalid color '%.*s' in log.graphColors"
-msgstr ""
+msgstr "Ignoriere ungültige Farbe '%.*s' in log.graphColors"
 
 #: grep.c:1794
 #, c-format
 msgid "'%s': unable to read %s"
 msgstr "'%s': konnte %s nicht lesen"
 
 #: grep.c:1811 builtin/clone.c:381 builtin/diff.c:81 builtin/rm.c:133
 #, c-format
@@ -2320,17 +2320,17 @@ msgstr "%s: 'literal' und 'glob' sind inkompatibel"
 #: pathspec.c:363
 #, c-format
 msgid "%s: '%s' is outside repository"
 msgstr "%s: '%s' liegt außerhalb des Repositories"
 
 #: pathspec.c:451
 #, c-format
 msgid "'%s' (mnemonic: '%c')"
-msgstr ""
+msgstr "'%s' (Kürzel: '%c')"
 
 #: pathspec.c:461
 #, c-format
 msgid "%s: pathspec magic not supported by this command: %s"
 msgstr ""
 "%s: Pfadspezifikationsangabe wird von diesem Befehl nicht unterstützt: %s"
 
 #: pathspec.c:511
@@ -2418,19 +2418,19 @@ msgid "%%(body) does not take arguments"
 msgstr "%%(body) akzeptiert keine Argumente"
 
 #: ref-filter.c:85
 #, c-format
 msgid "%%(subject) does not take arguments"
 msgstr "%%(subject) akzeptiert keine Argumente"
 
 #: ref-filter.c:92
-#, fuzzy, c-format
+#, c-format
 msgid "%%(trailers) does not take arguments"
-msgstr "%%(body) akzeptiert keine Argumente"
+msgstr "%%(trailers) akzeptiert keine Argumente"
 
 #: ref-filter.c:111
 #, c-format
 msgid "positive value expected contents:lines=%s"
 msgstr "Positiver Wert erwartet contents:lines=%s"
 
 #: ref-filter.c:113
 #, c-format
@@ -2613,32 +2613,30 @@ msgstr "  (benutzen Sie \"git branch --unset-upstream\" zum Beheben)\n"
 #, 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:2092
 #, 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"
+msgstr[0] "Ihr Branch ist %2$d Commit vor '%1$s'.\n"
+msgstr[1] "Ihr Branch ist %2$d Commits vor '%1$s'.\n"
 
 #: remote.c:2098
 msgid "  (use \"git push\" to publish your local commits)\n"
 msgstr "  (benutzen Sie \"git push\", um lokale Commits zu publizieren)\n"
 
 #: remote.c:2101
 #, c-format
 msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
 msgid_plural ""
 "Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n"
-msgstr[0] ""
-"Ihr Branch ist zu '%s' um %d Commit hinterher, und kann vorgespult werden.\n"
-msgstr[1] ""
-"Ihr Branch ist zu '%s' um %d Commits hinterher, und kann vorgespult werden.\n"
+msgstr[0] "Ihr Branch ist %2$d Commit hinter '%1$s', und kann vorgespult werden.\n"
+msgstr[1] "Ihr Branch ist %2$d Commits hinter '%1$s', und kann vorgespult werden.\n"
 
 #: remote.c:2109
 msgid "  (use \"git pull\" to update your local branch)\n"
 msgstr ""
 "  (benutzen Sie \"git pull\", um Ihren lokalen Branch zu aktualisieren)\n"
 
 #: remote.c:2112
 #, c-format
@@ -2712,24 +2710,23 @@ msgstr "die Gegenseite unterstützt keine Push-Optionen"
 msgid "revert"
 msgstr "Revert"
 
 #: sequencer.c:217
 msgid "cherry-pick"
 msgstr "Cherry-Pick"
 
 #: sequencer.c:219
-#, fuzzy
 msgid "rebase -i"
-msgstr "Basis-Commit"
+msgstr "interaktives Rebase"
 
 #: sequencer.c:221
-#, fuzzy, c-format
+#, c-format
 msgid "Unknown action: %d"
-msgstr "Unbekannter Typ: %d"
+msgstr "Unbekannte Aktion: %d"
 
 #: sequencer.c:278
 msgid ""
 "after resolving the conflicts, mark the corrected paths\n"
 "with 'git add <paths>' or 'git rm <paths>'"
 msgstr ""
 "nach Auflösung der Konflikte, markieren Sie die korrigierten Pfade\n"
 "mit 'git add <Pfade>' oder 'git rm <Pfade>'"
@@ -2844,72 +2841,76 @@ msgstr "Konnte Eltern-Commit %s nicht parsen\n"
 
 #: sequencer.c:815
 #, c-format
 msgid ""
 "unexpected 1st line of squash message:\n"
 "\n"
 "\t%.*s"
 msgstr ""
+"unerwartete erste Zeile der Squash-Beschreibung:\n"
+"\n"
+"\t%.*s"
 
 #: sequencer.c:821
 #, c-format
 msgid ""
 "invalid 1st line of squash message:\n"
 "\n"
 "\t%.*s"
 msgstr ""
+"ungültige erste Zeile der Squash-Beschreibung:\n"
+"\n"
+"\t%.*s"
 
 #: sequencer.c:827 sequencer.c:852
-#, fuzzy, c-format
+#, c-format
 msgid "This is a combination of %d commits."
-msgstr "Das ist eine Kombination aus 2 Commits."
+msgstr "Das ist eine Kombination aus %d Commits."
 
 #: sequencer.c:836
 msgid "need a HEAD to fixup"
-msgstr ""
+msgstr "benötige HEAD für fixup"
 
 #: sequencer.c:838
-#, fuzzy
 msgid "could not read HEAD"
-msgstr "Konnte HEAD nicht loslösen"
+msgstr "Konnte HEAD nicht lesen"
 
 #: sequencer.c:840
-#, fuzzy
 msgid "could not read HEAD's commit message"
-msgstr "Konnte Commit-Beschreibung nicht lesen: %s"
+msgstr "Konnte Commit-Beschreibung von HEAD nicht lesen"
 
 #: sequencer.c:846
-#, fuzzy, c-format
+#, c-format
 msgid "cannot write '%s'"
-msgstr "kann '%s' nicht erstellen"
+msgstr "kann '%s' nicht schreiben"
 
 #: sequencer.c:855 git-rebase--interactive.sh:445
 msgid "This is the 1st commit message:"
 msgstr "Das ist die erste Commit-Beschreibung:"
 
 #: sequencer.c:863
-#, fuzzy, c-format
+#, c-format
 msgid "could not read commit message of %s"
-msgstr "Konnte Commit-Beschreibung nicht lesen: %s"
+msgstr "Konnte Commit-Beschreibung von %s nicht lesen."
 
 #: sequencer.c:870
-#, fuzzy, c-format
+#, c-format
 msgid "This is the commit message #%d:"
-msgstr "Das ist Commit-Beschreibung #${n}:"
+msgstr "Das ist Commit-Beschreibung #%d:"
 
 #: sequencer.c:875
-#, fuzzy, c-format
+#, c-format
 msgid "The commit message #%d will be skipped:"
-msgstr "Commit-Beschreibung #${n} wird ausgelassen:"
+msgstr "Die Commit-Beschreibung #%d wird ausgelassen:"
 
 #: sequencer.c:880
-#, fuzzy, c-format
+#, c-format
 msgid "unknown command: %d"
-msgstr "Unbekannter Unterbefehl: %s"
+msgstr "Unbekannter Befehl: %d"
 
 #: sequencer.c:946
 msgid "your index file is unmerged."
 msgstr "Ihre Index-Datei ist nicht zusammengeführt."
 
 #: sequencer.c:964
 #, c-format
 msgid "commit %s is a merge but no -m option was given."
@@ -2933,19 +2934,19 @@ msgstr "Kann keine Commit-Beschreibung für %s bekommen."
 #. TRANSLATORS: The first %s will be a "todo" command like
 #. "revert" or "pick", the second %s a SHA1.
 #: sequencer.c:1001
 #, c-format
 msgid "%s: cannot parse parent commit %s"
 msgstr "%s: kann Eltern-Commit %s nicht parsen"
 
 #: sequencer.c:1063 sequencer.c:1812
-#, fuzzy, c-format
+#, c-format
 msgid "could not rename '%s' to '%s'"
-msgstr "Konnte '%s' nicht zu '%s' setzen."
+msgstr "Konnte '%s' nicht zu '%s' umbenennen."
 
 #: sequencer.c:1114
 #, c-format
 msgid "could not revert %s... %s"
 msgstr "Konnte \"revert\" nicht auf %s... (%s) ausführen"
 
 #: sequencer.c:1115
 #, c-format
@@ -2967,29 +2968,28 @@ msgid "git %s: failed to refresh the index"
 msgstr "git %s: Fehler beim Aktualisieren des Index"
 
 #: sequencer.c:1294
 #, c-format
 msgid "invalid line %d: %.*s"
 msgstr "Ungültige Zeile %d: %.*s"
 
 #: sequencer.c:1302
-#, fuzzy, c-format
+#, c-format
 msgid "cannot '%s' without a previous commit"
-msgstr "Kann nicht '$squash_style' ohne vorherigen Commit"
+msgstr "Kann '%s' nicht ohne vorherigen Commit ausführen"
 
 #: sequencer.c:1334
 #, c-format
 msgid "could not read '%s'."
 msgstr "Konnte '%s' nicht lesen."
 
 #: sequencer.c:1341
-#, fuzzy
 msgid "please fix this using 'git rebase --edit-todo'."
-msgstr "Bitte beheben Sie das, indem Sie 'git rebase --edit-todo' ausführen."
+msgstr "Bitte beheben Sie dieses, indem Sie 'git rebase --edit-todo' ausführen."
 
 #: sequencer.c:1343
 #, c-format
 msgid "unusable instruction sheet: '%s'"
 msgstr "Unbenutzbares Instruktionsblatt: '%s'"
 
 #: sequencer.c:1348
 msgid "no commits parsed."
@@ -3062,166 +3062,155 @@ msgid "unexpected end of file"
 msgstr "Unerwartetes Dateiende"
 
 #: sequencer.c:1629
 #, 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:1640
-#, fuzzy
 msgid "You seem to have moved HEAD. Not rewinding, check your HEAD!"
-msgstr ""
-"Sie scheinen seit dem letzten gescheiterten 'am' HEAD geändert zu haben.\n"
-"Keine Zurücksetzung zu ORIG_HEAD."
+msgstr "Sie scheinen HEAD verschoben zu haben. Keine Zurücksetzung, prüfen Sie HEAD."
 
 #: sequencer.c:1777 sequencer.c:2049
-#, fuzzy
 msgid "cannot read HEAD"
 msgstr "Kann HEAD nicht lesen"
 
 #: sequencer.c:1817 builtin/difftool.c:574
-#, fuzzy, c-format
+#, c-format
 msgid "could not copy '%s' to '%s'"
-msgstr "Konnte '%s' nicht zu '%s' setzen."
+msgstr "Konnte '%s' nicht nach '%s' kopieren."
 
 #: sequencer.c:1833
-#, fuzzy
 msgid "could not read index"
-msgstr "Konnte den Index nicht lesen"
+msgstr "Konnte den Index nicht lesen."
 
 #: sequencer.c:1838
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "execution failed: %s\n"
 "%sYou can fix the problem, and then run\n"
 "\n"
 "  git rebase --continue\n"
 "\n"
 msgstr ""
-"Sie können das Problem beheben, und dann\n"
+"Ausführung fehlgeschlagen: %s\n"
+"%sSie können das Problem beheben, und dann\n"
 "\n"
 "\tgit rebase --continue\n"
 "\n"
-"ausführen."
+"ausführen.\n"
 
 #: sequencer.c:1844
-#, fuzzy
 msgid "and made changes to the index and/or the working tree\n"
-msgstr "Der Index und/oder das Arbeitsverzeichnis wurde geändert."
+msgstr "Der Index und/oder das Arbeitsverzeichnis wurde geändert.\n"
 
 #: sequencer.c:1850
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "execution succeeded: %s\n"
 "but left changes to the index and/or the working tree\n"
 "Commit or stash your changes, and then run\n"
 "\n"
 "  git rebase --continue\n"
 "\n"
 msgstr ""
-"Ausführung erfolgreich: $rest\n"
+"Ausführung erfolgreich: %s\n"
 "Aber Änderungen in Index oder Arbeitsverzeichnis verblieben.\n"
 "Committen Sie Ihre Änderungen oder benutzen Sie \"stash\".\n"
 "Führen Sie dann aus:\n"
 "\n"
-"\tgit rebase --continue"
+"  git rebase --continue\n"
+"\n"
 
 #: sequencer.c:1905 git-rebase.sh:168
 #, c-format
 msgid "Applied autostash."
 msgstr "Automatischen Stash angewendet."
 
 #: sequencer.c:1917
-#, fuzzy, c-format
+#, c-format
 msgid "cannot store %s"
-msgstr "kann '%s' nicht öffnen"
+msgstr "kann %s nicht speichern"
 
 #: sequencer.c:1919 git-rebase.sh:172
 #, c-format
 msgid ""
 "Applying autostash resulted in conflicts.\n"
 "Your changes are safe in the stash.\n"
 "You can run \"git stash pop\" or \"git stash drop\" at any time.\n"
 msgstr ""
 "Anwendung des automatischen Stash resultierte in Konflikten.\n"
 "Ihre Änderungen sind im Stash sicher.\n"
 "Sie können jederzeit \"git stash pop\" oder \"git stash drop\" ausführen.\n"
 
 #: sequencer.c:2000
-#, fuzzy, c-format
+#, c-format
 msgid "stopped at %s... %.*s"
-msgstr "Anwendung des Patches fehlgeschlagen bei %s %.*s"
+msgstr "Angehalten bei %s... %.*s"
 
 #: sequencer.c:2027
-#, fuzzy, c-format
+#, c-format
 msgid "unknown command %d"
-msgstr "Unbekannter Unterbefehl: %s"
+msgstr "Unbekannter Befehl %d"
 
 #: sequencer.c:2057
-#, fuzzy
 msgid "could not read orig-head"
-msgstr "Konnte Referenz %s nicht lesen."
+msgstr "Konnte orig-head nicht lesen."
 
 #: sequencer.c:2061
-#, fuzzy
 msgid "could not read 'onto'"
-msgstr "Konnte '%s' nicht lesen"
+msgstr "Konnte 'onto' nicht lesen."
 
 #: sequencer.c:2068
-#, fuzzy, c-format
+#, c-format
 msgid "could not update %s"
-msgstr "konnte %s nicht parsen"
+msgstr "Konnte %s nicht aktualisieren."
 
 #: sequencer.c:2075
-#, fuzzy, c-format
+#, c-format
 msgid "could not update HEAD to %s"
-msgstr "Konnte nicht nach '%s' schreiben."
+msgstr "Konnte HEAD nicht auf %s aktualisieren."
 
 #: sequencer.c:2159
-#, fuzzy
 msgid "cannot rebase: You have unstaged changes."
 msgstr ""
-"Rebase nicht möglich: Sie haben Änderungen, die nicht zum Commit vorgemerkt "
-"sind."
+"Rebase nicht möglich: Sie haben Änderungen, die nicht zum Commit\n"
+"vorgemerkt sind."
 
 #: sequencer.c:2164
-#, fuzzy
 msgid "could not remove CHERRY_PICK_HEAD"
-msgstr "Konnte CHERRY_PICK_HEAD nicht löschen"
+msgstr "Konnte CHERRY_PICK_HEAD nicht löschen."
 
 #: sequencer.c:2173
-#, fuzzy
 msgid "cannot amend non-existing commit"
-msgstr "Kann existierendes Objekt %s nicht lesen."
+msgstr "Kann nicht existierenden Commit nicht nachbessern."
 
 #: sequencer.c:2175
-#, fuzzy, c-format
+#, c-format
 msgid "invalid file: '%s'"
-msgstr "Ungültiger Schlüssel: %s"
+msgstr "Ungültige Datei: '%s'"
 
 #: sequencer.c:2177
-#, fuzzy, c-format
+#, c-format
 msgid "invalid contents: '%s'"
-msgstr "Ungültige Option: %s"
+msgstr "Ungültige Inhalte: '%s'"
 
 #: sequencer.c:2180
-#, fuzzy
 msgid ""
 "\n"
 "You have uncommitted changes in your working tree. Please, commit them\n"
 "first and then run 'git rebase --continue' again."
 msgstr ""
+"\n"
 "Sie haben nicht committete Änderungen in Ihrem Arbeitsverzeichnis. Bitte\n"
-"committen Sie diese zuerst und führen Sie dann 'git rebase --continue' "
-"erneut\n"
-"aus."
+"committen Sie diese zuerst und führen Sie dann 'git rebase --continue'\n"
+"erneut aus."
 
 #: sequencer.c:2190
-#, fuzzy
 msgid "could not commit staged changes."
 msgstr "Konnte Änderungen aus der Staging-Area nicht committen."
 
 #: sequencer.c:2270
 #, c-format
 msgid "%s: can't cherry-pick a %s"
 msgstr "%s: %s kann nicht in \"cherry-pick\" benutzt werden"
 
@@ -3416,54 +3405,59 @@ msgstr "Konnte Eintrag '%s' nicht aus .gitmodules entfernen"
 msgid "staging updated .gitmodules failed"
 msgstr "Konnte aktualisierte .gitmodules-Datei nicht zum Commit vormerken"
 
 #: submodule.c:159
 msgid "negative values not allowed for submodule.fetchJobs"
 msgstr "Negative Werte für submodule.fetchJobs nicht erlaubt"
 
 #: submodule.c:1184
-#, fuzzy, c-format
+#, c-format
 msgid "could not start 'git status in submodule '%s'"
-msgstr "Konnte Submodul-Verzeichnis '%s' nicht finden."
+msgstr "Konnte 'git status' in Submodul '%s' nicht starten."
 
 #: submodule.c:1197
-#, fuzzy, c-format
+#, c-format
 msgid "could not run 'git status in submodule '%s'"
-msgstr "konnte Datei '%s' nicht erstellen"
+msgstr "konnte 'git status' in Submodul '%s' nicht ausführen"
 
 #: submodule.c:1398
 #, c-format
 msgid ""
 "relocate_gitdir for submodule '%s' with more than one worktree not supported"
 msgstr ""
+"relocate_gitdir für Submodul '%s' mit mehr als einem Arbeitsverzeichnis\n"
+"wird nicht unterstützt"
 
 #: submodule.c:1410 submodule.c:1471
-#, fuzzy, c-format
+#, c-format
 msgid "could not lookup name for submodule '%s'"
-msgstr "konnte '%s' nicht öffnen oder lesen"
+msgstr "konnte Name für Submodul '%s' nicht nachschlagen"
 
 #: submodule.c:1414 submodule.c:1474 builtin/submodule--helper.c:640
 #: builtin/submodule--helper.c:650
 #, c-format
 msgid "could not create directory '%s'"
 msgstr "Konnte Verzeichnis '%s' nicht erstellen."
 
 #: submodule.c:1420
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "Migrating git directory of '%s%s' from\n"
 "'%s' to\n"
 "'%s'\n"
-msgstr "Fehler beim Kopieren der Notizen von '%s' nach '%s'"
+msgstr ""
+"Migriere Git-Verzeichnis von '%s%s' von\n"
+"'%s' nach\n"
+"'%s'\n"
 
 #: submodule.c:1512
-#, fuzzy, c-format
+#, c-format
 msgid "could not recurse into submodule '%s'"
-msgstr "Fehler bei Rekursion in Submodul-Pfad '$sm_path'"
+msgstr "Fehler bei Rekursion in Submodul-Pfad '%s'"
 
 #: submodule-config.c:360
 #, c-format
 msgid "invalid value for %s"
 msgstr "Ungültiger Wert für %s"
 
 #: trailer.c:240
 #, c-format
@@ -3646,17 +3640,17 @@ msgstr ""
 msgid ""
 "Your local changes to the following files would be overwritten by %s:\n"
 "%%s"
 msgstr ""
 "Ihre lokalen Änderungen würden durch %s überschrieben werden.\n"
 "%%s"
 
 #: unpack-trees.c:116
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "Updating the following directories would lose untracked files in them:\n"
 "%s"
 msgstr ""
 "Durch die Aktualisierung der folgenden Verzeichnisse würden unversionierte\n"
 "Dateien in diesen Verzeichnissen verloren gehen:\n"
 "%s"
 
@@ -4104,17 +4098,17 @@ msgstr "  (benutzen Sie \"git am --skip\", um diesen Patch auszulassen)"
 #: wt-status.c:1047
 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:1176
 msgid "git-rebase-todo is missing."
-msgstr ""
+msgstr "git-rebase-todo fehlt."
 
 #: wt-status.c:1178
 msgid "No commands done."
 msgstr "Keine Befehle ausgeführt."
 
 #: wt-status.c:1181
 #, c-format
 msgid "Last command done (%d command done):"
@@ -4343,42 +4337,40 @@ msgid "no changes added to commit\n"
 msgstr "keine Änderungen zum Commit vorgemerkt\n"
 
 #: wt-status.c:1611
 #, c-format
 msgid ""
 "nothing added to commit but untracked files present (use \"git add\" to "
 "track)\n"
 msgstr ""
-"nichts zum Commit vorgemerkt, aber es gibt unversionierte Dateien (benutzen "
-"Sie \"git add\" zum Versionieren)\n"
+"nichts zum Commit vorgemerkt, aber es gibt unversionierte Dateien\n"
+"(benutzen Sie \"git add\" zum Versionieren)\n"
 
 #: wt-status.c:1614
 #, c-format
 msgid "nothing added to commit but untracked files present\n"
 msgstr "nichts zum Commit vorgemerkt, aber es gibt unversionierte Dateien\n"
 
 #: wt-status.c:1617
 #, 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 Versionieren)\n"
+"nichts zu committen (Erstellen/Kopieren Sie Dateien und benutzen\n"
+"Sie \"git add\" zum Versionieren)\n"
 
 #: wt-status.c:1620 wt-status.c:1625
 #, c-format
 msgid "nothing to commit\n"
 msgstr "nichts zu committen\n"
 
 #: wt-status.c:1623
 #, c-format
 msgid "nothing to commit (use -u to show untracked files)\n"
-msgstr ""
-"nichts zu committen (benutzen Sie die Option -u, um unversionierte Dateien "
-"anzuzeigen)\n"
+msgstr "nichts zu committen (benutzen Sie die Option -u, um unversionierte Dateien anzuzeigen)\n"
 
 #: wt-status.c:1627
 #, c-format
 msgid "nothing to commit, working tree clean\n"
 msgstr "nichts zu committen, Arbeitsverzeichnis unverändert\n"
 
 #: wt-status.c:1734
 msgid "Initial commit on "
@@ -5086,21 +5078,20 @@ msgid "Show author email instead of name (Default: off)"
 msgstr ""
 "Anstatt des Namens die E-Mail-Adresse des Autors anzeigen (Standard: aus)"
 
 #: builtin/blame.c:2597
 msgid "Ignore whitespace differences"
 msgstr "Unterschiede im Whitespace ignorieren"
 
 #: builtin/blame.c:2604
-#, fuzzy
 msgid "Use an experimental heuristic to improve diffs"
 msgstr ""
-"eine experimentelle, auf Einrückungen basierende Heuristik zur Verbesserung\n"
-"der Darstellung von Unterschieden verwenden"
+"eine experimentelle Heuristik zur Verbesserung der Darstellung\n"
+"von Unterschieden verwenden"
 
 #: builtin/blame.c:2606
 msgid "Spend extra cycles to find better match"
 msgstr "Länger arbeiten, um bessere Übereinstimmungen zu finden"
 
 #: builtin/blame.c:2607
 msgid "Use revisions from <file> instead of calling git-rev-list"
 msgstr "Commits von <Datei> benutzen, anstatt \"git-rev-list\" aufzurufen"
@@ -5520,17 +5511,17 @@ msgid "object"
 msgstr "Objekt"
 
 #: builtin/branch.c:679
 msgid "print only branches of the object"
 msgstr "nur Branches von diesem Objekt ausgeben"
 
 #: builtin/branch.c:681 builtin/for-each-ref.c:46 builtin/tag.c:388
 msgid "sorting and filtering are case insensitive"
-msgstr ""
+msgstr "Sortierung und Filterung sind unabhängig von Groß- und Kleinschreibung"
 
 #: builtin/branch.c:698
 msgid "Failed to resolve HEAD as a valid ref."
 msgstr "Konnte HEAD nicht als gültige Referenz auflösen."
 
 #: builtin/branch.c:702 builtin/clone.c:706
 msgid "HEAD not found below refs/heads!"
 msgstr "HEAD wurde nicht unter \"refs/heads\" gefunden!"
@@ -6211,30 +6202,30 @@ msgid "Would skip repository %s\n"
 msgstr "Würde Repository %s überspringen\n"
 
 #: builtin/clean.c:33
 #, c-format
 msgid "failed to remove %s"
 msgstr "Fehler beim Löschen von %s"
 
 #: builtin/clean.c:291 git-add--interactive.perl:623
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "Prompt help:\n"
 "1          - select a numbered item\n"
 "foo        - select item based on unique prefix\n"
 "           - (empty) select nothing\n"
 msgstr ""
 "Eingabehilfe:\n"
 "1          - nummeriertes Element auswählen\n"
 "foo        - Element anhand eines eindeutigen Präfix auswählen\n"
-"           - (leer) nichts auswählen"
+"           - (leer) nichts auswählen\n"
 
 #: builtin/clean.c:295 git-add--interactive.perl:632
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "Prompt help:\n"
 "1          - select a single item\n"
 "3-5        - select a range of items\n"
 "2-3,6-9    - select multiple ranges\n"
 "foo        - select item based on unique prefix\n"
 "-...       - unselect specified items\n"
 "*          - choose all items\n"
@@ -6242,23 +6233,23 @@ msgid ""
 msgstr ""
 "Eingabehilfe:\n"
 "1          - einzelnes Element auswählen\n"
 "3-5        - Bereich von Elementen auswählen\n"
 "2-3,6-9    - mehrere Bereiche auswählen\n"
 "foo        - Element anhand eines eindeutigen Präfix auswählen\n"
 "-...       - angegebenes Element abwählen\n"
 "*          - alle Elemente auswählen\n"
-"           - (leer) Auswahl beenden"
+"           - (leer) Auswahl beenden\n"
 
 #: builtin/clean.c:511 git-add--interactive.perl:598
 #: git-add--interactive.perl:603
-#, fuzzy, c-format, perl-format
+#, c-format, perl-format
 msgid "Huh (%s)?\n"
-msgstr "Wie bitte (%s)?"
+msgstr "Wie bitte (%s)?\n"
 
 #: builtin/clean.c:653
 #, c-format
 msgid "Input ignore patterns>> "
 msgstr "Ignorier-Muster eingeben>> "
 
 #: builtin/clean.c:690
 #, c-format
@@ -6271,19 +6262,19 @@ msgstr "Wählen Sie Einträge zum Löschen"
 
 #. TRANSLATORS: Make sure to keep [y/N] as is
 #: builtin/clean.c:752
 #, c-format
 msgid "Remove %s [y/N]? "
 msgstr "'%s' löschen [y/N]? "
 
 #: builtin/clean.c:777 git-add--interactive.perl:1669
-#, fuzzy, c-format
+#, c-format
 msgid "Bye.\n"
-msgstr "Tschüss."
+msgstr "Tschüss.\n"
 
 #: builtin/clean.c:785
 msgid ""
 "clean               - start cleaning\n"
 "filter by pattern   - exclude items from deletion\n"
 "select by numbers   - select items to be deleted by numbers\n"
 "ask each            - confirm each deletion (like \"rm -i\")\n"
 "quit                - stop cleaning\n"
@@ -6459,17 +6450,16 @@ msgstr ""
 "Zeit\n"
 "erstellen"
 
 #: builtin/clone.c:101 builtin/fetch.c:124
 msgid "revision"
 msgstr "Commit"
 
 #: builtin/clone.c:102 builtin/fetch.c:125
-#, fuzzy
 msgid "deepen history of shallow clone, excluding rev"
 msgstr ""
 "die Historie eines Klons mit unvollständiger Historie (shallow) mittels\n"
 "Ausschluss eines Commits vertiefen"
 
 #: builtin/clone.c:104
 msgid "clone only one branch, HEAD or --branch"
 msgstr "nur einen Branch klonen, HEAD oder --branch"
@@ -7699,100 +7689,101 @@ msgid "more than two blobs given: '%s'"
 msgstr "Mehr als zwei Blobs angegeben: '%s'"
 
 #: builtin/diff.c:417
 #, c-format
 msgid "unhandled object '%s' given."
 msgstr "unbehandeltes Objekt '%s' angegeben"
 
 #: builtin/difftool.c:28
-#, fuzzy
 msgid "git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]"
-msgstr "git log [<Optionen>] [<Commitbereich>] [[--] <Pfad>...]"
+msgstr "git difftool [<Optionen>] [<Commit> [<Commit>]] [--] [<Pfad>...]"
 
 #: builtin/difftool.c:241
-#, fuzzy, c-format
+#, c-format
 msgid "failed: %d"
-msgstr "Anwendung des Patches fehlgeschlagen: %s:%ld"
+msgstr "fehlgeschlagen: %d"
 
 #: builtin/difftool.c:342
 msgid ""
 "combined diff formats('-c' and '--cc') are not supported in\n"
 "directory diff mode('-d' and '--dir-diff')."
 msgstr ""
+"Kombinierte Diff-Formate('-c' und '--cc') werden im Verzeichnis-\n"
+"Diff-Modus('-d' und '--dir-diff') nicht unterstützt."
 
 #: builtin/difftool.c:567
 #, c-format
 msgid "both files modified: '%s' and '%s'."
-msgstr ""
+msgstr "beide Dateien geändert: '%s' und '%s'."
 
 #: builtin/difftool.c:569
-#, fuzzy
 msgid "working tree file has been left."
-msgstr "Arbeitsverzeichnis '%s' existiert bereits."
+msgstr "Datei im Arbeitsverzeichnis belassen."
 
 #: builtin/difftool.c:580
 #, c-format
 msgid "temporary files exist in '%s'."
-msgstr ""
+msgstr "Es existieren temporäre Dateien in '%s'."
 
 #: builtin/difftool.c:581
 msgid "you may want to cleanup or recover these."
-msgstr ""
+msgstr "Sie könnten diese aufräumen oder wiederherstellen."
 
 #: builtin/difftool.c:626
 msgid "use `diff.guitool` instead of `diff.tool`"
-msgstr ""
+msgstr "`diff.guitool` anstatt `diff.tool` benutzen"
 
 #: builtin/difftool.c:628
 msgid "perform a full-directory diff"
-msgstr ""
+msgstr "Diff über ganzes Verzeichnis ausführen"
 
 #: builtin/difftool.c:630
 msgid "do not prompt before launching a diff tool"
-msgstr ""
+msgstr "keine Eingabeaufforderung vor Ausführung eines Diff-Tools"
 
 #: builtin/difftool.c:636
 msgid "use symlinks in dir-diff mode"
-msgstr ""
+msgstr "symbolische Verknüpfungen im dir-diff Modus verwenden"
 
 #: builtin/difftool.c:637
 msgid "<tool>"
-msgstr ""
+msgstr "<Tool>"
 
 #: builtin/difftool.c:638
 msgid "use the specified diff tool"
-msgstr ""
+msgstr "das angegebene Diff-Tool benutzen"
 
 #: builtin/difftool.c:640
 msgid "print a list of diff tools that may be used with `--tool`"
-msgstr ""
+msgstr "eine Liste mit Diff-Tools darstellen, die mit `--tool` benutzt werden können"
 
 #: builtin/difftool.c:643
 msgid ""
 "make 'git-difftool' exit when an invoked diff tool returns a non - zero exit "
 "code"
 msgstr ""
+"'git-difftool' beenden, wenn das aufgerufene Diff-Tool mit einem Rückkehrwert\n"
+"verschieden 0 ausgeführt wurde"
 
 #: builtin/difftool.c:645
-#, fuzzy
 msgid "<command>"
-msgstr "Programm"
+msgstr "<Programm>"
 
 #: builtin/difftool.c:646
 msgid "specify a custom command for viewing diffs"
-msgstr ""
+msgstr "eigenen Befehl zur Anzeige von Unterschieden angeben"
 
 #: builtin/difftool.c:670
 msgid "no <tool> given for --tool=<tool>"
-msgstr ""
+msgstr "kein <Tool> für --tool=<Tool> angegeben"
 
 #: builtin/difftool.c:677
 msgid "no <cmd> given for --extcmd=<cmd>"
-msgstr ""
+msgstr "kein <Programm> für --extcmd=<Programm> angegeben"
 
 #: builtin/fast-export.c:25
 msgid "git fast-export [rev-list-opts]"
 msgstr "git fast-export [rev-list-opts]"
 
 #: builtin/fast-export.c:980
 msgid "show progress after <n> objects"
 msgstr "Fortschritt nach <n> Objekten anzeigen"
@@ -8399,29 +8390,26 @@ msgstr "auch in Inhalten finden, die nicht von Git verwaltet werden"
 msgid "search in both tracked and untracked files"
 msgstr "in versionierten und unversionierten Dateien suchen"
 
 #: builtin/grep.c:979
 msgid "ignore files specified via '.gitignore'"
 msgstr "Dateien, die über '.gitignore' angegeben sind, ignorieren"
 
 #: builtin/grep.c:981
-#, fuzzy
 msgid "recursivley search in each submodule"
-msgstr "rekursive Anforderungen von Submodulen kontrollieren"
+msgstr "rekursive Suche in jedem Submodul"
 
 #: builtin/grep.c:983
-#, fuzzy
 msgid "basename"
-msgstr "umbenennen"
+msgstr "Basisname"
 
 #: builtin/grep.c:984
-#, fuzzy
 msgid "prepend parent project's basename to output"
-msgstr "dies an die Ausgabe der Submodul-Pfade voranstellen"
+msgstr "Basisname des Elternprojektes an Ausgaben voranstellen"
 
 #: builtin/grep.c:987
 msgid "show non-matching lines"
 msgstr "Zeilen ohne Übereinstimmungen anzeigen"
 
 #: builtin/grep.c:989
 msgid "case insensitive matching"
 msgstr "Übereinstimmungen unabhängig von Groß- und Kleinschreibung finden"
@@ -8590,17 +8578,17 @@ msgstr "ungültige Anzahl von Threads angegeben (%d)"
 #: builtin/grep.c:1215
 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:1238
 msgid "option not supported with --recurse-submodules."
-msgstr ""
+msgstr "Option wird mit --recurse-submodules nicht unterstützt."
 
 #: builtin/grep.c:1244
 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:1249
@@ -9068,20 +9056,18 @@ msgstr "Name der Paketdatei '%s' endet nicht mit '.pack'"
 msgid "bad %s"
 msgstr "%s ist ungültig"
 
 #: builtin/index-pack.c:1734
 msgid "--fix-thin cannot be used without --stdin"
 msgstr "Die Option --fix-thin kann nicht ohne --stdin verwendet werden."
 
 #: builtin/index-pack.c:1736
-#, fuzzy
 msgid "--stdin requires a git repository"
-msgstr ""
-"Die Option --index kann nicht außerhalb eines Repositories verwendet werden."
+msgstr "--stdin erfordert ein Git-Repository"
 
 #: builtin/index-pack.c:1744
 msgid "--verify with no packfile name given"
 msgstr "Die Option --verify wurde ohne Namen der Paketdatei angegeben."
 
 #: builtin/init-db.c:54
 #, c-format
 msgid "cannot stat '%s'"
@@ -9762,19 +9748,18 @@ msgstr "git merge [<Optionen>] [<Commit>...]"
 msgid "git merge [<options>] <msg> HEAD <commit>"
 msgstr "git merge [<Optionen>] <Beschreibung> HEAD <Commit>"
 
 #: builtin/merge.c:48
 msgid "git merge --abort"
 msgstr "git merge --abort"
 
 #: builtin/merge.c:49
-#, fuzzy
 msgid "git merge --continue"
-msgstr "git merge --abort"
+msgstr "git merge --continue"
 
 #: builtin/merge.c:104
 msgid "switch `m' requires a value"
 msgstr "Schalter 'm' erfordert einen Wert."
 
 #: builtin/merge.c:141
 #, c-format
 msgid "Could not find merge strategy '%s'.\n"
@@ -9854,19 +9839,18 @@ msgid "merge commit message (for a non-fast-forward merge)"
 msgstr ""
 "Commit-Beschreibung zusammenführen (für einen Merge, der kein Vorspulen war)"
 
 #: builtin/merge.c:227
 msgid "abort the current in-progress merge"
 msgstr "den sich im Gange befindlichen Merge abbrechen"
 
 #: builtin/merge.c:229
-#, fuzzy
 msgid "continue the current in-progress merge"
-msgstr "den sich im Gange befindlichen Merge abbrechen"
+msgstr "den sich im Gange befindlichen Merge fortsetzen"
 
 #: builtin/merge.c:231 builtin/pull.c:170
 msgid "allow merging unrelated histories"
 msgstr "erlaube das Zusammenführen von nicht zusammenhängenden Historien"
 
 #: builtin/merge.c:259
 msgid "could not run stash."
 msgstr "Konnte \"stash\" nicht ausführen."
@@ -10004,32 +9988,30 @@ msgstr "Konnte '%s' nicht schließen"
 msgid "not something we can merge in %s: %s"
 msgstr "nichts was wir in %s zusammenführen können: %s"
 
 #: builtin/merge.c:1099
 msgid "not something we can merge"
 msgstr "nichts was wir zusammenführen können"
 
 #: builtin/merge.c:1167
-#, fuzzy
 msgid "--abort expects no arguments"
-msgstr "%%(body) akzeptiert keine Argumente"
+msgstr "--abort akzeptiert keine Argumente"
 
 #: builtin/merge.c:1171
 msgid "There is no merge to abort (MERGE_HEAD missing)."
 msgstr "Es gibt keinen Merge zum Abbrechen (MERGE_HEAD fehlt)"
 
 #: builtin/merge.c:1183
 msgid "--continue expects no arguments"
-msgstr ""
+msgstr "--continue erwartet keine Argumente"
 
 #: builtin/merge.c:1187
-#, fuzzy
 msgid "There is no merge in progress (MERGE_HEAD missing)."
-msgstr "Es gibt keinen Merge zum Abbrechen (MERGE_HEAD fehlt)"
+msgstr "Es ist keine Merge im Gange (MERGE_HEAD fehlt)."
 
 #: builtin/merge.c:1203
 msgid ""
 "You have not concluded your merge (MERGE_HEAD exists).\n"
 "Please, commit your changes before you merge."
 msgstr ""
 "Sie haben Ihren Merge nicht abgeschlossen (MERGE_HEAD existiert).\n"
 "Bitte committen Sie Ihre Änderungen, bevor Sie den Merge ausführen."
@@ -11641,17 +11623,16 @@ msgstr "Anwendung des Filters für partielles Auschecken überspringen"
 msgid "debug unpack-trees"
 msgstr "unpack-trees protokollieren"
 
 #: builtin/receive-pack.c:26
 msgid "git receive-pack <git-dir>"
 msgstr "git receive-pack <Git-Verzeichnis>"
 
 #: builtin/receive-pack.c:793
-#, fuzzy
 msgid ""
 "By default, updating the current branch in a non-bare repository\n"
 "is denied, because it will make the index and work tree inconsistent\n"
 "with what you pushed, and will require 'git reset --hard' to match\n"
 "the work tree to HEAD.\n"
 "\n"
 "You can set the 'receive.denyCurrentBranch' configuration variable\n"
 "to 'ignore' or 'warn' in the remote repository to allow pushing into\n"
@@ -11664,17 +11645,17 @@ msgid ""
 msgstr ""
 "Standardmäßig wird die Aktualisierung des aktuellen Branches in einem\n"
 "nicht-Bare-Repository zurückgewiesen, da dies den Index und das Arbeits-\n"
 "verzeichnis inkonsistent zu dem machen würde, was Sie gepushed haben, und\n"
 "'git reset --hard' erforderlich wäre, damit das Arbeitsverzeichnis HEAD\n"
 "entspricht.\n"
 "\n"
 "Sie könnten die Konfigurationsvariable 'receive.denyCurrentBranch' im\n"
-"Remote-Repository zu 'ignore' oder 'warn' setzen, um den Push in den\n"
+"Remote-Repository auf 'ignore' oder 'warn' setzen, um den Push in den\n"
 "aktuellen Branch zu erlauben; dies wird jedoch nicht empfohlen außer\n"
 "Sie stellen durch andere Wege die Aktualität des Arbeitsverzeichnisses\n"
 "gegenüber dem gepushten Stand sicher.\n"
 "\n"
 "Um diese Meldung zu unterdrücken und das Standardverhalten zu behalten,\n"
 "setzen Sie die Konfigurationsvariable 'receive.denyCurrentBranch' auf\n"
 "'refuse'."
 
@@ -12237,16 +12218,19 @@ msgstr "Unbekannter Unterbefehl: %s"
 msgid "git repack [<options>]"
 msgstr "git repack [<Optionen>]"
 
 #: builtin/repack.c:22
 msgid ""
 "Incremental repacks are incompatible with bitmap indexes.  Use\n"
 "--no-write-bitmap-index or disable the pack.writebitmaps configuration."
 msgstr ""
+"Schrittweises Neupacken ist mit Bitmap-Indexen inkompatibel. Benutzen Sie\n"
+"--no-write-bitmap-index oder deaktivieren Sie die pack.writebitmaps\n"
+"Konfiguration."
 
 #: builtin/repack.c:166
 msgid "pack everything in a single pack"
 msgstr "alles in eine einzige Pack-Datei packen"
 
 #: builtin/repack.c:168
 msgid "same as -a, and turn unreachable objects loose"
 msgstr "genau wie -a, unerreichbare Objekte werden aber nicht gelöscht"
@@ -12740,19 +12724,19 @@ msgid "not removing '%s' recursively without -r"
 msgstr "'%s' wird nicht ohne -r rekursiv entfernt"
 
 #: builtin/rm.c:347
 #, c-format
 msgid "git rm: unable to remove %s"
 msgstr "git rm: konnte %s nicht löschen"
 
 #: builtin/rm.c:370
-#, fuzzy, c-format
+#, c-format
 msgid "could not remove '%s'"
-msgstr "Konnte Referenz '%s' nicht auflösen"
+msgstr "Konnte '%s' nicht löschen"
 
 #: builtin/send-pack.c:18
 msgid ""
 "git send-pack [--all | --mirror] [--dry-run] [--force] [--receive-pack=<git-"
 "receive-pack>] [--verbose] [--thin] [--atomic] [<host>:]<directory> "
 "[<ref>...]\n"
 "  --all and explicit <ref> specification are mutually exclusive."
 msgstr ""
@@ -12779,17 +12763,17 @@ msgid "print status from remote helper"
 msgstr "Status des Remote-Helpers ausgeben"
 
 #: builtin/shortlog.c:13
 msgid "git shortlog [<options>] [<revision-range>] [[--] [<path>...]]"
 msgstr "git shortlog [<Optionen>] [<Commitbereich>] [[--] [<Pfad>...]]"
 
 #: builtin/shortlog.c:249
 msgid "Group by committer rather than author"
-msgstr ""
+msgstr "über Commit-Ersteller anstatt Autor gruppieren"
 
 #: builtin/shortlog.c:251
 msgid "sort output according to the number of commits per author"
 msgstr "die Ausgabe entsprechend der Anzahl von Commits pro Autor sortieren"
 
 #: builtin/shortlog.c:253
 msgid "Suppress commit descriptions, only provides commit count"
 msgstr "Commit-Beschreibungen unterdrücken, nur Anzahl der Commits liefern"
@@ -13217,33 +13201,31 @@ msgstr "Fehlerhafter Wert für --update Parameter"
 msgid ""
 "Submodule (%s) branch configured to inherit branch from superproject, but "
 "the superproject is not on any branch"
 msgstr ""
 "Branch von Submodul (%s) ist konfiguriert, den Branch des Hauptprojektes\n"
 "zu erben, aber das Hauptprojekt befindet sich auf keinem Branch."
 
 #: builtin/submodule--helper.c:1106
-#, fuzzy
 msgid "recurse into submodules"
-msgstr "Rekursion in Submodulen durchführen"
+msgstr "Rekursion in Submodule durchführen"
 
 #: builtin/submodule--helper.c:1112
-#, fuzzy
 msgid "git submodule--helper embed-git-dir [<path>...]"
-msgstr "git submodule--helper init [<Pfad>]"
+msgstr "git submodule--helper embed-git-dir [<Pfad>...]"
 
 #: builtin/submodule--helper.c:1157
 msgid "submodule--helper subcommand must be called with a subcommand"
 msgstr "submodule--helper muss mit einem Unterbefehl aufgerufen werden"
 
 #: builtin/submodule--helper.c:1164
-#, fuzzy, c-format
+#, c-format
 msgid "%s doesn't support --super-prefix"
-msgstr "Server unterstützt kein --deepen"
+msgstr "%s unterstützt kein --super-prefix"
 
 #: builtin/submodule--helper.c:1170
 #, c-format
 msgid "'%s' is not a valid submodule--helper subcommand"
 msgstr "'%s' ist kein gültiger Unterbefehl von submodule--helper"
 
 #: builtin/symbolic-ref.c:7
 msgid "git symbolic-ref [<options>] <name> [<ref>]"
@@ -13290,19 +13272,18 @@ msgstr "git tag -d <Tagname>..."
 msgid ""
 "git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>]\n"
 "\t\t[--format=<format>] [--[no-]merged [<commit>]] [<pattern>...]"
 msgstr ""
 "git tag -l [-n[<Nummer>]] [--contains <Commit>] [--points-at <Objekt>]\n"
 "\t\t[--format=<Muster>] [--[no-]merged [<Commit>]] [<Muster>...]"
 
 #: builtin/tag.c:27
-#, fuzzy
 msgid "git tag -v [--format=<format>] <tagname>..."
-msgstr "git tag -v <Tagname>..."
+msgstr "git tag -v [--format=<Format>] <Tagname>..."
 
 #: builtin/tag.c:82
 #, c-format
 msgid "tag name too long: %.*s..."
 msgstr "Tagname zu lang: %.*s..."
 
 #: builtin/tag.c:87
 #, c-format
@@ -13762,19 +13743,18 @@ msgstr "git verify-pack [-v | --verbose] [-s | --stat-only] <Paket>..."
 msgid "verbose"
 msgstr "erweiterte Ausgaben"
 
 #: builtin/verify-pack.c:66
 msgid "show statistics only"
 msgstr "nur Statistiken anzeigen"
 
 #: builtin/verify-tag.c:18
-#, fuzzy
 msgid "git verify-tag [-v | --verbose] [--format=<format>] <tag>..."
-msgstr "git verify-tag [-v | --verbose] <Tag>..."
+msgstr "git verify-tag [-v | --verbose] [--format=<Format>] <Tag>..."
 
 #: builtin/verify-tag.c:36
 msgid "print tag contents"
 msgstr "Tag-Inhalte ausgeben"
 
 #: builtin/worktree.c:15
 msgid "git worktree add [<options>] <path> [<branch>]"
 msgstr "git worktree add [<Optionen>] <Pfad> [<Branch>]"
@@ -13816,24 +13796,22 @@ msgid "Removing worktrees/%s: invalid gitdir file"
 msgstr "Lösche worktrees/%s: ungültige gitdir-Datei"
 
 #: builtin/worktree.c:80
 #, c-format
 msgid "Removing worktrees/%s: gitdir file points to non-existent location"
 msgstr "Lösche worktrees/%s: gitdir-Datei verweist auf nicht existierenden Ort"
 
 #: builtin/worktree.c:128
-#, fuzzy
 msgid "report pruned working trees"
-msgstr "gelöschte Notizen melden"
+msgstr "entfernte Arbeitsverzeichnisse ausgeben"
 
 #: builtin/worktree.c:130
-#, fuzzy
 msgid "expire working trees older than <time>"
-msgstr "Objekte älter als <Zeit> verfallen lassen"
+msgstr "Arbeitsverzeichnisse älter als <Zeit> verfallen lassen"
 
 #: builtin/worktree.c:204
 #, c-format
 msgid "'%s' already exists"
 msgstr "'%s' existiert bereits"
 
 #: builtin/worktree.c:236
 #, c-format
@@ -13976,21 +13954,24 @@ msgstr ""
 
 #: http.c:1713
 #, c-format
 msgid ""
 "unable to update url base from redirection:\n"
 "  asked for: %s\n"
 "   redirect: %s"
 msgstr ""
+"Konnte Basis-URL nicht durch Umleitung aktualisieren:\n"
+"  gefragt nach: %s\n"
+"    umgeleitet: %s"
 
 #: remote-curl.c:319
 #, c-format
 msgid "redirecting to %s"
-msgstr ""
+msgstr "Leite nach %s um"
 
 #: common-cmds.h:9
 msgid "start a working area (see also: git help tutorial)"
 msgstr "Arbeitsverzeichnis anlegen (siehe auch: git help tutorial)"
 
 #: common-cmds.h:10
 msgid "work on the current change (see also: git help everyday)"
 msgstr "an aktuellen Änderungen arbeiten (siehe auch: git help everyday)"
@@ -14685,19 +14666,19 @@ msgid "repo URL: '$repo' must be absolute or begin with ./|../"
 msgstr "repo URL: '$repo' muss absolut sein oder mit ./|../ beginnen"
 
 #: git-submodule.sh:210
 #, sh-format
 msgid "'$sm_path' already exists in the index"
 msgstr "'$sm_path' ist bereits zum Commit vorgemerkt"
 
 #: git-submodule.sh:213
-#, fuzzy, sh-format
+#, sh-format
 msgid "'$sm_path' already exists in the index and is not a submodule"
-msgstr "'$sm_path' ist bereits zum Commit vorgemerkt"
+msgstr "'$sm_path' ist bereits zum Commit vorgemerkt und ist kein Submodul"
 
 #: git-submodule.sh:218
 #, sh-format
 msgid ""
 "The following path is ignored by one of your .gitignore files:\n"
 "$sm_path\n"
 "Use -f if you really want to add it."
 msgstr ""
@@ -15441,791 +15422,878 @@ msgstr ""
 #: git-sh-setup.sh:377
 msgid "Unable to determine absolute path of git directory"
 msgstr "Konnte absoluten Pfad des Git-Verzeichnisses nicht bestimmen."
 
 #. TRANSLATORS: you can adjust this to align "git add -i" status menu
 #: git-add--interactive.perl:238
 #, perl-format
 msgid "%12s %12s %s"
-msgstr ""
+msgstr "%28s %25s %s"
 
 #: git-add--interactive.perl:239
 msgid "staged"
-msgstr ""
+msgstr "zur Staging-Area hinzugefügt"
 
 #: git-add--interactive.perl:239
 msgid "unstaged"
-msgstr ""
+msgstr "aus Staging-Area entfernt"
 
 #: git-add--interactive.perl:297 git-add--interactive.perl:322
 msgid "binary"
-msgstr ""
+msgstr "Binär"
 
 #: git-add--interactive.perl:306 git-add--interactive.perl:360
 msgid "nothing"
-msgstr ""
+msgstr "Nichts"
 
 #: git-add--interactive.perl:342 git-add--interactive.perl:357
-#, fuzzy
 msgid "unchanged"
-msgstr "Keine Änderungen"
+msgstr "unverändert"
 
 #: git-add--interactive.perl:653
-#, fuzzy, perl-format
+#, perl-format
 msgid "added %d path\n"
 msgid_plural "added %d paths\n"
-msgstr[0] "von denen hinzugefügt:"
-msgstr[1] "von denen hinzugefügt:"
+msgstr[0] "%d Pfad hinzugefügt\n"
+msgstr[1] "%d Pfade hinzugefügt\n"
 
 #: git-add--interactive.perl:656
 #, perl-format
 msgid "updated %d path\n"
 msgid_plural "updated %d paths\n"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Pfad aktualisiert\n"
+msgstr[1] "%d Pfade aktualisiert\n"
 
 #: git-add--interactive.perl:659
 #, perl-format
 msgid "reverted %d path\n"
 msgid_plural "reverted %d paths\n"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Pfad wiederhergestellt\n"
+msgstr[1] "%d Pfade wiederhergestellt\n"
 
 #: git-add--interactive.perl:662
 #, perl-format
 msgid "touched %d path\n"
 msgid_plural "touched %d paths\n"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Pfad angefasst\n"
+msgstr[1] "%d Pfade angefasst\n"
 
 #: git-add--interactive.perl:671
-#, fuzzy
 msgid "Update"
-msgstr "Datum"
+msgstr "Aktualisieren"
 
 #: git-add--interactive.perl:683
-#, fuzzy
 msgid "Revert"
 msgstr "Revert"
 
 #: git-add--interactive.perl:706
 #, perl-format
 msgid "note: %s is untracked now.\n"
-msgstr ""
+msgstr "Hinweis: %s ist nun unversioniert.\n"
 
 #: git-add--interactive.perl:717
-#, fuzzy
 msgid "Add untracked"
-msgstr " gefolgt"
+msgstr "unversionierte Dateien hinzufügen"
 
 #: git-add--interactive.perl:723
-#, fuzzy
 msgid "No untracked files.\n"
-msgstr "Unversionierte Dateien"
+msgstr "Keine unversionierten Dateien.\n"
 
 #: git-add--interactive.perl:1039
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be\n"
 "marked for staging."
 msgstr ""
+"Wenn der Patch sauber angewendet werden kann, wird der bearbeitete Patch-Block\n"
+"direkt als zum Hinzufügen zur Staging-Area markiert."
 
 #: git-add--interactive.perl:1042
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be\n"
 "marked for stashing."
 msgstr ""
+"Wenn der Patch sauber angewendet werden kann, wird der bearbeitete Patch-Block\n"
+"direkt als zum Hinzufügen zum Stash markiert."
 
 #: git-add--interactive.perl:1045
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be\n"
 "marked for unstaging."
 msgstr ""
+"Wenn der Patch sauber angewendet werden kann, wird der bearbeitete Patch-Block\n"
+"direkt als zum Entfernen aus der Staging-Area markiert."
 
 #: git-add--interactive.perl:1048 git-add--interactive.perl:1057
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be\n"
 "marked for applying."
 msgstr ""
+"Wenn der Patch sauber angewendet werden kann, wird der bearbeitete Patch-Block\n"
+"direkt als zum Anwenden markiert."
 
 #: git-add--interactive.perl:1051
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be\n"
 "marked for discarding"
 msgstr ""
+"Wenn der Patch sauber angewendet werden kann, wird der bearbeitete Patch-Block\n"
+"direkt als zum Verwerfen markiert."
 
 #: git-add--interactive.perl:1054
 msgid ""
 "If the patch applies cleanly, the edited hunk will immediately be\n"
 "marked for discarding."
 msgstr ""
+"Wenn der Patch sauber angewendet werden kann, wird der bearbeitete Patch-Block\n"
+"direkt als zum Verwerfen markiert."
 
 #: git-add--interactive.perl:1067
-#, fuzzy, perl-format
+#, perl-format
 msgid "failed to open hunk edit file for writing: %s"
-msgstr "Fehler beim Erweitern des Nutzerverzeichnisses in: '%s'"
+msgstr "Fehler beim Öffnen von Editier-Datei eines Patch-Blocks zum Schreiben: %s"
 
 #: git-add--interactive.perl:1068
 msgid "Manual hunk edit mode -- see bottom for a quick guide.\n"
 msgstr ""
+"Manueller Editiermodus für Patch-Blöcke -- siehe nach unten für eine\n"
+"Kurzanleitung.\n"
 
 #: git-add--interactive.perl:1074
 #, perl-format
 msgid ""
 "---\n"
 "To remove '%s' lines, make them ' ' lines (context).\n"
 "To remove '%s' lines, delete them.\n"
 "Lines starting with %s will be removed.\n"
 msgstr ""
+"---\n"
+"Um '%s' Zeilen zu entfernen, machen Sie aus diesen ' ' Zeilen (Kontext).\n"
+"Um '%s' Zeilen zu entfernen, löschen Sie diese.\n"
+"Zeilen, die mit %s beginnen, werden entfernt.\n"
 
 #. TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.
 #: git-add--interactive.perl:1082
 msgid ""
 "If it does not apply cleanly, you will be given an opportunity to\n"
 "edit again.  If all lines of the hunk are removed, then the edit is\n"
 "aborted and the hunk is left unchanged.\n"
 msgstr ""
+"Wenn das nicht sauber angewendet werden kann, haben Sie die Möglichkeit\n"
+"einer erneuten Bearbeitung. Wenn alle Zeilen des Patch-Blocks entfernt werden,\n"
+"wird die Bearbeitung abgebrochen und der Patch-Block bleibt unverändert.\n"
 
 #: git-add--interactive.perl:1096
-#, fuzzy, perl-format
+#, perl-format
 msgid "failed to open hunk edit file for reading: %s"
-msgstr "Fehler beim Erweitern des Nutzerverzeichnisses in: '%s'"
+msgstr "Fehler beim Öffnen von Editier-Datei eines Patch-Blocks zum Lesen: %s"
 
 #. TRANSLATORS: do not translate [y/n]
 #. The program will only accept that input
 #. at this point.
 #. Consider translating (saying "no" discards!) as
 #. (saying "n" for "no" discards!) if the translation
 #. of the word "no" does not start with n.
 #: git-add--interactive.perl:1187
 msgid ""
 "Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? "
 msgstr ""
+"Ihr bearbeiteter Patch-Block kann nicht angewendet werden.\n"
+"Erneut bearbeiten? (\"n\" verwirft Bearbeitung!) [y/n]?"
 
 #: git-add--interactive.perl:1196
 msgid ""
 "y - stage this hunk\n"
 "n - do not stage this hunk\n"
 "q - quit; do not stage this hunk or any of the remaining ones\n"
 "a - stage this hunk and all later hunks in the file\n"
 "d - do not stage this hunk or any of the later hunks in the file"
 msgstr ""
+"y - diesen Patch-Block zum Commit vormerken\n"
+"n - diesen Patch-Block nicht zum Commit vormerken\n"
+"q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht zum Commit vormerken\n"
+"a - diesen und alle weiteren Patch-Blöcke dieser Datei zum Commit vormerken\n"
+"d - diesen oder alle weiteren Patch-Blöcke in dieser Datei nicht zum Commit vormerken"
 
 #: git-add--interactive.perl:1202
 msgid ""
 "y - stash this hunk\n"
 "n - do not stash this hunk\n"
 "q - quit; do not stash this hunk or any of the remaining ones\n"
 "a - stash this hunk and all later hunks in the file\n"
 "d - do not stash this hunk or any of the later hunks in the file"
 msgstr ""
+"y - diesen Patch-Block stashen\n"
+"n - diesen Patch-Block nicht stashen\n"
+"q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht stashen\n"
+"a - diesen und alle weiteren Patch-Blöcke dieser Datei stashen\n"
+"d - diesen oder alle weiteren Patch-Blöcke dieser Datei nicht stashen"
 
 #: git-add--interactive.perl:1208
 msgid ""
 "y - unstage this hunk\n"
 "n - do not unstage this hunk\n"
 "q - quit; do not unstage this hunk or any of the remaining ones\n"
 "a - unstage this hunk and all later hunks in the file\n"
 "d - do not unstage this hunk or any of the later hunks in the file"
 msgstr ""
+"y - diesen Patch-Block unstashen\n"
+"n - diesen Patch-Block nicht unstashen\n"
+"q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht unstashen\n"
+"a - diesen und alle weiteren Patch-Blöcke dieser Datei unstashen\n"
+"d - diesen oder alle weiteren Patch-Blöcke dieser Datei nicht unstashen"
 
 #: git-add--interactive.perl:1214
 msgid ""
 "y - apply this hunk to index\n"
 "n - do not apply this hunk to index\n"
 "q - quit; do not apply this hunk or any of the remaining ones\n"
 "a - apply this hunk and all later hunks in the file\n"
 "d - do not apply this hunk or any of the later hunks in the file"
 msgstr ""
+"y - diesen Patch-Block auf den Index anwenden\n"
+"n - diesen Patch-Block nicht auf den Index anwenden\n"
+"q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht auf den Index anwenden\n"
+"a - diesen und alle weiteren Patch-Blöcke dieser Datei auf den Index anwenden\n"
+"d - diesen oder alle weiteren Patch-Blöcke dieser Datei nicht auf den Index anwenden"
 
 #: git-add--interactive.perl:1220
 msgid ""
 "y - discard this hunk from worktree\n"
 "n - do not discard this hunk from worktree\n"
 "q - quit; do not discard this hunk or any of the remaining ones\n"
 "a - discard this hunk and all later hunks in the file\n"
 "d - do not discard this hunk or any of the later hunks in the file"
 msgstr ""
+"y - diesen Patch-Block im Arbeitsverzeichnis verwerfen\n"
+"n - diesen Patch-Block im Arbeitsverzeichnis nicht verwerfen\n"
+"q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht im Arbeitsverzeichnis verwerfen\n"
+"a - diesen und alle weiteren Patch-Blöcke dieser Datei im Arbeitsverzeichnis verwerfen\n"
+"d - diesen oder alle weiteren Patch-Blöcke dieser Datei nicht im Arbeitsverzeichnis verwerfen"
 
 #: git-add--interactive.perl:1226
 msgid ""
 "y - discard this hunk from index and worktree\n"
 "n - do not discard this hunk from index and worktree\n"
 "q - quit; do not discard this hunk or any of the remaining ones\n"
 "a - discard this hunk and all later hunks in the file\n"
 "d - do not discard this hunk or any of the later hunks in the file"
 msgstr ""
+"y - diesen Patch-Block im Index und Arbeitsverzeichnis verwerfen\n"
+"n - diesen Patch-Block nicht im Index und Arbeitsverzeichnis verwerfen\n"
+"q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht im Index und Arbeitsverzeichnis verwerfen\n"
+"a - diesen und alle weiteren Patch-Blöcke in der Datei verwerfen\n"
+"d - diesen oder alle weiteren Patch-Blöcke in der Datei nicht verwerfen"
 
 #: git-add--interactive.perl:1232
 msgid ""
 "y - apply this hunk to index and worktree\n"
 "n - do not apply this hunk to index and worktree\n"
 "q - quit; do not apply this hunk or any of the remaining ones\n"
 "a - apply this hunk and all later hunks in the file\n"
 "d - do not apply this hunk or any of the later hunks in the file"
 msgstr ""
+"y - diesen Patch-Block im Index und auf Arbeitsverzeichnis anwenden\n"
+"n - diesen Patch-Block nicht im Index und auf Arbeitsverzeichnis anwenden\n"
+"q - Beenden; diesen oder alle verbleibenden Patch-Blöcke nicht anwenden\n"
+"a - diesen und alle weiteren Patch-Blöcke in der Datei anwenden\n"
+"d - diesen oder alle weiteren Patch-Blöcke in der Datei nicht anwenden"
 
 #: git-add--interactive.perl:1241
 msgid ""
 "g - select a hunk to go to\n"
 "/ - search for a hunk matching the given regex\n"
 "j - leave this hunk undecided, see next undecided hunk\n"
 "J - leave this hunk undecided, see next hunk\n"
 "k - leave this hunk undecided, see previous undecided hunk\n"
 "K - leave this hunk undecided, see previous hunk\n"
 "s - split the current hunk into smaller hunks\n"
 "e - manually edit the current hunk\n"
 "? - print help\n"
 msgstr ""
+"g - Patch-Block zum Hinspringen auswählen\n"
+"/ - nach Patch-Block suchen der gegebenem regulärem Ausdruck entspricht\n"
+"j - diesen Patch-Block unbestimmt lassen, nächsten unbestimmten Patch-Block anzeigen\n"
+"J - diesen Patch-Block unbestimmt lassen, nächsten Patch-Block anzeigen\n"
+"k - diesen Patch-Block unbestimmt lassen, vorherigen unbestimmten Patch-Block anzeigen\n"
+"K - diesen Patch-Block unbestimmt lassen, vorherigen Patch-Block anzeigen\n"
+"s - aktuellen Patch-Block in kleinere Patch-Blöcke aufteilen\n"
+"e - aktuellen Patch-Block manuell editieren\n"
+"? - Hilfe anzeigen\n"
 
 #: git-add--interactive.perl:1272
-#, fuzzy
 msgid "The selected hunks do not apply to the index!\n"
-msgstr "den angegebenen Eintrag zum Commit vormerken"
+msgstr "Die ausgewählten Patch-Blöcke können nicht auf den Index angewendet werden!\n"
 
 #: git-add--interactive.perl:1273
-#, fuzzy
 msgid "Apply them to the worktree anyway? "
-msgstr "Pfad zum Arbeitsverzeichnis"
+msgstr "Trotzdem auf Arbeitsverzeichnis anwenden? "
 
 #: git-add--interactive.perl:1276
 msgid "Nothing was applied.\n"
-msgstr ""
+msgstr "Nichts angewendet.\n"
 
 #: git-add--interactive.perl:1287
-#, fuzzy, perl-format
+#, perl-format
 msgid "ignoring unmerged: %s\n"
-msgstr "Füge zusammengeführte Datei %s hinzu"
+msgstr "ignoriere nicht zusammengeführte Datei: %s\n"
 
 #: git-add--interactive.perl:1296
 msgid "Only binary files changed.\n"
-msgstr ""
+msgstr "Nur Binärdateien geändert.\n"
 
 #: git-add--interactive.perl:1298
-#, fuzzy
 msgid "No changes.\n"
-msgstr "Keine Änderungen"
+msgstr "Keine Änderungen.\n"
 
 #: git-add--interactive.perl:1306
-#, fuzzy
 msgid "Patch update"
-msgstr "[Tag Aktualisierung]"
+msgstr "Patch Aktualisierung"
 
 #: git-add--interactive.perl:1358
 #, perl-format
 msgid "Stage mode change [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Modusänderung der Staging-Area hinzufügen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1359
 #, perl-format
 msgid "Stage deletion [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Löschung der Staging-Area hinzufügen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1360
 #, perl-format
 msgid "Stage this hunk [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Diesen Patch-Block der Staging-Area hinzufügen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1363
 #, perl-format
 msgid "Stash mode change [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Modusänderung stashen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1364
 #, perl-format
 msgid "Stash deletion [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Löschung stashen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1365
 #, perl-format
 msgid "Stash this hunk [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Diesen Patch-Block stashen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1368
 #, perl-format
 msgid "Unstage mode change [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Modusänderung aus der Staging-Area entfernen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1369
 #, perl-format
 msgid "Unstage deletion [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Löschung aus der Staging-Area entfernen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1370
 #, perl-format
 msgid "Unstage this hunk [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Diesen Patch-Block aus der Staging-Area entfernen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1373
 #, perl-format
 msgid "Apply mode change to index [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Modusänderung auf Index anwenden [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1374
 #, perl-format
 msgid "Apply deletion to index [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Löschung auf Index anwenden [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1375
 #, perl-format
 msgid "Apply this hunk to index [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Diesen Patch-Block auf Index anwenden [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1378
 #, perl-format
 msgid "Discard mode change from worktree [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Modusänderung im Arbeitsverzeichnis verwerfen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1379
 #, perl-format
 msgid "Discard deletion from worktree [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Löschung im Arbeitsverzeichnis verwerfen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1380
 #, perl-format
 msgid "Discard this hunk from worktree [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "diesen Patch-Block im Arbeitsverzeichnis verwerfen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1383
 #, perl-format
 msgid "Discard mode change from index and worktree [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Modusänderung vom Index und Arbeitsverzeichnis verwerfen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1384
 #, perl-format
 msgid "Discard deletion from index and worktree [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Löschung vom Index und Arbeitsverzeichnis verwerfen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1385
 #, perl-format
 msgid "Discard this hunk from index and worktree [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Diesen Patch-Block vom Index und Arbeitsverzeichnis verwerfen [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1388
 #, perl-format
 msgid "Apply mode change to index and worktree [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Modusänderung auf Index und Arbeitsverzeichnis anwenden [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1389
 #, perl-format
 msgid "Apply deletion to index and worktree [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Löschung auf Index und Arbeitsverzeichnis anwenden [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1390
 #, perl-format
 msgid "Apply this hunk to index and worktree [y,n,q,a,d,/%s,?]? "
-msgstr ""
+msgstr "Diesen Patch-Block auf Index und Arbeitsverzeichnis anwenden [y,n,q,a,d,/%s,?]? "
 
 #: git-add--interactive.perl:1493
 msgid "go to which hunk (<ret> to see more)? "
-msgstr ""
+msgstr "zu welchem Patch-Block springen (<Enter> für mehr Informationen)? "
 
 #: git-add--interactive.perl:1495
 msgid "go to which hunk? "
-msgstr ""
+msgstr "zu welchem Patch-Block springen? "
 
 #: git-add--interactive.perl:1504
-#, fuzzy, perl-format
+#, perl-format
 msgid "Invalid number: '%s'\n"
-msgstr "Ungültiger %s: '%s'"
+msgstr "Ungültige Nummer: '%s'\n"
 
 #: git-add--interactive.perl:1509
 #, perl-format
 msgid "Sorry, only %d hunk available.\n"
 msgid_plural "Sorry, only %d hunks available.\n"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Entschuldigung, nur %d Patch-Block verfügbar.\n"
+msgstr[1] "Entschuldigung, nur %d Patch-Blöcke verfügbar.\n"
 
 #: git-add--interactive.perl:1535
 msgid "search for regex? "
-msgstr ""
+msgstr "Suche nach regulärem Ausdruck? "
 
 #: git-add--interactive.perl:1548
 #, perl-format
 msgid "Malformed search regexp %s: %s\n"
-msgstr ""
+msgstr "Fehlerhafter regulärer Ausdruck für Suche %s: %s\n"
 
 #: git-add--interactive.perl:1558
-#, fuzzy
 msgid "No hunk matches the given pattern\n"
-msgstr "Änderungen nur im angegebenen Pfad anwenden"
+msgstr "Kein Patch-Block entspricht dem angegebenen Pattern\n"
 
 #: git-add--interactive.perl:1570 git-add--interactive.perl:1592
 msgid "No previous hunk\n"
-msgstr ""
+msgstr "Kein vorheriger Patch-Block\n"
 
 #: git-add--interactive.perl:1579 git-add--interactive.perl:1598
 msgid "No next hunk\n"
-msgstr ""
+msgstr "Kein folgender Patch-Block\n"
 
 #: git-add--interactive.perl:1606
 #, perl-format
 msgid "Split into %d hunk.\n"
 msgid_plural "Split into %d hunks.\n"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "In %d Patch-Block aufgeteilt.\n"
+msgstr[1] "In %d Patch-Blöcke aufgeteilt.\n"
 
 #: git-add--interactive.perl:1658
 msgid "Review diff"
-msgstr ""
+msgstr "Diff überprüfen"
 
 #. TRANSLATORS: please do not translate the command names
 #. 'status', 'update', 'revert', etc.
 #: git-add--interactive.perl:1677
 msgid ""
 "status        - show paths with changes\n"
 "update        - add working tree state to the staged set of changes\n"
 "revert        - revert staged set of changes back to the HEAD version\n"
 "patch         - pick hunks and update selectively\n"
 "diff\t      - view diff between HEAD and index\n"
 "add untracked - add contents of untracked files to the staged set of "
 "changes\n"
 msgstr ""
+"status        - Pfade mit Änderungen anzeigen\n"
+"update        - Zustand des Arbeitsverzeichnisses den zum Commit vorgemerkten Änderungen hinzufügen\n"
+"revert        - zum Commit vorgemerkten Änderungen auf HEAD Version zurücksetzen\n"
+"patch         - Patch-Blöcke auswählen und selektiv aktualisieren\n"
+"diff\t      - Unterschiede zwischen HEAD und Index anzeigen\n"
+"add untracked - Inhalte von unversionierten Dateien zum Commit vormerken\n"
 
 #: git-add--interactive.perl:1694 git-add--interactive.perl:1699
 #: git-add--interactive.perl:1702 git-add--interactive.perl:1709
 #: git-add--interactive.perl:1713 git-add--interactive.perl:1719
 msgid "missing --"
-msgstr ""
+msgstr "-- fehlt"
 
 #: git-add--interactive.perl:1715
-#, fuzzy, perl-format
+#, perl-format
 msgid "unknown --patch mode: %s"
-msgstr "Unbekannter Wert für -s/--strategy: %s"
+msgstr "Unbekannter --patch Modus: %s"
 
 #: git-add--interactive.perl:1721 git-add--interactive.perl:1727
-#, fuzzy, perl-format
+#, perl-format
 msgid "invalid argument %s, expecting --"
-msgstr "ungültige Pfadspezifikation"
+msgstr "ungültiges Argument %s, erwarte --"
 
 #: git-send-email.perl:121
 msgid "local zone differs from GMT by a non-minute interval\n"
-msgstr ""
+msgstr "lokale Zeitzone unterscheidet sich von GMT nicht um einen Minutenintervall\n"
 
 #: git-send-email.perl:128 git-send-email.perl:134
 msgid "local time offset greater than or equal to 24 hours\n"
-msgstr ""
+msgstr "lokaler Zeit-Offset größer oder gleich 24 Stunden\n"
 
 #: git-send-email.perl:202 git-send-email.perl:208
 msgid "the editor exited uncleanly, aborting everything"
-msgstr ""
+msgstr "Der Editor wurde unsauber beendet, breche alles ab."
 
 #: git-send-email.perl:282
 #, perl-format
 msgid ""
 "'%s' contains an intermediate version of the email you were composing.\n"
-msgstr ""
+msgstr "'%s' enthält eine Zwischenversion der E-Mail, die Sie gerade verfassen.\n"
 
 #: git-send-email.perl:287
 #, perl-format
 msgid "'%s.final' contains the composed email.\n"
-msgstr ""
+msgstr "'%s.final' enthält die verfasste E-Mail.\n"
 
 #: git-send-email.perl:305
-#, fuzzy
 msgid "--dump-aliases incompatible with other options\n"
-msgstr "Die Option --dirty kann nicht mit Commits verwendet werden."
+msgstr "--dump-aliases ist mit anderen Optionen inkompatibel\n"
 
 #: git-send-email.perl:368 git-send-email.perl:623
-#, fuzzy
 msgid "Cannot run git format-patch from outside a repository\n"
-msgstr ""
-"Die Option --cached kann nicht außerhalb eines Repositories verwendet werden."
+msgstr "Kann 'git format-patch' nicht außerhalb eines Repositories ausführen.\n"
 
 #: git-send-email.perl:437
 #, perl-format
 msgid "Unknown --suppress-cc field: '%s'\n"
-msgstr ""
+msgstr "Unbekanntes --suppress-cc Feld: '%s'\n"
 
 #: git-send-email.perl:466
-#, fuzzy, perl-format
+#, perl-format
 msgid "Unknown --confirm setting: '%s'\n"
-msgstr "Unbekannter Commit %s"
+msgstr "Unbekannte --confirm Einstellung: '%s'\n"
 
 #: git-send-email.perl:498
 #, perl-format
 msgid "warning: sendmail alias with quotes is not supported: %s\n"
-msgstr ""
+msgstr "Warnung: sendemail Alias mit Anführungsstrichen wird nicht unterstützt: %s\n"
 
 #: git-send-email.perl:500
 #, perl-format
 msgid "warning: `:include:` not supported: %s\n"
-msgstr ""
+msgstr "Warnung: `:include:` wird nicht unterstützt: %s\n"
 
 #: git-send-email.perl:502
 #, perl-format
 msgid "warning: `/file` or `|pipe` redirection not supported: %s\n"
-msgstr ""
+msgstr "Warnung: `/file` oder `|pipe` Umleitung wird nicht unterstützt: %s\n"
 
 #: git-send-email.perl:507
 #, perl-format
 msgid "warning: sendmail line is not recognized: %s\n"
-msgstr ""
+msgstr "Warnung: sendmail Zeile wird nicht erkannt: %s\n"
 
 #: git-send-email.perl:589
 #, perl-format
 msgid ""
 "File '%s' exists but it could also be the range of commits\n"
 "to produce patches for.  Please disambiguate by...\n"
 "\n"
 "    * Saying \"./%s\" if you mean a file; or\n"
 "    * Giving --format-patch option if you mean a range.\n"
 msgstr ""
+"Datei '%s' existiert, aber es könnte auch der Bereich von Commits sein,\n"
+"für den Patches erzeugt werden sollen. Bitte machen Sie dies eindeutig\n"
+"indem Sie ...\n"
+"\n"
+"    * \"./%s\" angeben, wenn Sie eine Datei meinen, oder\n"
+"    * die Option --format-patch angeben, wenn Sie einen Commit-Bereich meinen\n"
 
 #: git-send-email.perl:610
-#, fuzzy, perl-format
+#, perl-format
 msgid "Failed to opendir %s: %s"
-msgstr "Fehler beim Öffnen von '%s': %s"
+msgstr "Fehler beim Öffnen von %s: %s"
 
 #: git-send-email.perl:634
 #, perl-format
 msgid ""
 "fatal: %s: %s\n"
 "warning: no patches were sent\n"
 msgstr ""
+"fatal: %s: %s\n"
+"Warnung: Es wurden keine Patches versendet.\n"
 
 #: git-send-email.perl:645
-#, fuzzy
 msgid ""
 "\n"
 "No patch files specified!\n"
 "\n"
-msgstr "kein Pfad angegeben"
+msgstr "\nkeine Patch-Dateien angegeben!\n\n"
 
 #: git-send-email.perl:658
-#, fuzzy, perl-format
+#, perl-format
 msgid "No subject line in %s?"
-msgstr "Objekt nicht gefunden: %s"
+msgstr "Keine Betreffzeile in %s?"
 
 #: git-send-email.perl:668
-#, fuzzy, perl-format
+#, perl-format
 msgid "Failed to open for writing %s: %s"
-msgstr "Fehler beim Öffnen von '%s': %s"
+msgstr "Fehler beim Öffnen von '%s' zum Schreiben: %s"
 
 #: git-send-email.perl:678
 msgid ""
 "Lines beginning in \"GIT:\" will be removed.\n"
 "Consider including an overall diffstat or table of contents\n"
 "for the patch you are writing.\n"
 "\n"
 "Clear the body content if you don't wish to send a summary.\n"
 msgstr ""
+"Zeilen, die mit \"GIT:\" beginnen, werden entfernt.\n"
+"Ziehen Sie in Betracht, einen allgemeinen \"diffstat\" oder ein\n"
+"Inhaltsverzeichnis, für den Patch den Sie schreiben, hinzuzufügen.\n"
+"\n"
+"Leeren Sie den Inhalt des Bodys, wenn Sie keine Zusammenfassung senden möchten.\n"
 
 #: git-send-email.perl:701
-#, fuzzy, perl-format
+#, perl-format
 msgid "Failed to open %s.final: %s"
-msgstr "Fehler beim Öffnen von '%s': %s"
+msgstr "Fehler beim Öffnen von %s.final: %s"
 
 #: git-send-email.perl:704
-#, fuzzy, perl-format
+#, perl-format
 msgid "Failed to open %s: %s"
-msgstr "Fehler beim Öffnen von '%s': %s"
+msgstr "Fehler beim Öffnen von %s: %s"
 
 #: git-send-email.perl:739
 msgid "To/Cc/Bcc fields are not interpreted yet, they have been ignored\n"
-msgstr ""
+msgstr "To/Cc/Bcc Felder wurden noch nicht interpretiert, sie wurden ignoriert\n"
 
 #: git-send-email.perl:748
 msgid "Summary email is empty, skipping it\n"
-msgstr ""
+msgstr "E-Mail mit Zusammenfassung ist leer, wird ausgelassen\n"
 
 #. TRANSLATORS: please keep [y/N] as is.
 #: git-send-email.perl:780
 #, perl-format
 msgid "Are you sure you want to use <%s> [y/N]? "
-msgstr ""
+msgstr "Sind Sie sich sicher, <%s> zu benutzen [y/N]? "
 
 #: git-send-email.perl:809
 msgid ""
 "The following files are 8bit, but do not declare a Content-Transfer-"
 "Encoding.\n"
 msgstr ""
+"Die folgenden Dateien sind 8-Bit, aber deklarieren kein\n"
+"Content-Transfer-Encoding.\n"
 
 #: git-send-email.perl:814
 msgid "Which 8bit encoding should I declare [UTF-8]? "
-msgstr ""
+msgstr "Welches 8-Bit-Encoding soll deklariert werden [UTF-8]? "
 
 #: git-send-email.perl:822
 #, perl-format
 msgid ""
 "Refusing to send because the patch\n"
 "\t%s\n"
 "has the template subject '*** SUBJECT HERE ***'. Pass --force if you really "
 "want to send.\n"
 msgstr ""
+"Versand zurückgewiesen, weil der Patch\n"
+"\t%s\n"
+"die Betreffzeilenvorlage '*** SUBJECT HERE ***' enthält. Geben Sie --force an,\n"
+"wenn Sie den Patch wirklich versenden wollen.\n"
 
 #: git-send-email.perl:841
 msgid "To whom should the emails be sent (if anyone)?"
-msgstr ""
+msgstr "An wen sollen die E-Mails versendet werden (wenn überhaupt jemand)?"
 
 #: git-send-email.perl:859
 #, perl-format
 msgid "fatal: alias '%s' expands to itself\n"
-msgstr ""
+msgstr "fatal: Alias '%s' erweitert sich zu sich selbst\n"
 
 #: git-send-email.perl:871
 msgid "Message-ID to be used as In-Reply-To for the first email (if any)? "
-msgstr ""
+msgstr "Message-ID zur Verwendung als In-Reply-To für die erste E-Mail (wenn eine existiert)? "
 
 #: git-send-email.perl:921 git-send-email.perl:929
 #, perl-format
 msgid "error: unable to extract a valid address from: %s\n"
-msgstr ""
+msgstr "Fehler: konnte keine gültige Adresse aus %s extrahieren\n"
 
 #. TRANSLATORS: Make sure to include [q] [d] [e] in your
 #. translation. The program will only accept English input
 #. at this point.
 #: git-send-email.perl:933
 msgid "What to do with this address? ([q]uit|[d]rop|[e]dit): "
-msgstr ""
+msgstr "Was soll mit dieser Adresse geschehen? (Beenden [q]|Löschen [d]|Bearbeiten [e]): "
 
 #: git-send-email.perl:1234
-#, fuzzy, perl-format
+#, perl-format
 msgid "CA path \"%s\" does not exist"
-msgstr "Pfad '%s' existiert nicht"
+msgstr "CA Pfad \"%s\" existiert nicht"
 
 #: git-send-email.perl:1309
 msgid ""
 "    The Cc list above has been expanded by additional\n"
 "    addresses found in the patch commit message. By default\n"
 "    send-email prompts before sending whenever this occurs.\n"
 "    This behavior is controlled by the sendemail.confirm\n"
 "    configuration setting.\n"
 "\n"
 "    For additional information, run 'git send-email --help'.\n"
 "    To retain the current behavior, but squelch this message,\n"
 "    run 'git config --global sendemail.confirm auto'.\n"
 "\n"
 msgstr ""
+"    Die Cc-Liste oberhalb wurde um zusätzliche Adressen erweitert, die in der\n"
+"    Commit-Beschreibung des Patches gefunden wurden. Wenn dies passiert, werden\n"
+"    Sie von send-email zu einer Eingabe aufgefordert. Dieses Verhalten wird\n"
+"    durch die Konfigurationseinstellung sendemail.confirm gesteuert.\n"
+"\n"
+"    Für weitere Informationen, führen Sie 'git send-email --help' aus.\n"
+"    Um das aktuelle Verhalten beizubehalten, aber diese Meldung zu unterdrücken,\n"
+"    führen Sie 'git config --global sendemail.confirm auto' aus.\n"
+"\n"
 
 #. TRANSLATORS: Make sure to include [y] [n] [q] [a] in your
 #. translation. The program will only accept English input
 #. at this point.
 #: git-send-email.perl:1324
 msgid "Send this email? ([y]es|[n]o|[q]uit|[a]ll): "
-msgstr ""
+msgstr "Diese E-Mail versenden? (Ja [y]|Nein [n]|Beenden [q]|Alle [a]): "
 
 #: git-send-email.perl:1327
 msgid "Send this email reply required"
-msgstr ""
+msgstr "Zum Versenden dieser E-Mail ist eine Antwort erforderlich."
 
 #: git-send-email.perl:1353
 msgid "The required SMTP server is not properly defined."
-msgstr ""
+msgstr "Der erforderliche SMTP-Server ist nicht korrekt definiert."
 
 #: git-send-email.perl:1397
-#, fuzzy, perl-format
+#, perl-format
 msgid "Server does not support STARTTLS! %s"
-msgstr "Server unterstützt kein --deepen"
+msgstr "Server unterstützt kein STARTTLS! %s"
 
 #: git-send-email.perl:1403
 msgid "Unable to initialize SMTP properly. Check config and use --smtp-debug."
 msgstr ""
+"Konnte SMTP nicht korrekt initialisieren. Bitte prüfen Sie Ihre Konfiguration\n"
+"und benutzen Sie --smtp-debug."
 
 #: git-send-email.perl:1421
-#, fuzzy, perl-format
+#, perl-format
 msgid "Failed to send %s\n"
-msgstr "Fehler beim Lesen von %s"
+msgstr "Fehler beim Senden %s\n"
 
 #: git-send-email.perl:1424
 #, perl-format
 msgid "Dry-Sent %s\n"
-msgstr ""
+msgstr "Probeversand %s\n"
 
 #: git-send-email.perl:1424
-#, fuzzy, perl-format
+#, perl-format
 msgid "Sent %s\n"
-msgstr "Lösche %s\n"
+msgstr "%s gesendet\n"
 
 #: git-send-email.perl:1426
 msgid "Dry-OK. Log says:\n"
-msgstr ""
+msgstr "Probeversand OK. Log enthält:\n"
 
 #: git-send-email.perl:1426
 msgid "OK. Log says:\n"
-msgstr ""
+msgstr "OK. Log enthält:\n"
 
 #: git-send-email.perl:1438
 msgid "Result: "
-msgstr ""
+msgstr "Ergebnis: "
 
 #: git-send-email.perl:1441
 msgid "Result: OK\n"
-msgstr ""
+msgstr "Ergebnis: OK\n"
 
 #: git-send-email.perl:1454
-#, fuzzy, perl-format
+#, perl-format
 msgid "can't open file %s"
-msgstr "Kann Datei '%s' nicht öffnen"
+msgstr "Kann Datei %s nicht öffnen"
 
 #: git-send-email.perl:1501 git-send-email.perl:1521
 #, perl-format
 msgid "(mbox) Adding cc: %s from line '%s'\n"
-msgstr ""
+msgstr "(mbox) Füge cc: hinzu: %s von Zeile '%s'\n"
 
 #: git-send-email.perl:1507
 #, perl-format
 msgid "(mbox) Adding to: %s from line '%s'\n"
-msgstr ""
+msgstr "(mbox) Füge to: hinzu: %s von Zeile '%s'\n"
 
 #: git-send-email.perl:1555
 #, perl-format
 msgid "(non-mbox) Adding cc: %s from line '%s'\n"
-msgstr ""
+msgstr "(non-mbox) Füge cc: hinzu: %s von Zeile '%s'\n"
 
 #: git-send-email.perl:1578
 #, perl-format
 msgid "(body) Adding cc: %s from line '%s'\n"
-msgstr ""
+msgstr "(body) Füge cc: hinzu: %s von Zeile '%s'\n"
 
 #: git-send-email.perl:1676
-#, fuzzy, perl-format
+#, perl-format
 msgid "(%s) Could not execute '%s'"
-msgstr "Konnte %s nicht entfernen"
+msgstr "(%s) Konnte '%s' nicht ausführen"
 
 #: git-send-email.perl:1683
 #, perl-format
 msgid "(%s) Adding %s: %s from: '%s'\n"
-msgstr ""
+msgstr "(%s) Füge %s: %s hinzu von: '%s'\n"
 
 #: git-send-email.perl:1687
-#, fuzzy, perl-format
+#, perl-format
 msgid "(%s) failed to close pipe to '%s'"
-msgstr "Konnte Datei nicht nach '%s' kopieren"
+msgstr "(%s) Fehler beim Schließen der Pipe nach '%s'"
 
 #: git-send-email.perl:1714
-#, fuzzy
 msgid "cannot send message as 7bit"
-msgstr "Kann keine Commit-Beschreibung für %s bekommen."
+msgstr "Kann Nachricht nicht als 7bit versenden."
 
 #: git-send-email.perl:1722
-#, fuzzy
 msgid "invalid transfer encoding"
-msgstr "Ungültige Referenz: %s"
+msgstr "Ungültiges Transfer-Encoding"
 
 #: git-send-email.perl:1741 git-send-email.perl:1792 git-send-email.perl:1802
-#, fuzzy, perl-format
+#, perl-format
 msgid "unable to open %s: %s\n"
-msgstr "kann %s nicht öffnen"
+msgstr "konnte %s nicht öffnen: %s\n"
 
 #: git-send-email.perl:1744
 #, perl-format
 msgid "%s: patch contains a line longer than 998 characters"
-msgstr ""
+msgstr "%s: Patch enthält eine Zeile, die länger als 998 Zeichen ist"
 
 #: git-send-email.perl:1760
 #, perl-format
 msgid "Skipping %s with backup suffix '%s'.\n"
-msgstr ""
+msgstr "Lasse %s mit Backup-Suffix '%s' aus.\n"
 
 #. TRANSLATORS: please keep "[y|N]" as is.
 #: git-send-email.perl:1764
 #, perl-format
 msgid "Do you really want to send %s? [y|N]: "
-msgstr ""
+msgstr "Wollen Sie %s wirklich versenden? [y|N]: "
 
 #~ msgid "Use an experimental blank-line-based heuristic to improve diffs"
 #~ msgstr ""
 #~ "eine experimentelle, auf Leerzeilen basierende Heuristik zur "
 #~ "Verbesserung\n"
 #~ "der Darstellung von Unterschieden verwenden"
 
 #~ msgid "Clever... amending the last one with dirty index."
-- 
2.12.0.rc1.72.g32572afd0


^ permalink raw reply related

* Re: new git-diff switch to eliminate leading "+" and "-" characters
From: Junio C Hamano @ 2017-02-19 18:59 UTC (permalink / raw)
  To: Vanderhoof, Tzadik; +Cc: Duy Nguyen, git@vger.kernel.org
In-Reply-To: <2C8817BDA27E034F8E9A669458E375EF11888CC1@APSWP0428.ms.ds.uhc.com>

"Vanderhoof, Tzadik" <tzadik.vanderhoof@optum360.com> writes:

>> From: Duy Nguyen [mailto:pclouds@gmail.com]
>> 
>> I face this "problem" every day, but most editors nowadays have block-
>> based editing that would allow you to remove a column of "+/-"
>> easily. At least it has not bothered me to think of improving it.
>
> Would a patch be welcome?

I am not enthused for at least two reasons.  

The weaker one is "it would likely to introduce a lot of noise in
the code for a feature of dubious merit".  

The other is a bit more serious.  Cutting and pasting has been a
source of lost or mangled whitespaces.  Tabs get expanded, a wrapped
long single line turns into two lines, an originally indented line
auto-indented when inserted to the receiving editor, etc., etc.,
depending on the pager that the output was passed through for the
terminal, the terminal program itself and the editor.  The "feature"
will encourage cut-and-paste, and I personally would be reluctant to
add things that encourage bad practice to the users.

As Duy said, saving the "diff" output to another file, opening in an
editor that output file and the file the patch targets to modify,
and transferring the lines while dropping unnecessray parts (i.e.
unwanted context lines and preimage lines, and possibly undesired
postimage lines, and also the leading SP/+/- designators) has no
such downside.  It obviously has an added benefit that it makes it
less likely for people to cut and paste a line and then become
unsure if they really cut from the green line or they by mistake
also pasted an adjacent red line.

So, I'd say the answer is "probably not".

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox