Simplify t3404

We have test_commit for a while now.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Explain the idea of t3404.20

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
t3404: do not test implementation details

It stands to argue whether rebasing F onto D with --preserve-merges
should keep E as-is, or rebase it onto D, too, in the following
scenario:

A - B - C - D
      \   \
        E - F

Be that as may (the current behavior is to keep it as-is, the intended
upcoming change will rebase it), we should not test whether E was kept
as-is, but only whether it is where we'd expect it.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
lib-rebase: be more careful how to edit the edit script

We really only want to remove the usage, not all comments. This used to
make no difference because we did not generate comments before the
usage, but that is going to change: the upcoming changes in 'rebase -i
-p' will prefix the 'merge' lines with the original merge commit's
one-line.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
lib-rebase: handle SED_LINES

Earlier, it looked good enough to be able to rewrite edit scripts for
the purpose of unit tests via FAKE_LINES, but that assumes a very fixed
file format.

Let's be cleverer and allow calling sed (1) with a specified command
instead.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Future-proof test for rebase -p

We are about to change the way 'rebase -i -p' works, including a
change in the format of the edit script.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
rebase -i: introduce the 'label' and 'goto' commands

In edit scripts, 'label <nick>' will mark the then-current commit for
later use with 'goto <nick>' (which will reset the HEAD to the
formerly-current commit).

These two commands will be used extensively in the upcoming changes to
'rebase -i -p'.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
rebase -i: introduce the 'merge' command

In edit scripts, 'merge [-c <message-commit>] <commit>...' will merge
the specified commits, possibly taking the commit message from another
commit.

This command will be used extensively in the upcoming changes to
'rebase -i -p'.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
rebase -i: allow a comment after 'merge'

Allow comments after a hash sign, i.e. lines in the edit script like
this one:

	merge -c abcdef cafebabe # comment

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
lib-rebase: handle more commands

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Teach rebase about preserving merges while in interactive mode

It has been quite a while since I tried my hand at this... But with Git
for Windows' fork needing to hold several topic branches, I felt the
need for something practical. Something like 'git rebase --interactive
--preserve-merges' that can handle fixup commits.

The major obstacle was the need to implement our own topological order.
Why? Because rev-list's topo-order is overly eager to continue with the
*last* parent after inspecting a merge commit, whereas we want to
continue with the *first* parent so that we have longer runs of "pick"
commands before merging, without having to jump around (if you're a
Badger, you may sing and dance at this point).

This is how we do it: we first make a list of tip commits (i.e.  commits
at the end of afore-mentioned pick & merge runs), in the order in which
we want to build the edit script.

For each tip, we then build the edit script in *reverse* order,
traversing from each commit to its first parent. Whenever we encounter a
parent commit that is already in the edit script, we remember to label
it and stop. Upon encountering a first parent commit that is not to be
rebased at all, we are done with that particular tip, too.

To support this mode, we added three new commands previously:

	label <name>: make a temporary ref for the now-current commit
	goto <name>: jump to a previously labeled temporary ref
	merge -c <commit> <parents>: perform a merge

Technically, we could have done all of these as "exec" lines, but they
would have looked horribly ugly.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>