Hi Michael,
On Wed, 10 Oct 2018, Michael Witten wrote:
> In my opinion, the `--rebase-merges' feature has been broken since the
> beginning, and the builtin version should be fixed before it is moved
> ahead.
Everybody is entitled to an opinion. My opinion differs from yours, and I
am a heavy user of `git rebase -kir`.
The `--rebase-merges` feature is not without problems, of course. I can
name a couple of bugs, but I have a hunch that it is more efficient for me
to just fix them.
> In short: "labels" are brittle; see below for tests.
Sure, let's improve them.
> Also, here are some quick *additional* thoughts:
>
> * Labels should be simply "r0", "r1", ... "rN".
That would not be an improvement.
The *interactive* version of `--rebase-merges` is what I use extensively
to juggle Git for Windows' branch thicket. It would be really bad if I had
to somehow map those label names in my head, rather than having the
intuitively-understood labels.
I would understand if you suggested to try to come up with a better naming
than `branch-point-<n>`. But `r<n>`? That's worse than the current state.
By a lot.
> * Why is the command "label" and not "branch"?
Because it is more versatile than just a branch. It is also branch points.
As a matter of fact, the very first statement is about the `onto` label,
which is not a branch.
> * In my experience, there's a lot of this boiler plate:
>
> pick 12345
> label r1
> reset r0
> merge r1
>
> How about instead, use git's existing ideas:
>
> pick 12345
> reset r0
> merge ORIG_HEAD
Too magic. And you cannot change it easily. I had this very real example,
a couple of times yesterday: A merge was in one of the "branches", and
needed to be moved out of it:
pick abc
label branch-point
merge -C 0123 topic
pick def
label bug-fix
reset branch-point
merge -C 4567 bug-fix
This `merge -C 0123 topic` needed to be moved before the branch point.
Another example where the explicit labeling comes in *real* handy is when
I made a Pull Request in Git for Windows ready for contribution to core
Git. These Pull Requests are normally based on `master`, because that is
what the best PR flow is: you based your contributions as close to the tip
as possible, to avoid merge conflicts (and to test as close to the real,
after-merge thing). This would look like this:
label branch-point
pick 123
pick 456
label pr-0815
reset branch-point
merge -C abc pr-0815
Now, to prepare this for core Git, I have to graft this PR onto the
`master` of *upstream*, in our case I would use the `onto` label for that,
by inserting a `reset onto` just before `pick 123`.
So you see, the current, non-implicit, but very much explicit syntax,
makes all of these tasks *quite* easy, and more importantly,
straight-forward: I did not have to explain this to anyone who I needed to
teach how this works.
Remember: the syntax of the todo list is not optimized to be short. It is
optimized to be *editable*. I need to have a very easy way to juggle
criss-cross-merging branch thickets. And the current syntax, while
chattier than you would like, does the job. Pretty well, even.
> * Why not just `--merges' instead of `--rebase-merges'?
This ship has sailed. It is pointless to discuss this now.
Besides, I believe that in your quest to shorten things, you unfortunately
shortened things too much: it is no longer clear what "merges" means in
the context of `--merges`.
> Unfortunately, both the legacy version and the rewrite of
> `--rebase-merges' display a bug that makes this feature fairly
> unusable in practice;
You will be surprised just how much I would embrace bug fixes, once you
provide any.
> it tries to create a "label" (i.e., a branch name) from a commit log
> summary line, and the result is often invalid (or just plain
> irritating to work with). In particular, it fails on typical
> characters, including at least these:
>
> :/\?.*[]
And of course those are not the only ones. The trick is to reduce runs of
disallowed characters to dashes, as is already done with spaces.
Ciao,
Johannes
>
> To see this, first define some POSIX shell functions:
>
> test()
> {
> (
> set -e
> summary=$1
> d=/tmp/repo ##### WARNING. CHANGE IF NECESSARY.
> rm -rf "$d"; mkdir -p "$d"; cd "$d"
> git init -q
> echo a > a; git add a; git commit -q -m a
> git branch base
> echo b > b; git add b; git commit -q -m b
> git reset -q --hard HEAD^
> git merge -q --no-ff -m "$summary" ORIG_HEAD
> git log --graph --oneline
> git rebase --rebase-merges base
> ); status=$?
> echo
> return "$status"
> }
>
> Test()
> {
> if test "$@" 1>/dev/null 2>&1; then
> echo ' good'; return 0
> else
> echo ' fail'; return 1
> fi
> }
>
> Then, try various commit summaries (see below for results):
>
> test c
> test 'combine these into a merge: a and b'
> Test ab:
> Test a:b
> Test :
> Test a/b
> Test 'Now supports /regex/'
> Test ab/
> Test /ab
> Test /
> Test 'a\b'
> Test '\'
> Test 'Maybe this works?'
> Test '?'
> Test 'This does not work.'
> Test 'This works. Strange!'
> Test .git
> Test .
> Test 'Cast each pointer to *void'
> Test '*'
> Test 'return a[1] not a[0]'
> Test '[ does not work'
> Test '['
> Test '] does work'
> Test ']'
>
> Here are the results of pasting the above commands into my terminal:
>
> $ test c
> warning: templates not found in ../install/share/git-core/templates
> * 1992d07 (HEAD -> master) c
> |\
> | * 34555b5 b
> |/
> * 338db9b (base) a
> Successfully rebased and updated refs/heads/master.
>
> $ test 'combine these into a merge: a and b'
> warning: templates not found in ../install/share/git-core/templates
> * 4202c49 (HEAD -> master) combine these into a merge: a and b
> |\
> | * 34555b5 b
> |/
> * 338db9b (base) a
> error: refusing to update ref with bad name
> 'refs/rewritten/combine-these-into-a-merge:-a-and-b'
> hint: Could not execute the todo command
> hint:
> hint: label combine-these-into-a-merge:-a-and-b
> hint:
> hint: It has been rescheduled; To edit the command before continuing,
> please
> hint: edit the todo list first:
> hint:
> hint: git rebase --edit-todo
> hint: git rebase --continue
>
> $ Test ab:
> fail
> $ Test a:b
> fail
> $ Test :
> fail
> $ Test a/b
> good
> $ Test 'Now supports /regex/'
> fail
> $ Test ab/
> fail
> $ Test /ab
> fail
> $ Test /
> fail
> $ Test 'a\b'
> fail
> $ Test '\'
> fail
> $ Test 'Maybe this works?'
> fail
> $ Test '?'
> fail
> $ Test 'This does not work.'
> fail
> $ Test 'This works. Strange!'
> good
> $ Test .git
> fail
> $ Test .
> fail
> $ Test 'Cast each pointer to *void'
> fail
> $ Test '*'
> fail
> $ Test 'return a[1] not a[0]'
> fail
> $ Test '[ does not work'
> fail
> $ Test '['
> fail
> $ Test '] does work'
> good
> $ Test ']'
> good
>