From: Marcel M. Cary Date: Wed, 18 Mar 2009 21:02:08 GMT Subject: Re: Ability to edit message from git rebase --interactive. Message-ID: <49C16150.6070001@earth.care2.com> In-Reply-To: <49C10A97.6060201@oak.homeunix.org> Marcel M. Cary wrote: > Michael J Gruber wrote: >> Sverre Rabbelier venit, vidit, dixit 18.03.2009 06:42: >>> Heya, >>> >>> On Wed, Mar 18, 2009 at 02:06, Junio C Hamano wrote: >>>> Jeff King writes: >>>> I am not quite sure what rephrase is buying us. Do we also want to >>>> introduce retree that allows you to muck with the tree object recorded >>>> without giving you a chance to clobber the commit log message? >>> Is that a common operation? Rephrase is, at least to me... >>> >> Rephrase for sure is common, and for sure can be done currently... It's >> only that "commit --amend, save&quit, continue" could be shortened. >> >> OTOH: Most commonly one would want to rephrase a commit message or two >> without actually rebasing anything. And the proposed change doesn't help >> as much as it could, in two respects: >> >> 1) I want to be able to say "rephrase HEAD~2" without having to edit a >> rebase action script. (That would be useful for rewriting a single >> commit as well, and could be added easily.) >> >> 2) Currently, all rebasing operations have trouble with merges. But if >> all I want to do is rephrasing a log message then no diff/apply is >> necessary, no rewriting of trees, no change in the DAG structure (i.e. >> connectivity; sha1s change, of course). So there should be a special >> mode for DAG-preserving rewrites, where one can be sure that merges are >> fully preserved. >> >> 2) seems to be the most important point to make rephrasing safe and >> convenient. > > Interesting points about skipping the action script and preserving > structure. I just tried to do something like that with filter-branch: > > git filter-branch --msg-filter 'cat > tmp; $EDITOR tmp < '$(tty)' > > '$(tty)' 2>&1; cat tmp' ^HEAD^ HEAD > > And discovered that it will neither accept "HEAD^^..HEAD^" nor "HEAD^" > as a shortcut for a rev-list containing a single commit. But if you're > content to save and quit each message through the branch tip and specify > the range, it seems to work. > > I have no idea what it would take to make filter-branch support the > additional kinds of rev and rev list specifications, or if that would be > undesirable. > > I'm assuming it accomplishes (2) because of the nature of filter-branch. Ok, so I guess you have to explicity tell filter-branch all the commits that reach the ones you want to rewrite so it will know to fixup their parents. Below is a rough way of doing that, but sometimes it will find too many commits, and it's rather slow, even on a git.git. git-rephrase: #!/bin/sh if [ -z "$EDITOR" ]; then export EDITOR=vim fi # Does change tags refs=$(git for-each-ref --format='%(refname)' 'refs/heads/*' | while read ref; do # This is the slow part if git rev-list $ref | grep -q $(git rev-parse --verify $1); then echo $ref else echo ^$ref fi; done ) parents=$(git rev-list --max-count=1 --parents $1 | { read hash parents for hash in $parents; do echo ^$hash done }) git filter-branch --msg-filter " if [ \$GIT_COMMIT = $(git rev-parse $1) ]; then cat > tmp \$EDITOR tmp < $(tty) > $(tty) 2>&1 cat tmp else cat fi " $refs $parents