git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v9 10/17] rebase: introduce the --rebase-merges option

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Apr 25, 2018, 12:29 UTC
Message-ID
<922adf04f1cbb04e83f075cb99c6673d2fee5026.1524659287.git.johannes.schindelin@gmx.de>
In-Reply-To
<cover.1524659287.git.johannes.schindelin@gmx.de>

Once upon a time, this here developer thought: wouldn't it be nice if, say, Git for Windows' patches on top of core Git could be represented as a thicket of branches, and be rebased on top of core Git in order to maintain a cherry-pick'able set of patch series?

The original attempt to answer this was: git rebase --preserve-merges.

However, that experiment was never intended as an interactive option, and it only piggy-backed on git rebase --interactive because that command's implementation looked already very, very familiar: it was designed by the same person who designed --preserve-merges: yours truly.

Some time later, some other developer (I am looking at you, Andreas! ;-)) decided that it would be a good idea to allow --preserve-merges to be combined with --interactive (with caveats!) and the Git maintainer (well, the interim Git maintainer during Junio's absence, that is) agreed, and that is when the glamor of the --preserve-merges design started to fall apart rather quickly and unglamorously.

The reason? In --preserve-merges mode, the parents of a merge commit (or for that matter, of *any* commit) were not stated explicitly, but were *implied* by the commit name passed to the `pick` command.

This made it impossible, for example, to reorder commits. Not to mention to move commits between branches or, deity forbid, to split topic branches into two.

Alas, these shortcomings also prevented that mode (whose original purpose was to serve Git for Windows' needs, with the additional hope that it may be useful to others, too) from serving Git for Windows' needs.

Five years later, when it became really untenable to have one unwieldy, big hodge-podge patch series of partly related, partly unrelated patches in Git for Windows that was rebased onto core Git's tags from time to time (earning the undeserved wrath of the developer of the ill-fated git-remote-hg series that first obsoleted Git for Windows' competing approach, only to be abandoned without maintainer later) was really untenable, the "Git garden shears" were born [*1*/*2*]: a script, piggy-backing on top of the interactive rebase, that would first determine the branch topology of the patches to be rebased, create a pseudo todo list for further editing, transform the result into a real todo list (making heavy use of the `exec` command to "implement" the missing todo list commands) and finally recreate the patch series on top of the new base commit.

That was in 2013. And it took about three weeks to come up with the design and implement it as an out-of-tree script. Needless to say, the implementation needed quite a few years to stabilize, all the while the design itself proved itself sound.

With this patch, the goodness of the Git garden shears comes to `git rebase -i` itself. Passing the `--rebase-merges` option will generate a todo list that can be understood readily, and where it is obvious how to reorder commits. New branches can be introduced by inserting `label` commands and calling `merge <label>`. And once this mode will have become stable and universally accepted, we can deprecate the design mistake that was `--preserve-merges`.

Link *1*: https://github.com/msysgit/msysgit/blob/master/share/msysGit/shears.sh Link *2*: https://github.com/git-for-windows/build-extra/blob/master/shears.sh

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 Documentation/git-rebase.txt           |  21 ++-
 contrib/completion/git-completion.bash |   2 +-
 git-rebase--interactive.sh             |   1 +
 git-rebase.sh                          |   6 +
 t/t3430-rebase-merges.sh               | 179 +++++++++++++++++++++++++
 5 files changed, 207 insertions(+), 2 deletions(-)
 create mode 100755 t/t3430-rebase-merges.sh
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index dd852068b1d..7f1756f1eba 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -379,6 +379,24 @@ The commit list format can be changed by setting the configuration option
 rebase.instructionFormat.  A customized instruction format will automatically
 have the long commit hash prepended to the format.
 
+-r::
+--rebase-merges::
+	By default, a rebase will simply drop merge commits from the todo
+	list, and put the rebased commits into a single, linear branch.
+	With `--rebase-merges`, the rebase will instead try to preserve
+	the branching structure within the commits that are to be rebased,
+	by recreating the merge commits. Any resolved merge conflicts or
+	manual amendments in these merge commits will have to be
+	resolved/re-applied manually.
++
+This mode is similar in spirit to `--preserve-merges`, but in contrast to
+that option works well in interactive rebases: commits can be reordered,
+inserted and dropped at will.
++
+It is currently only possible to recreate the merge commits using the
+`recursive` merge strategy; Different merge strategies can be used only via
+explicit `exec git merge -s <strategy> [...]` commands.
+
 -p::
 --preserve-merges::
 	Recreate merge commits instead of flattening the history by replaying
@@ -781,7 +799,8 @@ BUGS
 The todo list presented by `--preserve-merges --interactive` does not
 represent the topology of the revision graph.  Editing commits and
 rewording their commit messages should work fine, but attempts to
-reorder commits tend to produce counterintuitive results.
+reorder commits tend to produce counterintuitive results. Use
+`--rebase-merges` in such scenarios instead.
 
 For example, an attempt to rearrange
 ------------
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 01dd9ff07a2..e6469004099 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1944,7 +1944,7 @@ _git_rebase ()
 	--*)
 		__gitcomp "
 			--onto --merge --strategy --interactive
-			--preserve-merges --stat --no-stat
+			--rebase-merges --preserve-merges --stat --no-stat
 			--committer-date-is-author-date --ignore-date
 			--ignore-whitespace --whitespace=
 			--autosquash --no-autosquash
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index acb4bfd3fc8..e29da634339 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -970,6 +970,7 @@ git_rebase__interactive () {
 	init_revisions_and_shortrevisions
 
 	git rebase--helper --make-script ${keep_empty:+--keep-empty} \
+		${rebase_merges:+--rebase-merges} \
 		$revisions ${restrict_revision+^$restrict_revision} >"$todo" ||
 	die "$(gettext "Could not generate todo list")"
 
diff --git a/git-rebase.sh b/git-rebase.sh
index ded5de085a8..a553f969d11 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -17,6 +17,7 @@ q,quiet!           be quiet. implies --no-stat
 autostash          automatically stash/stash pop before and after
 fork-point         use 'merge-base --fork-point' to refine upstream
 onto=!             rebase onto given branch instead of upstream
+r,rebase-merges!   try to rebase merges instead of skipping them
 p,preserve-merges! try to recreate merges instead of ignoring them
 s,strategy=!       use the given merge strategy
 no-ff!             cherry-pick all commits, even if unchanged
@@ -89,6 +90,7 @@ type=
 state_dir=
 # One of {'', continue, skip, abort}, as parsed from command line
 action=
+rebase_merges=
 preserve_merges=
 autosquash=
 keep_empty=
@@ -280,6 +282,10 @@ do
 	--no-keep-empty)
 		keep_empty=
 		;;
+	--rebase-merges)
+		rebase_merges=t
+		test -z "$interactive_rebase" && interactive_rebase=implied
+		;;
 	--preserve-merges)
 		preserve_merges=t
 		test -z "$interactive_rebase" && interactive_rebase=implied
diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh
new file mode 100755
index 00000000000..5f0febb9970
--- /dev/null
+++ b/t/t3430-rebase-merges.sh
@@ -0,0 +1,179 @@
+#!/bin/sh
+#
+# Copyright (c) 2018 Johannes E. Schindelin
+#
+
+test_description='git rebase -i --rebase-merges
+
+This test runs git rebase "interactively", retaining the branch structure by
+recreating merge commits.
+
+Initial setup:
+
+    -- B --                   (first)
+   /       \
+ A - C - D - E - H            (master)
+       \       /
+         F - G                (second)
+'
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+test_cmp_graph () {
+	cat >expect &&
+	git log --graph --boundary --format=%s "$@" >output &&
+	sed "s/ *$//" <output >output.trimmed &&
+	test_cmp expect output.trimmed
+}
+
+test_expect_success 'setup' '
+	write_script replace-editor.sh <<-\EOF &&
+	mv "$1" "$(git rev-parse --git-path ORIGINAL-TODO)"
+	cp script-from-scratch "$1"
+	EOF
+
+	test_commit A &&
+	git checkout -b first &&
+	test_commit B &&
+	git checkout master &&
+	test_commit C &&
+	test_commit D &&
+	git merge --no-commit B &&
+	test_tick &&
+	git commit -m E &&
+	git tag -m E E &&
+	git checkout -b second C &&
+	test_commit F &&
+	test_commit G &&
+	git checkout master &&
+	git merge --no-commit G &&
+	test_tick &&
+	git commit -m H &&
+	git tag -m H H
+'
+
+test_expect_success 'create completely different structure' '
+	cat >script-from-scratch <<-\EOF &&
+	label onto
+
+	# onebranch
+	pick G
+	pick D
+	label onebranch
+
+	# second
+	reset onto
+	pick B
+	label second
+
+	reset onto
+	merge -C H second
+	merge onebranch # Merge the topic branch '\''onebranch'\''
+	EOF
+	test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
+	test_tick &&
+	git rebase -i -r A &&
+	test_cmp_graph <<-\EOF
+	*   Merge the topic branch '\''onebranch'\''
+	|\
+	| * D
+	| * G
+	* |   H
+	|\ \
+	| |/
+	|/|
+	| * B
+	|/
+	* A
+	EOF
+'
+
+test_expect_success 'generate correct todo list' '
+	cat >expect <<-\EOF &&
+	label onto
+
+	reset onto
+	pick d9df450 B
+	label E
+
+	reset onto
+	pick 5dee784 C
+	label branch-point
+	pick ca2c861 F
+	pick 088b00a G
+	label H
+
+	reset branch-point # C
+	pick 12bd07b D
+	merge -C 2051b56 E # E
+	merge -C 233d48a H # H
+
+	EOF
+
+	grep -v "^#" <.git/ORIGINAL-TODO >output &&
+	test_cmp expect output
+'
+
+test_expect_success '`reset` refuses to overwrite untracked files' '
+	git checkout -b refuse-to-reset &&
+	test_commit dont-overwrite-untracked &&
+	git checkout @{-1} &&
+	: >dont-overwrite-untracked.t &&
+	echo "reset refs/tags/dont-overwrite-untracked" >script-from-scratch &&
+	test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
+	test_must_fail git rebase -r HEAD &&
+	git rebase --abort
+'
+
+test_expect_success 'failed `merge` writes patch (may be rescheduled, too)' '
+	test_when_finished "test_might_fail git rebase --abort" &&
+	git checkout -b conflicting-merge A &&
+
+	: fail because of conflicting untracked file &&
+	>G.t &&
+	echo "merge -C H G" >script-from-scratch &&
+	test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
+	test_tick &&
+	test_must_fail git rebase -ir HEAD &&
+	grep "^merge -C .* G$" .git/rebase-merge/done &&
+	grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo &&
+	test_path_is_file .git/rebase-merge/patch &&
+
+	: fail because of merge conflict &&
+	rm G.t .git/rebase-merge/patch &&
+	git reset --hard &&
+	test_commit conflicting-G G.t not-G conflicting-G &&
+	test_must_fail git rebase --continue &&
+	! grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo &&
+	test_path_is_file .git/rebase-merge/patch
+'
+
+test_expect_success 'with a branch tip that was cherry-picked already' '
+	git checkout -b already-upstream master &&
+	base="$(git rev-parse --verify HEAD)" &&
+
+	test_commit A1 &&
+	test_commit A2 &&
+	git reset --hard $base &&
+	test_commit B1 &&
+	test_tick &&
+	git merge -m "Merge branch A" A2 &&
+
+	git checkout -b upstream-with-a2 $base &&
+	test_tick &&
+	git cherry-pick A2 &&
+
+	git checkout already-upstream &&
+	test_tick &&
+	git rebase -i -r upstream-with-a2 &&
+	test_cmp_graph upstream-with-a2.. <<-\EOF
+	*   Merge branch A
+	|\
+	| * A1
+	* | B1
+	|/
+	o A2
+	EOF
+'
+
+test_done
-- 
2.17.0.windows.1.33.gfcbb1fa0445
Previous: Johannes SchindelinNext: Johannes Schindelin
Message 401 of 412 in “rebase -i: offer to recreate merge commits”
  1. 0/8 rebase -i: offer to recreate merge commitsJohannes Schindelin, Jan 18, 2018
  2. 1/8 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Jan 18, 2018
  3. Jacob KellerJan 18, 2018
  4. Johannes SchindelinJan 18, 2018
  5. Jacob KellerJan 18, 2018
  6. Philip OakleyJan 18, 2018
  7. Jacob KellerJan 18, 2018
  8. Johannes SchindelinJan 29, 2018
  9. Junio C HamanoJan 22, 2018
  10. Johannes SchindelinJan 29, 2018
  11. Eric SunshineJan 19, 2018
  12. Junio C HamanoJan 24, 2018
  13. Johannes SchindelinJan 29, 2018
  14. Johannes SchindelinJan 29, 2018
  15. Eric SunshineJan 30, 2018
  16. Phillip WoodJan 19, 2018
  17. Phillip WoodJan 19, 2018
  18. Jacob KellerJan 19, 2018
  19. Johannes SchindelinJan 29, 2018
  20. Johannes SchindelinJan 29, 2018
  21. Johannes SchindelinJan 29, 2018
  22. 2/8 sequencer: introduce the `merge` commandJohannes Schindelin, Jan 18, 2018
  23. Jacob KellerJan 18, 2018
  24. Johannes SchindelinJan 18, 2018
  25. Jacob KellerJan 18, 2018
  26. Eric SunshineJan 19, 2018
  27. Phillip WoodJan 19, 2018
  28. Jacob KellerJan 20, 2018
  29. Johannes SchindelinJan 29, 2018
  30. Johannes SchindelinJan 31, 2018
  31. Phillip WoodJan 31, 2018
  32. Jacob KellerFeb 1, 2018
  33. Junio C HamanoJan 22, 2018
  34. Johannes SchindelinJan 29, 2018
  35. 3/8 sequencer: fast-forward merge commits, if possibleJohannes Schindelin, Jan 18, 2018
  36. Phillip WoodJan 19, 2018
  37. Junio C HamanoJan 23, 2018
  38. Phillip WoodJan 24, 2018
  39. Junio C HamanoJan 24, 2018
  40. Johannes SchindelinJan 29, 2018
  41. Junio C HamanoJan 23, 2018
  42. Johannes SchindelinJan 29, 2018
  43. 4/8 rebase-helper --make-script: introduce a flag to recreate mergesJohannes Schindelin, Jan 18, 2018
  44. Philip OakleyJan 18, 2018
  45. Eric SunshineJan 19, 2018
  46. Junio C HamanoJan 23, 2018
  47. Johannes SchindelinJan 29, 2018
  48. Johannes SchindelinJan 29, 2018
  49. Junio C HamanoJan 23, 2018
  50. Johannes SchindelinJan 29, 2018
  51. 5/8 rebase: introduce the --recreate-merges optionJohannes Schindelin, Jan 18, 2018
  52. Eric SunshineJan 19, 2018
  53. Johannes SchindelinJan 29, 2018
  54. Junio C HamanoJan 23, 2018
  55. Johannes SchindelinFeb 10, 2018
  56. Sergey OrganovFeb 7, 2018
  57. Jacob KellerFeb 7, 2018
  58. Sergey OrganovFeb 7, 2018
  59. Johannes SixtFeb 7, 2018
  60. Johannes SchindelinFeb 7, 2018
  61. Øyvind RønningstadFeb 7, 2018
  62. Junio C HamanoFeb 7, 2018
  63. Johannes SchindelinFeb 8, 2018
  64. Sergey OrganovFeb 14, 2018
  65. Sergey OrganovFeb 9, 2018
  66. Johannes SixtFeb 9, 2018
  67. Jacob KellerFeb 11, 2018
  68. Sergey OrganovFeb 12, 2018
  69. Sergey OrganovFeb 9, 2018
  70. Johannes SchindelinFeb 10, 2018
  71. Sergey OrganovFeb 12, 2018
  72. Johannes SchindelinFeb 12, 2018
  73. Sergey OrganovFeb 13, 2018
  74. Johannes SchindelinFeb 15, 2018
  75. Sergey OrganovFeb 15, 2018
  76. Johannes SchindelinFeb 15, 2018
  77. Sergey OrganovFeb 12, 2018
  78. Johannes SchindelinFeb 12, 2018
  79. Jacob KellerFeb 13, 2018
  80. Sergey OrganovFeb 13, 2018
  81. Jacob KellerFeb 14, 2018
  82. Johannes SchindelinFeb 15, 2018
  83. Sergey OrganovFeb 15, 2018
  84. Johannes SchindelinFeb 15, 2018
  85. Sergey OrganovFeb 13, 2018
  86. Johannes SchindelinFeb 15, 2018
  87. 6/8 sequencer: handle autosquash and post-rewrite for merge commandsJohannes Schindelin, Jan 18, 2018
  88. Jacob KellerJan 18, 2018
  89. Johannes SchindelinJan 18, 2018
  90. Jacob KellerJan 18, 2018
  91. Junio C HamanoJan 23, 2018
  92. 7/8 pull: accept --rebase=recreate to recreate the branch topologyJohannes Schindelin, Jan 18, 2018
  93. 8/8 rebase -i: introduce --recreate-merges=no-rebase-cousinsJohannes Schindelin, Jan 18, 2018
  94. Philip OakleyJan 18, 2018
  95. Johannes SchindelinJan 29, 2018
  96. Eric SunshineJan 20, 2018
  97. Jacob KellerJan 18, 2018
  98. 10/8 interactive rebase feedbackStefan Beller, Jan 18, 2018
  99. 9/8 [DO NOT APPLY, but squash?] git-rebase--interactive: clarify argumentsStefan Beller, Jan 18, 2018
  100. Jacob KellerJan 18, 2018
  101. Johannes SchindelinJan 18, 2018
  102. Stefan BellerJan 18, 2018
  103. Junio C HamanoJan 19, 2018
  104. Jacob KellerJan 20, 2018
  105. Johannes SchindelinJan 29, 2018
  106. 10/8 [DO NOT APPLY, but improve?] rebase--interactive: introduce "stop" commandStefan Beller, Jan 18, 2018
  107. Jacob KellerJan 18, 2018
  108. Philip OakleyJan 18, 2018
  109. Jacob KellerJan 18, 2018
  110. Johannes SchindelinJan 18, 2018
  111. Stefan BellerJan 18, 2018
  112. Junio C HamanoJan 19, 2018
  113. Johannes SchindelinJan 29, 2018
  114. Junio C HamanoJan 23, 2018
  115. Johannes SchindelinJan 29, 2018
  116. 00/10 rebase -i: offer to recreate merge commitsJohannes Schindelin, Jan 29, 2018
  117. 01/10 git-rebase--interactive: clarify argumentsJohannes Schindelin, Jan 29, 2018
  118. 03/10 sequencer: introduce the `merge` commandJohannes Schindelin, Jan 29, 2018
  119. 02/10 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Jan 29, 2018
  120. Eric SunshineJan 30, 2018
  121. Johannes SchindelinFeb 10, 2018
  122. Stefan BellerJan 30, 2018
  123. Johannes SchindelinJan 31, 2018
  124. Phillip WoodJan 31, 2018
  125. Johannes SchindelinFeb 10, 2018
  126. 04/10 sequencer: fast-forward merge commits, if possibleJohannes Schindelin, Jan 29, 2018
  127. 05/10 rebase-helper --make-script: introduce a flag to recreate mergesJohannes Schindelin, Jan 29, 2018
  128. 07/10 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Jan 29, 2018
  129. 06/10 rebase: introduce the --recreate-merges optionJohannes Schindelin, Jan 29, 2018
  130. 08/10 sequencer: handle autosquash and post-rewrite for merge commandsJohannes Schindelin, Jan 29, 2018
  131. 09/10 pull: accept --rebase=recreate to recreate the branch topologyJohannes Schindelin, Jan 29, 2018
  132. 10/10 rebase -i: introduce --recreate-merges=[no-]rebase-cousinsJohannes Schindelin, Jan 29, 2018
  133. Stefan BellerJan 30, 2018
  134. Johannes SchindelinJan 31, 2018
  135. Junio C HamanoJan 30, 2018
  136. Johannes SchindelinJan 31, 2018
  137. Jacob KellerFeb 1, 2018
  138. 00/12 rebase -i: offer to recreate merge commitsJohannes Schindelin, Feb 11, 2018
  139. 01/12 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Feb 11, 2018
  140. 02/12 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Feb 11, 2018
  141. 03/12 git-rebase--interactive: clarify argumentsJohannes Schindelin, Feb 11, 2018
  142. 04/12 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Feb 11, 2018
  143. Eric SunshineFeb 12, 2018
  144. Johannes SchindelinFeb 12, 2018
  145. 05/12 sequencer: introduce the `merge` commandJohannes Schindelin, Feb 11, 2018
  146. Eric SunshineFeb 12, 2018
  147. Johannes SchindelinFeb 12, 2018
  148. 06/12 sequencer: fast-forward merge commits, if possibleJohannes Schindelin, Feb 11, 2018
  149. 07/12 rebase-helper --make-script: introduce a flag to recreate mergesJohannes Schindelin, Feb 11, 2018
  150. 08/12 rebase: introduce the --recreate-merges optionJohannes Schindelin, Feb 11, 2018
  151. 09/12 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Feb 11, 2018
  152. 10/12 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Feb 11, 2018
  153. 11/12 pull: accept --rebase=recreate to recreate the branch topologyJohannes Schindelin, Feb 11, 2018
  154. 12/12 rebase -i: introduce --recreate-merges=[no-]rebase-cousinsJohannes Schindelin, Feb 11, 2018
  155. 00/12 rebase -i: offer to recreate merge commitsJohannes Schindelin, Feb 23, 2018
  156. 01/12 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Feb 23, 2018
  157. 02/12 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Feb 23, 2018
  158. 04/12 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Feb 23, 2018
  159. 03/12 git-rebase--interactive: clarify argumentsJohannes Schindelin, Feb 23, 2018
  160. 05/12 sequencer: introduce the `merge` commandJohannes Schindelin, Feb 23, 2018
  161. 06/12 sequencer: fast-forward merge commits, if possibleJohannes Schindelin, Feb 23, 2018
  162. 07/12 rebase-helper --make-script: introduce a flag to recreate mergesJohannes Schindelin, Feb 23, 2018
  163. 08/12 rebase: introduce the --recreate-merges optionJohannes Schindelin, Feb 23, 2018
  164. 09/12 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Feb 23, 2018
  165. 10/12 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Feb 23, 2018
  166. 11/12 pull: accept --rebase=recreate to recreate the branch topologyJohannes Schindelin, Feb 23, 2018
  167. 12/12 rebase -i: introduce --recreate-merges=[no-]rebase-cousinsJohannes Schindelin, Feb 23, 2018
  168. Jacob KellerFeb 25, 2018
  169. Johannes SchindelinFeb 26, 2018
  170. 00/12 rebase -i: offer to recreate merge commitsJohannes Schindelin, Feb 26, 2018
  171. 01/12 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Feb 26, 2018
  172. Martin ÅgrenFeb 27, 2018
  173. Johannes SchindelinMar 2, 2018
  174. 03/12 git-rebase--interactive: clarify argumentsJohannes Schindelin, Feb 26, 2018
  175. 04/12 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Feb 26, 2018
  176. 05/12 sequencer: introduce the `merge` commandJohannes Schindelin, Feb 26, 2018
  177. 07/12 rebase-helper --make-script: introduce a flag to recreate mergesJohannes Schindelin, Feb 26, 2018
  178. 06/12 sequencer: fast-forward merge commits, if possibleJohannes Schindelin, Feb 26, 2018
  179. 08/12 rebase: introduce the --recreate-merges optionJohannes Schindelin, Feb 26, 2018
  180. 09/12 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Feb 26, 2018
  181. 10/12 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Feb 26, 2018
  182. 11/12 pull: accept --rebase=recreate to recreate the branch topologyJohannes Schindelin, Feb 26, 2018
  183. 12/12 rebase -i: introduce --recreate-merges=[no-]rebase-cousinsJohannes Schindelin, Feb 26, 2018
  184. 02/12 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Feb 26, 2018
  185. Igor DjordjevicMar 6, 2018
  186. Johannes SchindelinMar 7, 2018
  187. 00/15 rebase -i: offer to recreate commit topologyJohannes Schindelin, Apr 10, 2018
  188. 02/15 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Apr 10, 2018
  189. 01/15 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Apr 10, 2018
  190. 03/15 git-rebase--interactive: clarify argumentsJohannes Schindelin, Apr 10, 2018
  191. 04/15 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Apr 10, 2018
  192. Sergey OrganovApr 11, 2018
  193. Johannes SchindelinApr 11, 2018
  194. Sergey OrganovApr 11, 2018
  195. Phillip WoodApr 13, 2018
  196. Philip OakleyApr 15, 2018
  197. Phillip WoodApr 18, 2018
  198. 05/15 sequencer: introduce the `merge` commandJohannes Schindelin, Apr 10, 2018
  199. Phillip WoodApr 13, 2018
  200. Phillip WoodApr 13, 2018
  201. Johannes SchindelinApr 14, 2018
  202. Phillip WoodApr 18, 2018
  203. Johannes SchindelinApr 19, 2018
  204. 06/15 sequencer: fast-forward `merge` commands, if possibleJohannes Schindelin, Apr 10, 2018
  205. 07/15 rebase-helper --make-script: introduce a flag to rebase mergesJohannes Schindelin, Apr 10, 2018
  206. 08/15 rebase: introduce the --rebase-merges optionJohannes Schindelin, Apr 10, 2018
  207. 09/15 rebase --rebase-merges: add test for --keep-emptyJohannes Schindelin, Apr 10, 2018
  208. 10/15 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Apr 10, 2018
  209. 12/15 rebase --rebase-merges: avoid "empty merges"Johannes Schindelin, Apr 10, 2018
  210. 13/15 pull: accept --rebase=merges to recreate the branch topologyJohannes Schindelin, Apr 10, 2018
  211. 14/15 rebase -i: introduce --rebase-merges=[no-]rebase-cousinsJohannes Schindelin, Apr 10, 2018
  212. Sergey OrganovApr 12, 2018
  213. 15/15 rebase -i --rebase-merges: add a section to the man pageJohannes Schindelin, Apr 10, 2018
  214. Martin ÅgrenApr 10, 2018
  215. Johannes SchindelinApr 10, 2018
  216. Phillip WoodApr 11, 2018
  217. Eric SunshineApr 11, 2018
  218. Johannes SchindelinApr 12, 2018
  219. Phillip WoodApr 13, 2018
  220. Johannes SchindelinApr 12, 2018
  221. Jacob KellerApr 12, 2018
  222. Phillip WoodApr 13, 2018
  223. Sergey OrganovApr 12, 2018
  224. 11/15 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Apr 10, 2018
  225. Sergey OrganovApr 10, 2018
  226. Johannes SchindelinApr 10, 2018
  227. Sergey OrganovApr 11, 2018
  228. Johannes SchindelinApr 11, 2018
  229. Sergey OrganovApr 11, 2018
  230. Johannes SchindelinApr 11, 2018
  231. Sergey OrganovApr 12, 2018
  232. Johannes SchindelinApr 12, 2018
  233. Jacob KellerApr 11, 2018
  234. Sergey OrganovApr 12, 2018
  235. Jacob KellerApr 12, 2018
  236. Johannes SchindelinApr 12, 2018
  237. Jacob KellerApr 12, 2018
  238. Johannes SchindelinApr 13, 2018
  239. Phillip WoodApr 13, 2018
  240. Johannes SchindelinApr 13, 2018
  241. Sergey OrganovApr 19, 2018
  242. Jacob KellerApr 19, 2018
  243. Sergey OrganovApr 19, 2018
  244. Johannes SchindelinApr 20, 2018
  245. Jacob KellerApr 20, 2018
  246. Sergey OrganovApr 18, 2018
  247. 00/17 rebase -i: offer to recreate commit topologyJohannes Schindelin, Apr 19, 2018
  248. 01/17 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Apr 19, 2018
  249. 02/17 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Apr 19, 2018
  250. 03/17 sequencer: refactor how original todo list lines are accessedJohannes Schindelin, Apr 19, 2018
  251. 04/17 sequencer: offer helpful advice when a command was rescheduledJohannes Schindelin, Apr 19, 2018
  252. 05/17 git-rebase--interactive: clarify argumentsJohannes Schindelin, Apr 19, 2018
  253. 06/17 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Apr 19, 2018
  254. Phillip WoodApr 20, 2018
  255. Johannes SchindelinApr 20, 2018
  256. 07/17 # This is a combination of 2 commits. # This is the 1st commit message:Johannes Schindelin, Apr 19, 2018
  257. Eric SunshineApr 20, 2018
  258. Johannes SchindelinApr 20, 2018
  259. 0/4 rebase -i: avoid stale "# This is a combination of" in commit messagesJohannes Schindelin, Apr 20, 2018
  260. 1/4 rebase -i: demonstrate bugs with fixup!/squash! commit messagesJohannes Schindelin, Apr 20, 2018
  261. 2/4 rebase -i: Handle "combination of <n> commits" with GETTEXT_POISONJohannes Schindelin, Apr 20, 2018
  262. Stefan BellerApr 20, 2018
  263. Johannes SchindelinApr 21, 2018
  264. 3/4 sequencer: leave a tell-tale when a fixup/squash failedJohannes Schindelin, Apr 20, 2018
  265. Stefan BellerApr 20, 2018
  266. Johannes SchindelinApr 21, 2018
  267. 4/4 rebase --skip: clean up commit message after a failed fixup/squashJohannes Schindelin, Apr 20, 2018
  268. 0/4 rebase -i: avoid stale "# This is a combination of" in commit messagesJohannes Schindelin, Apr 21, 2018
  269. 1/4 rebase -i: demonstrate bugs with fixup!/squash! commit messagesJohannes Schindelin, Apr 21, 2018
  270. 2/4 rebase -i: Handle "combination of <n> commits" with GETTEXT_POISONJohannes Schindelin, Apr 21, 2018
  271. 3/4 sequencer: leave a tell-tale when a fixup/squash failedJohannes Schindelin, Apr 21, 2018
  272. 4/4 rebase --skip: clean up commit message after a failed fixup/squashJohannes Schindelin, Apr 21, 2018
  273. Stefan BellerApr 23, 2018
  274. Phillip WoodApr 23, 2018
  275. Johannes SchindelinApr 25, 2018
  276. Phillip WoodApr 25, 2018
  277. Johannes SchindelinApr 26, 2018
  278. Phillip WoodApr 26, 2018
  279. Junio C HamanoApr 24, 2018
  280. 0/4 rebase -i: avoid stale "# This is a combination of" in commit messagesJohannes Schindelin, Apr 27, 2018
  281. 1/4 rebase -i: demonstrate bugs with fixup!/squash! commit messagesJohannes Schindelin, Apr 27, 2018
  282. 3/4 sequencer: always commit without editing when asked forJohannes Schindelin, Apr 27, 2018
  283. 2/4 rebase -i: Handle "combination of <n> commits" with GETTEXT_POISONJohannes Schindelin, Apr 27, 2018
  284. 4/4 rebase --skip: clean up commit message after a failed fixup/squashJohannes Schindelin, Apr 27, 2018
  285. Stefan BellerApr 27, 2018
  286. Johannes SchindelinApr 28, 2018
  287. Phillip WoodMay 6, 2018
  288. Phillip WoodMay 9, 2018
  289. Johannes SchindelinOct 2, 2018
  290. Phillip WoodOct 8, 2018
  291. 08/17 sequencer: fast-forward `merge` commands, if possibleJohannes Schindelin, Apr 19, 2018
  292. 09/17 rebase-helper --make-script: introduce a flag to rebase mergesJohannes Schindelin, Apr 19, 2018
  293. 10/17 rebase: introduce the --rebase-merges optionJohannes Schindelin, Apr 19, 2018
  294. 11/17 rebase --rebase-merges: add test for --keep-emptyJohannes Schindelin, Apr 19, 2018
  295. 12/17 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Apr 19, 2018
  296. 13/17 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Apr 19, 2018
  297. 14/17 rebase --rebase-merges: avoid "empty merges"Johannes Schindelin, Apr 19, 2018
  298. 15/17 pull: accept --rebase=merges to recreate the branch topologyJohannes Schindelin, Apr 19, 2018
  299. 16/17 rebase -i: introduce --rebase-merges=[no-]rebase-cousinsJohannes Schindelin, Apr 19, 2018
  300. 17/17 rebase -i --rebase-merges: add a section to the man pageJohannes Schindelin, Apr 19, 2018
  301. 00/16 rebase -i: offer to recreate commit topology by rebasing mergesJohannes Schindelin, Apr 21, 2018
  302. 01/16 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Apr 21, 2018
  303. 02/16 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Apr 21, 2018
  304. 03/16 sequencer: refactor how original todo list lines are accessedJohannes Schindelin, Apr 21, 2018
  305. 04/16 sequencer: offer helpful advice when a command was rescheduledJohannes Schindelin, Apr 21, 2018
  306. 05/16 git-rebase--interactive: clarify argumentsJohannes Schindelin, Apr 21, 2018
  307. 06/16 sequencer: introduce the `merge` commandJohannes Schindelin, Apr 21, 2018
  308. Phillip WoodApr 21, 2018
  309. Phillip WoodApr 22, 2018
  310. Johannes SchindelinApr 23, 2018
  311. Johannes SchindelinApr 23, 2018
  312. Phillip WoodApr 23, 2018
  313. Martin ÅgrenApr 24, 2018
  314. 1/2 merge: setup `opts` later in `checkout_fast_forward()`Martin Ågren, Apr 24, 2018
  315. Jacob KellerApr 24, 2018
  316. Martin ÅgrenApr 24, 2018
  317. Johannes SchindelinApr 24, 2018
  318. 2/2 unpack_trees_options: free messages when doneMartin Ågren, Apr 24, 2018
  319. Elijah NewrenApr 24, 2018
  320. Martin ÅgrenApr 28, 2018
  321. Johannes SchindelinApr 28, 2018
  322. Elijah NewrenApr 28, 2018
  323. Elijah NewrenMay 16, 2018
  324. 0/3 unpack_trees_options: free messages when doneMartin Ågren, May 16, 2018
  325. 1/3 merge: setup `opts` later in `checkout_fast_forward()`Martin Ågren, May 16, 2018
  326. Stefan BellerMay 16, 2018
  327. Martin ÅgrenMay 16, 2018
  328. Jacob KellerMay 16, 2018
  329. Jacob KellerMay 16, 2018
  330. Junio C HamanoMay 17, 2018
  331. Jacob KellerMay 18, 2018
  332. 2/3 merge-recursive: provide pair of `unpack_trees_{start,finish}()`Martin Ågren, May 16, 2018
  333. 3/3 unpack_trees_options: free messages when doneMartin Ågren, May 16, 2018
  334. Junio C HamanoMay 17, 2018
  335. Martin ÅgrenMay 18, 2018
  336. 0/3 unpack_trees_options: free messages when doneMartin Ågren, May 18, 2018
  337. 1/3 merge: setup `opts` later in `checkout_fast_forward()`Martin Ågren, May 18, 2018
  338. 2/3 merge-recursive: provide pair of `unpack_trees_{start,finish}()`Martin Ågren, May 18, 2018
  339. 3/3 unpack_trees_options: free messages when doneMartin Ågren, May 18, 2018
  340. Jeff KingMay 18, 2018
  341. Elijah NewrenMay 18, 2018
  342. Jeff KingMay 19, 2018
  343. Martin ÅgrenMay 19, 2018
  344. 0/4 unpack_trees_options: free messages when doneMartin Ågren, May 20, 2018
  345. 1/4 merge: setup `opts` later in `checkout_fast_forward()`Martin Ågren, May 20, 2018
  346. 2/4 merge-recursive: provide pair of `unpack_trees_{start,finish}()`Martin Ågren, May 20, 2018
  347. 3/4 string-list: provide `string_list_appendf()`Martin Ågren, May 20, 2018
  348. Jacob KellerMay 20, 2018
  349. Re*: [PATCH v4 3/4] string-list: provide `string_list_appendf()`Junio C Hamano, May 21, 2018
  350. Junio C HamanoMay 21, 2018
  351. Jeff KingMay 21, 2018
  352. 0/4 unpack_trees_options: free messages when doneMartin Ågren, May 21, 2018
  353. 1/4 merge: setup `opts` later in `checkout_fast_forward()`Martin Ågren, May 21, 2018
  354. 2/4 merge-recursive: provide pair of `unpack_trees_{start,finish}()`Martin Ågren, May 21, 2018
  355. 3/4 argv-array: return the pushed string from argv_push*()Martin Ågren, May 21, 2018
  356. 4/4 unpack_trees_options: free messages when doneMartin Ågren, May 21, 2018
  357. Jeff KingMay 21, 2018
  358. Junio C HamanoMay 22, 2018
  359. Junio C HamanoMay 22, 2018
  360. Martin ÅgrenMay 22, 2018
  361. Junio C HamanoMay 23, 2018
  362. Jeff KingMay 21, 2018
  363. 4/4 unpack_trees_options: free messages when doneMartin Ågren, May 20, 2018
  364. Elijah NewrenMay 16, 2018
  365. Ben PeartMay 17, 2018
  366. Johannes SchindelinApr 24, 2018
  367. Philip OakleyApr 22, 2018
  368. Johannes SchindelinApr 23, 2018
  369. Philip OakleyApr 23, 2018
  370. Johannes SchindelinApr 24, 2018
  371. Philip OakleyApr 24, 2018
  372. Philip OakleyApr 22, 2018
  373. 07/16 sequencer: fast-forward `merge` commands, if possibleJohannes Schindelin, Apr 21, 2018
  374. 08/16 rebase-helper --make-script: introduce a flag to rebase mergesJohannes Schindelin, Apr 21, 2018
  375. Philip OakleyApr 22, 2018
  376. Johannes SchindelinApr 24, 2018
  377. 09/16 rebase: introduce the --rebase-merges optionJohannes Schindelin, Apr 21, 2018
  378. Philip OakleyApr 22, 2018
  379. Johannes SchindelinApr 24, 2018
  380. Philip OakleyApr 22, 2018
  381. Junio C HamanoApr 24, 2018
  382. Johannes SchindelinApr 24, 2018
  383. Johannes SchindelinApr 24, 2018
  384. 10/16 rebase --rebase-merges: add test for --keep-emptyJohannes Schindelin, Apr 21, 2018
  385. 11/16 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Apr 21, 2018
  386. 12/16 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Apr 21, 2018
  387. 13/16 rebase --rebase-merges: avoid "empty merges"Johannes Schindelin, Apr 21, 2018
  388. 14/16 pull: accept --rebase=merges to recreate the branch topologyJohannes Schindelin, Apr 21, 2018
  389. 15/16 rebase -i: introduce --rebase-merges=[no-]rebase-cousinsJohannes Schindelin, Apr 21, 2018
  390. 16/16 rebase -i --rebase-merges: add a section to the man pageJohannes Schindelin, Apr 21, 2018
  391. 00/17 rebase -i: offer to recreate commit topology by rebasing mergesJohannes Schindelin, Apr 25, 2018
  392. 01/17 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Apr 25, 2018
  393. 02/17 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Apr 25, 2018
  394. 03/17 sequencer: refactor how original todo list lines are accessedJohannes Schindelin, Apr 25, 2018
  395. 04/17 sequencer: offer helpful advice when a command was rescheduledJohannes Schindelin, Apr 25, 2018
  396. 05/17 git-rebase--interactive: clarify argumentsJohannes Schindelin, Apr 25, 2018
  397. 06/17 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Apr 25, 2018
  398. 07/17 sequencer: introduce the `merge` commandJohannes Schindelin, Apr 25, 2018
  399. 08/17 sequencer: fast-forward `merge` commands, if possibleJohannes Schindelin, Apr 25, 2018
  400. 09/17 rebase-helper --make-script: introduce a flag to rebase mergesJohannes Schindelin, Apr 25, 2018
  401. 10/17 rebase: introduce the --rebase-merges optionJohannes Schindelin, Apr 25, 2018
  402. 11/17 rebase --rebase-merges: add test for --keep-emptyJohannes Schindelin, Apr 25, 2018
  403. 12/17 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Apr 25, 2018
  404. 13/17 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Apr 25, 2018
  405. 15/17 pull: accept --rebase=merges to recreate the branch topologyJohannes Schindelin, Apr 25, 2018
  406. 16/17 rebase -i: introduce --rebase-merges=[no-]rebase-cousinsJohannes Schindelin, Apr 25, 2018
  407. 14/17 rebase --rebase-merges: avoid "empty merges"Johannes Schindelin, Apr 25, 2018
  408. 17/17 rebase -i --rebase-merges: add a section to the man pageJohannes Schindelin, Apr 25, 2018
  409. Junio C HamanoApr 26, 2018
  410. Junio C HamanoApr 26, 2018
  411. Sergey OrganovMay 25, 2018
  412. Sergey OrganovMay 25, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.