Git development
 help / color / mirror / Atom feed
* Re: [PATCH 0/2] Fix segmentation fault with cherry-pick
From: Johannes Schindelin @ 2016-11-25 16:41 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Markus Klein
In-Reply-To: <cover.1480091758.git.johannes.schindelin@gmx.de>

Hi,

On Fri, 25 Nov 2016, Johannes Schindelin wrote:

> The culprit is actually not cherry-pick, but a special code path that
> expects refresh_cache_entry() not to return NULL. And the fix is to
> teach it to handle NULL there.
> 
> This bug was brought to my attention by Markus Klein via
> https://github.com/git-for-windows/git/issues/952.

For the record, I looked at other callers of `refresh_cache_entry()`:
there is only `make_cache_entry()`, whose callers all handle NULL return
values except in resolve-undo.c. But that latter caller is okay because it
specifically does not allow refreshing (by passing 0 as options), so
refresh_cache_entry() cannot return NULL.

Ciao,
Dscho

^ permalink raw reply

* [PATCH 2/2] Avoid a segmentation fault with renaming merges
From: Johannes Schindelin @ 2016-11-25 16:36 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Markus Klein
In-Reply-To: <cover.1480091758.git.johannes.schindelin@gmx.de>

Under very particular circumstances, merge-recursive's `add_cacheinfo()`
function gets a `NULL` returned from `refresh_cache_entry()` without
expecting it, and subsequently passes it to `add_cache_entry()` which
consequently crashes.

Let's not crash.

This fixes https://github.com/git-for-windows/git/issues/952

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 merge-recursive.c             | 2 ++
 t/t3501-revert-cherry-pick.sh | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index 9041c2f149..609061f58a 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -235,6 +235,8 @@ static int add_cacheinfo(struct merge_options *o,
 		struct cache_entry *nce;
 
 		nce = refresh_cache_entry(ce, CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING);
+		if (!nce)
+			return err(o, _("addinfo: '%s' is not up-to-date"), path);
 		if (nce != ce)
 			ret = add_cache_entry(nce, options);
 	}
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index d96d391af3..8e21840f11 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -141,7 +141,7 @@ test_expect_success 'cherry-pick "-" works with arguments' '
 	test_cmp expect actual
 '
 
-test_expect_failure 'cherry-pick fails gracefully with dirty renamed file' '
+test_expect_success 'cherry-pick fails gracefully with dirty renamed file' '
 	test_commit to-rename &&
 	git checkout -b unrelated &&
 	test_commit unrelated &&
-- 
2.11.0.rc3.windows.1

^ permalink raw reply related

* [PATCH 1/2] cherry-pick: demonstrate a segmentation fault
From: Johannes Schindelin @ 2016-11-25 16:36 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Markus Klein
In-Reply-To: <cover.1480091758.git.johannes.schindelin@gmx.de>

In https://github.com/git-for-windows/git/issues/952, a complicated
scenario was described that leads to a segmentation fault in
cherry-pick.

It boils down to a certain code path involving a renamed file that is
dirty, for which `refresh_cache_entry()` returns `NULL`, and that
`NULL` not being handled properly.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 t/t3501-revert-cherry-pick.sh | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index 394f0005a1..d96d391af3 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -141,4 +141,16 @@ test_expect_success 'cherry-pick "-" works with arguments' '
 	test_cmp expect actual
 '
 
+test_expect_failure 'cherry-pick fails gracefully with dirty renamed file' '
+	test_commit to-rename &&
+	git checkout -b unrelated &&
+	test_commit unrelated &&
+	git checkout @{-1} &&
+	git mv to-rename.t renamed &&
+	test_tick &&
+	git commit -m renamed &&
+	echo modified >renamed &&
+	git cherry-pick unrelated
+'
+
 test_done
-- 
2.11.0.rc3.windows.1



^ permalink raw reply related

* [PATCH 0/2] Fix segmentation fault with cherry-pick
From: Johannes Schindelin @ 2016-11-25 16:36 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Markus Klein

The culprit is actually not cherry-pick, but a special code path that
expects refresh_cache_entry() not to return NULL. And the fix is to
teach it to handle NULL there.

This bug was brought to my attention by Markus Klein via
https://github.com/git-for-windows/git/issues/952.


Johannes Schindelin (2):
  cherry-pick: demonstrate a segmentation fault
  Avoid a segmentation fault with renaming merges

 merge-recursive.c             |  2 ++
 t/t3501-revert-cherry-pick.sh | 12 ++++++++++++
 2 files changed, 14 insertions(+)


base-commit: e2b2d6a172b76d44cb7b1ddb12ea5bfac9613a44
Published-As: https://github.com/dscho/git/releases/tag/cherry-pick-segfault-v1
Fetch-It-Via: git fetch https://github.com/dscho/git cherry-pick-segfault-v1

-- 
2.11.0.rc3.windows.1


^ permalink raw reply

* Re: [PATCH v8 07/10] convert: unify the "auto" handling of CRLF
From: Torsten Bögershausen @ 2016-11-25 15:48 UTC (permalink / raw)
  To: tboegi, git
In-Reply-To: <1461942123-16179-1-git-send-email-tboegi@web.de>

RFH, the normalization as descrived in Documentation/gitattributes.txt
does not work anymore:


From a clean working directory:

-------------------------------------------------
$ echo "* text=auto" >.gitattributes
$ rm .git/index     # Remove the index to force Git to
$ git reset         # re-scan the working directory
$ git status        # Show files that will be normalized
$ git add -u
$ git add .gitattributes
$ git commit -m "Introduce end-of-line normalization"
-------------------------------------------------


I have different ideas, how a a normalizatio  can be done:

A) 
-------------------------------------------------
$ echo "* text=auto" >.gitattributes
$ rm .git/index
$ git add .
$ git status        # Show files that will be normalized
$ git commit -m "Introduce end-of-line normalization"
-------------------------------------------------

B)
$ echo "* text=auto" >.gitattributes &&
$ git add .gitattributes &&
$ git ls-files --eol | egrep '^i/(crlf|mixed).*attr/(text|auto)' | ( TAB=$(printf "\t") ; sed -e "s/.*$TAB/dos2unix /" ) >/tmp/$$ &&
$ /bin/sh /tmp/$$ &&
$ rm -f /tmp/$$ &&
$ git add -u &&
$ git commit -m "Introduce end-of-line normalization"

C) 
Teach "git add" to learn --renormalize and then
-------------------------------------------------
$ echo "* text=auto" >.gitattributes
$ git add -u --renormalize
$ git add .gitattributes
$ git commit -m "Introduce end-of-line normalization"
-------------------------------------------------

(None of them is really tested)

A) may loose the execute bit
B) dos2unix is not installed everywhere (like Mac OS)
C) seems to most attractive, but I couldn't find out how to forward
   options from "git add" into convert.c


Any help is appreciated.







^ permalink raw reply

* Re: [PATCH 0/3] Minor fixes on 'git worktree'
From: Duy Nguyen @ 2016-11-25 13:44 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List, Mike Rappazzo
In-Reply-To: <CACsJy8D+vyO0LF_A2Wym+PUg=HOTPyDe-1fVwv8zN797pL-rmw@mail.gmail.com>

On Fri, Nov 25, 2016 at 7:24 PM, Duy Nguyen <pclouds@gmail.com> wrote:
> Adding the test for the failed parse_ref() is possible, I think. But
> since that function is destined to die, as I promised to use
> refs-provided api instead of rolling out a custom ref parser, and I'm
> going to have another hard look at refs subsystem for the
> gc-not-looking-at-worktree-refs problem, may I make another promise to
> add tests after this function is gone?

Never mind. I went ahead and made a test case anyway because why not.

But that's not worth an email. An interesting thing maybe worth
sharing is, if HEAD is broken (the only reason we would fail to create
"struct worktree" for main worktree), then "git worktree list" from
main worktree would fail too, because repo setup code fails to parse
HEAD as well and die(). That makes the "always show main worktree"
patch useless, since we won't get far enough to execute
get_worktrees() in the first place. However, you can still do "git
worktree list" from a linked worktree, gitdir setup code will not stop
you (how can it). And the patch is still needed.
-- 
Duy

^ permalink raw reply

* Re: [PATCH 0/3] Minor fixes on 'git worktree'
From: Duy Nguyen @ 2016-11-25 12:24 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List, Mike Rappazzo
In-Reply-To: <xmqqbmx6nnpg.fsf@gitster.mtv.corp.google.com>

On Wed, Nov 23, 2016 at 11:52 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:
>
>> This fixes two things:
>>
>>  - make sure the first item is always the main worktree even if we
>>    fail to retrieve some info
>>
>>  - keep 'worktree list' order stable (which in turn fixes the random
>>    failure on my 'worktree-move' series
>> Nguyễn Thái Ngọc Duy (3):
>>   worktree.c: zero new 'struct worktree' on allocation
>>   get_worktrees() must return main worktree as first item even on error
>>   worktree list: keep the list sorted
>>
>>  builtin/worktree.c | 26 ++++++++++++++++++++++----
>>  worktree.c         | 20 ++++----------------
>>  2 files changed, 26 insertions(+), 20 deletions(-)
>
> Any tests?

I discarded the idea of adding test for sorting because it relies on
filesystems. A passed test may just mean the filesystem happens to
return files in "good" order. But I guess a test wouldn't hurt.
Somewhere out there some user may still have a "bad" filesystem and
the test could help catch breakage then.

Adding the test for the failed parse_ref() is possible, I think. But
since that function is destined to die, as I promised to use
refs-provided api instead of rolling out a custom ref parser, and I'm
going to have another hard look at refs subsystem for the
gc-not-looking-at-worktree-refs problem, may I make another promise to
add tests after this function is gone? It should happen "soon".
-- 
Duy

^ permalink raw reply

* Re: [PATCH 3/3] worktree list: keep the list sorted
From: Duy Nguyen @ 2016-11-25 12:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List, Mike Rappazzo
In-Reply-To: <xmqqwpfum801.fsf@gitster.mtv.corp.google.com>

On Thu, Nov 24, 2016 at 12:16 AM, Junio C Hamano <gitster@pobox.com> wrote:
> More importantly, perhaps get_worktrees() should learn to take an
> optional pointer to int that returns how many items are in the list?

My first thought was "yeah I remember there are many counting loop
like this" then grepped and realized this is the only place. For now I
think it's ok to leave it as is. When the second place does the same,
we'll change get_worktrees()

> Alternatively, other existing callers of the function do not care
> about the order, so it may not be such a good idea to always sort
> the result, but it may be a good idea to teach it to take a boolean
> that signals that the list should be sorted in a "natural order",
> which is how "worktree list" would show them to the user?

OK. I'll make it a bit flag, not a boolean though, to avoid changing
all call sites next time.
-- 
Duy

^ permalink raw reply

* Re: [PATCH v2] merge-recursive.c: use string_list_sort instead of qsort
From: Duy Nguyen @ 2016-11-25 12:15 UTC (permalink / raw)
  To: Jeff King; +Cc: Git Mailing List, René Scharfe, Junio C Hamano
In-Reply-To: <20161124205242.ts4qhvfz2hvxez36@sigill.intra.peff.net>

On Fri, Nov 25, 2016 at 3:52 AM, Jeff King <peff@peff.net> wrote:
> On Thu, Nov 24, 2016 at 06:45:36PM +0700, Nguyễn Thái Ngọc Duy wrote:
>
>> This started out to as a hunt for remaining qsort() calls after rs/qsort
>> series because qsort() API is a bit easy to get wrong (*). However,
>> since we have string_list_sort(), it's conceptually a better way to sort
>> here.
>>
>> (*) In this particular case, it's even more confusing when you sort one
>> variable but you use the number of items and item size from an unrelated
>> variable (from a first glance)
>
> Makes sense, though I think I probably would have explained it in
> reverse order:
>
>   Merge-recursive sorts a string list using a raw qsort(), where it
>   feeds the "items" from one struct but the "nr" and size fields from
>   another struct. This isn't a bug because one list is a copy of the
>   other, but it's unnecessarily confusing (and also caused our recent
>   QSORT() cleanups via coccinelle to miss this call site).
>
>   Let's use string_list_sort() instead, which is more concise and harder
>   to get wrong. Note that we need to adjust our comparison function,
>   which gets fed only the strings now, not the string_list_items. That's
>   OK because we don't use the "util" field as part of our sort.
>
> Feel free to use or ignore my description as you see fit. :)

I delegate the decision to Junio. He can amend the commit if he
decides so. I suspect it's a good idea to do so.

>> -static int string_list_df_name_compare(const void *a, const void *b)
>> +static int string_list_df_name_compare(const char *one, const char *two)
>>  {
>> -     const struct string_list_item *one = a;
>> -     const struct string_list_item *two = b;
>> -     int onelen = strlen(one->string);
>> -     int twolen = strlen(two->string);
>> +     int onelen = strlen(one);
>> +     int twolen = strlen(two);
>
> I guess I haven't used string_list_sort() in a while, but I was
> surprised to find that it just feeds the strings to the comparator. That
> makes sense for using a raw strcmp() as the comparator, but I wonder if
> any callers would ever want to take the util field into account (e.g.,
> to break ties).
>
> We don't seem to care here, though (which can be verified by reading the
> code, but also because any mention of one->util would be a compilation
> error after your patch). So I guess we can punt on it until the day that
> some caller does need it.

Some callers do need it, or at least fmt-merge-msg.c:add_people_info()
does, maybe builtin/remote.c:show() and shortlog.c:shortlog_output()
too. But I'll stop here and get back to my worktree stuff.
-- 
Duy

^ permalink raw reply

* Re: [PATCH v3 1/2] difftool: add a skeleton for the upcoming builtin
From: Johannes Schindelin @ 2016-11-25 11:05 UTC (permalink / raw)
  To: Jeff King; +Cc: git, Junio C Hamano, David Aguilar, Dennis Kaarsemaker
In-Reply-To: <20161125031809.mueurvjijlnzy2s5@sigill.intra.peff.net>

Hi Peff,

On Thu, 24 Nov 2016, Jeff King wrote:

> On Thu, Nov 24, 2016 at 10:56:23PM +0100, Johannes Schindelin wrote:
> 
> > > I think it would probably be OK to ship with that caveat (people would
> > > probably use --global config, or "git -c" for a quick override), but if
> > > you really wanted to address it, you can do something like what
> > > pager.c:read_early_config() does.
> > 
> > The config setting is already overkill (and does even make something much
> > harder than before: running tests with the builtin difftool used to be as
> > simply as `touch use-builtin-difftool && make -C t t7800-difftool.sh, now
> > I have to edit t7800-difftool.sh to configure difftool.useBuiltin, and
> > without the repo-level config even that would not be working).
> > 
> > Imitating read_early_config() would be overkill deluxe.
> 
> I would have expected it to just be a build-time flag, like:
> 
>   make BUILTIN_DIFFTOOL=Yes test

That works for Git developers.

I want to let as many users as possible test the builtin difftool.
Hopefully a lot more users than there are Git developers.

Which means that I need a feature flag in production code, not a build
time flag.

> I'm happy with pretty much anything under the reasoning of "this does not
> matter much because it is going away soon".

Yeah, well, I am more happy with anything along the lines of David's
review, pointing out flaws in the current revision of the builtin difftool
before it bites users ;-)

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH v3 1/2] difftool: add a skeleton for the upcoming builtin
From: Jeff King @ 2016-11-25  3:18 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: git, Junio C Hamano, David Aguilar, Dennis Kaarsemaker
In-Reply-To: <alpine.DEB.2.20.1611242211450.117539@virtualbox>

On Thu, Nov 24, 2016 at 10:56:23PM +0100, Johannes Schindelin wrote:

> > I think it would probably be OK to ship with that caveat (people would
> > probably use --global config, or "git -c" for a quick override), but if
> > you really wanted to address it, you can do something like what
> > pager.c:read_early_config() does.
> 
> The config setting is already overkill (and does even make something much
> harder than before: running tests with the builtin difftool used to be as
> simply as `touch use-builtin-difftool && make -C t t7800-difftool.sh, now
> I have to edit t7800-difftool.sh to configure difftool.useBuiltin, and
> without the repo-level config even that would not be working).
> 
> Imitating read_early_config() would be overkill deluxe.

I would have expected it to just be a build-time flag, like:

  make BUILTIN_DIFFTOOL=Yes test

but I did not closely follow the rest of the conversation, so I am
probably just repeating bits that were already said. So probably ignore
me.

I'm happy with pretty much anything under the reasoning of "this does not
matter much because it is going away soon".

-Peff

^ permalink raw reply

* Re: [char-misc-next] mei: request async autosuspend at the end of enumeration
From: Jeff King @ 2016-11-25  3:14 UTC (permalink / raw)
  To: Winkler, Tomas
  Cc: Matthieu Moy, git@vger.kernel.org,
	Greg KH (gregkh@linuxfoundation.org), Usyskin, Alexander,
	linux-kernel@vger.kernel.org
In-Reply-To: <5B8DA87D05A7694D9FA63FD143655C1B54331476@hasmsx108.ger.corp.intel.com>

On Thu, Nov 24, 2016 at 10:37:14PM +0000, Winkler, Tomas wrote:

> > > > Cc: <stable@vger.kernel.org> # 4.4+
> > >
> > > Looks like git send-email is not able to parse this address correctly
> > > though this is suggested format by Documentation/stable_kernel_rules.txt.
> > > Create wrong address If git parsers is used : 'stable@vger.kernel.org#4.4+'
> > >
> > > Something like s/#.*$// is needed before parsing Cc:
> > 
> > This should be fixed by e3fdbcc8e (parse_mailboxes: accept extra text after
> > <...> address, 2016-10-13), which will be released next week as part of v2.11. As
> > a workaround, you can also install the Mail::Address perl module.  See [1] for
> > the gory details.
> 
> Thanks for update, I failed to understand from the thread though what
> decision was actually applied, I will look at the patch itself.  I've
> tried to install Mail::Address and it fixes the actual address, but it
> appends  the # 4.4+ suffix into the name  as also mentioned in the
> thread, which doesn't fit the stable rules doc.

The patch just brings parity to the Mail::Address behavior and git's
fallback parser, so that you don't end up with the broken
stable@vger.kernel.org#4.4+ address. Instead, that content goes into the
name part of the address.

It sounds like you want the "# 4.4+" to be dropped entirely in the
rfc822 header. It looks like send-email used to do that, but stopped in
b1c8a11c8 (send-email: allow multiple emails using --cc, --to and --bcc,
2015-06-30).

So perhaps there are further fixes required, but it's hard to know. The
input isn't a valid rfc822 header, so it's not entirely clear what the
output is supposed to be. I can buy either "drop it completely" or
"stick it in the name field of the cc header" as reasonable.

-Peff

^ permalink raw reply

* Git Gui bugs Debian Jessie Package: git (1:2.1.4-2.1+deb8u2)
From: Walt Feasel @ 2016-11-24 23:58 UTC (permalink / raw)
  To: git

These may be well know but I was not able to find a bug tracker so here it goes.

1) When selecting help, about git gui it crashes wth the error:
	
	error: git-gui died of signal 11

2) With the default installation there are two different default text types.
	
	Edit, Options, under Global (All Repositories) at the bottom for
	Main Font: DejaVu Sans-12pt
	Diff/Console Font: DejaVu Sans Mono-12pt.

	This causes a discrepence with text alignment. 
	When changed to the same it corrects this.

3) When the same text styles are selected (from above) text alignment still varies
   from what is shown in the text editor (nano for this example) and what is shown
   from using 'git add -p'. 'git add -p' will have the correct alignment but 'git gui'
   will have have lines shifted.

	This will produce varying patches dependant on which method is used.

I have spent alot of time playing with whitespace trying to get columns to align
and not having a viewable bug tracker listing has added to the this frustration.

If these issues have been corrected in a newer version than the Debian package ;)
please let me know and also if more info is requested.

Walt

^ permalink raw reply

* RE: [char-misc-next] mei: request async autosuspend at the end of enumeration
From: Winkler, Tomas @ 2016-11-24 22:37 UTC (permalink / raw)
  To: Jeff King
  Cc: Matthieu Moy, git@vger.kernel.org,
	Greg KH (gregkh@linuxfoundation.org), Usyskin, Alexander,
	linux-kernel@vger.kernel.org
In-Reply-To: <20161124204316.sqxjpc7uzbrzhvho@sigill.intra.peff.net>

> 
> On Thu, Nov 24, 2016 at 04:10:49PM +0000, Winkler, Tomas wrote:
> 
> > > Cc: <stable@vger.kernel.org> # 4.4+
> >
> > Looks like git send-email is not able to parse this address correctly
> > though this is suggested format by Documentation/stable_kernel_rules.txt.
> > Create wrong address If git parsers is used : 'stable@vger.kernel.org#4.4+'
> >
> > Something like s/#.*$// is needed before parsing Cc:
> 
> This should be fixed by e3fdbcc8e (parse_mailboxes: accept extra text after
> <...> address, 2016-10-13), which will be released next week as part of v2.11. As
> a workaround, you can also install the Mail::Address perl module.  See [1] for
> the gory details.

Thanks for update, I failed to understand from the thread though what decision was actually applied, I will look at the patch itself.
I've tried to install Mail::Address and it fixes the actual address, but it appends  the # 4.4+ suffix into the name  
as also mentioned in the thread, which doesn't fit the stable rules doc.

So far I've fixed the particular issue with the simple substitute above, till the real fix is released.

Maybe the stable kernel maintainers should also be pulled into the conversation.  

Thanks
Tomas 


^ permalink raw reply

* Re: [PATCH v3 1/2] difftool: add a skeleton for the upcoming builtin
From: Johannes Schindelin @ 2016-11-24 21:56 UTC (permalink / raw)
  To: Jeff King; +Cc: git, Junio C Hamano, David Aguilar, Dennis Kaarsemaker
In-Reply-To: <20161124210841.c4yi2nv57tjfejgj@sigill.intra.peff.net>

Hi Peff,

On Thu, 24 Nov 2016, Jeff King wrote:

> On Thu, Nov 24, 2016 at 09:55:07PM +0100, Johannes Schindelin wrote:
> 
> > +/*
> > + * NEEDSWORK: this function can go once the legacy-difftool Perl script is
> > + * retired.
> > + *
> > + * We intentionally avoid reading the config directly here, to avoid messing up
> > + * the GIT_* environment variables when we need to fall back to exec()ing the
> > + * Perl script.
> > + */
> > +static int use_builtin_difftool(void) {
> > +	struct child_process cp = CHILD_PROCESS_INIT;
> > +	struct strbuf out = STRBUF_INIT;
> > +	int ret;
> > +
> > +	argv_array_pushl(&cp.args,
> > +			 "config", "--bool", "difftool.usebuiltin", NULL);
> > +	cp.git_cmd = 1;
> > +	if (capture_command(&cp, &out, 6))
> > +		return 0;
> > +	strbuf_trim(&out);
> > +	ret = !strcmp("true", out.buf);
> > +	strbuf_release(&out);
> > +	return ret;
> > +}
> 
> FWIW, it should mostly Just Work to use the internal config functions
> these days, with the caveat that they will not read repo-level config if
> you haven't done repo setup yet.
> 
> I think it would probably be OK to ship with that caveat (people would
> probably use --global config, or "git -c" for a quick override), but if
> you really wanted to address it, you can do something like what
> pager.c:read_early_config() does.

