Hi again,
Jiří Paleček explained how trying to interactively rebase
1 --- 2 --- 3 --- 4 --- 5
to
1 --- 2+4 --- 3 --- 5
with git rebase -i -p fails utterly (the 3 is just forgotten).
I got a chance to look at this briefly again, and here’s what I
learned.
The current code
----------------
The “git rebase -i -p” code is very lightly modified from
“git rebase -i”. The list of commits you edit does not represent the
topology of the revision graph. It is just a list of pick lines for
_all_ commits in HEAD but not upstream, just like what you would get
with “git rebase -i”.
Example: given the history
4 --- 5
/ \
3 --- 6 --- 7 [HEAD, master]
/
1 --- 2 [upstream]
the “insn sheet” produced by “git rebase -i -p upstream” is simply
something like:
pick 6a2a427 3
pick 5437c76 6
pick ab03bd2 4
pick 1adb5b5 5
pick f021136 7
(try it!).
The pick insn then looks to the original commits to figure out what
the parents of the new commit should be! So you can’t change their
parentage, which means this is only good for transplanting a branch
wholesale.
A past attempt to fix it
------------------------
Jörg Sommer made a valiant attempt to fix this in a series including
a patch called “Teach rebase interactive the mark command”. The idea
is that if one wants to transplant a history like the above by hand,
you might do something like this:
git checkout 2
git cherry-pick 3
git tag A
git cherry-pick 4
git cherry-pick 5
git tag B
git checkout A
git cherry-pick 6
git merge B -m 7
git tag -d A
git tag -d B
The tags here are temporary bookmarkers to allow moving around within
the newly created history. Jörg’s idea was to use a new “mark” insn
to create what are in effect temporary tags like this.
Reception of the mark command
-----------------------------
Johannes Schindelin wrote [1]:
Actually, I think that this whole "mark" stuff is way too complicated,
as can be seen by the amount of patches needed to get it somewhere
usable.
I would like it much better, if there was something like
pick 5cc8f37 (init: show "Reinit" message even in ...)
pick 18d077c (quiltimport: fix misquoting of parse...)
merge 9876543:5cc8f37,18d077c (Merge blub)
reset 5cc8f37
...
I.e. like with filter-branch, and like with rebase -i -p in its
current form, we take the _original_ names as keys as to which
commits to merge, or where to reset to.
which makes a lot of sense. In other words, it is a pain to maintain
an insn list with many markers in it (and which do not have meaningful
names). It would be simpler to be able to refer to the commits
themselves.
Another variant by Dmitry Potapov [2]:
Maybe, it would be better if re-written commits were marked a bit
differently, so there will be no confusion about whether an original
or re-written commit is referred. For instance, re-written commits
can be marked by adding apostrophe at the end, so if the original
commit was "abcdef" then the re-written should be called as
"abcdef'". At least, it will make plain clear for anyone where in
merge rewritten commits are mentioned. Otherwise, it looks too
magical to me.
Dscho has written a lot more about this elsewhere, but it is kind of
hard to find today since gmane is down.
[1] http://marc.info/?l=git&m=120818225406611&w=2
[2] http://marc.info/?l=git&m=120956084007135&w=2
Recent work
-----------
See the thread http://markmail.org/message/jzi7xbotwq6bhb7b
and the repositories
http://repo.or.cz/w/git/price.git
and http://repo.or.cz/w/git/dscho.git/shortlog/refs/heads/rebase-i-p
Please keep me informed if you get a chance to work on this.
Many thanks,
Jonathan
--
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]