{"thread":{"id":"56582","subject":"Feature Request: `git commit --amend-to`","startedAt":"2021-09-24T16:04:50Z","lastAt":"2021-09-30T13:56:15Z","messageCount":7,"participants":["Aidan Gallagher","Carlo Arenas","Glen Choo","Ævar Arnfjörð Bjarmason","Fabian Stelzer","Phillip Wood"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"436970","messageId":"CAENgTz0st6RpnVusP67-SSh2eENSxQn1_qiEqUDiMKzg=r54vQ@mail.gmail.com","threadId":"56582","inReplyTo":"CAENgTz2DoStQEqoKYKa-qMcyaez64u55mnv1HHOzDm392fuEqQ@mail.gmail.com","subject":"Feature Request: `git commit --amend-to`","fromName":"Aidan Gallagher","fromEmail":"aidgal2@gmail.com","sentAt":"2021-09-24T16:04:34Z","receivedAt":"2021-09-24T16:04:50Z","isPatch":false,"sender":{"key":"aidgal2@gmail.com","avatar":null},"body":"`git commit --amend` is very useful for adding changes to the previous\ncommit quickly.\n\nUnfortunately, it is more difficult to add changes to older commits.\nTo do so I have to enter interactive rebase, mark the commit to\nchange, make the changes, amend the previous commit, and continue the\ninteractive rebase.\n\nIt would be nice if there was a single command to do this like `git\ncommit --amend-to SHA`\n\nI have solved this issue for myself with this handy alias I found online\n```\ngit config --global alias.amend-to '!f() { SHA=`git rev-parse \"$1\"`;\ngit commit --fixup \"$SHA\" && GIT_SEQUENCE_EDITOR=true git rebase\n--interactive --autosquash \"$SHA^\"; }; f'\n```\n\nI think it would be beneficial if a command `git commit --amend-to`\ncould be officially added.\n\nThanks,\nAidan Gallagher\n"},{"id":"436980","messageId":"CAPUEspgr71t-thozi+Ez4xwxAkSJizsLuV=0TnROKZ85M6-kBg@mail.gmail.com","threadId":"56582","inReplyTo":"CAENgTz0st6RpnVusP67-SSh2eENSxQn1_qiEqUDiMKzg=r54vQ@mail.gmail.com","subject":"Re: Feature Request: `git commit --amend-to`","fromName":"Carlo Arenas","fromEmail":"carenas@gmail.com","sentAt":"2021-09-24T17:15:20Z","receivedAt":"2021-09-24T17:15:40Z","isPatch":false,"sender":{"key":"carenas@gmail.com","avatar":"https://avatars.githubusercontent.com/u/76036?v=4"},"body":"On Fri, Sep 24, 2021 at 9:08 AM Aidan Gallagher <aidgal2@gmail.com> wrote:\n> I have solved this issue for myself with this handy alias I found online\n> ```\n> git config --global alias.amend-to '!f() { SHA=`git rev-parse \"$1\"`;\n> git commit --fixup \"$SHA\" && GIT_SEQUENCE_EDITOR=true git rebase\n> --interactive --autosquash \"$SHA^\"; }; f'\n> ```\n\nsince v2.31.0 you can do instead :\n\n  git commit --fixup reword:$SHA && EDITOR=true git rebase\n--interactive --autosquash \"$SHA^\"\n\ngranted it is not 1 command, but usually I find it useful to do\nseveral of those and then one single\nrebase at the end.\n\nCarlo\n"},{"id":"437328","messageId":"kl6l1r58r6ba.fsf@chooglen-macbookpro.roam.corp.google.com","threadId":"56582","inReplyTo":"CAPUEspgr71t-thozi+Ez4xwxAkSJizsLuV=0TnROKZ85M6-kBg@mail.gmail.com","subject":"Re: Feature Request: `git commit --amend-to`","fromName":"Glen Choo","fromEmail":"chooglen@google.com","sentAt":"2021-09-28T16:52:25Z","receivedAt":"2021-09-28T16:52:30Z","isPatch":false,"sender":{"key":"glencbz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58092771?v=4"},"body":"Carlo Arenas <carenas@gmail.com> writes:\n>   git commit --fixup reword:$SHA && EDITOR=true git rebase\n> --interactive --autosquash \"$SHA^\"\n>\n> granted it is not 1 command, but usually I find it useful to do\n> several of those and then one single\n> rebase at the end.\n\nThis is fairly similar to what I use, though I use this through the\nMagit Emacs plugin.\n\nMy concern with \"--amend-to\" is that the semantics aren't as simple as\n--amend.\n\nWith --amend, you know you're working on the branch tip, so\nit's relatively simple to discard the last commit and create a new one.\n\nWith something like --amend-to, you aren't just modifying a single\ncommit, you are also introducing a potential merge conflict with every\ncommit after that. You would have to provide some kind of facility for\nusers to fix the merge conflicts. A command like git rebase --autosquash\ndoes a good job at communicating to users that they are actually doing a\nrebase and they need to be prepared to fix problems through a rebase UX.\nHowever, git commit --amend-to communicates none of that. A user who\ntakes a cursory glance at git commit --amend-to has no idea that they\nare potentially comitting to a rebase.\n\nI personally think the current UI makes sense given how Git works. I\nalso wish that it were easier to do --amend-to, but I think the problem\nhas more to do with how Git manages merges and conflicts and less to do\nwith having shortcuts in the CLI.\n"},{"id":"437348","messageId":"87y27gv5bk.fsf@evledraar.gmail.com","threadId":"56582","inReplyTo":"kl6l1r58r6ba.fsf@chooglen-macbookpro.roam.corp.google.com","subject":"Re: Feature Request: `git commit --amend-to`","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-09-28T19:54:28Z","receivedAt":"2021-09-28T20:00:19Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Sep 28 2021, Glen Choo wrote:\n\n> Carlo Arenas <carenas@gmail.com> writes:\n>>   git commit --fixup reword:$SHA && EDITOR=true git rebase\n>> --interactive --autosquash \"$SHA^\"\n>>\n>> granted it is not 1 command, but usually I find it useful to do\n>> several of those and then one single\n>> rebase at the end.\n>\n> This is fairly similar to what I use, though I use this through the\n> Magit Emacs plugin.\n>\n> My concern with \"--amend-to\" is that the semantics aren't as simple as\n> --amend.\n>\n> With --amend, you know you're working on the branch tip, so\n> it's relatively simple to discard the last commit and create a new one.\n>\n> With something like --amend-to, you aren't just modifying a single\n> commit, you are also introducing a potential merge conflict with every\n> commit after that. You would have to provide some kind of facility for\n> users to fix the merge conflicts. A command like git rebase --autosquash\n> does a good job at communicating to users that they are actually doing a\n> rebase and they need to be prepared to fix problems through a rebase UX.\n> However, git commit --amend-to communicates none of that. A user who\n> takes a cursory glance at git commit --amend-to has no idea that they\n> are potentially comitting to a rebase.\n>\n> I personally think the current UI makes sense given how Git works. I\n> also wish that it were easier to do --amend-to, but I think the problem\n> has more to do with how Git manages merges and conflicts and less to do\n> with having shortcuts in the CLI.\n\nI think that users who'd like an --amend-to would probably be happy with\nor might want to try out something like \"hg absorb\", which is something\nI think we should have stolen in git already, but it's never too late.\n\nI.e. it's a \"git commit --squash\" on steroids, which tries to find what\ncommit to amend things into.\n\nSee [1] (and [2] for an archive of the linked PDF) for a past\nreference. There's a \"git absorb\" in Rust that I haven't tried out, but\nseems interesting[3]. It looks like \"absorb\" is now part of \"hg\"\nitself[4], but I'd looked at & tried it back when it was part of the\nFacebook-specific patchset to \"hg\", which I understand has then mostly\nor entirely gotten upstreamed in some way.\n\nI'd think that for a git implementation we'd want to re-use the engine\nwe've got in range-diff.c, i.e. consider each unstaged hunk and find\nwhich hunk/commit in say @{u}.. to squash it into.\n\n1. https://lore.kernel.org/git/877ej0iuhc.fsf@evledraar.gmail.com\n2. https://web.archive.org/web/20181003211051/http://files.lihdd.net/hgabsorb-note.pdf\n3. https://crates.io/crates/git-absorb\n4. https://gregoryszorc.com/blog/2018/11/05/absorbing-commit-changes-in-mercurial-4.8/\n"},{"id":"437468","messageId":"kl6lwnmzpbhq.fsf@chooglen-macbookpro.roam.corp.google.com","threadId":"56582","inReplyTo":"87y27gv5bk.fsf@evledraar.gmail.com","subject":"Re: Feature Request: `git commit --amend-to`","fromName":"Glen Choo","fromEmail":"chooglen@google.com","sentAt":"2021-09-29T16:55:45Z","receivedAt":"2021-09-29T16:55:49Z","isPatch":false,"sender":{"key":"glencbz@gmail.com","avatar":"https://avatars.githubusercontent.com/u/58092771?v=4"},"body":"Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n\n>> [...] I think the problem\n>> has more to do with how Git manages merges and conflicts and less to do\n>> with having shortcuts in the CLI.\n>\n> I think that users who'd like an --amend-to would probably be happy with\n> or might want to try out something like \"hg absorb\", which is something\n> I think we should have stolen in git already, but it's never too late.\n\nAgree. I think some \"hg absorb\" features get at the heart of what I\nmeant, which is that users would benefit from making this merge conflict\nresolution a lot simpler.\n\n> I.e. it's a \"git commit --squash\" on steroids, which tries to find what\n> commit to amend things into.\n\nBut this is an even bigger step up from what I was suggesting. I blame\nmy own lack of imagination for not even considering this possibility.\n\nTo me, what really sells the feature is the \"history of lines\" approach\ncited in\nhttps://gregoryszorc.com/blog/2018/11/05/absorbing-commit-changes-in-mercurial-4.8/:\n\n  The automatic rewriting logic of hg absorb is implemented by following\n  the history of lines. This is fundamentally different from the approach\n  taken by hg histedit or git rebase, which tend to rely on merge\n  strategies based on the 3-way merge to derive a new version of a file\n  given multiple input versions.\n\nTraditional 3-way merge is extremely frustrating when you find yourself\ntouching the same lines over and over in a rebase, and I think \"history\nof lines\" maps quite cleanly to how humans think of lines. However I'm\nnot sure if Git has any machinery for doing this.\n"},{"id":"437508","messageId":"435d33d0-8991-d8c5-85b0-928ec97310c6@gigacodes.de","threadId":"56582","inReplyTo":"kl6lwnmzpbhq.fsf@chooglen-macbookpro.roam.corp.google.com","subject":"Re: Feature Request: `git commit --amend-to`","fromName":"Fabian Stelzer","fromEmail":"fs@gigacodes.de","sentAt":"2021-09-30T08:05:13Z","receivedAt":"2021-09-30T08:06:21Z","isPatch":false,"sender":{"key":"fs@gigacodes.de","avatar":"https://avatars.githubusercontent.com/u/564858?v=4"},"body":"On 29.09.21 18:55, Glen Choo wrote:\n> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n> \n>>> [...] I think the problem\n>>> has more to do with how Git manages merges and conflicts and less to do\n>>> with having shortcuts in the CLI.\n>>\n>> I think that users who'd like an --amend-to would probably be happy with\n>> or might want to try out something like \"hg absorb\", which is something\n>> I think we should have stolen in git already, but it's never too late.\n> \n> Agree. I think some \"hg absorb\" features get at the heart of what I\n> meant, which is that users would benefit from making this merge conflict\n> resolution a lot simpler.\n> \n\nI have never used hg absorb but after reading about its concepts i think\nit best maps to something like git automatically creating fixup commits\nfor you. I also found https://github.com/tummychow/git-absorb (also\nuntested by me) which claims to do exactly this.\n\nSomething like having \"git commit -a --fixup\" (without any commit hash)\ncreate matching fixup commits for all changes i made would already be\nquite cool.\n\nFrom what i see from our corporate environments and github/bitbucket\nworkflows though i think most users never even heard about fixup commits\nor ever did an interactive rebase (this is totally a view from my\ncorporate bubble and might not really represent the average git userbase).\nMost code review workflows i see don't focus on individual commits and\nonly present the complete final patch (some at least allow you to view\nindividual commits but not much more) and therefore users have no big\nincentive during review to shape their changes into proper commits.\nSome tools (like phabricator) even squash the final patch into a single\ncommit by default which i think is a good idea if single commits are of\nno concern during review anyway.\n\nI wonder if something like an easy to use \"absorb\" feature (without\nfixups, rebases) might encourage and produce more clean commit histories\neven for the mentioned workflows.\n\n"},{"id":"437540","messageId":"18e7c572-3f71-e3d3-b5c3-1f8c54196899@gmail.com","threadId":"56582","inReplyTo":"kl6lwnmzpbhq.fsf@chooglen-macbookpro.roam.corp.google.com","subject":"Re: Feature Request: `git commit --amend-to`","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2021-09-30T13:56:06Z","receivedAt":"2021-09-30T13:56:15Z","isPatch":false,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 29/09/2021 17:55, Glen Choo wrote:\n> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n> \n>>> [...] I think the problem\n>>> has more to do with how Git manages merges and conflicts and less to do\n>>> with having shortcuts in the CLI.\n>>\n>> I think that users who'd like an --amend-to would probably be happy with\n>> or might want to try out something like \"hg absorb\", which is something\n>> I think we should have stolen in git already, but it's never too late.\n> \n> Agree. I think some \"hg absorb\" features get at the heart of what I\n> meant, which is that users would benefit from making this merge conflict\n> resolution a lot simpler.\n> \n>> I.e. it's a \"git commit --squash\" on steroids, which tries to find what\n>> commit to amend things into.\n> \n> But this is an even bigger step up from what I was suggesting. I blame\n> my own lack of imagination for not even considering this possibility.\n> \n> To me, what really sells the feature is the \"history of lines\" approach\n> cited in\n> https://gregoryszorc.com/blog/2018/11/05/absorbing-commit-changes-in-mercurial-4.8/:\n\nThanks for the link, I had not realized absorb did not use a 3-way merge.\n\n>    The automatic rewriting logic of hg absorb is implemented by following\n>    the history of lines. This is fundamentally different from the approach\n>    taken by hg histedit or git rebase, which tend to rely on merge\n>    strategies based on the 3-way merge to derive a new version of a file\n>    given multiple input versions.\n> \n> Traditional 3-way merge is extremely frustrating when you find yourself\n> touching the same lines over and over in a rebase, and I think \"history\n> of lines\" maps quite cleanly to how humans think of lines. \n\nI agree that conflicts get frustrating with fixups but having just \nplayed with hg absorb it seems a bit too cavalier to me. The test script \nat the end of this email sets up the history below. I was surprised it \napplied the fixup as to my mind it is ambiguous whether 'z' should go \nbefore of after 'x' in HEAD~1 and whether 'p' should go before or after \n'e' in HEAD~2.\n\nWorktree HEAD HEAD~1 HEAD~2       HEAD HEAD~1 HEAD~2\n    a       a    a     +a            a    a     +a\n    b       b    b     +b            b    b     +b\n   +z      -x   +x     +c      =>   -x   +x     +z\n    c       c    c     +d            z    z     +c\n    d       d    d     +e            c    d     +d\n   +p       f   -e     +f            d   -e     +e\n    f            f                   p    p     +p\n                                     f    f     +f\n\n> However I'm not sure if Git has any machinery for doing this.\n\nI think we could use a modified version of blame to find which commit a \nline comes from, but bail out in cases where it is ambiguous such as my \nexample above (I think we'd want to require that the two context lines \neither side of an insertion remain adjacency as we track backwards \nthrough the history, and that a group of modified lines remain \ncontiguous). The commits could be rewritten by applying zero context \npatches taking care to adjust the offsets where the fixup adds or \ndeletes lines (similar to what add -p does)\n\nBest Wishes\n\nPhillip\n\n----- >8 -----\nwrite_lines() {\n     printf '%s\\n' \"$@\"\n}\n\nrepo=\"$(mktemp -d)\" &&\n     cd \"$repo\" &&\n     hg init &&\n     write_lines >file a b c d e f &&\n     hg add file &&\n     hg commit -m initial &&\n     write_lines >file a b x c d f &&\n     hg commit -m one &&\n     write_lines >file a b c d f &&\n     hg commit -m two &&\n     write_lines >file a b z c d p f &&\n     hg absorb &&\n     hg log -p\n\n\n"}]}