summaryrefslogtreecommitdiff
path: root/t/t3430-rebase-merges.sh
AgeCommit message (Collapse)AuthorFilesLines
2020-06-09t/t3430: avoid undefined git diff behaviorLibravatar Chris Torek1-1/+1
The autosquash-and-exec test used "git diff HEAD^!" to mean "git diff HEAD^ HEAD". Use these directly instead of relying on the undefined but actual-current behavior of "HEAD^!". Signed-off-by: Chris Torek <chris.torek@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2020-02-24lib-log-graph: consolidate test_cmp_graph logicLibravatar Abhishek Kumar1-3/+2
Log graph comparision logic is duplicated many times in: - t3430-rebase-merges.sh - t4202-log.sh - t4214-log-graph-octopus.sh - t4215-log-skewed-merges.sh Consolidate the core of the comparision and sanitization logic in lib-log-graph, and use it to replace the existing tests. While at it, lose the singular/plural transition magic from the sanitize_output helper, which was necessary around 7f814632 ("Use correct grammar in diffstat summary line", 2012-02-01), that has long outlived its usefulness. Signed-off-by: Abhishek Kumar <abhishekkumar8222@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-12-05Merge branch 'dl/t5520-cleanup'Libravatar Junio C Hamano1-1/+1
Test cleanup. * dl/t5520-cleanup: t5520: replace `! git` with `test_must_fail git` t5520: remove redundant lines in test cases t5520: replace $(cat ...) comparison with test_cmp t5520: don't put git in upstream of pipe t5520: test single-line files by git with test_cmp t5520: use test_cmp_rev where possible t5520: replace test -{n,z} with test-lib functions t5520: use test_line_count where possible t5520: remove spaces after redirect operator t5520: replace test -f with test-lib functions t5520: let sed open its own input t5520: use sq for test case names t5520: improve test style t: teach test_cmp_rev to accept ! for not-equals t0000: test multiple local assignment
2019-12-05Merge branch 'dd/rebase-merge-reserves-onto-label'Libravatar Junio C Hamano1-0/+21
The logic to avoid duplicate label names generated by "git rebase --rebase-merges" forgot that the machinery itself uses "onto" as a label name, which must be avoided by auto-generated labels, which has been corrected. * dd/rebase-merge-reserves-onto-label: sequencer: handle rebase-merges for "onto" message
2019-12-05Merge branch 'js/rebase-r-safer-label'Libravatar Junio C Hamano1-0/+6
A label used in the todo list that are generated by "git rebase --rebase-merges" is used as a part of a refname; the logic to come up with the label has been tightened to avoid names that cannot be used as such. * js/rebase-r-safer-label: rebase -r: let `label` generate safer labels rebase-merges: move labels' whitespace mangling into `label_oid()`
2019-11-21t: teach test_cmp_rev to accept ! for not-equalsLibravatar Denton Liu1-1/+1
In the case where we are using test_cmp_rev() to report not-equals, we write `! test_cmp_rev`. However, since test_cmp_rev() contains r1=$(git rev-parse --verify "$1") && r2=$(git rev-parse --verify "$2") && `! test_cmp_rev` will succeed if any of the rev-parses fail. This behavior is not desired. We want the rev-parses to _always_ be successful. Rewrite test_cmp_rev() to optionally accept "!" as the first argument to do a not-equals comparison. Rewrite `! test_cmp_rev` to `test_cmp_rev !` in all tests to take advantage of this new functionality. Also, rewrite the rev-parse logic to end with a `|| return 1` instead of &&-chaining into the rev-comparison logic. This makes it obvious to future readers that we explicitly intend on returning early if either of the rev-parses fail. Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-11-20sequencer: handle rebase-merges for "onto" messageLibravatar Doan Tran Cong Danh1-0/+21
In order to work correctly, git-rebase --rebase-merges needs to make initial todo list with unique labels. Those unique labels is being handled by employing a hashmap and appending an unique number if any duplicate is found. But, we forget that beside those labels for side branches, we also have a special label `onto' for our so-called new-base. In a special case that any of those labels for side branches named `onto', git will run into trouble. Correct it. Signed-off-by: Doan Tran Cong Danh <congdanhqx@gmail.com> Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-11-18rebase -r: let `label` generate safer labelsLibravatar Matthew Rogers1-0/+6
The `label` todo command in interactive rebases creates temporary refs in the `refs/rewritten/` namespace. These refs are stored as loose refs, i.e. as files in `.git/refs/rewritten/`, therefore they have to conform with file name limitations on the current filesystem in addition to the accepted ref format. This poses a problem in particular on NTFS/FAT, where e.g. the colon, double-quote and pipe characters are disallowed as part of a file name. Let's safeguard against this by replacing not only white-space characters by dashes, but all non-alpha-numeric ones. However, we exempt non-ASCII UTF-8 characters from that, as it should be quite possible to reflect branch names such as `↯↯↯` in refs/file names. Signed-off-by: Matthew Rogers <mattr94@gmail.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-10-16graph: smooth appearance of collapsing edges on commit linesLibravatar James Coglan1-1/+1
When a graph contains edges that are in the process of collapsing to the left, but those edges cross a commit line, the effect is that the edges have a jagged appearance: * |\ | * | \ *-. \ |\ \ \ | | * | | * | | | |/ / * | | |/ / * | |/ * We already takes steps to smooth edges like this when they're expanding; when an edge appears to the right of a merge commit marker on a GRAPH_COMMIT line immediately following a GRAPH_POST_MERGE line, we render it as a `\`: * \ |\ \ | * \ | |\ \ We can make a similar improvement to collapsing edges, making them easier to follow and giving the overall graph a feeling of increased symmetry: * |\ | * | \ *-. \ |\ \ \ | | * | | * | | | |/ / * / / |/ / * / |/ * To do this, we introduce a new special case for edges on GRAPH_COMMIT lines that immediately follow a GRAPH_COLLAPSING line. By retaining a copy of the `mapping` array used to render the GRAPH_COLLAPSING line in the `old_mapping` array, we can determine that an edge is collapsing through the GRAPH_COMMIT line and should be smoothed. Signed-off-by: James Coglan <jcoglan@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-09-30Merge branch 'dl/use-sq-from-test-lib'Libravatar Junio C Hamano1-1/+0
Code cleanup. * dl/use-sq-from-test-lib: t: use common $SQ variable
2019-09-30Merge branch 'bc/hash-independent-tests-part-5'Libravatar Junio C Hamano1-8/+15
Preparation for SHA-256 upgrade continues in the test department. * bc/hash-independent-tests-part-5: t4009: make hash size independent t4002: make hash independent t4000: make hash size independent t3903: abstract away SHA-1-specific constants t3800: make hash-size independent t3600: make hash size independent t3506: make hash independent t3430: avoid hard-coded object IDs t3404: abstract away SHA-1-specific constants t3306: abstract away SHA-1-specific constants t3305: make hash size independent t3301: abstract away SHA-1-specific constants t3206: abstract away hash size constants t3201: abstract away SHA-1-specific constants
2019-09-18Merge branch 'js/rebase-r-strategy'Libravatar Junio C Hamano1-0/+21
"git rebase --rebase-merges" learned to drive different merge strategies and pass strategy specific options to them. * js/rebase-r-strategy: t3427: accelerate this test by using fast-export and fast-import rebase -r: do not (re-)generate root commits with `--root` *and* `--onto` t3418: test `rebase -r` with merge strategies t/lib-rebase: prepare for testing `git rebase --rebase-merges` rebase -r: support merge strategies other than `recursive` t3427: fix another incorrect assumption t3427: accommodate for the `rebase --merge` backend having been replaced t3427: fix erroneous assumption t3427: condense the unnecessarily repetitive test cases into three t3427: move the `filter-branch` invocation into the `setup` case t3427: simplify the `setup` test case significantly t3427: add a clarifying comment rebase: fold git-rebase--common into the -p backend sequencer: the `am` and `rebase--interactive` scripts are gone .gitignore: there is no longer a built-in `git-rebase--interactive` t3400: stop referring to the scripted rebase Drop unused git-rebase--am.sh
2019-09-06t: use common $SQ variableLibravatar Denton Liu1-1/+0
In many test scripts, there are bespoke definitions of the single quote that are some variation of this: SQ="'" Define a common $SQ variable in test-lib.sh and replace all usages of these bespoke variables with the common one. This change was done by running `git grep =\"\'\" t/` and `git grep =\\\\\'` and manually changing the resulting definitions and corresponding usages. Signed-off-by: Denton Liu <liu.denton@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-08-20t3430: avoid hard-coded object IDsLibravatar brian m. carlson1-8/+15
Compute the object IDs used in the todo list instead of hard-coding them. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-07-31rebase -r: support merge strategies other than `recursive`Libravatar Johannes Schindelin1-0/+21
We already support merge strategies in the sequencer, but only for `pick` commands. With this commit, we now also support them in `merge` commands. The approach is simple: if any merge strategy option is specified, or if any merge strategy other than `recursive` is specified, we simply spawn the `git merge` command. Otherwise, we handle the merge in-process just as before. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-07-09Merge branch 'pw/rebase-abort-clean-rewritten'Libravatar Junio C Hamano1-1/+17
"git rebase --abort" used to leave refs/rewritten/ when concluding "git rebase -r", which has been corrected. * pw/rebase-abort-clean-rewritten: rebase --abort/--quit: cleanup refs/rewritten sequencer: return errors from sequencer_remove_state() rebase: warn if state directory cannot be removed rebase: fix a memory leak
2019-05-19rebase -r: always reword merge -cLibravatar Phillip Wood1-0/+13
If a merge can be fast-forwarded then make sure that we still edit the commit message if the user specifies -c. The implementation follows the same pattern that is used for ordinary rewords that are fast-forwarded. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-05-15rebase --abort/--quit: cleanup refs/rewrittenLibravatar Phillip Wood1-1/+17
When `rebase -r` finishes it removes any refs under refs/rewritten that it has created. However if the user aborts or quits the rebase refs are not removed. This can cause problems for future rebases. For example I recently wanted to merge a updated version of a topic branch into an integration branch so ran `rebase -ir` and removed the picks and label for the topic branch from the todo list so that merge -C <old-merge> topic would pick up the new version of topic. Unfortunately refs/rewritten/topic already existed from a previous rebase that had been aborted so the rebase just used the old topic, not the new one. The logic for the non-interactive quit case is changed to ensure `buf` is always freed. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-04-02tests (rebase): spell out the `--force-rebase` optionLibravatar Johannes Schindelin1-2/+2
In quite a few test cases, we were sloppy and used the abbreviation `--force`, but we really should be precise in what we want to test. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-01-28implicit interactive rebase: don't run sequence editorLibravatar Phillip Wood1-1/+1
If GIT_SEQUENCE_EDITOR is set then rebase runs it when executing implicit interactive rebases which are supposed to appear non-interactive to the user. Fix this by setting GIT_SEQUENCE_EDITOR=: rather than GIT_EDITOR=:. A couple of tests relied on the old behavior so they are updated to work with the new regime. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-13rebase -r: do not write MERGE_HEAD unless neededLibravatar Johannes Schindelin1-1/+1
When we detect that a `merge` can be skipped because the merged commit is already an ancestor of HEAD, we do not need to commit, therefore writing the MERGE_HEAD file is useless. It is actually worse than useless: a subsequent `git commit` will pick it up and think that we want to merge that commit, still. To avoid that, move the code that writes the MERGE_HEAD file to a location where we already know that the `merge` cannot be skipped. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-11-13rebase -r: demonstrate bug with conflicting mergesLibravatar Johannes Schindelin1-0/+16
When calling `merge` on a branch that has already been merged, that `merge` is skipped quietly, but currently a MERGE_HEAD file is being left behind and will then be grabbed by the next `pick` (that did not want to create a *merge* commit). Demonstrate this. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-20Merge branch 'pw/rebase-i-merge-segv-fix'Libravatar Junio C Hamano1-7/+23
"git rebase -i", when a 'merge <branch>' insn in its todo list fails, segfaulted, which has been (minimally) corrected. * pw/rebase-i-merge-segv-fix: rebase -i: fix SIGSEGV when 'merge <branch>' fails t3430: add conflicting commit
2018-08-16rebase -i: fix SIGSEGV when 'merge <branch>' failsLibravatar Phillip Wood1-1/+14
If a merge command in the todo list specifies just a branch to merge with no -C/-c argument then item->commit is NULL. This means that if there are merge conflicts error_with_patch() is passed a NULL commit which causes a segmentation fault when make_patch() tries to look it up. This commit implements a minimal fix which fixes the crash and allows the user to successfully commit a conflict resolution with 'git rebase --continue'. It does not write .git/rebase-merge/patch, .git/rebase-merge/stopped-sha or update REBASE_HEAD. To sensibly get the hashes of the merge parents would require refactoring do_merge() to extract the code that parses the merge parents into a separate function which error_with_patch() could then use to write the parents into the stopped-sha file. To create meaningful output make_patch() and 'git rebase --show-current-patch' would also need to be modified to diff the merge parent and merge base in this case. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Acked-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-16t3430: add conflicting commitLibravatar Phillip Wood1-6/+9
Move the creation of conflicting-G from a test to the setup so that it can be used in subsequent tests without creating the kind of implicit dependencies that plague t3404. While we're at it simplify the arguments to the test_commit() call the creates the conflicting commit. Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-09rebase --exec: make it work with --rebase-mergesLibravatar Johannes Schindelin1-1/+1
The idea of `--exec` is to append an `exec` call after each `pick`. Since the introduction of fixup!/squash! commits, this idea was extended to apply to "pick, possibly followed by a fixup/squash chain", i.e. an exec would not be inserted between a `pick` and any of its corresponding `fixup` or `squash` lines. The current implementation uses a dirty trick to achieve that: it assumes that there are only pick/fixup/squash commands, and then *inserts* the `exec` lines before any `pick` but the first, and appends a final one. With the todo lists generated by `git rebase --rebase-merges`, this simple implementation shows its problems: it produces the exact wrong thing when there are `label`, `reset` and `merge` commands. Let's change the implementation to do exactly what we want: look for `pick` lines, skip any fixup/squash chains, and then insert the `exec` line. Lather, rinse, repeat. Note: we take pains to insert *before* comment lines whenever possible, as empty commits are represented by commented-out pick lines (and we want to insert a preceding pick's exec line *before* such a line, not afterward). While at it, also add `exec` lines after `merge` commands, because they are similar in spirit to `pick` commands: they add new commits. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-06t3430: demonstrate what -r, --autosquash & --exec should doLibravatar Johannes Schindelin1-0/+17
The --exec option's implementation is not really well-prepared for --rebase-merges. Demonstrate this. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-07-11rebase --rebase-merges: add support for octopus mergesLibravatar Johannes Schindelin1-0/+34
Previously, we introduced the `merge` command for use in todo lists, to allow to recreate and modify branch topology. For ease of implementation, and to make review easier, the initial implementation only supported merge commits with exactly two parents. This patch adds support for octopus merges, making use of the just-introduced `-F <file>` option for the `git merge` command: to keep things simple, we spawn a new Git command instead of trying to call a library function, also opening an easier door to enhance `rebase --rebase-merges` to optionally use a merge strategy different from `recursive` for regular merges: this feature would use the same code path as octopus merges and simply spawn a `git merge`. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-06-04Merge branch 'bc/t3430-fixup'Libravatar Junio C Hamano1-3/+2
Test fix. * bc/t3430-fixup: t3430: test clean-up
2018-06-04t3430: test clean-upLibravatar brian m. carlson1-3/+2
Remove unnecessary test_tick etc... Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-06-01Merge branch 'js/rebase-recreate-merge'Libravatar Junio C Hamano1-0/+17
Hotfixes. * js/rebase-recreate-merge: sequencer: ensure labels that are object IDs are rewritten git-rebase--interactive: fix copy-paste mistake
2018-05-30sequencer: ensure labels that are object IDs are rewrittenLibravatar brian m. carlson1-0/+17
When writing the todo script for --rebase-merges, we try to find a label for certain commits. If the label ends up being a valid object ID, such as when we merge a detached commit, we want to rewrite it so it is no longer a valid object ID. However, the code path that does this checks for its length to be equivalent to GIT_SHA1_RAWSZ, which isn't correct, since what we are reading is a hex object ID. Instead, check for the length being equivalent to that of a hex object ID. Use the_hash_algo so this code works regardless of the hash size. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-06rebase --rebase-merges: root commits can be cousins, tooLibravatar Johannes Schindelin1-0/+25
Reported by Wink Saville: when rebasing with no-rebase-cousins, we will want to refrain from rebasing all of them, even when they are root commits. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-06rebase --rebase-merges: a "merge" into a new root is a fast-forwardLibravatar Johannes Schindelin1-0/+13
When a user provides a todo list containing something like reset [new root] merge my-branch let's do the same as if pulling into an orphan branch: simply fast-forward. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-05-06sequencer: allow introducing new root commitsLibravatar Johannes Schindelin1-0/+34
In the context of the new --rebase-merges mode, which was designed specifically to allow for changing the existing branch topology liberally, a user may want to extract commits into a completely fresh branch that starts with a newly-created root commit. This is now possible by inserting the command `reset [new root]` before `pick`ing the commit that wants to become a root commit. Example: reset [new root] pick 012345 a commit that is about to become a root commit pick 234567 this commit will have the previous one as parent This does not conflict with other uses of the `reset` command because `[new root]` is not (part of) a valid ref name: both the opening bracket as well as the space are illegal in ref names. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-26rebase -i: introduce --rebase-merges=[no-]rebase-cousinsLibravatar Johannes Schindelin1-0/+18
When running `git rebase --rebase-merges` non-interactively with an ancestor of HEAD as <upstream> (or leaving the todo list unmodified), we would ideally recreate the exact same commits as before the rebase. However, if there are commits in the commit range <upstream>.. that do not have <upstream> as direct ancestor (i.e. if `git log <upstream>..` would show commits that are omitted by `git log --ancestry-path <upstream>..`), this is currently not the case: we would turn them into commits that have <upstream> as direct ancestor. Let's illustrate that with a diagram: C / \ A - B - E - F \ / D Currently, after running `git rebase -i --rebase-merges B`, the new branch structure would be (pay particular attention to the commit `D`): --- C' -- / \ A - B ------ E' - F' \ / D' This is not really preserving the branch topology from before! The reason is that the commit `D` does not have `B` as ancestor, and therefore it gets rebased onto `B`. This is unintuitive behavior. Even worse, when recreating branch structure, most use cases would appear to want cousins *not* to be rebased onto the new base commit. For example, Git for Windows (the heaviest user of the Git garden shears, which served as the blueprint for --rebase-merges) frequently merges branches from `next` early, and these branches certainly do *not* want to be rebased. In the example above, the desired outcome would look like this: --- C' -- / \ A - B ------ E' - F' \ / -- D' -- Let's introduce the term "cousins" for such commits ("D" in the example), and let's not rebase them by default. For hypothetical use cases where cousins *do* need to be rebased, `git rebase --rebase=merges=rebase-cousins` needs to be used. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-26rebase --rebase-merges: avoid "empty merges"Libravatar Johannes Schindelin1-0/+8
The `git merge` command does not allow merging commits that are already reachable from HEAD: `git merge HEAD^`, for example, will report that we are already up to date and not change a thing. In an interactive rebase, such a merge could occur previously, e.g. when competing (or slightly modified) versions of a patch series were applied upstream, and the user had to `git rebase --skip` all of the local commits, and the topic branch becomes "empty" as a consequence. Let's teach the todo command `merge` to behave the same as `git merge`. Seeing as it requires some low-level trickery to create such merges with Git's commands in the first place, we do not even have to bother to introduce an option to force `merge` to create such merge commits. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-26sequencer: handle post-rewrite for merge commandsLibravatar Johannes Schindelin1-0/+25
In the previous patches, we implemented the basic functionality of the `git rebase -i --rebase-merges` command, in particular the `merge` command to create merge commits in the sequencer. The interactive rebase is a lot more these days, though, than a simple cherry-pick in a loop. For example, it calls the post-rewrite hook (if any) after rebasing with a mapping of the old->new commits. This patch implements the post-rewrite handling for the `merge` command we just introduced. The other commands that were added recently (`label` and `reset`) do not create new commits, therefore post-rewrite hooks do not need to handle them. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-26sequencer: make refs generated by the `label` command worktree-localLibravatar Johannes Schindelin1-0/+14
This allows for rebases to be run in parallel in separate worktrees (think: interrupted in the middle of one rebase, being asked to perform a different rebase, adding a separate worktree just for that job). Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-04-26rebase: introduce the --rebase-merges optionLibravatar Johannes Schindelin1-0/+179
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>