Git development
 help / color / mirror / Atom feed
* Re: [PATCH] terminology tweak: prune -> path limiting
From: Junio C Hamano @ 2018-12-09  1:52 UTC (permalink / raw)
  To: Matthew DeVore; +Cc: git, jrn, matvore, dstolee, pclouds, peff
In-Reply-To: <xmqqo99v5vnc.fsf@gitster-ct.c.googlers.com>

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

> AFAIK, "prune" is also used to describe unreachable loose objects,

s/describe/& the act of culling/

> but that use is fairly isolated and have little risk of being
> confusing too much.  Are there other uses to make you consider it
> "highly overloaded"?

^ permalink raw reply

* Re: [PATCH] fetch: ensure submodule objects fetched
From: Junio C Hamano @ 2018-12-09  1:57 UTC (permalink / raw)
  To: Stefan Beller; +Cc: jonathantanmy, git
In-Reply-To: <20181206212655.145586-1-sbeller@google.com>

Stefan Beller <sbeller@google.com> writes:

> Currently when git-fetch is asked to recurse into submodules, it dispatches
> a plain "git-fetch -C <submodule-dir>" (with some submodule related options
> such as prefix and recusing strategy, but) without any information of the
> remote or the tip that should be fetched.
>
> But this default fetch is not sufficient, as a newly fetched commit in
> the superproject could point to a commit in the submodule that is not
> in the default refspec. This is common in workflows like Gerrit's.
> When fetching a Gerrit change under review (from refs/changes/??), the
> commits in that change likely point to submodule commits that have not
> been merged to a branch yet.
>
> Fetch a submodule object by id if the object that the superproject
> points to, cannot be found. For now this object is fetched from the
> 'origin' remote as we defer getting the default remote to a later patch.
>
> A list of new submodule commits are already generated in certain
> conditions (by check_for_new_submodule_commits()); this new feature
> invokes that function in more situations.
>
> The submodule checks were done only when a ref in the superproject
> changed, these checks were extended to also be performed when fetching
> into FETCH_HEAD for completeness, and add a test for that too.
>
> Signed-off-by: Stefan Beller <sbeller@google.com>
> ---
>
> Thanks Jonathan for the review!
> So it looks like only the last patch needs some improvements,
> which is why I'd only resend the last patch here.
> Also note the test with interious superproject commits.

Sorry, can't parse the last sentence.

Anyway, will replace the last step with this.  Thanks.


^ permalink raw reply

* Re: Documentation: update "man git-add" to include "[]"
From: Junio C Hamano @ 2018-12-09  2:07 UTC (permalink / raw)
  To: Robert P. J. Day; +Cc: Git Mailing list
In-Reply-To: <alpine.LFD.2.21.1812080958180.26244@localhost.localdomain>

"Robert P. J. Day" <rpjday@crashcourse.ca> writes:

> Current "man git-add" emphasizes single letter interactive
> shortcut commands with "[]".

Not for me.  These prefixes are instead painted in colors.

^ permalink raw reply

* Re: [PATCH v3 2/3] commit-graph: fix buffer read-overflow
From: Junio C Hamano @ 2018-12-09  4:01 UTC (permalink / raw)
  To: Josh Steadmon; +Cc: git, stolee, avarab, peff
In-Reply-To: <675d58ecea2f315bd05d2a21f6a473e9de1105a0.1544221121.git.steadmon@google.com>

Josh Steadmon <steadmon@google.com> writes:

> diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
> index 5fe21db99f..5b6b44b78e 100755
> --- a/t/t5318-commit-graph.sh
> +++ b/t/t5318-commit-graph.sh
> @@ -366,24 +366,30 @@ GRAPH_OCTOPUS_DATA_OFFSET=$(($GRAPH_COMMIT_DATA_OFFSET + \
>  GRAPH_BYTE_OCTOPUS=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4))
>  GRAPH_BYTE_FOOTER=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4 * $NUM_OCTOPUS_EDGES))
>  
> -# usage: corrupt_graph_and_verify <position> <data> <string>
> +# usage: corrupt_graph_and_verify <position> <data> <string> [<zero_pos>]
>  # Manipulates the commit-graph file at the position
> -# by inserting the data, then runs 'git commit-graph verify'
> +# by inserting the data, optionally zeroing the file
> +# starting at <zero_pos>, then runs 'git commit-graph verify'
>  # and places the output in the file 'err'. Test 'err' for
>  # the given string.
>  corrupt_graph_and_verify() {
>  	pos=$1
>  	data="${2:-\0}"
>  	grepstr=$3
> +	orig_size=$(stat --format=%s $objdir/info/commit-graph)

"stat(1)" is not so portable, so you'll get complaints from minority
platform users later.  So is "truncate(1)".

> +	zero_pos=${4:-${orig_size}}
>  	cd "$TRASH_DIRECTORY/full" &&
>  	test_when_finished mv commit-graph-backup $objdir/info/commit-graph &&
>  	cp $objdir/info/commit-graph commit-graph-backup &&
>  	printf "$data" | dd of="$objdir/info/commit-graph" bs=1 seek="$pos" conv=notrunc &&
> +	truncate --size=$zero_pos $objdir/info/commit-graph &&
> +	truncate --size=$orig_size $objdir/info/commit-graph &&
>  	test_must_fail git commit-graph verify 2>test_err &&
>  	grep -v "^+" test_err >err
>  	test_i18ngrep "$grepstr" err
>  }
>  
> +
>  test_expect_success 'detect bad signature' '
>  	corrupt_graph_and_verify 0 "\0" \
>  		"graph signature"
> @@ -484,6 +490,11 @@ test_expect_success 'detect invalid checksum hash' '
>  		"incorrect checksum"
>  '
>  
> +test_expect_success 'detect incorrect chunk count' '
> +	corrupt_graph_and_verify $GRAPH_BYTE_CHUNK_COUNT "\xff" \

Implementations of printf(1) may not grok "\xff" as a valid
representation of "\377".  The shell built-in of dash(1) for example
would not work with this.

> +		"chunk lookup table entry missing" $GRAPH_CHUNK_LOOKUP_OFFSET
> +'
> +
>  test_expect_success 'git fsck (checks commit-graph)' '
>  	cd "$TRASH_DIRECTORY/full" &&
>  	git fsck &&

^ permalink raw reply

* [GIT PULL] l10n updates for 2.20.0 round 3
From: Jiang Xin @ 2018-12-09  4:04 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git List, Alexander Shopov, Jordi Mas, Ralf Thielow,
	Christopher Díaz, Jean-Noël Avila, Marco Paolone,
	Gwan-gyeong Mun, Vasco Almeida, Dimitriy Ryazantcev,
	Peter Krefting, Trần Ngọc Quân, Jiang Xin,
	Christopher Diaz Riveros, Minh Nguyen

Hi Junio,

Please pull the following git l10n updates for Git 2.20.0.

The following changes since commit 8a0ba68f6dab2c8b1f297a0d46b710bb9af3237a:

  Git 2.20-rc2 (2018-12-01 21:44:56 +0900)

are available in the Git repository at:

  git@github.com:git-l10n/git-po.git tags/l10n-2.20.0-rnd3

for you to fetch changes up to 0688c551a3e0f812e2153b716b9674da5914122c:

  l10n: de.po: fix two messages (2018-12-07 19:43:07 +0100)

----------------------------------------------------------------
l10n-2.20.0-rnd3

----------------------------------------------------------------
Alexander Shopov (3):
      l10n: bg.po: Updated Bulgarian translation (4185t)
      l10n: bg.po: Updated Bulgarian translation (4185t)
      l10n: bg.po: Updated Bulgarian translation (4187t)

Christopher Díaz Riveros (2):
      l10n: es.po v2.20.0 round 1
      l10n: es.po v2.20.0 round 3

Jean-Noël Avila (2):
      l10n: fr.po v2.20 rnd 1
      l10n: fr.po v2.20.0 round 3

Jiang Xin (16):
      l10n: zh_CN: review for git v2.19.0 l10n
      Merge branch 'master' of https://github.com/Softcatala/git-po
      l10n: git.pot: v2.20.0 round 1 (254 new, 27 removed)
      Merge branch 'master' of git://github.com/git-l10n/git-po
      Merge branch 'fr_2.20_rnd1' of git://github.com/jnavila/git
      Merge branch 'master' of git://github.com/nafmo/git-l10n-sv
      Merge branch 'master' of git://github.com/alshopov/git-po
      Merge branch 'master' of git://github.com/git-l10n/git-po
      l10n: git.pot: v2.20.0 round 2 (2 new, 2 removed)
      Merge branch 'master' of https://github.com/vnwildman/git
      Merge branch 'master' of git://github.com/git-l10n/git-po
      l10n: git.pot: v2.20.0 round 3 (5 new, 3 removed)
      Merge branch 'master' of https://github.com/vnwildman/git
      Merge branch 'fr_2.20_round3' of git://github.com/jnavila/git
      Merge branch 'master' of git://github.com/alshopov/git-po
      l10n: zh_CN: for git v2.20.0 l10n round 1 to 3

Jordi Mas (2):
      l10n: Update Catalan translation
      l10n: Update Catalan translation

Minh Nguyen (1):
      l10n: vi.po: fix typo in pack-objects

Peter Krefting (2):
      l10n: sv.po: Update Swedish translation (4185t0f0u)
      l10n: sv.po: Update Swedish translation (4187t0f0u)

Ralf Thielow (3):
      l10n: update German translation
      l10n: update German translation
      l10n: de.po: fix two messages

Trần Ngọc Quân (2):
      l10n: vi(4185t): Updated Vietnamese translation for v2.20.0
      l10n: vi(4187t): Updated Vietnamese translation for v2.20.0 rd3

 po/bg.po    |  7398 ++++++++++++++++-------------
 po/ca.po    | 14723 +++++++++++++++++++++++++++++++++++++---------------------
 po/de.po    | 10702 ++++++++++++++++++++++++++++--------------
 po/es.po    |  7642 +++++++++++++++++-------------
 po/fr.po    |  7344 +++++++++++++++++------------
 po/git.pot  |  7243 +++++++++++++++++------------
 po/sv.po    |  7324 +++++++++++++++++------------
 po/vi.po    |  7357 +++++++++++++++++------------
 po/zh_CN.po |  7422 ++++++++++++++++-------------
 9 files changed, 46477 insertions(+), 30678 deletions(-)

--
Jiang Xin

^ permalink raw reply

* Re: [GIT PULL] l10n updates for 2.20.0 round 3
From: Junio C Hamano @ 2018-12-09  4:09 UTC (permalink / raw)
  To: Jiang Xin
  Cc: Git List, Alexander Shopov, Jordi Mas, Ralf Thielow,
	Christopher Díaz, Jean-Noël Avila, Marco Paolone,
	Gwan-gyeong Mun, Vasco Almeida, Dimitriy Ryazantcev,
	Peter Krefting, Trần Ngọc Quân,
	Christopher Diaz Riveros, Minh Nguyen
In-Reply-To: <CANYiYbF07DNC=UMm5zKJwzGFyo8UY-Auh+K3khFjCNOftV2KyQ@mail.gmail.com>

Jiang Xin <worldhello.net@gmail.com> writes:

> Please pull the following git l10n updates for Git 2.20.0.
>
> The following changes since commit 8a0ba68f6dab2c8b1f297a0d46b710bb9af3237a:
>
>   Git 2.20-rc2 (2018-12-01 21:44:56 +0900)
>
> are available in the Git repository at:
>
>   git@github.com:git-l10n/git-po.git tags/l10n-2.20.0-rnd3
>
> for you to fetch changes up to 0688c551a3e0f812e2153b716b9674da5914122c:
>
>   l10n: de.po: fix two messages (2018-12-07 19:43:07 +0100)

Thanks, will do.



^ permalink raw reply

* What's cooking in git.git (Dec 2018, #01; Sun, 9)
From: Junio C Hamano @ 2018-12-09  8:42 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.  The ones marked with '.' do not appear in any of
the integration branches, but I am still holding onto them.

Git 2.20 has been tagged.  I'd expect that we would slow down to see
how stable it is and queue only the brown-paper-bag fixes for a week
or so, before opening the tree for the next cycle, rewinding the tip
of 'next', etc.

You can find the changes described here in the integration branches
of the repositories listed at

    http://git-blame.blogspot.com/p/git-public-repositories.html

--------------------------------------------------
[Graduated to "master"]

* ab/push-example-in-doc (2018-11-14) 1 commit
  (merged to 'next' on 2018-11-18 at 8fd935a19c)
 + push: change needlessly ambiguous example in error

 An error message that sugggests how to give correct arguments to
 "git push" has been updated.


* ab/replace-graft-with-replace-advice (2018-11-29) 1 commit
  (merged to 'next' on 2018-11-30 at c5d658e075)
 + advice: don't pointlessly suggest --convert-graft-file

 The advice message to tell the user to migrate an existing graft
 file to the replace system when a graft file was read was shown
 even when "git replace --convert-graft-file" command, which is the
 way the message suggests to use, was running, which made little
 sense.


* gh/diff-raw-has-no-ellipses (2018-11-26) 1 commit
  (merged to 'next' on 2018-11-29 at 24a7536f15)
 + doc: update diff-format.txt for removed ellipses in --raw

 "git diff --raw" lost ellipses to adjust the output columns for
 some time now, but the documentation still showed them.


* jc/format-patch-range-diff-fix (2018-11-30) 1 commit
  (merged to 'next' on 2018-11-30 at 26290b1ec1)
 + format-patch: do not let its diff-options affect --range-diff

 "git format-patch --range-diff" by mistake passed the diff options
 used to generate the primary output of the command to the
 range-diff machinery, which caused the range-diff in the cover
 letter to include fairly useless "--stat" output.  This has been
 corrected by forcing a non-customizable default formatting options
 on the range-diff machinery when driven by format-patch.


* js/rebase-reflog-action-fix (2018-11-30) 1 commit
  (merged to 'next' on 2018-11-30 at 93fd2fb920)
 + rebase: fix GIT_REFLOG_ACTION regression

 "git rebase" reimplemented recently in C accidentally changed the
 way reflog entries are recorded (earlier "rebase -i" identified the
 entries it leaves with "rebase -i", but the new version always
 marks them with "rebase").  This has been corrected.


* js/rebase-stat-unrelated-fix (2018-11-30) 1 commit
  (merged to 'next' on 2018-11-30 at a9faaff8c1)
 + rebase --stat: fix when rebasing to an unrelated history

 "git rebase --stat" to transplant a piece of history onto a totally
 unrelated history were not working before and silently showed wrong
 result.  With the recent reimplementation in C, it started to instead
 die with an error message, as the original logic was not prepared
 to cope with this case.  This has now been fixed.


* ma/reset-doc-rendering-fix (2018-11-29) 2 commits
  (merged to 'next' on 2018-11-30 at be718c19e2)
 + git-reset.txt: render literal examples as monospace
 + git-reset.txt: render tables correctly under Asciidoctor

 Doc updates.


* rt/rebase-in-c-message-fix (2018-12-01) 1 commit
  (merged to 'next' on 2018-12-01 at 4428c15a66)
 + builtin/rebase.c: remove superfluous space in messages


* sg/daemon-test-signal-fix (2018-11-27) 1 commit
  (merged to 'next' on 2018-11-30 at b3f7fdf727)
 + t/lib-git-daemon: fix signal checking

 Test fix.


* sg/test-BUG (2018-11-20) 1 commit
  (merged to 'next' on 2018-11-21 at bb81013952)
 + tests: send "bug in the test script" errors to the script's stderr

 test framework has been updated to make a bug in the test script
 (as opposed to bugs in Git that are discovered by running the
 tests) stand out more prominently.


* sg/test-cmp-rev (2018-11-20) 1 commit
  (merged to 'next' on 2018-11-21 at 5d65cb2a76)
 + test-lib-functions: make 'test_cmp_rev' more informative on failure

 Test framework update.


* ss/msvc-strcasecmp (2018-11-20) 1 commit
  (merged to 'next' on 2018-11-21 at 9e45649e6e)
 + msvc: directly use MS version (_stricmp) of strcasecmp

 MSVC update.

--------------------------------------------------
[New Topics]

* cb/openbsd-allows-reading-directory (2018-12-03) 1 commit
 - config.mak.uname: OpenBSD uses BSD semantics with fread for directories

 BSD port update.

 Will merge to 'next'.


* cb/t5004-empty-tar-archive-fix (2018-12-03) 1 commit
 - t5004: avoid using tar for empty packages

 BSD port update.

 Will merge to 'next'.


* cb/test-lint-cp-a (2018-12-03) 1 commit
 - tests: add lint for non portable cp -a

 BSD port update.

 Will merge to 'next'.


* hb/t0061-dot-in-path-fix (2018-12-03) 1 commit
 - t0061: do not fail test if '.' is part of $PATH

 Test update.

 Will merge to 'next'.


* hn/highlight-sideband-keywords (2018-12-04) 1 commit
 - sideband: color lines with keyword only

 Lines that begin with a certain keyword that come over the wire, as
 well as lines that consist only of one of these keywords, ought to
 be painted in color for easier eyeballing, but the latter was
 broken ever since the feature was introduced in 2.19, which has
 been corrected.

 Will merge to 'next'.


* js/commit-graph-chunk-table-fix (2018-12-09) 4 commits
 - SQUASH???
 - Makefile: correct example fuzz build
 - commit-graph: fix buffer read-overflow
 - commit-graph, fuzz: add fuzzer for commit-graph

 The codepath to read from the commit-graph file attempted to read
 past the end of it when the file's table-of-contents was corrupt.


* jt/get-reference-with-commit-graph (2018-12-06) 1 commit
 - revision: use commit graph in get_reference()
 (this branch uses sb/more-repo-in-api.)

 Micro-optimize the code that prepares commit objects to be walked
 by "git rev-list" when the commit-graph is available.

 Will merge to 'next'.


* md/exclude-promisor-objects-fix-cleanup (2018-12-06) 1 commit
 - revision.c: put promisor option in specialized struct

 Code clean-up.

 Will merge to 'next'.


* bw/mailmap (2018-12-09) 1 commit
 - mailmap: update Brandon Williams's email address

 Will merge to 'next'.


* do/gitweb-strict-export-conf-doc (2018-12-09) 1 commit
 - docs: fix $strict_export text in gitweb.conf.txt

 Doc update.

 Will merge to 'next'.


* en/directory-renames-nothanks-doc-update (2018-12-09) 1 commit
 - git-rebase.txt: update note about directory rename detection and am

 Doc update.

 Will merge to 'next'.


* fd/gitweb-snapshot-conf-doc-fix (2018-12-09) 1 commit
 - docs/gitweb.conf: config variable typo

 Doc update.

 Will merge to 'next'.


* km/rebase-doc-typofix (2018-12-09) 1 commit
 - rebase docs: drop stray word in merge command description

 Doc update.

 Will merge to 'next'.


* nd/indentation-fix (2018-12-09) 1 commit
 - Indent code with TABs

 Code cleanup.

 Will merge to 'next'.


* tb/use-common-win32-pathfuncs-on-cygwin (2018-12-09) 1 commit
 - git clone <url> C:\cygwin\home\USER\repo' is working (again)

 Cygwin update.

 Will merge to 'next'.

--------------------------------------------------
[Stalled]

* lt/date-human (2018-07-09) 1 commit
 - Add 'human' date format

 A new date format "--date=human" that morphs its output depending
 on how far the time is from the current time has been introduced.
 "--date=auto" can be used to use this new format when the output is
 goint to the pager or to the terminal and otherwise the default
 format.

--------------------------------------------------
[Cooking]

* mk/http-backend-kill-children-before-exit (2018-11-26) 1 commit
  (merged to 'next' on 2018-11-29 at bf2d45062f)
 + http-backend: enable cleaning up forked upload/receive-pack on exit

 The http-backend CGI process did not correctly clean up the child
 processes it spawns to run upload-pack etc. when it dies itself,
 which has been corrected.

 Will cook in 'next'.


* tb/log-G-binary (2018-11-29) 1 commit
 - log -G: ignore binary files

 "git log -G<regex>" looked for a hunk in the "git log -p" patch
 output that contained a string that matches the given pattern.
 Optimize this code to ignore binary files, which by default will
 not show any hunk that would match any pattern (unless textconv or
 the --text option is in effect, that is).

 Expecting an update to the tests.


* dl/merge-cleanup-scissors-fix (2018-11-21) 2 commits
  (merged to 'next' on 2018-11-21 at 217be06acb)
 + merge: add scissors line on merge conflict
 + t7600: clean up 'merge --squash c3 with c7' test

 The list of conflicted paths shown in the editor while concluding a
 conflicted merge was shown above the scissors line when the
 clean-up mode is set to "scissors", even though it was commented
 out just like the list of updated paths and other information to
 help the user explain the merge better.

 Will cook in 'next'.


* aw/pretty-trailers (2018-12-09) 7 commits
 - pretty: add support for separator option in %(trailers)
 - strbuf: separate callback for strbuf_expand:ing literals
 - pretty: add support for "valueonly" option in %(trailers)
 - pretty: allow showing specific trailers
 - pretty: single return path in %(trailers) handling
 - pretty: allow %(trailers) options with explicit value
 - doc: group pretty-format.txt placeholders descriptions

 The %(trailers) formatter in "git log --format=..."  now allows to
 optionally pick trailers selectively by keyword, show only values,
 etc.

 How's the doneness of this one?


* nd/attr-pathspec-in-tree-walk (2018-11-19) 5 commits
 - tree-walk: support :(attr) matching
 - dir.c: move, rename and export match_attrs()
 - pathspec.h: clean up "extern" in function declarations
 - tree-walk.c: make tree_entry_interesting() take an index
 - tree.c: make read_tree*() take 'struct repository *'

 The traversal over tree objects has learned to honor
 ":(attr:label)" pathspec match, which has been implemented only for
 enumerating paths on the filesystem.

 Will merge to 'next'.


* ab/commit-graph-progress-fix (2018-11-20) 1 commit
 - commit-graph: split up close_reachable() progress output

 Will merge to 'next'.


* jn/unknown-index-extensions (2018-11-21) 2 commits
 - index: offer advice for unknown index extensions
 - index: do not warn about unrecognized extensions

 A bit too alarming warning given when unknown index extensions
 exist is getting revamped.

 Expecting a reroll.


* en/fast-export-import (2018-11-17) 11 commits
  (merged to 'next' on 2018-11-18 at 87bbbffc95)
 + fast-export: add a --show-original-ids option to show original names
 + fast-import: remove unmaintained duplicate documentation
 + fast-export: add --reference-excluded-parents option
 + fast-export: ensure we export requested refs
 + fast-export: when using paths, avoid corrupt stream with non-existent mark
 + fast-export: move commit rewriting logic into a function for reuse
 + fast-export: avoid dying when filtering by paths and old tags exist
 + fast-export: use value from correct enum
 + git-fast-export.txt: clarify misleading documentation about rev-list args
 + git-fast-import.txt: fix documentation for --quiet option
 + fast-export: convert sha1 to oid

 Small fixes and features for fast-export and fast-import, mostly on
 the fast-export side.

 Will cook in 'next'.


* nd/checkout-dwim-fix (2018-11-14) 1 commit
  (merged to 'next' on 2018-11-18 at 3d714e7719)
 + checkout: disambiguate dwim tracking branches and local files

 "git checkout frotz" (without any double-dash) avoids ambiguity by
 making sure 'frotz' cannot be interpreted as a revision and as a
 path at the same time.  This safety has been updated to check also
 a unique remote-tracking branch 'frotz' in a remote, when dwimming
 to create a local branch 'frotz' out of a remote-tracking branch
 'frotz' from a remote.

 Will cook in 'next'.


* nd/checkout-noisy (2018-11-20) 2 commits
 - t0027: squelch checkout path run outside test_expect_* block
 - checkout: print something when checking out paths

 "git checkout [<tree-ish>] path..." learned to report the number of
 paths that have been checked out of the index or the tree-ish,
 which gives it the same degree of noisy-ness as the case in which
 the command checks out a branch.

 Will merge to 'next'.


* sg/clone-initial-fetch-configuration (2018-11-16) 3 commits
  (merged to 'next' on 2018-11-18 at cae0f3985b)
 + Documentation/clone: document ignored configuration variables
 + clone: respect additional configured fetch refspecs during initial fetch
 + clone: use a more appropriate variable name for the default refspec

 Refspecs configured with "git -c var=val clone" did not propagate
 to the resulting repository, which has been corrected.

 Will cook in 'next'.


* en/rebase-merge-on-sequencer (2018-11-08) 2 commits
 - rebase: implement --merge via git-rebase--interactive
 - git-rebase, sequencer: extend --quiet option for the interactive machinery

 "git rebase --merge" as been reimplemented by reusing the internal
 machinery used for "git rebase -i".

 Expecting a reroll.
 cf. <CABPp-BF8RupyfP69iqAVTXxEhBGyzVd-wUgp3y0pf+CbBFAQeg@mail.gmail.com>


* fc/http-version (2018-11-09) 1 commit
  (merged to 'next' on 2018-11-18 at 42f5155095)
 + http: add support selecting http version

 The "http.version" configuration variable can be used with recent
 enough cURL library to force the version of HTTP used to talk when
 fetching and pushing.

 Will cook in 'next'.


* dl/remote-save-to-push (2018-11-13) 1 commit
 - remote: add --save-to-push option to git remote set-url

 "git remote set-url" learned a new option that moves existing value
 of the URL field to pushURL field of the remote before replacing
 the URL field with a new value.

 I am personally not yet quite convinced if this is worth pursuing.


* jk/loose-object-cache (2018-11-24) 10 commits
  (merged to 'next' on 2018-11-24 at 5f4f22707d)
 + odb_load_loose_cache: fix strbuf leak
  (merged to 'next' on 2018-11-18 at 276691a21b)
 + fetch-pack: drop custom loose object cache
 + sha1-file: use loose object cache for quick existence check
 + object-store: provide helpers for loose_objects_cache
 + sha1-file: use an object_directory for the main object dir
 + handle alternates paths the same as the main object dir
 + sha1_file_name(): overwrite buffer instead of appending
 + rename "alternate_object_database" to "object_directory"
 + submodule--helper: prefer strip_suffix() to ends_with()
 + fsck: do not reuse child_process structs

 Code clean-up with optimization for the codepath that checks
 (non-)existence of loose objects.

 Will cook in 'next'.


