{"thread":{"id":"49458","subject":"Git Evolve","startedAt":"2018-09-29T23:00:08Z","lastAt":"2018-11-09T13:06:26Z","messageCount":13,"participants":["Stefan Xenos","Junio C Hamano","Derrick Stolee","Taylor Blau","Ævar Arnfjörð Bjarmason","Kyle Meyer","Jakub Narebski","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"359321","messageId":"CAPL8ZivFmHqS2y+WmNR6faRMnuahiqwPVYsV99NiJ1QLHOs9fQ@mail.gmail.com","threadId":"49458","inReplyTo":null,"subject":"Git Evolve","fromName":"Stefan Xenos","fromEmail":"sxenos@google.com","sentAt":"2018-09-29T23:00:04Z","receivedAt":"2018-09-29T23:00:08Z","isPatch":false,"sender":{"key":"sxenos@google.com","avatar":null},"body":"Hello, List!\n\nI'm interested in porting something like Mercurial's evolve command to\nGit. I'll be following up with a formal proposal shortly, but before I\ndo I thought I'd introduce myself to the list and find out if anyone\nelse is interested in this topic.\n\nWhat is the evolve command?\n\nImagine you have three dependent changes up for review and you receive\nfeedback that requires editing all three changes. While you're editing\none, more feedback arrives on one of the others. What do you do?\n\nThe evolve command is a convenient way to work with chains of commits\nthat are under review. Whenever you rebase or amend a commit, the\nrepository remembers that the old commit is obsolete and has been\nreplaced by the new one. Then, at some point in the future, you can\nrun \"git evolve\" and the correct sequence of rebases will occur in the\ncorrect order such that no commit has an obsolete parent.\n\nPart of making the \"evolve\" command work involves tracking the edits\nto a commit over time, which could provide a lot of other benefits:\n\n- Systems like gerrit would no longer need to rely on \"change-id\" tags\nin commit comments to associate commits with the change that they\nedit, since git itself would have that information.\n- You could directly view the history of a commit over time (ie: the\nsequence of amends and rebases that occurred with that commit,\northogonal to the history of the branch it is on). If you've used\nmercurial, this would be a git equivalent to \"hg obslog\". If you've\nused gerrit, this would be like the gerrit \"change log\" but it would\nwork for all commits and work offline.\n- You can easily list all the changes that you have as works-in\nprogress. If you've used gerrit, this would be an offline equivalent\nto the gerrit dashboard.\n- You could choose to share the history of a commit with others, or\ncollaborate on and merge different variants of the same change.\n\nSome information about Mercurial's evolve command can be found here:\nhttps://www.mercurial-scm.org/doc/evolution/\n\nOther similar technologies:\n\nrebase -i can be used to solve the same problem, but you can't easily\nswitch tasks midway through an interactive rebase or have more than\none interactive rebase going on at the same time. It also can't handle\nthe case where you have multiple changes sharing the same parent that\nneeds to be rebased and won't let you collaborate with others on\nresolving a complicated interactive rebase.\n\npatch queues (topgit, stgit, quilt) address a very similar problem,\nhowever since they're built on top of git rather than integrated with\nit, most of them end up managing extra state that can get easily\ndamaged whenever you run a native git command that doesn't know about\nthe patch queue. Most of them also have various workflow problems that\naren't present in hg evolve.\n\nIs anyone else interested in this? Please email me directly or on this\nlist. Let's chat: I want to make sure that whatever we come up with is\nat least as good as any similar technology that has come before.\n"},{"id":"359322","messageId":"xmqqbm8f952b.fsf@gitster-ct.c.googlers.com","threadId":"49458","inReplyTo":"CAPL8ZivFmHqS2y+WmNR6faRMnuahiqwPVYsV99NiJ1QLHOs9fQ@mail.gmail.com","subject":"Re: Git Evolve","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-09-30T00:55:56Z","receivedAt":"2018-09-30T00:57:54Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Stefan Xenos <sxenos@google.com> writes:\n\n> What is the evolve command?\n> ...\n> - Systems like gerrit would no longer need to rely on \"change-id\" tags\n> in commit comments to associate commits with the change that they\n> edit, since git itself would have that information.\n> ...\n> Is anyone else interested in this? Please email me directly or on this\n> list. Let's chat: I want to make sure that whatever we come up with is\n> at least as good as any similar technology that has come before.\n\nAs you listed in the related technologies section, I think the\nunderlying machinery that supports \"rebase -i\", especially with the\nrecent addition of redoing the existing merges (i.e. \"rebase -i\n-r\"), may be enough to rewrite the histories that were built on top\nof a commit that has been obsoleted by amending.\n\nI would imagine that the main design effort you would need to make\nis to figure out a good way to\n\n (1) keep track of which commits are obsoleted by which other ones\n     [*1*], and\n\n (2) to figure out what histories are still to be rebuilt in what\n     order on top of what commit efficiently.\n\nOnce these are done, you should be able to write out the sequence of\ninstructions to feed the same sequencer machinery used by the\n\"rebase -i\" command.\n\n[Side note]\n\n*1* It is very desirable to keep track of the evolution of a change\n    without polluting the commit object with things like Change-Id:\n    and other cruft, either in the body or in the header.  If we\n    lose the Change-Id: footer without adding any new cruft in the\n    commit object header, that would be a great success.  It would\n    be a failure if we end up touching the object header.\n\n\n\n\n"},{"id":"359349","messageId":"CAPL8ZiuzxmgNRE5mVy64xpm_bwbEdkV_X_cAW9B=6LU1T_YF9w@mail.gmail.com","threadId":"49458","inReplyTo":"xmqqbm8f952b.fsf@gitster-ct.c.googlers.com","subject":"Re: Git Evolve","fromName":"Stefan Xenos","fromEmail":"sxenos@google.com","sentAt":"2018-09-30T20:17:59Z","receivedAt":"2018-09-30T20:18:03Z","isPatch":false,"sender":{"key":"sxenos@google.com","avatar":null},"body":"> If we lose the Change-Id: footer without adding any new cruft in the\n> commit object header, that would be a great success.  It would\n> be a failure if we end up touching the object header.\n\nYes, I was thinking along the same lines.\n\nIf obsolescence graph is stored as part of the commit header, it would\nget unconditionally shared whenever that commit is pushed, and I would\nconsider it a desirable property if users could choose whether to push\njust a commit or a the obsolescence graph that contains the commit.\nSometimes the reason you're amending a commit may be because the\noriginal contained content that shouldn't be pushed.\n\nPutting it in the header would also either cause it to get retained\nforever by git gc or create a situation where we permit dangling\nreferences - and neither seem desirable to me. It would be nice if\nusers could retain the obsolescence graph for stuff a user is actively\nworking on, but we could discard it (with 0 cost) for commits they're\ndone with or were never interested in editing.\n\nOn Sat, Sep 29, 2018 at 5:55 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Stefan Xenos <sxenos@google.com> writes:\n>\n>> What is the evolve command?\n>> ...\n>> - Systems like gerrit would no longer need to rely on \"change-id\" tags\n>> in commit comments to associate commits with the change that they\n>> edit, since git itself would have that information.\n>> ...\n>> Is anyone else interested in this? Please email me directly or on this\n>> list. Let's chat: I want to make sure that whatever we come up with is\n>> at least as good as any similar technology that has come before.\n>\n> As you listed in the related technologies section, I think the\n> underlying machinery that supports \"rebase -i\", especially with the\n> recent addition of redoing the existing merges (i.e. \"rebase -i\n> -r\"), may be enough to rewrite the histories that were built on top\n> of a commit that has been obsoleted by amending.\n>\n> I would imagine that the main design effort you would need to make\n> is to figure out a good way to\n>\n>  (1) keep track of which commits are obsoleted by which other ones\n>      [*1*], and\n>\n>  (2) to figure out what histories are still to be rebuilt in what\n>      order on top of what commit efficiently.\n>\n> Once these are done, you should be able to write out the sequence of\n> instructions to feed the same sequencer machinery used by the\n> \"rebase -i\" command.\n>\n> [Side note]\n>\n> *1* It is very desirable to keep track of the evolution of a change\n>     without polluting the commit object with things like Change-Id:\n>     and other cruft, either in the body or in the header.  If we\n>     lose the Change-Id: footer without adding any new cruft in the\n>     commit object header, that would be a great success.  It would\n>     be a failure if we end up touching the object header.\n>\n>\n>\n>\n"},{"id":"359356","messageId":"5539c3ab-9c55-fc9a-6e78-9ab128cc30bc@gmail.com","threadId":"49458","inReplyTo":"CAPL8ZivFmHqS2y+WmNR6faRMnuahiqwPVYsV99NiJ1QLHOs9fQ@mail.gmail.com","subject":"Re: Git Evolve","fromName":"Derrick Stolee","fromEmail":"stolee@gmail.com","sentAt":"2018-10-01T12:37:25Z","receivedAt":"2018-10-01T12:37:30Z","isPatch":false,"sender":{"key":"stolee@gmail.com","avatar":"https://avatars.githubusercontent.com/u/570044?v=4"},"body":"On 9/29/2018 7:00 PM, Stefan Xenos wrote:\n> Hello, List!\n\nHello! Welcome.\n\n> I'm interested in porting something like Mercurial's evolve command to\n> Git. I'll be following up with a formal proposal shortly, but before I\n> do I thought I'd introduce myself to the list and find out if anyone\n> else is interested in this topic.\n\nI'm CC'ing some contributors who have also expressed interest in this topic.\n\n> What is the evolve command?\n\nI'm snipping the rest of your thread because I'm vaguely familiar with \nhow this is used in hg, but I haven't used it myself. Instead, I'm going \nto ask you the same questions I asked the last time I had a conversation \nabout this with someone. In my opinion, these questions should have good \nanswers before we start working on the solution, or else we could paint \nourselves into a corner as we build the first pieces.\n\n---\n\nWhat would the command-line experience look like for this workflow? Be \nspecific, including examples!\n\nHow does one create a commit that obsoletes another? Are we in the \nmiddle of an interactive rebase, or are we simply checking out the \ncommit? How does a use keep track of their progress in a topic?\n\nHow do I view which commits in my topic are obsolete, and to what commits?\n\nIf I want to obsolete commits on one machine and then finish the work on \nanother machine, how do I do that? Similarly: how can I share obsolete \ncommits with other users so they can apply them (or not)?\n\nDo obsolescence markers live in the ref space? (This is one way to help \nanswer the question above.)\n\nCan I make multiple commits obsolete into one commit (merge patches)? \nCan I make my commit obsolete in multiple ways (split a patch)? How is \nthis communicated to the user?\n\n---\n\nIn my opinion, a good way to move forward is to create a patch that adds \na design document to Documentation/technical that answers these \nquestions. Then we can dig in more to make the vision clearer.\n\nI'm not a UX expert, but this seems like a place where we could use \nsomeone with expertise in the area. If we are not careful, we could end \nup with something even harder to use than interactive rebase. The main \ngoal here is to make it easy to rewrite a topic (plus, the ability to do \nso in stages).\n\nI look forward to see what goes on in this space. Count me in to review \nthe technical details.\n\nThanks,\n-Stolee\n"},{"id":"359395","messageId":"20181002012326.GA96979@syl","threadId":"49458","inReplyTo":"CAPL8ZivFmHqS2y+WmNR6faRMnuahiqwPVYsV99NiJ1QLHOs9fQ@mail.gmail.com","subject":"Re: Git Evolve","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2018-10-02T01:23:26Z","receivedAt":"2018-10-02T01:23:35Z","isPatch":false,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"Hi Stefan,\n\nOn Sat, Sep 29, 2018 at 04:00:04PM -0700, Stefan Xenos wrote:\n> Hello, List!\n>\n> I'm interested in porting something like Mercurial's evolve command to\n> Git.\n\nWelcome to Git :-). I think that the discussion in this thread is good,\nbut it's not why I'm replying. I have also wanted a Mercurial feature in\nGit, but a different one than yours.\n\nSpecifically, I've wanted the 'hg absorb' command. My understanding of\nthe commands functionality is that it builds a sort of flamegraph-esque\nview of the blame, and then cascades downwards parts of a change. I am\nsure that I'm not doing the command justice, so I'll defer to [1] where\nit is explained in more detail.\n\nThe benefit of this command is that it gives you a way to--without\nambiguity--absorb changes into earlier commits, and in fact, the\nearliest commit that they make sense to belong to.\n\nThis would simplify my workflow greatly when re-rolling patches, as I\noften want to rewrite a part of an earlier commit. This is certainly\npossible by a number of different `git rebase` invocations (e.g., (1)\ncreate fixup commits, and then re-order them, or (2) mark points in your\nhistory as 'edit', and rewrite them in a detached state, and I'm sure\nmany more).\n\nI'm curious if you or anyone else has thought about how this might work\nin Git.\n\nThanks,\nTaylor\n\n[1]: http://files.lihdd.net/hgabsorb-note.pdf\n"},{"id":"359408","messageId":"877ej0iuhc.fsf@evledraar.gmail.com","threadId":"49458","inReplyTo":"20181002012326.GA96979@syl","subject":"Re: Git Evolve","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2018-10-02T09:11:11Z","receivedAt":"2018-10-02T09:11:17Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Oct 02 2018, Taylor Blau wrote:\n\n> Hi Stefan,\n>\n> On Sat, Sep 29, 2018 at 04:00:04PM -0700, Stefan Xenos wrote:\n>> Hello, List!\n>>\n>> I'm interested in porting something like Mercurial's evolve command to\n>> Git.\n>\n> Welcome to Git :-). I think that the discussion in this thread is good,\n> but it's not why I'm replying. I have also wanted a Mercurial feature in\n> Git, but a different one than yours.\n>\n> Specifically, I've wanted the 'hg absorb' command. My understanding of\n> the commands functionality is that it builds a sort of flamegraph-esque\n> view of the blame, and then cascades downwards parts of a change. I am\n> sure that I'm not doing the command justice, so I'll defer to [1] where\n> it is explained in more detail.\n>\n> The benefit of this command is that it gives you a way to--without\n> ambiguity--absorb changes into earlier commits, and in fact, the\n> earliest commit that they make sense to belong to.\n>\n> This would simplify my workflow greatly when re-rolling patches, as I\n> often want to rewrite a part of an earlier commit. This is certainly\n> possible by a number of different `git rebase` invocations (e.g., (1)\n> create fixup commits, and then re-order them, or (2) mark points in your\n> history as 'edit', and rewrite them in a detached state, and I'm sure\n> many more).\n>\n> I'm curious if you or anyone else has thought about how this might work\n> in Git.\n\nI've wanted a \"git absorb\" for a while, but have done no actual work on\nit, I just found out about it.\n\nI think a combination of these two heuristics would probably do the\ntrick:\n\n 1. If a change in your \"git diff\" output has a hunk whose lines overlap\n    with an earlier commit in the @{u}.. range, we do the equivalent of\n    \"git add -p\", select that hunk, and \"git commit --fixup <that\n    commit>\". We fixup the most recent commit that matches (otherwise\n    commit>we'd conflict).\n\n 2. Have some mode where we fall back from #1 and consider changes to\n    entire files, if that's unambiguous.\n\nThe neat thing about this would be that you could tweak how promiscuous\n#1 would be via the -U option to git-diff, and #2 would just be a\nspecial case of -U9999999999999 (we should really add a -Uinf...).\n\nThen once you ran this you could run \"git rebase -i --autosquash\" to see\nhow the TODO list would look, and optionally have some \"git absorb\n--now\" or whatever to do the \"git add -p\", \"git commit --fixup\" and \"git\nrebase --autosquash\" all in one go.\n\n> [1]: http://files.lihdd.net/hgabsorb-note.pdf\n"},{"id":"359453","messageId":"CAPL8ZiupaJ0ZoyUzgFWm9cV5QypXXUi6wZkmbOf8OGXJa0ZJQA@mail.gmail.com","threadId":"49458","inReplyTo":"877ej0iuhc.fsf@evledraar.gmail.com","subject":"Re: Git Evolve","fromName":"Stefan Xenos","fromEmail":"sxenos@google.com","sentAt":"2018-10-02T19:35:40Z","receivedAt":"2018-10-02T19:35:44Z","isPatch":false,"sender":{"key":"sxenos@google.com","avatar":null},"body":"If you're curious how the Mercurial absorb command works, here's the code:\n\nhttps://www.mercurial-scm.org/repo/hg/file/tip/hgext/absorb.py\n\nIt's GPL 2:\n\nhttps://www.mercurial-scm.org/repo/hg/file/tip/COPYING\n\n\n\nOn Tue, Oct 2, 2018 at 2:11 AM, Ævar Arnfjörð Bjarmason\n<avarab@gmail.com> wrote:\n>\n> On Tue, Oct 02 2018, Taylor Blau wrote:\n>\n>> Hi Stefan,\n>>\n>> On Sat, Sep 29, 2018 at 04:00:04PM -0700, Stefan Xenos wrote:\n>>> Hello, List!\n>>>\n>>> I'm interested in porting something like Mercurial's evolve command to\n>>> Git.\n>>\n>> Welcome to Git :-). I think that the discussion in this thread is good,\n>> but it's not why I'm replying. I have also wanted a Mercurial feature in\n>> Git, but a different one than yours.\n>>\n>> Specifically, I've wanted the 'hg absorb' command. My understanding of\n>> the commands functionality is that it builds a sort of flamegraph-esque\n>> view of the blame, and then cascades downwards parts of a change. I am\n>> sure that I'm not doing the command justice, so I'll defer to [1] where\n>> it is explained in more detail.\n>>\n>> The benefit of this command is that it gives you a way to--without\n>> ambiguity--absorb changes into earlier commits, and in fact, the\n>> earliest commit that they make sense to belong to.\n>>\n>> This would simplify my workflow greatly when re-rolling patches, as I\n>> often want to rewrite a part of an earlier commit. This is certainly\n>> possible by a number of different `git rebase` invocations (e.g., (1)\n>> create fixup commits, and then re-order them, or (2) mark points in your\n>> history as 'edit', and rewrite them in a detached state, and I'm sure\n>> many more).\n>>\n>> I'm curious if you or anyone else has thought about how this might work\n>> in Git.\n>\n> I've wanted a \"git absorb\" for a while, but have done no actual work on\n> it, I just found out about it.\n>\n> I think a combination of these two heuristics would probably do the\n> trick:\n>\n>  1. If a change in your \"git diff\" output has a hunk whose lines overlap\n>     with an earlier commit in the @{u}.. range, we do the equivalent of\n>     \"git add -p\", select that hunk, and \"git commit --fixup <that\n>     commit>\". We fixup the most recent commit that matches (otherwise\n>     commit>we'd conflict).\n>\n>  2. Have some mode where we fall back from #1 and consider changes to\n>     entire files, if that's unambiguous.\n>\n> The neat thing about this would be that you could tweak how promiscuous\n> #1 would be via the -U option to git-diff, and #2 would just be a\n> special case of -U9999999999999 (we should really add a -Uinf...).\n>\n> Then once you ran this you could run \"git rebase -i --autosquash\" to see\n> how the TODO list would look, and optionally have some \"git absorb\n> --now\" or whatever to do the \"git add -p\", \"git commit --fixup\" and \"git\n> rebase --autosquash\" all in one go.\n>\n>> [1]: http://files.lihdd.net/hgabsorb-note.pdf\n"},{"id":"359477","messageId":"87r2h8c7f3.fsf@kyleam.com","threadId":"49458","inReplyTo":"877ej0iuhc.fsf@evledraar.gmail.com","subject":"Re: Git Evolve","fromName":"Kyle Meyer","fromEmail":"kyle@kyleam.com","sentAt":"2018-10-02T22:25:52Z","receivedAt":"2018-10-02T22:32:31Z","isPatch":false,"sender":{"key":"kyle@kyleam.com","avatar":"https://avatars.githubusercontent.com/u/1297788?v=4"},"body":"Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n\n> On Tue, Oct 02 2018, Taylor Blau wrote:\n\n[...]\n\n>> Specifically, I've wanted the 'hg absorb' command. My understanding of\n>> the commands functionality is that it builds a sort of flamegraph-esque\n>> view of the blame, and then cascades downwards parts of a change. I am\n>> sure that I'm not doing the command justice, so I'll defer to [1] where\n>> it is explained in more detail.\n>>\n>> The benefit of this command is that it gives you a way to--without\n>> ambiguity--absorb changes into earlier commits, and in fact, the\n>> earliest commit that they make sense to belong to.\n>>\n>> This would simplify my workflow greatly when re-rolling patches, as I\n>> often want to rewrite a part of an earlier commit. This is certainly\n>> possible by a number of different `git rebase` invocations (e.g., (1)\n>> create fixup commits, and then re-order them, or (2) mark points in your\n>> history as 'edit', and rewrite them in a detached state, and I'm sure\n>> many more).\n>>\n>> I'm curious if you or anyone else has thought about how this might work\n>> in Git.\n>\n> I've wanted a \"git absorb\" for a while, but have done no actual work on\n> it, I just found out about it.\n\nIt may be worth looking into git-autofixup [0] (author cc'd).  I learned\nabout it when Magit used it in its magit-commit-absorb command, but I\nhaven't used it yet myself.\n\n[0] https://github.com/torbiak/git-autofixup\n\n-- \nKyle\n"},{"id":"359483","messageId":"20181002230948.GB18063@syl","threadId":"49458","inReplyTo":"877ej0iuhc.fsf@evledraar.gmail.com","subject":"Re: Git Evolve","fromName":"Taylor Blau","fromEmail":"me@ttaylorr.com","sentAt":"2018-10-02T23:09:48Z","receivedAt":"2018-10-02T23:09:54Z","isPatch":false,"sender":{"key":"me@ttaylorr.com","avatar":"https://avatars.githubusercontent.com/u/301000140?v=4"},"body":"On Tue, Oct 02, 2018 at 11:11:11AM +0200, Ævar Arnfjörð Bjarmason wrote:\n\nYou timed this email quite well ;-).\n\n> On Tue, Oct 02 2018, Taylor Blau wrote:\n>\n> > Hi Stefan,\n> >\n> > On Sat, Sep 29, 2018 at 04:00:04PM -0700, Stefan Xenos wrote:\n> >> Hello, List!\n> >>\n> >> I'm interested in porting something like Mercurial's evolve command to\n> >> Git.\n> >\n> > Welcome to Git :-). I think that the discussion in this thread is good,\n> > but it's not why I'm replying. I have also wanted a Mercurial feature in\n> > Git, but a different one than yours.\n> >\n> > Specifically, I've wanted the 'hg absorb' command. My understanding of\n> > the commands functionality is that it builds a sort of flamegraph-esque\n> > view of the blame, and then cascades downwards parts of a change. I am\n> > sure that I'm not doing the command justice, so I'll defer to [1] where\n> > it is explained in more detail.\n> >\n> > The benefit of this command is that it gives you a way to--without\n> > ambiguity--absorb changes into earlier commits, and in fact, the\n> > earliest commit that they make sense to belong to.\n> >\n> > This would simplify my workflow greatly when re-rolling patches, as I\n> > often want to rewrite a part of an earlier commit. This is certainly\n> > possible by a number of different `git rebase` invocations (e.g., (1)\n> > create fixup commits, and then re-order them, or (2) mark points in your\n> > history as 'edit', and rewrite them in a detached state, and I'm sure\n> > many more).\n> >\n> > I'm curious if you or anyone else has thought about how this might work\n> > in Git.\n>\n> I've wanted a \"git absorb\" for a while, but have done no actual work on\n> it, I just found out about it.\n>\n> I think a combination of these two heuristics would probably do the\n> trick:\n>\n>  1. If a change in your \"git diff\" output has a hunk whose lines overlap\n>     with an earlier commit in the @{u}.. range, we do the equivalent of\n>     \"git add -p\", select that hunk, and \"git commit --fixup <that\n>     commit>\". We fixup the most recent commit that matches (otherwise\n>     commit>we'd conflict).\n\nI had imagined this working slightly differently. I think about it in\nterms of a flamegraph-shape, where each line is affected by gravity.\nConsider this:\n\n       [---------------]\n  L0   L1   L2   L3   L4   L5   L6   L7\n\nHere's a line in a diff that affects L1-L4. Were we to create a\n``fixup'' to L3-L4, it would look like this:\n\n                 [-----] --|\n       [---------|-----] <-|\n  L0   L1   L2   L3   L4   L5   L6   L7\n\nThe commit owning the adjacent edit hunk is the one that gets the\nchanges applied to it.\n\nConsider instead the case where we have two overlapping parts of a\nchange:\n\n                 [-----|----]\n       [---------|-----]\n  L0   L1   L2   L3   L4   L5   L6   L7\n\nThe left-hand side of the top-most hunk belongs to the hunk below it,\nbut the right-hand side is ``affected by gravity'' down to the base:\n\n                 [-----|\n       [---------|-----]|---]\n  L0   L1   L2   L3   L4   L5   L6   L7\n\nAnd thus could be reapplied anywhere. I have not spent time proving this,\nbut I believe that this resolves appropriate bases without ambiguity\n(or, at least can detect when finding a base introduces ambiguity).\n\n>  2. Have some mode where we fall back from #1 and consider changes to\n>     entire files, if that's unambiguous.\n>\n> The neat thing about this would be that you could tweak how promiscuous\n> #1 would be via the -U option to git-diff, and #2 would just be a\n> special case of -U9999999999999 (we should really add a -Uinf...).\n>\n> Then once you ran this you could run \"git rebase -i --autosquash\" to see\n> how the TODO list would look, and optionally have some \"git absorb\n> --now\" or whatever to do the \"git add -p\", \"git commit --fixup\" and \"git\n> rebase --autosquash\" all in one go.\n\nThat's cool. I hadn't known about '--autosquash' before, but it now\nmakes sense to me why I have often seen patches that begin with\n\"fixup!\".\n\nAnother thought that I am reminded of was an off-list discussion with\nPeff, where we thought that a particularly Git-like way to implement\nsomething like this would be to generate a set of commits that would be\nimmediately '--autosquash'-able.\n\n> > [1]: http://files.lihdd.net/hgabsorb-note.pdf\n\nThanks,\nTaylor\n"},{"id":"359629","messageId":"86d0spzoi1.fsf@gmail.com","threadId":"49458","inReplyTo":"xmqqbm8f952b.fsf@gitster-ct.c.googlers.com","subject":"Re: Git Evolve","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2018-10-04T16:05:10Z","receivedAt":"2018-10-04T16:05:20Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n> Stefan Xenos <sxenos@google.com> writes:\n>\n>> What is the evolve command?\n>> ...\n>> - Systems like gerrit would no longer need to rely on \"change-id\" tags\n>> in commit comments to associate commits with the change that they\n>> edit, since git itself would have that information.\n>> ...\n>> Is anyone else interested in this? Please email me directly or on this\n>> list. Let's chat: I want to make sure that whatever we come up with is\n>> at least as good as any similar technology that has come before.\n>\n> As you listed in the related technologies section, I think the\n> underlying machinery that supports \"rebase -i\", especially with the\n> recent addition of redoing the existing merges (i.e. \"rebase -i\n> -r\"), may be enough to rewrite the histories that were built on top\n> of a commit that has been obsoleted by amending.\n>\n> I would imagine that the main design effort you would need to make\n> is to figure out a good way to\n>\n>  (1) keep track of which commits are obsoleted by which other ones\n>      [*1*], and\n>\n>  (2) to figure out what histories are still to be rebuilt in what\n>      order on top of what commit efficiently.\n>\n> Once these are done, you should be able to write out the sequence of\n> instructions to feed the same sequencer machinery used by the\n> \"rebase -i\" command.\n\nWell, that assumes that \"rebase -i\" can correctly recreate merges, if\nneeded.\n\n> [Side note]\n>\n> *1* It is very desirable to keep track of the evolution of a change\n>     without polluting the commit object with things like Change-Id:\n>     and other cruft, either in the body or in the header.  If we\n>     lose the Change-Id: footer without adding any new cruft in the\n>     commit object header, that would be a great success.  It would\n>     be a failure if we end up touching the object header.\n\nDoesn't Gerrit use git-notes instead of 'Change-Id:' trailer nowadays?\nNotes transport is quite easily controlled; the problem with notes merge\ndoes not matter for this use.\n\nBest,\n--\nJakub Narębski\n"},{"id":"359631","messageId":"CAPL8ZitYycD=zZc9yK2ZWn6xSP2rtyviQnOYPFhBpsvQQHe09w@mail.gmail.com","threadId":"49458","inReplyTo":"86d0spzoi1.fsf@gmail.com","subject":"Re: Git Evolve","fromName":"Stefan Xenos","fromEmail":"sxenos@google.com","sentAt":"2018-10-04T17:29:11Z","receivedAt":"2018-10-04T17:29:17Z","isPatch":false,"sender":{"key":"sxenos@google.com","avatar":null},"body":"Gerrit uses notes and branches of meta-commits internally for its\ndatabase, but it still uses the change-id footers to associate an\nuploaded commit with a change within its database.\n\nOn Thu, Oct 4, 2018 at 9:05 AM, Jakub Narebski <jnareb@gmail.com> wrote:\n> Junio C Hamano <gitster@pobox.com> writes:\n>> Stefan Xenos <sxenos@google.com> writes:\n>>\n>>> What is the evolve command?\n>>> ...\n>>> - Systems like gerrit would no longer need to rely on \"change-id\" tags\n>>> in commit comments to associate commits with the change that they\n>>> edit, since git itself would have that information.\n>>> ...\n>>> Is anyone else interested in this? Please email me directly or on this\n>>> list. Let's chat: I want to make sure that whatever we come up with is\n>>> at least as good as any similar technology that has come before.\n>>\n>> As you listed in the related technologies section, I think the\n>> underlying machinery that supports \"rebase -i\", especially with the\n>> recent addition of redoing the existing merges (i.e. \"rebase -i\n>> -r\"), may be enough to rewrite the histories that were built on top\n>> of a commit that has been obsoleted by amending.\n>>\n>> I would imagine that the main design effort you would need to make\n>> is to figure out a good way to\n>>\n>>  (1) keep track of which commits are obsoleted by which other ones\n>>      [*1*], and\n>>\n>>  (2) to figure out what histories are still to be rebuilt in what\n>>      order on top of what commit efficiently.\n>>\n>> Once these are done, you should be able to write out the sequence of\n>> instructions to feed the same sequencer machinery used by the\n>> \"rebase -i\" command.\n>\n> Well, that assumes that \"rebase -i\" can correctly recreate merges, if\n> needed.\n>\n>> [Side note]\n>>\n>> *1* It is very desirable to keep track of the evolution of a change\n>>     without polluting the commit object with things like Change-Id:\n>>     and other cruft, either in the body or in the header.  If we\n>>     lose the Change-Id: footer without adding any new cruft in the\n>>     commit object header, that would be a great success.  It would\n>>     be a failure if we end up touching the object header.\n>\n> Doesn't Gerrit use git-notes instead of 'Change-Id:' trailer nowadays?\n> Notes transport is quite easily controlled; the problem with notes merge\n> does not matter for this use.\n>\n> Best,\n> --\n> Jakub Narębski\n"},{"id":"362133","messageId":"CAPL8ZitjHCT=28K0Yuc4UhhvU8ut33k2vedHWMetJBzMd-D4tw@mail.gmail.com","threadId":"49458","inReplyTo":"5539c3ab-9c55-fc9a-6e78-9ab128cc30bc@gmail.com","subject":"Re: Git Evolve","fromName":"Stefan Xenos","fromEmail":"sxenos@google.com","sentAt":"2018-10-31T21:12:27Z","receivedAt":"2018-10-31T21:12:32Z","isPatch":false,"sender":{"key":"sxenos@google.com","avatar":null},"body":"Sorry it's taken awhile for me to get back to this thread. I've been\nkeeping my open source contributions timeboxed, and had to work\nthrough a bit of a backlog before this email thread got back to the\nfront of the queue.\n\n> What would the command-line experience look like for this workflow? Be specific, including examples!\n\nYes, I agree that's critical. I'm not going to try to improvise an\nanswer over email, but I will be sure to include such examples when I\nsubmit the patch to Documentation/technical, after some careful\nthought.\n\n> How does one create a commit that obsoletes another?\n\nI was planning to classify all git commands that create commits as\neither \"modifications\" or \"clones\". Modification commands (such as\nrebase or commit --amend) would automatically obsolete their\npredecessors. Clone commands (such as cherry-pick) would create copies\nwithout obsoleting the original.\n\n> Are we in the middle of an interactive rebase, or are we simply checking out the commit?\n\nTo obsolete a commit, you'd just check it out and amend. You really\nwouldn't want to have to do anything extra or put yourself in a\nspecial mode to mark things as obsolete or they wouldn't be much of a\nconvenience. However, if you were to run the \"evolve\" command (the\nthing that reads the obsolescence markers) and it encountered errors,\nyou'd be in the middle of something very much like an interactive\nrebase.\n\n> How does a use keep track of their progress in a topic?\n> How do I view which commits in my topic are obsolete, and to what commits?\n> Do obsolescence markers live in the ref space? (This is one way to help answer the question above.)\n\nThe answers to these questions are more complicated. I'll be sure to\naddress them in the technical proposal, but I wouldn't want create a\nmisunderstanding with an incomplete explanation.\n\n> Can I make multiple commits obsolete into one commit (merge patches)? Can I make my commit obsolete in multiple ways (split a patch)? How is this communicated to the user?\n\nYes and yes. When a single commit is obsoleted by one or more\nnon-obsolete commits, this is called divergence and it needs to be\nresolved by the user (the evolve command will stop when it encounters\ndivergence, much like a rebase will stop when it encounters a merge\nconflict). Possible resolutions are to discard one of the two\nnon-obsolete commits by marking them as obsolete, merge the two, or\nkeep both by cloning one of them and marking it as no longer\nobsoleting its predecessor.\n\nUnnecessary divergence isn't a good thing since it requires user\nintervention to resolve. Splitting a patch doesn't need to create\ndivergence (and probably shouldn't). If you split a commit, the\nearlier one would be a completely new commit and the latter one would\nobsolete the original. Doing it the other way around creates a merge\nconflict between the later commit and anything that followed the\noriginal. If both commits obsolete the original, it creates divergence\n- and either divergence or a merge would get the user involved\nunnecessarily.\n\nA more likely scenario where divergence would occur is of two\ndifferent users try to amend the same commit and then share their\nresults -- or if a user amends a commit, resets back to the original,\nand then amends it again.\n\n> Count me in to review the technical details.\n\nWill do!\n\nOn Mon, Oct 1, 2018 at 5:37 AM, Derrick Stolee <stolee@gmail.com> wrote:\n> On 9/29/2018 7:00 PM, Stefan Xenos wrote:\n>>\n>> Hello, List!\n>\n>\n> Hello! Welcome.\n>\n>> I'm interested in porting something like Mercurial's evolve command to\n>> Git. I'll be following up with a formal proposal shortly, but before I\n>> do I thought I'd introduce myself to the list and find out if anyone\n>> else is interested in this topic.\n>\n>\n> I'm CC'ing some contributors who have also expressed interest in this topic.\n>\n>> What is the evolve command?\n>\n>\n> I'm snipping the rest of your thread because I'm vaguely familiar with how\n> this is used in hg, but I haven't used it myself. Instead, I'm going to ask\n> you the same questions I asked the last time I had a conversation about this\n> with someone. In my opinion, these questions should have good answers before\n> we start working on the solution, or else we could paint ourselves into a\n> corner as we build the first pieces.\n>\n> ---\n>\n> What would the command-line experience look like for this workflow? Be\n> specific, including examples!\n>\n> How does one create a commit that obsoletes another? Are we in the middle of\n> an interactive rebase, or are we simply checking out the commit? How does a\n> use keep track of their progress in a topic?\n>\n> How do I view which commits in my topic are obsolete, and to what commits?\n>\n> If I want to obsolete commits on one machine and then finish the work on\n> another machine, how do I do that? Similarly: how can I share obsolete\n> commits with other users so they can apply them (or not)?\n>\n> Do obsolescence markers live in the ref space? (This is one way to help\n> answer the question above.)\n>\n> Can I make multiple commits obsolete into one commit (merge patches)? Can I\n> make my commit obsolete in multiple ways (split a patch)? How is this\n> communicated to the user?\n>\n> ---\n>\n> In my opinion, a good way to move forward is to create a patch that adds a\n> design document to Documentation/technical that answers these questions.\n> Then we can dig in more to make the vision clearer.\n>\n> I'm not a UX expert, but this seems like a place where we could use someone\n> with expertise in the area. If we are not careful, we could end up with\n> something even harder to use than interactive rebase. The main goal here is\n> to make it easy to rewrite a topic (plus, the ability to do so in stages).\n>\n> I look forward to see what goes on in this space. Count me in to review the\n> technical details.\n>\n> Thanks,\n> -Stolee\n"},{"id":"362826","messageId":"nycvar.QRO.7.76.6.1811091357190.39@tvgsbejvaqbjf.bet","threadId":"49458","inReplyTo":"877ej0iuhc.fsf@evledraar.gmail.com","subject":"Re: Git Evolve","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2018-11-09T13:06:20Z","receivedAt":"2018-11-09T13:06:26Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 2 Oct 2018, Ævar Arnfjörð Bjarmason wrote:\n\n> On Tue, Oct 02 2018, Taylor Blau wrote:\n> \n> > Hi Stefan,\n> >\n> > On Sat, Sep 29, 2018 at 04:00:04PM -0700, Stefan Xenos wrote:\n> >> Hello, List!\n> >>\n> >> I'm interested in porting something like Mercurial's evolve command to\n> >> Git.\n> >\n> > Welcome to Git :-). I think that the discussion in this thread is good,\n> > but it's not why I'm replying. I have also wanted a Mercurial feature in\n> > Git, but a different one than yours.\n> >\n> > Specifically, I've wanted the 'hg absorb' command. My understanding of\n> > the commands functionality is that it builds a sort of flamegraph-esque\n> > view of the blame, and then cascades downwards parts of a change. I am\n> > sure that I'm not doing the command justice, so I'll defer to [1] where\n> > it is explained in more detail.\n> >\n> > The benefit of this command is that it gives you a way to--without\n> > ambiguity--absorb changes into earlier commits, and in fact, the\n> > earliest commit that they make sense to belong to.\n> >\n> > This would simplify my workflow greatly when re-rolling patches, as I\n> > often want to rewrite a part of an earlier commit. This is certainly\n> > possible by a number of different `git rebase` invocations (e.g., (1)\n> > create fixup commits, and then re-order them, or (2) mark points in your\n> > history as 'edit', and rewrite them in a detached state, and I'm sure\n> > many more).\n> >\n> > I'm curious if you or anyone else has thought about how this might work\n> > in Git.\n> \n> I've wanted a \"git absorb\" for a while, but have done no actual work on\n> it, I just found out about it.\n> \n> I think a combination of these two heuristics would probably do the\n> trick:\n> \n>  1. If a change in your \"git diff\" output has a hunk whose lines overlap\n>     with an earlier commit in the @{u}.. range, we do the equivalent of\n>     \"git add -p\", select that hunk, and \"git commit --fixup <that\n>     commit>\". We fixup the most recent commit that matches (otherwise\n>     commit>we'd conflict).\n> \n>  2. Have some mode where we fall back from #1 and consider changes to\n>     entire files, if that's unambiguous.\n> \n> The neat thing about this would be that you could tweak how promiscuous\n> #1 would be via the -U option to git-diff, and #2 would just be a\n> special case of -U9999999999999 (we should really add a -Uinf...).\n> \n> Then once you ran this you could run \"git rebase -i --autosquash\" to see\n> how the TODO list would look, and optionally have some \"git absorb\n> --now\" or whatever to do the \"git add -p\", \"git commit --fixup\" and \"git\n> rebase --autosquash\" all in one go.\n\nThis is essentially what the script does that I sent to this here mailing\nlist back in May:\nhttps://public-inbox.org/git/nycvar.QRO.7.76.6.1805052220360.77@tvgsbejvaqbjf.bet/\n\nI used this quite a lot, but I still find it slow (especially on Windows),\nso I am still in search for a better solution. And yes, I was intrigued by\n`hg absorb` when it was presented at GitMerge last year, and wanted to\nhave the same.\n\nIn the meantime, what I often do is to call `git log -L <range>:<file>`\nwhere <range> and <file> are taken from the hunk(s) of the current diff.\nActually, I have a script to do that, hidden behind a Git alias. Then I\ninspect the diffs in that log and call `git commit --fixup` with the one I\ndeem most appropriate.\n\nNote that it sometimes fails because of semantic dependencies. That is,\neven if my current change overlaps with an earlier change, it may be too\nearly to be squashed in.\n\nAs an example: imagine that I moved a git_config() call from some function\ninto the cmd_<command>() function. Only: I intended to move it, but in\nfact, I just added the call to the latter function. Eventually, I figure\nit out! So I want to make a fixup! commit. My script, as well as Ævar's\nsuggestion, as well as literally all the other attempts to solve this that\nI am aware of, would try to squash this change into whichever commit\nintroduced the function that originally called git_config(). But that is\nwrong. It should be squashed into the commit that added the git_config()\ncall to the cmd_<command>() function.\n\nCiao,\nDscho\n\n> \n> > [1]: http://files.lihdd.net/hgabsorb-note.pdf\n> "}]}