From c6de36b9480f6b9c34a3a3bb5ff224eed3de0301 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 19 Dec 2013 20:39:26 -0600 Subject: [PATCH] shears.sh: introduce 'bud' and 'finish' commands The most common operations during splitting a bunch of commits into neatly-packaged topic branches are: 1) 'finish': name a branch & mark it for merging at the end, and 2) 'bud': start a new branch from the 'onto' commit Since multiple branches most often want to branch off from a common base commit, the 'finish' command implies a 'bud' after marking the HEAD for later merging. For example, when given an edit script as this: pick abcdef Adds an initial README.md file pick 012345 Adds a FAQ section to the README pick 987654 Fix an off-by-one bug you might want to put the first two commits into the 'readme' branch while the third commit wants to live in the 'fixes' branch. This can be accomplished by inserting two 'finish' lines: pick abcdef Adds an initial README.md file pick 012345 Adds a FAQ section to the README finish readme pick 987654 Fix an off-by-one bug finish fixes Since 'finish' implies a 'bud', this will result in a rewritten history like this: * 3141592 Merge 'fixes' into HEAD |\ | * cafebabe Fix an off-by-one bug * | badf00d Merge 'readme' into HEAD |\ \ | * | c0eddad Adds a FAQ section to the README | * | d1bad00 Adds an initial README.md file |/ / o-' fa7d00d Start the merging-rebase Signed-off-by: Johannes Schindelin --- share/msysGit/shears.sh | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/share/msysGit/shears.sh b/share/msysGit/shears.sh index 5c34cfe7..e3f67add 100755 --- a/share/msysGit/shears.sh +++ b/share/msysGit/shears.sh @@ -38,7 +38,7 @@ EOF } # Extra commands for use in the rebase script -extra_commands="edit mark rewind merge start_merging_rebase cleanup" +extra_commands="edit bud finish mark rewind merge start_merging_rebase cleanup" edit () { GIT_EDITOR="$1" && @@ -71,6 +71,19 @@ rewind () { git reset --hard refs/rewritten/"$1" } +bud () { + shorthead="$(git rev-parse --short --verify HEAD)" && + git for-each-ref refs/rewritten/ | + grep "^$shorthead" || + die "Refusing to leave unmarked revision $shorthead behind" + git reset --hard refs/rewritten/onto +} + +finish () { + mark "$@" && + bud +} + merge () { # parse command-line arguments parents= @@ -129,6 +142,13 @@ cleanup () { do git update-ref -d refs/rewritten/$rewritten done && + for rewritten in $(git for-each-ref refs/rewritten/ | + sed 's/^[^ ]* commit.refs\/rewritten\///') + do + test onto = "$rewritten" || + merge $rewritten + git update-ref -d refs/rewritten/$rewritten + done && git config --unset alias..r } @@ -274,8 +294,7 @@ EOF # if there is no line, branch from the 'onto' commit if test -z "$line" then - subtodo="$(printf '\nexec %s\n%s' \ - 'git reset --hard refs/rewritten/onto' \ + subtodo="$(printf '\nbud\n%s' \ "$subtodo")" break fi @@ -382,6 +401,9 @@ $command $shortsha1 $oneline")" this="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")" setup () { + test -z "$(git for-each-ref refs/rewritten/)" || + die "There are still rewritten revisions" + alias="$(git config --get alias..r)" test -z "$alias" || test "a$alias" = "a!sh \"$this\"" || -- 2.11.4.GIT