* js/protocol-advertise-multi (2018-11-17) 1 commit
 - protocol: advertise multiple supported versions

 The transport layer has been updated so that the protocol version
 used can be negotiated between the parties, by the initiator
 listing the protocol versions it is willing to talk, and the other
 side choosing from one of them.

 How's the doneness of this one?


* js/smart-http-detect-remote-error (2018-11-17) 3 commits
  (merged to 'next' on 2018-11-18 at 5c6edfcb85)
 + remote-curl: die on server-side errors
 + remote-curl: tighten "version 2" check for smart-http
 + remote-curl: refactor smart-http discovery

 Some errors from the other side coming over smart HTTP transport
 were not noticed, which has been corrected.

 Will cook in 'next'.


* nb/branch-show-other-worktrees-head (2018-11-12) 2 commits
 - branch: mark and colorize a branch differently if it is checked out in a linked worktree
 - ref-filter: add worktree atom

 "git branch --list" learned to show branches that are checked out
 in other worktrees connected to the same repository prefixed with
 '+', similar to the way the currently checked out branch is shown
 with '*' in front.

 Expecting a reroll.


* nd/the-index (2018-11-12) 22 commits
  (merged to 'next' on 2018-11-18 at 73d1d8594e)
 + rebase-interactive.c: remove the_repository references
 + rerere.c: remove the_repository references
 + pack-*.c: remove the_repository references
 + pack-check.c: remove the_repository references
 + notes-cache.c: remove the_repository references
 + line-log.c: remove the_repository reference
 + diff-lib.c: remove the_repository references
 + delta-islands.c: remove the_repository references
 + cache-tree.c: remove the_repository references
 + bundle.c: remove the_repository references
 + branch.c: remove the_repository reference
 + bisect.c: remove the_repository reference
 + blame.c: remove implicit dependency the_repository
 + sequencer.c: remove implicit dependency on the_repository
 + sequencer.c: remove implicit dependency on the_index
 + transport.c: remove implicit dependency on the_index
 + notes-merge.c: remove implicit dependency the_repository
 + notes-merge.c: remove implicit dependency on the_index
 + list-objects.c: reduce the_repository references
 + list-objects-filter.c: remove implicit dependency on the_index
 + wt-status.c: remove implicit dependency the_repository
 + wt-status.c: remove implicit dependency on the_index

 More codepaths become aware of working with in-core repository
 instance other than the default "the_repository".

 Will cook in 'next'.


* ot/ref-filter-object-info (2018-11-24) 6 commits
  (merged to 'next' on 2018-11-24 at f8505762e3)
 + ref-filter: replace unportable `%lld` format with %PRIdMAX
  (merged to 'next' on 2018-11-18 at ad4c086678)
 + ref-filter: add docs for new options
 + ref-filter: add tests for deltabase
 + ref-filter: add deltabase option
 + ref-filter: add tests for objectsize:disk
 + ref-filter: add objectsize:disk option

 The "--format=<placeholder>" option of for-each-ref, branch and tag
 learned to show a few more traits of objects that can be learned by
 the object_info API.

 Will cook in 'next'.


* sb/diff-color-moved-config-option-fixup (2018-11-14) 1 commit
 - diff: align move detection error handling with other options

 Minor inconsistency fix.

 Will merge to 'next'.


* ab/push-dwim-dst (2018-11-14) 7 commits
  (merged to 'next' on 2018-11-18 at 36567023be)
 + push doc: document the DWYM behavior pushing to unqualified <dst>
 + push: test that <src> doesn't DWYM if <dst> is unqualified
 + push: add an advice on unqualified <dst> push
 + push: move unqualified refname error into a function
 + push: improve the error shown on unqualified <dst> push
 + i18n: remote.c: mark error(...) messages for translation
 + remote.c: add braces in anticipation of a follow-up change

 "git push $there $src:$dst" rejects when $dst is not a fully
 qualified refname and not clear what the end user meant.  The
 codepath has been taught to give a clearer error message, and also
 guess where the push should go by taking the type of the pushed
 object into account (e.g. a tag object would want to go under
 refs/tags/).

 Will cook in 'next'.


* md/list-lazy-objects-fix (2018-12-06) 1 commit
 - list-objects.c: don't segfault for missing cmdline objects

 "git rev-list --exclude-promissor-objects" had to take an object
 that does not exist locally (and is lazily available) from the
 command line without barfing, but the code dereferenced NULL.

 Will merge to 'next'.


* nd/i18n (2018-11-12) 16 commits
  (merged to 'next' on 2018-11-18 at 5215bd2f7d)
 + fsck: mark strings for translation
 + fsck: reduce word legos to help i18n
 + parse-options.c: mark more strings for translation
 + parse-options.c: turn some die() to BUG()
 + parse-options: replace opterror() with optname()
 + repack: mark more strings for translation
 + remote.c: mark messages for translation
 + remote.c: turn some error() or die() to BUG()
 + reflog: mark strings for translation
 + read-cache.c: add missing colon separators
 + read-cache.c: mark more strings for translation
 + read-cache.c: turn die("internal error") to BUG()
 + attr.c: mark more string for translation
 + archive.c: mark more strings for translation
 + alias.c: mark split_cmdline_strerror() strings for translation
 + git.c: mark more strings for translation

 More _("i18n") markings.

 Will cook in 'next'.


* sb/more-repo-in-api (2018-11-14) 23 commits
  (merged to 'next' on 2018-11-19 at e5d2a129da)
 + t/helper/test-repository: celebrate independence from the_repository
 + path.h: make REPO_GIT_PATH_FUNC repository agnostic
 + commit: prepare free_commit_buffer and release_commit_memory for any repo
 + commit-graph: convert remaining functions to handle any repo
 + submodule: don't add submodule as odb for push
 + submodule: use submodule repos for object lookup
 + pretty: prepare format_commit_message to handle arbitrary repositories
 + commit: prepare logmsg_reencode to handle arbitrary repositories
 + commit: prepare repo_unuse_commit_buffer to handle any repo
 + commit: prepare get_commit_buffer to handle any repo
 + commit-reach: prepare in_merge_bases[_many] to handle any repo
 + commit-reach: prepare get_merge_bases to handle any repo
 + commit-reach.c: allow get_merge_bases_many_0 to handle any repo
 + commit-reach.c: allow remove_redundant to handle any repo
 + commit-reach.c: allow merge_bases_many to handle any repo
 + commit-reach.c: allow paint_down_to_common to handle any repo
 + commit: allow parse_commit* to handle any repo
 + object: parse_object to honor its repository argument
 + object-store: prepare has_{sha1, object}_file to handle any repo
 + object-store: prepare read_object_file to deal with any repo
 + object-store: allow read_object_file_extended to read from any repo
 + packfile: allow has_packed_and_bad to handle arbitrary repositories
 + sha1_file: allow read_object to read objects in arbitrary repositories
 (this branch is used by jt/get-reference-with-commit-graph.)

 The in-core repository instances are passed through more codepaths.

 Will cook in 'next'.
 cf. <20181115221254.45373-1-jonathantanmy@google.com>


* en/merge-path-collision (2018-12-01) 11 commits
  (merged to 'next' on 2018-12-01 at 24492e61f1)
 + t6036: avoid non-portable "cp -a"
  (merged to 'next' on 2018-11-18 at 3ec9286e0b)
 + merge-recursive: combine error handling
 + t6036, t6043: increase code coverage for file collision handling
 + merge-recursive: improve rename/rename(1to2)/add[/add] handling
 + merge-recursive: use handle_file_collision for add/add conflicts
 + merge-recursive: improve handling for rename/rename(2to1) conflicts
 + merge-recursive: fix rename/add conflict handling
 + merge-recursive: new function for better colliding conflict resolutions
 + merge-recursive: increase marker length with depth of recursion
 + t6036, t6042: testcases for rename collision of already conflicting files
 + t6042: add tests for consistency in file collision conflict handling

 Updates for corner cases in merge-recursive.

 Will cook in 'next'.


* sd/stash-wo-user-name (2018-11-19) 1 commit
  (merged to 'next' on 2018-11-19 at 0838b091ea)
 + stash: tolerate missing user identity

 A properly configured username/email is required under
 user.useConfigOnly in order to create commits; now "git stash"
 (even though it creates commit objects to represent stash entries)
 command is excempt from the requirement.

 Will cook in 'next'.


* bc/sha-256 (2018-11-14) 12 commits
 - hash: add an SHA-256 implementation using OpenSSL
 - sha256: add an SHA-256 implementation using libgcrypt
 - Add a base implementation of SHA-256 support
 - commit-graph: convert to using the_hash_algo
 - t/helper: add a test helper to compute hash speed
 - sha1-file: add a constant for hash block size
 - t: make the sha1 test-tool helper generic
 - t: add basic tests for our SHA-1 implementation
 - cache: make hashcmp and hasheq work with larger hashes
 - hex: introduce functions to print arbitrary hashes
 - sha1-file: provide functions to look up hash algorithms
 - sha1-file: rename algorithm to "sha1"

 Add sha-256 hash and plug it through the code to allow building Git
 with the "NewHash".


* js/vsts-ci (2018-10-16) 13 commits
 . travis: fix skipping tagged releases
 . README: add a build badge (status of the Azure Pipelines build)
 . tests: record more stderr with --write-junit-xml in case of failure
 . tests: include detailed trace logs with --write-junit-xml upon failure
 . git-p4: use `test_atexit` to kill the daemon
 . git-daemon: use `test_atexit` in the tests
 . tests: introduce `test_atexit`
 . ci: add a build definition for Azure DevOps
 . ci/lib.sh: add support for Azure Pipelines
 . tests: optionally write results as JUnit-style .xml
 . test-date: add a subcommand to measure times in shell scripts
 . ci/lib.sh: encapsulate Travis-specific things
 . ci: rename the library of common functions

 Prepare to run test suite on Azure DevOps.

 Ejected out of 'pu', as doing so seems to help other topics get
 tested at TravisCI.

 https://travis-ci.org/git/git/builds/452713184 is a sample of a
 build whose tests on 4 hang (with this series in).  Ejecting it
 gave us https://travis-ci.org/git/git/builds/452778963 which still
 shows breakages from other topics not yet in 'next', but at least
 the tests do not stall.


* du/branch-show-current (2018-10-26) 1 commit
 - branch: introduce --show-current display option

 "git branch" learned a new subcommand "--show-current".

 I am personally not yet quite convinced if this is worth pursuing.


* mk/use-size-t-in-zlib (2018-10-15) 1 commit
 - zlib.c: use size_t for size

 The wrapper to call into zlib followed our long tradition to use
 "unsigned long" for sizes of regions in memory, which have been
 updated to use "size_t".


* ag/sequencer-reduce-rewriting-todo (2018-11-12) 16 commits
 . rebase--interactive: move transform_todo_file() to rebase--interactive.c
 . sequencer: fix a call to error() in transform_todo_file()
 . sequencer: use edit_todo_list() in complete_action()
 . rebase-interactive: rewrite edit_todo_list() to handle the initial edit
 . rebase-interactive: append_todo_help() changes
 . rebase-interactive: use todo_list_write_to_file() in edit_todo_list()
 . sequencer: refactor skip_unnecessary_picks() to work on a todo_list
 . sequencer: change complete_action() to use the refactored functions
 . sequencer: make sequencer_make_script() write its script to a strbuf
 . sequencer: refactor rearrange_squash() to work on a todo_list
 . sequencer: refactor sequencer_add_exec_commands() to work on a todo_list
 . sequencer: refactor check_todo_list() to work on a todo_list
 . sequencer: introduce todo_list_write_to_file()
 . sequencer: refactor transform_todos() to work on a todo_list
 . sequencer: make the todo_list structure public
 . sequencer: changes in parse_insn_buffer()

 The scripted version of "git rebase -i" wrote and rewrote the todo
 list many times during a single step of its operation, and the
 recent C-rewrite made a faithful conversion of the logic to C.  The
 implementation has been updated to carry necessary information
 around in-core to avoid rewriting the same file over and over
 unnecessarily.

 With too many topics in-flight that touch sequencer and rebaser,
 this need to wait giving precedence to other topics that fix bugs.


* sb/submodule-recursive-fetch-gets-the-tip (2018-12-09) 9 commits
 - fetch: ensure submodule objects fetched
 - submodule.c: fetch in submodules git directory instead of in worktree
 - submodule: migrate get_next_submodule to use repository structs
 - repository: repo_submodule_init to take a submodule struct
 - submodule: store OIDs in changed_submodule_names
 - submodule.c: tighten scope of changed_submodule_names struct
 - submodule.c: sort changed_submodule_names before searching it
 - submodule.c: fix indentation
 - sha1-array: provide oid_array_filter

 "git fetch --recurse-submodules" may not fetch the necessary commit
 that is bound to the superproject, which is getting corrected.

 Ready?


* js/add-i-coalesce-after-editing-hunk (2018-08-28) 1 commit
 - add -p: coalesce hunks before testing applicability

 Applicability check after a patch is edited in a "git add -i/p"
 session has been improved.

 Will hold.
 cf. <e5b2900a-0558-d3bf-8ea1-d526b078bbc2@talktalk.net>


* ps/stash-in-c (2018-11-26) 22 commits
 . stash: replace all `write-tree` child processes with API calls
 . stash: optimize `get_untracked_files()` and `check_changes()`
 . stash: convert `stash--helper.c` into `stash.c`
 . stash: convert save to builtin
 . stash: make push -q quiet
 . stash: convert push to builtin
 . stash: convert create to builtin
 . stash: convert store to builtin
 . stash: convert show to builtin
 . stash: convert list to builtin
 . stash: convert pop to builtin
 . stash: convert branch to builtin
 . stash: convert drop and clear to builtin
 . stash: convert apply to builtin
 . stash: mention options in `show` synopsis
 . stash: add tests for `git stash show` config
 . stash: rename test cases to be more descriptive
 . t3903: modernize style
 . stash: improve option parsing test coverage
 . strbuf.c: add `strbuf_insertf()` and `strbuf_vinsertf()`
 . strbuf.c: add `strbuf_join_argv()`
 . sha1-name.c: add `get_oidf()` which acts like `get_oid()`

 "git stash" rewritten in C.

 Expecting a reroll, probably on top of the sd/stash-wo-user-name
 topic after it stabilizes, with an escape hatch like the one in
 "rebase in C".


* pw/add-p-select (2018-07-26) 4 commits
 - add -p: optimize line selection for short hunks
 - add -p: allow line selection to be inverted
 - add -p: select modified lines correctly
 - add -p: select individual hunk lines

 "git add -p" interactive interface learned to let users choose
 individual added/removed lines to be used in the operation, instead
 of accepting or rejecting a whole hunk.

 Will discard.
 No further feedbacks on the topic for quite some time.

 cf. <d622a95b-7302-43d4-4ec9-b2cf3388c653@talktalk.net>
 I found the feature to be hard to explain, and may result in more
 end-user complaints, but let's see.

--------------------------------------------------
[Discarded]

* ab/reject-alias-loop (2018-10-19) 1 commit
  (merged to 'next' on 2018-10-26 at bc213f1bef)
 + alias: detect loops in mixed execution mode

 Two (or more) aliases that mutually refer to each other can form an
 infinite loop; we now attempt to notice and stop.

 Discarded.
 Reverted out of 'next'.
 cf. <87sh0slvxm.fsf@evledraar.gmail.com>


* gl/bundle-unlock-before-aborting (2018-11-14) 1 commit
 . bundle: rollback lock file while refusing to create an empty bundle

 Superseded by jk/close-duped-fd-before-unlock-for-bundle


* js/remote-archive-v2 (2018-09-28) 4 commits
  (merged to 'next' on 2018-10-12 at 5f34377f60)
 + archive: allow archive over HTTP(S) with proto v2
 + archive: implement protocol v2 archive command
 + archive: use packet_reader for communications
 + archive: follow test standards around assertions

 The original implementation of "git archive --remote" more or less
 bypassed the transport layer and did not work over http(s).  The
 version 2 of the protocol is defined to allow going over http(s) as
 well as Git native transport.

 Retracted; reverted out of next.
 cf. <20181114195142.GI126896@google.com>


* ab/format-patch-rangediff-not-stat (2018-11-24) 1 commit
  (merged to 'next' on 2018-11-26 at d9c84916b3)
 + format-patch: don't include --stat with --range-diff output

 The "--rangediff" option recently added to "format-patch"
 interspersed a bogus and useless "--stat" information by mistake,
 which is being corrected.

 Reverted out of 'next'.


* jc/postpone-rebase-in-c (2018-11-26) 1 commit
  (merged to 'next' on 2018-11-26 at c6ae45110f)
 + rebase: mark the C reimplementation as an experimental opt-in feature

 People seem to be still finding latent bugs in the "rebase in C"
 reimplementation.  For the upcoming release, use the scripted
 version by default and adjust the documentation accordingly.

 Reverted out of 'next'.

^ permalink raw reply

* [ANNOUNCE] Git v2.20.0
From: Junio C Hamano @ 2018-12-09  8:43 UTC (permalink / raw)
  To: git; +Cc: Linux Kernel, git-packagers

The latest feature release Git v2.20.0 is now available at the usual
places.  It is comprised of 962 non-merge commits since v2.19.0
(this is by far the largest release in v2.x.x series), contributed
by 83 people, 26 of which are new faces.

The tarballs are found at:

    https://www.kernel.org/pub/software/scm/git/

The following public repositories all have a copy of the 'v2.20.0'
tag and the 'master' branch that the tag points at:

  url = https://kernel.googlesource.com/pub/scm/git/git
  url = git://repo.or.cz/alt-git.git
  url = https://github.com/gitster/git

New contributors whose contributions weren't in v2.19.0 are as follows.
Welcome to the Git development community!

  Aaron Lindsay, Alexander Pyhalov, Anton Serbulov, Brendan
  Forster, Carlo Marcelo Arenas Belón, Daniels Umanovskis,
  David Zych, Đoàn Trần Công Danh, Frederick Eaton, Greg
  Hurrell, James Knight, Jann Horn, Joshua Watt, Loo Rong Jie,
  Lucas De Marchi, Matthew DeVore, Mihir Mehta, Minh Nguyen,
  Nickolai Belakovski, Roger Strain, Sam McKelvie, Saulius Gurklys,
  Shulhan, Steven Fernandez, Strain, Roger L, and Tim Schumacher.

Returning contributors who helped this release are as follows.
Thanks for your continued support.

  Ævar Arnfjörð Bjarmason, Alban Gruin, Alexander Shopov,
  Andreas Gruenbacher, Andreas Heiduk, Antonio Ospite, Ben Peart,
  Brandon Williams, brian m. carlson, Christian Couder, Christian
  Hesse, Christopher Díaz Riveros, Denton Liu, Derrick Stolee,
  Elijah Newren, Eric Sunshine, Jean-Noël Avila, Jeff Hostetler,
  Jeff King, Jiang Xin, Johannes Schindelin, Johannes Sixt,
  Jonathan Nieder, Jonathan Tan, Jordi Mas, Josh Steadmon,
  Junio C Hamano, Karsten Blees, Luke Diamand, Martin Ågren,
  Max Kirillov, Michael Witten, Michał Górny, Nguyễn Thái
  Ngọc Duy, Noam Postavsky, Olga Telezhnaya, Peter Krefting,
  Phillip Wood, Pratik Karki, Rafael Ascensão, Ralf Thielow,
  Ramsay Jones, Rasmus Villemoes, René Scharfe, Sebastian Staudt,
  Stefan Beller, Stephen P. Smith, Steve Hoelzer, Sven Strickroth,
  SZEDER Gábor, Tao Qingyun, Taylor Blau, Thomas Gummerer,
  Todd Zullinger, Torsten Bögershausen, Trần Ngọc Quân,
  and Uwe Kleine-König.

----------------------------------------------------------------

Git 2.20 Release Notes
======================

