RFC - "git editlog" feature for fixing up local commit messages

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I'm quite prone to typos in my commit comments - sufficiently so that
that when I was using Subversion for GPSD I wrote a script to ssh to
the repo server and edit the comment property of a specified revision.
That way, when I noticed a typo in the output of SVN log, I could fix it.

I don't have that liberty in the DVCS world of chained commit hashes, unless
the commit is only local and hasn't been pushed.  But that exception 
is important.  Since switching GPSD to git, I've developed a workflow
that looks like this: 

(1) I develop, test, and commit a bunch of changes.

(2) Before pushing them to rigin, I eyeball the git log.

(3) If I spot typos in past revisions, I fix them locally.

(4) Only then do I push upstream.

Now, about step 3.  The official git command set only directly supports
amending the tip commit.  There is a semi-documented procedure for 
amending previous commits using an interactive rebase, but trying to
understand it makes my brain hurt.  Don't want to go there.

Instead, following a suggestion by thiago on #git, I've written a
script I call editcomment (enclosed).  It takes a revision spec as
argument, then checks to see if that ref has any remote references; it
it does, the script warns the user that he will discombobulate the
order of the universe if he continues and requests confrmation.

If the commit is local only, or the user confirms he want to shoot
self in foot, the script then runs a filter-branch operation using a
filter that no-ops all other commits through but fires up an editor on the
contents of the matching one as presented on stdin, writing the
modified version to stdout on editor exit.

The overall effect is the commit comment gets edited and all hashes
there and afterwards change, but if they were all local that's OK.
I don't have to think about rebases or amends or reverts, and that;s
exactly the way I want it.  When I need to edit a comment, *I desire 
the luxury of ignorance about how it's done*.

My editcomment script, as it exists, has a technical problem...the
editor needs to be something like emacsclient that actually invokes in
a different X window, otherwise whatever it writes to stdout will end
up stuffed in the comment along with the text I actually wanted to put
there.  The underlying problem is that git-filter-branch is sort of a
nuclear-powered chainsaw - gets the job done, but in a way that is
prone to messy side effects.  A more elegant implementation would
probably need to tie deeper into the plumbing.

Here's what I think any git user should be able to do: call "git editlog
<commit>" and have it either

(1) refuse with an error message because the commit has remote references
    and the user didn't specify -f, or

(2) fire up an editor of the user's choice, accepting the edited result as
    a replacement for the commit comment. It should no-op if the
    comment is not changed.

For my own purposes, my editcomment script would be good enough, since 
I never really want to be able to use anything but emacsclient anyway --
vi not working is at best a very minor inconvenience for me.  

But I'm advocating for this feature to be in git anyway, because I
think it addresses a common need for which the existing interface is
needlessly painful and difficult to understand. In the local case, I
think this is not an operation that should require the user to care
that DAG surgery is implied.  git would be better art if users could
ignore that.

Accordingly, I want to open a discussion on this...

* Do others agree that git editlog would be a desirable feature?

* Supposing it is, what would be the best way to implement it?

* Are there issues with this proposal that I haven't noticed?
-- 
		<a href="http://www.catb.org/~esr/";>Eric S. Raymond</a>
#!/bin/sh
# Give this a commit-ID specification.  It will edit the associated comment.
# Usual caveats apply; the edited one and all commits after will change IDs,
# and pushing them to a repo with the old commits will wreak havoc.
# Note also that this cavalierly overwrites refs/original.
#
# This script by Eric S. Raymond, March 2010, all rites perverted.
# It's based on an idea by thiago from #git, but debugged and with a safety.
# It contains porcelain and porcelain byproducts.

topdir=`git rev-parse --show-cdup`
test -n "$topdir" && cd "$topdir"

my_commit=`git rev-parse $1` || exit $?

# Run a safety check before edits that could hose remotes.
if test -n "`git branch -r --contains $mycommit`"
then
    echo -n "Commit has been pushed.  Really edit? "
    read yn
    if test "$yn" != 'y'
    then
	exit 0
    fi
fi

my_file=COMMIT_EDITMSG
test -d .git && myfile=.git/COMMIT_EDITMSG

# This effort to invoke the user's normal editor fails.
# the problem is that anything the editor writes to stdout on the
# controlling terminal becomes part of the commit message.  So
# the editor needs to actually run inside another window.
#test -z "$GIT_EDITOR" && GIT_EDITOR=$EDITOR
#test -z "$GIT_EDITOR" && GIT_EDITOR=vi
#my_editor=$GIT_EDITOR

# xterm -e vi should also work.
my_editor=emacsclient

export my_file my_commit my_editor

exec git filter-branch -f --msg-filter '
if test "$GIT_COMMIT" = "$my_commit"; then
    cat > $my_file;
    $my_editor $my_file >/dev/null;
    cat $my_file
else
    cat
fi' "$1~.."

# End

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]