Previously, the interactive rebase edit mode placed the user after the commit in question. That was awkward because a commit is supposedly immutable. Thus, she was forced to use "git commit --amend" for her changes. To improve on this UI, we now issue "git reset --soft HEAD^" before exiting to the user. This puts the changes in the index, editable in the Git sense. It also makes sure that a pre-filled editor is fired up when doing "git rebase --continue", in case the user just wanted to fix the commit message. The revised UI is close to the situation in a merge/rebase conflict, and thus familiar to the user. Signed-off-by: Anders Melchiorsen <mail@cup.kalibalik.dk> --- I always have a hard time figuring out what to do during an interactive rebase. Recently, it dawned on me that the reason is that I have to do different things: one thing when editing on purpose, and a different thing when resolving a conflict. So my fingers never learn. With this change, I propose to make the UI more uniform. I think that the new way is more intuitive, too, if you will agree that a Git UI can be intuitive. As I expect this to not be acceptable due to compatibility concerns, I have not tested it much. The patch is mostly to catch some attention, but I will be happy to complete it if there is interest in the change. It was surprising for me to find the needed code already present. Now I know that I do not have to do "git commit --amend", it will happen automatically if I add some files. That trick alone is worth the time that I have spent on this :-). Cheers, Anders. Documentation/git-rebase.txt | 10 ++++------ git-rebase--interactive.sh | 29 ++++++++--------------------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 32f0f12..3442a68 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -320,9 +320,8 @@ not look at them but at the commit names ...
We may need a version bump to 1.7.0 to update the UI for this command, but please do test rigorously to build a stronger case for a saner UI. I've always had trouble with the instruction we give for splitting one commit into two using the interactive rebase in the documentation, as it always had a strong "Huh?" effect on me when it suddenly starts talking about doing a "git reset HEAD^"; I suspect your change may improve this situation quite a bit. --
On Wednesday 14 January 2009, Junio C Hamano <gitster@pobox.com> wrote=20 about 'Re: [RFC PATCH] Make the rebase edit mode really end up in an edit=20 Instead of changing the meaning of edit, how about introducing a "replace"= =20 command? =2D-=20 Boyd Stephen Smith Jr. ,=3D ,-_-. =3D.=20 bss@iguanasuicide.net ((_/)o o(\_)) ICQ: 514984 YM/AIM: DaTwinkDaddy `-'(. .)`-'=20 http://iguanasuicide.net/ \_/ =20
That seems like at best an awkward workaround, not a real solution to the problem, which is that the term "edit XXXX" suggests you're starting with XXXX and modifying it. The term "replace" by contrast, seems more to connote entirely removing XXXX and substituting something else. [I do wonder how on earth the current awkward behavior was accepted in the first place...] -Miles -- "Most attacks seem to take place at night, during a rainstorm, uphill, where four map sheets join." -- Anon. British Officer in WW I --
On Wednesday 14 January 2009, Miles Bader <miles@gnu.org> wrote about 'Re:= =20 Actually, I think it's a better solution (or rather a solution to the real= =20 problem) because others have already said they like and expect the current= =20 edit behavior. The "real problem" is you need different behavior for your interactive=20 Exactly. "edit" is: While interactively rebuilding history (rebase -i), you= =20 get to the first place that commit existed and then modify it=20 Exactly. "replace" is: While rebasing you stop just before the commit=20 existed (changes are even staged) and decide to do something else (like=20 (Actually, I do too, but it's accepted and expected behavior now--good=20 reason not to change it.) =2D-=20 Boyd Stephen Smith Jr. ,=3D ,-_-. =3D.=20 bss@iguanasuicide.net ((_/)o o(\_)) ICQ: 514984 YM/AIM: DaTwinkDaddy `-'(. .)`-'=20 http://iguanasuicide.net/ \_/ =20
That's actually very easy to explain. Both the contributor and the maintainer were rather familiar with the workflow using tools before "rebase -i" appeared, and to them, editing an existing commit was equivalent to first plant yourself on the commit to be amended, issue "commit --amend", and continue on with other tasks (similarly, "picking" an existing commit is to cherry-pick the commit to the state whatever the previous sequence of commands left). In other words, they both thought in terms of the underlying command sequence and it did not appear unnatural at all to them. --
Hi, Thanks for the praise! It is always nice to hear that one's work is appreciated. --
I think we might want do differentiate editing a commit (modifying either the commit message or the patch or both) or splitting a commit. The first is served well with the current 'edit' rebase command IMHO. I don't really see the point of the additional 'git reset --soft HEAD^'. * If you want to edit the commit message only, then you are better off with 'git commit --amend', because it preserves the previous commit message. But with 'git reset --soft HEAD^' and 'git commit' the commit message is "lost"; you have to use 'git commit -c ORIG_HEAD' instead, which is not that straightforward (and we don't have completion support for it). * If you want to modify the patch, too, then you would have to use 'git add' anyway, regardless of whether there was a 'git reset --soft HEAD^', or not. The only benefit of that 'reset' I'm seeing is that in that case 'git diff --cached' would show all the changes that would be committed; without the 'reset' 'git diff --cached HEAD^' is needed. But I'm not sure whether that benefit would offset the confusion of one more rebase command with just slightly different meaning. For the second we could introduce a new rebase command like 'split', which would do the same as 'edit' but would also perform that 'git reset HEAD^' mentioned in the documentation automatically. Or perhaps it could be called 'divide', since the 's' abbreviation for 'split' is already taken by 'squash'. (Or maybe use capital 'S' for 'split'? might be confusing...) Regards, Gábor --
I agree that is a true disadvantage that shows "reset --soft HEAD^" is a Perhaps. --
But it's not: "It also makes sure that a pre-filled editor is fired up when doing "git rebase --continue", in case the user just wanted to fix the commit message." -- Cheers, Sverre Rabbelier --
Indeed, but in this case the rebase process will continue after
finishing the commit message. OTOH, with the current behaviour, you
must do a 'git commit --amend && git rebase --continue', which might
seem more complicated at first sight, but...
But the current behaviour of the 'edit' rebase command gives you the
possibility of adding further commits on top of the selected one
(after you have edited that or left intact, doesn't matter). To do
that with this automatic 'reset --soft HEAD^' modification you would
first need to 'git commit -c @{1}' to keep the selected commit before
going on with adding further commits, which is not quite nice.
Regards,
Gábor
--
No, you don't have to do that. As long as you only want to "edit" the commit you marked as "edit", you only need to use "git add" and "git rebase --continue". rebase -i checks whether HEAD still resolves to the same commit and if so, it automatically does the soft reset for you. Maybe we should just advertise that in the message provided by rebase after it stops? I'm afraid I can't come up with a sane wording though, as there are still cases when you need to commit yourself, eg. when you use reset. And getting that into one simple sentence seems a bit hard (for me). A bit off-topic: The "auto-amend" code path passes --no-verify to git commit. What's the reason for doing that? I actually always expected that to use my pre-commit hook to stop me from committing crap. :-/ Björn --
I was happy to learn that trick when looking at the source, so I agree
that it is a good idea to advertise it. You are right that it is hard
to describe well in few words, though. Does somebody feel like
repainting this?
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -336,14 +336,13 @@ do_next () {
make_patch $sha1
git rev-parse --verify HEAD > "$DOTEST"/amend
warn "Stopped at $sha1... $rest"
- warn "You can amend the commit now, with"
- warn
- warn " git commit --amend"
- warn
- warn "Once you are satisfied with your changes, run"
+ warn "You can amend the commit now, by marking"
+ warn "paths with 'git add <paths>' and running"
warn
warn " git rebase --continue"
warn
+ warn "If you want to create new commits, run"
+ warn "'git commit' yourself before continuing."
exit 0
;;
squash|s)
--
Yeah, I agree.
I think my confusion mostly came from perception, and the way the "edit"
action is (not) explained.
What "edit" means is "pick this commit and then stop to give control back
to the user. The user is free to muck with the history starting from the
state after picking the named commit in any way, and --continue will carry
on the rest of the insns from the state" [*1*]. Once I realize that,
it becomes clear what it means to do any of the following when "edit"
gives the control back to me:
(1) commit --amend (with or without changing the tree and message); this
is the originally intended usage. Edit the commit the machinery just
picked and let it continue. The end result is as if you edited one
commit in the sequence.
(2) making completely unrelated commits on top of the state "edit" gave
you; this inserts a new commit in the sequence.
(3) first "reset HEAD^", commit selected parts of the difference in one
commit, commit the reaminder in another commit; this splits the
commit the machinery just picked into two.
By the way, "rebase --continue" codepath has extra code that does
something magical when the index does not match the HEAD commit. I
suspect what it does makes sense only in the originally intended usage
sequence (i.e. "edit" stops, you want to do "commit --amend" and then
"rebase --continue" but somehow you forgot to commit everything).
How well does that logic work when the user wanted to do (2) or (3) above,
and happened to have the index unclean when s/he said "rebase --continue"?
Does it do something nonsensical?
[Footnote]
*1* Explained the same way, "pick" is "cherry-pick the named commit to
replay its effect and then continue".
--
Hi, AFAICT the special handling is the only sane way to cope with (2) and (3), if it is the special handling that I am talking about: If the current HEAD differs with the HEAD just after dropping to the shell, rebase --continue will _not_ just commit with the recorded information and continue. The intended effect is that when you split a commit and continue with uncommitted changes, it will not just go ahead and call an editor with the original commit message: this message is now likely wrong. It will only call an editor with the original message as a convenience when you did changes, but did not commit at all before continuing. Just a convenience I found quite useful. Ciao, Dscho --
Hi, I think I like it and I think it's not the first time this comes up on the list. (Not sure, and too lazy to grab the archives.) Also, in the design process of "git-sequencer" we (at least my mentors and I) discussed about doing this ("edit" vs "pause"), too, but it is always bad to change behavior many people are used, too. But sequencer instructions support options. So this could be solved as an option for "edit", e.g. "edit --no-commit" (or "edit -n"). So I'm writing this on my TODO list for the time after sequencer is merged into git... Regards, Stephan -- Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F --
Hi, Maybe, maybe not. I frequently rebase with "edit" when I actually mean "stop" (but "s" was taken from "squash" already). Then I test things, possibly fixing them. So in that case, I do not want a git reset --soft HEAD^. In any case, there is a pretty obvious difference between a merge conflict and a stop at "edit": the latter even shows you a pretty verbose explanation what to do next. I also have to admit that it escapes me why you would want to force a new commit if nothing was changed to begin with. However, I often would like to have "amend message" or some such, and I remember having seen patches, but I do not remember why they did not make it in. Ciao, Dscho --
Absolutely! I use "edit" for this purpose as well quite frequently. -- Hannes --
What about providing both options? "modify" does the "git reset --soft HEAD^" (Anders' suggestion) "amend" requires a "git commit --amend" (current behaviour) "edit" == "amend", but is deprecated and goes away in the future ...Johan -- Johan Herland, <johan@herland.net> www.herland.net --
Why have amend do the same as edit? If you add an 'amend' one instead make it drop you into an editor to change the commit message. That's a workflow I often use. Often times I do not have a proper commit message when I commit (sometimes it is the result of "git commit -a -m "tmp"). To me having an 'amend' command that allows one to edit the And as such, have edit do what it currently does. -- Cheers, Sverre Rabbelier --
Hi, FWIW I fully agree. If at all, I'd introduce 'examine' as a synonym to 'edit' (might be more intuitive). However, for the same reason (is it intuitive?) I am not fully convinced of 'amend' either. Because --amend _can_ mean that you change the diff of the commit. Maybe 'correct', 'redact' or 'rephrase'? BTW I was not fully happy with 'edit' back then, either, which is the reason why I showed the usage in the comment _above_ the commit list. But nobody could suggest a name that I found convincingly better. Ciao, Dscho --
editmsg?
--
Adeodato Simó dato at net.com.org.es
Debian Developer adeodato at debian.org
He who has not a good memory should never take upon himself the trade of lying.
-- Michel de Montaigne
--
Hi, On Thu, 15 Jan 2009, Adeodato Sim
On Thu, Jan 15, 2009 at 14:41, Johannes Schindelin "msgedit" with shortcut 'm'? -- Cheers, Sverre Rabbelier --
Hi, *sigh* If I was just not so late with sequencer... There it is "pick -e" (or "pick --edit"). Regards, Stephan -- Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F --
Hi, ... which obviously shares all the shortcomings of "edit". Ciao, Dscho --
Yes, you are right. I always write the full word myself, so I forgot
abbreviations are supported and commonly used.
--
Adeodato Simó dato at net.com.org.es
Debian Developer adeodato at debian.org
A lie can go round the world before the truth has got its boots on.
-- Terry Pratchett
--
On Thu, Jan 15, 2009 at 13:36, Johannes Schindelin Examine suggests that you cannot change the commit (you can look, but OTOH, when you have no changes staged "git commit --ammend" will do exactly that, it will let you edit the commit message of the last The coder's law #349: "The hardest part of writing new functionality is coming up with a proper name that everyone agrees on". -- Cheers, Sverre Rabbelier --
Hi, So if you want to look but don't touch it, you can do exactly that. Brilliant, isn't it? Ciao, Dscho --
On Thu, Jan 15, 2009 at 14:42, Johannes Schindelin Yes, ofcourse, but the current edit does allow you to modify (with 'git commit --amend')... I agree with Johan Herland though, Bikeshedding ftw :). -- Cheers, Sverre Rabbelier --
'stop' would be closest to what it currently does. It stops and it is up to you how to screw up the result ;-). --
Hmmm, yes, I think that would be a better alias; but I think I like the idea to wait for changes like this till sequencer goes in, mhh? -- Cheers, Sverre Rabbelier --
Hi, But it shares the first letter with 'squash'. Ciao, Dscho --
Personally, I'd rather use "pause", but that is taken as well. Other suggestions: wait yield rest timeout ..Johan -- Johan Herland, <johan@herland.net> www.herland.net --
Hi, As rebase -i is just a loop of cherry-picks, as a C programmer I would think: "does this break out of the loop"? Ciao, Dscho --
Perhaps stating the obvious, but: wait - best suggestion so far, seeing as we can't use "stop" yield - might sound intuitive to a Ruby programmer; but for others it's probably not so obvious as "yield" has a number of meanings in normal English similar to "give up", "give over" etc rest - not quite as good as "wait"; machines wait for humans, but the never need to rest timeout - sounds like an error condition, so not really appropriate Sorry for participating in the painting. Just thought that "wait" was good enough to merit some positive feedback. Cheers, Wincent --
This is a fun game. I like the color "halt". j. --
Ooh, yes. An even better color. Wincent --
Nice. I like this one as well. After some more thinking (triggered by Junio's recent post in another subthread), it occured to me that the current behaviour (currently known as "edit") is not something that is applied to one of the commits in the rebase list per se, but rather something that affects the rebase machinery *between* commits. So instead of edit e8902c1 Foo we should consider something like pick e8902c1 Foo halt which I think better encapsulates the current behaviour. (IOW, insert "halt" wherever you'd like to muck about with the history; e.g. doing "commit --amend", inserting extra commits, etc.) We can then make shortcuts for common actions: amend e8902c1 Foo does a "pick" followed by "commit --amend" (for editing the commit message), followed by "rebase --continue". Finally, we implement Anders' suggestion: modify e8902c1 Foo (or whatever synonym for "edit" we converge on) does a "pick" followed by a "reset --soft HEAD^", followed by a "halt". Have fun! ...Johan -- Johan Herland, <johan@herland.net> www.herland.net --
Of all the suggestions, I like this one the most. Also, when placed like I do not think that "amend" is the best word for editing only the commit message. A "commit --amend" can also make a new tree, so reusing the word with a different meaning could be bad. As for alternatives, however, I can only come up with "copyedit", and that is so horrible that I will not even propose it :-) Cheers, Anders. --
"rephrase"? ...Johan -- Johan Herland, <johan@herland.net> www.herland.net --
This is the first one that I found acceptable. 'amend', 'modify' and 'edit' are just too close and non-intuitive: they don't indicate _what_ will be amended, modified or edited at all. 'rephrase', on the other hand, is better, as you can rephrase a commit message, but it's weird to say "rephrase the patch". But it's still not as to-the-point as 'editmsg' (but that one has conflicting abbreviation). Best, Gábor --
Hi, On Fri, 16 Jan 2009, SZEDER G
Yes, I indeed missed that. And still think that 'rephrase' is best
among all the suggestions for this "edit just the commit message"
thing. ('editmsg' conflicts; 'amend', 'modify', and 'correct' are
not obvious enough (they don't clearly indicate what will be
modified); and I'm not sure about 'redact', but I don't really like it
because I had to look it up in the dictionary first).
Best,
Gábor
--
Two more colors for consideration: - "msg"/"msgedit"/"message" or similar - "reword" I agree with Gábor that options like "modify" aren't clear because there's nothing in them that suggests that they're intended to operate on the commit _message_. Wincent --
I very much like this suggestion, Stephan, is this somewhat similar to how git sequencer will do things? -- Cheers, Sverre Rabbelier --
Hi, Yes, it is pick e8902c1 # Foo pause in sequencer currently. Of course, "pause" could be renamed to "halt", "stop" or whatever you like. But I think everyone likes something different. And edit e8902c1 # Foo is simply a shortcut for the pick-pause above. (Or "e e8902c1" instead of edit, which works, too.) I usually prefer typing "cw edit<ESC>" over "o pause<ESC>" into vim in such cases. Regards, Stephan -- Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F --
Hi, Both 's' and 'p' shortcuts are already taken, unfortunately. Ciao, Dscho --
(BTW, I reply to this thread because I'm also often confused with the rebase. The thing that hits me most is that with resolving conflicts, you have to do a 'git commit' and with 'edit', you have to do a 'git commit --amend'. This can get confusing if you set up an interactive rebase where you have some new picks or squashes, and also an edit. If the rebase stops, you first have to carefully read whether you're supposed to do a 'git commit' or a 'git commit --amend', and remember that until you're finished with the changes). - Pieter --
You can handle both cases with: git add -u # Or whatever git rebase --continue Only when you split a commit, you have to explicitly reset and commit. Björn --
I think this demonstrates that you can do a lot more with 'edit' than just edit. 'redact' etc also don't cover it. Perhaps just a general 'pause' or something? You can then put something like 'pause -- pause, for example to amend commit' in the description part. --
That makes sense, perhaps we could name the feature described by the OP something like "reset", as that is what it actually does? -- Cheers, Sverre Rabbelier --
The names I chose are somewhat arbitrary, since we obviously have to keep on bikeshedding until we have something everybody can agree to. However, my rationale was that IMO the word "edit" more closely matches Anders' suggestion, and is therefore somewhat misleading as a description of the current behaviour. But we obviously cannot change the meaning of "edit" without upsetting current users. Therefore, introduce "amend" to more accurately describe the current behaviour. As for "modify", it was simply the best synonym for "edit" I could find. ...Johan -- Johan Herland, <johan@herland.net> www.herland.net --