Backward Compatibility Notes
----------------------------

 * "git branch -l <foo>" used to be a way to ask a reflog to be
   created while creating a new branch, but that is no longer the
   case.  It is a short-hand for "git branch --list <foo>" now.

 * "git push" into refs/tags/* hierarchy is rejected without getting
   forced, but "git fetch" (misguidedly) used the "fast forwarding"
   rule used for the refs/heads/* hierarchy; this has been corrected,
   which means some fetches of tags that did not fail with older
   version of Git will fail without "--force" with this version.

 * "git help -a" now gives verbose output (same as "git help -av").
   Those who want the old output may say "git help --no-verbose -a"..

 * "git cpn --help", when "cpn" is an alias to, say, "cherry-pick -n",
   reported only the alias expansion of "cpn" in earlier versions of
   Git.  It now runs "git cherry-pick --help" to show the manual page
   of the command, while sending the alias expansion to the standard
   error stream.

 * "git send-email" learned to grab address-looking string on any
   trailer whose name ends with "-by". This is a backward-incompatible
   change.  Adding "--suppress-cc=misc-by" on the command line, or
   setting sendemail.suppresscc configuration variable to "misc-by",
   can be used to disable this behaviour.


Updates since v2.19
-------------------

UI, Workflows & Features

 * Running "git clone" against a project that contain two files with
   pathnames that differ only in cases on a case insensitive
   filesystem would result in one of the files lost because the
   underlying filesystem is incapable of holding both at the same
   time.  An attempt is made to detect such a case and warn.

 * "git checkout -b newbranch [HEAD]" should not have to do as much as
   checking out a commit different from HEAD.  An attempt is made to
   optimize this special case.

 * "git rev-list --stdin </dev/null" used to be an error; it now shows
   no output without an error.  "git rev-list --stdin --default HEAD"
   still falls back to the given default when nothing is given on the
   standard input.

 * Lift code from GitHub to restrict delta computation so that an
   object that exists in one fork is not made into a delta against
   another object that does not appear in the same forked repository.

 * "git format-patch" learned new "--interdiff" and "--range-diff"
   options to explain the difference between this version and the
   previous attempt in the cover letter (or after the three-dashes as
   a comment).

 * "git mailinfo" used in "git am" learned to make a best-effort
   recovery of a patch corrupted by MUA that sends text/plain with
   format=flawed option.
   (merge 3aa4d81f88 rs/mailinfo-format-flowed later to maint).

 * The rules used by "git push" and "git fetch" to determine if a ref
   can or cannot be updated were inconsistent; specifically, fetching
   to update existing tags were allowed even though tags are supposed
   to be unmoving anchoring points.  "git fetch" was taught to forbid
   updates to existing tags without the "--force" option.

 * "git multi-pack-index" learned to detect corruption in the .midx
   file it uses, and this feature has been integrated into "git fsck".

 * Generation of (experimental) commit-graph files have so far been
   fairly silent, even though it takes noticeable amount of time in a
   meaningfully large repository.  The users will now see progress
   output.

 * The minimum version of Windows supported by Windows port of Git is
   now set to Vista.

 * The completion script (in contrib/) learned to complete a handful of
   options "git stash list" command takes.

 * The completion script (in contrib/) learned that "git fetch
   --multiple" only takes remote names as arguments and no refspecs.

 * "git status" learns to show progress bar when refreshing the index
   takes a long time.
   (merge ae9af12287 nd/status-refresh-progress later to maint).

 * "git help -a" and "git help -av" give different pieces of
   information, and generally the "verbose" version is more friendly
   to the new users.  "git help -a" by default now uses the more
   verbose output (with "--no-verbose", you can go back to the
   original).  Also "git help -av" now lists aliases and external
   commands, which it did not used to.

 * Unlike "grep", "git grep" by default recurses to the whole tree.
   The command learned "git grep --recursive" option, so that "git
   grep --no-recursive" can serve as a synonym to setting the
   max-depth to 0.

 * When pushing into a repository that borrows its objects from an
   alternate object store, "git receive-pack" that responds to the
   push request on the other side lists the tips of refs in the
   alternate to reduce the amount of objects transferred.  This
   sometimes is detrimental when the number of refs in the alternate
   is absurdly large, in which case the bandwidth saved in potentially
   fewer objects transferred is wasted in excessively large ref
   advertisement.  The alternate refs that are advertised are now
   configurable with a pair of configuration variables.

 * "git cmd --help" when "cmd" is aliased used to only say "cmd is
   aliased to ...".  Now it shows that to the standard error stream
   and runs "git $cmd --help" where $cmd is the first word of the
   alias expansion.

 * The documentation of "git gc" has been updated to mention that it
   is no longer limited to "pruning away crufts" but also updates
   ancillary files like commit-graph as a part of repository
   optimization.

 * "git p4 unshelve" improvements.

 * The logic to select the default user name and e-mail on Windows has
   been improved.
   (merge 501afcb8b0 js/mingw-default-ident later to maint).

 * The "rev-list --filter" feature learned to exclude all trees via
   "tree:0" filter.

 * "git send-email" learned to grab address-looking string on any
   trailer whose name ends with "-by"; --suppress-cc=misc-by on the
   command line, or setting sendemail.suppresscc configuration
   variable to "misc-by", can be used to disable this behaviour.

 * "git mergetool" learned to take the "--[no-]gui" option, just like
   "git difftool" does.

 * "git rebase -i" learned a new insn, 'break', that the user can
   insert in the to-do list.  Upon hitting it, the command returns
   control back to the user.

 * New "--pretty=format:" placeholders %GF and %GP that show the GPG
   key fingerprints have been invented.

 * On platforms with recent cURL library, http.sslBackend configuration
   variable can be used to choose a different SSL backend at runtime.
   The Windows port uses this mechanism to switch between OpenSSL and
   Secure Channel while talking over the HTTPS protocol.

 * "git send-email" learned to disable SMTP authentication via the
   "--smtp-auth=none" option, even when the smtp username is given
   (which turns the authentication on by default).

 * A fourth class of configuration files (in addition to the
   traditional "system wide", "per user in the $HOME directory" and
   "per repository in the $GIT_DIR/config") has been introduced so
   that different worktrees that share the same repository (hence the
   same $GIT_DIR/config file) can use different customization.

 * A pattern with '**' that does not have a slash on either side used
   to be an invalid one, but the code now treats such double-asterisks
   the same way as two normal asterisks that happen to be adjacent to
   each other.
   (merge e5bbe09e88 nd/wildmatch-double-asterisk later to maint).

 * The "--no-patch" option, which can be used to get a high-level
   overview without the actual line-by-line patch difference shown, of
   the "range-diff" command was earlier broken, which has been
   corrected.

 * The recently merged "rebase in C" has an escape hatch to use the
   scripted version when necessary, but it hasn't been documented,
   which has been corrected.


Performance, Internal Implementation, Development Support etc.

 * Developer builds now use -Wunused-function compilation option.

 * One of our CI tests to run with "unusual/experimental/random"
   settings now also uses commit-graph and midx.

 * When there are too many packfiles in a repository (which is not
   recommended), looking up an object in these would require
   consulting many pack .idx files; a new mechanism to have a single
   file that consolidates all of these .idx files is introduced.

 * "git submodule update" is getting rewritten piece-by-piece into C.

 * The code for computing history reachability has been shuffled,
   obtained a bunch of new tests to cover them, and then being
   improved.

 * The unpack_trees() API used in checking out a branch and merging
   walks one or more trees along with the index.  When the cache-tree
   in the index tells us that we are walking a tree whose flattened
   contents is known (i.e. matches a span in the index), as linearly
   scanning a span in the index is much more efficient than having to
   open tree objects recursively and listing their entries, the walk
   can be optimized, which has been done.

 * When creating a thin pack, which allows objects to be made into a
   delta against another object that is not in the resulting pack but
   is known to be present on the receiving end, the code learned to
   take advantage of the reachability bitmap; this allows the server
   to send a delta against a base beyond the "boundary" commit.

 * spatch transformation to replace boolean uses of !hashcmp() to
   newly introduced oideq() is added, and applied, to regain
   performance lost due to support of multiple hash algorithms.

 * Fix a bug in which the same path could be registered under multiple
   worktree entries if the path was missing (for instance, was removed
   manually).  Also, as a convenience, expand the number of cases in
   which --force is applicable.

 * Split Documentation/config.txt for easier maintenance.
   (merge 6014363f0b nd/config-split later to maint).

 * Test helper binaries clean-up.
   (merge c9a1f4161f nd/test-tool later to maint).

 * Various tests have been updated to make it easier to swap the
   hash function used for object identification.
   (merge ae0c89d41b bc/hash-independent-tests later to maint).

 * Update fsck.skipList implementation and documentation.
   (merge 371a655074 ab/fsck-skiplist later to maint).

 * An alias that expands to another alias has so far been forbidden,
   but now it is allowed to create such an alias.

 * Various test scripts have been updated for style and also correct
   handling of exit status of various commands.

 * "gc --auto" ended up calling exit(-1) upon error, which has been
   corrected to use exit(1).  Also the error reporting behaviour when
   daemonized has been updated to exit with zero status when stopping
   due to a previously discovered error (which implies there is no
   point running gc to improve the situation); we used to exit with
   failure in such a case.

 * Various codepaths in the core-ish part learned to work on an
   arbitrary in-core index structure, not necessarily the default
   instance "the_index".
   (merge b3c7eef9b0 nd/the-index later to maint).

 * Code clean-up in the internal machinery used by "git status" and
   "git commit --dry-run".
   (merge 73ba5d78b4 ss/wt-status-committable later to maint).

 * Some environment variables that control the runtime options of Git
   used during tests are getting renamed for consistency.
   (merge 4231d1ba99 bp/rename-test-env-var later to maint).

 * A pair of new extensions to the index file have been introduced.
   They allow the index file to be read in parallel for performance.

 * The oidset API was built on top of the oidmap API which in turn is
   on the hashmap API.  Replace the implementation to build on top of
   the khash API and gain performance.

 * Over some transports, fetching objects with an exact commit object
   name can be done without first seeing the ref advertisements.  The
   code has been optimized to exploit this.

 * In a partial clone that will lazily be hydrated from the
   originating repository, we generally want to avoid "does this
   object exist (locally)?" on objects that we deliberately omitted
   when we created the clone.  The cache-tree codepath (which is used
   to write a tree object out of the index) however insisted that the
   object exists, even for paths that are outside of the partial
   checkout area.  The code has been updated to avoid such a check.

 * To help developers, an EditorConfig file that attempts to follow
   the project convention has been added.
   (merge b548d698a0 bc/editorconfig later to maint).

 * The result of coverage test can be combined with "git blame" to
   check the test coverage of code introduced recently with a new
   'coverage-diff' tool (in contrib/).
   (merge 783faedd65 ds/coverage-diff later to maint).

 * An experiment to fuzz test a few areas, hopefully we can gain more
   coverage to various areas.

 * More codepaths are moving away from hardcoded hash sizes.

 * The way the Windows port figures out the current directory has been
   improved.

 * The way DLLs are loaded on the Windows port has been improved.

 * Some tests have been reorganized and renamed; "ls t/" now gives a
   better overview of what is tested for these scripts than before.

 * "git rebase" and "git rebase -i" have been reimplemented in C.

 * Windows port learned to use nano-second resolution file timestamps.

 * The overly large Documentation/config.txt file have been split into
   million little pieces.  This potentially allows each individual piece
   to be included into the manual page of the command it affects more easily.

 * Replace three string-list instances used as look-up tables in "git
   fetch" with hashmaps.

 * Unify code to read the author-script used in "git am" and the
   commands that use the sequencer machinery, e.g. "git rebase -i".

 * In preparation to the day when we can deprecate and remove the
   "rebase -p", make sure we can skip and later remove tests for
   it.

 * The history traversal used to implement the tag-following has been
   optimized by introducing a new helper.

 * The helper function to refresh the cached stat information in the
   in-core index has learned to perform the lstat() part of the
   operation in parallel on multi-core platforms.

 * The code to traverse objects for reachability, used to decide what
   objects are unreferenced and expendable, have been taught to also
   consider per-worktree refs of other worktrees as starting points to
   prevent data loss.

 * "git add" needs to internally run "diff-files" equivalent, and the
   codepath learned the same optimization as "diff-files" has to run
   lstat(2) in parallel to find which paths have been updated in the
   working tree.

 * The procedure to install dependencies before testing at Travis CI
   is getting revamped for both simplicity and flexibility, taking
   advantage of the recent move to the vm-based environment.

 * The support for format-patch (and send-email) by the command-line
   completion script (in contrib/) has been simplified a bit.

 * The revision walker machinery learned to take advantage of the
   commit generation numbers stored in the commit-graph file.

 * The codebase has been cleaned up to reduce "#ifndef NO_PTHREADS".

 * The way -lcurl library gets linked has been simplified by taking
   advantage of the fact that we can just ask curl-config command how.

 * Various functions have been audited for "-Wunused-parameter" warnings
   and bugs in them got fixed.

 * A sanity check for start-up sequence has been added in the config
   API codepath.

 * The build procedure to link for fuzzing test has been made
   customizable with a new Makefile variable.

 * The way "git rebase" parses and forwards the command line options
   meant for underlying "git am" has been revamped, which fixed for
   options with parameters that were not passed correctly.

 * Our testing framework uses a special i18n "poisoned localization"
   feature to find messages that ought to stay constant but are
   incorrectly marked to be translated.  This feature has been made
   into a runtime option (it used to be a compile-time option).

 * "git push" used to check ambiguities between object-names and
   refnames while processing the list of refs' old and new values,
   which was unnecessary (as it knew that it is feeding raw object
   names).  This has been optimized out.

 * The xcurl_off_t() helper function is used to cast size_t to
   curl_off_t, but some compilers gave warnings against the code to
   ensure the casting is done without wraparound, when size_t is
   narrower than curl_off_t.  This warning has been squelched.

 * Code preparation to replace ulong vars with size_t vars where
   appropriate continues.

 * The "test installed Git" mode of our test suite has been updated to
   work better.

 * A coding convention around the Coccinelle semantic patches to have
   two classes to ease code migration process has been proposed and
   its support has been added to the Makefile.

 * The "container" mode of TravisCI is going away.  Our .travis.yml
   file is getting prepared for the transition.
   (merge 32ee384be8 ss/travis-ci-force-vm-mode later to maint).

 * Our test scripts can now take the '-V' option as a synonym for the
   '--verbose-log' option.
   (merge a5f52c6dab sg/test-verbose-log later to maint).


Fixes since v2.19
-----------------

 * "git interpret-trailers" and its underlying machinery had a buggy
   code that attempted to ignore patch text after commit log message,
   which triggered in various codepaths that will always get the log
   message alone and never get such an input.
   (merge 66e83d9b41 jk/trailer-fixes later to maint).

 * Malformed or crafted data in packstream can make our code attempt
   to read or write past the allocated buffer and abort, instead of
   reporting an error, which has been fixed.

 * "git rebase -i" did not clear the state files correctly when a run
   of "squash/fixup" is aborted and then the user manually amended the
   commit instead, which has been corrected.
   (merge 10d2f35436 js/rebase-i-autosquash-fix later to maint).

 * When fsmonitor is in use, after operation on submodules updates
   .gitmodules, we lost track of the fact that we did so and relied on
   stale fsmonitor data.
   (merge 43f1180814 bp/mv-submodules-with-fsmonitor later to maint).

 * Fix for a long-standing bug that leaves the index file corrupt when
   it shrinks during a partial commit.
   (merge 6c003d6ffb jk/reopen-tempfile-truncate later to maint).

 * Further fix for O_APPEND emulation on Windows
   (merge eeaf7ddac7 js/mingw-o-append later to maint).

 * A corner case bugfix in "git rerere" code.
   (merge ad2bf0d9b4 en/rerere-multi-stage-1-fix later to maint).

 * "git add ':(attr:foo)'" is not supported and is supposed to be
   rejected while the command line arguments are parsed, but we fail
   to reject such a command line upfront.
   (merge 84d938b732 nd/attr-pathspec-fix later to maint).

 * Recent update broke the reachability algorithm when refs (e.g.
   tags) that point at objects that are not commit were involved,
   which has been fixed.

 * "git rebase" etc. in Git 2.19 fails to abort when given an empty
   commit log message as result of editing, which has been corrected.
   (merge a3ec9eaf38 en/sequencer-empty-edit-result-aborts later to maint).

 * The code to backfill objects in lazily cloned repository did not
   work correctly, which has been corrected.
   (merge e68302011c jt/lazy-object-fetch-fix later to maint).

 * Update error messages given by "git remote" and make them consistent.
   (merge 5025425dff ms/remote-error-message-update later to maint).

 * "git update-ref" learned to make both "--no-deref" and "--stdin"
   work at the same time.
   (merge d345e9fbe7 en/update-ref-no-deref-stdin later to maint).

 * Recently added "range-diff" had a corner-case bug to cause it
   segfault, which has been corrected.
   (merge e467a90c7a tg/range-diff-corner-case-fix later to maint).

 * The recently introduced commit-graph auxiliary data is incompatible
   with mechanisms such as replace & grafts that "breaks" immutable
   nature of the object reference relationship.  Disable optimizations
   based on its use (and updating existing commit-graph) when these
   incompatible features are in use in the repository.
   (merge 829a321569 ds/commit-graph-with-grafts later to maint).

 * The mailmap file update.
   (merge 255eb03edf jn/mailmap-update later to maint).

 * The code in "git status" sometimes hit an assertion failure.  This
   was caused by a structure that was reused without cleaning the data
   used for the first run, which has been corrected.
   (merge 3e73cc62c0 en/status-multiple-renames-to-the-same-target-fix later to maint).

 * "git fetch $repo $object" in a partial clone did not correctly
   fetch the asked-for object that is referenced by an object in
   promisor packfile, which has been fixed.

 * A corner-case bugfix.
   (merge c5cbb27cb5 sm/show-superproject-while-conflicted later to maint).

 * Various fixes to "diff --color-moved-ws".

 * A partial clone that is configured to lazily fetch missing objects
   will on-demand issue a "git fetch" request to the originating
   repository to fill not-yet-obtained objects.  The request has been
   optimized for requesting a tree object (and not the leaf blob
   objects contained in it) by telling the originating repository that
   no blobs are needed.
   (merge 4c7f9567ea jt/non-blob-lazy-fetch later to maint).

 * The codepath to support the experimental split-index mode had
   remaining "racily clean" issues fixed.
   (merge 4c490f3d32 sg/split-index-racefix later to maint).

 * "git log --graph" showing an octopus merge sometimes miscounted the
   number of display columns it is consuming to show the merge and its
   parent commits, which has been corrected.
   (merge 04005834ed np/log-graph-octopus-fix later to maint).

 * "git range-diff" did not work well when the compared ranges had
   changes in submodules and the "--submodule=log" was used.

 * The implementation of run_command() API on the UNIX platforms had a
   bug that caused a command not on $PATH to be found in the current
   directory.
   (merge f67b980771 jk/run-command-notdot later to maint).

 * A mutex used in "git pack-objects" were not correctly initialized
   and this caused "git repack" to dump core on Windows.
   (merge 34204c8166 js/pack-objects-mutex-init-fix later to maint).

 * Under certain circumstances, "git diff D:/a/b/c D:/a/b/d" on
   Windows would strip initial parts from the paths because they
   were not recognized as absolute, which has been corrected.
   (merge ffd04e92e2 js/diff-notice-has-drive-prefix later to maint).

 * The receive.denyCurrentBranch=updateInstead codepath kicked in even
   when the push should have been rejected due to other reasons, such
   as it does not fast-forward or the update-hook rejects it, which
   has been corrected.
   (merge b072a25fad jc/receive-deny-current-branch-fix later to maint).

 * The logic to determine the archive type "git archive" uses did not
   correctly kick in for "git archive --remote", which has been
   corrected.

 * "git repack" in a shallow clone did not correctly update the
   shallow points in the repository, leading to a repository that
   does not pass fsck.
   (merge 5dcfbf564c js/shallow-and-fetch-prune later to maint).

 * Some codepaths failed to form a proper URL when .gitmodules record
   the URL to a submodule repository as relative to the repository of
   superproject, which has been corrected.
   (merge e0a862fdaf sb/submodule-url-to-absolute later to maint).

 * "git fetch" over protocol v2 into a shallow repository failed to
   fetch full history behind a new tip of history that was diverged
   before the cut-off point of the history that was previously fetched
   shallowly.

 * The command line completion machinery (in contrib/) has been
   updated to allow the completion script to tweak the list of options
   that are reported by the parse-options machinery correctly.
   (merge 276b49ff34 nd/completion-negation later to maint).

 * Operations on promisor objects make sense in the context of only a
   small subset of the commands that internally use the revisions
   machinery, but the "--exclude-promisor-objects" option were taken
   and led to nonsense results by commands like "log", to which it
   didn't make much sense.  This has been corrected.
   (merge 669b1d2aae md/exclude-promisor-objects-fix later to maint).

 * A regression in Git 2.12 era made "git fsck" fall into an infinite
   loop while processing truncated loose objects.
   (merge 18ad13e5b2 jk/detect-truncated-zlib-input later to maint).

 * "git ls-remote $there foo" was broken by recent update for the
   protocol v2 and stopped showing refs that match 'foo' that are not
   refs/{heads,tags}/foo, which has been fixed.
   (merge 6a139cdd74 jk/proto-v2-ref-prefix-fix later to maint).

 * Additional comment on a tricky piece of code to help developers.
   (merge 0afbe3e806 jk/stream-pack-non-delta-clarification later to maint).

 * A couple of tests used to leave the repository in a state that is
   deliberately corrupt, which have been corrected.
   (merge aa984dbe5e ab/pack-tests-cleanup later to maint).

 * The submodule support has been updated to read from the blob at
   HEAD:.gitmodules when the .gitmodules file is missing from the
   working tree.
   (merge 2b1257e463 ao/submodule-wo-gitmodules-checked-out later to maint).

 * "git fetch" was a bit loose in parsing responses from the other side
   when talking over the protocol v2.

 * "git rev-parse --exclude=* --branches --branches"  (i.e. first
   saying "add only things that do not match '*' out of all branches"
   and then adding all branches, without any exclusion this time)
   worked as expected, but "--exclude=* --all --all" did not work the
   same way, which has been fixed.
   (merge 5221048092 ag/rev-parse-all-exclude-fix later to maint).

 * "git send-email --transfer-encoding=..." in recent versions of Git
   sometimes produced an empty "Content-Transfer-Encoding:" header,
   which has been corrected.
   (merge 3c88e46f1a al/send-email-auto-cte-fixup later to maint).

 * The interface into "xdiff" library used to discover the offset and
   size of a generated patch hunk by first formatting it into the
   textual hunk header "@@ -n,m +k,l @@" and then parsing the numbers
   out.  A new interface has been introduced to allow callers a more
   direct access to them.
   (merge 5eade0746e jk/xdiff-interface later to maint).

 * Pathspec matching against a tree object were buggy when negative
   pathspec elements were involved, which has been fixed.
   (merge b7845cebc0 nd/tree-walk-path-exclusion later to maint).

 * "git merge" and "git pull" that merges into an unborn branch used
   to completely ignore "--verify-signatures", which has been
   corrected.
   (merge 01a31f3bca jk/verify-sig-merge-into-void later to maint).

 * "git rebase --autostash" did not correctly re-attach the HEAD at times.

 * "rev-parse --exclude=<pattern> --branches=<pattern>" etc. did not
   quite work, which has been corrected.
   (merge 9ab9b5df0e ra/rev-parse-exclude-glob later to maint).

 * When editing a patch in a "git add -i" session, a hunk could be
   made to no-op.  The "git apply" program used to reject a patch with
   such a no-op hunk to catch user mistakes, but it is now updated to
   explicitly allow a no-op hunk in an edited patch.
   (merge 22cb3835b9 js/apply-recount-allow-noop later to maint).

 * The URL to an MSDN page in a comment has been updated.
   (merge 2ef2ae2917 js/mingw-msdn-url later to maint).

 * "git ls-remote --sort=<thing>" can feed an object that is not yet
   available into the comparison machinery and segfault, which has
   been corrected to check such a request upfront and reject it.

 * When "git bundle" aborts due to an empty commit ranges
   (i.e. resulting in an empty pack), it left a file descriptor to an
   lockfile open, which resulted in leftover lockfile on Windows where
   you cannot remove a file with an open file descriptor.  This has
   been corrected.
   (merge 2c8ee1f53c jk/close-duped-fd-before-unlock-for-bundle later to maint).

 * "git format-patch --stat=<width>" can be used to specify the width
   used by the diffstat (shown in the cover letter).
   (merge 284aeb7e60 nd/format-patch-cover-letter-stat-width later to maint).

 * The way .git/index and .git/sharedindex* files were initially
   created gave these files different perm bits until they were
   adjusted for shared repository settings.  This was made consistent.
   (merge c9d6c78870 cc/shared-index-permbits later to maint).

 * "git rebase --stat" to transplant a piece of history onto a totally
   unrelated history were not working before and silently showed wrong
   result.  With the recent reimplementation in C, it started to instead
   die with an error message, as the original logic was not prepared
   to cope with this case.  This has now been fixed.

 * The advice message to tell the user to migrate an existing graft
   file to the replace system when a graft file was read was shown
   even when "git replace --convert-graft-file" command, which is the
   way the message suggests to use, was running, which made little
   sense.
   (merge 8821e90a09 ab/replace-graft-with-replace-advice later to maint).

 * "git diff --raw" lost ellipses to adjust the output columns for
   some time now, but the documentation still showed them.

 * Code cleanup, docfix, build fix, etc.
   (merge 96a7501aad ts/doc-build-manpage-xsl-quietly later to maint).
   (merge b9b07efdb2 tg/conflict-marker-size later to maint).
   (merge fa0aeea770 sg/doc-trace-appends later to maint).
   (merge d64324cb60 tb/void-check-attr later to maint).
   (merge c3b9bc94b9 en/double-semicolon-fix later to maint).
   (merge 79336116f5 sg/t3701-tighten-trace later to maint).
   (merge 801fa63a90 jk/dev-build-format-security later to maint).
   (merge 0597dd62ba sb/string-list-remove-unused later to maint).
   (merge db2d36fad8 bw/protocol-v2 later to maint).
   (merge 456d7cd3a9 sg/split-index-test later to maint).
   (merge 7b6057c852 tq/refs-internal-comment-fix later to maint).
   (merge 29e8dc50ad tg/t5551-with-curl-7.61.1 later to maint).
   (merge 55f6bce2c9 fe/doc-updates later to maint).
   (merge 7987d2232d jk/check-everything-connected-is-long-gone later to maint).
   (merge 4ba3c9be47 dz/credential-doc-url-matching-rules later to maint).
   (merge 4c399442f7 ma/commit-graph-docs later to maint).
   (merge fc0503b04e ma/t1400-undebug-test later to maint).
   (merge e56b53553a nd/packobjectshook-doc-fix later to maint).
   (merge c56170a0c4 ma/mailing-list-address-in-git-help later to maint).
   (merge 6e8fc70fce rs/sequencer-oidset-insert-avoids-dups later to maint).
   (merge ad0b8f9575 mw/doc-typofixes later to maint).
   (merge d9f079ad1a jc/how-to-document-api later to maint).
   (merge b1492bf315 ma/t7005-bash-workaround later to maint).
   (merge ac1f98a0df du/rev-parse-is-plumbing later to maint).
   (merge ca8ed443a5 mm/doc-no-dashed-git later to maint).
   (merge ce366a8144 du/get-tar-commit-id-is-plumbing later to maint).
   (merge 61018fe9e0 du/cherry-is-plumbing later to maint).
   (merge c7e5fe79b9 sb/strbuf-h-update later to maint).
   (merge 8d2008196b tq/branch-create-wo-branch-get later to maint).
   (merge 2e3c894f4b tq/branch-style-fix later to maint).
   (merge c5d844af9c sg/doc-show-branch-typofix later to maint).
   (merge 081d91618b ah/doc-updates later to maint).
   (merge b84c783882 jc/cocci-preincr later to maint).
   (merge 5e495f8122 uk/merge-subtree-doc-update later to maint).
   (merge aaaa881822 jk/uploadpack-packobjectshook-fix later to maint).
   (merge 3063477445 tb/char-may-be-unsigned later to maint).
   (merge 8c64bc9420 sg/test-rebase-editor-fix later to maint).
   (merge 71571cd7d6 ma/sequencer-do-reset-saner-loop-termination later to maint).
   (merge 9a4cb8781e cb/notes-freeing-always-null-fix later to maint).
   (merge 3006f5ee16 ma/reset-doc-rendering-fix later to maint).
   (merge 4c2eb06419 sg/daemon-test-signal-fix later to maint).
   (merge d27525e519 ss/msvc-strcasecmp later to maint).

----------------------------------------------------------------

Changes since v2.19.0 are as follows:

Aaron Lindsay (1):
      send-email: avoid empty transfer encoding header

Alban Gruin (21):
      sequencer: make three functions and an enum from sequencer.c public
      rebase -i: rewrite append_todo_help() in C
      editor: add a function to launch the sequence editor
      rebase -i: rewrite the edit-todo functionality in C
      sequencer: add a new function to silence a command, except if it fails
      rebase -i: rewrite setup_reflog_action() in C
      rebase -i: rewrite checkout_onto() in C
      sequencer: refactor append_todo_help() to write its message to a buffer
      sequencer: change the way skip_unnecessary_picks() returns its result
      t3404: todo list with commented-out commands only aborts
      rebase -i: rewrite complete_action() in C
      rebase -i: remove unused modes and functions
      rebase -i: implement the logic to initialize $revisions in C
      rebase -i: rewrite the rest of init_revisions_and_shortrevisions() in C
      rebase -i: rewrite write_basic_state() in C
      rebase -i: rewrite init_basic_state() in C
      rebase -i: implement the main part of interactive rebase as a builtin
      rebase--interactive2: rewrite the submodes of interactive rebase in C
      rebase -i: remove git-rebase--interactive.sh
      rebase -i: move rebase--helper modes to rebase--interactive
      p3400: replace calls to `git checkout -b' by `git checkout -B'

Alexander Pyhalov (1):
      t7005-editor: quote filename to fix whitespace-issue

Alexander Shopov (3):
      l10n: bg.po: Updated Bulgarian translation (4185t)
      l10n: bg.po: Updated Bulgarian translation (4185t)
      l10n: bg.po: Updated Bulgarian translation (4187t)

Andreas Gruenbacher (1):
      rev-parse: clear --exclude list after 'git rev-parse --all'

Andreas Heiduk (6):
      doc: clarify boundaries of 'git worktree list --porcelain'
      doc: fix ASCII art tab spacing
      doc: fix inappropriate monospace formatting
      doc: fix descripion for 'git tag --format'
      doc: fix indentation of listing blocks in gitweb.conf.txt
      doc: fix formatting in git-update-ref

Anton Serbulov (1):
      mingw: fix getcwd when the parent directory cannot be queried

Antonio Ospite (10):
      submodule: add a print_config_from_gitmodules() helper
      submodule: factor out a config_set_in_gitmodules_file_gently function
      t7411: merge tests 5 and 6
      t7411: be nicer to future tests and really clean things up
      submodule--helper: add a new 'config' subcommand
      submodule: use the 'submodule--helper config' command
      t7506: clean up .gitmodules properly before setting up new scenario
      submodule: add a helper to check if it is safe to write to .gitmodules
      submodule: support reading .gitmodules when it's not in the working tree
      t/helper: add test-submodule-nested-repo-config

Ben Peart (19):
      checkout: optimize "git checkout -b <new_branch>"
      git-mv: allow submodules and fsmonitor to work together
      t/README: correct spelling of "uncommon"
      preload-index: use git_env_bool() not getenv() for customization
      fsmonitor: update GIT_TEST_FSMONITOR support
      read-cache: update TEST_GIT_INDEX_VERSION support
      preload-index: update GIT_FORCE_PRELOAD_TEST support
      read-cache: clean up casting and byte decoding
      eoie: add End of Index Entry (EOIE) extension
      config: add new index.threads config setting
      read-cache: load cache extensions on a worker thread
      ieot: add Index Entry Offset Table (IEOT) extension
      read-cache: load cache entries on worker threads
      reset: don't compute unstaged changes after reset when --quiet
      reset: add new reset.quiet config setting
      reset: warn when refresh_index() takes more than 2 seconds
      speed up refresh_index() by utilizing preload_index()
      add: speed up cmd_add() by utilizing read_cache_preload()
      refresh_index: remove unnecessary calls to preload_index()

Brandon Williams (1):
      config: document value 2 for protocol.version

Brendan Forster (1):
      http: add support for disabling SSL revocation checks in cURL

Carlo Marcelo Arenas Belón (8):
      unpack-trees: avoid dead store for struct progress
      multi-pack-index: avoid dead store for struct progress
      read-cache: use of memory after it is freed
      commit-slabs: move MAYBE_UNUSED out
      khash: silence -Wunused-function for delta-islands
      compat: make sure git_mmap is not expected to write
      sequencer: cleanup for gcc warning in non developer mode
      builtin/notes: remove unnecessary free

Christian Couder (3):
      pack-objects: refactor code into compute_layer_order()
      pack-objects: move tree_depth into 'struct packing_data'
      pack-objects: move 'layer' into 'struct packing_data'

Christian Hesse (2):
      subtree: add build targets 'man' and 'html'
      subtree: make install targets depend on build targets

Christopher Díaz Riveros (2):
      l10n: es.po v2.20.0 round 1
      l10n: es.po v2.20.0 round 3

Daniels Umanovskis (3):
      doc: move git-rev-parse from porcelain to plumbing
      doc: move git-get-tar-commit-id to plumbing
      doc: move git-cherry to plumbing

David Zych (1):
      doc: clarify gitcredentials path component matching

Denton Liu (3):
      mergetool: accept -g/--[no-]gui as arguments
      completion: support `git mergetool --[no-]gui`
      doc: document diff/merge.guitool config keys

Derrick Stolee (93):
      multi-pack-index: add design document
      multi-pack-index: add format details
      multi-pack-index: add builtin
      multi-pack-index: add 'write' verb
      midx: write header information to lockfile
      multi-pack-index: load into memory
      t5319: expand test data
      packfile: generalize pack directory list
      multi-pack-index: read packfile list
      multi-pack-index: write pack names in chunk
      midx: read pack names into array
      midx: sort and deduplicate objects from packfiles
      midx: write object ids in a chunk
      midx: write object id fanout chunk
      midx: write object offsets
      config: create core.multiPackIndex setting
      midx: read objects from multi-pack-index
      midx: use midx in abbreviation calculations
      midx: use existing midx when writing new one
      midx: use midx in approximate_object_count
      midx: prevent duplicate packfile loads
      packfile: skip loading index if in multi-pack-index
      midx: clear midx on repack
      commit-reach: move walk methods from commit.c
      commit.h: remove method declarations
      commit-reach: move ref_newer from remote.c
      commit-reach: move commit_contains from ref-filter
      upload-pack: make reachable() more generic
      upload-pack: refactor ok_to_give_up()
      upload-pack: generalize commit date cutoff
      commit-reach: move can_all_from_reach_with_flags
      test-reach: create new test tool for ref_newer
      test-reach: test in_merge_bases
      test-reach: test is_descendant_of
      test-reach: test get_merge_bases_many
      test-reach: test reduce_heads
      test-reach: test can_all_from_reach_with_flags
      test-reach: test commit_contains
      commit-reach: replace ref_newer logic
      commit-reach: make can_all_from_reach... linear
      commit-reach: use can_all_from_reach
      multi-pack-index: provide more helpful usage info
      multi-pack-index: store local property
      midx: mark bad packed objects
      midx: stop reporting garbage
      midx: fix bug that skips midx with alternates
      packfile: add all_packs list
      treewide: use get_all_packs
      midx: test a few commands that use get_all_packs
      pack-objects: consider packs in multi-pack-index
      commit-graph: update design document
      test-repository: properly init repo
      commit-graph: not compatible with replace objects
      commit-graph: not compatible with grafts
      commit-graph: not compatible with uninitialized repo
      commit-graph: close_commit_graph before shallow walk
      commit-graph: define GIT_TEST_COMMIT_GRAPH
      t3206-range-diff.sh: cover single-patch case
      t5318: use test_oid for HASH_LEN
      multi-pack-index: add 'verify' verb
      multi-pack-index: verify bad header
      multi-pack-index: verify corrupt chunk lookup table
      multi-pack-index: verify packname order
      multi-pack-index: verify missing pack
      multi-pack-index: verify oid fanout order
      multi-pack-index: verify oid lookup order
      multi-pack-index: fix 32-bit vs 64-bit size check
      multi-pack-index: verify object offsets
      multi-pack-index: report progress during 'verify'
      fsck: verify multi-pack-index
      commit-reach: properly peel tags
      commit-reach: fix memory and flag leaks
      commit-reach: cleanups in can_all_from_reach...
      commit-graph: clean up leaked memory during write
      commit-graph: reduce initial oid allocation
      midx: fix broken free() in close_midx()
      contrib: add coverage-diff script
      ci: add optional test variables
      commit-reach: fix first-parent heuristic
      midx: close multi-pack-index on repack
      multi-pack-index: define GIT_TEST_MULTI_PACK_INDEX
      packfile: close multi-pack-index in close_all_packs
      prio-queue: add 'peek' operation
      test-reach: add run_three_modes method
      test-reach: add rev-list tests
      revision.c: begin refactoring --topo-order logic
      commit/revisions: bookkeeping before refactoring
      revision.c: generation-based topo-order algorithm
      t6012: make rev-list tests more interesting
      commit-reach: implement get_reachable_subset
      test-reach: test get_reachable_subset
      remote: make add_missing_tags() linear
      pack-objects: ignore ambiguous object warnings

Elijah Newren (14):
      Remove superfluous trailing semicolons
      t4200: demonstrate rerere segfault on specially crafted merge
      rerere: avoid buffer overrun
      update-ref: fix type of update_flags variable to match its usage
      update-ref: allow --no-deref with --stdin
      sequencer: fix --allow-empty-message behavior, make it smarter
      merge-recursive: set paths correctly when three-way merging content
      merge-recursive: avoid wrapper function when unnecessary and wasteful
      merge-recursive: remove final remaining caller of merge_file_one()
      merge-recursive: rename merge_file_1() and merge_content()
      commit: fix erroneous BUG, 'multiple renames on the same target? how?'
      merge-recursive: improve auto-merging messages with path collisions
      merge-recursive: avoid showing conflicts with merge branch before HEAD
      fsck: move fsck_head_link() to get_default_heads() to avoid some globals

Eric Sunshine (26):
      format-patch: allow additional generated content in make_cover_letter()
      format-patch: add --interdiff option to embed diff in cover letter
      format-patch: teach --interdiff to respect -v/--reroll-count
      interdiff: teach show_interdiff() to indent interdiff
      log-tree: show_log: make commentary block delimiting reusable
      format-patch: allow --interdiff to apply to a lone-patch
      range-diff: respect diff_option.file rather than assuming 'stdout'
      range-diff: publish default creation factor
      range-diff: relieve callers of low-level configuration burden
      format-patch: add --range-diff option to embed diff in cover letter
      format-patch: extend --range-diff to accept revision range
      format-patch: teach --range-diff to respect -v/--reroll-count
      format-patch: add --creation-factor tweak for --range-diff
      format-patch: allow --range-diff to apply to a lone-patch
      worktree: don't die() in library function find_worktree()
      worktree: move delete_git_dir() earlier in file for upcoming new callers
      worktree: generalize delete_git_dir() to reduce code duplication
      worktree: prepare for more checks of whether path can become worktree
      worktree: disallow adding same path multiple times
      worktree: teach 'add' to respect --force for registered but missing path
      worktree: teach 'move' to override lock when --force given twice
      worktree: teach 'remove' to override lock when --force given twice
      worktree: delete .git/worktrees if empty after 'remove'
      doc-diff: fix non-portable 'man' invocation
      doc-diff: add --clean mode to remove temporary working gunk
      doc/Makefile: drop doc-diff worktree and temporary files on "make clean"

Frederick Eaton (3):
      git-archimport.1: specify what kind of Arch we're talking about
      git-column.1: clarify initial description, provide examples
      git-describe.1: clarify that "human readable" is also git-readable

Greg Hurrell (1):
      doc: update diff-format.txt for removed ellipses in --raw

James Knight (1):
      build: link with curl-defined linker flags

Jann Horn (2):
      patch-delta: fix oob read
      patch-delta: consistently report corruption

Jean-Noël Avila (3):
      l10n: fr.po v2.20 rnd 1
      i18n: fix small typos
      l10n: fr.po v2.20.0 round 3

Jeff Hostetler (2):
      t0051: test GIT_TRACE to a windows named pipe
      mingw: fix mingw_open_append to work with named pipes

Jeff King (98):
      branch: make "-l" a synonym for "--list"
      Add delta-islands.{c,h}
      pack-objects: add delta-islands support
      repack: add delta-islands support
      t5320: tests for delta islands
      t/perf: factor boilerplate out of test_perf
      t/perf: factor out percent calculations
      t/perf: add infrastructure for measuring sizes
      t/perf: add perf tests for fetches from a bitmapped server
      pack-bitmap: save "have" bitmap from walk
      pack-objects: reuse on-disk deltas for thin "have" objects
      SubmittingPatches: mention doc-diff
      rev-list: make empty --stdin not an error
      trailer: use size_t for string offsets
      trailer: use size_t for iterating trailer list
      trailer: pass process_trailer_opts to trailer_info_get()
      interpret-trailers: tighten check for "---" patch boundary
      interpret-trailers: allow suppressing "---" divider
      pretty, ref-filter: format %(trailers) with no_divider option
      sequencer: ignore "---" divider when parsing trailers
      append_signoff: use size_t for string offsets
      coccinelle: use <...> for function exclusion
      introduce hasheq() and oideq()
      convert "oidcmp() == 0" to oideq()
      convert "hashcmp() == 0" to hasheq()
      convert "oidcmp() != 0" to "!oideq()"
      convert "hashcmp() != 0" to "!hasheq()"
      convert hashmap comparison functions to oideq()
      read-cache: use oideq() in ce_compare functions
      show_dirstat: simplify same-content check
      doc-diff: always use oids inside worktree
      test-delta: read input into a heap buffer
      t5303: test some corrupt deltas
      patch-delta: handle truncated copy parameters
      t5303: use printf to generate delta bases
      doc/git-branch: remove obsolete "-l" references
      bitmap_has_sha1_in_uninteresting(): drop BUG check
      t5310: test delta reuse with bitmaps
      traverse_bitmap_commit_list(): don't free result
      pack-bitmap: drop "loaded" flag
      reopen_tempfile(): truncate opened file
      doc-diff: force worktree add
      config.mak.dev: add -Wformat-security
      pack-objects: handle island check for "external" delta base
      receive-pack: update comment with check_everything_connected
      submodule--helper: use "--" to signal end of clone options
      submodule-config: ban submodule urls that start with dash
      submodule-config: ban submodule paths that start with a dash
      fsck: detect submodule urls starting with dash
      fsck: detect submodule paths starting with dash
      more oideq/hasheq conversions
      transport: drop refnames from for_each_alternate_ref
      test-tool: show tool list on error
      config.mak.dev: enable -Wunused-function
      run-command: mark path lookup errors with ENOENT
      t5410: use longer path for sample script
      upload-pack: fix broken if/else chain in config callback
      t1450: check large blob in trailing-garbage test
      check_stream_sha1(): handle input underflow
      cat-file: handle streaming failures consistently
      ls-remote: do not send ref prefixes for patterns
      ls-remote: pass heads/tags prefixes to transport
      read_istream_pack_non_delta(): document input handling
      xdiff: provide a separate emit callback for hunks
      xdiff-interface: provide a separate consume callback for hunks
      rev-list: handle flags for --indexed-objects
      approxidate: handle pending number for "specials"
      pathspec: handle non-terminated strings with :(attr)
      diff: avoid generating unused hunk header lines
      diff: discard hunk headers for patch-ids earlier
      diff: use hunk callback for word-diff
      combine-diff: use an xdiff hunk callback
      diff: convert --check to use a hunk callback
      range-diff: use a hunk callback
      xdiff-interface: drop parse_hunk_header()
      apply: mark include/exclude options as NONEG
      am: handle --no-patch-format option
      ls-files: mark exclude options as NONEG
      pack-objects: mark index-version option as NONEG
      cat-file: mark batch options with NONEG
      status: mark --find-renames option with NONEG
      format-patch: mark "--no-numbered" option with NONEG
      show-branch: mark --reflog option as NONEG
      tag: mark "--message" option with NONEG
      cat-file: report an error on multiple --batch options
      apply: return -1 from option callback instead of calling exit(1)
      parse-options: drop OPT_DATE()
      assert NOARG/NONEG behavior of parse-options callbacks
      midx: double-check large object write loop
      merge: extract verify_merge_signature() helper
      merge: handle --verify-signatures for unborn branch
      pull: handle --verify-signatures for unborn branch
      approxidate: fix NULL dereference in date_time()
      bundle: dup() output descriptor closer to point-of-use
      pack-objects: fix tree_depth and layer invariants
      pack-objects: zero-initialize tree_depth/layer arrays
      pack-objects: fix off-by-one in delta-island tree-depth computation
      t5562: fix perl path

Jiang Xin (5):
      l10n: zh_CN: review for git v2.19.0 l10n
      l10n: git.pot: v2.20.0 round 1 (254 new, 27 removed)
      l10n: git.pot: v2.20.0 round 2 (2 new, 2 removed)
      l10n: git.pot: v2.20.0 round 3 (5 new, 3 removed)
      l10n: zh_CN: for git v2.20.0 l10n round 1 to 3

Johannes Schindelin (64):
      rebase -i --autosquash: demonstrate a problem skipping the last squash
      rebase -i: be careful to wrap up fixup/squash chains
      compat/poll: prepare for targeting Windows Vista
      mingw: set _WIN32_WINNT explicitly for Git for Windows
      mingw: bump the minimum Windows version to Vista
      builtin rebase: prepare for builtin rebase -i
      rebase -i: clarify what happens on a failed `exec`
      rebase -i: introduce the 'break' command
      getpwuid(mingw): initialize the structure only once
      getpwuid(mingw): provide a better default for the user name
      mingw: use domain information for default email
      http: add support for selecting SSL backends at runtime
      pack-objects: fix typo 'detla' -> 'delta'
      pack-objects (mingw): demonstrate a segmentation fault with large deltas
      pack-objects (mingw): initialize `packing_data` mutex in the correct spot
      rebase (autostash): avoid duplicate call to state_dir_path()
      rebase (autostash): store the full OID in <state-dir>/autostash
      rebase (autostash): use an explicit OID to apply the stash
      mingw: factor out code to set stat() data
      rebase --autostash: demonstrate a problem with dirty submodules
      rebase --autostash: fix issue with dirty submodules
      mingw: load system libraries the recommended way
      mingw: ensure `getcwd()` reports the correct case
      repack: point out a bug handling stale shallow info
      shallow: offer to prune only non-existing entries
      repack -ad: prune the list of shallow commits
      http: when using Secure Channel, ignore sslCAInfo by default
      t7800: fix quoting
      mingw: reencode environment variables on the fly (UTF-16 <-> UTF-8)
      config: rename `dummy` parameter to `cb` in git_default_config()
      config: allow for platform-specific core.* config settings
      config: move Windows-specific config settings into compat/mingw.c
      mingw: unset PERL5LIB by default
      mingw: fix isatty() after dup2()
      t3404: decouple some test cases from outcomes of previous test cases
      t3418: decouple test cases from a previous `rebase -p` test case
      tests: optionally skip `git rebase -p` tests
      Windows: force-recompile git.res for differing architectures
      built-in rebase: demonstrate regression with --autostash
      built-in rebase --autostash: leave the current branch alone if possible
      Update .mailmap
      rebase -r: demonstrate bug with conflicting merges
      rebase -r: do not write MERGE_HEAD unless needed
      rebase -i: include MERGE_HEAD into files to clean up
      built-in rebase --skip/--abort: clean up stale .git/<name> files
      status: rebase and merge can be in progress at the same time
      apply --recount: allow "no-op hunks"
      rebase: consolidate clean-up code before leaving reset_head()
      rebase: prepare reset_head() for more flags
      built-in rebase: reinstate `checkout -q` behavior where appropriate
      tests: fix GIT_TEST_INSTALLED's PATH to include t/helper/
      tests: respect GIT_TEST_INSTALLED when initializing repositories
      t/lib-gettext: test installed git-sh-i18n if GIT_TEST_INSTALLED is set
      mingw: use `CreateHardLink()` directly
      rebase: really just passthru the `git am` options
      rebase: validate -C<n> and --whitespace=<mode> parameters early
      config: report a bug if git_dir exists without commondir
      tests: do not require Git to be built when testing an installed Git
      tests: explicitly use `git.exe` on Windows
      mingw: replace an obsolete link with the superseding one
      legacy-rebase: backport -C<n> and --whitespace=<option> checks
      rebase: warn about the correct tree's OID
      rebase: fix GIT_REFLOG_ACTION regression
      rebase --stat: fix when rebasing to an unrelated history

Johannes Sixt (4):
      diff: don't attempt to strip prefix from absolute Windows paths
      rebase -i: recognize short commands without arguments
      t3404-rebase-interactive: test abbreviated commands
      rebase docs: fix incorrect format of the section Behavioral Differences

Jonathan Nieder (9):
      gc: improve handling of errors reading gc.log
      gc: exit with status 128 on failure
      gc: do not return error for prior errors in daemonized mode
      commit-reach: correct accidental #include of C file
      mailmap: consistently normalize brian m. carlson's name
      git doc: direct bug reporters to mailing list archive
      eoie: default to not writing EOIE section
      ieot: default to not writing IEOT section
      index: make index.threads=true enable ieot and eoie

Jonathan Tan (15):
      fetch-object: unify fetch_object[s] functions
      fetch-object: set exact_oid when fetching
      connected: document connectivity in partial clones
      fetch: in partial clone, check presence of targets
      fetch-pack: avoid object flags if no_dependents
      fetch-pack: exclude blobs when lazy-fetching trees
      transport: allow skipping of ref listing
      transport: do not list refs if possible
      transport: list refs before fetch if necessary
      fetch: do not list refs if fetching only hashes
      cache-tree: skip some blob checks in partial clone
      upload-pack: make have_obj not global
      upload-pack: make want_obj not global
      upload-pack: clear flags before each v2 request
      fetch-pack: be more precise in parsing v2 response

Jordi Mas (2):
      l10n: Update Catalan translation
      l10n: Update Catalan translation

Josh Steadmon (4):
      fuzz: add basic fuzz testing target.
      fuzz: add fuzz testing for packfile indices.
      archive: initialize archivers earlier
      Makefile: use FUZZ_CXXFLAGS for linking fuzzers

Joshua Watt (1):
      send-email: explicitly disable authentication

Junio C Hamano (37):
      Revert "doc/Makefile: drop doc-diff worktree and temporary files on "make clean""
      Initial batch post 2.19
      Second batch post 2.19
      Git 2.14.5
      Git 2.15.3
      Git 2.16.5
      Git 2.17.2
      Git 2.18.1
      Git 2.19.1
      t0000: do not get self-test disrupted by environment warnings
      CodingGuidelines: document the API in *.h files
      Declare that the next one will be named 2.20
      Third batch for 2.20
      rebase: fix typoes in error messages
      Fourth batch for 2.20
      Revert "subtree: make install targets depend on build targets"
      Fifth batch for 2.20
      receive: denyCurrentBranch=updateinstead should not blindly update
      cocci: simplify "if (++u > 1)" to "if (u++)"
      fsck: s/++i > 1/i++/
      http: give curl version warnings consistently
      Sixth batch for 2.20
      Seventh batch for 2.20
      fetch: replace string-list used as a look-up table with a hashmap
      rebase: apply cocci patch
      Eighth batch for 2.20
      Ninth batch for 2.20
      Makefile: ease dynamic-gettext-poison transition
      Tenth batch for 2.20
      Git 2.20-rc0
      RelNotes: name the release properly
      Prepare for 2.20-rc1
      Git 2.19.2
      Git 2.20-rc1
      format-patch: do not let its diff-options affect --range-diff
      Git 2.20-rc2
      Git 2.20

Karsten Blees (2):
      mingw: replace MSVCRT's fstat() with a Win32-based implementation
      mingw: implement nanosecond-precision file times

Loo Rong Jie (1):
      win32: replace pthread_cond_*() with much simpler code

Lucas De Marchi (1):
      range-diff: allow to diff files regardless of submodule config

Luke Diamand (3):
      git-p4: do not fail in verbose mode for missing 'fileSize' key
      git-p4: unshelve into refs/remotes/p4-unshelved, not refs/remotes/p4/unshelved
      git-p4: fully support unshelving changelists

Martin Ågren (15):
      Doc: use `--type=bool` instead of `--bool`
      git-config.txt: fix 'see: above' note
      git-commit-graph.txt: fix bullet lists
      git-commit-graph.txt: typeset more in monospace
      git-commit-graph.txt: refer to "*commit*-graph file"
      Doc: refer to the "commit-graph file" with dash
      t1400: drop debug `echo` to actually execute `test`
      builtin/commit-graph.c: UNLEAK variables
      sequencer: break out of loop explicitly
      git-reset.txt: render tables correctly under Asciidoctor
      git-reset.txt: render literal examples as monospace
      range-diff: always pass at least minimal diff options
      RelNotes 2.20: move some items between sections
      RelNotes 2.20: clarify sentence
      RelNotes 2.20: drop spurious double quote

Matthew DeVore (19):
      list-objects: store common func args in struct
      list-objects: refactor to process_tree_contents
      list-objects: always parse trees gently
      t/README: reformat Do, Don't, Keep in mind lists
      Documentation: add shell guidelines
      tests: standardize pipe placement
      t/*: fix ordering of expected/observed arguments
      tests: don't swallow Git errors upstream of pipes
      t9109: don't swallow Git errors upstream of pipes
      tests: order arguments to git-rev-list properly
      rev-list: handle missing tree objects properly
      revision: mark non-user-given objects instead
      list-objects-filter: use BUG rather than die
      list-objects-filter-options: do not over-strbuf_init
      list-objects-filter: implement filter tree:0
      filter-trees: code clean-up of tests
      list-objects: support for skipping tree traversal
      Documentation/git-log.txt: do not show --exclude-promisor-objects
      exclude-promisor-objects: declare when option is allowed

Max Kirillov (1):
      http-backend test: make empty CONTENT_LENGTH test more realistic

Michael Witten (3):
      docs: typo: s/go/to/
      docs: graph: remove unnecessary `graph_update()' call
      docs: typo: s/isimilar/similar/

Michał Górny (6):
      gpg-interface.c: detect and reject multiple signatures on commits
      gpg-interface.c: use flags to determine key/signer info presence
      gpg-interface.c: support getting key fingerprint via %GF format
      gpg-interface.c: obtain primary key fingerprint as well
      t/t7510-signed-commit.sh: Add %GP to custom format checks
      t/t7510-signed-commit.sh: add signing subkey to Eris Discordia key

Mihir Mehta (1):
      doc: fix a typo and clarify a sentence

Minh Nguyen (1):
      l10n: vi.po: fix typo in pack-objects

Nguyễn Thái Ngọc Duy (170):
      clone: report duplicate entries on case-insensitive filesystems
      trace.h: support nested performance tracing
      unpack-trees: add performance tracing
      unpack-trees: optimize walking same trees with cache-tree
      unpack-trees: reduce malloc in cache-tree walk
      unpack-trees: reuse (still valid) cache-tree from src_index
      unpack-trees: add missing cache invalidation
      cache-tree: verify valid cache-tree in the test suite
      Document update for nd/unpack-trees-with-cache-tree
      bisect.c: make show_list() build again
      t/helper: keep test-tool command list sorted
      t/helper: merge test-dump-untracked-cache into test-tool
      t/helper: merge test-pkt-line into test-tool
      t/helper: merge test-parse-options into test-tool
      t/helper: merge test-dump-fsmonitor into test-tool
      Makefile: add a hint about TEST_BUILTINS_OBJS
      config.txt: follow camelCase naming
      config.txt: move fetch part out to a separate file
      config.txt: move format part out to a separate file
      config.txt: move gitcvs part out to a separate file
      config.txt: move gui part out to a separate file
      config.txt: move pull part out to a separate file
      config.txt: move push part out to a separate file
      config.txt: move receive part out to a separate file
      config.txt: move sendemail part out to a separate file
      config.txt: move sequence.editor out of "core" part
      config.txt: move submodule part out to a separate file
      archive.c: remove implicit dependency the_repository
      status: show progress bar if refreshing the index takes too long
      add: do not accept pathspec magic 'attr'
      completion: support "git fetch --multiple"
      read-cache.c: remove 'const' from index_has_changes()
      diff.c: reduce implicit dependency on the_index
      combine-diff.c: remove implicit dependency on the_index
      blame.c: rename "repo" argument to "r"
      diff.c: remove the_index dependency in textconv() functions
      grep.c: remove implicit dependency on the_index
      diff.c: remove implicit dependency on the_index
      read-cache.c: remove implicit dependency on the_index
      diff-lib.c: remove implicit dependency on the_index
      ll-merge.c: remove implicit dependency on the_index
      merge-blobs.c: remove implicit dependency on the_index
      merge.c: remove implicit dependency on the_index
      patch-ids.c: remove implicit dependency on the_index
      sha1-file.c: remove implicit dependency on the_index
      rerere.c: remove implicit dependency on the_index
      userdiff.c: remove implicit dependency on the_index
      line-range.c: remove implicit dependency on the_index
      submodule.c: remove implicit dependency on the_index
      tree-diff.c: remove implicit dependency on the_index
      ws.c: remove implicit dependency on the_index
      revision.c: remove implicit dependency on the_index
      revision.c: reduce implicit dependency the_repository
      read-cache.c: optimize reading index format v4
      config.txt: correct the note about uploadpack.packObjectsHook
      help -a: improve and make --verbose default
      refs.c: indent with tabs, not spaces
      Add a place for (not) sharing stuff between worktrees
      submodule.c: remove some of the_repository references
      completion: fix __gitcomp_builtin no longer consider extra options
      t1300: extract and use test_cmp_config()
      worktree: add per-worktree config files
      refs: new ref types to make per-worktree refs visible to all worktrees
      revision.c: correct a parameter name
      revision.c: better error reporting on ref from different worktrees
      fsck: check HEAD and reflog from other worktrees
      reflog expire: cover reflog from all worktrees
      Update makefile in preparation for Documentation/config/*.txt
      config.txt: move advice.* to a separate file
      config.txt: move core.* to a separate file
      config.txt: move add.* to a separate file
      config.txt: move alias.* to a separate file
      config.txt: move am.* to a separate file
      config.txt: move apply.* to a separate file
      config.txt: move blame.* to a separate file
      config.txt: move branch.* to a separate file
      config.txt: move browser.* to a separate file
      config.txt: move checkout.* to a separate file
      config.txt: move clean.* to a separate file
      config.txt: move color.* to a separate file
      config.txt: move column.* to a separate file
      config.txt: move commit.* to a separate file
      config.txt: move credential.* to a separate file
      config.txt: move completion.* to a separate file
      config.txt: move diff-config.txt to config/
      config.txt: move difftool.* to a separate file
      config.txt: move fastimport.* to a separate file
      config.txt: move fetch-config.txt to config/
      config.txt: move filter.* to a separate file
      config.txt: move format-config.txt to config/
      config.txt: move fmt-merge-msg-config.txt to config/
      config.txt: move fsck.* to a separate file
      config.txt: move gc.* to a separate file
      config.txt: move gitcvs-config.txt to config/
      config.txt: move gitweb.* to a separate file
      config.txt: move grep.* to a separate file
      config.txt: move gpg.* to a separate file
      config.txt: move gui-config.txt to config/
      config.txt: move guitool.* to a separate file
      config.txt: move help.* to a separate file
      config.txt: move ssh.* to a separate file
      config.txt: move http.* to a separate file
      config.txt: move i18n.* to a separate file
      git-imap-send.txt: move imap.* to a separate file
      config.txt: move index.* to a separate file
      config.txt: move init.* to a separate file
      config.txt: move instaweb.* to a separate file
      config.txt: move interactive.* to a separate file
      config.txt: move log.* to a separate file
      config.txt: move mailinfo.* to a separate file
      config.txt: move mailmap.* to a separate file
      config.txt: move man.* to a separate file
      config.txt: move merge-config.txt to config/
      config.txt: move mergetool.* to a separate file
      config.txt: move notes.* to a separate file
      config.txt: move pack.* to a separate file
      config.txt: move pager.* to a separate file
      config.txt: move pretty.* to a separate file
      config.txt: move protocol.* to a separate file
      config.txt: move pull-config.txt to config/
      config.txt: move push-config.txt to config/
      config.txt: move rebase-config.txt to config/
      config.txt: move receive-config.txt to config/
      config.txt: move remote.* to a separate file
      config.txt: move remotes.* to a separate file
      config.txt: move repack.* to a separate file
      config.txt: move rerere.* to a separate file
      config.txt: move reset.* to a separate file
      config.txt: move sendemail-config.txt to config/
      config.txt: move sequencer.* to a separate file
      config.txt: move showBranch.* to a separate file
      config.txt: move splitIndex.* to a separate file
      config.txt: move status.* to a separate file
      config.txt: move stash.* to a separate file
      config.txt: move submodule.* to a separate file
      config.txt: move tag.* to a separate file
      config.txt: move transfer.* to a separate file
      config.txt: move uploadarchive.* to a separate file
      config.txt: move uploadpack.* to a separate file
      config.txt: move url.* to a separate file
      config.txt: move user.* to a separate file
      config.txt: move versionsort.* to a separate file
      config.txt: move web.* to a separate file
      config.txt: move worktree.* to a separate file
      config.txt: remove config/dummy.txt
      thread-utils: macros to unconditionally compile pthreads API
      wildmatch: change behavior of "foo**bar" in WM_PATHNAME mode
      git-worktree.txt: correct linkgit command name
      sequencer.c: remove a stray semicolon
      tree-walk.c: fix overoptimistic inclusion in :(exclude) matching
      run-command.h: include thread-utils.h instead of pthread.h
      send-pack.c: move async's #ifdef NO_PTHREADS back to run-command.c
      index-pack: remove #ifdef NO_PTHREADS
      name-hash.c: remove #ifdef NO_PTHREADS
      attr.c: remove #ifdef NO_PTHREADS
      grep: remove #ifdef NO_PTHREADS
      grep: clean up num_threads handling
      preload-index.c: remove #ifdef NO_PTHREADS
      pack-objects: remove #ifdef NO_PTHREADS
      read-cache.c: remove #ifdef NO_PTHREADS
      read-cache.c: reduce branching based on HAVE_THREADS
      read-cache.c: initialize copy_len to shut up gcc 8
      Clean up pthread_create() error handling
      completion: use __gitcomp_builtin for format-patch
      build: fix broken command-list.h generation with core.autocrlf
      format-patch: respect --stat in cover letter's diffstat
      doc: move extensions.worktreeConfig to the right place
      clone: fix colliding file detection on APFS
      files-backend.c: fix build error on Solaris
      transport-helper.c: do not translate a string twice

Nickolai Belakovski (2):
      worktree: update documentation for lock_reason and lock_reason_valid
      worktree: rename is_worktree_locked to worktree_lock_reason

Noam Postavsky (1):
      log: fix coloring of certain octopus merge shapes

Olga Telezhnaya (3):
      ref-filter: free memory from used_atom
      ls-remote: release memory instead of UNLEAK
      ref-filter: free item->value and item->value->s

Peter Krefting (2):
      l10n: sv.po: Update Swedish translation (4185t0f0u)
      l10n: sv.po: Update Swedish translation (4187t0f0u)

Phillip Wood (11):
      diff: fix --color-moved-ws=allow-indentation-change
      diff --color-moved-ws: fix double free crash
      diff --color-moved-ws: fix out of bounds string access
      diff --color-moved-ws: fix a memory leak
      diff --color-moved-ws: fix another memory leak
      diff --color-moved: fix a memory leak
      am: don't die in read_author_script()
      am: improve author-script error reporting
      am: rename read_author_script()
      add read_author_script() to libgit
      sequencer: use read_author_script()

Pratik Karki (46):
      rebase: start implementing it as a builtin
      rebase: refactor common shell functions into their own file
      builtin/rebase: support running "git rebase <upstream>"
      builtin rebase: support --onto
      builtin rebase: support `git rebase --onto A...B`
      builtin rebase: handle the pre-rebase hook and --no-verify
      builtin rebase: support --quiet
      builtin rebase: support the `verbose` and `diffstat` options
      builtin rebase: require a clean worktree
      builtin rebase: try to fast forward when possible
      builtin rebase: support --force-rebase
      builtin rebase: start a new rebase only if none is in progress
      builtin rebase: only store fully-qualified refs in `options.head_name`
      builtin rebase: support `git rebase <upstream> <switch-to>`
      builtin rebase: support --continue
      builtin rebase: support --skip
      builtin rebase: support --abort
      builtin rebase: support --quit
      builtin rebase: support --edit-todo and --show-current-patch
      builtin rebase: actions require a rebase in progress
      builtin rebase: stop if `git am` is in progress
      builtin rebase: allow selecting the rebase "backend"
      builtin rebase: support --signoff
      builtin rebase: support --rerere-autoupdate
      builtin rebase: support --committer-date-is-author-date
      builtin rebase: support `ignore-whitespace` option
      builtin rebase: support `ignore-date` option
      builtin rebase: support `keep-empty` option
      builtin rebase: support `--autosquash`
      builtin rebase: support `--gpg-sign` option
      builtin rebase: support `-C` and `--whitespace=<type>`
      builtin rebase: support `--autostash` option
      builtin rebase: support `--exec`
      builtin rebase: support `--allow-empty-message` option
      builtin rebase: support --rebase-merges[=[no-]rebase-cousins]
      merge-base --fork-point: extract libified function
      builtin rebase: support `fork-point` option
      builtin rebase: add support for custom merge strategies
      builtin rebase: support --root
      builtin rebase: optionally auto-detect the upstream
      builtin rebase: optionally pass custom reflogs to reset_head()
      builtin rebase: fast-forward to onto if it is a proper descendant
      builtin rebase: show progress when connected to a terminal
      builtin rebase: use no-op editor when interactive is "implied"
      builtin rebase: error out on incompatible option/mode combinations
      rebase: default to using the builtin rebase

Rafael Ascensão (2):
      refs: show --exclude failure with --branches/tags/remotes=glob
      refs: fix some exclude patterns being ignored

Ralf Thielow (5):
      git-rebase.sh: fix typos in error messages
      l10n: update German translation
      builtin/rebase.c: remove superfluous space in messages
      l10n: update German translation
      l10n: de.po: fix two messages

Ramsay Jones (12):
      Makefile: add a hdr-check target
      json-writer.h: add missing include (hdr-check)
      ewah/ewok_rlw.h: add missing include (hdr-check)
      refs/ref-cache.h: add missing declarations (hdr-check)
      refs/packed-backend.h: add missing declaration (hdr-check)
      refs/refs-internal.h: add missing declarations (hdr-check)
      midx.h: add missing forward declarations (hdr-check)
      delta-islands.h: add missing forward declarations (hdr-check)
      headers: normalize the spelling of some header guards
      fetch-object.h: add missing declaration (hdr-check)
      ewok_rlw.h: add missing 'inline' to function definition
      commit-reach.h: add missing declarations (hdr-check)

Rasmus Villemoes (6):
      help: redirect to aliased commands for "git cmd --help"
      git.c: handle_alias: prepend alias info when first argument is -h
      git-help.txt: document "git help cmd" vs "git cmd --help" for aliases
      Documentation/git-send-email.txt: style fixes
      send-email: only consider lines containing @ or <> for automatic Cc'ing
      send-email: also pick up cc addresses from -by trailers

René Scharfe (12):
      mailinfo: support format=flowed
      fsck: add a performance test for skipList
      fsck: use strbuf_getline() to read skiplist file
      fsck: use oidset instead of oid_array for skipList
      sequencer: use return value of oidset_insert()
      grep: add -r/--[no-]recursive
      fetch-pack: factor out is_unmatched_ref()
      fetch-pack: load tip_oids eagerly iff needed
      khash: factor out kh_release_*
      oidset: use khash
      oidset: uninline oidset_init()
      commit-reach: fix cast in compare_commits_by_gen()

Roger Strain (1):
      subtree: performance improvement for finding unexpected parent commits

SZEDER Gábor (20):
      t1404: increase core.packedRefsTimeout to avoid occasional test failure
      Documentation/git.txt: clarify that GIT_TRACE=/path appends
      t3701-add-interactive: tighten the check of trace output
      t1700-split-index: drop unnecessary 'grep'
      t0090: disable GIT_TEST_SPLIT_INDEX for the test checking split index
      t1700-split-index: document why FSMONITOR is disabled in this test script
      split-index: add tests to demonstrate the racy split index problem
      t1700-split-index: date back files to avoid racy situations
      split-index: count the number of deleted entries
      split-index: don't compare cached data of entries already marked for split index
      split-index: smudge and add racily clean cache entries to split index
      split-index: BUG() when cache entry refers to non-existing shared entry
      object_id.cocci: match only expressions of type 'struct object_id'
      test-lib: introduce the '-V' short option for '--verbose-log'
      travis-ci: install packages in 'ci/install-dependencies.sh'
      coccicheck: introduce 'pending' semantic patches
      ref-filter: don't look for objects when outside of a repository
      tests: send "bug in the test script" errors to the script's stderr
      test-lib-functions: make 'test_cmp_rev' more informative on failure
      t/lib-git-daemon: fix signal checking

Sam McKelvie (1):
      rev-parse: --show-superproject-working-tree should work during a merge

Saulius Gurklys (1):
      doc: fix small typo in git show-branch

Sebastian Staudt (1):
      travis-ci: no longer use containers

Shulhan (1):
      builtin/remote: quote remote name on error to display empty name

Stefan Beller (25):
      git-submodule.sh: align error reporting for update mode to use path
      git-submodule.sh: rename unused variables
      builtin/submodule--helper: factor out submodule updating
      builtin/submodule--helper: store update_clone information in a struct
      builtin/submodule--helper: factor out method to update a single submodule
      submodule--helper: replace connect-gitdir-workingtree by ensure-core-worktree
      submodule--helper: introduce new update-module-mode helper
      test_decode_color: understand FAINT and ITALIC
      t3206: add color test for range-diff --dual-color
      diff.c: simplify caller of emit_line_0
      diff.c: reorder arguments for emit_line_ws_markup
      diff.c: add set_sign to emit_line_0
      diff: use emit_line_0 once per line
      diff.c: omit check for line prefix in emit_line_0
      diff.c: rewrite emit_line_0 more understandably
      diff.c: add --output-indicator-{new, old, context}
      range-diff: make use of different output indicators
      range-diff: indent special lines as context
      refs.c: migrate internal ref iteration to pass thru repository argument
      refs.c: upgrade for_each_replace_ref to be a each_repo_ref_fn callback
      string-list: remove unused function print_string_list
      strbuf.h: format according to coding guidelines
      diff.c: pass sign_index to emit_line_ws_markup
      submodule helper: convert relative URL to absolute URL if needed
      builtin/submodule--helper: remove debugging leftover tracing

Stephen P. Smith (10):
      wt-status.c: move has_unmerged earlier in the file
      wt-status: rename commitable to committable
      t7501: add test of "commit --dry-run --short"
      wt-status.c: set the committable flag in the collect phase
      roll wt_status_state into wt_status and populate in the collect phase
      t2000: rename and combine checkout clash tests
      t7509: cleanup description and filename
      t7502: rename commit test script to comply with naming convention
      t7500: rename commit tests script to comply with naming convention
      t7501: rename commit test to comply with naming convention

Steve Hoelzer (1):
      poll: use GetTickCount64() to avoid wrap-around issues

Steven Fernandez (1):
      git-completion.bash: add completion for stash list

Strain, Roger L (4):
      subtree: refactor split of a commit into standalone method
      subtree: make --ignore-joins pay attention to adds
      subtree: use commits before rejoins for splits
      subtree: improve decision on merges kept in split

Sven Strickroth (1):
      msvc: directly use MS version (_stricmp) of strcasecmp

Tao Qingyun (3):
      refs: docstring typo
      builtin/branch.c: remove useless branch_get
      branch: trivial style fix

Taylor Blau (4):
      transport.c: extract 'fill_alternate_refs_command'
      transport.c: introduce core.alternateRefsCommand
      transport.c: introduce core.alternateRefsPrefixes
      Documentation/config.txt: fix typo in core.alternateRefsCommand

Thomas Gummerer (17):
      rerere: unify error messages when read_cache fails
      rerere: lowercase error messages
      rerere: wrap paths in output in sq
      rerere: mark strings for translation
      rerere: add documentation for conflict normalization
      rerere: fix crash with files rerere can't handle
      rerere: only return whether a path has conflicts or not
      rerere: factor out handle_conflict function
      rerere: return strbuf from handle path
      rerere: teach rerere to handle nested conflicts
      rerere: recalculate conflict ID when unresolved conflict is committed
      rerere: mention caveat about unmatched conflict markers
      rerere: add note about files with existing conflict markers
      .gitattributes: add conflict-marker-size for relevant files
      linear-assignment: fix potential out of bounds memory access
      t5551: move setup code inside test_expect blocks
      t5551: compare sorted cookies files

Tim Schumacher (4):
      Documentation/Makefile: make manpage-base-url.xsl generation quieter
      alias: add support for aliases of an alias
      alias: show the call history when an alias is looping
      t0014: introduce an alias testing suite

Todd Zullinger (1):
      Documentation: build technical/multi-pack-index

Torsten Bögershausen (5):
      Make git_check_attr() a void function
      path.c: char is not (always) signed
      Upcast size_t variables to uintmax_t when printing
      remote-curl.c: xcurl_off_t is not portable (on 32 bit platfoms)
      t5601-99: Enable colliding file detection for MINGW

Trần Ngọc Quân (2):
      l10n: vi(4185t): Updated Vietnamese translation for v2.20.0
      l10n: vi(4187t): Updated Vietnamese translation for v2.20.0 rd3

Uwe Kleine-König (1):
      howto/using-merge-subtree: mention --allow-unrelated-histories

brian m. carlson (26):
      t: add test functions to translate hash-related values
      t0000: use hash translation table
      t0000: update tests for SHA-256
      t0002: abstract away SHA-1 specific constants
      t0064: make hash size independent
      t1006: make hash size independent
      t1400: switch hard-coded object ID to variable
      t1405: make hash size independent
      t1406: make hash-size independent
      t1407: make hash size independent
      editorconfig: provide editor settings for Git developers
      editorconfig: indicate settings should be kept in sync
      pack-bitmap-write: use GIT_MAX_RAWSZ for allocation
      builtin/repack: replace hard-coded constants
      builtin/mktree: remove hard-coded constant
      builtin/fetch-pack: remove constants with parse_oid_hex
      pack-revindex: express constants in terms of the_hash_algo
      packfile: express constants in terms of the_hash_algo
      refs/packed-backend: express constants using the_hash_algo
      upload-pack: express constants in terms of the_hash_algo
      transport: use parse_oid_hex instead of a constant
      tag: express constant in terms of the_hash_algo
      apply: replace hard-coded constants
      apply: rename new_sha1_prefix and old_sha1_prefix
      submodule: make zero-oid comparison hash function agnostic
      rerere: convert to use the_hash_algo

Ævar Arnfjörð Bjarmason (35):
      fetch: change "branch" to "reference" in --force -h output
      push tests: make use of unused $1 in test description
      push tests: use spaces in interpolated string
      fetch tests: add a test for clobbering tag behavior
      push doc: remove confusing mention of remote merger
      push doc: move mention of "tag <tag>" later in the prose
      push doc: correct lies about how push refspecs work
      fetch: document local ref updates with/without --force
      fetch: stop clobbering existing tags without --force
      fsck tests: setup of bogus commit object
      fsck tests: add a test for no skipList input
      fsck: document and test sorted skipList input
      fsck: document and test commented & empty line skipList input
      fsck: document that skipList input must be unabbreviated
      fsck: add a performance test
      fsck: support comments & empty lines in skipList
      commit-graph write: add progress output
      commit-graph verify: add progress output
      config doc: add missing list separator for checkout.optimizeNewBranch
      push doc: add spacing between two words
      fetch doc: correct grammar in --force docs
      gc: fix regression in 7b0f229222 impacting --quiet
      gc doc: mention the commit-graph in the intro
      pack-objects test: modernize style
      pack-objects tests: don't leave test .git corrupt at end
      index-pack tests: don't leave test repo dirty at end
      i18n: make GETTEXT_POISON a runtime option
      range-diff doc: add a section about output stability
      range-diff: fix regression in passing along diff options
      range-diff: make diff option behavior (e.g. --stat) consistent
      push: change needlessly ambiguous example in error
      rebase doc: document rebase.useBuiltin
      tests: add a special setup where rebase.useBuiltin is off
      read-cache: make the split index obey umask settings
      advice: don't pointlessly suggest --convert-graft-file

Đoàn Trần Công Danh (1):
      git-compat-util: prefer poll.h to sys/poll.h


^ permalink raw reply

* Re: What's cooking in git.git (Dec 2018, #01; Sun, 9)
From: Denton Liu @ 2018-12-09  9:03 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <xmqq8t0z3xcc.fsf@gitster-ct.c.googlers.com>

On Sun, Dec 09, 2018 at 05:42:27PM +0900, Junio C Hamano wrote:
> * dl/merge-cleanup-scissors-fix (2018-11-21) 2 commits
>   (merged to 'next' on 2018-11-21 at 217be06acb)
>  + merge: add scissors line on merge conflict
>  + t7600: clean up 'merge --squash c3 with c7' test
> 
>  The list of conflicted paths shown in the editor while concluding a
>  conflicted merge was shown above the scissors line when the
>  clean-up mode is set to "scissors", even though it was commented
>  out just like the list of updated paths and other information to
>  help the user explain the merge better.
> 
>  Will cook in 'next'.

From our discussion[1], expect a reroll with the ability to do scissors
cleanup in messages generated by git-merge. Unfortunately, it'll be a
couple of weeks because of finals season.

> 
> * dl/remote-save-to-push (2018-11-13) 1 commit
>  - remote: add --save-to-push option to git remote set-url
> 
>  "git remote set-url" learned a new option that moves existing value
>  of the URL field to pushURL field of the remote before replacing
>  the URL field with a new value.
> 
>  I am personally not yet quite convinced if this is worth pursuing.

Any way I could convince you otherwise? I guess this could be rolled
into a helper script but it'd be very useful to have the behaviour
standardised into the actual remote builtin.

[1]: https://public-inbox.org/git/xmqqin0n44dv.fsf@gitster-ct.c.googlers.com/

^ permalink raw reply

* [PATCH] style: the opening '{' of a function is in a separate line
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:25 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 bisect.c                   | 3 ++-
 builtin/config.c           | 3 ++-
 builtin/push.c             | 4 +++-
 convert.c                  | 3 ++-
 credential-cache--daemon.c | 3 ++-
 diff.c                     | 6 ++++--
 git.c                      | 3 ++-
 imap-send.c                | 3 ++-
 remote-curl.c              | 3 ++-
 sequencer.c                | 6 ++++--
 string-list.c              | 3 ++-
 t/helper/test-sigchain.c   | 3 ++-
 transport-helper.c         | 3 ++-
 url.c                      | 3 ++-
 userdiff.c                 | 3 ++-
 15 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/bisect.c b/bisect.c
index 487675c672..bd140cde36 100644
--- a/bisect.c
+++ b/bisect.c
@@ -558,7 +558,8 @@ struct commit_list *filter_skipped(struct commit_list *list,
  * is increased by one between each call, but that should not matter
  * for this application.
  */
