This option tells rebase--interactive to cherry-pick all the commits in the rebased branch, instead of fast-forwarding over any unchanged commits. Signed-off-by: Marc Branchaud <marcnarc@xxxxxxxxxxx> --- Now passes all rebase unit tests. I'll repeat my rationale from the v1 posting: This offers an alterntive way to deal with reverted merges (the revert-a-faulty-merge.txt howto recommends reverting the initial reversion before re-merging a modified topic branch). With this change, you can instead use the --no-ff option to recreate the branch with entirely new commits (they're new because at the very least the committer time is different). This obviates the need to revert the reversion, as you can re-merge the new topic branch directly. (Honestly, I wouldn't say that this approach is vastly superior to reverting the reversion. I just find it a little less messy and a little more intuitive. It's also a bit easier to explain to people to "use --no-ff after reverting a merge" instead of making sure they get the double- reversion right.) M. Documentation/git-rebase.txt | 13 ++++++++++++- git-rebase--interactive.sh | 10 ++++++++-- t/t3417-rebase-no-ff.sh | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100755 t/t3417-rebase-no-ff.sh diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt index 823f2a4..01f1476 100644 --- a/Documentation/git-rebase.txt +++ b/Documentation/git-rebase.txt @@ -316,7 +316,18 @@ which makes little sense. commit to be modified, and change the action of the moved commit from `pick` to `squash` (or `fixup`). + -This option is only valid when '--interactive' option is used. +This option is only valid when the '--interactive' option is used. + +--no-ff:: + Cherry-pick all rebased commits instead of fast-forwarding over + the unchanged ones. This ensures that the entire history of the + rebased branch is composed of new commits. You may find this + helpful after reverting a topic branch merge, as this option + recreates the topic branch with fresh commits so it can be remerged + successfully without needing to "reverting the reversion" (as described + in the link:howto/revert-a-faulty-merge.txt[revert-a-faulty-merge How-To]). ++ +This option is only valid when the '--interactive' option is used. include::merge-strategies.txt[] diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index 3e4fd14..35943c0 100755 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -20,6 +20,7 @@ v,verbose display a diffstat of what changed upstream onto= rebase onto given branch instead of upstream p,preserve-merges try to recreate merges instead of ignoring them s,strategy= use the given merge strategy +no-ff never fast-forward any commits, even if they're unchanged m,merge always used (no-op) i,interactive always used (no-op) Actions: @@ -103,6 +104,7 @@ VERBOSE= OK_TO_SKIP_PRE_REBASE= REBASE_ROOT= AUTOSQUASH= +NO_SKIP= GIT_CHERRY_PICK_HELP=" After resolving the conflicts, mark the corrected paths with 'git add <paths>', and @@ -222,7 +224,7 @@ do_with_author () { } pick_one () { - no_ff= + no_ff=$NO_SKIP case "$1" in -n) sha1=$2; no_ff=t ;; *) sha1=$1 ;; esac output git rev-parse --verify $sha1 || die "Invalid commit name: $sha1" test -d "$REWRITTEN" && @@ -742,6 +744,10 @@ first and then run 'git rebase --continue' again." -i) # yeah, we know ;; + --no-ff) + # Set -n parameter to pass to pick_one function + NO_SKIP=t + ;; --root) REBASE_ROOT=t ;; @@ -927,7 +933,7 @@ EOF has_action "$TODO" || die_abort "Nothing to do" - test -d "$REWRITTEN" || skip_unnecessary_picks + test -d "$REWRITTEN" || test -n "$NO_SKIP" || skip_unnecessary_picks git update-ref ORIG_HEAD $HEAD output git checkout $ONTO && do_rest diff --git a/t/t3417-rebase-no-ff.sh b/t/t3417-rebase-no-ff.sh new file mode 100755 index 0000000..2a2be81 --- /dev/null +++ b/t/t3417-rebase-no-ff.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# Copyright (c) 2010 Marc Branchaud +# + +test_description='git rebase -i --no-ff tests' + +. ./test-lib.sh + +. "$TEST_DIRECTORY"/lib-rebase.sh + +set_fake_editor + +test_expect_success setup ' + echo hello > hello && + git add hello && + git commit -m "hello" && + + echo world >> hello && + git commit -a -m "hello world" && + + echo goodbye >> hello && + git commit -a -m "goodbye" && + + git tag old_head + ' +# Pause to ensure that the cherry-picked commits have a different +# timestamp. +sleep 1 + +test_expect_success 'rebase -i --no-ff' ' + git rebase -i --no-ff HEAD~2 && + test ! $(git rev-parse HEAD) = $(git rev-parse old_head) + ' + +test_done -- 1.7.0.2.1.g6d104.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html