The config setting is already overkill (and does even make something much
harder than before: running tests with the builtin difftool used to be as
simply as `touch use-builtin-difftool && make -C t t7800-difftool.sh, now
I have to edit t7800-difftool.sh to configure difftool.useBuiltin, and
without the repo-level config even that would not be working).

Imitating read_early_config() would be overkill deluxe.

> Of course, your method here is fine, too; I just know you are sensitive
> to forking extra processes.
> 
> Also, a minor nit: capture_command() might return data in "out" with a
> non-zero exit if the command both generates stdout and exits non-zero
> itself. I'm not sure that's possible with git-config, though, so it
> might not be worth worrying about.

As it is, I spent way too much time on a feature flag *that will go away
real soon*. And not only I spent too much time on it: everybody who even
bothered to think about it spent too much time on it. It is a temporary
feature flag. It will go away. If it is inefficient, or inelegant, it
won't matter in a month from now.

In other words, it was not really necessary to spend all of that time and
all of that brain power to first discuss the shortcomings of having the
presence of a file in exec path as a feature flag, then converting it into
a config setting, only to find out that this *causes* problems that were
not there before.

Frankly, that was not what I was hoping for. I was hoping to get a decent
review of the *difftool* functionality. David did a fine job to provide
that review. All that discussion about the temporary feature flag was
really a side track for me, and I hate to admit that I let myself get
sucked into it, and it cost me quite some time that I would have rather
spent on release engineering the preview based on v2.11.0-rc3 (including
the difftool with *any* type of working opt-in feature flag).

Maybe I will write more explicitly in the next cover letter what I intend
to do, and what parts of the patch series is intended to be throw-away
material (hence "good enough" is good enough, and discussions about it are
really wasting all of our time). Of course, I cannot dictate what other
people find interesting to comment on, but at least I will have a good
excuse to ignore suggestions that only distract from the work that is
really needed.

My only solace is that I did some substantially more intensive testing in
the wake of this discussion, thanks to the test suite breakages incurred
by switching the feature flag to a soon-to-be-abandoned config setting.
That makes me much more confident about the builtin difftool, which is all
I wanted in the first place.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH v3 1/2] difftool: add a skeleton for the upcoming builtin
From: Jeff King @ 2016-11-24 21:08 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: git, Junio C Hamano, David Aguilar, Dennis Kaarsemaker
In-Reply-To: <3a10fd72cf336743891d6bc9a003cfeb5c3f0063.1480019834.git.johannes.schindelin@gmx.de>

On Thu, Nov 24, 2016 at 09:55:07PM +0100, Johannes Schindelin wrote:

> +/*
> + * NEEDSWORK: this function can go once the legacy-difftool Perl script is
> + * retired.
> + *
> + * We intentionally avoid reading the config directly here, to avoid messing up
> + * the GIT_* environment variables when we need to fall back to exec()ing the
> + * Perl script.
> + */
> +static int use_builtin_difftool(void) {
> +	struct child_process cp = CHILD_PROCESS_INIT;
> +	struct strbuf out = STRBUF_INIT;
> +	int ret;
> +
> +	argv_array_pushl(&cp.args,
> +			 "config", "--bool", "difftool.usebuiltin", NULL);
> +	cp.git_cmd = 1;
> +	if (capture_command(&cp, &out, 6))
> +		return 0;
> +	strbuf_trim(&out);
> +	ret = !strcmp("true", out.buf);
> +	strbuf_release(&out);
> +	return ret;
> +}

FWIW, it should mostly Just Work to use the internal config functions
these days, with the caveat that they will not read repo-level config if
you haven't done repo setup yet.

I think it would probably be OK to ship with that caveat (people would
probably use --global config, or "git -c" for a quick override), but if
you really wanted to address it, you can do something like what
pager.c:read_early_config() does.

Of course, your method here is fine, too; I just know you are sensitive
to forking extra processes.

Also, a minor nit: capture_command() might return data in "out" with a
non-zero exit if the command both generates stdout and exits non-zero
itself. I'm not sure that's possible with git-config, though, so it
might not be worth worrying about.

-Peff

^ permalink raw reply

* [PATCH v3 2/2] difftool: implement the functionality in the builtin
From: Johannes Schindelin @ 2016-11-24 20:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, David Aguilar, Dennis Kaarsemaker
In-Reply-To: <cover.1480019834.git.johannes.schindelin@gmx.de>

This patch gives life to the skeleton added in the previous patch.

The motivation for converting the difftool is that Perl scripts are not at
all native on Windows, and that `git difftool` therefore is pretty slow on
that platform, when there is no good reason for it to be slow.

In addition, Perl does not really have access to Git's internals. That
means that any script will always have to jump through unnecessary
hoops.

The current version of the builtin difftool does not, however, make full
use of the internals but instead chooses to spawn a couple of Git
processes, still, to make for an easier conversion. There remains a lot
of room for improvement, left for a later date.

Note: to play it safe, the original difftool is still called unless the
config setting difftool.useBuiltin is set to true.

The reason: this new, experimental, builtin difftool will be shipped as
part of Git for Windows v2.11.0, to allow for easier large-scale
testing, but of course as an opt-in feature.

Sadly, the speedup is more noticable on Linux than on Windows: a quick
test shows that t7800-difftool.sh runs in (2.183s/0.052s/0.108s)
(real/user/sys) in a Linux VM, down from  (6.529s/3.112s/0.644s), while
on Windows, it is (36.064s/2.730s/7.194s), down from
(47.637s/2.407s/6.863s). The culprit is most likely the overhead
incurred from *still* having to shell out to mergetool-lib.sh and
difftool--helper.sh.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 builtin/difftool.c | 670 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 669 insertions(+), 1 deletion(-)

diff --git a/builtin/difftool.c b/builtin/difftool.c
index 53870bb..3480920 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -11,9 +11,608 @@
  *
  * Copyright (C) 2016 Johannes Schindelin
  */
+#include "cache.h"
 #include "builtin.h"
 #include "run-command.h"
 #include "exec_cmd.h"
+#include "parse-options.h"
+#include "argv-array.h"
+#include "strbuf.h"
+#include "lockfile.h"
+#include "dir.h"
+
+static char *diff_gui_tool;
+static int trust_exit_code;
+
+static const char *const builtin_difftool_usage[] = {
+	N_("git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]"),
+	NULL
+};
+
+static int difftool_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "diff.guitool")) {
+		diff_gui_tool = xstrdup(value);
+		return 0;
+	}
+
+	if (!strcmp(var, "difftool.trustexitcode")) {
+		trust_exit_code = git_config_bool(var, value);
+		return 0;
+	}
+
+	return git_default_config(var, value, cb);
+}
+
+static int print_tool_help(void)
+{
+	const char *argv[] = { "mergetool", "--tool-help=diff", NULL };
+	return run_command_v_opt(argv, RUN_GIT_CMD);
+}
+
+static int parse_index_info(char *p, int *mode1, int *mode2,
+			    struct object_id *oid1, struct object_id *oid2,
+			    char *status)
+{
+	if (*p != ':')
+		return error("expected ':', got '%c'", *p);
+	*mode1 = (int)strtol(p + 1, &p, 8);
+	if (*p != ' ')
+		return error("expected ' ', got '%c'", *p);
+	*mode2 = (int)strtol(p + 1, &p, 8);
+	if (*p != ' ')
+		return error("expected ' ', got '%c'", *p);
+	if (get_oid_hex(++p, oid1))
+		return error("expected object ID, got '%s'", p + 1);
+	p += GIT_SHA1_HEXSZ;
+	if (*p != ' ')
+		return error("expected ' ', got '%c'", *p);
+	if (get_oid_hex(++p, oid2))
+		return error("expected object ID, got '%s'", p + 1);
+	p += GIT_SHA1_HEXSZ;
+	if (*p != ' ')
+		return error("expected ' ', got '%c'", *p);
+	*status = *++p;
+	if (!status || p[1])
+		return error("unexpected trailer: '%s'", p);
+	return 0;
+}
+
+/*
+ * Remove any trailing slash from $workdir
+ * before starting to avoid double slashes in symlink targets.
+ */
+static void add_path(struct strbuf *buf, size_t base_len, const char *path)
+{
+	strbuf_setlen(buf, base_len);
+	if (buf->len && buf->buf[buf->len - 1] != '/')
+		strbuf_addch(buf, '/');
+	strbuf_addstr(buf, path);
+}
+
+/*
+ * Determine whether we can simply reuse the file in the worktree.
+ */
+static int use_wt_file(const char *workdir, const char *name,
+		       struct object_id *oid)
+{
+	struct strbuf buf = STRBUF_INIT;
+	struct stat st;
+	int use = 0;
+
+	strbuf_addstr(&buf, workdir);
+	add_path(&buf, buf.len, name);
+
+	if (!lstat(buf.buf, &st) && !S_ISLNK(st.st_mode)) {
+		struct object_id wt_oid;
+		int fd = open(buf.buf, O_RDONLY);
+
+		if (!index_fd(wt_oid.hash, fd, &st, OBJ_BLOB, name, 0)) {
+			if (is_null_oid(oid)) {
+				oidcpy(oid, &wt_oid);
+				use = 1;
+			} else if (!oidcmp(oid, &wt_oid))
+				use = 1;
+		}
+	}
+
+	strbuf_release(&buf);
+
+	return use;
+}
+
+struct working_tree_entry {
+	struct hashmap_entry entry;
+	char path[FLEX_ARRAY];
+};
+
+static int working_tree_entry_cmp(struct working_tree_entry *a,
+				  struct working_tree_entry *b, void *keydata)
+{
+	return strcmp(a->path, b->path);
+}
+
+/*
+ * The `left` and `right` entries hold paths for the symlinks hashmap,
+ * and a SHA-1 surrounded by brief text for submodules.
+ */
+struct pair_entry {
+	struct hashmap_entry entry;
+	char left[PATH_MAX], right[PATH_MAX];
+	const char path[FLEX_ARRAY];
+};
+
+static int pair_cmp(struct pair_entry *a, struct pair_entry *b, void *keydata)
+{
+	return strcmp(a->path, b->path);
+}
+
+static void add_left_or_right(struct hashmap *map, const char *path,
+			      const char *content, int is_right)
+{
+	struct pair_entry *e, *existing;
+
+	FLEX_ALLOC_STR(e, path, path);
+	hashmap_entry_init(e, strhash(path));
+	existing = hashmap_get(map, e, NULL);
+	if (existing) {
+		free(e);
+		e = existing;
+	} else {
+		e->left[0] = e->right[0] = '\0';
+		hashmap_add(map, e);
+	}
+	strcpy(is_right ? e->right : e->left, content);
+}
+
+struct path_entry {
+	struct hashmap_entry entry;
+	char path[FLEX_ARRAY];
+};
+
+int path_entry_cmp(struct path_entry *a, struct path_entry *b, void *key)
+{
+	return strcmp(a->path, key ? key : b->path);
+}
+
+static void changed_files(struct hashmap *result, const char *index_path,
+			  const char *workdir)
+{
+	struct child_process update_index = CHILD_PROCESS_INIT;
+	struct child_process diff_files = CHILD_PROCESS_INIT;
+	struct strbuf index_env = STRBUF_INIT, buf = STRBUF_INIT;
+	const char *git_dir = absolute_path(get_git_dir()), *env[] = {
+		NULL, NULL
+	};
+	FILE *fp;
+
+	strbuf_addf(&index_env, "GIT_INDEX_FILE=%s", index_path);
+	env[0] = index_env.buf;
+
+	argv_array_pushl(&update_index.args,
+			 "--git-dir", git_dir, "--work-tree", workdir,
+			 "update-index", "--really-refresh", "-q",
+			 "--unmerged", NULL);
+	update_index.no_stdin = 1;
+	update_index.no_stdout = 1;
+	update_index.no_stderr = 1;
+	update_index.git_cmd = 1;
+	update_index.use_shell = 0;
+	update_index.clean_on_exit = 1;
+	update_index.dir = workdir;
+	update_index.env = env;
+	/* Ignore any errors of update-index */
+	run_command(&update_index);
+
+	argv_array_pushl(&diff_files.args,
+			 "--git-dir", git_dir, "--work-tree", workdir,
+			 "diff-files", "--name-only", "-z", NULL);
+	diff_files.no_stdin = 1;
+	diff_files.git_cmd = 1;
+	diff_files.use_shell = 0;
+	diff_files.clean_on_exit = 1;
+	diff_files.out = -1;
+	diff_files.dir = workdir;
+	diff_files.env = env;
+	if (start_command(&diff_files))
+		die("could not obtain raw diff");
+	fp = xfdopen(diff_files.out, "r");
+	while (!strbuf_getline_nul(&buf, fp)) {
+		struct path_entry *entry;
+		FLEX_ALLOC_STR(entry, path, buf.buf);
+		hashmap_entry_init(entry, strhash(buf.buf));
+		hashmap_add(result, entry);
+	}
+	if (finish_command(&diff_files))
+		die("diff-files did not exit properly");
+	strbuf_release(&index_env);
+	strbuf_release(&buf);
+}
+
+static NORETURN void exit_cleanup(const char *tmpdir, int exit_code)
+{
+	struct strbuf buf = STRBUF_INIT;
+	strbuf_addstr(&buf, tmpdir);
+	remove_dir_recursively(&buf, 0);
+	if (exit_code)
+		warning(_("failed: %d"), exit_code);
+	exit(exit_code);
+}
+
+static int ensure_leading_directories(char *path)
+{
+	switch (safe_create_leading_directories(path)) {
+		case SCLD_OK:
+		case SCLD_EXISTS:
+			return 0;
+		default:
+			return error(_("could not create leading directories "
+				       "of '%s'"), path);
+	}
+}
+
+static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
+			int argc, const char **argv)
+{
+	char tmpdir[PATH_MAX];
+	struct strbuf info = STRBUF_INIT, lpath = STRBUF_INIT;
+	struct strbuf rpath = STRBUF_INIT, buf = STRBUF_INIT;
+	struct strbuf ldir = STRBUF_INIT, rdir = STRBUF_INIT;
+	struct strbuf wtdir = STRBUF_INIT;
+	size_t ldir_len, rdir_len, wtdir_len;
+	struct cache_entry *ce = xcalloc(1, sizeof(ce) + PATH_MAX + 1);
+	const char *workdir, *tmp;
+	int ret = 0, i;
+	FILE *fp;
+	struct hashmap working_tree_dups, submodules, symlinks2;
+	struct hashmap_iter iter;
+	struct pair_entry *entry;
+	enum object_type type;
+	unsigned long size;
+	struct index_state wtindex;
+	struct checkout lstate, rstate;
+	int rc, flags = RUN_GIT_CMD, err = 0;
+	struct child_process child = CHILD_PROCESS_INIT;
+	const char *helper_argv[] = { "difftool--helper", NULL, NULL, NULL };
+	struct hashmap wt_modified, tmp_modified;
+	int indices_loaded = 0;
+
+	workdir = get_git_work_tree();
+
+	/* Setup temp directories */
+	tmp = getenv("TMPDIR");
+	xsnprintf(tmpdir, sizeof(tmpdir), "%s/git-difftool.XXXXXX", tmp ? tmp : "/tmp");
+	if (!mkdtemp(tmpdir))
+		return error("could not create '%s'", tmpdir);
+	strbuf_addf(&ldir, "%s/left/", tmpdir);
+	strbuf_addf(&rdir, "%s/right/", tmpdir);
+	strbuf_addstr(&wtdir, workdir);
+	if (!wtdir.len || !is_dir_sep(wtdir.buf[wtdir.len - 1]))
+		strbuf_addch(&wtdir, '/');
+	mkdir(ldir.buf, 0700);
+	mkdir(rdir.buf, 0700);
+
+	memset(&wtindex, 0, sizeof(wtindex));
+
+	memset(&lstate, 0, sizeof(lstate));
+	lstate.base_dir = ldir.buf;
+	lstate.base_dir_len = ldir.len;
+	lstate.force = 1;
+	memset(&rstate, 0, sizeof(rstate));
+	rstate.base_dir = rdir.buf;
+	rstate.base_dir_len = rdir.len;
+	rstate.force = 1;
+
+	ldir_len = ldir.len;
+	rdir_len = rdir.len;
+	wtdir_len = wtdir.len;
+
+	hashmap_init(&working_tree_dups,
+		     (hashmap_cmp_fn)working_tree_entry_cmp, 0);
+	hashmap_init(&submodules, (hashmap_cmp_fn)pair_cmp, 0);
+	hashmap_init(&symlinks2, (hashmap_cmp_fn)pair_cmp, 0);
+
+	child.no_stdin = 1;
+	child.git_cmd = 1;
+	child.use_shell = 0;
+	child.clean_on_exit = 1;
+	child.dir = prefix;
+	child.out = -1;
+	argv_array_pushl(&child.args, "diff", "--raw", "--no-abbrev", "-z",
+			 NULL);
+	for (i = 0; i < argc; i++)
+		argv_array_push(&child.args, argv[i]);
+	if (start_command(&child))
+		die("could not obtain raw diff");
+	fp = xfdopen(child.out, "r");
+
+	/* Build index info for left and right sides of the diff */
+	i = 0;
+	while (!strbuf_getline_nul(&info, fp)) {
+		int lmode, rmode;
+		struct object_id loid, roid;
+		char status;
+		const char *src_path, *dst_path;
+		size_t src_path_len, dst_path_len;
+
+		if (starts_with(info.buf, "::"))
+			die(N_("combined diff formats('-c' and '--cc') are "
+			       "not supported in\n"
+			       "directory diff mode('-d' and '--dir-diff')."));
+
+		if (parse_index_info(info.buf, &lmode, &rmode, &loid, &roid,
+				     &status))
+			break;
+		if (strbuf_getline_nul(&lpath, fp))
+			break;
+		src_path = lpath.buf;
+		src_path_len = lpath.len;
+
+		i++;
+		if (status != 'C' && status != 'R') {
+			dst_path = src_path;
+			dst_path_len = src_path_len;
+		} else {
+			if (strbuf_getline_nul(&rpath, fp))
+				break;
+			dst_path = rpath.buf;
+			dst_path_len = rpath.len;
+		}
+
+		if (S_ISGITLINK(lmode) || S_ISGITLINK(rmode)) {
+			strbuf_reset(&buf);
+			strbuf_addf(&buf, "Subproject commit %s",
+				    oid_to_hex(&loid));
+			add_left_or_right(&submodules, src_path, buf.buf, 0);
+			strbuf_reset(&buf);
+			strbuf_addf(&buf, "Subproject commit %s",
+				    oid_to_hex(&roid));
+			if (!oidcmp(&loid, &roid))
+				strbuf_addstr(&buf, "-dirty");
+			add_left_or_right(&submodules, dst_path, buf.buf, 1);
+			continue;
+		}
+
+		if (S_ISLNK(lmode)) {
+			char *content = read_sha1_file(loid.hash, &type, &size);
+			add_left_or_right(&symlinks2, src_path, content, 0);
+			free(content);
+		}
+
+		if (S_ISLNK(rmode)) {
+			char *content = read_sha1_file(roid.hash, &type, &size);
+			add_left_or_right(&symlinks2, dst_path, content, 1);
+			free(content);
+		}
+
+		if (lmode && status != 'C') {
+			ce->ce_mode = lmode;
+			oidcpy(&ce->oid, &loid);
+			strcpy(ce->name, src_path);
+			ce->ce_namelen = src_path_len;
+			if (checkout_entry(ce, &lstate, NULL))
+				return error("could not write '%s'", src_path);
+		}
+
+		if (rmode) {
+			struct working_tree_entry *entry;
+
+			/* Avoid duplicate working_tree entries */
+			FLEX_ALLOC_STR(entry, path, dst_path);
+			hashmap_entry_init(entry, strhash(dst_path));
+			if (hashmap_get(&working_tree_dups, entry, NULL)) {
+				free(entry);
+				continue;
+			}
+			hashmap_add(&working_tree_dups, entry);
+
+			if (!use_wt_file(workdir, dst_path, &roid)) {
+				ce->ce_mode = rmode;
+				oidcpy(&ce->oid, &roid);
+				strcpy(ce->name, dst_path);
+				ce->ce_namelen = dst_path_len;
+				if (checkout_entry(ce, &rstate, NULL))
+					return error("could not write '%s'",
+						     dst_path);
+			} else if (!is_null_oid(&roid)) {
+				/*
+				 * Changes in the working tree need special
+				 * treatment since they are not part of the
+				 * index.
+				 */
+				struct cache_entry *ce2 =
+					make_cache_entry(rmode, roid.hash,
+							 dst_path, 0, 0);
+				ce_mode_from_stat(ce2, rmode);
+
+				add_index_entry(&wtindex, ce2,
+						ADD_CACHE_JUST_APPEND);
+
+				add_path(&wtdir, wtdir_len, dst_path);
+				add_path(&rdir, rdir_len, dst_path);
+				if (ensure_leading_directories(rdir.buf))
+					return error("could not create "
+						     "directory for '%s'",
+						     dst_path);
+				if (symlinks) {
+					if (symlink(wtdir.buf, rdir.buf)) {
+						ret = error_errno("could not symlink '%s' to '%s'", wtdir.buf, rdir.buf);
+						goto finish;
+					}
+				} else {
+					struct stat st;
+					if (stat(wtdir.buf, &st))
+						st.st_mode = 0644;
+					if (copy_file(rdir.buf, wtdir.buf,
+						      st.st_mode)) {
+						ret = error("could not copy '%s' to '%s'", wtdir.buf, rdir.buf);
+						goto finish;
+					}
+				}
+			}
+		}
+	}
+
+	if (finish_command(&child)) {
+		ret = error("error occurred running diff --raw");
+		goto finish;
+	}
+
+	if (!i)
+		return 0;
+
+	/*
+	 * Changes to submodules require special treatment.This loop writes a
+	 * temporary file to both the left and right directories to show the
+	 * change in the recorded SHA1 for the submodule.
+	 */
+	hashmap_iter_init(&submodules, &iter);
+	while ((entry = hashmap_iter_next(&iter))) {
+		if (*entry->left) {
+			add_path(&ldir, ldir_len, entry->path);
+			ensure_leading_directories(ldir.buf);
+			write_file(ldir.buf, "%s", entry->left);
+		}
+		if (*entry->right) {
+			add_path(&rdir, rdir_len, entry->path);
+			ensure_leading_directories(rdir.buf);
+			write_file(rdir.buf, "%s", entry->right);
+		}
+	}
+
+	/*
+	 * Symbolic links require special treatment.The standard "git diff"
+	 * shows only the link itself, not the contents of the link target.
+	 * This loop replicates that behavior.
+	 */
+	hashmap_iter_init(&symlinks2, &iter);
+	while ((entry = hashmap_iter_next(&iter))) {
+		if (*entry->left) {
+			add_path(&ldir, ldir_len, entry->path);
+			ensure_leading_directories(ldir.buf);
+			write_file(ldir.buf, "%s", entry->left);
+		}
+		if (*entry->right) {
+			add_path(&rdir, rdir_len, entry->path);
+			ensure_leading_directories(rdir.buf);
+			write_file(rdir.buf, "%s", entry->right);
+		}
+	}
+
+	strbuf_release(&buf);
+
+	strbuf_setlen(&ldir, ldir_len);
+	helper_argv[1] = ldir.buf;
+	strbuf_setlen(&rdir, rdir_len);
+	helper_argv[2] = rdir.buf;
+
+	if (extcmd) {
+		helper_argv[0] = extcmd;
+		flags = 0;
+	} else
+		setenv("GIT_DIFFTOOL_DIRDIFF", "true", 1);
+	rc = run_command_v_opt(helper_argv, flags);
+
+	/*
+	 * If the diff includes working copy files and those
+	 * files were modified during the diff, then the changes
+	 * should be copied back to the working tree.
+	 * Do not copy back files when symlinks are used and the
+	 * external tool did not replace the original link with a file.
+	 *
+	 * These hashes are loaded lazily since they aren't needed
+	 * in the common case of --symlinks and the difftool updating
+	 * files through the symlink.
+	 */
+	hashmap_init(&wt_modified, (hashmap_cmp_fn)path_entry_cmp,
+		     wtindex.cache_nr);
+	hashmap_init(&tmp_modified, (hashmap_cmp_fn)path_entry_cmp,
+		     wtindex.cache_nr);
+
+	for (i = 0; i < wtindex.cache_nr; i++) {
+		struct hashmap_entry dummy;
+		const char *name = wtindex.cache[i]->name;
+		struct stat st;
+
+		add_path(&rdir, rdir_len, name);
+		if (lstat(rdir.buf, &st))
+			continue;
+
+		if ((symlinks && S_ISLNK(st.st_mode)) || !S_ISREG(st.st_mode))
+			continue;
+
+		if (!indices_loaded) {
+			static struct lock_file lock;
+			strbuf_reset(&buf);
+			strbuf_addf(&buf, "%s/wtindex", tmpdir);
+			if (hold_lock_file_for_update(&lock, buf.buf, 0) < 0 ||
+			    write_locked_index(&wtindex, &lock, COMMIT_LOCK)) {
+				ret = error("could not write %s", buf.buf);
+				rollback_lock_file(&lock);
+				goto finish;
+			}
+			changed_files(&wt_modified, buf.buf, workdir);
+			strbuf_setlen(&rdir, rdir_len);
+			changed_files(&tmp_modified, buf.buf, rdir.buf);
+			add_path(&rdir, rdir_len, name);
+			indices_loaded = 1;
+		}
+
+		hashmap_entry_init(&dummy, strhash(name));
+		if (hashmap_get(&tmp_modified, &dummy, name)) {
+			add_path(&wtdir, wtdir_len, name);
+			if (hashmap_get(&wt_modified, &dummy, name)) {
+				warning(_("both files modified: '%s' and '%s'."),
+					wtdir.buf, rdir.buf);
+				warning(_("working tree file has been left."));
+				warning("");
+				err = 1;
+			} else if (unlink(wtdir.buf) ||
+				   copy_file(wtdir.buf, rdir.buf, st.st_mode))
+				warning_errno(_("could not copy '%s' to '%s'"),
+					      rdir.buf, wtdir.buf);
+		}
+	}
+
+	if (err) {
+		warning(_("temporary files exist in '%s'."), tmpdir);
+		warning(_("you may want to cleanup or recover these."));
+		exit(1);
+	} else
+		exit_cleanup(tmpdir, rc);
+
+finish:
+	free(ce);
+	strbuf_release(&ldir);
+	strbuf_release(&rdir);
+	strbuf_release(&wtdir);
+	strbuf_release(&buf);
+
+	return ret;
+}
+
+static int run_file_diff(int prompt, const char *prefix,
+			 int argc, const char **argv)
+{
+	struct argv_array args = ARGV_ARRAY_INIT;
+	const char *env[] = {
+		"GIT_PAGER=", "GIT_EXTERNAL_DIFF=git-difftool--helper", NULL,
+		NULL
+	};
+	int ret = 0, i;
+
+	if (prompt > 0)
+		env[2] = "GIT_DIFFTOOL_PROMPT=true";
+	else if (!prompt)
+		env[2] = "GIT_DIFFTOOL_NO_PROMPT=true";
+
+
+	argv_array_push(&args, "diff");
+	for (i = 0; i < argc; i++)
+		argv_array_push(&args, argv[i]);
+	ret = run_command_v_opt_cd_env(args.argv, RUN_GIT_CMD, prefix, env);
+	exit(ret);
+}
 
 /*
  * NEEDSWORK: this function can go once the legacy-difftool Perl script is
@@ -41,6 +640,35 @@ static int use_builtin_difftool(void) {
 
 int cmd_difftool(int argc, const char **argv, const char *prefix)
 {
+	int use_gui_tool = 0, dir_diff = 0, prompt = -1, symlinks = 0,
+	    tool_help = 0;
+	static char *difftool_cmd = NULL, *extcmd = NULL;
+	struct option builtin_difftool_options[] = {
+		OPT_BOOL('g', "gui", &use_gui_tool,
+			 N_("use `diff.guitool` instead of `diff.tool`")),
+		OPT_BOOL('d', "dir-diff", &dir_diff,
+			 N_("perform a full-directory diff")),
+		{ OPTION_SET_INT, 'y', "no-prompt", &prompt, NULL,
+			N_("do not prompt before launching a diff tool"),
+			PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 0},
+		{ OPTION_SET_INT, 0, "prompt", &prompt, NULL, NULL,
+			PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_HIDDEN,
+			NULL, 1 },
+		OPT_BOOL(0, "symlinks", &symlinks,
+			 N_("use symlinks in dir-diff mode")),
+		OPT_STRING('t', "tool", &difftool_cmd, N_("<tool>"),
+			   N_("use the specified diff tool")),
+		OPT_BOOL(0, "tool-help", &tool_help,
+			 N_("print a list of diff tools that may be used with "
+			    "`--tool`")),
+		OPT_BOOL(0, "trust-exit-code", &trust_exit_code,
+			 N_("make 'git-difftool' exit when an invoked diff "
+			    "tool returns a non - zero exit code")),
+		OPT_STRING('x', "extcmd", &extcmd, N_("<command>"),
+			   N_("specify a custom command for viewing diffs")),
+		OPT_END()
+	};
+
 	/*
 	 * NEEDSWORK: Once the builtin difftool has been tested enough
 	 * and git-legacy-difftool.perl is retired to contrib/, this preamble
@@ -58,6 +686,46 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
 	prefix = setup_git_directory();
 	trace_repo_setup(prefix);
 	setup_work_tree();
+	/* NEEDSWORK: once we no longer spawn anything, remove this */
+	setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
+	setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
+
+	git_config(difftool_config, NULL);
+	symlinks = has_symlinks;
+
+	argc = parse_options(argc, argv, prefix, builtin_difftool_options,
+			     builtin_difftool_usage, PARSE_OPT_KEEP_UNKNOWN |
+			     PARSE_OPT_KEEP_DASHDASH);
 
-	die("TODO");
+	if (tool_help)
+		return print_tool_help();
+
+	if (use_gui_tool && diff_gui_tool && *diff_gui_tool)
+		setenv("GIT_DIFF_TOOL", diff_gui_tool, 1);
+	else if (difftool_cmd) {
+		if (*difftool_cmd)
+			setenv("GIT_DIFF_TOOL", difftool_cmd, 1);
+		else
+			die(_("no <tool> given for --tool=<tool>"));
+	}
+
+	if (extcmd) {
+		if (*extcmd)
+			setenv("GIT_DIFFTOOL_EXTCMD", extcmd, 1);
+		else
+			die(_("no <cmd> given for --extcmd=<cmd>"));
+	}
+
+	setenv("GIT_DIFFTOOL_TRUST_EXIT_CODE",
+	       trust_exit_code ? "true" : "false", 1);
+
+	/*
+	 * In directory diff mode, 'git-difftool--helper' is called once
+	 * to compare the a / b directories. In file diff mode, 'git diff'
+	 * will invoke a separate instance of 'git-difftool--helper' for
+	 * each file that changed.
+	 */
+	if (dir_diff)
+		return run_dir_diff(extcmd, symlinks, prefix, argc, argv);
+	return run_file_diff(prompt, prefix, argc, argv);
 }
-- 
2.10.1.583.g721a9e0

^ permalink raw reply related

* [PATCH v3 1/2] difftool: add a skeleton for the upcoming builtin
From: Johannes Schindelin @ 2016-11-24 20:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, David Aguilar, Dennis Kaarsemaker
In-Reply-To: <cover.1480019834.git.johannes.schindelin@gmx.de>

This adds a builtin difftool that still falls back to the legacy Perl
version, which has been renamed to `legacy-difftool`.

The idea is that the new, experimental, builtin difftool immediately hands
off to the legacy difftool for now, unless the config variable
difftool.useBuiltin is set to true.

This feature flag will be used in the upcoming Git for Windows v2.11.0
release, to allow early testers to opt-in to use the builtin difftool and
flesh out any bugs.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 .gitignore                                    |  1 +
 Makefile                                      |  3 +-
 builtin.h                                     |  1 +
 builtin/difftool.c                            | 63 +++++++++++++++++++++++++++
 git-difftool.perl => git-legacy-difftool.perl |  0
 git.c                                         |  6 +++
 t/t7800-difftool.sh                           |  2 +
 7 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 builtin/difftool.c
 rename git-difftool.perl => git-legacy-difftool.perl (100%)

diff --git a/.gitignore b/.gitignore
index 05cb58a..f96e50e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -76,6 +76,7 @@
 /git-init-db
 /git-interpret-trailers
 /git-instaweb
+/git-legacy-difftool
 /git-log
 /git-ls-files
 /git-ls-remote
diff --git a/Makefile b/Makefile
index f53fcc9..7863bc2 100644
--- a/Makefile
+++ b/Makefile
@@ -527,7 +527,7 @@ SCRIPT_LIB += git-sh-setup
 SCRIPT_LIB += git-sh-i18n
 
 SCRIPT_PERL += git-add--interactive.perl
-SCRIPT_PERL += git-difftool.perl
+SCRIPT_PERL += git-legacy-difftool.perl
 SCRIPT_PERL += git-archimport.perl
 SCRIPT_PERL += git-cvsexportcommit.perl
 SCRIPT_PERL += git-cvsimport.perl
@@ -888,6 +888,7 @@ BUILTIN_OBJS += builtin/diff-files.o
 BUILTIN_OBJS += builtin/diff-index.o
 BUILTIN_OBJS += builtin/diff-tree.o
 BUILTIN_OBJS += builtin/diff.o
+BUILTIN_OBJS += builtin/difftool.o
 BUILTIN_OBJS += builtin/fast-export.o
 BUILTIN_OBJS += builtin/fetch-pack.o
 BUILTIN_OBJS += builtin/fetch.o
diff --git a/builtin.h b/builtin.h
index b9122bc..67f8051 100644
--- a/builtin.h
+++ b/builtin.h
@@ -60,6 +60,7 @@ extern int cmd_diff_files(int argc, const char **argv, const char *prefix);
 extern int cmd_diff_index(int argc, const char **argv, const char *prefix);
 extern int cmd_diff(int argc, const char **argv, const char *prefix);
 extern int cmd_diff_tree(int argc, const char **argv, const char *prefix);
+extern int cmd_difftool(int argc, const char **argv, const char *prefix);
 extern int cmd_fast_export(int argc, const char **argv, const char *prefix);
 extern int cmd_fetch(int argc, const char **argv, const char *prefix);
 extern int cmd_fetch_pack(int argc, const char **argv, const char *prefix);
diff --git a/builtin/difftool.c b/builtin/difftool.c
new file mode 100644
index 0000000..53870bb
--- /dev/null
+++ b/builtin/difftool.c
@@ -0,0 +1,63 @@
+/*
+ * "git difftool" builtin command
+ *
+ * This is a wrapper around the GIT_EXTERNAL_DIFF-compatible
+ * git-difftool--helper script.
+ *
+ * This script exports GIT_EXTERNAL_DIFF and GIT_PAGER for use by git.
+ * The GIT_DIFF* variables are exported for use by git-difftool--helper.
+ *
+ * Any arguments that are unknown to this script are forwarded to 'git diff'.
+ *
+ * Copyright (C) 2016 Johannes Schindelin
+ */
+#include "builtin.h"
+#include "run-command.h"
+#include "exec_cmd.h"
+
+/*
+ * NEEDSWORK: this function can go once the legacy-difftool Perl script is
+ * retired.
+ *
+ * We intentionally avoid reading the config directly here, to avoid messing up
+ * the GIT_* environment variables when we need to fall back to exec()ing the
+ * Perl script.
+ */
+static int use_builtin_difftool(void) {
+	struct child_process cp = CHILD_PROCESS_INIT;
+	struct strbuf out = STRBUF_INIT;
+	int ret;
+
+	argv_array_pushl(&cp.args,
+			 "config", "--bool", "difftool.usebuiltin", NULL);
+	cp.git_cmd = 1;
+	if (capture_command(&cp, &out, 6))
+		return 0;
+	strbuf_trim(&out);
+	ret = !strcmp("true", out.buf);
+	strbuf_release(&out);
+	return ret;
+}
+
+int cmd_difftool(int argc, const char **argv, const char *prefix)
+{
+	/*
+	 * NEEDSWORK: Once the builtin difftool has been tested enough
+	 * and git-legacy-difftool.perl is retired to contrib/, this preamble
+	 * can be removed.
+	 */
+	if (!use_builtin_difftool()) {
+		const char *path = mkpath("%s/git-legacy-difftool",
+					  git_exec_path());
+
+		if (sane_execvp(path, (char **)argv) < 0)
+			die_errno("could not exec %s", path);
+
+		return 0;
+	}
+	prefix = setup_git_directory();
+	trace_repo_setup(prefix);
+	setup_work_tree();
+
+	die("TODO");
+}
diff --git a/git-difftool.perl b/git-legacy-difftool.perl
similarity index 100%
rename from git-difftool.perl
rename to git-legacy-difftool.perl
diff --git a/git.c b/git.c
index e8b2baf..a8e6a15 100644
--- a/git.c
+++ b/git.c
@@ -424,6 +424,12 @@ static struct cmd_struct commands[] = {
 	{ "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },
 	{ "diff-index", cmd_diff_index, RUN_SETUP },
 	{ "diff-tree", cmd_diff_tree, RUN_SETUP },
+	/*
+	 * NEEDSWORK: Once the redirection to git-legacy-difftool.perl in
+	 * builtin/difftool.c has been removed, this entry should be changed to
+	 * RUN_SETUP | NEED_WORK_TREE
+	 */
+	{ "difftool", cmd_difftool },
 	{ "fast-export", cmd_fast_export, RUN_SETUP },
 	{ "fetch", cmd_fetch, RUN_SETUP },
 	{ "fetch-pack", cmd_fetch_pack, RUN_SETUP },
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 70a2de4..b6a6c30 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -23,6 +23,8 @@ prompt_given ()
 	test "$prompt" = "Launch 'test-tool' [Y/n]? branch"
 }
 
+# NEEDSWORK: lose all the PERL prereqs once legacy-difftool is retired.
+
 # Create a file on master and change it on branch
 test_expect_success PERL 'setup' '
 	echo master >file &&
-- 
2.10.1.583.g721a9e0



^ permalink raw reply related

* [PATCH v3 0/2] Show Git Mailing List: a builtin difftool
From: Johannes Schindelin @ 2016-11-24 20:55 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, David Aguilar, Dennis Kaarsemaker
In-Reply-To: <cover.1479938494.git.johannes.schindelin@gmx.de>

I have been working on the builtin difftool for almost two weeks,
for two reasons:

1. Perl is really not native on Windows. Not only is there a performance
   penalty to be paid just for running Perl scripts, we also have to deal
   with the fact that users may have different Perl installations, with
   different options, and some other Perl installation may decide to set
   PERL5LIB globally, wreaking havoc with Git for Windows' Perl (which we
   have to use because almost all other Perl distributions lack the
   Subversion bindings we need for `git svn`).

2. Perl makes for a rather large reason that Git for Windows' installer
   weighs in with >30MB. While one Perl script less does not relieve us
   of that burden, it is one step in the right direction.

This patch serves two purposes: to ask for reviews, and to show what I
plan to release as part of Git for Windows v2.11.0 (which is due this
coming Wednesday, if Git v2.11.0 is released on Tuesday, as planned).

Changes since v2:

- adjusted the config setting's name according to Junio's concerns

- fixed launching difftool in a subdirectory

- fixed dir-diff mode when there are no changes (it did not exit early
  but tried to diff two empty directories)


Johannes Schindelin (2):
  difftool: add a skeleton for the upcoming builtin
  difftool: implement the functionality in the builtin

 .gitignore                                    |   1 +
 Makefile                                      |   3 +-
 builtin.h                                     |   1 +
 builtin/difftool.c                            | 731 ++++++++++++++++++++++++++
 git-difftool.perl => git-legacy-difftool.perl |   0
 git.c                                         |   6 +
 t/t7800-difftool.sh                           |   2 +
 7 files changed, 743 insertions(+), 1 deletion(-)
 create mode 100644 builtin/difftool.c
 rename git-difftool.perl => git-legacy-difftool.perl (100%)


base-commit: e2b2d6a172b76d44cb7b1ddb12ea5bfac9613a44
Published-As: https://github.com/dscho/git/releases/tag/builtin-difftool-v3
Fetch-It-Via: git fetch https://github.com/dscho/git builtin-difftool-v3

Interdiff vs v2:

 diff --git a/builtin/difftool.c b/builtin/difftool.c
 index f845879..3480920 100644
 --- a/builtin/difftool.c
 +++ b/builtin/difftool.c
 @@ -13,17 +13,16 @@
   */
  #include "cache.h"
  #include "builtin.h"
 -#include "parse-options.h"
  #include "run-command.h"
 +#include "exec_cmd.h"
 +#include "parse-options.h"
  #include "argv-array.h"
  #include "strbuf.h"
  #include "lockfile.h"
  #include "dir.h"
 -#include "exec_cmd.h"
  
  static char *diff_gui_tool;
  static int trust_exit_code;
 -static int use_builtin_difftool;
  
  static const char *const builtin_difftool_usage[] = {
  	N_("git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]"),
 @@ -42,11 +41,6 @@ static int difftool_config(const char *var, const char *value, void *cb)
  		return 0;
  	}
  
 -	if (!strcmp(var, "core.usebuiltindifftool")) {
 -		use_builtin_difftool = git_config_bool(var, value);
 -		return 0;
 -	}
 -
  	return git_default_config(var, value, cb);
  }
  
 @@ -257,7 +251,7 @@ static int ensure_leading_directories(char *path)
  	}
  }
  
 -static int run_dir_diff(const char *extcmd, int symlinks,
 +static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
  			int argc, const char **argv)
  {
  	char tmpdir[PATH_MAX];
 @@ -283,7 +277,6 @@ static int run_dir_diff(const char *extcmd, int symlinks,
  	struct hashmap wt_modified, tmp_modified;
  	int indices_loaded = 0;
  
 -	setup_work_tree();
  	workdir = get_git_work_tree();
  
  	/* Setup temp directories */
 @@ -323,6 +316,7 @@ static int run_dir_diff(const char *extcmd, int symlinks,
  	child.git_cmd = 1;
  	child.use_shell = 0;
  	child.clean_on_exit = 1;
 +	child.dir = prefix;
  	child.out = -1;
  	argv_array_pushl(&child.args, "diff", "--raw", "--no-abbrev", "-z",
  			 NULL);
 @@ -333,6 +327,7 @@ static int run_dir_diff(const char *extcmd, int symlinks,
  	fp = xfdopen(child.out, "r");
  
  	/* Build index info for left and right sides of the diff */
 +	i = 0;
  	while (!strbuf_getline_nul(&info, fp)) {
  		int lmode, rmode;
  		struct object_id loid, roid;
 @@ -353,6 +348,7 @@ static int run_dir_diff(const char *extcmd, int symlinks,
  		src_path = lpath.buf;
  		src_path_len = lpath.len;
  
 +		i++;
  		if (status != 'C' && status != 'R') {
  			dst_path = src_path;
  			dst_path_len = src_path_len;
 @@ -456,11 +452,15 @@ static int run_dir_diff(const char *extcmd, int symlinks,
  			}
  		}
  	}
 +
  	if (finish_command(&child)) {
  		ret = error("error occurred running diff --raw");
  		goto finish;
  	}
  
 +	if (!i)
 +		return 0;
 +
  	/*
  	 * Changes to submodules require special treatment.This loop writes a
  	 * temporary file to both the left and right directories to show the
 @@ -591,7 +591,8 @@ static int run_dir_diff(const char *extcmd, int symlinks,
  	return ret;
  }
  
 -static int run_file_diff(int prompt, int argc, const char **argv)
 +static int run_file_diff(int prompt, const char *prefix,
 +			 int argc, const char **argv)
  {
  	struct argv_array args = ARGV_ARRAY_INIT;
  	const char *env[] = {
 @@ -605,14 +606,39 @@ static int run_file_diff(int prompt, int argc, const char **argv)
  	else if (!prompt)
  		env[2] = "GIT_DIFFTOOL_NO_PROMPT=true";
  
 +
  	argv_array_push(&args, "diff");
  	for (i = 0; i < argc; i++)
  		argv_array_push(&args, argv[i]);
 -	ret = run_command_v_opt_cd_env(args.argv, RUN_GIT_CMD, NULL, env);
 +	ret = run_command_v_opt_cd_env(args.argv, RUN_GIT_CMD, prefix, env);
  	exit(ret);
  }
  
 -int cmd_difftool(int argc, const char ** argv, const char * prefix)
 +/*
 + * NEEDSWORK: this function can go once the legacy-difftool Perl script is
 + * retired.
 + *
 + * We intentionally avoid reading the config directly here, to avoid messing up
 + * the GIT_* environment variables when we need to fall back to exec()ing the
 + * Perl script.
 + */
 +static int use_builtin_difftool(void) {
 +	struct child_process cp = CHILD_PROCESS_INIT;
 +	struct strbuf out = STRBUF_INIT;
 +	int ret;
 +
 +	argv_array_pushl(&cp.args,
 +			 "config", "--bool", "difftool.usebuiltin", NULL);
 +	cp.git_cmd = 1;
 +	if (capture_command(&cp, &out, 6))
 +		return 0;
 +	strbuf_trim(&out);
 +	ret = !strcmp("true", out.buf);
 +	strbuf_release(&out);
 +	return ret;
 +}
 +
 +int cmd_difftool(int argc, const char **argv, const char *prefix)
  {
  	int use_gui_tool = 0, dir_diff = 0, prompt = -1, symlinks = 0,
  	    tool_help = 0;
 @@ -643,16 +669,29 @@ int cmd_difftool(int argc, const char ** argv, const char * prefix)
  		OPT_END()
  	};
  
 -	git_config(difftool_config, NULL);
 -	symlinks = has_symlinks;
 -	if (!use_builtin_difftool) {
 -		const char *path = mkpath("%s/git-legacy-difftool", git_exec_path());
 +	/*
 +	 * NEEDSWORK: Once the builtin difftool has been tested enough
 +	 * and git-legacy-difftool.perl is retired to contrib/, this preamble
 +	 * can be removed.
 +	 */
 +	if (!use_builtin_difftool()) {
 +		const char *path = mkpath("%s/git-legacy-difftool",
 +					  git_exec_path());
  
  		if (sane_execvp(path, (char **)argv) < 0)
  			die_errno("could not exec %s", path);
  
  		return 0;
  	}
 +	prefix = setup_git_directory();
 +	trace_repo_setup(prefix);
 +	setup_work_tree();
 +	/* NEEDSWORK: once we no longer spawn anything, remove this */
 +	setenv(GIT_DIR_ENVIRONMENT, absolute_path(get_git_dir()), 1);
 +	setenv(GIT_WORK_TREE_ENVIRONMENT, absolute_path(get_git_work_tree()), 1);
 +
 +	git_config(difftool_config, NULL);
 +	symlinks = has_symlinks;
  
  	argc = parse_options(argc, argv, prefix, builtin_difftool_options,
  			     builtin_difftool_usage, PARSE_OPT_KEEP_UNKNOWN |
 @@ -687,6 +726,6 @@ int cmd_difftool(int argc, const char ** argv, const char * prefix)
  	 * each file that changed.
  	 */
  	if (dir_diff)
 -		return run_dir_diff(extcmd, symlinks, argc, argv);
 -	return run_file_diff(prompt, argc, argv);
 +		return run_dir_diff(extcmd, symlinks, prefix, argc, argv);
 +	return run_file_diff(prompt, prefix, argc, argv);
  }
 diff --git a/git.c b/git.c
 index e68b6eb..a8e6a15 100644
 --- a/git.c
 +++ b/git.c
 @@ -424,7 +424,12 @@ static struct cmd_struct commands[] = {
  	{ "diff-files", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },
  	{ "diff-index", cmd_diff_index, RUN_SETUP },
  	{ "diff-tree", cmd_diff_tree, RUN_SETUP },
 -	{ "difftool", cmd_difftool, RUN_SETUP | NEED_WORK_TREE },
 +	/*
 +	 * NEEDSWORK: Once the redirection to git-legacy-difftool.perl in
 +	 * builtin/difftool.c has been removed, this entry should be changed to
 +	 * RUN_SETUP | NEED_WORK_TREE
 +	 */
 +	{ "difftool", cmd_difftool },
  	{ "fast-export", cmd_fast_export, RUN_SETUP },
  	{ "fetch", cmd_fetch, RUN_SETUP },
  	{ "fetch-pack", cmd_fetch_pack, RUN_SETUP },
 diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
 index 70a2de4..b6a6c30 100755
 --- a/t/t7800-difftool.sh
 +++ b/t/t7800-difftool.sh
 @@ -23,6 +23,8 @@ prompt_given ()
  	test "$prompt" = "Launch 'test-tool' [Y/n]? branch"
  }
  
 +# NEEDSWORK: lose all the PERL prereqs once legacy-difftool is retired.
 +
  # Create a file on master and change it on branch
  test_expect_success PERL 'setup' '
  	echo master >file &&

-- 
2.10.1.583.g721a9e0


^ permalink raw reply

* Re: [PATCH v2] merge-recursive.c: use string_list_sort instead of qsort
From: Jeff King @ 2016-11-24 20:52 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: git, René Scharfe, Junio C Hamano
In-Reply-To: <20161124114536.22249-1-pclouds@gmail.com>

On Thu, Nov 24, 2016 at 06:45:36PM +0700, Nguyễn Thái Ngọc Duy wrote:

> This started out to as a hunt for remaining qsort() calls after rs/qsort
> series because qsort() API is a bit easy to get wrong (*). However,
> since we have string_list_sort(), it's conceptually a better way to sort
> here.
> 
> (*) In this particular case, it's even more confusing when you sort one
> variable but you use the number of items and item size from an unrelated
> variable (from a first glance)

Makes sense, though I think I probably would have explained it in
reverse order:

  Merge-recursive sorts a string list using a raw qsort(), where it
  feeds the "items" from one struct but the "nr" and size fields from
  another struct. This isn't a bug because one list is a copy of the
  other, but it's unnecessarily confusing (and also caused our recent
  QSORT() cleanups via coccinelle to miss this call site).

  Let's use string_list_sort() instead, which is more concise and harder
  to get wrong. Note that we need to adjust our comparison function,
  which gets fed only the strings now, not the string_list_items. That's
  OK because we don't use the "util" field as part of our sort.

Feel free to use or ignore my description as you see fit. :)

> -static int string_list_df_name_compare(const void *a, const void *b)
> +static int string_list_df_name_compare(const char *one, const char *two)
>  {
> -	const struct string_list_item *one = a;
> -	const struct string_list_item *two = b;
> -	int onelen = strlen(one->string);
> -	int twolen = strlen(two->string);
> +	int onelen = strlen(one);
> +	int twolen = strlen(two);

I guess I haven't used string_list_sort() in a while, but I was
surprised to find that it just feeds the strings to the comparator. That
makes sense for using a raw strcmp() as the comparator, but I wonder if
any callers would ever want to take the util field into account (e.g.,
to break ties).

We don't seem to care here, though (which can be verified by reading the
code, but also because any mention of one->util would be a compilation
error after your patch). So I guess we can punt on it until the day that
some caller does need it.

-Peff

^ permalink raw reply

* Re: [char-misc-next] mei: request async autosuspend at the end of enumeration
From: Jeff King @ 2016-11-24 20:43 UTC (permalink / raw)
  To: Winkler, Tomas
  Cc: Matthieu Moy, git@vger.kernel.org,
	Greg KH (gregkh@linuxfoundation.org), Usyskin, Alexander,
	linux-kernel@vger.kernel.org
In-Reply-To: <5B8DA87D05A7694D9FA63FD143655C1B5433132E@hasmsx108.ger.corp.intel.com>

On Thu, Nov 24, 2016 at 04:10:49PM +0000, Winkler, Tomas wrote:

> > Cc: <stable@vger.kernel.org> # 4.4+
> 
> Looks like git send-email is not able to parse this address correctly
> though this is suggested format by Documentation/stable_kernel_rules.txt.
> Create wrong address If git parsers is used : 'stable@vger.kernel.org#4.4+' 
> 
> Something like s/#.*$// is needed before parsing Cc:

This should be fixed by e3fdbcc8e (parse_mailboxes: accept extra text
after <...> address, 2016-10-13), which will be released next week as
part of v2.11. As a workaround, you can also install the Mail::Address
perl module.  See [1] for the gory details.

-Peff

[1] http://public-inbox.org/git/41164484-309b-bfff-ddbb-55153495d41a@lwfinger.net/

^ permalink raw reply

* [PATCH] l10n: de.po: translate 210 new message
From: Ralf Thielow @ 2016-11-24 18:25 UTC (permalink / raw)
  To: git
  Cc: tr, jk, stimming, phillip.szelat, matthias.ruester,
	magnus.goerlitz, Ralf Thielow

Translate 210 new messages came from git.pot update in fda7b09
(l10n: git.pot: v2.11.0 round 1 (209 new, 53 removed)) and c091ffb
(l10n: git.pot: v2.11.0 round 2 (1 new, 1 removed)).

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

diff --git a/po/de.po b/po/de.po
index 766a8e1b0..6a37885f5 100644
--- a/po/de.po
+++ b/po/de.po
@@ -111,32 +111,30 @@ msgstr ""
 
 #: apply.c:57
 #, c-format
 msgid "unrecognized whitespace option '%s'"
 msgstr "nicht erkannte Whitespace-Option: '%s'"
 
 #: apply.c:73
 #, c-format
 msgid "unrecognized whitespace ignore option '%s'"
 msgstr "nicht erkannte Option zum Ignorieren von Whitespace: '%s'"
 
 #: apply.c:125
-#, fuzzy
 msgid "--reject and --3way cannot be used together."
-msgstr "Die Optionen -x und -X können nicht gemeinsam verwendet werden."
+msgstr "--reject und --3way können nicht gemeinsam verwendet werden."
 
 #: apply.c:127
-#, fuzzy
 msgid "--cached and --3way cannot be used together."
-msgstr "Die Optionen -x und -X können nicht gemeinsam verwendet werden."
+msgstr "--cached und --3way können nicht gemeinsam verwendet werden."
 
 #: apply.c:130
 msgid "--3way outside a repository"
 msgstr ""
 "Die Option --3way kann nicht außerhalb eines Repositories verwendet werden."
 
 #: apply.c:141
 msgid "--index outside a repository"
 msgstr ""
 "Die Option --index kann nicht außerhalb eines Repositories verwendet werden."
 
 #: apply.c:144
@@ -200,29 +198,27 @@ msgid ""
 "component (line %d)"
 msgid_plural ""
 "git diff header lacks filename information when removing %d leading pathname "
 "components (line %d)"
 msgstr[0] ""
 "Dem Kopfbereich von \"git diff\" fehlen Informationen zum Dateinamen, wenn "
 "%d vorangestellter Teil des Pfades entfernt wird (Zeile %d)"
 msgstr[1] ""
 "Dem Kopfbereich von \"git diff\" fehlen Informationen zum Dateinamen, wenn "
 "%d vorangestellte Teile des Pfades entfernt werden (Zeile %d)"
 
 #: apply.c:1589
-#, fuzzy, c-format
+#, c-format
 msgid "git diff header lacks filename information (line %d)"
-msgstr ""
-"Dem Kopfbereich von \"git diff\" fehlen Informationen zum Dateinamen, wenn "
-"%d vorangestellter Teil des Pfades entfernt wird (Zeile %d)"
+msgstr "Dem Kopfbereich von \"git diff\" fehlen Informationen zum Dateinamen (Zeile %d)"
 
 #: apply.c:1759
 msgid "new file depends on old contents"
 msgstr "neue Datei hängt von alten Inhalten ab"
 
 #: apply.c:1761
 msgid "deleted file still has contents"
 msgstr "entfernte Datei hat noch Inhalte"
 
 #: apply.c:1795
 #, c-format
 msgid "corrupt patch at line %d"
@@ -295,45 +291,49 @@ msgstr ""
 "bei der Suche nach:\n"
 "%.*s"
 
 #: apply.c:3090
 #, c-format
 msgid "missing binary patch data for '%s'"
 msgstr "keine Daten in Binär-Patch für '%s'"
 
 #: apply.c:3098
 #, c-format
 msgid "cannot reverse-apply a binary patch without the reverse hunk to '%s'"
 msgstr ""
+"kann binären Patch nicht in umgekehrter Reihenfolge anwenden ohne einen\n"
+"umgekehrten Patch-Block auf '%s'"
 
 #: apply.c:3144
 #, c-format
 msgid "cannot apply binary patch to '%s' without full index line"
-msgstr ""
+msgstr "kann binären Patch auf '%s' nicht ohne eine vollständige Index-Zeile anwenden"
 
 #: apply.c:3154
 #, c-format
 msgid ""
 "the patch applies to '%s' (%s), which does not match the current contents."
 msgstr ""
+"der Patch wird angewendet auf '%s' (%s), was nicht den aktuellen Inhalten\n"
+"entspricht"
 
 #: apply.c:3162
 #, c-format
 msgid "the patch applies to an empty '%s' but it is not empty"
-msgstr ""
+msgstr "der Patch wird auf ein leeres '%s' angewendet, was aber nicht leer ist"
 
 #: apply.c:3180
 #, c-format
 msgid "the necessary postimage %s for '%s' cannot be read"
-msgstr ""
+msgstr "das erforderliche Postimage %s für '%s' kann nicht gelesen werden"
 
 #: apply.c:3193
 #, c-format
 msgid "binary patch does not apply to '%s'"
 msgstr "Konnte Binär-Patch nicht auf '%s' anwenden"
 
 #: apply.c:3199
 #, c-format
 msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)"
 msgstr ""
 "Binär-Patch für '%s' erzeugt falsches Ergebnis (erwartete %s, bekam %s)"
 
@@ -364,55 +364,53 @@ msgstr "Pfad %s wurde umbenannt/gelöscht"
 
 #: apply.c:3510 apply.c:3681
 #, c-format
 msgid "%s: does not exist in index"
 msgstr "%s ist nicht im Index"
 
 #: apply.c:3519 apply.c:3689
 #, c-format
 msgid "%s: does not match index"
 msgstr "%s entspricht nicht der Version im Index"
 
 #: apply.c:3554
-#, fuzzy
 msgid "repository lacks the necessary blob to fall back on 3-way merge."
 msgstr ""
-"Dem Repository fehlen notwendige Blobs um auf einen 3-Wege-Merge "
+"Dem Repository fehlt der notwendige Blob, um auf einen 3-Wege-Merge\n"
 "zurückzufallen."
 
 #: apply.c:3557
-#, fuzzy, c-format
+#, c-format
 msgid "Falling back to three-way merge...\n"
-msgstr "Falle zurück zum Patchen der Basis und zum 3-Wege-Merge ..."
+msgstr "Falle zurück auf 3-Wege-Merge ...\n"
 
 #: apply.c:3573 apply.c:3577
-#, fuzzy, c-format
+#, c-format
 msgid "cannot read the current contents of '%s'"
-msgstr ""
-"Kann aktuellen Branch nicht umbenennen, solange Sie sich auf keinem befinden."
+msgstr "kann aktuelle Inhalte von '%s' nicht lesen"
 
 #: apply.c:3589
-#, fuzzy, c-format
+#, c-format
 msgid "Failed to fall back on three-way merge...\n"
-msgstr "erlaube, falls notwendig, das Zurückfallen auf einen 3-Wege-Merge"
+msgstr "Fehler beim Zurückfallen auf 3-Wege-Merge...\n"
 
 #: apply.c:3603
-#, fuzzy, c-format
+#, c-format
 msgid "Applied patch to '%s' with conflicts.\n"
-msgstr "Patch %s sauber angewendet"
+msgstr "Patch auf '%s' mit Konflikten angewendet.\n"
 
 #: apply.c:3608
-#, fuzzy, c-format
+#, c-format
 msgid "Applied patch to '%s' cleanly.\n"
-msgstr "Patch %s sauber angewendet"
+msgstr "Patch auf '%s' sauber angewendet.\n"
 
 #: apply.c:3634
 msgid "removal patch leaves file contents"
 msgstr "Lösch-Patch hinterlässt Dateiinhalte"
 
 #: apply.c:3706
 #, c-format
 msgid "%s: wrong type"
 msgstr "%s: falscher Typ"
 
 #: apply.c:3708
 #, c-format
@@ -453,50 +451,50 @@ msgstr "betroffene Datei '%s' ist hinter einer symbolischen Verknüpfung"
 #, c-format
 msgid "%s: patch does not apply"
 msgstr "%s: Patch konnte nicht angewendet werden"
 
 #: apply.c:3984
 #, c-format
 msgid "Checking patch %s..."
 msgstr "Prüfe Patch %s ..."
 
 #: apply.c:4075
 #, c-format
 msgid "sha1 information is lacking or useless for submodule %s"
-msgstr ""
+msgstr "SHA-1 Information fehlt oder ist unbrauchbar für Submodul %s"
 
 #: apply.c:4082
 #, c-format
 msgid "mode change for %s, which is not in current HEAD"
-msgstr ""
+msgstr "Modusänderung für %s, was sich nicht im aktuellen HEAD befindet"
 
 #: apply.c:4085
 #, c-format
 msgid "sha1 information is lacking or useless (%s)."
-msgstr ""
+msgstr "SHA-1 Information fehlt oder ist unbrauchbar (%s)."
 
 #: apply.c:4090 builtin/checkout.c:233 builtin/reset.c:135
 #, c-format
 msgid "make_cache_entry failed for path '%s'"
 msgstr "make_cache_entry für Pfad '%s' fehlgeschlagen"
 
 #: apply.c:4094
-#, fuzzy, c-format
+#, c-format
 msgid "could not add %s to temporary index"
-msgstr "konnte temporäre Datei nicht erstellen"
+msgstr "konnte %s nicht zum temporären Index hinzufügen"
 
 #: apply.c:4104
-#, fuzzy, c-format
+#, c-format
 msgid "could not write temporary index to %s"
-msgstr "konnte temporäre Datei nicht zu %s umbenennen"
+msgstr "konnte temporären Index nicht nach %s schreiben"
 
 #: apply.c:4242
 #, c-format
 msgid "unable to remove %s from index"
 msgstr "konnte %s nicht aus dem Index entfernen"
 
 #: apply.c:4277
 #, c-format
 msgid "corrupt patch for submodule %s"
 msgstr "fehlerhafter Patch für Submodul %s"
 
 #: apply.c:4283
@@ -506,27 +504,27 @@ msgstr "konnte neu erstellte Datei '%s' nicht lesen"
 
 #: apply.c:4291
 #, c-format
 msgid "unable to create backing store for newly created file %s"
 msgstr "kann internen Speicher für eben erstellte Datei %s nicht erzeugen"
 
 #: apply.c:4297 apply.c:4441
 #, c-format
 msgid "unable to add cache entry for %s"
 msgstr "kann für %s keinen Eintrag in den Zwischenspeicher hinzufügen"
 
 #: apply.c:4338
-#, fuzzy, c-format
+#, c-format
 msgid "failed to write to '%s'"
-msgstr "Fehler beim Löschen von '%s'"
+msgstr "Fehler beim Schreiben nach '%s'"
 
 #: apply.c:4342
 #, c-format
 msgid "closing file '%s'"
 msgstr "schließe Datei '%s'"
 
 #: apply.c:4412
 #, c-format
 msgid "unable to write file '%s' mode %o"
 msgstr "konnte Datei '%s' mit Modus %o nicht schreiben"
 
 #: apply.c:4510
@@ -570,48 +568,48 @@ msgstr "Patch-Block #%d zurückgewiesen."
 msgid "Skipped patch '%s'."
 msgstr "Patch '%s' ausgelassen."
 
 #: apply.c:4676
 msgid "unrecognized input"
 msgstr "nicht erkannte Eingabe"
 
 #: apply.c:4695
 msgid "unable to read index file"
 msgstr "Konnte Index-Datei nicht lesen"
 
 #: apply.c:4833
-#, fuzzy, c-format
+#, c-format
 msgid "can't open patch '%s': %s"
-msgstr "kann Patch '%s' nicht öffnen"
+msgstr "kann Patch '%s' nicht öffnen: %s"
 
 #: apply.c:4858
 #, c-format
 msgid "squelched %d whitespace error"
 msgid_plural "squelched %d whitespace errors"
 msgstr[0] "unterdrückte %d Whitespace-Fehler"
 msgstr[1] "unterdrückte %d Whitespace-Fehler"
 
 #: apply.c:4864 apply.c:4879
 #, c-format
 msgid "%d line adds whitespace errors."
 msgid_plural "%d lines add whitespace errors."
 msgstr[0] "%d Zeile fügt Whitespace-Fehler hinzu."
 msgstr[1] "%d Zeilen fügen Whitespace-Fehler hinzu."
 
 #: apply.c:4872
-#, fuzzy, c-format
+#, c-format
 msgid "%d line applied after fixing whitespace errors."
 msgid_plural "%d lines applied after fixing whitespace errors."
-msgstr[0] "%d Zeile fügt Whitespace-Fehler hinzu."
-msgstr[1] "%d Zeilen fügen Whitespace-Fehler hinzu."
+msgstr[0] "%d Zeile nach Behebung von Whitespace-Fehlern angewendet."
+msgstr[1] "%d Zeilen nach Behebung von Whitespace-Fehlern angewendet."
 
 #: apply.c:4888 builtin/add.c:463 builtin/mv.c:286 builtin/rm.c:431
 msgid "Unable to write new index file"
 msgstr "Konnte neue Index-Datei nicht schreiben."
 
 #: apply.c:4919 apply.c:4922 builtin/am.c:2277 builtin/am.c:2280
 #: builtin/clone.c:95 builtin/fetch.c:98 builtin/pull.c:180
 #: builtin/submodule--helper.c:281 builtin/submodule--helper.c:407
 #: builtin/submodule--helper.c:589 builtin/submodule--helper.c:592
 #: builtin/submodule--helper.c:944 builtin/submodule--helper.c:947
 msgid "path"
 msgstr "Pfad"
@@ -1231,24 +1229,28 @@ msgstr "konnte %s nicht parsen"
 
 #: commit.c:42
 #, c-format
 msgid "%s %s is not a commit!"
 msgstr "%s %s ist kein Commit!"
 
 #: commit.c:1514
 msgid ""
 "Warning: commit message did not conform to UTF-8.\n"
 "You may want to amend it after fixing the message, or set the config\n"
 "variable i18n.commitencoding to the encoding your project uses.\n"
 msgstr ""
+"Warnung: Die Commit-Beschreibung ist nicht UTF-8 konform.\n"
+"Sie können das Nachbessern, nachdem Sie die Beschreibung korrigiert haben,\n"
+"oder Sie setzen die Konfigurationsvariable i18n.commitencoding auf das Encoding,\n"
+"welches von ihrem Projekt verwendet wird.\n"
 
 #: compat/obstack.c:406 compat/obstack.c:408
 msgid "memory exhausted"
 msgstr "Speicher verbraucht"
 
 #: config.c:516
 #, c-format
 msgid "bad config line %d in blob %s"
 msgstr "Ungültige Konfigurationszeile %d in Blob %s"
 
 #: config.c:520
 #, c-format
@@ -1370,73 +1372,81 @@ msgstr "%s hat mehrere Werte"
 #: config.c:2311
 #, c-format
 msgid "could not set '%s' to '%s'"
 msgstr "Konnte '%s' nicht zu '%s' setzen."
 
 #: config.c:2313
 #, c-format
 msgid "could not unset '%s'"
 msgstr "Konnte '%s' nicht aufheben."
 
 #: connect.c:49
 msgid "The remote end hung up upon initial contact"
-msgstr ""
+msgstr "Die Gegenseite hat sich nach dem erstmaligen Kontakt aufgehangen."
 
 #: connect.c:51
 msgid ""
 "Could not read from remote repository.\n"
 "\n"
 "Please make sure you have the correct access rights\n"
 "and the repository exists."
 msgstr ""
+"Konnte nicht vom Remote-Repository lesen.\n"
+"\n"
+"Bitte stellen Sie sicher, dass die korrekten Zugriffsberechtigungen bestehen\n"
+"und das Repository existiert."
 
 #: connected.c:63 builtin/fsck.c:173 builtin/prune.c:140
 msgid "Checking connectivity"
 msgstr "Prüfe Konnektivität"
 
 #: connected.c:75
 msgid "Could not run 'git rev-list'"
 msgstr "Konnte 'git rev-list' nicht ausführen"
 
 #: connected.c:95
 msgid "failed write to rev-list"
 msgstr "Fehler beim Schreiben nach rev-list"
 
 #: connected.c:102
 msgid "failed to close rev-list's stdin"
 msgstr "Fehler beim Schließen von rev-list's Standard-Eingabe"
 
 #: convert.c:201
 #, c-format
 msgid ""
 "CRLF will be replaced by LF in %s.\n"
 "The file will have its original line endings in your working directory."
 msgstr ""
+"CRLF wird in %s durch LF ersetzt.\n"
+"Die Datei wird ihre ursprünglichen Zeilenenden im Arbeitsverzeichnis behalten."
 
 #: convert.c:205
 #, c-format
 msgid "CRLF would be replaced by LF in %s."
-msgstr ""
+msgstr "CRLF würde in %s durch LF ersetzt werden."
 
 #: convert.c:211
 #, c-format
 msgid ""
 "LF will be replaced by CRLF in %s.\n"
 "The file will have its original line endings in your working directory."
 msgstr ""
+"LF wird in %s durch CRLF ersetzt.\n"
+"Die Datei wird ihre ursprünglichen Zeilenenden im Arbeitsverzeichnis behalten."
 
 #: convert.c:215
 #, c-format
 msgid "LF would be replaced by CRLF in %s"
-msgstr ""
+msgstr "LF würde in %s durch CRLF ersetzt werden."
 
 #: date.c:97
 msgid "in the future"
 msgstr "in der Zukunft"
 
 #: date.c:103
 #, c-format
 msgid "%lu second ago"
 msgid_plural "%lu seconds ago"
 msgstr[0] "vor %lu Sekunde"
 msgstr[1] "vor %lu Sekunden"
 
@@ -1498,27 +1508,27 @@ msgstr[0] "vor %lu Jahr"
 msgstr[1] "vor %lu Jahren"
 
 #: diffcore-order.c:24
 #, c-format
 msgid "failed to read orderfile '%s'"
 msgstr "Fehler beim Lesen der Reihenfolgedatei '%s'."
 
 #: diffcore-rename.c:536
 msgid "Performing inexact rename detection"
 msgstr "Führe Erkennung für ungenaue Umbenennung aus"
 
 #: diff.c:62
-#, fuzzy, c-format
+#, c-format
 msgid "option '%s' requires a value"
-msgstr "Schalter 'm' erfordert einen Wert."
+msgstr "Option '%s' erfordert einen Wert."
 
 #: diff.c:124
 #, c-format
 msgid "  Failed to parse dirstat cut-off percentage '%s'\n"
 msgstr ""
 "  Fehler beim Parsen des abgeschnittenen \"dirstat\" Prozentsatzes '%s'\n"
 
 #: diff.c:129
 #, c-format
 msgid "  Unknown dirstat parameter '%s'\n"
 msgstr "  Unbekannter \"dirstat\" Parameter '%s'\n"
 
@@ -1533,246 +1543,239 @@ msgid ""
 "Found errors in 'diff.dirstat' config variable:\n"
 "%s"
 msgstr ""
 "Fehler in 'diff.dirstat' Konfigurationsvariable gefunden:\n"
 "%s"
 
 #: diff.c:3087
 #, c-format
 msgid "external diff died, stopping at %s"
 msgstr "externes Diff-Programm unerwartet beendet, angehalten bei %s"
 
 #: diff.c:3412
-#, fuzzy
 msgid "--name-only, --name-status, --check and -s are mutually exclusive"
-msgstr "-b, -B und --detach schließen sich gegenseitig aus"
+msgstr "--name-only, --name-status, --check und -s schließen sich gegenseitig aus"
 
 #: diff.c:3502
 msgid "--follow requires exactly one pathspec"
 msgstr "--follow erfordert genau eine Pfadspezifikation"
 
 #: diff.c:3665
 #, c-format
 msgid ""
 "Failed to parse --dirstat/-X option parameter:\n"
 "%s"
 msgstr ""
 "Fehler beim Parsen des --dirstat/-X Optionsparameters:\n"
 "%s"
 
 #: diff.c:3679
 #, c-format
 msgid "Failed to parse --submodule option parameter: '%s'"
 msgstr "Fehler beim Parsen des --submodule Optionsparameters: '%s'"
 
 #: diff.c:4700
 msgid "inexact rename detection was skipped due to too many files."
 msgstr ""
+"Ungenaue Erkennung für Umbenennungen wurde aufgrund zu vieler Dateien\n"
+"übersprungen."
 
 #: diff.c:4703
 msgid "only found copies from modified paths due to too many files."
-msgstr ""
+msgstr "nur Kopien von geänderten Pfaden, aufgrund zu vieler Dateien, gefunden"
 
 #: diff.c:4706
 #, c-format
 msgid ""
 "you may want to set your %s variable to at least %d and retry the command."
 msgstr ""
+"Sie könnten die Variable %s auf mindestens %d setzen und den Befehl\n"
+"erneut versuchen."
 
 #: dir.c:1866
 msgid "failed to get kernel name and information"
 msgstr "Fehler beim Sammeln von Namen und Informationen zum Kernel"
 
 #: dir.c:1985
 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."
 
 #: fetch-pack.c:213
-#, fuzzy
 msgid "git fetch-pack: expected shallow list"
-msgstr "git archive: erwartete eine Spülung (flush)"
+msgstr "git fetch-pack: erwartete shallow-Liste"
 
 #: fetch-pack.c:225
-#, fuzzy
 msgid "git fetch-pack: expected ACK/NAK, got EOF"
-msgstr "git archive: habe ACK/NAK erwartet, aber EOF bekommen"
+msgstr "git fetch-pack: ACK/NAK erwartet, EOF bekommen"
 
 #: fetch-pack.c:243
-#, fuzzy, c-format
+#, c-format
 msgid "git fetch-pack: expected ACK/NAK, got '%s'"
-msgstr "git archive: habe ACK/NAK erwartet, aber EOF bekommen"
+msgstr "git fetch-pack: ACK/NAK erwartet, '%s' bekommen"
 
 #: fetch-pack.c:295
 msgid "--stateless-rpc requires multi_ack_detailed"
-msgstr ""
+msgstr "--stateless-rpc benötigt multi_ack_detailed"
 
 #: fetch-pack.c:381
-#, fuzzy, c-format
+#, c-format
 msgid "invalid shallow line: %s"
-msgstr "Ungültiger Zeilenanfang: '%c'"
+msgstr "Ungültige shallow-Zeile: %s"
 
 #: fetch-pack.c:387
-#, fuzzy, c-format
+#, c-format
 msgid "invalid unshallow line: %s"
-msgstr "Ungültige Identifikationszeile: %s"
+msgstr "Ungültige unshallow-Zeile: %s"
 
 #: fetch-pack.c:389
-#, fuzzy, c-format
+#, c-format
 msgid "object not found: %s"
-msgstr "Objekt %s nicht gefunden"
+msgstr "Objekt nicht gefunden: %s"
 
 #: fetch-pack.c:392
-#, fuzzy, c-format
+#, c-format
 msgid "error in object: %s"
-msgstr "Fehler in Objekt"
+msgstr "Fehler in Objekt: %s"
 
 #: fetch-pack.c:394
-#, fuzzy, c-format
+#, c-format
 msgid "no shallow found: %s"
-msgstr "Keine solche URL gefunden: %s"
+msgstr "Kein shallow-Objekt gefunden: %s"
 
 #: fetch-pack.c:397
 #, c-format
 msgid "expected shallow/unshallow, got %s"
-msgstr ""
+msgstr "shallow/unshallow erwartet, %s bekommen"
 
 #: fetch-pack.c:436
-#, fuzzy, c-format
+#, c-format
 msgid "got %s %d %s"
-msgstr "%s: %s - %s"
+msgstr "%s %d %s bekommen"
 
 #: fetch-pack.c:450
-#, fuzzy, c-format
+#, c-format
 msgid "invalid commit %s"
-msgstr "Ungültige Option: %s"
+msgstr "Ungültiger Commit %s"
 
 #: fetch-pack.c:483
 msgid "giving up"
-msgstr ""
+msgstr "Gebe auf"
 
 #: fetch-pack.c:493 progress.c:235
 msgid "done"
 msgstr "Fertig"
 
 #: fetch-pack.c:505
 #, c-format
 msgid "got %s (%d) %s"
-msgstr ""
+msgstr "%s (%d) %s bekommen"
 
 #: fetch-pack.c:551
 #, c-format
 msgid "Marking %s as complete"
-msgstr ""
+msgstr "Markiere %s als vollständig"
 
 #: fetch-pack.c:697
 #, c-format
 msgid "already have %s (%s)"
-msgstr ""
+msgstr "habe %s (%s) bereits"
 
 #: fetch-pack.c:735
 msgid "fetch-pack: unable to fork off sideband demultiplexer"
-msgstr ""
+msgstr "fetch-pack: Fehler beim Starten des sideband demultiplexer"
 
 #: fetch-pack.c:743
 msgid "protocol error: bad pack header"
-msgstr ""
+msgstr "Protokollfehler: ungültiger Pack-Header"
 
 #: fetch-pack.c:799
-#, fuzzy, c-format
+#, c-format
 msgid "fetch-pack: unable to fork off %s"
-msgstr "git rm: konnte %s nicht löschen"
+msgstr "fetch-pack: konnte %s nicht starten"
 
 #: fetch-pack.c:815
-#, fuzzy, c-format
+#, c-format
 msgid "%s failed"
-msgstr "\"fseek\" fehlgeschlagen"
+msgstr "%s fehlgeschlagen"
 
 #: fetch-pack.c:817
 msgid "error in sideband demultiplexer"
-msgstr ""
+msgstr "Fehler in sideband demultiplexer"
 
 #: fetch-pack.c:844
-#, fuzzy
 msgid "Server does not support shallow clients"
-msgstr "rev-list unterstützt keine Anzeige von Notizen"
+msgstr "Server unterstützt keine shallow-Clients"
 
 #: fetch-pack.c:848
 msgid "Server supports multi_ack_detailed"
-msgstr ""
+msgstr "Server unterstützt multi_ack_detailed"
 
 #: fetch-pack.c:851
 msgid "Server supports no-done"
-msgstr ""
+msgstr "Server unterstützt no-done"
 
 #: fetch-pack.c:857
 msgid "Server supports multi_ack"
-msgstr ""
+msgstr "Server unterstützt multi_ack"
 
 #: fetch-pack.c:861
 msgid "Server supports side-band-64k"
-msgstr ""
+msgstr "Server unterstützt side-band-64k"
 
 #: fetch-pack.c:865
 msgid "Server supports side-band"
-msgstr ""
+msgstr "Server unterstützt side-band"
 
 #: fetch-pack.c:869
 msgid "Server supports allow-tip-sha1-in-want"
-msgstr ""
+msgstr "Server unterstützt allow-tip-sha1-in-want"
 
 #: fetch-pack.c:873
 msgid "Server supports allow-reachable-sha1-in-want"
-msgstr ""
+msgstr "Server unterstützt allow-reachable-sha1-in-want"
 
 #: fetch-pack.c:883
 msgid "Server supports ofs-delta"
-msgstr ""
+msgstr "Server unterstützt ofs-delta"
 
 #: fetch-pack.c:890
 #, c-format
 msgid "Server version is %.*s"
-msgstr ""
+msgstr "Server-Version ist %.*s"
 
 #: fetch-pack.c:896
-#, fuzzy
 msgid "Server does not support --shallow-since"
-msgstr ""
-"die Gegenseite unterstützt keinen signierten Versand (\"--signed push\")"
+msgstr "Server unterstützt kein --shallow-since"
 
 #: fetch-pack.c:900
-#, fuzzy
 msgid "Server does not support --shallow-exclude"
-msgstr "die Gegenseite unterstützt keinen atomaren Versand (\"--atomic push\")"
+msgstr "Server unterstützt kein --shallow-exclude"
 
 #: fetch-pack.c:902
-#, fuzzy
 msgid "Server does not support --deepen"
-msgstr ""
-"die Gegenseite unterstützt keinen signierten Versand (\"--signed push\")"
+msgstr "Server unterstützt kein --deepen"
 
 #: fetch-pack.c:913
-#, fuzzy
 msgid "no common commits"
-msgstr "Unbekannter Commit %s"
+msgstr "keine gemeinsamen Commits"
 
 #: fetch-pack.c:925
-#, fuzzy
 msgid "git fetch-pack: fetch failed."
-msgstr "Bearbeitung des Patches fehlgeschlagen"
+msgstr "git fetch-pack: Abholen fehlgeschlagen."
 
 #: fetch-pack.c:1087
 msgid "no matching remote head"
-msgstr ""
+msgstr "kein übereinstimmender Remote-Branch"
 
 #: gpg-interface.c:185
 msgid "gpg failed to sign the data"
 msgstr "gpg beim Signieren der Daten fehlgeschlagen"
 
 #: gpg-interface.c:215
 msgid "could not create temporary file"
 msgstr "konnte temporäre Datei nicht erstellen"
 
 #: gpg-interface.c:217
 #, c-format
 msgid "failed writing detached signature to '%s'"
@@ -1862,24 +1865,35 @@ msgid ""
 "\n"
 "*** Please tell me who you are.\n"
 "\n"
 "Run\n"
 "\n"
 "  git config --global user.email \"you@example.com\"\n"
 "  git config --global user.name \"Your Name\"\n"
 "\n"
 "to set your account's default identity.\n"
 "Omit --global to set the identity only in this repository.\n"
 "\n"
 msgstr ""
+"\n"
+"*** Bitte geben Sie an, wer Sie sind.\n"
+"\n"
+"Führen Sie\n"
+"\n"
+"  git config --global user.email \"you@example.com\"\n"
+"  git config --global user.name \"Your Name\"\n"
+"\n"
+"aus, um das als Ihre standardmäßige Identität zu setzen.\n"
+"Lassen Sie die Option \"--global\" weg, um die Identität nur\n"
+"für dieses Repository zu setzen.\n"
 
 #: lockfile.c:152
 #, c-format
 msgid ""
 "Unable to create '%s.lock': %s.\n"
 "\n"
 "Another git process seems to be running in this repository, e.g.\n"
 "an editor opened by 'git commit'. Please make sure all processes\n"
 "are terminated then try again. If it still fails, a git process\n"
 "may have crashed in this repository earlier:\n"
 "remove the file manually to continue."
 msgstr ""
@@ -2146,29 +2160,33 @@ msgstr "Konnte Objekt '%s' nicht parsen."
 
 #: merge-recursive.c:2135 builtin/merge.c:641 builtin/merge.c:788
 msgid "Unable to write index."
 msgstr "Konnte Index nicht schreiben."
 
 #: notes-merge.c:273
 #, c-format
 msgid ""
 "You have not concluded your previous notes merge (%s exists).\n"
 "Please, use 'git notes merge --commit' or 'git notes merge --abort' to "
 "commit/abort the previous merge before you start a new notes merge."
 msgstr ""
+"Sie haben Ihren vorherigen Merge von Notizen nicht abgeschlossen (%s existiert).\n"
+"Bitte benutzen Sie 'git notes merge --commit' oder 'git notes merge --abort', um\n"
+"den vorherigen Merge zu committen bzw. abzubrechen, bevor Sie einen neuen Merge\n"
+"von Notizen beginnen."
 
 #: notes-merge.c:280
-#, fuzzy, c-format
+#, c-format
 msgid "You have not concluded your notes merge (%s exists)."
-msgstr "Sie haben Ihren Merge nicht abgeschlossen (MERGE_HEAD existiert)."
+msgstr "Sie haben Ihren Merge von Notizen nicht abgeschlossen (%s existiert)."
 
 #: notes-utils.c:41
 msgid "Cannot commit uninitialized/unreferenced notes tree"
 msgstr ""
 "Kann uninitialisiertes/unreferenzierte Notiz-Verzeichnis nicht committen."
 
 #: notes-utils.c:100
 #, c-format
 msgid "Bad notes.rewriteMode value: '%s'"
 msgstr "Ungültiger notes.rewriteMode Wert: '%s'"
 
 #: notes-utils.c:110
@@ -2274,24 +2292,26 @@ msgstr "Pfadspezifikation '%s' befindet sich in Submodul '%.*s'"
 
 #: pathspec.c:353
 #, 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:408
 msgid ""
 "empty strings as pathspecs will be made invalid in upcoming releases. please "
 "use . instead if you meant to match all paths"
 msgstr ""
+"Leere Strings als Pfadspezifikationen werden in kommenden Releases ungültig.\n"
+"Bitte benutzen Sie stattdessen . wenn Sie alle Pfade meinen."
 
 #: pathspec.c:440
 #, c-format
 msgid "pathspec '%s' is beyond a symbolic link"
 msgstr "Pfadspezifikation '%s' ist hinter einer symbolischen Verknüpfung"
 
 #: pathspec.c:449
 msgid ""
 "There is nothing to exclude from by :(exclude) patterns.\n"
 "Perhaps you forgot to add either ':/' or '.' ?"
 msgstr ""
 ":(exclude) Muster, aber keine anderen Pfadspezifikationen angegeben.\n"
@@ -2637,180 +2657,173 @@ msgstr ""
 "kein Versand des \"push\"-Zertifikates, da die Gegenseite keinen signierten\n"
 "Versand (\"--signed push\") unterstützt"
 
 #: send-pack.c:424
 msgid "the receiving end does not support --atomic push"
 msgstr "die Gegenseite unterstützt keinen atomaren Versand (\"--atomic push\")"
 
 #: send-pack.c:429
 msgid "the receiving end does not support push options"
 msgstr "die Gegenseite unterstützt keine Push-Optionen"
 
 #: sequencer.c:171
-#, fuzzy
 msgid "revert"
-msgstr "\"revert\" fehlgeschlagen"
+msgstr "Revert"
 
 #: sequencer.c:171
-#, fuzzy
 msgid "cherry-pick"
-msgstr "\"cherry-pick\" fehlgeschlagen"
+msgstr "Cherry-Pick"
 
 #: sequencer.c:228
 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>'"
 
 #: sequencer.c:231
 msgid ""
 "after resolving the conflicts, mark the corrected paths\n"
 "with 'git add <paths>' or 'git rm <paths>'\n"
 "and commit the result with 'git commit'"
 msgstr ""
 "nach Auflösung der Konflikte, markieren Sie die korrigierten Pfade\n"
 "mit 'git add <Pfade>' oder 'git rm <Pfade>'und tragen Sie das Ergebnis mit\n"
 "'git commit' ein"
 
 #: sequencer.c:244 sequencer.c:1209
-#, fuzzy, c-format
+#, c-format
 msgid "could not lock '%s'"
-msgstr "Konnte '%s' nicht anwenden."
+msgstr "Konnte '%s' nicht sperren"
 
 #: sequencer.c:247 sequencer.c:1125 sequencer.c:1214
-#, fuzzy, c-format
+#, c-format
 msgid "could not write to '%s'"
 msgstr "Konnte nicht nach '%s' schreiben."
 
 #: sequencer.c:251
-#, fuzzy, c-format
+#, c-format
 msgid "could not write eol to '%s"
-msgstr "Konnte nicht nach '%s' schreiben."
+msgstr "Konnte EOL nicht nach '%s' schreiben."
 
 #: sequencer.c:255 sequencer.c:1130 sequencer.c:1216
-#, fuzzy, c-format
+#, c-format
 msgid "failed to finalize '%s'."
-msgstr "Konnte '%s' nicht entfernen."
+msgstr "Fehler beim Fertigstellen von '%s'."
 
 #: sequencer.c:279 builtin/am.c:259 builtin/commit.c:749 builtin/merge.c:1032
 #, c-format
 msgid "could not read '%s'"
 msgstr "Konnte '%s' nicht lesen"
 
 #: sequencer.c:305
-#, fuzzy, c-format
+#, c-format
 msgid "your local changes would be overwritten by %s."
-msgstr "Ihre lokalen Änderungen würden durch den Revert überschrieben werden."
+msgstr "Ihre lokalen Änderungen würden durch den %s überschrieben werden."
 
 #: sequencer.c:309
-#, fuzzy
 msgid "commit your changes or stash them to proceed."
 msgstr ""
 "Committen Sie Ihre Änderungen oder benutzen Sie \"stash\", um fortzufahren."
 
 #: sequencer.c:324
 #, c-format
 msgid "%s: fast-forward"
 msgstr "%s: Vorspulen"
 
 #. TRANSLATORS: %s will be "revert" or "cherry-pick"
 #: sequencer.c:399
 #, c-format
 msgid "%s: Unable to write new index file"
 msgstr "%s: Konnte neue Index-Datei nicht schreiben"
 
 #: sequencer.c:418
-#, fuzzy
 msgid "could not resolve HEAD commit\n"
-msgstr "Konnte Commit von HEAD nicht auflösen\n"
+msgstr "Konnte HEAD-Commit nicht auflösen\n"
 
 #: sequencer.c:438
-#, fuzzy
 msgid "unable to update cache tree\n"
 msgstr "Konnte Cache-Verzeichnis nicht aktualisieren\n"
 
 #: sequencer.c:483
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "you have staged changes in your working tree\n"
 "If these changes are meant to be squashed into the previous commit, run:\n"
 "\n"
 "  git commit --amend %s\n"
 "\n"
 "If they are meant to go into a new commit, run:\n"
 "\n"
 "  git commit %s\n"
 "\n"
 "In both cases, once you're done, continue with:\n"
 "\n"
 "  git rebase --continue\n"
 msgstr ""
-"Es befinden sich zum Commit vorgemerkte Änderungen in Ihrem "
-"Arbeitsverzeichnis.\n"
+"Es befinden sich zum Commit vorgemerkte Änderungen in Ihrem Arbeitsverzeichnis.\n"
 "Wenn diese Änderungen in den vorherigen Commit aufgenommen werden sollen,\n"
 "führen Sie aus:\n"
 "\n"
-"  git commit --amend $gpg_sign_opt_quoted\n"
+"  git commit --amend %s\n"
 "\n"
 "Wenn daraus ein neuer Commit erzeugt werden soll, führen Sie aus:\n"
 "\n"
-"  git commit $gpg_sign_opt_quoted\n"
+"  git commit %s\n"
 "\n"
 "Im Anschluss führen Sie zum Fortfahren aus:\n"
 "\n"
 "  git rebase --continue\n"
 
 #: sequencer.c:567
-#, fuzzy, c-format
+#, c-format
 msgid "could not parse commit %s\n"
 msgstr "Konnte Commit %s nicht parsen\n"
 
 #: sequencer.c:572
-#, fuzzy, c-format
+#, c-format
 msgid "could not parse parent commit %s\n"
 msgstr "Konnte Eltern-Commit %s nicht parsen\n"
 
 #: sequencer.c:656
-#, fuzzy
 msgid "your index file is unmerged."
 msgstr "Ihre Index-Datei ist nicht zusammengeführt."
 
 #: sequencer.c:675
-#, fuzzy, c-format
+#, c-format
 msgid "commit %s is a merge but no -m option was given."
 msgstr "Commit %s ist ein Merge, aber die Option -m wurde nicht angegeben."
 
 #: sequencer.c:683
-#, fuzzy, c-format
+#, c-format
 msgid "commit %s does not have parent %d"
-msgstr "Commit %s hat keinen Elternteil %d"
+msgstr "Commit %s hat keinen Eltern-Commit %d"
 
 #: sequencer.c:687
-#, fuzzy, c-format
+#, c-format
 msgid "mainline was specified but commit %s is not a merge."
 msgstr "Hauptlinie wurde spezifiziert, aber Commit %s ist kein Merge."
 
 #. TRANSLATORS: The first %s will be a "todo" command like
 #. "revert" or "pick", the second %s a SHA1.
 #: sequencer.c:700
 #, c-format
 msgid "%s: cannot parse parent commit %s"
 msgstr "%s: kann Eltern-Commit %s nicht parsen"
 
 #: sequencer.c:705
-#, fuzzy, c-format
+#, c-format
 msgid "cannot get commit message for %s"
-msgstr "Kann keine Commit-Beschreibung für %s bekommen"
+msgstr "Kann keine Commit-Beschreibung für %s bekommen."
 
 #: sequencer.c:797
 #, c-format
 msgid "could not revert %s... %s"
 msgstr "Konnte \"revert\" nicht auf %s... (%s) ausführen"
 
 #: sequencer.c:798
 #, c-format
 msgid "could not apply %s... %s"
 msgstr "Konnte %s... (%s) nicht anwenden"
 
 #: sequencer.c:833
@@ -2819,129 +2832,124 @@ msgstr "leere Menge von Commits übergeben"
 
 #: sequencer.c:843
 #, c-format
 msgid "git %s: failed to read the index"
 msgstr "git %s: Fehler beim Lesen des Index"
 
 #: sequencer.c:850
 #, c-format
 msgid "git %s: failed to refresh the index"
 msgstr "git %s: Fehler beim Aktualisieren des Index"
 
 #: sequencer.c:944
-#, fuzzy, c-format
+#, c-format
 msgid "invalid line %d: %.*s"
-msgstr "Ungültige Identifikationszeile: %s"
+msgstr "Ungültige Zeile %d: %.*s"
 
 #: sequencer.c:950
-#, fuzzy
 msgid "no commits parsed."
 msgstr "Keine Commits geparst."
 
 #: sequencer.c:966
-#, fuzzy, c-format
+#, c-format
 msgid "could not read '%s'."
-msgstr "Konnte '%s' nicht lesen"
+msgstr "Konnte '%s' nicht lesen."
 
 #: sequencer.c:972
-#, fuzzy, c-format
+#, c-format
 msgid "unusable instruction sheet: '%s'"
-msgstr "Unbenutzbares Instruktionsblatt: %s"
+msgstr "Unbenutzbares Instruktionsblatt: '%s'"
 
 #: sequencer.c:983
-#, fuzzy
 msgid "cannot cherry-pick during a revert."
 msgstr "Kann Cherry-Pick nicht während eines Reverts ausführen."
 
 #: sequencer.c:985
-#, fuzzy
 msgid "cannot revert during a cherry-pick."
 msgstr "Kann Revert nicht während eines Cherry-Picks ausführen."
 
 #: sequencer.c:1028
-#, fuzzy, c-format
+#, c-format
 msgid "invalid key: %s"
 msgstr "Ungültiger Schlüssel: %s"
 
 #: sequencer.c:1031
-#, fuzzy, c-format
+#, c-format
 msgid "invalid value for %s: %s"
 msgstr "Ungültiger Wert für %s: %s"
 
 #: sequencer.c:1063
-#, fuzzy, c-format
+#, c-format
 msgid "malformed options sheet: '%s'"
-msgstr "Fehlerhaftes Optionsblatt: %s"
+msgstr "Fehlerhaftes Optionsblatt: '%s'"
 
 #: sequencer.c:1101
 msgid "a cherry-pick or revert is already in progress"
 msgstr "\"cherry-pick\" oder \"revert\" ist bereits im Gang"
 
 #: sequencer.c:1102
 msgid "try \"git cherry-pick (--continue | --quit | --abort)\""
 msgstr "versuchen Sie \"git cherry-pick (--continue | --quit | --abort)\""
 
 #: sequencer.c:1106
-#, fuzzy, c-format
+#, c-format
 msgid "could not create sequencer directory '%s'"
-msgstr "Konnte \"sequencer\"-Verzeichnis %s nicht erstellen"
+msgstr "Konnte \"sequencer\"-Verzeichnis '%s' nicht erstellen."
 
 #: sequencer.c:1120
-#, fuzzy
 msgid "could not lock HEAD"
-msgstr "Konnte HEAD nicht loslösen"
+msgstr "Konnte HEAD nicht sperren"
 
 #: sequencer.c:1151 sequencer.c:1289
 msgid "no cherry-pick or revert in progress"
 msgstr "kein \"cherry-pick\" oder \"revert\" im Gang"
 
 #: sequencer.c:1153
 msgid "cannot resolve HEAD"
 msgstr "kann HEAD nicht auflösen"
 
 #: sequencer.c:1155 sequencer.c:1189
 msgid "cannot abort from a branch yet to be born"
 msgstr "kann nicht abbrechen: bin auf einem Branch, der noch geboren wird"
 
 #: sequencer.c:1175 builtin/grep.c:578
 #, c-format
 msgid "cannot open '%s'"
 msgstr "kann '%s' nicht öffnen"
 
 #: sequencer.c:1177
-#, fuzzy, c-format
+#, c-format
 msgid "cannot read '%s': %s"
-msgstr "Kann %s nicht lesen: %s"
+msgstr "Kann '%s' nicht lesen: %s"
 
 #: sequencer.c:1178
 msgid "unexpected end of file"
 msgstr "Unerwartetes Dateiende"
 
 #: sequencer.c:1184
 #, 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:1354
 #, c-format
 msgid "%s: can't cherry-pick a %s"
 msgstr "%s: %s kann nicht in \"cherry-pick\" benutzt werden"
 
 #: sequencer.c:1358
 #, c-format
 msgid "%s: bad revision"
 msgstr "%s: ungültiger Commit"
 
 #: sequencer.c:1391
-#, fuzzy
 msgid "can't revert as initial commit"
 msgstr "Kann nicht als allerersten Commit einen Revert ausführen."
 
 #: setup.c:160
 #, c-format
 msgid ""
 "%s: no such path in the working tree.\n"
 "Use 'git <command> -- <path>...' to specify paths that do not exist locally."
 msgstr ""
 "%s: kein solcher Pfad im Arbeitsverzeichnis.\n"
 "Benutzen Sie 'git <Befehl> -- <Pfad>...' zur Angabe von Pfaden, die lokal\n"
 "nicht existieren."
@@ -3007,27 +3015,27 @@ msgid "Cannot change to '%s/..'"
 msgstr "Kann nicht in Verzeichnis '%s/..' wechseln"
 
 #: setup.c:989
 #, c-format
 msgid ""
 "Problem with core.sharedRepository filemode value (0%.3o).\n"
 "The owner of files must always have read and write permissions."
 msgstr ""
 "Problem mit Wert für Dateimodus (0%.3o) von core.sharedRepository.\n"
 "Der Besitzer der Dateien muss immer Lese- und Schreibrechte haben."
 
 #: sha1_file.c:473
-#, fuzzy, c-format
+#, c-format
 msgid "path '%s' does not exist"
-msgstr "Branch '%s' existiert nicht"
+msgstr "Pfad '%s' existiert nicht"
 
 #: sha1_file.c:499
 #, c-format
 msgid "reference repository '%s' as a linked checkout is not supported yet."
 msgstr ""
 "Referenziertes Repository '%s' wird noch nicht als verknüpftes\n"
 "Arbeitsverzeichnis unterstützt."
 
 #: sha1_file.c:505
 #, c-format
 msgid "reference repository '%s' is not a local repository."
 msgstr "Referenziertes Repository '%s' ist kein lokales Repository."
@@ -3053,30 +3061,29 @@ msgstr "Offset vor Ende der Packdatei (fehlerhafte Indexdatei?)"
 #, c-format
 msgid "offset before start of pack index for %s (corrupt index?)"
 msgstr "Offset vor Beginn des Pack-Index für %s (beschädigter Index?)"
 
 #: sha1_file.c:2596
 #, c-format
 msgid "offset beyond end of pack index for %s (truncated index?)"
 msgstr "Offset hinter Ende des Pack-Index für %s (abgeschnittener Index?)"
 
 #: sha1_name.c:407
 #, c-format
 msgid "short SHA1 %s is ambiguous"
-msgstr ""
+msgstr "Kurzer SHA-1 %s ist mehrdeutig."
 
 #: sha1_name.c:418
-#, fuzzy
 msgid "The candidates are:"
-msgstr "Die allgemein verwendeten Git-Anleitungen sind:\n"
+msgstr "Die Kandidaten sind:"
 
 #: sha1_name.c:578
 msgid ""
 "Git normally never creates a ref that ends with 40 hex characters\n"
 "because it will be ignored when you just specify 40-hex. These refs\n"
 "may be created by mistake. For example,\n"
 "\n"
 "  git checkout -b $br $(git rev-parse ...)\n"
 "\n"
 "where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
 "examine these refs and maybe delete them. Turn this message off by\n"
 "running \"git config advice.objectNameWarning false\""
@@ -3229,40 +3236,38 @@ msgstr ""
 "\n"
 
 #: transport.c:829
 msgid "Aborting."
 msgstr "Abbruch."
 
 #: transport-helper.c:1075
 #, c-format
 msgid "Could not read ref %s"
 msgstr "Konnte Referenz %s nicht lesen."
 
 #: tree-walk.c:31
-#, fuzzy
 msgid "too-short tree object"
-msgstr "unerreichbare Objekte anzeigen"
+msgstr "zu kurzes Tree-Objekt"
 
 #: tree-walk.c:37
-#, fuzzy
 msgid "malformed mode in tree entry"
-msgstr "Missgebildeter Objektname %s"
+msgstr "fehlerhafter Modus in Tree-Eintrag"
 
 #: tree-walk.c:41
 msgid "empty filename in tree entry"
-msgstr ""
+msgstr "leerer Dateiname in Tree-Eintrag"
 
 #: tree-walk.c:113
 msgid "too-short tree file"
-msgstr ""
+msgstr "zu kurze Tree-Datei"
 
 #: unpack-trees.c:64
 #, c-format
 msgid ""
 "Your local changes to the following files would be overwritten by checkout:\n"
 "%%sPlease commit your changes or stash them before you switch branches."
 msgstr ""
 "Ihre lokalen Änderungen in den folgenden Dateien würden beim Auschecken\n"
 "überschrieben werden:\n"
 "%%sBitte committen oder stashen Sie Ihre Änderungen, bevor Sie Branches\n"
 "wechseln."
 
@@ -3459,43 +3464,43 @@ msgstr "Eintrag '%s' überschneidet sich mit '%s'. Kann nicht verbinden."
 #: unpack-trees.c:124
 #, c-format
 msgid ""
 "Cannot update sparse checkout: the following entries are not up-to-date:\n"
 "%s"
 msgstr ""
 "Kann partiellen Checkout nicht aktualisieren: die folgenden Einträge sind "
 "nicht\n"
 "aktuell:\n"
 "%s"
 
 #: unpack-trees.c:126
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "The following working tree files would be overwritten by sparse checkout "
 "update:\n"
 "%s"
 msgstr ""
-"Die folgenden Dateien im Arbeitsbereich würden durch die Aktualisierung\n"
-"des partiellen Checkouts überschrieben werden:\n"
+"Die folgenden Dateien im Arbeitsverzeichnis würden durch die Aktualisierung\n"
+"über einen partiellen Checkout überschrieben werden:\n"
 "%s"
 
 #: unpack-trees.c:128
-#, fuzzy, c-format
+#, c-format
 msgid ""
 "The following working tree files would be removed by sparse checkout "
 "update:\n"
 "%s"
 msgstr ""
-"Die folgenden Dateien im Arbeitsbereich würden durch die Aktualisierung\n"
-"des partiellen Checkouts entfernt werden:\n"
+"Die folgenden Dateien im Arbeitsverzeichnis würden durch die Aktualisierung\n"
+"über einen partiellen Checkout entfernt werden:\n"
 "%s"
 
 #: unpack-trees.c:205
 #, c-format
 msgid "Aborting\n"
 msgstr "Abbruch\n"
 
 #: unpack-trees.c:237
 msgid "Checking out files"
 msgstr "Checke Dateien aus"
 
 #: urlmatch.c:120
@@ -4054,41 +4059,36 @@ msgid "gone"
 msgstr "entfernt"
 
 #: wt-status.c:1763 wt-status.c:1771
 msgid "behind "
 msgstr "hinterher "
 
 #: wt-status.c:1766 wt-status.c:1769
 msgid "ahead "
 msgstr "voraus "
 
 #. TRANSLATORS: the action is e.g. "pull with rebase"
 #: wt-status.c:2270
-#, fuzzy, c-format
+#, c-format
 msgid "cannot %s: You have unstaged changes."
-msgstr ""
-"Rebase nicht möglich: Sie haben Änderungen, die nicht zum Commit vorgemerkt "
-"sind."
+msgstr "%s nicht möglich: Sie haben Änderungen, die nicht zum Commit vorgemerkt sind."
 
 #: wt-status.c:2276
-#, fuzzy
 msgid "additionally, your index contains uncommitted changes."
-msgstr "Zusätzlich beinhaltet die Staging-Area nicht committete Änderungen."
+msgstr "Zusätzlich enthält die Staging-Area nicht committete Änderungen."
 
 #: wt-status.c:2278
-#, fuzzy, c-format
+#, c-format
 msgid "cannot %s: Your index contains uncommitted changes."
-msgstr ""
-"Rebase nicht möglich: Die Staging-Area beinhaltet nicht committete "
-"Änderungen."
+msgstr "%s nicht möglich: Die Staging-Area enthält nicht committete Änderungen."
 
 #: compat/precompose_utf8.c:57 builtin/clone.c:414
 #, c-format
 msgid "failed to unlink '%s'"
 msgstr "Konnte '%s' nicht entfernen."
 
 #: builtin/add.c:22
 msgid "git add [<options>] [--] <pathspec>..."
 msgstr "git add [<Optionen>] [--] <Pfadspezifikation>..."
 
 #: builtin/add.c:80
 #, c-format
@@ -4464,27 +4464,26 @@ msgid ""
 "You seem to have moved HEAD since the last 'am' failure.\n"
 "Not rewinding to ORIG_HEAD"
 msgstr ""
 "Sie scheinen seit dem letzten gescheiterten 'am' HEAD geändert zu haben.\n"
 "Keine Zurücksetzung zu ORIG_HEAD."
 
 #: builtin/am.c:2200
 #, c-format
 msgid "Invalid value for --patch-format: %s"
 msgstr "Ungültiger Wert für --patch-format: %s"
 
 #: builtin/am.c:2233
-#, fuzzy
 msgid "git am [<options>] [(<mbox> | <Maildir>)...]"
-msgstr "git am [<Optionen>] [(<mbox>|<E-Mail-Verzeichnis>)...]"
+msgstr "git am [<Optionen>] [(<mbox> | <E-Mail-Verzeichnis>)...]"
 
 #: builtin/am.c:2234
 msgid "git am [<options>] (--continue | --skip | --abort)"
 msgstr "git am [<Optionen>] (--continue | --skip | --abort)"
 
 #: builtin/am.c:2240
 msgid "run interactively"
 msgstr "interaktiv ausführen"
 
 #: builtin/am.c:2242
 msgid "historical option -- no-op"
 msgstr "historische Option -- kein Effekt"
@@ -4749,28 +4748,32 @@ msgstr "Den Namen des Autors und den Zeitstempel unterdrücken (Standard: aus)"
 #: builtin/blame.c:2591
 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:2592
 msgid "Ignore whitespace differences"
 msgstr "Unterschiede im Whitespace ignorieren"
 
 #: builtin/blame.c:2599
 msgid "Use an experimental indent-based heuristic to improve diffs"
 msgstr ""
+"eine experimentelle, auf Einrückungen basierende Heuristik zur Verbesserung\n"
+"der Darstellung von Unterschieden verwenden"
 
 #: builtin/blame.c:2600
 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"
 
 #: builtin/blame.c:2602
 msgid "Spend extra cycles to find better match"
 msgstr "Länger arbeiten, um bessere Übereinstimmungen zu finden"
 
 #: builtin/blame.c:2603
 msgid "Use revisions from <file> instead of calling git-rev-list"
 msgstr "Commits von <Datei> benutzen, anstatt \"git-rev-list\" aufzurufen"
 
 #: builtin/blame.c:2604
 msgid "Use <file>'s contents as the final image"
 msgstr "Inhalte der <Datei>en als endgültiges Abbild benutzen"
@@ -4787,72 +4790,76 @@ msgstr "kopierte Zeilen innerhalb oder zwischen Dateien finden"
 msgid "Find line movements within and across files"
 msgstr "verschobene Zeilen innerhalb oder zwischen Dateien finden"
 
 #: builtin/blame.c:2607
 msgid "n,m"
 msgstr "n,m"
 
 #: builtin/blame.c:2607
 msgid "Process only line range n,m, counting from 1"
 msgstr "nur Zeilen im Bereich n,m verarbeiten, gezählt von 1"
 
 #: builtin/blame.c:2654
-#, fuzzy
 msgid "--progress can't be used with --incremental or porcelain formats"
-msgstr "Tags versenden (kann nicht mit --all oder --mirror verwendet werden)"
+msgstr ""
+"--progress kann nicht mit --incremental oder Formaten für Fremdprogramme\n"
+"verwendet werden"
 
 #. TRANSLATORS: This string is used to tell us the maximum
 #. display width for a relative timestamp in "git blame"
 #. output.  For C locale, "4 years, 11 months ago", which
 #. takes 22 places, is the longest among various forms of
 #. relative timestamps, but your language may need more or
 #. fewer display columns.
 #: builtin/blame.c:2700
 msgid "4 years, 11 months ago"
 msgstr "vor 4 Jahren, und 11 Monaten"
 
 #: builtin/blame.c:2780
-#, fuzzy
 msgid "--contents and --reverse do not blend well."
-msgstr "Die Optionen --column und --verbose sind inkompatibel."
+msgstr "--contents und --reverse funktionieren gemeinsam nicht."
 
 #: builtin/blame.c:2800
 msgid "cannot use --contents with final commit object name"
-msgstr ""
+msgstr "kann --contents nicht mit endgültigem Namen des Commit-Objektes benutzen"
 
 #: builtin/blame.c:2805
 msgid "--reverse and --first-parent together require specified latest commit"
 msgstr ""
+"--reverse und --first-parent zusammen erfordern die Angabe eines endgültigen\n"
+"Commits"
 
 #: builtin/blame.c:2832
 msgid ""
 "--reverse --first-parent together require range along first-parent chain"
 msgstr ""
+"--reverse und --first-parent zusammen erfordern einen Bereich entlang der\n"
+"\"first-parent\"-Kette"
 
 #: builtin/blame.c:2843
-#, fuzzy, c-format
+#, c-format
 msgid "no such path %s in %s"
-msgstr "Kein solcher Branch '%s'"
+msgstr "Pfad %s nicht in %s"
 
 #: builtin/blame.c:2854
-#, fuzzy, c-format
+#, c-format
 msgid "cannot read blob %s for path %s"
-msgstr "kann Objekt %s '%s' nicht lesen"
+msgstr "kann Blob %s für Pfad '%s' nicht lesen"
 
 #: builtin/blame.c:2873
 #, c-format
 msgid "file %s has only %lu line"
 msgid_plural "file %s has only %lu lines"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Datei %s hat nur %lu Zeile"
+msgstr[1] "Datei %s hat nur %lu Zeilen"
 
 #: builtin/branch.c:26
 msgid "git branch [<options>] [-r | -a] [--merged | --no-merged]"
 msgstr "git branch [<Optionen>] [-r | -a] [--merged | --no-merged]"
 
 #: builtin/branch.c:27
 msgid "git branch [<options>] [-l] [-f] <branch-name> [<start-point>]"
 msgstr "git branch [<Optionen>] [-l] [-f] <Branchname> [<Startpunkt>]"
 
 #: builtin/branch.c:28
 msgid "git branch [<options>] [-r] (-d | -D) <branch-name>..."
 msgstr "git branch [<Optionen>] [-r] (-d | -D) <Branchname>..."
@@ -5088,27 +5095,26 @@ msgstr "den Übernahmemodus einstellen (siehe git-pull(1))"
 msgid "change upstream info"
 msgstr "Informationen zum Upstream-Branch ändern"
 
 #: builtin/branch.c:659
 msgid "upstream"
 msgstr "Upstream"
 
 #: builtin/branch.c:659
 msgid "change the upstream info"
 msgstr "Informationen zum Upstream-Branch ändern"
 
 #: builtin/branch.c:660
-#, fuzzy
 msgid "Unset the upstream info"
-msgstr "Informationen zum Upstream-Branch ändern"
+msgstr "Informationen zum Upstream-Branch entfernen"
 
 #: builtin/branch.c:661
 msgid "use colored output"
 msgstr "farbige Ausgaben verwenden"
 
 #: builtin/branch.c:662
 msgid "act on remote-tracking branches"
 msgstr "auf Remote-Tracking-Branches wirken"
 
 #: builtin/branch.c:664 builtin/branch.c:665
 msgid "print only branches that contain the commit"
 msgstr "nur Branches ausgeben, welche diesen Commit beinhalten"
@@ -5295,38 +5301,34 @@ msgstr ""
 msgid "%s is okay\n"
 msgstr "%s ist in Ordnung\n"
 
 #: builtin/bundle.c:64
 msgid "Need a repository to create a bundle."
 msgstr "Um ein Paket zu erstellen wird ein Repository benötigt."
 
 #: builtin/bundle.c:68
 msgid "Need a repository to unbundle."
 msgstr "Zum Entpacken wird ein Repository benötigt."
 
 #: builtin/cat-file.c:513
-#, fuzzy
 msgid ""
 "git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e | -"
 "p | <type> | --textconv | --filters) [--path=<path>] <object>"
-msgstr ""
-"git cat-file (-t [--allow-unknown-type]|-s [--allow-unknown-type]|-e|-p|"
-"<Art>|--textconv) <Objekt>"
+msgstr "git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e | -p | <Art> | --textconv | --filters) [--path=<Pfad>] <Objekt>"
 
 #: builtin/cat-file.c:514
-#, fuzzy
 msgid ""
 "git cat-file (--batch | --batch-check) [--follow-symlinks] [--textconv | --"
 "filters]"
-msgstr "git cat-file (--batch | --batch-check) [--follow-symlinks]"
+msgstr "git cat-file (--batch | --batch-check) [--follow-symlinks] [--textconv | --filters]"
 
 #: builtin/cat-file.c:551
 msgid "<type> can be one of: blob, tree, commit, tag"
 msgstr "<Art> kann sein: blob, tree, commit, tag"
 
 #: builtin/cat-file.c:552
 msgid "show object type"
 msgstr "Objektart anzeigen"
 
 #: builtin/cat-file.c:553
 msgid "show object size"
 msgstr "Objektgröße anzeigen"
@@ -5335,35 +5337,34 @@ msgstr "Objektgröße anzeigen"
 msgid "exit with zero when there's no error"
 msgstr "mit Rückgabewert 0 beenden, wenn kein Fehler aufgetreten ist"
 
 #: builtin/cat-file.c:556
 msgid "pretty-print object's content"
 msgstr "ansprechende Anzeige des Objektinhaltes"
 
 #: builtin/cat-file.c:558
 msgid "for blob objects, run textconv on object's content"
 msgstr "eine Textkonvertierung auf den Inhalt von Blob-Objekten ausführen"
 
 #: builtin/cat-file.c:560
-#, fuzzy
 msgid "for blob objects, run filters on object's content"
-msgstr "eine Textkonvertierung auf den Inhalt von Blob-Objekten ausführen"
+msgstr "für Blob-Objekte, Filter auf Objekt-Inhalte ausführen"
 
 #: builtin/cat-file.c:561 git-submodule.sh:923
 msgid "blob"
 msgstr "Blob"
 
 #: builtin/cat-file.c:562
 msgid "use a specific path for --textconv/--filters"
-msgstr ""
+msgstr "einen bestimmten Pfad für --textconv/--filters verwenden"
 
 #: builtin/cat-file.c:564
 msgid "allow -s and -t to work with broken/corrupt objects"
 msgstr "-s und -t mit beschädigten Objekten erlauben"
 
 #: builtin/cat-file.c:565
 msgid "buffer --batch output"
 msgstr "Ausgabe von --batch puffern"
 
 #: builtin/cat-file.c:567
 msgid "show info and content of objects fed from the standard input"
 msgstr ""
@@ -6098,39 +6099,38 @@ msgstr "Tiefe"
 
 #: builtin/clone.c:98
 msgid "create a shallow clone of that depth"
 msgstr ""
 "einen Klon mit unvollständiger Historie (shallow) in dieser Tiefe erstellen"
 
 #: builtin/clone.c:99 builtin/fetch.c:122 builtin/pack-objects.c:2848
 #: parse-options.h:142
 msgid "time"
 msgstr "Zeit"
 
 #: builtin/clone.c:100
-#, fuzzy
 msgid "create a shallow clone since a specific time"
 msgstr ""
-"einen Klon mit unvollständiger Historie (shallow) in dieser Tiefe erstellen"
+"einen Klon mit unvollständiger Historie (shallow) seit einer bestimmten Zeit\n"
+"erstellen"
 
 #: builtin/clone.c:101 builtin/fetch.c:124
-#, fuzzy
 msgid "revision"
-msgstr "%s: ungültiger Commit"
+msgstr "Commit"
 
 #: builtin/clone.c:102 builtin/fetch.c:125
-#, fuzzy
 msgid "deepen history of shallow clone by excluding rev"
 msgstr ""
-"die Historie eines Klons mit unvollständiger Historie (shallow) vertiefen"
+"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"
 
 #: builtin/clone.c:106
 msgid "any cloned submodules will be shallow"
 msgstr "jedes geklonte Submodul mit unvollständiger Historie (shallow)"
 
 #: builtin/clone.c:107 builtin/init-db.c:484
 msgid "gitdir"
 msgstr ".git-Verzeichnis"
@@ -6155,27 +6155,27 @@ msgstr "nur IPv4-Adressen benutzen"
 msgid "use IPv6 addresses only"
 msgstr "nur IPv6-Adressen benutzen"
 
 #: builtin/clone.c:250
 msgid ""
 "No directory name could be guessed.\n"
 "Please specify a directory on the command line"
 msgstr ""
 "Konnte keinen Verzeichnisnamen erraten.\n"
 "Bitte geben Sie ein Verzeichnis auf der Befehlszeile an."
 
 #: builtin/clone.c:303
-#, fuzzy, c-format
+#, c-format
 msgid "info: Could not add alternate for '%s': %s\n"
-msgstr "Kann \"reflog\" für '%s' nicht durchführen: %s\n"
+msgstr "info: Konnte Alternative für '%s' nicht hinzufügen: %s\n"
 
 #: builtin/clone.c:375
 #, c-format
 msgid "failed to open '%s'"
 msgstr "Fehler beim Öffnen von '%s'"
 
 #: builtin/clone.c:383
 #, c-format
 msgid "%s exists and is not a directory"
 msgstr "%s existiert und ist kein Verzeichnis"
 
 #: builtin/clone.c:397
@@ -6297,45 +6297,39 @@ msgstr "Konnte Arbeitsverzeichnis '%s' nicht erstellen"
 msgid "Cloning into bare repository '%s'...\n"
 msgstr "Klone in Bare-Repository '%s' ...\n"
 
 #: builtin/clone.c:957
 #, c-format
 msgid "Cloning into '%s'...\n"
 msgstr "Klone nach '%s' ...\n"
 
 #: builtin/clone.c:963
 msgid ""
 "clone --recursive is not compatible with both --reference and --reference-if-"
 "able"
-msgstr ""
+msgstr "'clone --recursive' ist nicht kompatibel mit --reference und --reference-if-able"
 
 #: builtin/clone.c:1019
 msgid "--depth is ignored in local clones; use file:// instead."
 msgstr ""
 "Die Option --depth wird in lokalen Klonen ignoriert; benutzen Sie "
 "stattdessen file://"
 
 #: builtin/clone.c:1021
-#, fuzzy
 msgid "--shallow-since is ignored in local clones; use file:// instead."
-msgstr ""
-"Die Option --depth wird in lokalen Klonen ignoriert; benutzen Sie "
-"stattdessen file://"
+msgstr "--shallow-since wird in lokalen Klonen ignoriert; benutzen Sie stattdessen file://"
 
 #: builtin/clone.c:1023
-#, fuzzy
 msgid "--shallow-exclude is ignored in local clones; use file:// instead."
-msgstr ""
-"Die Option --depth wird in lokalen Klonen ignoriert; benutzen Sie "
-"stattdessen file://"
+msgstr "--shallow-exclude wird in lokalen Klonen ignoriert; benutzen Sie stattdessen file://"
 
 #: builtin/clone.c:1026
 msgid "source repository is shallow, ignoring --local"
 msgstr ""
 "Quelle ist ein Repository mit unvollständiger Historie (shallow),ignoriere --"
 "local"
 
 #: builtin/clone.c:1031
 msgid "--local is ignored"
 msgstr "--local wird ignoriert"
 
 #: builtin/clone.c:1035
@@ -6753,27 +6747,26 @@ msgstr "Ungültiger \"cleanup\" Modus %s"
 msgid "Paths with -a does not make sense."
 msgstr "Die Option -a kann nicht mit der Angabe von Pfaden verwendet werden."
 
 #: builtin/commit.c:1341 builtin/commit.c:1617
 msgid "show status concisely"
 msgstr "Status im Kurzformat anzeigen"
 
 #: builtin/commit.c:1343 builtin/commit.c:1619
 msgid "show branch information"
 msgstr "Branchinformationen anzeigen"
 
 #: builtin/commit.c:1345
-#, fuzzy
 msgid "version"
-msgstr "Berechtigungen"
+msgstr "Version"
 
 #: builtin/commit.c:1345 builtin/commit.c:1621 builtin/push.c:522
 #: builtin/worktree.c:440
 msgid "machine-readable output"
 msgstr "maschinenlesbare Ausgabe"
 
 #: builtin/commit.c:1348 builtin/commit.c:1623
 msgid "show status in long format (default)"
 msgstr "Status im Langformat anzeigen (Standard)"
 
 #: builtin/commit.c:1351 builtin/commit.c:1626
 msgid "terminate entries with NUL"
@@ -7168,24 +7161,27 @@ msgstr ""
 
 #: builtin/config.c:613
 #, c-format
 msgid "cannot create configuration file %s"
 msgstr "Konnte Konfigurationsdatei '%s' nicht erstellen."
 
 #: builtin/config.c:625
 #, c-format
 msgid ""
 "cannot overwrite multiple values with a single value\n"
 "       Use a regexp, --add or --replace-all to change %s."
 msgstr ""
+"kann nicht mehrere Werte mit einem einzigen Wert überschreiben\n"
+"       Benutzen Sie einen regulären Ausdruck, --add oder --replace, um %s\n"
+"       zu ändern."
 
 #: builtin/count-objects.c:86
 msgid "git count-objects [-v] [-H | --human-readable]"
 msgstr "git count-objects [-v] [-H | --human-readable]"
 
 #: builtin/count-objects.c:96
 msgid "print sizes in human readable format"
 msgstr "gibt Größenangaben in menschenlesbaren Format aus"
 
 #: builtin/describe.c:17
 msgid "git describe [<options>] [<commit-ish>...]"
 msgstr "git describe [<Optionen>] [<Commit-Angabe>...]"
@@ -7476,28 +7472,28 @@ msgid "keep downloaded pack"
 msgstr "heruntergeladenes Paket behalten"
 
 #: builtin/fetch.c:118
 msgid "allow updating of HEAD ref"
 msgstr "Aktualisierung der \"HEAD\"-Referenz erlauben"
 
 #: builtin/fetch.c:121 builtin/fetch.c:127 builtin/pull.c:203
 msgid "deepen history of shallow clone"
 msgstr ""
 "die Historie eines Klons mit unvollständiger Historie (shallow) vertiefen"
 
 #: builtin/fetch.c:123
-#, fuzzy
 msgid "deepen history of shallow repository based on time"
 msgstr ""
-"die Historie eines Klons mit unvollständiger Historie (shallow) vertiefen"
+"die Historie eines Klons mit unvollständiger Historie (shallow) auf Zeitbasis\n"
+"vertiefen"
 
 #: builtin/fetch.c:129 builtin/pull.c:206
 msgid "convert to a complete repository"
 msgstr "zu einem vollständigen Repository konvertieren"
 
 #: builtin/fetch.c:131 builtin/log.c:1433
 msgid "dir"
 msgstr "Verzeichnis"
 
 #: builtin/fetch.c:132
 msgid "prepend this to submodule path output"
 msgstr "dies an die Ausgabe der Submodul-Pfade voranstellen"
@@ -7655,30 +7651,29 @@ msgid ""
 "remote name from which new revisions should be fetched."
 msgstr ""
 "Kein Remote-Repository angegeben. Bitte geben Sie entweder eine URL\n"
 "oder den Namen des Remote-Repositories an, von welchem neue\n"
 "Commits angefordert werden sollen."
 
 #: builtin/fetch.c:1280
 msgid "You need to specify a tag name."
 msgstr "Sie müssen den Namen des Tags angeben."
 
 #: builtin/fetch.c:1322
 msgid "Negative depth in --deepen is not supported"
-msgstr ""
+msgstr "Negative Tiefe wird von --deepen nicht unterstützt."
 
 #: builtin/fetch.c:1324
-#, fuzzy
 msgid "--deepen and --depth are mutually exclusive"
-msgstr "-b, -B und --detach schließen sich gegenseitig aus"
+msgstr "--deepen und --depth schließen sich gegenseitig aus"
 
 #: builtin/fetch.c:1329
 msgid "--depth and --unshallow cannot be used together"
 msgstr ""
 "Die Optionen --depth und --unshallow können nicht gemeinsam verwendet werden."
 
 #: builtin/fetch.c:1331
 msgid "--unshallow on a complete repository does not make sense"
 msgstr ""
 "Die Option --unshallow kann nicht in einem Repository mit unvollständiger "
 "Historie verwendet werden."
 
@@ -8208,25 +8203,25 @@ msgstr ""
 "Fehlersuche in Git, erzeugen"
 
 #: builtin/hash-object.c:101
 msgid "process file as it were from this path"
 msgstr "Datei verarbeiten, als ob sie von diesem Pfad wäre"
 
 #: builtin/help.c:42
 msgid "print all available commands"
 msgstr "alle vorhandenen Befehle anzeigen"
 
 #: builtin/help.c:43
 msgid "exclude guides"
-msgstr ""
+msgstr "Anleitungen ausschließen"
 
 #: builtin/help.c:44
 msgid "print list of useful guides"
 msgstr "Liste von allgemein verwendeten Anleitungen anzeigen"
 
 #: builtin/help.c:45
 msgid "show man page"
 msgstr "Handbuch anzeigen"
 
 #: builtin/help.c:46
 msgid "show manual in web browser"
 msgstr "Handbuch in einem Webbrowser anzeigen"
@@ -8375,25 +8370,25 @@ msgid "read error on input"
 msgstr "Fehler beim Lesen der Eingabe"
 
 #: builtin/index-pack.c:292
 msgid "used more bytes than were available"
 msgstr "verwendete mehr Bytes als verfügbar waren"
 
 #: builtin/index-pack.c:299
 msgid "pack too large for current definition of off_t"
 msgstr "Paket ist zu groß für die aktuelle Definition von off_t"
 
 #: builtin/index-pack.c:302 builtin/unpack-objects.c:92
 msgid "pack exceeds maximum allowed size"
-msgstr ""
+msgstr "Paket überschreitet die maximal erlaubte Größe"
 
 #: builtin/index-pack.c:317
 #, c-format
 msgid "unable to create '%s'"
 msgstr "konnte '%s' nicht erstellen"
 
 #: builtin/index-pack.c:322
 #, c-format
 msgid "cannot open packfile '%s'"
 msgstr "Kann Paketdatei '%s' nicht öffnen"
 
 #: builtin/index-pack.c:336
@@ -8933,27 +8928,26 @@ msgstr "Dateiendung"
 msgid "use <sfx> instead of '.patch'"
 msgstr "<Dateiendung> anstatt '.patch' verwenden"
 
 #: builtin/log.c:1423
 msgid "start numbering patches at <n> instead of 1"
 msgstr "die Nummerierung der Patches bei <n> anstatt bei 1 beginnen"
 
 #: builtin/log.c:1425
 msgid "mark the series as Nth re-roll"
 msgstr "die Serie als n-te Fassung kennzeichnen"
 
 #: builtin/log.c:1427
-#, fuzzy
 msgid "Use [RFC PATCH] instead of [PATCH]"
-msgstr "[<Präfix>] anstatt [PATCH] verwenden"
+msgstr "[RFC PATCH] anstatt [PATCH] verwenden"
 
 #: builtin/log.c:1430
 msgid "Use [<prefix>] instead of [PATCH]"
 msgstr "[<Präfix>] anstatt [PATCH] verwenden"
 
 #: builtin/log.c:1433
 msgid "store resulting files in <dir>"
 msgstr "erzeugte Dateien in <Verzeichnis> speichern"
 
 #: builtin/log.c:1436
 msgid "don't strip/add [PATCH]"
 msgstr "[PATCH] nicht entfernen/hinzufügen"
@@ -9053,27 +9047,26 @@ msgstr "erforderliche Revisions-Informationen der Patch-Serie hinzufügen"
 msgid "add a signature from a file"
 msgstr "eine Signatur aus einer Datei hinzufügen"
 
 #: builtin/log.c:1475
 msgid "don't print the patch filenames"
 msgstr "keine Dateinamen der Patches anzeigen"
 
 #: builtin/log.c:1565
 msgid "-n and -k are mutually exclusive."
 msgstr "Die Optionen -n und -k schließen sich gegenseitig aus."
 
 #: builtin/log.c:1567
-#, fuzzy
 msgid "--subject-prefix/--rfc and -k are mutually exclusive."
-msgstr "Die Optionen --subject-prefix und -k schließen sich gegenseitig aus."
+msgstr "--subject-prefix/--rfc und -k schließen sich gegenseitig aus."
 
 #: builtin/log.c:1575
 msgid "--name-only does not make sense"
 msgstr "Die Option --name-only kann nicht verwendet werden."
 
 #: builtin/log.c:1577
 msgid "--name-status does not make sense"
 msgstr "Die Option --name-status kann nicht verwendet werden."
 
 #: builtin/log.c:1579
 msgid "--check does not make sense"
 msgstr "Die Option --check kann nicht verwendet werden."
@@ -9183,27 +9176,26 @@ msgstr "Muster, gelesen von <Datei>, ausschließen"
 msgid "read additional per-directory exclude patterns in <file>"
 msgstr "zusätzliche pro-Verzeichnis Auschlussmuster aus <Datei> auslesen"
 
 #: builtin/ls-files.c:545
 msgid "add the standard git exclusions"
 msgstr "die standardmäßigen Git-Ausschlüsse hinzufügen"
 
 #: builtin/ls-files.c:548
 msgid "make the output relative to the project top directory"
 msgstr "Ausgabe relativ zum Projektverzeichnis"
 
 #: builtin/ls-files.c:551
-#, fuzzy
 msgid "recurse through submodules"
-msgstr "Rekursion in Unterverzeichnissen durchführen"
+msgstr "Rekursion in Submodulen durchführen"
 
 #: builtin/ls-files.c:553
 msgid "if any <file> is not in the index, treat this as an error"
 msgstr "als Fehler behandeln, wenn sich eine <Datei> nicht im Index befindet"
 
 #: builtin/ls-files.c:554
 msgid "tree-ish"
 msgstr "Commit-Referenz"
 
 #: builtin/ls-files.c:555
 msgid "pretend that paths removed since <tree-ish> are still present"
 msgstr ""
@@ -9752,54 +9744,53 @@ msgstr "bei Konflikten eine gemeinsame Variante verwenden"
 msgid "for conflicts, use this marker size"
 msgstr "bei Konflikten diese Kennzeichnungslänge verwenden"
 
 #: builtin/merge-file.c:43
 msgid "do not warn about conflicts"
 msgstr "keine Warnung bei Konflikten"
 
 #: builtin/merge-file.c:45
 msgid "set labels for file1/orig-file/file2"
 msgstr "Beschriftung für Datei1/orig-Datei/Datei2 setzen"
 
 #: builtin/merge-recursive.c:45
-#, fuzzy, c-format
+#, c-format
 msgid "unknown option %s"
-msgstr "unbekannte Option: $opt"
+msgstr "unbekannte Option: %s"
 
 #: builtin/merge-recursive.c:51
-#, fuzzy, c-format
+#, c-format
 msgid "could not parse object '%s'"
 msgstr "Konnte Objekt '%s' nicht parsen."
 
 #: builtin/merge-recursive.c:55
 #, c-format
 msgid "cannot handle more than %d base. Ignoring %s."
 msgid_plural "cannot handle more than %d bases. Ignoring %s."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "kann nicht mit mehr als %d Merge-Basis umgehen. Ignoriere %s."
+msgstr[1] "kann nicht mit mehr als %d Merge-Basen umgehen. Ignoriere %s."
 
 #: builtin/merge-recursive.c:63
-#, fuzzy
 msgid "not handling anything other than two heads merge."
 msgstr "Es wird nur der Merge von zwei Branches behandelt."
 
 #: builtin/merge-recursive.c:69 builtin/merge-recursive.c:71
-#, fuzzy, c-format
+#, c-format
 msgid "could not resolve ref '%s'"
-msgstr "Konnte Referenz %s nicht löschen"
+msgstr "Konnte Referenz '%s' nicht auflösen"
 
 #: builtin/merge-recursive.c:77
-#, fuzzy, c-format
+#, c-format
 msgid "Merging %s with %s\n"
-msgstr "Benenne %s nach %s um\n"
+msgstr "Führe %s mit %s zusammen\n"
 
 #: builtin/mktree.c:65
 msgid "git mktree [-z] [--missing] [--batch]"
 msgstr "git mktree [-z] [--missing] [--batch]"
 
 #: builtin/mktree.c:152
 msgid "input is NUL terminated"
 msgstr "Eingabe ist durch NUL-Zeichen abgeschlossen"
 
 #: builtin/mktree.c:153 builtin/write-tree.c:24
 msgid "allow missing objects"
 msgstr "fehlende Objekte erlauben"
@@ -10065,91 +10056,88 @@ msgid "unable to start 'show' for object '%s'"
 msgstr "konnte 'show' für Objekt '%s' nicht starten"
 
 #: builtin/notes.c:151
 msgid "could not read 'show' output"
 msgstr "Konnte Ausgabe von 'show' nicht lesen."
 
 #: builtin/notes.c:159
 #, c-format
 msgid "failed to finish 'show' for object '%s'"
 msgstr "konnte 'show' für Objekt '%s' nicht abschließen"
 
 #: builtin/notes.c:194
-#, fuzzy
 msgid "please supply the note contents using either -m or -F option"
-msgstr ""
-"Bitte liefern Sie den Notiz-Inhalt unter Verwendung der Option -m oder -F."
+msgstr "Bitte liefern Sie die Notiz-Inhalte unter Verwendung der Option -m oder -F."
 
 #: builtin/notes.c:203
 msgid "unable to write note object"
 msgstr "Konnte Notiz-Objekt nicht schreiben"
 
 #: builtin/notes.c:205
-#, fuzzy, c-format
+#, c-format
 msgid "the note contents have been left in %s"
-msgstr "Die Notiz-Inhalte wurden in %s belassen"
+msgstr "Die Notiz-Inhalte wurden in %s belassen."
 
 #: builtin/notes.c:233 builtin/tag.c:439
 #, c-format
 msgid "cannot read '%s'"
 msgstr "kann '%s' nicht lesen"
 
 #: builtin/notes.c:235 builtin/tag.c:442
 #, c-format
 msgid "could not open or read '%s'"
 msgstr "konnte '%s' nicht öffnen oder lesen"
 
 #: builtin/notes.c:254 builtin/notes.c:305 builtin/notes.c:307
 #: builtin/notes.c:372 builtin/notes.c:427 builtin/notes.c:513
 #: builtin/notes.c:518 builtin/notes.c:596 builtin/notes.c:659
-#, fuzzy, c-format
+#, c-format
 msgid "failed to resolve '%s' as a valid ref."
 msgstr "Konnte '%s' nicht als gültige Referenz auflösen."
 
 #: builtin/notes.c:257
-#, fuzzy, c-format
+#, c-format
 msgid "failed to read object '%s'."
 msgstr "Fehler beim Lesen des Objektes '%s'."
 
 #: builtin/notes.c:261
-#, fuzzy, c-format
+#, c-format
 msgid "cannot read note data from non-blob object '%s'."
 msgstr "Kann Notiz-Daten nicht von Nicht-Blob Objekt '%s' lesen."
 
 #: builtin/notes.c:301
-#, fuzzy, c-format
+#, c-format
 msgid "malformed input line: '%s'."
 msgstr "Fehlerhafte Eingabezeile: '%s'."
 
 #: builtin/notes.c:316
-#, fuzzy, c-format
+#, c-format
 msgid "failed to copy notes from '%s' to '%s'"
 msgstr "Fehler beim Kopieren der Notizen von '%s' nach '%s'"
 
 #. TRANSLATORS: the first %s will be replaced by a
 #. git notes command: 'add', 'merge', 'remove', etc.
 #: builtin/notes.c:345
-#, fuzzy, c-format
+#, c-format
 msgid "refusing to %s notes in %s (outside of refs/notes/)"
-msgstr ""
-"Umschreiben der Notizen in %s zurückgewiesen (außerhalb von refs/notes/)"
+msgstr "Ausführung von %s auf Notizen in %s (außerhalb von refs/notes/) zurückgewiesen"
 
 #: builtin/notes.c:365 builtin/notes.c:420 builtin/notes.c:496
 #: builtin/notes.c:508 builtin/notes.c:584 builtin/notes.c:652
 #: builtin/notes.c:802 builtin/notes.c:949 builtin/notes.c:970
 msgid "too many parameters"
 msgstr "zu viele Parameter"
 
 #: builtin/notes.c:378 builtin/notes.c:665
-#, fuzzy, c-format
+#, c-format
 msgid "no note found for object %s."
 msgstr "Keine Notiz für Objekt %s gefunden."
 
 #: builtin/notes.c:399 builtin/notes.c:562
 msgid "note contents as a string"
 msgstr "Notizinhalte als Zeichenkette"
 
 #: builtin/notes.c:402 builtin/notes.c:565
 msgid "note contents in a file"
 msgstr "Notizinhalte in einer Datei"
 
 #: builtin/notes.c:405 builtin/notes.c:568
@@ -10202,72 +10190,68 @@ msgid "too few parameters"
 msgstr "zu wenig Parameter"
 
 #: builtin/notes.c:525
 #, c-format
 msgid ""
 "Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite "
 "existing notes"
 msgstr ""
 "Kann Notizen nicht kopieren. Existierende Notizen für Objekt %s gefunden. "
 "Verwenden Sie '-f', um die existierenden Notizen zu überschreiben."
 
 #: builtin/notes.c:537
-#, fuzzy, c-format
+#, c-format
 msgid "missing notes on source object %s. Cannot copy."
 msgstr "Keine Notizen für Quell-Objekt %s. Kopie nicht möglich."
 
 #: builtin/notes.c:589
 #, c-format
 msgid ""
 "The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n"
 "Please use 'git notes add -f -m/-F/-c/-C' instead.\n"
 msgstr ""
 "Die Optionen -m/-F/-c/-C sind für den Unterbefehl 'edit' veraltet.\n"
 "Bitte benutzen Sie stattdessen 'git notes add -f -m/-F/-c/-C'.\n"
 
 #: builtin/notes.c:685
 msgid "failed to delete ref NOTES_MERGE_PARTIAL"
-msgstr ""
+msgstr "Fehler beim Löschen der Referenz NOTES_MERGE_PARTIAL"
 
 #: builtin/notes.c:687
-#, fuzzy
 msgid "failed to delete ref NOTES_MERGE_REF"
-msgstr "Konnte Datei '%s' nicht löschen"
+msgstr "Fehler beim Löschen der Referenz NOTES_MERGE_REF"
 
 #: builtin/notes.c:689
-#, fuzzy
 msgid "failed to remove 'git notes merge' worktree"
-msgstr "Fehler beim Löschen von '%s'"
+msgstr "Fehler beim Löschen des Arbeitsverzeichnisses von 'git notes merge'."
 
 #: builtin/notes.c:709
 msgid "failed to read ref NOTES_MERGE_PARTIAL"
-msgstr ""
+msgstr "Fehler beim Lesen der Referenz NOTES_MERGE_PARTIAL"
 
 #: builtin/notes.c:711
 msgid "could not find commit from NOTES_MERGE_PARTIAL."
-msgstr ""
+msgstr "Konnte Commit von NOTES_MERGE_PARTIAL nicht finden."
 
 #: builtin/notes.c:713
 msgid "could not parse commit from NOTES_MERGE_PARTIAL."
-msgstr ""
+msgstr "Konnte Commit von NOTES_MERGE_PARTIAL nicht parsen."
 
 #: builtin/notes.c:726
-#, fuzzy
 msgid "failed to resolve NOTES_MERGE_REF"
-msgstr "Fehler beim Löschen von %s"
+msgstr "Fehler beim Auflösen von NOTES_MERGE_REF"
 
 #: builtin/notes.c:729
-#, fuzzy
 msgid "failed to finalize notes merge"
-msgstr "Fehler beim Finden einer exakten Merge-Basis."
+msgstr "Fehler beim Abschließen der Zusammenführung der Notizen."
 
 #: builtin/notes.c:755
 #, c-format
 msgid "unknown notes merge strategy %s"
 msgstr "unbekannte Merge-Strategie '%s' für Notizen"
 
 #: builtin/notes.c:771
 msgid "General options"
 msgstr "Allgemeine Optionen"
 
 #: builtin/notes.c:773
 msgid "Merge options"
@@ -10295,40 +10279,39 @@ msgstr ""
 msgid "Aborting notes merge resolution"
 msgstr "Konfliktauflösung beim Merge von Notizen abbrechen"
 
 #: builtin/notes.c:783
 msgid "abort notes merge"
 msgstr "Merge von Notizen abbrechen"
 
 #: builtin/notes.c:794
 msgid "cannot mix --commit, --abort or -s/--strategy"
 msgstr "Kann --commit, --abort oder -s/--strategy nicht kombinieren."
 
 #: builtin/notes.c:799
-#, fuzzy
 msgid "must specify a notes ref to merge"
 msgstr "Sie müssen eine Notiz-Referenz zum Mergen angeben."
 
 #: builtin/notes.c:823
-#, fuzzy, c-format
+#, c-format
 msgid "unknown -s/--strategy: %s"
 msgstr "Unbekannter Wert für -s/--strategy: %s"
 
 #: builtin/notes.c:860
-#, fuzzy, c-format
+#, c-format
 msgid "a notes merge into %s is already in-progress at %s"
 msgstr "Ein Merge von Notizen nach %s ist bereits im Gange bei %s"
 
 #: builtin/notes.c:863
-#, fuzzy, c-format
+#, c-format
 msgid "failed to store link to current notes ref (%s)"
 msgstr ""
 "Fehler beim Speichern der Verknüpfung zur aktuellen Notes-Referenz (%s)"
 
 #: builtin/notes.c:865
 #, c-format
 msgid ""
 "Automatic notes merge failed. Fix conflicts in %s and commit the result with "
 "'git notes merge --commit', or abort the merge with 'git notes merge --"
 "abort'.\n"
 msgstr ""
 "Automatisches Zusammenführen der Notizen fehlgeschlagen. Beheben Sie die\n"
@@ -10357,25 +10340,25 @@ msgstr "nicht löschen, nur anzeigen"
 msgid "report pruned notes"
 msgstr "gelöschte Notizen melden"
 
 #: builtin/notes.c:983
 msgid "notes-ref"
 msgstr "Notiz-Referenz"
 
 #: builtin/notes.c:984
 msgid "use notes from <notes-ref>"
 msgstr "Notizen von <Notiz-Referenz> verwenden"
 
 #: builtin/notes.c:1019
-#, fuzzy, c-format
+#, c-format
 msgid "unknown subcommand: %s"
 msgstr "Unbekannter Unterbefehl: %s"
 
 #: builtin/pack-objects.c:29
 msgid ""
 "git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]"
 msgstr ""
 "git pack-objects --stdout [<Optionen>...] [< <Referenzliste> | < "
 "<Objektliste>]"
 
 #: builtin/pack-objects.c:30
 msgid ""
@@ -10735,28 +10718,27 @@ msgstr "Ignoriere --verify-signatures für Rebase"
 #: builtin/pull.c:801
 msgid "--[no-]autostash option is only valid with --rebase."
 msgstr "--[no-]autostash ist nur mit --rebase zulässig."
 
 #: builtin/pull.c:809
 msgid "Updating an unborn branch with changes added to the index."
 msgstr ""
 "Aktualisiere einen ungeborenen Branch mit Änderungen, die zum Commit "
 "vorgemerkt sind."
 
 #: builtin/pull.c:812
 msgid "pull with rebase"
-msgstr ""
+msgstr "Pull mit Rebase"
 
 #: builtin/pull.c:813
-#, fuzzy
 msgid "please commit or stash them."
 msgstr "Bitte committen Sie die Änderungen oder benutzen Sie \"stash\"."
 
 #: builtin/pull.c:838
 #, c-format
 msgid ""
 "fetch updated the current branch head.\n"
 "fast-forwarding your working tree from\n"
 "commit %s."
 msgstr ""
 "\"fetch\" aktualisierte die Spitze des aktuellen Branches.\n"
 "Spule Ihr Arbeitsverzeichnis von Commit %s vor."
@@ -11159,58 +11141,82 @@ msgid "don't check the working tree after merging"
 msgstr "das Arbeitsverzeichnis nach dem Merge nicht prüfen"
 
 #: builtin/read-tree.c:135
 msgid "don't update the index or the work tree"
 msgstr "weder den Index, noch das Arbeitsverzeichnis aktualisieren"
 
 #: builtin/read-tree.c:137
 msgid "skip applying sparse checkout filter"
 msgstr "Anwendung des Filters für partielles Auschecken überspringen"
 
 #: builtin/read-tree.c:139
 msgid "debug unpack-trees"
-msgstr "Entpacken der Bäume protokollieren"
+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
 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 'receive.denyCurrentBranch' configuration variable to\n"
 "'ignore' or 'warn' in the remote repository to allow pushing into\n"
 "its current branch; however, this is not recommended unless you\n"
 "arranged to update its work tree to match what you pushed in some\n"
 "other way.\n"
 "\n"
 "To squelch this message and still keep the default behaviour, set\n"
 "'receive.denyCurrentBranch' configuration variable to 'refuse'."
 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"
+"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'."
 
 #: builtin/receive-pack.c:813
 msgid ""
 "By default, deleting the current branch is denied, because the next\n"
 "'git clone' won't result in any file checked out, causing confusion.\n"
 "\n"
 "You can set 'receive.denyDeleteCurrent' configuration variable to\n"
 "'warn' or 'ignore' in the remote repository to allow deleting the\n"
 "current branch, with or without a warning message.\n"
 "\n"
 "To squelch this message, you can set it to 'refuse'."
 msgstr ""
+"Standardmäßig wird das Löschen des aktuellen Branches zurückgewiesen,\n"
+"da beim nächsten 'git clone' keine Dateien ausgecheckt werden würden,\n"
+"was zu Verwunderung führt.\n"
+"\n"
+"Sie können die Konfigurationsvariable 'receive.denyDeleteCurrent' im\n"
+"Remote-Repository auf 'warn' oder 'ignore' setzen, um das Löschen des\n"
+"aktuellen Branch mit oder ohne Warnung zu erlauben.\n"
+"\n"
+"Um diese Meldung zu unterdrücken, setzen Sie die Variable auf 'refuse'."
 
 #: builtin/receive-pack.c:1883
 msgid "quiet"
 msgstr "weniger Ausgaben"
 
 #: builtin/receive-pack.c:1897
 msgid "You must specify a directory."
 msgstr "Sie müssen ein Repository angeben."
 
 #: builtin/reflog.c:423
 #, c-format
 msgid "'%s' for '%s' is not a valid timestamp"
@@ -11917,27 +11923,26 @@ msgstr "git rerere [clean | forget <Pfad>... | status | remaining | diff | gc]"
 
 #: builtin/rerere.c:58
 msgid "register clean resolutions in index"
 msgstr "saubere Auflösungen im Index registrieren"
 
 #: builtin/reset.c:26
 msgid ""
 "git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"
 msgstr ""
 "git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<Commit>]"
 
 #: builtin/reset.c:27
-#, fuzzy
 msgid "git reset [-q] [<tree-ish>] [--] <paths>..."
-msgstr "git reset [-q] <Commit-Referenz> [--] <Pfade>..."
+msgstr "git reset [-q] [<Commit-Referenz>] [--] <Pfade>..."
 
 #: builtin/reset.c:28
 msgid "git reset --patch [<tree-ish>] [--] [<paths>...]"
 msgstr "git reset --patch [<Commit-Referenz>] [--] [<Pfade>...]"
 
 #: builtin/reset.c:34
 msgid "mixed"
 msgstr "mixed"
 
 #: builtin/reset.c:34
 msgid "soft"
 msgstr "soft"
@@ -12330,31 +12335,31 @@ msgstr ""
 "\t\t[--current] [--color[=<Wann>] | --no-color] [--sparse]\n"
 "\t\t[--more=<n> | --list | --independent | --merge-base]\n"
 "\t\t[--no-name | --sha1-name] [--topics] [(<Commit> | <glob>)...]"
 
 #: builtin/show-branch.c:14
 msgid "git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]"
 msgstr "git show-branch (-g | --reflog)[=<n>[,<Basis>]] [--list] [<Referenz>]"
 
 #: builtin/show-branch.c:375
 #, c-format
 msgid "ignoring %s; cannot handle more than %d ref"
 msgid_plural "ignoring %s; cannot handle more than %d refs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "ignoriere %s; kann nicht mehr als %d Referenz behandeln"
+msgstr[1] "ignoriere %s; kann nicht mehr als %d Referenzen behandeln"
 
 #: builtin/show-branch.c:541
-#, fuzzy, c-format
+#, c-format
 msgid "no matching refs with %s"
-msgstr "Dateien mit Übereinstimmungen im Anzeigeprogramm anzeigen"
+msgstr "keine übereinstimmenden Referenzen mit %s"
 
 #: builtin/show-branch.c:639
 msgid "show remote-tracking and local branches"
 msgstr "Remote-Tracking und lokale Branches anzeigen"
 
 #: builtin/show-branch.c:641
 msgid "show remote-tracking branches"
 msgstr "Remote-Tracking-Branches anzeigen"
 
 #: builtin/show-branch.c:643
 msgid "color '*!+-' corresponding to the branch"
 msgstr "'*!+-' entsprechend des Branches einfärben"
@@ -12404,66 +12409,64 @@ msgstr "Merges anzeigen, die nur von einem Branch aus erreichbar sind"
 msgid "topologically sort, maintaining date order where possible"
 msgstr "topologische Sortierung, Beibehaltung Datumsordnung wo möglich"
 
 #: builtin/show-branch.c:668
 msgid "<n>[,<base>]"
 msgstr "<n>[,<Basis>]"
 
 #: builtin/show-branch.c:669
 msgid "show <n> most recent ref-log entries starting at base"
 msgstr "die <n> jüngsten Einträge im Reflog, beginnend an der Basis, anzeigen"
 
 #: builtin/show-branch.c:703
-#, fuzzy
 msgid ""
 "--reflog is incompatible with --all, --remotes, --independent or --merge-base"
-msgstr "Die Option --delete ist inkompatibel mit --all, --mirror und --tags."
+msgstr "--reflog ist inkompatibel mit --all, --remotes, --independent oder --merge-base"
 
 #: builtin/show-branch.c:727
 msgid "no branches given, and HEAD is not valid"
-msgstr ""
+msgstr "keine Branches angegeben, und HEAD ist ungültig"
 
 #: builtin/show-branch.c:730
-#, fuzzy
 msgid "--reflog option needs one branch name"
-msgstr "Bei der Option --track muss ein Branchname angegeben werden."
+msgstr "Die Option --reflog benötigt einen Branchnamen."
 
 #: builtin/show-branch.c:733
 #, c-format
 msgid "only %d entry can be shown at one time."
 msgid_plural "only %d entries can be shown at one time."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "nur %d Eintrag kann zur selben Zeit angezeigt werden"
+msgstr[1] "nur %d Einträge können zur selben Zeit angezeigt werden"
 
 #: builtin/show-branch.c:737
-#, fuzzy, c-format
+#, c-format
 msgid "no such ref %s"
 msgstr "Referenz nicht gefunden: %s"
 
 #: builtin/show-branch.c:829
 #, c-format
 msgid "cannot handle more than %d rev."
 msgid_plural "cannot handle more than %d revs."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Kann nicht mehr als %d Commit behandeln."
+msgstr[1] "Kann nicht mehr als %d Commits behandeln."
 
 #: builtin/show-branch.c:833
-#, fuzzy, c-format
+#, c-format
 msgid "'%s' is not a valid ref."
-msgstr "'%s' ist kein gültiger Tagname."
+msgstr "'%s' ist keine gültige Referenz."
 
 #: builtin/show-branch.c:836
-#, fuzzy, c-format
+#, c-format
 msgid "cannot find commit %s (%s)"
-msgstr "kann Objekt %s '%s' nicht lesen"
+msgstr "kann Commit %s (%s) nicht finden"
 
 #: builtin/show-ref.c:10
 msgid ""
 "git show-ref [-q | --quiet] [--verify] [--head] [-d | --dereference] [-s | --"
 "hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [<pattern>...]"
 msgstr ""
 "git show-ref [-q | --quiet] [--verify] [--head] [-d | --dereference] [-s | --"
 "hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [<Muster>...] "
 
 #: builtin/show-ref.c:11
 msgid "git show-ref --exclude-existing[=<pattern>]"
 msgstr "git show-ref --exclude-existing[=<Muster>]"
@@ -12585,56 +12588,55 @@ msgstr "git submodule--helper init [<Pfad>]"
 #: builtin/submodule--helper.c:435
 msgid "git submodule--helper name <path>"
 msgstr "git submodule--helper name <Pfad>"
 
 #: builtin/submodule--helper.c:441
 #, c-format
 msgid "no submodule mapping found in .gitmodules for path '%s'"
 msgstr "Keine Submodul-Zuordnung in .gitmodules für Pfad '%s' gefunden"
 
 #: builtin/submodule--helper.c:524 builtin/submodule--helper.c:527
 #, c-format
 msgid "submodule '%s' cannot add alternate: %s"
-msgstr ""
+msgstr "Submodul '%s' kann Alternative nicht hinzufügen: %s"
 
 #: builtin/submodule--helper.c:563
 #, c-format
 msgid "Value '%s' for submodule.alternateErrorStrategy is not recognized"
-msgstr ""
+msgstr "Wert '%s' für submodule.alternateErrorStrategy wird nicht erkannt"
 
 #: builtin/submodule--helper.c:570
 #, c-format
 msgid "Value '%s' for submodule.alternateLocation is not recognized"
-msgstr ""
+msgstr "Wert '%s' für submodule.alternateLocation wird nicht erkannt."
 
 #: builtin/submodule--helper.c:593
 msgid "where the new submodule will be cloned to"
 msgstr "Pfad für neues Submodul"
 
 #: builtin/submodule--helper.c:596
 msgid "name of the new submodule"
 msgstr "Name des neuen Submoduls"
 
 #: builtin/submodule--helper.c:599
 msgid "url where to clone the submodule from"
 msgstr "URL von der das Submodul geklont wird"
 
 #: builtin/submodule--helper.c:605
 msgid "depth for shallow clones"
 msgstr "Tiefe des Klons mit unvollständiger Historie (shallow)"
 
 #: builtin/submodule--helper.c:608 builtin/submodule--helper.c:964
-#, fuzzy
 msgid "force cloning progress"
-msgstr "keine Fortschrittsanzeige beim Klonen"
+msgstr "Fortschrittsanzeige beim Klonen erzwingen"
 
 #: builtin/submodule--helper.c:613
 msgid ""
 "git submodule--helper clone [--prefix=<path>] [--quiet] [--reference "
 "<repository>] [--name <name>] [--depth <depth>] --url <url> --path <path>"
 msgstr ""
 "git submodule--helper clone [--prefix=<Pfad>] [--quiet] [--reference "
 "<Repository>] [--name <Name>] [--url <URL>] [--name <Name>] [--depth "
 "<Tiefe>] --url <URL> --path <Pfad>"
 
 #: builtin/submodule--helper.c:638 builtin/submodule--helper.c:648
 #, c-format
@@ -13179,34 +13181,38 @@ msgstr ""
 "prüfen ob das Dateisystem einen Cache für unversionierte Dateien unterstützt"
 
 #: builtin/update-index.c:1003
 msgid "enable untracked cache without testing the filesystem"
 msgstr ""
 "Cache für unversionierte Dateien ohne Prüfung des Dateisystems aktivieren"
 
 #: builtin/update-index.c:1119
 msgid ""
 "core.untrackedCache is set to true; remove or change it, if you really want "
 "to disable the untracked cache"
 msgstr ""
+"core.untrackedCache ist auf 'true' gesetzt. Entfernen oder ändern Sie dies,\n"
+"wenn Sie wirklich den Cache für unversionierte Dateien deaktivieren möchten."
 
 #: builtin/update-index.c:1123
 msgid "Untracked cache disabled"
 msgstr "Cache für unversionierte Dateien deaktiviert"
 
 #: builtin/update-index.c:1131
 msgid ""
 "core.untrackedCache is set to false; remove or change it, if you really want "
 "to enable the untracked cache"
 msgstr ""
+"core.untrackedCache ist auf 'false' gesetzt. Entfernen oder ändern Sie dies,\n"
+"wenn sie wirklich den Cache für unversionierte Dateien aktivieren möchten."
 
 #: builtin/update-index.c:1135
 #, c-format
 msgid "Untracked cache enabled for '%s'"
 msgstr "Cache für unversionierte Dateien für '%s' aktiviert"
 
 #: builtin/update-ref.c:9
 msgid "git update-ref [<options>] -d <refname> [<old-val>]"
 msgstr "git update-ref [<Optionen>] -d <Referenzname> [<alter-Wert>]"
 
 #: builtin/update-ref.c:10
 msgid "git update-ref [<options>]    <refname> <new-val> [<old-val>]"
@@ -13420,46 +13426,50 @@ msgstr ""
 #: upload-pack.c:1034
 msgid "interrupt transfer after <n> seconds of inactivity"
 msgstr "Übertragung nach <n> Sekunden Inaktivität unterbrechen"
 
 #: credential-cache--daemon.c:223
 #, c-format
 msgid ""
 "The permissions on your socket directory are too loose; other\n"
 "users may be able to read your cached credentials. Consider running:\n"
 "\n"
 "\tchmod 0700 %s"
 msgstr ""
+"Die Berechtigungen auf Ihr Socket-Verzeichnis sind zu schwach; andere\n"
+"Nutzer könnten Ihre zwischengespeicherten Anmeldeinformationen lesen.\n"
+"Ziehen Sie in Betracht\n"
+"\n"
+"\tchmod 0700 %s\n"
+"\n"
+"auszuführen."
 
 #: credential-cache--daemon.c:271
 msgid "print debugging messages to stderr"
 msgstr "Meldungen zur Fehlersuche in Standard-Fehlerausgabe ausgeben"
 
 #: git.c:14
 msgid ""
 "'git help -a' and 'git help -g' list available subcommands and some\n"
 "concept guides. See 'git help <command>' or 'git help <concept>'\n"
 "to read about a specific subcommand or concept."
 msgstr ""
 "'git help -a' und 'git help -g' listet verfügbare Unterbefehle und\n"
 "einige Anleitungen zu Git-Konzepten auf. Benutzen Sie 'git help <Befehl>'\n"
 "oder 'git help <Konzept>', um mehr über einen spezifischen Befehl oder\n"
 "Konzept zu erfahren."
 
 #: http.c:342
-#, fuzzy
 msgid "Delegation control is not supported with cURL < 7.22.0"
-msgstr ""
-"Das Anheften des öffentlichen Schlüssels wird mit cURL < 7.44.0\n"
-"nicht unterstützt."
+msgstr "Kontrolle über Delegation wird mit cURL < 7.22.0 nicht unterstützt"
 
 #: http.c:351
 msgid "Public key pinning not supported with cURL < 7.44.0"
 msgstr ""
 "Das Anheften des öffentlichen Schlüssels wird mit cURL < 7.44.0\n"
 "nicht unterstützt."
 
 #: 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
@@ -13806,25 +13816,24 @@ msgid ""
 "Error: Your local changes to the following files would be overwritten by "
 "merge"
 msgstr ""
 "Fehler Ihre lokalen Änderungen in den folgenden Dateien würden durch den "
 "Merge\n"
 "überschrieben werden"
 
 #: git-merge-octopus.sh:61
 msgid "Automated merge did not work."
 msgstr "Automatischer Merge hat nicht funktioniert."
 
 #: git-merge-octopus.sh:62
-#, fuzzy
 msgid "Should not be doing an octopus."
 msgstr "Sollte keinen Octopus-Merge ausführen."
 
 #: git-merge-octopus.sh:73
 #, sh-format
 msgid "Unable to find common commit with $pretty_name"
 msgstr "Konnte keinen gemeinsamen Commit mit $pretty_name finden."
 
 #: git-merge-octopus.sh:77
 #, sh-format
 msgid "Already up-to-date with $pretty_name"
 msgstr "Bereits aktuell mit $pretty_name"
@@ -14001,27 +14010,26 @@ msgstr "$branch_name zu $onto_name vorgespult."
 msgid "git stash clear with parameters is unimplemented"
 msgstr "git stash clear mit Parametern ist nicht implementiert"
 
 #: git-stash.sh:73
 msgid "You do not have the initial commit yet"
 msgstr "Sie haben bisher noch keinen initialen Commit"
 
 #: git-stash.sh:88
 msgid "Cannot save the current index state"
 msgstr "Kann den aktuellen Zustand des Index nicht speichern"
 
 #: git-stash.sh:103
-#, fuzzy
 msgid "Cannot save the untracked files"
-msgstr "Kann den aktuellen Zustand des Index nicht speichern"
+msgstr "Kann die unversionierten Dateien nicht speichern"
 
 #: git-stash.sh:123 git-stash.sh:136
 msgid "Cannot save the current worktree state"
 msgstr "Kann den aktuellen Zustand des Arbeitsverzeichnisses nicht speichern"
 
 #: git-stash.sh:140
 msgid "No changes selected"
 msgstr "Keine Änderungen ausgewählt"
 
 #: git-stash.sh:143
 msgid "Cannot remove temporary index (can't happen)"
 msgstr "Kann temporären Index nicht löschen (kann nicht passieren)"
@@ -14047,28 +14055,26 @@ msgstr "Kann $ref_stash nicht mit $w_commit aktualisieren."
 #. To provide a message, use git stash save -- '--blah-blah'
 #: git-stash.sh:238
 #, sh-format
 msgid ""
 "error: unknown option for 'stash save': $option\n"
 "       To provide a message, use git stash save -- '$option'"
 msgstr ""
 "Fehler: unbekannte Option für 'stash save': $option\n"
 "        Um eine Beschreibung anzugeben, benutzen Sie \"git stash save -- "
 "'$option'\""
 
 #: git-stash.sh:251
-#, fuzzy
 msgid "Can't use --patch and --include-untracked or --all at the same time"
-msgstr ""
-"Kann nicht gleichzeitig Pfade aktualisieren und zu Branch '%s' wechseln"
+msgstr "Kann nicht gleichzeitig --patch und --include-untracked oder --all verwenden"
 
 #: git-stash.sh:259
 msgid "No local changes to save"
 msgstr "Keine lokalen Änderungen zum Speichern"
 
 #: git-stash.sh:263
 msgid "Cannot initialize stash"
 msgstr "Kann \"stash\" nicht initialisieren"
 
 #: git-stash.sh:267
 msgid "Cannot save the current status"
 msgstr "Kann den aktuellen Status nicht speichern"
@@ -14119,27 +14125,26 @@ msgstr "Konnte den Index nicht aktualisieren."
 msgid "Cannot apply a stash in the middle of a merge"
 msgstr "Kann \"stash\" nicht anwenden, solang ein Merge im Gange ist"
 
 #: git-stash.sh:497
 msgid "Conflicts in index. Try without --index."
 msgstr "Konflikte im Index. Versuchen Sie es ohne --index."
 
 #: git-stash.sh:499
 msgid "Could not save index tree"
 msgstr "Konnte Index-Verzeichnis nicht speichern"
 
 #: git-stash.sh:508
-#, fuzzy
 msgid "Could not restore untracked files from stash"
-msgstr "konnte nicht von '%s' lesen"
+msgstr "Konnte unversionierte Dateien vom Stash nicht wiederherstellen"
 
 #: git-stash.sh:533
 msgid "Cannot unstage modified files"
 msgstr "Kann geänderte Dateien nicht aus dem Index entfernen"
 
 #: git-stash.sh:548
 msgid "Index was not unstashed."
 msgstr "Index wurde nicht aus dem Stash zurückgeladen."
 
 #: git-stash.sh:562
 msgid "The stash is kept in case you need it again."
 msgstr "Der Stash wird behalten, im Falle Sie benötigen diesen nochmal."
@@ -14716,57 +14721,57 @@ msgstr ""
 
 #: git-rebase--interactive.sh:1027
 #, sh-format
 msgid ""
 "Unrecognized setting $check_level for option rebase.missingCommitsCheck. "
 "Ignoring."
 msgstr ""
 "Nicht erkannte Einstellung $check_level für Option rebase."
 "missingCommitsCheck.\n"
 "Ignoriere."
 
 #: git-rebase--interactive.sh:1044
-#, fuzzy
 msgid ""
 "You can fix this with 'git rebase --edit-todo' and then run 'git rebase --"
 "continue'."
-msgstr "Sie können das mit 'git rebase --edit-todo' beheben."
+msgstr ""
+"Sie können das mit 'git rebase --edit-todo' beheben. Führen Sie danach\n"
+"'git rebase --continue' aus."
 
 #: git-rebase--interactive.sh:1045
 msgid "Or you can abort the rebase with 'git rebase --abort'."
 msgstr "Oder Sie können den Rebase mit 'git rebase --abort' abbrechen."
 
 #: git-rebase--interactive.sh:1069
 msgid "Could not remove CHERRY_PICK_HEAD"
 msgstr "Konnte CHERRY_PICK_HEAD nicht löschen"
 
 #: git-rebase--interactive.sh:1074
-#, fuzzy, sh-format
+#, sh-format
 msgid ""
 "You have staged changes in your working tree.\n"
 "If these changes are meant to be\n"
 "squashed into the previous commit, run:\n"
 "\n"
 "  git commit --amend $gpg_sign_opt_quoted\n"
 "\n"
 "If they are meant to go into a new commit, run:\n"
 "\n"
 "  git commit $gpg_sign_opt_quoted\n"
 "\n"
 "In both cases, once you're done, continue with:\n"
 "\n"
 "  git rebase --continue\n"
 msgstr ""
-"Es befinden sich zum Commit vorgemerkte Änderungen in Ihrem "
-"Arbeitsverzeichnis.\n"
+"Es befinden sich zum Commit vorgemerkte Änderungen in Ihrem Arbeitsverzeichnis.\n"
 "Wenn diese Änderungen in den vorherigen Commit aufgenommen werden sollen,\n"
 "führen Sie aus:\n"
 "\n"
 "  git commit --amend $gpg_sign_opt_quoted\n"
 "\n"
 "Wenn daraus ein neuer Commit erzeugt werden soll, führen Sie aus:\n"
 "\n"
 "  git commit $gpg_sign_opt_quoted\n"
 "\n"
 "Im Anschluss führen Sie zum Fortfahren aus:\n"
 "\n"
 "  git rebase --continue\n"
-- 
2.11.0.rc2.160.gf034b25


^ permalink raw reply related

* Re: [ANNOUNCE] Git v2.11.0-rc3
From: Johannes Sixt @ 2016-11-24 17:40 UTC (permalink / raw)
  To: Marc Branchaud, Junio C Hamano; +Cc: git
In-Reply-To: <836824f5-79e5-fbbf-dfe0-78cc19af1fb2@xiplink.com>

Am 24.11.2016 um 17:25 schrieb Marc Branchaud:
> On 2016-11-23 06:21 PM, Junio C Hamano wrote:
>>
>>  * The original command line syntax for "git merge", which was "git
>>    merge <msg> HEAD <parent>...", has been deprecated for quite some
>>    time, and "git gui" was the last in-tree user of the syntax.  This
>>    is finally fixed, so that we can move forward with the deprecation.
>
> Is this still true, given j6t's recent patch at
>
> http://public-inbox.org/git/e61cc267-a59b-3be1-29db-c49d56f521f7@kdbg.org/T/

It is still true. The git-gui shipped with 2.11 does not depend on the 
deprecated syntax. The deprecation can move forward.

In what ever way the regression will be fixed: we do not have to return 
to the deprecated syntax.

-- Hannes


^ permalink raw reply

* [PATCH] Release note spelling and phrasing fixups.
From: Marc Branchaud @ 2016-11-24 16:59 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano
In-Reply-To: <xmqqinrdlr3o.fsf@gitster.mtv.corp.google.com>

Signed-off-by: Marc Branchaud <marcnarc@xiplink.com>
---

Mostly just missing words and what I feel are clarifications.

The biggest change is to the "git add -N" item.  Not 100% sure
I got it right.

		M.

 Documentation/RelNotes/2.11.0.txt | 145 +++++++++++++++++++-------------------
 1 file changed, 72 insertions(+), 73 deletions(-)

diff --git a/Documentation/RelNotes/2.11.0.txt b/Documentation/RelNotes/2.11.0.txt
index cea2a50..de5892e 100644
--- a/Documentation/RelNotes/2.11.0.txt
+++ b/Documentation/RelNotes/2.11.0.txt
@@ -57,39 +57,40 @@ UI, Workflows & Features
 
  * Even though "git hash-objects", which is a tool to take an
    on-filesystem data stream and put it into the Git object store,
-   allowed to perform the "outside-world-to-Git" conversions (e.g.
+   can perform "outside-world-to-Git" conversions (e.g.
    end-of-line conversions and application of the clean-filter), and
-   it had the feature on by default from very early days, its reverse
+   it has had this feature on by default from very early days, its reverse
    operation "git cat-file", which takes an object from the Git object
-   store and externalize for the consumption by the outside world,
+   store and externalizes it for consumption by the outside world,
    lacked an equivalent mechanism to run the "Git-to-outside-world"
    conversion.  The command learned the "--filters" option to do so.
 
- * Output from "git diff" can be made easier to read by selecting
+ * Output from "git diff" can be made easier to read by intelligently selecting
    which lines are common and which lines are added/deleted
-   intelligently when the lines before and after the changed section
-   are the same.  A command line option is added to help with the
-   experiment to find a good heuristics.
+   when the lines before and after the changed section
+   are the same.  A command line option (--indent-heuristic) and a
+   configuration variable (diff.indentHeuristic) are added to help with the
+   experiment to find good heuristics.
 
  * In some projects, it is common to use "[RFC PATCH]" as the subject
    prefix for a patch meant for discussion rather than application.  A
-   new option "--rfc" is a short-hand for "--subject-prefix=RFC PATCH"
+   new format-patch option "--rfc" is a short-hand for "--subject-prefix=RFC PATCH"
    to help the participants of such projects.
 
- * "git add --chmod=+x <pathspec>" added recently only toggled the
+ * "git add --chmod={+,-}x <pathspec>" only changed the
    executable bit for paths that are either new or modified. This has
-   been corrected to flip the executable bit for all paths that match
+   been corrected to change the executable bit for all paths that match
    the given pathspec.
 
  * When "git format-patch --stdout" output is placed as an in-body
-   header and it uses the RFC2822 header folding, "git am" failed to
+   header and it uses RFC2822 header folding, "git am" fails to
    put the header line back into a single logical line.  The
    underlying "git mailinfo" was taught to handle this properly.
 
  * "gitweb" can spawn "highlight" to show blob contents with
    (programming) language-specific syntax highlighting, but only
    when the language is known.  "highlight" can however be told
-   to make the guess itself by giving it "--force" option, which
+   to guess the language itself by giving it "--force" option, which
    has been enabled.
 
  * "git gui" l10n to Portuguese.
@@ -109,19 +110,19 @@ UI, Workflows & Features
    history leading to nth parent was looking the other way.
 
  * In recent versions of cURL, GSSAPI credential delegation is
-   disabled by default due to CVE-2011-2192; introduce a configuration
-   to selectively allow enabling this.
+   disabled by default due to CVE-2011-2192; introduce a http.delegation
+   configuration variable to selectively allow enabling this.
    (merge 26a7b23429 ps/http-gssapi-cred-delegation later to maint).
 
  * "git mergetool" learned to honor "-O<orderfile>" to control the
    order of paths to present to the end user.
 
  * "git diff/log --ws-error-highlight=<kind>" lacked the corresponding
-   configuration variable to set it by default.
+   configuration variable (diff.wsErrorHighlight) to set it by default.
 
- * "git ls-files" learned "--recurse-submodules" option that can be
-   used to get a listing of tracked files across submodules (i.e. this
-   only works with "--cached" option, not for listing untracked or
+ * "git ls-files" learned the "--recurse-submodules" option
+   to get a listing of tracked files across submodules (i.e. this
+   only works with the "--cached" option, not for listing untracked or
    ignored files).  This would be a useful tool to sit on the upstream
    side of a pipe that is read with xargs to work on all working tree
    files from the top-level superproject.
@@ -130,7 +131,7 @@ UI, Workflows & Features
    implementations of XDG Secret Service API has been added to
    contrib/credential/.
 
- * The GPG verification status shown in "%G?" pretty format specifier
+ * The GPG verification status shown by the "%G?" pretty format specifier
    was not rich enough to differentiate a signature made by an expired
    key, a signature made by a revoked key, etc.  New output letters
    have been assigned to express them.
@@ -139,17 +140,17 @@ UI, Workflows & Features
    learned to turn "git describe" output (e.g. v2.9.3-599-g2376d31787)
    into clickable links in its output.
 
- * When new paths were added by "git add -N" to the index, it was
-   enough to circumvent the check by "git commit" to refrain from
-   making an empty commit without "--allow-empty".  The same logic
-   prevented "git status" to show such a path as "new file" in the
+ * "git commit" created an empty commit when invoked with an index
+   consisting solely of intend-to-add paths (added with "git add -N").
+   It now requires the "--allow-empty" option to create such a commit.
+   The same logic prevented "git status" from showing such paths as "new files" in the
    "Changes not staged for commit" section.
 
- * The smudge/clean filter API expect an external process is spawned
-   to filter the contents for each path that has a filter defined.  A
+ * The smudge/clean filter API spawns an external process
+   to filter the contents of each path that has a filter defined.  A
    new type of "process" filter API has been added to allow the first
    request to run the filter for a path to spawn a single process, and
-   all filtering need is served by this single process for multiple
+   all filtering is served by this single process for multiple
    paths, reducing the process creation overhead.
 
  * The user always has to say "stash@{$N}" when naming a single
@@ -173,7 +174,7 @@ Performance, Internal Implementation, Development Support etc.
    script file "git am" internally uses.
    (merge a77598e jc/am-read-author-file later to maint).
 
- * Lifts calls to exit(2) and die() higher in the callchain in
+ * Lift calls to exit(2) and die() higher in the callchain in
    sequencer.c files so that more helper functions in it can be used
    by callers that want to handle error conditions themselves.
 
@@ -192,13 +193,13 @@ Performance, Internal Implementation, Development Support etc.
    does not advertise any refs, but "git fetch" was not prepared to
    see such an advertisement.  When the other side disconnects without
    giving any ref advertisement, we used to say "there may not be a
-   repository at that URL", but we may have seen other advertisement
+   repository at that URL", but we may have seen other advertisements
    like "shallow" and ".have" in which case we definitely know that a
    repository is there.  The code to detect this case has also been
    updated.
 
  * Some codepaths in "git pack-objects" were not ready to use an
-   existing pack bitmap; now they are and as the result they have
+   existing pack bitmap; now they are and as a result they have
    become faster.
 
  * The codepath in "git fsck" to detect malformed tree objects has
@@ -214,7 +215,7 @@ Performance, Internal Implementation, Development Support etc.
    packfile first.
    (merge c9af708b1a jk/pack-objects-optim-mru later to maint).
 
- * Codepaths involved in interacting alternate object store have
+ * Codepaths involved in interacting alternate object stores have
    been cleaned up.
 
  * In order for the receiving end of "git push" to inspect the
@@ -222,7 +223,7 @@ Performance, Internal Implementation, Development Support etc.
    from the sending end need to be made available to the hook and
    the mechanism for the connectivity check, and this was done
    traditionally by storing the objects in the receiving repository
-   and letting "git gc" to expire it.  Instead, store the newly
+   and letting "git gc" expire them.  Instead, store the newly
    received objects in a temporary area, and make them available by
    reusing the alternate object store mechanism to them only while we
    decide if we accept the check, and once we decide, either migrate
@@ -237,7 +238,7 @@ Performance, Internal Implementation, Development Support etc.
    replaced with a priority queue.
 
  * "git diff --no-index" codepath has been updated not to try to peek
-   into .git/ directory that happens to be under the current
+   into a .git/ directory that happens to be under the current
    directory, when we know we are operating outside any repository.
 
  * Update of the sequencer codebase to make it reusable to reimplement
@@ -251,8 +252,8 @@ Performance, Internal Implementation, Development Support etc.
    holding onto them.  Use O_CLOEXEC flag to open files in various
    codepaths.
 
- * Update "interpret-trailers" machinery and teaches it that people in
-   real world write all sorts of crufts in the "trailer" that was
+ * Update "interpret-trailers" machinery and teach it that people in
+   the real world write all sorts of cruft in the "trailer" that was
    originally designed to have the neat-o "Mail-Header: like thing"
    and nothing else.
 
@@ -280,7 +281,7 @@ notes for details).
    has been removed.
 
  * Having a submodule whose ".git" repository is somehow corrupt
-   caused a few commands that recurse into submodules loop forever.
+   caused a few commands that recurse into submodules to loop forever.
 
  * "git symbolic-ref -d HEAD" happily removes the symbolic ref, but
    the resulting repository becomes an invalid one.  Teach the command
@@ -308,12 +309,12 @@ notes for details).
    forgot to update "git gui" to look at the configuration to match
    this change.
 
- * "git add --chmod=+x" added recently lacked documentation, which has
+ * "git add --chmod={+,-}x" added recently lacked documentation, which has
    been corrected.
 
  * "git log --cherry-pick" used to include merge commits as candidates
    to be matched up with other commits, resulting a lot of wasted time.
-   The patch-id generation logic has been updated to ignore merges to
+   The patch-id generation logic has been updated to ignore merges and
    avoid the wastage.
 
  * The http transport (with curl-multi option, which is the default
@@ -333,20 +334,20 @@ notes for details).
    line of the next one.  This process may have to merge two adjacent
    hunks, but the code forgot to do so in some cases.
 
- * Performance tests done via "t/perf" did not use the same set of
+ * Performance tests done via "t/perf" did not use the right
    build configuration if the user relied on autoconf generated
    configuration.
 
  * "git format-patch --base=..." feature that was recently added
-   showed the base commit information after "-- " e-mail signature
+   showed the base commit information after the "-- " e-mail signature
    line, which turned out to be inconvenient.  The base information
    has been moved above the signature line.
 
  * More i18n.
 
  * Even when "git pull --rebase=preserve" (and the underlying "git
-   rebase --preserve") can complete without creating any new commit
-   (i.e. fast-forwards), it still insisted on having a usable ident
+   rebase --preserve") can complete without creating any new commits
+   (i.e. fast-forwards), it still insisted on having usable ident
    information (read: user.email is set correctly), which was less
    than nice.  As the underlying commands used inside "git rebase"
    would fail with a more meaningful error message and advice text
@@ -396,7 +397,7 @@ notes for details).
  * Documentation around tools to import from CVS was fairly outdated.
 
  * "git clone --recurse-submodules" lost the progress eye-candy in
-   recent update, which has been corrected.
+   a recent update, which has been corrected.
 
  * A low-level function verify_packfile() was meant to show errors
    that were detected without dying itself, but under some conditions
@@ -409,23 +410,23 @@ notes for details).
    to a design bug, which has been fixed.
 
  * In the codepath that comes up with the hostname to be used in an
-   e-mail when the user didn't tell us, we looked at ai_canonname
+   e-mail when the user didn't tell us, we looked at the ai_canonname
    field in struct addrinfo without making sure it is not NULL first.
 
  * "git worktree", even though it used the default_abbrev setting that
-   ought to be affected by core.abbrev configuration variable, ignored
+   ought to be affected by the core.abbrev configuration variable, ignored
    the variable setting.  The command has been taught to read the
    default set of configuration variables to correct this.
 
  * "git init" tried to record core.worktree in the repository's
-   'config' file when GIT_WORK_TREE environment variable was set and
+   'config' file when the GIT_WORK_TREE environment variable was set and
    it was different from where GIT_DIR appears as ".git" at its top,
    but the logic was faulty when .git is a "gitdir:" file that points
    at the real place, causing trouble in working trees that are
    managed by "git worktree".  This has been corrected.
 
  * Codepaths that read from an on-disk loose object were too loose in
-   validating what they are reading is a proper object file and
+   validating that they are reading a proper object file and
    sometimes read past the data they read from the disk, which has
    been corrected.  H/t to Gustavo Grieco for reporting.
 
@@ -434,8 +435,8 @@ notes for details).
    time, and "git gui" was the last in-tree user of the syntax.  This
    is finally fixed, so that we can move forward with the deprecation.
 
- * An author name, that spelled a backslash-quoted double quote in the
-   human readable part "My \"double quoted\" name", was not unquoted
+ * An author name that has a backslash-quoted double quote in the
+   human readable part ("My \"double quoted\" name"), was not unquoted
    correctly while applying a patch from a piece of e-mail.
 
  * Doc update to clarify what "log -3 --reverse" does.
@@ -449,11 +450,10 @@ notes for details).
    has been fixed; this did not affect any existing code as nobody
    tried to write anything after the padding on such a line, though.
 
- * The code that parses the format parameter of for-each-ref command
+ * The code that parses the format parameter of the for-each-ref command
    has seen a micro-optimization.
 
- * When we started cURL to talk to imap server when a new enough
-   version of cURL library is available, we forgot to explicitly add
+ * When we started to use cURL to talk to an imap server, we forgot to explicitly add
    imap(s):// before the destination.  To some folks, that didn't work
    and the library tried to make HTTP(s) requests instead.
 
@@ -474,13 +474,12 @@ notes for details).
    "Give me only the history since that version".
    (merge cccf74e2da nd/shallow-deepen later to maint).
 
- * It is a common mistake to say "git blame --reverse OLD path",
-   expecting that the command line is dwimmed as if asking how lines
+ * "git blame --reverse OLD path" is now DWIMmed to show how lines
    in path in an old revision OLD have survived up to the current
    commit.
    (merge e1d09701a4 jc/blame-reverse later to maint).
 
- * http.emptyauth configuration is a way to allow an empty username to
+ * The http.emptyauth configuration variable is a way to allow an empty username to
    pass when attempting to authenticate using mechanisms like
    Kerberos.  We took an unspecified (NULL) username and sent ":"
    (i.e. no username, no password) to CURLOPT_USERPWD, but did not do
@@ -494,19 +493,19 @@ notes for details).
    -p <paths>" adds to the current contents of the index to come up
    with what to commit.
 
- * A stray symbolic link in $GIT_DIR/refs/ directory could make name
+ * A stray symbolic link in the $GIT_DIR/refs/ directory could make name
    resolution loop forever, which has been corrected.
 
  * The "submodule.<name>.path" stored in .gitmodules is never copied
    to .git/config and such a key in .git/config has no meaning, but
-   the documentation described it and submodule.<name>.url next to
-   each other as if both belong to .git/config.  This has been fixed.
+   the documentation described it next to submodule.<name>.url
+   as if both belong to .git/config.  This has been fixed.
 
- * In a worktree connected to a repository elsewhere, created via "git
+ * In a worktree created via "git
    worktree", "git checkout" attempts to protect users from confusion
    by refusing to check out a branch that is already checked out in
    another worktree.  However, this also prevented checking out a
-   branch, which is designated as the primary branch of a bare
+   branch which is designated as the primary branch of a bare
    reopsitory, in a worktree that is connected to the bare
    repository.  The check has been corrected to allow it.
 
@@ -515,7 +514,7 @@ notes for details).
 
  * When fetching from a remote that has many tags that are irrelevant
    to branches we are following, we used to waste way too many cycles
-   when checking if the object pointed at by a tag (that we are not
+   checking if the object pointed at by a tag (that we are not
    going to fetch!) exists in our repository too carefully.
 
  * Protect our code from over-eager compilers.
@@ -524,27 +523,27 @@ notes for details).
    "." instead of the branch name; the documentation has been updated
    to describe it.
 
- * A hot-fix for a test added by a recent topic that went to both
+ * Hot-fixed a test added by a recent topic that went to both
    'master' and 'maint' already.
 
  * "git send-email" attempts to pick up valid e-mails from the
-   trailers, but people in real world write non-addresses there, like
+   trailers, but people in the real world write non-addresses there, like
    "Cc: Stable <add@re.ss> # 4.8+", which broke the output depending
-   on the availability and vintage of Mail::Address perl module.
+   on the availability and vintage of the Mail::Address perl module.
    (merge dcfafc5214 mm/send-email-cc-cruft-after-address later to maint).
 
- * The Travis CI configuration we ship ran the tests with --verbose
+ * The Travis CI configuration we ship ran the tests with the --verbose
    option but this risks non-TAP output that happens to be "ok" to be
    misinterpreted as TAP signalling a test that passed.  This resulted
-   in unnecessary failure.  This has been corrected by introducing a
+   in unnecessary failures.  This has been corrected by introducing a
    new mode to run our tests in the test harness to send the verbose
    output separately to the log file.
 
- * Some AsciiDoc formatter mishandles a displayed illustration with
+ * Some AsciiDoc formatters mishandle a displayed illustration with
    tabs in it.  Adjust a few of them in merge-base documentation to
    work around them.
 
- * A minor regression fix for "git submodule" that was introduced
+ * Fixed a minor regression in "git submodule" that was introduced
    when more helper functions were reimplemented in C.
    (merge 77b63ac31e sb/submodule-ignore-trailing-slash later to maint).
 
@@ -553,19 +552,19 @@ notes for details).
    theoretical world.
    (merge bb84735c80 rs/ring-buffer-wraparound later to maint).
 
- * "git daemon" used fixed-length buffers to turn URL to the
+ * "git daemon" used fixed-length buffers to turn URLs to the
    repository the client asked for into the server side directory
-   path, using snprintf() to avoid overflowing these buffers, but
+   paths, using snprintf() to avoid overflowing these buffers, but
    allowed possibly truncated paths to the directory.  This has been
-   tightened to reject such a request that causes overlong path to be
-   required to serve.
+   tightened to reject such a request that causes an overlong path to be
+   served.
    (merge 6bdb0083be jk/daemon-path-ok-check-truncation later to maint).
 
  * Recent update to git-sh-setup (a library of shell functions that
    are used by our in-tree scripted Porcelain commands) included
    another shell library git-sh-i18n without specifying where it is,
    relying on the $PATH.  This has been fixed to be more explicit by
-   prefixing $(git --exec-path) output in front.
+   prefixing with $(git --exec-path) output.
    (merge 1073094f30 ak/sh-setup-dot-source-i18n-fix later to maint).
 
  * Fix for a racy false-positive test failure.
@@ -578,7 +577,7 @@ notes for details).
    caused the command to segfault when on an unborn branch.
    (merge 84679d470d jc/for-each-ref-head-segfault-fix later to maint).
 
- * "git rebase -i" did not work well with core.commentchar
+ * "git rebase -i" did not work well with the core.commentchar
    configuration variable for two reasons, both of which have been
    fixed.
    (merge 882cd23777 js/rebase-i-commentchar-fix later to maint).
-- 
2.10.2


^ permalink raw reply related

* Re: [ANNOUNCE] Git v2.11.0-rc3
From: Marc Branchaud @ 2016-11-24 16:25 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <xmqqinrdlr3o.fsf@gitster.mtv.corp.google.com>

On 2016-11-23 06:21 PM, Junio C Hamano wrote:
>
>  * The original command line syntax for "git merge", which was "git
>    merge <msg> HEAD <parent>...", has been deprecated for quite some
>    time, and "git gui" was the last in-tree user of the syntax.  This
>    is finally fixed, so that we can move forward with the deprecation.

Is this still true, given j6t's recent patch at

http://public-inbox.org/git/e61cc267-a59b-3be1-29db-c49d56f521f7@kdbg.org/T/

?

		M.


^ 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