{"thread":{"id":"23231","subject":"RFC - \"git editlog\" feature for fixing up local commit messages","startedAt":"2010-03-29T13:31:32Z","lastAt":"2010-03-30T23:11:14Z","messageCount":8,"participants":["Eric Raymond","Sverre Rabbelier","Nicolas Pitre","Avery Pennarun","Miles Bader","Michael J Gruber","Jonathan Nieder"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"138085","messageId":"20100329133132.GA12201@thyrsus.com","threadId":"23231","inReplyTo":null,"subject":"RFC - \"git editlog\" feature for fixing up local commit messages","fromName":"Eric Raymond","fromEmail":"esr@thyrsus.com","sentAt":"2010-03-29T13:31:32Z","receivedAt":"2010-03-29T13:31:32Z","isPatch":false,"sender":{"key":"esr@thyrsus.com","avatar":"https://avatars.githubusercontent.com/u/727961?v=4"},"body":"I'm quite prone to typos in my commit comments - sufficiently so that\nthat when I was using Subversion for GPSD I wrote a script to ssh to\nthe repo server and edit the comment property of a specified revision.\nThat way, when I noticed a typo in the output of SVN log, I could fix it.\n\nI don't have that liberty in the DVCS world of chained commit hashes, unless\nthe commit is only local and hasn't been pushed.  But that exception \nis important.  Since switching GPSD to git, I've developed a workflow\nthat looks like this: \n\n(1) I develop, test, and commit a bunch of changes.\n\n(2) Before pushing them to rigin, I eyeball the git log.\n\n(3) If I spot typos in past revisions, I fix them locally.\n\n(4) Only then do I push upstream.\n\nNow, about step 3.  The official git command set only directly supports\namending the tip commit.  There is a semi-documented procedure for \namending previous commits using an interactive rebase, but trying to\nunderstand it makes my brain hurt.  Don't want to go there.\n\nInstead, following a suggestion by thiago on #git, I've written a\nscript I call editcomment (enclosed).  It takes a revision spec as\nargument, then checks to see if that ref has any remote references; it\nit does, the script warns the user that he will discombobulate the\norder of the universe if he continues and requests confrmation.\n\nIf the commit is local only, or the user confirms he want to shoot\nself in foot, the script then runs a filter-branch operation using a\nfilter that no-ops all other commits through but fires up an editor on the\ncontents of the matching one as presented on stdin, writing the\nmodified version to stdout on editor exit.\n\nThe overall effect is the commit comment gets edited and all hashes\nthere and afterwards change, but if they were all local that's OK.\nI don't have to think about rebases or amends or reverts, and that;s\nexactly the way I want it.  When I need to edit a comment, *I desire \nthe luxury of ignorance about how it's done*.\n\nMy editcomment script, as it exists, has a technical problem...the\neditor needs to be something like emacsclient that actually invokes in\na different X window, otherwise whatever it writes to stdout will end\nup stuffed in the comment along with the text I actually wanted to put\nthere.  The underlying problem is that git-filter-branch is sort of a\nnuclear-powered chainsaw - gets the job done, but in a way that is\nprone to messy side effects.  A more elegant implementation would\nprobably need to tie deeper into the plumbing.\n\nHere's what I think any git user should be able to do: call \"git editlog\n<commit>\" and have it either\n\n(1) refuse with an error message because the commit has remote references\n    and the user didn't specify -f, or\n\n(2) fire up an editor of the user's choice, accepting the edited result as\n    a replacement for the commit comment. It should no-op if the\n    comment is not changed.\n\nFor my own purposes, my editcomment script would be good enough, since \nI never really want to be able to use anything but emacsclient anyway --\nvi not working is at best a very minor inconvenience for me.  \n\nBut I'm advocating for this feature to be in git anyway, because I\nthink it addresses a common need for which the existing interface is\nneedlessly painful and difficult to understand. In the local case, I\nthink this is not an operation that should require the user to care\nthat DAG surgery is implied.  git would be better art if users could\nignore that.\n\nAccordingly, I want to open a discussion on this...\n\n* Do others agree that git editlog would be a desirable feature?\n\n* Supposing it is, what would be the best way to implement it?\n\n* Are there issues with this proposal that I haven't noticed?\n-- \n\t\t<a href=\"http://www.catb.org/~esr/\">Eric S. Raymond</a>\n\n\n#!/bin/sh\n# Give this a commit-ID specification.  It will edit the associated comment.\n# Usual caveats apply; the edited one and all commits after will change IDs,\n# and pushing them to a repo with the old commits will wreak havoc.\n# Note also that this cavalierly overwrites refs/original.\n#\n# This script by Eric S. Raymond, March 2010, all rites perverted.\n# It's based on an idea by thiago from #git, but debugged and with a safety.\n# It contains porcelain and porcelain byproducts.\n\ntopdir=`git rev-parse --show-cdup`\ntest -n \"$topdir\" && cd \"$topdir\"\n\nmy_commit=`git rev-parse $1` || exit $?\n\n# Run a safety check before edits that could hose remotes.\nif test -n \"`git branch -r --contains $mycommit`\"\nthen\n    echo -n \"Commit has been pushed.  Really edit? \"\n    read yn\n    if test \"$yn\" != 'y'\n    then\n\texit 0\n    fi\nfi\n\nmy_file=COMMIT_EDITMSG\ntest -d .git && myfile=.git/COMMIT_EDITMSG\n\n# This effort to invoke the user's normal editor fails.\n# the problem is that anything the editor writes to stdout on the\n# controlling terminal becomes part of the commit message.  So\n# the editor needs to actually run inside another window.\n#test -z \"$GIT_EDITOR\" && GIT_EDITOR=$EDITOR\n#test -z \"$GIT_EDITOR\" && GIT_EDITOR=vi\n#my_editor=$GIT_EDITOR\n\n# xterm -e vi should also work.\nmy_editor=emacsclient\n\nexport my_file my_commit my_editor\n\nexec git filter-branch -f --msg-filter '\nif test \"$GIT_COMMIT\" = \"$my_commit\"; then\n    cat > $my_file;\n    $my_editor $my_file >/dev/null;\n    cat $my_file\nelse\n    cat\nfi' \"$1~..\"\n\n# End\n"},{"id":"138087","messageId":"fabb9a1e1003290641s27306373k3a2669318a7b67a8@mail.gmail.com","threadId":"23231","inReplyTo":"20100329133132.GA12201@thyrsus.com","subject":"Re: RFC - \"git editlog\" feature for fixing up local commit messages","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2010-03-29T13:41:13Z","receivedAt":"2010-03-29T13:41:13Z","isPatch":false,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Mon, Mar 29, 2010 at 07:31, Eric Raymond <esr@thyrsus.com> wrote:\n> Now, about step 3.  The official git command set only directly supports\n> amending the tip commit.  There is a semi-documented procedure for\n> amending previous commits using an interactive rebase, but trying to\n> understand it makes my brain hurt.  Don't want to go there.\n\nGo there anyway. These days it's as simple as changing \"pick\" to\n\"reword\" on the appropriate commit. Really, give it a try.\n\n$ git rebase -i origin/master\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"138094","messageId":"alpine.LFD.2.00.1003291102250.694@xanadu.home","threadId":"23231","inReplyTo":"fabb9a1e1003290641s27306373k3a2669318a7b67a8@mail.gmail.com","subject":"Re: RFC - \"git editlog\" feature for fixing up local commit messages","fromName":"Nicolas Pitre","fromEmail":"nico@fluxnic.net","sentAt":"2010-03-29T15:08:21Z","receivedAt":"2010-03-29T15:08:21Z","isPatch":false,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Mon, 29 Mar 2010, Sverre Rabbelier wrote:\n\n> Heya,\n> \n> On Mon, Mar 29, 2010 at 07:31, Eric Raymond <esr@thyrsus.com> wrote:\n> > Now, about step 3.  The official git command set only directly supports\n> > amending the tip commit.  There is a semi-documented procedure for\n> > amending previous commits using an interactive rebase, but trying to\n> > understand it makes my brain hurt.  Don't want to go there.\n> \n> Go there anyway. These days it's as simple as changing \"pick\" to\n> \"reword\" on the appropriate commit. Really, give it a try.\n\nWhile the 'git rebase -i' solution has its place (and I do use it \nmyself), it essentially deals with only one branch while having a \nfilter-branch based solution allows for such changes to be applied \nglobally i.e. to all branches in the presence of history fork points.\n\n\nNicolas\n"},{"id":"138127","messageId":"32541b131003291314r2f5a77e8g28e79b5983821e41@mail.gmail.com","threadId":"23231","inReplyTo":"20100329133132.GA12201@thyrsus.com","subject":"Re: RFC - \"git editlog\" feature for fixing up local commit messages","fromName":"Avery Pennarun","fromEmail":"apenwarr@gmail.com","sentAt":"2010-03-29T20:14:09Z","receivedAt":"2010-03-29T20:14:09Z","isPatch":false,"sender":{"key":"apenwarr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/20592?v=4"},"body":"On Mon, Mar 29, 2010 at 9:31 AM, Eric Raymond <esr@thyrsus.com> wrote:\n> My editcomment script, as it exists, has a technical problem...the\n> editor needs to be something like emacsclient that actually invokes in\n> a different X window, otherwise whatever it writes to stdout will end\n> up stuffed in the comment along with the text I actually wanted to put\n> there.  The underlying problem is that git-filter-branch is sort of a\n> nuclear-powered chainsaw - gets the job done, but in a way that is\n> prone to messy side effects.  A more elegant implementation would\n> probably need to tie deeper into the plumbing.\n\nIt ought to be easy to work around this; simply extract the log\nmessage *before* filter-branch using something like\n\n       git cat-file commit HEAD | tail -n +6 >msg.tmp\n\n(I'm sure someone will correct me by providing a less revolting way to\nextract the commit message, but it's somehow not coming to me right\nnow.)\n\nThen launch $EDITOR to edit the message, then inside the\nfilter-branch, just use that file instead of launching the editor.\n\nAlternatively, in case you want the option of editing *multiple*\ncommit messages at once, you could just redirect stdin/stdout to\n/dev/tty.\n\nA further option would be to extend git-rebase--interactive.sh (yes,\nit's just a shell script) to take an option that makes a given commit\n(or commits) 'reword' by default instead of 'pick'.  And maybe another\noption to make git-rebase--interactive.sh not actually pop up an\neditor before it starts running.  Then your editcommit script could\njust be a thin wrapper around rebase with those options.\n\n<insert obligatory wistful reference to git-sequencer> (I don't\nactually know anything about git-sequencer.)\n\nHave fun,\n\nAvery\n"},{"id":"138161","messageId":"buobpe6bbut.fsf@dhlpc061.dev.necel.com","threadId":"23231","inReplyTo":"20100329133132.GA12201@thyrsus.com","subject":"Re: RFC - \"git editlog\" feature for fixing up local commit messages","fromName":"Miles Bader","fromEmail":"miles@gnu.org","sentAt":"2010-03-30T05:46:34Z","receivedAt":"2010-03-30T05:46:34Z","isPatch":false,"sender":{"key":"miles@gnu.org","avatar":"https://gravatar.com/avatar/01069b69593af7bff28e2f97afeb3644ae6fe2f5f56cb3a8cf34c5fb8c36efe5?d=mp&s=160"},"body":"Eric Raymond <esr@thyrsus.com> writes:\n> There is a semi-documented procedure for amending previous commits\n> using an interactive rebase, but trying to understand it makes my\n> brain hurt.  Don't want to go there.\n\nI'd recommend becoming familiar with rebase -i anyway -- it's just\nplain useful, and really almost trivial to use once you've tried it.\n\nFixing comment typos is simple using the \"r\"/\"reword\" directive, but\nthe ability to rearrange, drop, and merge commits, is also very\nhandy and easy using rebase -i.\n\n-Miles\n\n-- \nIn New York, most people don't have cars, so if you want to kill a person, you\nhave to take the subway to their house.  And sometimes on the way, the train\nis delayed and you get impatient, so you have to kill someone on the subway.\n  [George Carlin]\n"},{"id":"138170","messageId":"4BB1BBDA.2050102@drmicha.warpmail.net","threadId":"23231","inReplyTo":"32541b131003291314r2f5a77e8g28e79b5983821e41@mail.gmail.com","subject":"Re: RFC - \"git editlog\" feature for fixing up local commit messages","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2010-03-30T08:52:42Z","receivedAt":"2010-03-30T08:52:42Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Avery Pennarun venit, vidit, dixit 29.03.2010 22:14:\n> On Mon, Mar 29, 2010 at 9:31 AM, Eric Raymond <esr@thyrsus.com> wrote:\n>> My editcomment script, as it exists, has a technical problem...the\n>> editor needs to be something like emacsclient that actually invokes in\n>> a different X window, otherwise whatever it writes to stdout will end\n>> up stuffed in the comment along with the text I actually wanted to put\n>> there.  The underlying problem is that git-filter-branch is sort of a\n>> nuclear-powered chainsaw - gets the job done, but in a way that is\n>> prone to messy side effects.  A more elegant implementation would\n>> probably need to tie deeper into the plumbing.\n> \n> It ought to be easy to work around this; simply extract the log\n> message *before* filter-branch using something like\n> \n>        git cat-file commit HEAD | tail -n +6 >msg.tmp\n> \n> (I'm sure someone will correct me by providing a less revolting way to\n> extract the commit message, but it's somehow not coming to me right\n> now.)\n> \n> Then launch $EDITOR to edit the message, then inside the\n> filter-branch, just use that file instead of launching the editor.\n> \n> Alternatively, in case you want the option of editing *multiple*\n> commit messages at once, you could just redirect stdin/stdout to\n> /dev/tty.\n> \n> A further option would be to extend git-rebase--interactive.sh (yes,\n> it's just a shell script) to take an option that makes a given commit\n> (or commits) 'reword' by default instead of 'pick'.  And maybe another\n> option to make git-rebase--interactive.sh not actually pop up an\n> editor before it starts running.  Then your editcommit script could\n> just be a thin wrapper around rebase with those options.\n\nI think the OP's point was that filter-branch is better at keeping\nmerges in place; I'm not sure if this is true when rebase-i is used with\nreword only.\n\n> <insert obligatory wistful reference to git-sequencer> (I don't\n> actually know anything about git-sequencer.)\n\nOh yeah:)\n\nMichael\n"},{"id":"138201","messageId":"32541b131003301136h4454f02cyd5a94d746e844a8d@mail.gmail.com","threadId":"23231","inReplyTo":"4BB1BBDA.2050102@drmicha.warpmail.net","subject":"Re: RFC - \"git editlog\" feature for fixing up local commit messages","fromName":"Avery Pennarun","fromEmail":"apenwarr@gmail.com","sentAt":"2010-03-30T18:36:27Z","receivedAt":"2010-03-30T18:36:27Z","isPatch":false,"sender":{"key":"apenwarr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/20592?v=4"},"body":"On Tue, Mar 30, 2010 at 4:52 AM, Michael J Gruber\n<git@drmicha.warpmail.net> wrote:\n> Avery Pennarun venit, vidit, dixit 29.03.2010 22:14:\n>> A further option would be to extend git-rebase--interactive.sh (yes,\n>> it's just a shell script) to take an option that makes a given commit\n>> (or commits) 'reword' by default instead of 'pick'.  And maybe another\n>> option to make git-rebase--interactive.sh not actually pop up an\n>> editor before it starts running.  Then your editcommit script could\n>> just be a thin wrapper around rebase with those options.\n>\n> I think the OP's point was that filter-branch is better at keeping\n> merges in place; I'm not sure if this is true when rebase-i is used with\n> reword only.\n\nI've never actually tried the \"--preserve-merges\" option to git rebase\n-i, but the description sounds as if it's supposed to not have this\nproblem.  Can anyone confirm/deny?\n\nThanks,\n\nAvery\n"},{"id":"138234","messageId":"20100330231114.GA11591@progeny.tock","threadId":"23231","inReplyTo":"32541b131003301136h4454f02cyd5a94d746e844a8d@mail.gmail.com","subject":"Re: RFC - \"git editlog\" feature for fixing up local commit messages","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-03-30T23:11:14Z","receivedAt":"2010-03-30T23:11:14Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Avery Pennarun wrote:\n> On Tue, Mar 30, 2010 at 4:52 AM, Michael J Gruber\n\n>> I think the OP's point was that filter-branch is better at keeping\n>> merges in place; I'm not sure if this is true when rebase-i is used with\n>> reword only.\n>\n> I've never actually tried the \"--preserve-merges\" option to git rebase\n> -i, but the description sounds as if it's supposed to not have this\n> problem.  Can anyone confirm/deny?\n\npreserve-merges is in bad shape.  I’d recommend not using it unless you’re\nwilling to hack on it.\n\nExample issues: interacts poorly with merge.log, reordering commits\nproduces very confusing results.\n\nExample of why it is not necessarily the tool for all seasons: requires a\ndiff+apply cycle.  If you are tracking large or binary files or amending a\nvery old commit message, it makes more sense to avoid this overhead.  See\nhttp://thread.gmane.org/gmane.comp.version-control.git/143426\nfor example.\n\nHope that helps,\nJonathan\n"}]}