-static unsigned get_prn(unsigned count) {
+static unsigned get_prn(unsigned count)
+{
 	count = count * 1103515245 + 12345;
 	return (count/65536) % PRN_MODULO;
 }
diff --git a/builtin/config.c b/builtin/config.c
index 84385ef165..99bc7ef64e 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -164,7 +164,8 @@ static NORETURN void usage_builtin_config(void)
 	usage_with_options(builtin_config_usage, builtin_config_options);
 }
 
-static void check_argc(int argc, int min, int max) {
+static void check_argc(int argc, int min, int max)
+{
 	if (argc >= min && argc <= max)
 		return;
 	if (min == max)
diff --git a/builtin/push.c b/builtin/push.c
index 8bb8a0849b..759812d1d5 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -143,7 +143,9 @@ static int push_url_of_remote(struct remote *remote, const char ***url_p)
 	return remote->url_nr;
 }
 
-static NORETURN int die_push_simple(struct branch *branch, struct remote *remote) {
+static NORETURN int die_push_simple(struct branch *branch,
+				    struct remote *remote)
+{
 	/*
 	 * There's no point in using shorten_unambiguous_ref here,
 	 * as the ambiguity would be on the remote side, not what
diff --git a/convert.c b/convert.c
index e0848226d2..bc40f01eb4 100644
--- a/convert.c
+++ b/convert.c
@@ -778,7 +778,8 @@ static int start_multi_file_filter_fn(struct subprocess_entry *subprocess)
 
 static void handle_filter_error(const struct strbuf *filter_status,
 				struct cmd2process *entry,
-				const unsigned int wanted_capability) {
+				const unsigned int wanted_capability)
+{
 	if (!strcmp(filter_status->buf, "error"))
 		; /* The filter signaled a problem with the file. */
 	else if (!strcmp(filter_status->buf, "abort") && wanted_capability) {
diff --git a/credential-cache--daemon.c b/credential-cache--daemon.c
index 4dfbc8c9f9..ec1271f89c 100644
--- a/credential-cache--daemon.c
+++ b/credential-cache--daemon.c
@@ -91,7 +91,8 @@ static timestamp_t check_expirations(void)
 }
 
 static int read_request(FILE *fh, struct credential *c,
-			struct strbuf *action, int *timeout) {
+			struct strbuf *action, int *timeout)
+{
 	static struct strbuf item = STRBUF_INIT;
 	const char *p;
 
diff --git a/diff.c b/diff.c
index dc9965e836..b5f573cf7a 100644
--- a/diff.c
+++ b/diff.c
@@ -1637,7 +1637,8 @@ static void emit_hunk_header(struct emit_callback *ecbdata,
 	strbuf_release(&msgbuf);
 }
 
-static struct diff_tempfile *claim_diff_tempfile(void) {
+static struct diff_tempfile *claim_diff_tempfile(void)
+{
 	int i;
 	for (i = 0; i < ARRAY_SIZE(diff_temp); i++)
 		if (!diff_temp[i].name)
@@ -4819,7 +4820,8 @@ static int parse_diff_filter_opt(const char *optarg, struct diff_options *opt)
 	return 0;
 }
 
-static void enable_patch_output(int *fmt) {
+static void enable_patch_output(int *fmt)
+{
 	*fmt &= ~DIFF_FORMAT_NO_OUTPUT;
 	*fmt |= DIFF_FORMAT_PATCH;
 }
diff --git a/git.c b/git.c
index 2f604a41ea..d69beaf3b0 100644
--- a/git.c
+++ b/git.c
@@ -98,7 +98,8 @@ static int list_cmds(const char *spec)
 	return 0;
 }
 
-static void commit_pager_choice(void) {
+static void commit_pager_choice(void)
+{
 	switch (use_pager) {
 	case 0:
 		setenv("GIT_PAGER", "cat", 1);
diff --git a/imap-send.c b/imap-send.c
index b4eb886e2a..18ca6ba10a 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -1471,7 +1471,8 @@ static CURL *setup_curl(struct imap_server_conf *srvc, struct credential *cred)
 }
 
 static int curl_append_msgs_to_imap(struct imap_server_conf *server,
-				    struct strbuf* all_msgs, int total) {
+				    struct strbuf* all_msgs, int total)
+{
 	int ofs = 0;
 	int n = 0;
 	struct buffer msgbuf = { STRBUF_INIT, 0 };
diff --git a/remote-curl.c b/remote-curl.c
index 1220dffcdc..90d565c8c5 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -617,7 +617,8 @@ static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
 	return err;
 }
 
-static curl_off_t xcurl_off_t(size_t len) {
+static curl_off_t xcurl_off_t(size_t len)
+{
 	uintmax_t size = len;
 	if (size > maximum_signed_value_of_type(curl_off_t))
 		die("cannot handle pushes this big");
diff --git a/sequencer.c b/sequencer.c
index e1a4dd15f1..55b609a7f4 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -1670,7 +1670,8 @@ static int update_squash_messages(enum todo_command command,
 	return res;
 }
 
-static void flush_rewritten_pending(void) {
+static void flush_rewritten_pending(void)
+{
 	struct strbuf buf = STRBUF_INIT;
 	struct object_id newoid;
 	FILE *out;
@@ -1695,7 +1696,8 @@ static void flush_rewritten_pending(void) {
 }
 
 static void record_in_rewritten(struct object_id *oid,
-		enum todo_command next_command) {
+		enum todo_command next_command)
+{
 	FILE *out = fopen_or_warn(rebase_path_rewritten_pending(), "a");
 
 	if (!out)
diff --git a/string-list.c b/string-list.c
index 1f6063f2a2..a917955fbd 100644
--- a/string-list.c
+++ b/string-list.c
@@ -155,7 +155,8 @@ static int item_is_not_empty(struct string_list_item *item, void *unused)
 	return *item->string != '\0';
 }
 
-void string_list_remove_empty_items(struct string_list *list, int free_util) {
+void string_list_remove_empty_items(struct string_list *list, int free_util)
+{
 	filter_string_list(list, free_util, item_is_not_empty, NULL);
 }
 
diff --git a/t/helper/test-sigchain.c b/t/helper/test-sigchain.c
index 77ac5bc33f..d013bccdda 100644
--- a/t/helper/test-sigchain.c
+++ b/t/helper/test-sigchain.c
@@ -14,7 +14,8 @@ X(two)
 X(three)
 #undef X
 
-int cmd__sigchain(int argc, const char **argv) {
+int cmd__sigchain(int argc, const char **argv)
+{
 	sigchain_push(SIGTERM, one);
 	sigchain_push(SIGTERM, two);
 	sigchain_push(SIGTERM, three);
diff --git a/transport-helper.c b/transport-helper.c
index bf225c698f..4702e150f0 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -1026,7 +1026,8 @@ static int push_refs(struct transport *transport,
 }
 
 
-static int has_attribute(const char *attrs, const char *attr) {
+static int has_attribute(const char *attrs, const char *attr)
+{
 	int len;
 	if (!attrs)
 		return 0;
diff --git a/url.c b/url.c
index eaf4f07081..25576c390b 100644
--- a/url.c
+++ b/url.c
@@ -104,7 +104,8 @@ void end_url_with_slash(struct strbuf *buf, const char *url)
 	strbuf_complete(buf, '/');
 }
 
-void str_end_url_with_slash(const char *url, char **dest) {
+void str_end_url_with_slash(const char *url, char **dest)
+{
 	struct strbuf buf = STRBUF_INIT;
 	end_url_with_slash(&buf, url);
 	free(*dest);
diff --git a/userdiff.c b/userdiff.c
index 46d34cc2a4..e0579522bd 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -265,7 +265,8 @@ int userdiff_config(const char *k, const char *v)
 	return 0;
 }
 
-struct userdiff_driver *userdiff_find_by_name(const char *name) {
+struct userdiff_driver *userdiff_find_by_name(const char *name)
+{
 	int len = strlen(name);
 	return userdiff_find_by_namelen(name, len);
 }
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH] parse-options: fix SunCC compiler warning
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:27 UTC (permalink / raw)
  To: avarab; +Cc: git, gitster, pclouds, sunshine, szeder.dev
In-Reply-To: <87va4cujtx.fsf@evledraar.gmail.com>

The compiler reports this because show_gitcomp() never actually
returns a value:

    "parse-options.c", line 520: warning: Function has no return
    statement : show_gitcomp

The function calls exit() and will never return. Update and mark it
NORETURN.

Reported-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 parse-options.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/parse-options.c b/parse-options.c
index 3b874a83a0..6577e52f63 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -474,8 +474,8 @@ static void show_negated_gitcomp(const struct option *opts, int nr_noopts)
 	}
 }
 
-static int show_gitcomp(struct parse_opt_ctx_t *ctx,
-			const struct option *opts)
+static void NORETURN show_gitcomp(struct parse_opt_ctx_t *ctx,
+				  const struct option *opts)
 {
 	const struct option *original_opts = opts;
 	int nr_noopts = 0;
@@ -550,7 +550,7 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
 
 		/* lone --git-completion-helper is asked by git-completion.bash */
 		if (ctx->total == 1 && !strcmp(arg + 1, "-git-completion-helper"))
-			return show_gitcomp(ctx, options);
+			show_gitcomp(ctx, options);
 
 		if (arg[1] != '-') {
 			ctx->opt = arg + 1;
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [RFC PATCH 00/24] Add backup log
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:43 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

"Backup log" is similar to reflog. But instead of keeping track of ref
changes, it keeps track of file content changes. These could be from
the index (e.g. "git add" replacing something in the index), worktree
("git reset --hard" deleting everything) or in gitdir ("git config
--edit", or deleted reflog).

Backup log, when enabled, keeps the backup versions so you can undo if
needed. Head for 01/24 to have a better picture what it does, when
backups are made... This series adds a new plumbing command 'git
backup-log' to manage these backups.

A couple things left to do:

- high level UI design, including maybe extended SHA-1 syntax
- whether "git checkout <paths>" should keep backups. I think doing it
  unconditionally may be too much, but maybe keep backups of files
  with "precious" attribute on
- a UI to edit $GIT_DIR/info/excludes and gitattributes so we can make
  backups of them
- whether we should keep command causing the changes in the backup log
  (e.g. this change is made by git-add, that one git-rebase...).
  Reflog has this. I did not add it because it complicates the parsing
  a bit and not sure if it's worth it.

Nguyễn Thái Ngọc Duy (24):
  doc: introduce new "backup log" concept
  backup-log: add "update" subcommand
  read-cache.c: new flag for add_index_entry() to write to backup log
  add: support backup log
  update-index: support backup log with --keep-backup
  commit: support backup log
  apply: support backup log with --keep-backup
  add--interactive: support backup log
  backup-log.c: add API for walking backup log
  backup-log: add cat command
  backup-log: add diff command
  backup-log: add log command
  backup-log: add prune command
  gc: prune backup logs
  backup-log: keep all blob references around
  sha1-file.c: let index_path() accept NULL istate
  config --edit: support backup log
  refs: keep backup of deleted reflog
  unpack-trees.c: keep backup of ignored files being overwritten
  reset --hard: keep backup of overwritten files
  checkout -f: keep backup of overwritten files
  am: keep backup of overwritten files on --skip or --abort
  rebase: keep backup of overwritten files on --skip or --abort
  FIXME

 .gitignore                         |   1 +
 Documentation/config/core.txt      |   5 +
 Documentation/git-apply.txt        |   3 +
 Documentation/git-backup-log.txt   | 109 ++++++++
 Documentation/git-update-index.txt |   3 +
 Makefile                           |   2 +
 apply.c                            |  38 ++-
 apply.h                            |   1 +
 backup-log.c                       | 388 +++++++++++++++++++++++++++++
 backup-log.h                       |  38 +++
 builtin.h                          |   1 +
 builtin/add.c                      |   5 +
 builtin/am.c                       |   3 +
 builtin/backup-log.c               | 371 +++++++++++++++++++++++++++
 builtin/checkout.c                 |   4 +
 builtin/commit.c                   |  16 +-
 builtin/config.c                   |  27 +-
 builtin/gc.c                       |   3 +
 builtin/pack-objects.c             |   9 +-
 builtin/rebase.c                   |   6 +-
 builtin/repack.c                   |   1 +
 builtin/reset.c                    |   2 +
 builtin/update-index.c             |   7 +
 cache.h                            |   2 +
 command-list.txt                   |   1 +
 git-add--interactive.perl          |  14 +-
 git.c                              |   1 +
 merge-recursive.c                  |   2 +-
 merge.c                            |   2 +
 parse-options.c                    |   2 +-
 reachable.c                        |   3 +
 read-cache.c                       |  49 +++-
 refs/files-backend.c               |  32 +++
 revision.c                         |   3 +
 sha1-file.c                        |   8 +-
 t/t2080-backup-log.sh              | 228 +++++++++++++++++
 unpack-trees.c                     | 143 +++++++++--
 unpack-trees.h                     |   6 +-
 38 files changed, 1488 insertions(+), 51 deletions(-)
 create mode 100644 Documentation/git-backup-log.txt
 create mode 100644 backup-log.c
 create mode 100644 backup-log.h
 create mode 100644 builtin/backup-log.c
 create mode 100755 t/t2080-backup-log.sh

-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply

* [PATCH 01/24] doc: introduce new "backup log" concept
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:43 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

A reflog file records changes of a certain ref over time. A backup log
file does a similar job, but it records changes of some files over time.
This is the main idea of it.

This is added so that we can support undoing certain changes. For
example, if you have carefully prepared your index with "git add -p"
then accidentally do "git commit -a", your well crafted index is lost
with no easy way to recover it. We could go the other way and make
"git commit -a" complain loudly, but that has other bad side effects,
the big one is we may complain too loudly at the wrong time and too
often. This "do the right things (most of the time) but allow the
user to undo when we get it wrong" approach seems more inline with how
git handles other things.

The current plan is to have three backup log files:

- $GIT_DIR/index.bkl contains "interesting" changes made in the index.

- $GIT_DIR/worktree.bkl contains "interesting" changes made in
  worktree.

- $GIT_DIR/common/gitdir.bkl contains changes made in other files
  inside $GIT_DIR such as config, those in info/ directory, or reflog
  file deletion (aka the mystical reflog graveyard)

All these only record "interesting" changes which will be defined
later. But a few examples of them are: "git add -p" is interesting,
but "git reset HEAD" is not. Similarly changes made in $GIT_DIR/config
are usually interesting.

This patch does none of that! It adds a new man page for a new
plumbing command "git backup-log" which does show what this
functionality looks like.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/config/core.txt    |   5 ++
 Documentation/git-backup-log.txt | 107 +++++++++++++++++++++++++++++++
 2 files changed, 112 insertions(+)
 create mode 100644 Documentation/git-backup-log.txt

diff --git a/Documentation/config/core.txt b/Documentation/config/core.txt
index d0e6635fe0..63b78cc048 100644
--- a/Documentation/config/core.txt
+++ b/Documentation/config/core.txt
@@ -316,6 +316,11 @@ This value is true by default in a repository that has
 a working directory associated with it, and false by
 default in a bare repository.
 
+core.backupLog::
+	If true, many commands will keep backup content in object database
+	before they modify some file. See linkgit:git-backup-log[1] for more
+	information.
+
 core.repositoryFormatVersion::
 	Internal variable identifying the repository format and layout
 	version.
diff --git a/Documentation/git-backup-log.txt b/Documentation/git-backup-log.txt
new file mode 100644
index 0000000000..98998156c1
--- /dev/null
+++ b/Documentation/git-backup-log.txt
@@ -0,0 +1,107 @@
+git-backup-log(1)
+=================
+
+NAME
+----
+git-backup-log - Manage backup log files
+
+
+SYNOPSIS
+--------
+[verse]
+'git backup-log' [--id=<id> | --path=<path>] log [<rev-options>] [[--] <path>...]
+'git backup-log' [--id=<id> | --path=<path>] cat [--before] [--hash] <change-id> <path>
+'git backup-log' [--id=<id> | --path=<path>] diff [<diff-options>] <change-id>
+'git backup-log' [--id=<id> | --path=<path>] prune [--expire=<time>]
+'git backup-log' [--id=<id> | --path=<path>] update <path> <old-hash> <new-hash>
+
+DESCRIPTION
+-----------
+Backup log records changes of certain files in the object database so
+that if some file is overwritten by accident, you could still get the
+original content back.
+
+Backup log is enabled by setting core.backupLog to true and the
+following commands will save backups:
+
+- linkgit:git-add[1] keeps all index changes. File removal is not
+  recorded.
+- linkgit:git-commit[1] keep all index changes in `-a` or partial
+  commit mode.
+- linkgit:git-apply[1] and linkgit:git-update-index[1] will keep
+  changes if `--keep-backup` is specified
+- Changes of `$GIT_DIR/config` made by `git config --edit` are kept.
+- Deleted reflogs are kept. References from this deleted reflog will
+  not be kept at the next garbage collection though. This is mostly
+  meant to immediately undo an accidental branch deletion.
+- linkgit:git-checkout[1] when switching branches and
+  linkgit:git-merge[1] will make a backup before overwriting
+  ignored files.
+- linkgit:git-checkout[1] with `--force`, linkgit:git-reset[1] with
+  `--hard` or linkgit:git-am[1] and linkgit:git-rebase[1] with
+  `--skip` or `--abort` will make a backup before overwriting non
+  up-to-date files.
+
+Backups are split in three groups, changes related in the index, in
+working directory or in $GIT_DIR. These can be selected with `--id`
+parameter as `index`, `worktree` and `gitdir` respectively.
+Alternatively file path of these are `$GIT_DIR/index.bkl`,
+`$GIT_DIR/worktree.bkl` and `$GIT_DIR/common/gitdir.bkl` which could
+be specified with `--path`
+
+This command is split into subcommands:
+
+update::
+	Add a new change associated with `<path>` from `<old-hash>` to
+	`<new-hash>` to the selected backup log file. `<path>` must be
+	normalized.
+
+log::
+	View the selected backup log (optionally filtered by pathspec).
+	By default, the diff of the change is shown.
+
+cat::
+	Output the file content or their object name of a specific
+	change.
+
+diff::
+	Output the diff of a specific change.
+
+prune::
+	Prune the backup log, delete updates older than a specific
+	time or invalid entries. The actual backup content is still in
+	the object database and may need to be pruned separatedly.
+
+OPTIONS
+-------
+
+--id=<id>::
+	The name of the the backup log file. Supported names are
+	`index`, `worktree` and `gitdir`.
+
+--path=<path>::
+	The path of a backup log file.
+
+--before::
+	Show the version before the change instead. This is most
+	useful when the change is a file deletion.
+
+--hash::
+	Show the object name instead of content.
+
+--expire=<time>::
+	The cutoff time for pruning backup log. The default is three
+	months ago.
+
+<path>::
+	The path of the file where the change is made.
+
+<old-hash>::
+	The blob hash of the content before the change.
+
+<old-hash>::
+	The blob hash of the content after the change.
+
+GIT
+---
+Part of the linkgit:git[1] suite
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH 02/24] backup-log: add "update" subcommand
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:43 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

This defines backup log file format and adds basic support for writing
new entries to backup log files. The format is the same as reflog
except that "message" field becomes "path".

Similar to reflog, updating is done by appending to the end of the file
instead of creating a branch new file and do an atomic rename. If the
backup log file gets large, regenerating whole file could take longer,
and we should keep backup log overhead to minimum since it will be
called by a bunch of commands later.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 .gitignore            |  1 +
 Makefile              |  2 ++
 backup-log.c          | 46 ++++++++++++++++++++++++
 backup-log.h          | 13 +++++++
 builtin.h             |  1 +
 builtin/backup-log.c  | 81 +++++++++++++++++++++++++++++++++++++++++++
 command-list.txt      |  1 +
 git.c                 |  1 +
 parse-options.c       |  2 +-
 t/t2080-backup-log.sh | 20 +++++++++++
 10 files changed, 167 insertions(+), 1 deletion(-)
 create mode 100644 backup-log.c
 create mode 100644 backup-log.h
 create mode 100644 builtin/backup-log.c
 create mode 100755 t/t2080-backup-log.sh

diff --git a/.gitignore b/.gitignore
index 0d77ea5894..9c0427c709 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@
 /git-apply
 /git-archimport
 /git-archive
+/git-backup-log
 /git-bisect
 /git-bisect--helper
 /git-blame
diff --git a/Makefile b/Makefile
index 1a44c811aa..d1e1a925c3 100644
--- a/Makefile
+++ b/Makefile
@@ -836,6 +836,7 @@ LIB_OBJS += archive-tar.o
 LIB_OBJS += archive-zip.o
 LIB_OBJS += argv-array.o
 LIB_OBJS += attr.o
+LIB_OBJS += backup-log.o
 LIB_OBJS += base85.o
 LIB_OBJS += bisect.o
 LIB_OBJS += blame.o
@@ -1027,6 +1028,7 @@ BUILTIN_OBJS += builtin/am.o
 BUILTIN_OBJS += builtin/annotate.o
 BUILTIN_OBJS += builtin/apply.o
 BUILTIN_OBJS += builtin/archive.o
+BUILTIN_OBJS += builtin/backup-log.o
 BUILTIN_OBJS += builtin/bisect--helper.o
 BUILTIN_OBJS += builtin/blame.o
 BUILTIN_OBJS += builtin/branch.o
diff --git a/backup-log.c b/backup-log.c
new file mode 100644
index 0000000000..c1e805b09e
--- /dev/null
+++ b/backup-log.c
@@ -0,0 +1,46 @@
+#include "cache.h"
+#include "backup-log.h"
+#include "lockfile.h"
+#include "strbuf.h"
+
+void bkl_append(struct strbuf *output, const char *path,
+		const struct object_id *from,
+		const struct object_id *to)
+{
+	if (oideq(from, to))
+		return;
+
+	strbuf_addf(output, "%s %s %s\t%s\n", oid_to_hex(from),
+		    oid_to_hex(to), git_committer_info(0), path);
+}
+
+static int bkl_write_unlocked(const char *path, struct strbuf *new_log)
+{
+	int fd = open(path, O_CREAT | O_WRONLY | O_APPEND, 0666);
+	if (fd == -1)
+		return error_errno(_("unable to open %s"), path);
+	if (write_in_full(fd, new_log->buf, new_log->len) < 0) {
+		close(fd);
+		return error_errno(_("unable to update %s"), path);
+	}
+	close(fd);
+	return 0;
+}
+
+int bkl_write(const char *path, struct strbuf *new_log)
+{
+	struct lock_file lk;
+	int ret;
+
+	ret = hold_lock_file_for_update(&lk, path, LOCK_REPORT_ON_ERROR);
+	if (ret == -1)
+		return -1;
+	ret = bkl_write_unlocked(path, new_log);
+	/*
+	 * We do not write the the .lock file and append to the real one
+	 * instead to reduce update cost. So we can't commit even in
+	 * successful case.
+	 */
+	rollback_lock_file(&lk);
+	return ret;
+}
diff --git a/backup-log.h b/backup-log.h
new file mode 100644
index 0000000000..5e475d6f35
--- /dev/null
+++ b/backup-log.h
@@ -0,0 +1,13 @@
+#ifndef __BACKUP_LOG_H__
+#define __BACKUP_LOG_H__
+
+struct object_id;
+struct strbuf;
+
+void bkl_append(struct strbuf *output, const char *path,
+		const struct object_id *from,
+		const struct object_id *to);
+
+int bkl_write(const char *path, struct strbuf *new_log);
+
+#endif
diff --git a/builtin.h b/builtin.h
index 6538932e99..4e16c52bfa 100644
--- a/builtin.h
+++ b/builtin.h
@@ -132,6 +132,7 @@ extern int cmd_am(int argc, const char **argv, const char *prefix);
 extern int cmd_annotate(int argc, const char **argv, const char *prefix);
 extern int cmd_apply(int argc, const char **argv, const char *prefix);
 extern int cmd_archive(int argc, const char **argv, const char *prefix);
+extern int cmd_backup_log(int argc, const char **argv, const char *prefix);
 extern int cmd_bisect__helper(int argc, const char **argv, const char *prefix);
 extern int cmd_blame(int argc, const char **argv, const char *prefix);
 extern int cmd_branch(int argc, const char **argv, const char *prefix);
diff --git a/builtin/backup-log.c b/builtin/backup-log.c
new file mode 100644
index 0000000000..75a02c8878
--- /dev/null
+++ b/builtin/backup-log.c
@@ -0,0 +1,81 @@
+#include "cache.h"
+#include "builtin.h"
+#include "backup-log.h"
+#include "parse-options.h"
+
+static char const * const backup_log_usage[] = {
+	N_("git backup-log [--path=<path> | --id=<id>] update <path> <old-hash> <new-hash>"),
+	NULL
+};
+
+static int update(int argc, const char **argv,
+		  const char *prefix, const char *log_path)
+{
+	struct strbuf sb = STRBUF_INIT;
+	struct object_id oid_from, oid_to;
+	const char *path;
+	int ret;
+
+	if (argc != 4)
+		usage_with_options(backup_log_usage, NULL);
+
+	path = argv[1];
+
+	if (get_oid(argv[2], &oid_from))
+		die(_("not a valid object name: %s"), argv[2]);
+
+	if (get_oid(argv[3], &oid_to))
+		die(_("not a valid object name: %s"), argv[3]);
+
+	bkl_append(&sb, path, &oid_from, &oid_to);
+	ret = bkl_write(log_path, &sb);
+	strbuf_release(&sb);
+
+	return ret;
+}
+
+static char *log_id_to_path(const char *id)
+{
+	if (!strcmp(id, "index"))
+		return git_pathdup("index.bkl");
+	else if (!strcmp(id, "worktree"))
+		return git_pathdup("worktree.bkl");
+	else if (!strcmp(id, "gitdir"))
+		return git_pathdup("common/gitdir.bkl");
+	else
+		die(_("backup log id '%s' is not recognized"), id);
+}
+
+int cmd_backup_log(int argc, const char **argv, const char *prefix)
+{
+	const char *log_id = NULL;
+	const char *log_path = NULL;
+	char *to_free = NULL;
+	struct option common_opts[] = {
+		OPT_STRING(0, "id", &log_id, N_("id"), N_("backup log file id")),
+		OPT_FILENAME(0, "path", &log_path, N_("backup log file path")),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, prefix, common_opts,
+			     backup_log_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+	if (!argc)
+		die(_("expected a subcommand"));
+
+	if (log_id) {
+		if (log_path)
+			die(_("--id and --path are incompatible"));
+		log_path = to_free = log_id_to_path(log_id);
+	}
+	if (!log_path)
+		die(_("either --id or --path is required"));
+
+	if (!strcmp(argv[0], "update"))
+		return update(argc, argv, prefix, log_path);
+	else
+		die(_("unknown subcommand: %s"), argv[0]);
+
+	free(to_free);
+	return 0;
+}
diff --git a/command-list.txt b/command-list.txt
index 3a9af104b5..d4162f73d5 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -51,6 +51,7 @@ git-annotate                            ancillaryinterrogators
 git-apply                               plumbingmanipulators            complete
 git-archimport                          foreignscminterface
 git-archive                             mainporcelain
+git-backup-log                          plumbinginterrogators
 git-bisect                              mainporcelain           info
 git-blame                               ancillaryinterrogators          complete
 git-branch                              mainporcelain           history
diff --git a/git.c b/git.c
index 2f604a41ea..d46d22c8b1 100644
--- a/git.c
+++ b/git.c
@@ -447,6 +447,7 @@ static struct cmd_struct commands[] = {
 	{ "annotate", cmd_annotate, RUN_SETUP | NO_PARSEOPT },
 	{ "apply", cmd_apply, RUN_SETUP_GENTLY },
 	{ "archive", cmd_archive, RUN_SETUP_GENTLY },
+	{ "backup-log", cmd_backup_log, RUN_SETUP_GENTLY },
 	{ "bisect--helper", cmd_bisect__helper, RUN_SETUP },
 	{ "blame", cmd_blame, RUN_SETUP },
 	{ "branch", cmd_branch, RUN_SETUP | DELAY_PAGER_CONFIG },
diff --git a/parse-options.c b/parse-options.c
index 3b874a83a0..e1fc080cc3 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -705,7 +705,7 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *ctx,
 
 	need_newline = 1;
 
-	for (; opts->type != OPTION_END; opts++) {
+	for (; opts && opts->type != OPTION_END; opts++) {
 		size_t pos;
 		int pad;
 
diff --git a/t/t2080-backup-log.sh b/t/t2080-backup-log.sh
new file mode 100755
index 0000000000..267c34bb25
--- /dev/null
+++ b/t/t2080-backup-log.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+test_description='backup-log'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	test_commit initial &&
+	mkdir sub
+'
+
+test_expect_success 'backup-log add new item' '
+	ID=$(git rev-parse HEAD:./initial.t) &&
+	test_tick &&
+	git -C sub backup-log --id=index update foo $ZERO_OID $ID &&
+	echo "$ZERO_OID $ID $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $test_tick -0700	foo" >expected &&
+	test_cmp expected .git/index.bkl
+'
+
+test_done
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH 03/24] read-cache.c: new flag for add_index_entry() to write to backup log
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:43 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

Index update API is updated to write to backup log if requested. The
entry deletion API is not updated because file removal is not
"interesting" from the undo point of view.

Note, we do double locking when writing $GIT_DIR/index now:

- $GIT_DIR/index.lock is created
- then $GIT_DIR/index.bkl.lock is created

Nobody will lock these in reverse order so no chance for dead lock
(yet)

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 cache.h      |  2 ++
 read-cache.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/cache.h b/cache.h
index ca36b44ee0..51ffae7961 100644
--- a/cache.h
+++ b/cache.h
@@ -336,6 +336,7 @@ struct index_state {
 	uint64_t fsmonitor_last_update;
 	struct ewah_bitmap *fsmonitor_dirty;
 	struct mem_pool *ce_mem_pool;
+	struct strbuf *backup_log;
 };
 
 extern struct index_state the_index;
@@ -745,6 +746,7 @@ extern int index_name_pos(const struct index_state *, const char *name, int name
 #define ADD_CACHE_JUST_APPEND 8		/* Append only; tree.c::read_tree() */
 #define ADD_CACHE_NEW_ONLY 16		/* Do not replace existing ones */
 #define ADD_CACHE_KEEP_CACHE_TREE 32	/* Do not invalidate cache-tree */
+#define ADD_CACHE_LOG_UPDATES 64	/* Log changes in $GIT_DIR/index.bkl */
 extern int add_index_entry(struct index_state *, struct cache_entry *ce, int option);
 extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
 
diff --git a/read-cache.c b/read-cache.c
index bd45dc3e24..a53cfabc2e 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -25,6 +25,7 @@
 #include "fsmonitor.h"
 #include "thread-utils.h"
 #include "progress.h"
+#include "backup-log.h"
 
 /* Mask for the name length in ce_flags in the on-disk index */
 
@@ -691,6 +692,21 @@ void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)
 	oidcpy(&ce->oid, &oid);
 }
 
+static void update_backup_log(struct index_state *istate,
+			      const struct object_id *prev,
+			      const struct cache_entry *ce)
+{
+	struct strbuf *sb = istate->backup_log;
+
+	if (!sb) {
+		sb = xmalloc(sizeof(*sb));
+		strbuf_init(sb, 0);
+		istate->backup_log = sb;
+	}
+
+	bkl_append(sb, ce->name, prev, &ce->oid);
+}
+
 int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)
 {
 	int namelen, was_same;
@@ -765,6 +781,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
 			discard_cache_entry(ce);
 			return error("unable to index file %s", path);
 		}
+		add_option |= flags & ADD_CACHE_LOG_UPDATES;
 	} else
 		set_object_name_for_intent_to_add_entry(ce);
 
@@ -1257,6 +1274,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
 	int ok_to_replace = option & ADD_CACHE_OK_TO_REPLACE;
 	int skip_df_check = option & ADD_CACHE_SKIP_DFCHECK;
 	int new_only = option & ADD_CACHE_NEW_ONLY;
+	struct object_id backup_prev;
 
 	if (!(option & ADD_CACHE_KEEP_CACHE_TREE))
 		cache_tree_invalidate_path(istate, ce->name);
@@ -1273,8 +1291,12 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
 
 	/* existing match? Just replace it. */
 	if (pos >= 0) {
-		if (!new_only)
-			replace_index_entry(istate, pos, ce);
+		if (new_only)
+			return 0;
+
+		if (option & ADD_CACHE_LOG_UPDATES)
+			update_backup_log(istate, &istate->cache[pos]->oid, ce);
+		replace_index_entry(istate, pos, ce);
 		return 0;
 	}
 	pos = -pos-1;
@@ -1282,6 +1304,7 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
 	if (!(option & ADD_CACHE_KEEP_CACHE_TREE))
 		untracked_cache_add_to_index(istate, ce->name);
 
+	oidclr(&backup_prev);
 	/*
 	 * Inserting a merged entry ("stage 0") into the index
 	 * will always replace all non-merged entries..
@@ -1289,6 +1312,8 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
 	if (pos < istate->cache_nr && ce_stage(ce) == 0) {
 		while (ce_same_name(istate->cache[pos], ce)) {
 			ok_to_add = 1;
+			if (ce_stage(ce) == 2)
+				oidcpy(&backup_prev, &istate->cache[pos]->oid);
 			if (!remove_index_entry_at(istate, pos))
 				break;
 		}
@@ -1307,6 +1332,8 @@ static int add_index_entry_with_check(struct index_state *istate, struct cache_e
 		pos = index_name_stage_pos(istate, ce->name, ce_namelen(ce), ce_stage(ce));
 		pos = -pos-1;
 	}
+	if (option & ADD_CACHE_LOG_UPDATES)
+		update_backup_log(istate, &backup_prev, ce);
 	return pos + 1;
 }
 
@@ -2323,6 +2350,10 @@ int discard_index(struct index_state *istate)
 	discard_split_index(istate);
 	free_untracked_cache(istate->untracked);
 	istate->untracked = NULL;
+	if (istate->backup_log) {
+		strbuf_release(istate->backup_log);
+		FREE_AND_NULL(istate->backup_log);
+	}
 
 	if (istate->ce_mem_pool) {
 		mem_pool_discard(istate->ce_mem_pool, should_validate_cache_entries());
@@ -3157,6 +3188,20 @@ int write_locked_index(struct index_state *istate, struct lock_file *lock,
 	if (istate->fsmonitor_last_update)
 		fill_fsmonitor_bitmap(istate);
 
+	if (istate->backup_log && istate->backup_log->len) {
+		struct strbuf sb = STRBUF_INIT;
+		char *path = get_locked_file_path(lock);
+
+		strbuf_addf(&sb, "%s.bkl", path);
+		free(path);
+		if (bkl_write(sb.buf, istate->backup_log)) {
+			strbuf_release(&sb);
+			return -1;
+		}
+		strbuf_reset(istate->backup_log);
+		strbuf_release(&sb);
+	}
+
 	if (!si || alternate_index_output ||
 	    (istate->cache_changed & ~EXTMASK)) {
 		if (si)
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH 04/24] add: support backup log
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:43 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

There is not much to say about the actual change in this patch, which
is straightforward. There is something to say about the lack of change
though.

The definition of "interesting" changes to keep in backup log
previously is "file modification, except file removal". It is further
refined: only changes coming from worktree (for from the user to be
more accurate) are interesting. Changes in the index from object
database (e.g. merging, switching branches, resetting...) are not
interesting because the actual content is already in the object
database and can be recovered (provided that you still have the
history of commands you used, of course)

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/add.c         |  5 +++++
 t/t2080-backup-log.sh | 11 +++++++++++
 2 files changed, 16 insertions(+)

diff --git a/builtin/add.c b/builtin/add.c
index f65c172299..f21d9efdd9 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -393,6 +393,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 	int require_pathspec;
 	char *seen = NULL;
 	struct lock_file lock_file = LOCK_INIT;
+	int core_backup_log = 0;
 
 	git_config(add_config, NULL);
 
@@ -439,6 +440,10 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 		 (!(addremove || take_worktree_changes)
 		  ? ADD_CACHE_IGNORE_REMOVAL : 0));
 
+	repo_config_get_bool(the_repository, "core.backuplog", &core_backup_log);
+	if (core_backup_log)
+		flags |= ADD_CACHE_LOG_UPDATES;
+
 	if (require_pathspec && argc == 0) {
 		fprintf(stderr, _("Nothing specified, nothing added.\n"));
 		fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
diff --git a/t/t2080-backup-log.sh b/t/t2080-backup-log.sh
index 267c34bb25..f7bdaaa3f6 100755
--- a/t/t2080-backup-log.sh
+++ b/t/t2080-backup-log.sh
@@ -17,4 +17,15 @@ test_expect_success 'backup-log add new item' '
 	test_cmp expected .git/index.bkl
 '
 
+test_expect_success 'add writes backup log' '
+	test_tick &&
+	echo update >>initial.t &&
+	OLD=$(git rev-parse :./initial.t) &&
+	NEW=$(git hash-object initial.t) &&
+	git -c core.backupLog=true add initial.t &&
+	echo "$OLD $NEW $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $test_tick -0700	initial.t" >expected &&
+	tail -n1 .git/index.bkl >actual &&
+	test_cmp expected actual
+'
+
 test_done
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH 05/24] update-index: support backup log with --keep-backup
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:44 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

Since this is a plumbing command, backup log support remains off by
default and only active when both --keep-backup and core.backupLog=true
are specified.

The check of core.backupLog is mostly for convenient, the calling script
does not have to explicitly check core.backupLog every time it executes
update-index. Truly disabling backup log must be done with something
like

    git -c core.backupLog=false update-index ...

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/git-update-index.txt |  3 +++
 builtin/update-index.c             |  7 +++++++
 t/t2080-backup-log.sh              | 11 +++++++++++
 3 files changed, 21 insertions(+)

diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
index 1c4d146a41..31fe330c88 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -218,6 +218,9 @@ will remove the intended effect of the option.
 	the configured value will take effect next time the index is
 	read and this will remove the intended effect of the option.
 
+--keep-backup::
+	Enable index backup log.
+
 \--::
 	Do not interpret any more arguments as options.
 
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 31e7cce301..295b5f5277 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -28,6 +28,8 @@
 static int allow_add;
 static int allow_remove;
 static int allow_replace;
+static int update_backup_log;
+static int core_backup_log;
 static int info_only;
 static int force_remove;
 static int verbose;
@@ -289,6 +291,7 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len
 	}
 	option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
 	option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
+	option |= update_backup_log && core_backup_log ? ADD_CACHE_LOG_UPDATES : 0;
 	if (add_cache_entry(ce, option)) {
 		discard_cache_entry(ce);
 		return error("%s: cannot add to the index - missing --add option?", path);
@@ -419,6 +422,7 @@ static int add_cacheinfo(unsigned int mode, const struct object_id *oid,
 		ce->ce_flags |= CE_VALID;
 	option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
 	option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
+	option |= update_backup_log && core_backup_log ? ADD_CACHE_LOG_UPDATES : 0;
 	if (add_cache_entry(ce, option))
 		return error("%s: cannot add to the index - missing --add option?",
 			     path);
@@ -969,6 +973,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
 			N_("let files replace directories and vice-versa"), 1),
 		OPT_SET_INT(0, "remove", &allow_remove,
 			N_("notice files missing from worktree"), 1),
+		OPT_SET_INT(0, "keep-backup", &update_backup_log,
+			N_("update index backup log if core.backupLog is set"), 1),
 		OPT_BIT(0, "unmerged", &refresh_args.flags,
 			N_("refresh even if index contains unmerged entries"),
 			REFRESH_UNMERGED),
@@ -1060,6 +1066,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
 		usage_with_options(update_index_usage, options);
 
 	git_config(git_default_config, NULL);
+	repo_config_get_bool(the_repository, "core.backupLog", &core_backup_log);
 
 	/* we will diagnose later if it turns out that we need to update it */
 	newfd = hold_locked_index(&lock_file, 0);
diff --git a/t/t2080-backup-log.sh b/t/t2080-backup-log.sh
index f7bdaaa3f6..6b3814c172 100755
--- a/t/t2080-backup-log.sh
+++ b/t/t2080-backup-log.sh
@@ -28,4 +28,15 @@ test_expect_success 'add writes backup log' '
 	test_cmp expected actual
 '
 
+test_expect_success 'update-index --keep-backup writes backup log' '
+	test_tick &&
+	echo update-index >>initial.t &&
+	OLD=$(git rev-parse :./initial.t) &&
+	git -c core.backupLog=true update-index --keep-backup initial.t &&
+	NEW=$(git hash-object initial.t) &&
+	echo "$OLD $NEW $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $test_tick -0700	initial.t" >expected &&
+	tail -n1 .git/index.bkl >actual &&
+	test_cmp expected actual
+'
+
 test_done
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH 08/24] add--interactive: support backup log
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:44 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 git-add--interactive.perl | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 20eb81cc92..730133f57e 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -102,28 +102,28 @@ sub colored {
 my %patch_modes = (
 	'stage' => {
 		DIFF => 'diff-files -p',
-		APPLY => sub { apply_patch 'apply --cached', @_; },
+		APPLY => sub { apply_patch 'apply --cached --keep-backup', @_; },
 		APPLY_CHECK => 'apply --cached',
 		FILTER => 'file-only',
 		IS_REVERSE => 0,
 	},
 	'stash' => {
 		DIFF => 'diff-index -p HEAD',
-		APPLY => sub { apply_patch 'apply --cached', @_; },
+		APPLY => sub { apply_patch 'apply --cached --keep-backup', @_; },
 		APPLY_CHECK => 'apply --cached',
 		FILTER => undef,
 		IS_REVERSE => 0,
 	},
 	'reset_head' => {
 		DIFF => 'diff-index -p --cached',
-		APPLY => sub { apply_patch 'apply -R --cached', @_; },
+		APPLY => sub { apply_patch 'apply -R --cached --keep-backup', @_; },
 		APPLY_CHECK => 'apply -R --cached',
 		FILTER => 'index-only',
 		IS_REVERSE => 1,
 	},
 	'reset_nothead' => {
 		DIFF => 'diff-index -R -p --cached',
-		APPLY => sub { apply_patch 'apply --cached', @_; },
+		APPLY => sub { apply_patch 'apply --cached --keep-backup', @_; },
 		APPLY_CHECK => 'apply --cached',
 		FILTER => 'index-only',
 		IS_REVERSE => 0,
@@ -628,7 +628,7 @@ sub update_cmd {
 				       HEADER => $status_head, },
 				     @mods);
 	if (@update) {
-		system(qw(git update-index --add --remove --),
+		system(qw(git update-index --add --remove --keep-backup --),
 		       map { $_->{VALUE} } @update);
 		say_n_paths('updated', @update);
 	}
@@ -648,7 +648,7 @@ sub revert_cmd {
 			my @lines = run_cmd_pipe(qw(git ls-tree HEAD --),
 						 map { $_->{VALUE} } @update);
 			my $fh;
-			open $fh, '| git update-index --index-info'
+			open $fh, '| git update-index --keep-backup --index-info'
 			    or die;
 			for (@lines) {
 				print $fh $_;
@@ -673,7 +673,7 @@ sub add_untracked_cmd {
 	my @add = list_and_choose({ PROMPT => __('Add untracked') },
 				  list_untracked());
 	if (@add) {
-		system(qw(git update-index --add --), @add);
+		system(qw(git update-index --keep-backup --add --), @add);
 		say_n_paths('added', @add);
 	} else {
 		print __("No untracked files.\n");
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH 06/24] commit: support backup log
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:44 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/commit.c      | 16 +++++++++++-----
 t/t2080-backup-log.sh | 24 ++++++++++++++++++++++++
 2 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index c021b119bb..2bdbeff4a2 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -268,7 +268,7 @@ static int list_paths(struct string_list *list, const char *with_tree,
 	return ret;
 }
 
-static void add_remove_files(struct string_list *list)
+static void add_remove_files(struct string_list *list, int flags)
 {
 	int i;
 	for (i = 0; i < list->nr; i++) {
@@ -280,7 +280,7 @@ static void add_remove_files(struct string_list *list)
 			continue;
 
 		if (!lstat(p->string, &st)) {
-			if (add_to_cache(p->string, &st, 0))
+			if (add_to_cache(p->string, &st, flags))
 				die(_("updating files failed"));
 		} else
 			remove_file_from_cache(p->string);
@@ -331,8 +331,14 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
 	struct string_list partial = STRING_LIST_INIT_DUP;
 	struct pathspec pathspec;
 	int refresh_flags = REFRESH_QUIET;
+	int add_flags = 0;
+	int core_backup_log = 0;
 	const char *ret;
 
+	repo_config_get_bool(the_repository, "core.backuplog", &core_backup_log);
+	if (core_backup_log)
+		add_flags = ADD_CACHE_LOG_UPDATES;
+
 	if (is_status)
 		refresh_flags |= REFRESH_UNMERGED;
 	parse_pathspec(&pathspec, 0,
@@ -391,7 +397,7 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
 	 */
 	if (all || (also && pathspec.nr)) {
 		hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
-		add_files_to_cache(also ? prefix : NULL, &pathspec, 0);
+		add_files_to_cache(also ? prefix : NULL, &pathspec, add_flags);
 		refresh_cache_or_die(refresh_flags);
 		update_main_cache_tree(WRITE_TREE_SILENT);
 		if (write_locked_index(&the_index, &index_lock, 0))
@@ -460,7 +466,7 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
 		die(_("cannot read the index"));
 
 	hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR);
-	add_remove_files(&partial);
+	add_remove_files(&partial, add_flags);
 	refresh_cache(REFRESH_QUIET);
 	update_main_cache_tree(WRITE_TREE_SILENT);
 	if (write_locked_index(&the_index, &index_lock, 0))
@@ -472,7 +478,7 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
 				  LOCK_DIE_ON_ERROR);
 
 	create_base_index(current_head);
-	add_remove_files(&partial);
+	add_remove_files(&partial, 0);
 	refresh_cache(REFRESH_QUIET);
 
 	if (write_locked_index(&the_index, &false_lock, 0))
diff --git a/t/t2080-backup-log.sh b/t/t2080-backup-log.sh
index 6b3814c172..b19e26a807 100755
--- a/t/t2080-backup-log.sh
+++ b/t/t2080-backup-log.sh
@@ -39,4 +39,28 @@ test_expect_success 'update-index --keep-backup writes backup log' '
 	test_cmp expected actual
 '
 
+test_expect_success 'commit -a writes backup log' '
+	test_tick &&
+	echo update-again >>initial.t &&
+	OLD=$(git rev-parse :./initial.t) &&
+	NEW=$(git hash-object initial.t) &&
+	git -c core.backupLog=true commit -am update-again &&
+	echo "$OLD $NEW $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $test_tick -0700	initial.t" >expected &&
+	tail -n1 .git/index.bkl >actual &&
+	test_cmp expected actual
+'
+
+test_expect_success 'partial commit writes backup log' '
+	rm -f .git/index.bkl &&
+	test_tick &&
+	echo rising >>new-file &&
+	git add -N new-file &&
+	OLD=$EMPTY_BLOB &&
+	NEW=$(git hash-object new-file) &&
+	git -c core.backupLog=true commit -m update-once-more -- new-file initial.t &&
+	echo "$OLD $NEW $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $test_tick -0700	new-file" >expected &&
+	# expect file deletion to not log anything &&
+	test_cmp expected .git/index.bkl
+'
+
 test_done
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH 07/24] apply: support backup log with --keep-backup
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:44 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

Normally changes from git-apply are not worth logging because they
come from a file and can be recovered from there. This option will
mostly be used by add--interactive.pl where patches are generated
during an interactive add session and are very much worth logging.

The logging is a bit more complicated because an update is done in two
phases. The old version of all patches is removed first then the new
one added. We need to keep track of the old version in order to make a
backup.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/git-apply.txt |  3 +++
 apply.c                     | 38 +++++++++++++++++++++++++++++++++++--
 apply.h                     |  1 +
 t/t2080-backup-log.sh       | 25 ++++++++++++++++++++++++
 4 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index b9aa39000f..7b0ae790db 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -250,6 +250,9 @@ When `git apply` is used as a "better GNU patch", the user can pass
 the `--unsafe-paths` option to override this safety check.  This option
 has no effect when `--index` or `--cached` is in use.
 
+--keep-backup::
+	Enable index backup log when `--cached` or `--index` is used.
+
 CONFIGURATION
 -------------
 
diff --git a/apply.c b/apply.c
index 01793d6126..716c9a658f 100644
--- a/apply.c
+++ b/apply.c
@@ -21,6 +21,7 @@
 #include "quote.h"
 #include "rerere.h"
 #include "apply.h"
+#include "backup-log.h"
 
 static void git_apply_config(void)
 {
@@ -226,6 +227,7 @@ struct patch {
 	char old_oid_prefix[GIT_MAX_HEXSZ + 1];
 	char new_oid_prefix[GIT_MAX_HEXSZ + 1];
 	struct patch *next;
+	struct object_id old_oid;
 
 	/* three-way fallback result */
 	struct object_id threeway_stage[3];
@@ -4261,6 +4263,16 @@ static void patch_stats(struct apply_state *state, struct patch *patch)
 static int remove_file(struct apply_state *state, struct patch *patch, int rmdir_empty)
 {
 	if (state->update_index && !state->ita_only) {
+		if (state->backup_log) {
+			int pos = index_name_pos(state->repo->index,
+						 patch->old_name,
+						 strlen(patch->old_name));
+			if (pos >= 0)
+				oidcpy(&patch->old_oid,
+				       &state->repo->index->cache[pos]->oid);
+			else
+				oidclr(&patch->old_oid);
+		}
 		if (remove_file_from_index(state->repo->index, patch->old_name) < 0)
 			return error(_("unable to remove %s from index"), patch->old_name);
 	}
@@ -4276,7 +4288,8 @@ static int add_index_file(struct apply_state *state,
 			  const char *path,
 			  unsigned mode,
 			  void *buf,
-			  unsigned long size)
+			  unsigned long size,
+			  const struct object_id *old_oid)
 {
 	struct stat st;
 	struct cache_entry *ce;
@@ -4314,6 +4327,16 @@ static int add_index_file(struct apply_state *state,
 				       "for newly created file %s"), path);
 		}
 	}
+	if (state->backup_log) {
+		struct strbuf *sb = state->repo->index->backup_log;
+
+		if (!sb) {
+			sb = xmalloc(sizeof(*sb));
+			strbuf_init(sb, 0);
+			state->repo->index->backup_log = sb;
+		}
+		bkl_append(sb, ce->name, old_oid, &ce->oid);
+	}
 	if (add_index_entry(state->repo->index, ce, ADD_CACHE_OK_TO_ADD) < 0) {
 		discard_cache_entry(ce);
 		return error(_("unable to add cache entry for %s"), path);
@@ -4484,7 +4507,8 @@ static int create_file(struct apply_state *state, struct patch *patch)
 	if (patch->conflicted_threeway)
 		return add_conflicted_stages_file(state, patch);
 	else if (state->update_index)
-		return add_index_file(state, path, mode, buf, size);
+		return add_index_file(state, path, mode, buf, size,
+				      &patch->old_oid);
 	return 0;
 }
 
@@ -4659,6 +4683,7 @@ static int apply_patch(struct apply_state *state,
 	struct patch *list = NULL, **listp = &list;
 	int skipped_patch = 0;
 	int res = 0;
+	int core_backup_log = 0;
 
 	state->patch_input_file = filename;
 	if (read_patch_file(&buf, fd) < 0)
@@ -4721,6 +4746,13 @@ static int apply_patch(struct apply_state *state,
 		goto end;
 	}
 
+	if (state->backup_log &&
+	    (!state->update_index ||
+	     repo_config_get_bool(state->repo, "core.backupLog",
+				  &core_backup_log) ||
+	     !core_backup_log))
+		state->backup_log = 0;
+
 	if (state->check || state->apply) {
 		int r = check_patch_list(state, list);
 		if (r == -128) {
@@ -4982,6 +5014,8 @@ int apply_parse_options(int argc, const char **argv,
 			N_("mark new files with `git add --intent-to-add`")),
 		OPT_BOOL(0, "cached", &state->cached,
 			N_("apply a patch without touching the working tree")),
+		OPT_BOOL(0, "keep-backup", &state->backup_log,
+			 N_("log index changes if the feature is enabled")),
 		OPT_BOOL_F(0, "unsafe-paths", &state->unsafe_paths,
 			   N_("accept a patch that touches outside the working area"),
 			   PARSE_OPT_NOCOMPLETE),
diff --git a/apply.h b/apply.h
index 5948348133..d4de2ebcb9 100644
--- a/apply.h
+++ b/apply.h
@@ -51,6 +51,7 @@ struct apply_state {
 	int check_index; /* preimage must match the indexed version */
 	int update_index; /* check_index && apply */
 	int ita_only;	  /* add intent-to-add entries to the index */
+	int backup_log;	  /* enable backup log */
 
 	/* These control cosmetic aspect of the output */
 	int diffstat; /* just show a diffstat, and don't actually apply */
diff --git a/t/t2080-backup-log.sh b/t/t2080-backup-log.sh
index b19e26a807..8d1c8c5935 100755
--- a/t/t2080-backup-log.sh
+++ b/t/t2080-backup-log.sh
@@ -63,4 +63,29 @@ test_expect_success 'partial commit writes backup log' '
 	test_cmp expected .git/index.bkl
 '
 
+test_expect_success 'apply --cached writes backup log' '
+	rm -f .git/index.bkl &&
+	git reset --hard &&
+	test_tick &&
+	echo to-be-deleted >to-be-deleted &&
+	echo to-be-modified >to-be-modified &&
+	OLD_M=$(git hash-object to-be-modified) &&
+	git add . &&
+	git commit -m first &&
+	rm to-be-deleted &&
+	echo modified >>to-be-modified &&
+	NEW_M=$(git hash-object to-be-modified) &&
+	OLD_A=$ZERO_OID &&
+	echo to-be-added >to-be-added &&
+	NEW_A=$(git hash-object to-be-added) &&
+	git add . &&
+	git commit -m second &&
+	git diff HEAD^ HEAD >patch &&
+	git reset --hard HEAD^ &&
+	git -c core.backupLog=true apply --cached --keep-backup patch &&
+	echo "$OLD_A $NEW_A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $test_tick -0700	to-be-added" >expected &&
+	echo "$OLD_M $NEW_M $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $test_tick -0700	to-be-modified" >>expected &&
+	test_cmp expected .git/index.bkl
+'
+
 test_done
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH 09/24] backup-log.c: add API for walking backup log
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:44 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 backup-log.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++
 backup-log.h |  21 ++++++-
 2 files changed, 193 insertions(+), 1 deletion(-)

diff --git a/backup-log.c b/backup-log.c
index c1e805b09e..49f2ce68fe 100644
--- a/backup-log.c
+++ b/backup-log.c
@@ -44,3 +44,176 @@ int bkl_write(const char *path, struct strbuf *new_log)
 	rollback_lock_file(&lk);
 	return ret;
 }
+
+int bkl_parse_entry(struct strbuf *sb, struct bkl_entry *re)
+{
+	char *email_end, *message;
+	const char *p = sb->buf;
+
+	/* old SP new SP name <email> SP time TAB msg LF */
+	if (!sb->len || sb->buf[sb->len - 1] != '\n' ||
+	    parse_oid_hex(p, &re->old_oid, &p) || *p++ != ' ' ||
+	    parse_oid_hex(p, &re->new_oid, &p) || *p++ != ' ' ||
+	    !(email_end = strchr(p, '>')) ||
+	    email_end[1] != ' ')
+		return -1;	/* corrupt? */
+	re->email = p;
+	re->timestamp = parse_timestamp(email_end + 2, &message, 10);
+	if (!re->timestamp ||
+	    !message || message[0] != ' ' ||
+	    (message[1] != '+' && message[1] != '-') ||
+	    !isdigit(message[2]) || !isdigit(message[3]) ||
+	    !isdigit(message[4]) || !isdigit(message[5]))
+		return -1; /* corrupt? */
+	email_end[1] = '\0';
+	re->tz = strtol(message + 1, NULL, 10);
+	if (message[6] != '\t')
+		message += 6;
+	else
+		message += 7;
+	sb->buf[sb->len - 1] = '\0'; /* no LF */
+	re->path = message;
+	return 0;
+}
+
+static char *find_beginning_of_line(char *bob, char *scan)
+{
+	while (bob < scan && *(--scan) != '\n')
+		; /* keep scanning backwards */
+	/*
+	 * Return either beginning of the buffer, or LF at the end of
+	 * the previous line.
+	 */
+	return scan;
+}
+
+int bkl_parse_file_reverse(const char *path,
+			   int (*parse)(struct strbuf *line, void *data),
+			   void *data)
+{
+	struct strbuf sb = STRBUF_INIT;
+	FILE *logfp;
+	long pos;
+	int ret = 0, at_tail = 1;
+
+	logfp = fopen(path, "r");
+	if (!logfp) {
+		if (errno == ENOENT || errno == ENOTDIR)
+			return 0;
+		return -1;
+	}
+
+	/* Jump to the end */
+	if (fseek(logfp, 0, SEEK_END) < 0)
+		ret = error_errno(_("cannot seek back in %s"), path);
+	pos = ftell(logfp);
+	while (!ret && 0 < pos) {
+		int cnt;
+		size_t nread;
+		char buf[BUFSIZ];
+		char *endp, *scanp;
+
+		/* Fill next block from the end */
+		cnt = (sizeof(buf) < pos) ? sizeof(buf) : pos;
+		if (fseek(logfp, pos - cnt, SEEK_SET)) {
+			ret = error_errno(_("cannot seek back in %s"), path);
+			break;
+		}
+		nread = fread(buf, cnt, 1, logfp);
+		if (nread != 1) {
+			ret = error_errno(_("cannot read %d bytes from %s"),
+					  cnt, path);
+			break;
+		}
+		pos -= cnt;
+
+		scanp = endp = buf + cnt;
+		if (at_tail && scanp[-1] == '\n')
+			/* Looking at the final LF at the end of the file */
+			scanp--;
+		at_tail = 0;
+
+		while (buf < scanp) {
+			/*
+			 * terminating LF of the previous line, or the beginning
+			 * of the buffer.
+			 */
+			char *bp;
+
+			bp = find_beginning_of_line(buf, scanp);
+
+			if (*bp == '\n') {
+				/*
+				 * The newline is the end of the previous line,
+				 * so we know we have complete line starting
+				 * at (bp + 1). Prefix it onto any prior data
+				 * we collected for the line and process it.
+				 */
+				strbuf_splice(&sb, 0, 0, bp + 1, endp - (bp + 1));
+				scanp = bp;
+				endp = bp + 1;
+				ret = parse(&sb, data);
+				strbuf_reset(&sb);
+				if (ret)
+					break;
+			} else if (!pos) {
+				/*
+				 * We are at the start of the buffer, and the
+				 * start of the file; there is no previous
+				 * line, and we have everything for this one.
+				 * Process it, and we can end the loop.
+				 */
+				strbuf_splice(&sb, 0, 0, buf, endp - buf);
+				ret = parse(&sb, data);
+				strbuf_reset(&sb);
+				break;
+			}
+
+			if (bp == buf) {
+				/*
+				 * We are at the start of the buffer, and there
+				 * is more file to read backwards. Which means
+				 * we are in the middle of a line. Note that we
+				 * may get here even if *bp was a newline; that
+				 * just means we are at the exact end of the
+				 * previous line, rather than some spot in the
+				 * middle.
+				 *
+				 * Save away what we have to be combined with
+				 * the data from the next read.
+				 */
+				strbuf_splice(&sb, 0, 0, buf, endp - buf);
+				break;
+			}
+		}
+
+	}
+	if (!ret && sb.len)
+		BUG("reverse reflog parser had leftover data");
+
+	fclose(logfp);
+	strbuf_release(&sb);
+	return ret;
+}
+
+int bkl_parse_file(const char *path,
+		   int (*parse)(struct strbuf *line, void *data),
+		   void *data)
+{
+	struct strbuf sb = STRBUF_INIT;
+	FILE *logfp;
+	int ret = 0;
+
+	logfp = fopen(path, "r");
+	if (!logfp) {
+		if (errno == ENOENT || errno == ENOTDIR)
+			return 0;
+		return -1;
+	}
+
+	while (!ret && !strbuf_getwholeline(&sb, logfp, '\n'))
+		ret = parse(&sb, data);
+	fclose(logfp);
+	strbuf_release(&sb);
+	return ret;
+}
diff --git a/backup-log.h b/backup-log.h
index 5e475d6f35..c9de9c687c 100644
--- a/backup-log.h
+++ b/backup-log.h
@@ -1,13 +1,32 @@
 #ifndef __BACKUP_LOG_H__
 #define __BACKUP_LOG_H__
 
-struct object_id;
+#include "cache.h"
+
 struct strbuf;
 
+struct bkl_entry
+{
+	struct object_id old_oid;
+	struct object_id new_oid;
+	const char *email;
+	timestamp_t timestamp;
+	int tz;
+	const char *path;
+};
+
 void bkl_append(struct strbuf *output, const char *path,
 		const struct object_id *from,
 		const struct object_id *to);
 
 int bkl_write(const char *path, struct strbuf *new_log);
 
+int bkl_parse_entry(struct strbuf *sb, struct bkl_entry *re);
+int bkl_parse_file_reverse(const char *path,
+			   int (*parse)(struct strbuf *line, void *data),
+			   void *data);
+int bkl_parse_file(const char *path,
+		   int (*parse)(struct strbuf *line, void *data),
+		   void *data);
+
 #endif
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH 11/24] backup-log: add diff command
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:44 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

This gives you a patch so you can apply if you want.

FIXME pathspec support?

PS. the file list in diff queue is not sorted like a normal "git
diff". If this is a big deal, we probably can sort it later.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/backup-log.c  | 100 ++++++++++++++++++++++++++++++++++++++++++
 t/t2080-backup-log.sh |  25 +++++++++++
 2 files changed, 125 insertions(+)

diff --git a/builtin/backup-log.c b/builtin/backup-log.c
index b370ff9d27..f8029e0011 100644
--- a/builtin/backup-log.c
+++ b/builtin/backup-log.c
@@ -1,6 +1,8 @@
 #include "cache.h"
 #include "builtin.h"
 #include "backup-log.h"
+#include "diff.h"
+#include "diffcore.h"
 #include "dir.h"
 #include "object-store.h"
 #include "parse-options.h"
@@ -8,6 +10,7 @@
 static char const * const backup_log_usage[] = {
 	N_("git backup-log [--path=<path> | --id=<id>] update <path> <old-hash> <new-hash>"),
 	N_("git backup-log [--path=<path> | --id=<id>] cat [<options>] <change-id> <path>"),
+	N_("git backup-log [--path=<path> | --id=<id>] diff [<diff-options>] <change-id>"),
 	NULL
 };
 
@@ -115,6 +118,101 @@ static int cat(int argc, const char **argv,
 	return ret - 1;
 }
 
+static void queue_blk_entry_for_diff(const struct bkl_entry *e)
+{
+	unsigned mode = canon_mode(S_IFREG | 0644);
+	struct diff_filespec *one, *two;
+	const struct object_id *old, *new;
+
+	if (is_null_oid(&e->old_oid))
+		old = the_hash_algo->empty_blob;
+	else
+		old = &e->old_oid;
+
+	if (is_null_oid(&e->new_oid))
+		new = the_hash_algo->empty_blob;
+	else
+		new = &e->new_oid;
+
+	if (oideq(old, new))
+		return;
+
+	one = alloc_filespec(e->path);
+	two = alloc_filespec(e->path);
+
+	fill_filespec(one, old, 1, mode);
+	fill_filespec(two, new, 1, mode);
+	diff_queue(&diff_queued_diff, one, two);
+}
+
+static int diff_parse(struct strbuf *line, void *data)
+{
+	timestamp_t id = *(timestamp_t *)data;
+	struct bkl_entry entry;
+
+	if (bkl_parse_entry(line, &entry))
+		return -1;
+
+	if (entry.timestamp < id)
+		return 1;
+
+	if (entry.timestamp > id)
+		return 0;
+
+	queue_blk_entry_for_diff(&entry);
+	return 0;
+}
+
+static int diff(int argc, const char **argv,
+		const char *prefix, const char *log_path)
+{
+	char *end = NULL;
+	struct diff_options diffopt;
+	timestamp_t id = -1;
+	int ret, i, found_dash_dash = 0;
+
+	repo_diff_setup(the_repository, &diffopt);
+	i = 1;
+	while (i < argc) {
+		const char *arg = argv[i];
+
+		if (!found_dash_dash && *arg == '-') {
+			if (!strcmp(arg, "--")) {
+				found_dash_dash = 1;
+				i++;
+				continue;
+			}
+			ret = diff_opt_parse(&diffopt, argv + i, argc - i, prefix);
+			if (ret < 0)
+				exit(128);
+			i += ret;
+			continue;
+		}
+
+		id = strtol(arg, &end, 10);
+		if (!end || *end)
+			die(_("not a valid change id: %s"), arg);
+		i++;
+		break;
+	}
+	if (!diffopt.output_format)
+		diffopt.output_format = DIFF_FORMAT_PATCH;
+	diff_setup_done(&diffopt);
+	if (i != argc || id == -1)
+		usage_with_options(backup_log_usage, NULL);
+
+	ret = bkl_parse_file_reverse(log_path, diff_parse, &id);
+	if (ret < 0)
+		die(_("failed to parse '%s'"), log_path);
+
+	if (ret == 1) {
+		setup_pager();
+		diffcore_std(&diffopt);
+		diff_flush(&diffopt);
+	}
+	return ret - 1;
+}
+
 static char *log_id_to_path(const char *id)
 {
 	if (!strcmp(id, "index"))
@@ -156,6 +254,8 @@ int cmd_backup_log(int argc, const char **argv, const char *prefix)
 		return update(argc, argv, prefix, log_path);
 	else if (!strcmp(argv[0], "cat"))
 		return cat(argc, argv, prefix, log_path);
+	else if (!strcmp(argv[0], "diff"))
+		return diff(argc, argv, prefix, log_path);
 	else
 		die(_("unknown subcommand: %s"), argv[0]);
 
diff --git a/t/t2080-backup-log.sh b/t/t2080-backup-log.sh
index 9c004c9727..cd4288d386 100755
--- a/t/t2080-backup-log.sh
+++ b/t/t2080-backup-log.sh
@@ -105,4 +105,29 @@ test_expect_success 'backup-log cat' '
 	test_cmp expected actual
 '
 
+test_expect_success 'backup-log diff' '
+	echo first >initial.t &&
+	git add initial.t &&
+	echo second >initial.t &&
+	test_tick &&
+	git -c core.backupLog=true add initial.t &&
+	git backup-log --id=index diff $test_tick >actual &&
+	cat >expected <<-\EOF &&
+	diff --git a/initial.t b/initial.t
+	index 9c59e24..e019be0 100644
+	--- a/initial.t
+	+++ b/initial.t
+	@@ -1 +1 @@
+	-first
+	+second
+	EOF
+	test_cmp expected actual &&
+	git backup-log --id=index diff --stat $test_tick >stat.actual &&
+	cat >stat.expected <<-\EOF &&
+	 initial.t | 2 +-
+	 1 file changed, 1 insertion(+), 1 deletion(-)
+	EOF
+	test_cmp stat.expected stat.actual
+'
+
 test_done
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH 10/24] backup-log: add cat command
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:44 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

This command introduces a new concept, "change id". This is similar to
"n" in reflog sha-1 extended syntax @{n}. I'm trying to group changes of
the same second together, and this timestamp becomes "change id", so
you view roughly a snapshot of changes. Of course it's not 100%
accurate. But it works most of the time and it keeps log update low.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/backup-log.c  | 83 +++++++++++++++++++++++++++++++++++++++++++
 t/t2080-backup-log.sh | 17 +++++++++
 2 files changed, 100 insertions(+)

diff --git a/builtin/backup-log.c b/builtin/backup-log.c
index 75a02c8878..b370ff9d27 100644
--- a/builtin/backup-log.c
+++ b/builtin/backup-log.c
@@ -1,10 +1,13 @@
 #include "cache.h"
 #include "builtin.h"
 #include "backup-log.h"
+#include "dir.h"
+#include "object-store.h"
 #include "parse-options.h"
 
 static char const * const backup_log_usage[] = {
 	N_("git backup-log [--path=<path> | --id=<id>] update <path> <old-hash> <new-hash>"),
+	N_("git backup-log [--path=<path> | --id=<id>] cat [<options>] <change-id> <path>"),
 	NULL
 };
 
@@ -34,6 +37,84 @@ static int update(int argc, const char **argv,
 	return ret;
 }
 
+struct cat_options {
+	timestamp_t id;
+	char *path;
+	int before;
+	int show_hash;
+};
+
+static int cat_parse(struct strbuf *line, void *data)
+{
+	struct cat_options *opts = data;
+	struct bkl_entry entry;
+	struct object_id *oid;
+	void *buf;
+	unsigned long size;
+	enum object_type type;
+
+	if (bkl_parse_entry(line, &entry))
+		return -1;
+
+	if (entry.timestamp < opts->id)
+		return 2;
+
+	if (entry.timestamp != opts->id ||
+	    fspathcmp(entry.path, opts->path))
+		return 0;
+
+	if (opts->before)
+		oid = &entry.old_oid;
+	else
+		oid = &entry.new_oid;
+
+	if (opts->show_hash) {
+		puts(oid_to_hex(oid));
+		return 1;
+	}
+
+	if (is_null_oid(oid))
+		return 1;	/* treat null oid like empty blob */
+
+	buf = read_object_file(oid, &type, &size);
+	if (!buf)
+		die(_("object not found: %s"), oid_to_hex(oid));
+	if (type != OBJ_BLOB)
+		die(_("not a blob: %s"), oid_to_hex(oid));
+
+	write_in_full(1, buf, size);
+	free(buf);
+
+	return 1;
+}
+
+static int cat(int argc, const char **argv,
+		const char *prefix, const char *log_path)
+{
+	struct cat_options opts;
+	struct option options[] = {
+		OPT_BOOL(0, "before", &opts.before, N_("select the version before the update")),
+		OPT_BOOL(0, "hash", &opts.show_hash, N_("show the hash instead of the content")),
+		OPT_END()
+	};
+	char *end = NULL;
+	int ret;
+
+	memset(&opts, 0, sizeof(opts));
+	argc = parse_options(argc, argv, prefix, options, backup_log_usage, 0);
+	if (argc != 2)
+		usage_with_options(backup_log_usage, options);
+	opts.id = strtol(argv[0], &end, 10);
+	if (!end || *end)
+		die(_("not a valid change id: %s"), argv[0]);
+	opts.path = prefix_path(prefix, prefix ? strlen(prefix) : 0, argv[1]);
+	setup_pager();
+	ret = bkl_parse_file_reverse(log_path, cat_parse, &opts);
+	if (ret < 0)
+		die(_("failed to parse '%s'"), log_path);
+	return ret - 1;
+}
+
 static char *log_id_to_path(const char *id)
 {
 	if (!strcmp(id, "index"))
@@ -73,6 +154,8 @@ int cmd_backup_log(int argc, const char **argv, const char *prefix)
 
 	if (!strcmp(argv[0], "update"))
 		return update(argc, argv, prefix, log_path);
+	else if (!strcmp(argv[0], "cat"))
+		return cat(argc, argv, prefix, log_path);
 	else
 		die(_("unknown subcommand: %s"), argv[0]);
 
diff --git a/t/t2080-backup-log.sh b/t/t2080-backup-log.sh
index 8d1c8c5935..9c004c9727 100755
--- a/t/t2080-backup-log.sh
+++ b/t/t2080-backup-log.sh
@@ -88,4 +88,21 @@ test_expect_success 'apply --cached writes backup log' '
 	test_cmp expected .git/index.bkl
 '
 
+test_expect_success 'backup-log cat' '
+	OLD=$(git rev-parse :./initial.t) &&
+	echo update >>initial.t &&
+	test_tick &&
+	git -c core.backupLog=true add initial.t &&
+	NEW=$(git rev-parse :./initial.t) &&
+	git backup-log --id=index cat --before --hash $test_tick initial.t >actual &&
+	echo $OLD >expected &&
+	test_cmp expected actual &&
+	git backup-log --id=index cat --hash $test_tick initial.t >actual &&
+	echo $NEW >expected &&
+	test_cmp expected actual &&
+	git backup-log --id=index cat $test_tick initial.t >actual &&
+	git cat-file blob $NEW >expected &&
+	test_cmp expected actual
+'
+
 test_done
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH 12/24] backup-log: add log command
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:44 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

One note about the default relative mode. Since this is mostly used
after a panic moment "oops I did it again!". The user would most
likely look for latest changes of a certain path and relative dates
make it easier to spot if the change is within a time frame.

Default to --patch too because the output is pretty useless otherwise.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/backup-log.c  | 90 +++++++++++++++++++++++++++++++++++++++++++
 t/t2080-backup-log.sh | 34 ++++++++++++++++
 2 files changed, 124 insertions(+)

diff --git a/builtin/backup-log.c b/builtin/backup-log.c
index f8029e0011..2496d73ba5 100644
--- a/builtin/backup-log.c
+++ b/builtin/backup-log.c
@@ -6,11 +6,13 @@
 #include "dir.h"
 #include "object-store.h"
 #include "parse-options.h"
+#include "revision.h"
 
 static char const * const backup_log_usage[] = {
 	N_("git backup-log [--path=<path> | --id=<id>] update <path> <old-hash> <new-hash>"),
 	N_("git backup-log [--path=<path> | --id=<id>] cat [<options>] <change-id> <path>"),
 	N_("git backup-log [--path=<path> | --id=<id>] diff [<diff-options>] <change-id>"),
+	N_("git backup-log [--path=<path> | --id=<id>] log [<options>] [--] [<path>]"),
 	NULL
 };
 
@@ -213,6 +215,92 @@ static int diff(int argc, const char **argv,
 	return ret - 1;
 }
 
+struct log_options {
+	struct rev_info revs;
+	timestamp_t last_time;
+	int last_tz;
+};
+
+static void dump(struct bkl_entry *entry, struct log_options *opts)
+{
+	timestamp_t last_time = opts->last_time;
+	int last_tz = opts->last_tz;
+
+	if (entry) {
+		opts->last_time = entry->timestamp;
+		opts->last_tz = entry->tz;
+	}
+
+	if (last_time != -1 &&
+	    ((!entry && diff_queued_diff.nr) ||
+	     (entry && last_time != entry->timestamp))) {
+		printf("Change-Id: %"PRItime"\n", last_time);
+		printf("Date: %s\n", show_date(last_time, last_tz, &opts->revs.date_mode));
+		printf("\n--\n");
+		diffcore_std(&opts->revs.diffopt);
+		diff_flush(&opts->revs.diffopt);
+		printf("\n");
+	}
+}
+
+static int log_parse(struct strbuf *line, void *data)
+{
+	struct log_options *opts = data;
+	struct bkl_entry entry;
+
+	if (bkl_parse_entry(line, &entry))
+		return -1;
+
+	if (opts->revs.max_age != -1 && entry.timestamp < opts->revs.max_age)
+		return 1;
+
+	if (!match_pathspec(the_repository->index, &opts->revs.prune_data,
+			    entry.path, strlen(entry.path),
+			    0, NULL, 0))
+		return 0;
+
+	dump(&entry, opts);
+
+	queue_blk_entry_for_diff(&entry);
+
+	return 0;
+}
+
+static int log_(int argc, const char **argv,
+		const char *prefix, const char *log_path)
+{
+	struct log_options opts;
+	int ret;
+
+	memset(&opts, 0, sizeof(opts));
+	opts.last_time = -1;
+	opts.last_tz = -1;
+
+	repo_init_revisions(the_repository, &opts.revs, prefix);
+	opts.revs.date_mode.type = DATE_RELATIVE;
+	argc = setup_revisions(argc, argv, &opts.revs, NULL);
+	if (!opts.revs.diffopt.output_format) {
+		opts.revs.diffopt.output_format = DIFF_FORMAT_PATCH;
+		diff_setup_done(&opts.revs.diffopt);
+	}
+
+	setup_pager();
+	if (opts.revs.reverse) {
+		/*
+		 * Default order is reading file from the bottom. --reverse
+		 * makes it read from the top instead (i.e. forward)
+		 */
+		ret = bkl_parse_file(log_path, log_parse, &opts);
+	} else {
+		ret = bkl_parse_file_reverse(log_path, log_parse, &opts);
+	}
+	if (ret < 0)
+		die(_("failed to parse '%s'"), log_path);
+	dump(NULL, &opts);	/* flush */
+
+	return ret;
+}
+
 static char *log_id_to_path(const char *id)
 {
 	if (!strcmp(id, "index"))
@@ -256,6 +344,8 @@ int cmd_backup_log(int argc, const char **argv, const char *prefix)
 		return cat(argc, argv, prefix, log_path);
 	else if (!strcmp(argv[0], "diff"))
 		return diff(argc, argv, prefix, log_path);
+	else if (!strcmp(argv[0], "log"))
+		return log_(argc, argv, prefix, log_path);
 	else
 		die(_("unknown subcommand: %s"), argv[0]);
 
diff --git a/t/t2080-backup-log.sh b/t/t2080-backup-log.sh
index cd4288d386..3cdabc2ba2 100755
--- a/t/t2080-backup-log.sh
+++ b/t/t2080-backup-log.sh
@@ -130,4 +130,38 @@ test_expect_success 'backup-log diff' '
 	test_cmp stat.expected stat.actual
 '
 
+test_expect_success 'backup-log log' '
+	rm -f .git/index.bkl &&
+	echo first >initial.t &&
+	git add initial.t &&
+	echo second >initial.t &&
+	test_tick &&
+	git -c core.backupLog=true add initial.t &&
+	echo third >initial.t &&
+	# note, same tick!
+	git -c core.backupLog=true add initial.t &&
+	test_tick &&
+	echo forth >initial.t &&
+	git -c core.backupLog=true add initial.t &&
+	git backup-log --id=index log --stat --date=iso >actual &&
+	cat >expected <<-\EOF &&
+	Change-Id: 1112912593
+	Date: 2005-04-07 15:23:13 -0700
+	
+	--
+	 initial.t | 2 +-
+	 1 file changed, 1 insertion(+), 1 deletion(-)
+	
+	Change-Id: 1112912533
+	Date: 2005-04-07 15:22:13 -0700
+	
+	--
+	 initial.t | 2 +-
+	 initial.t | 2 +-
+	 2 files changed, 2 insertions(+), 2 deletions(-)
+	
+	EOF
+	test_cmp expected actual
+'
+
 test_done
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related

* [PATCH 17/24] config --edit: support backup log
From: Nguyễn Thái Ngọc Duy @ 2018-12-09 10:44 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <20181209104419.12639-1-pclouds@gmail.com>

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/config.c      | 27 ++++++++++++++++++++++++++-
 t/t2080-backup-log.sh | 14 ++++++++++++++
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/builtin/config.c b/builtin/config.c
index 84385ef165..a42044d03e 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -1,5 +1,6 @@
 #include "builtin.h"
 #include "cache.h"
+#include "backup-log.h"
 #include "config.h"
 #include "color.h"
 #include "parse-options.h"
@@ -593,6 +594,15 @@ static char *default_user_config(void)
 	return strbuf_detach(&buf, NULL);
 }
 
+static void hash_one_path(const char *path, struct object_id *oid)
+{
+	struct stat st;
+
+	if (lstat(path, &st) ||
+	    index_path(NULL, oid, path, &st, HASH_WRITE_OBJECT))
+		oidclr(oid);
+}
+
 int cmd_config(int argc, const char **argv, const char *prefix)
 {
 	int nongit = !startup_info->have_repository;
@@ -735,6 +745,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 	}
 	else if (actions == ACTION_EDIT) {
 		char *config_file;
+		int core_backup_log = 0;
+		struct object_id old, new;
 
 		check_argc(argc, 0, 0);
 		if (!given_config_source.file && nongit)
@@ -747,6 +759,9 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 		config_file = given_config_source.file ?
 				xstrdup(given_config_source.file) :
 				git_pathdup("config");
+		repo_config_get_bool(the_repository, "core.backuplog",
+				     &core_backup_log);
+		oidclr(&old);
 		if (use_global_config) {
 			int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
 			if (fd >= 0) {
@@ -757,9 +772,19 @@ int cmd_config(int argc, const char **argv, const char *prefix)
 			}
 			else if (errno != EEXIST)
 				die_errno(_("cannot create configuration file %s"), config_file);
-		}
+		} else if (!given_config_source.file && core_backup_log)
+			hash_one_path(git_path("config"), &old);
 		launch_editor(config_file, NULL, NULL);
 		free(config_file);
+		if (!is_null_oid(&old)) {
+			struct strbuf sb = STRBUF_INIT;
+
+			hash_one_path(git_path("config"), &new);
+			bkl_append(&sb, "config", &old, &new);
+			mkdir(git_path("common"), 0777);
+			bkl_write(git_path("common/gitdir.bkl"), &sb);
+			strbuf_release(&sb);
+		}
 	}
 	else if (actions == ACTION_SET) {
 		int ret;
diff --git a/t/t2080-backup-log.sh b/t/t2080-backup-log.sh
index 3cdabc2ba2..dbd19db757 100755
--- a/t/t2080-backup-log.sh
+++ b/t/t2080-backup-log.sh
@@ -164,4 +164,18 @@ test_expect_success 'backup-log log' '
 	test_cmp expected actual
 '
 
+test_expect_success 'config --edit makes a backup' '
+	cat >edit.sh <<-EOF &&
+	#!$SHELL_PATH
+	echo ";Edited" >>"\$1"
+	EOF
+	chmod +x edit.sh &&
+	OLD=$(git hash-object .git/config) &&
+	EDITOR=./edit.sh git -c core.backupLog=true config --edit &&
+	NEW=$(git hash-object .git/config) &&
+	grep config .git/common/gitdir.bkl &&
+	grep ^$OLD .git/common/gitdir.bkl &&
+	grep $NEW .git/common/gitdir.bkl
+'
+
 test_done
-- 
2.20.0.rc2.486.g9832c05c3d


^ permalink raw reply related


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