1
0
mirror of https://github.com/git/git.git synced 2024-09-25 18:01:04 +02:00

rebase -i -p: include non-first-parent commits in todo list

Consider this graph:

        D---E    (topic, HEAD)
       /   /
  A---B---C      (master)
   \
    F            (topic2)

and the following three commands:
  1. git rebase -i -p A
  2. git rebase -i -p --onto F A
  3. git rebase -i -p B

Currently, (1) and (2) will pick B, D, C, and E onto A and F,
respectively.  However, (3) will only pick D and E onto B, but not C,
which is inconsistent with (1) and (2).  As a result, we cannot modify C
during the interactive-rebase.

The current behavior also creates a bug if we do:
  4. git rebase -i -p C

In (4), E is never picked.  And since interactive-rebase resets "HEAD"
to "onto" before picking any commits, D and E are lost after the
interactive-rebase.

This patch fixes the inconsistency and bug by ensuring that all children
of upstream are always picked.  This essentially reverts the commit:
  d80d6bc146

When compiling the todo list, commits reachable from "upstream" should
never be skipped under any conditions.  Otherwise, we lose the ability
to modify them like (3), and create a bug like (4).

Two of the tests contain a scenario like (3).  Since the new behavior
added more commits for picking, these tests need to be updated to
account for the additional pick lines.  A new test has also been added
for (4).

Signed-off-by: Andrew Wong <andrew.kw.w@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Andrew Wong 2011-06-18 18:12:01 -04:00 committed by Junio C Hamano
parent 2c162b56f3
commit 12bf828348
4 changed files with 30 additions and 5 deletions

View File

@ -713,7 +713,6 @@ then
# parents to rewrite and skipping dropped commits would # parents to rewrite and skipping dropped commits would
# prematurely end our probe # prematurely end our probe
merges_option= merges_option=
first_after_upstream="$(git rev-list --reverse --first-parent $upstream..$orig_head | head -n 1)"
else else
merges_option="--no-merges --cherry-pick" merges_option="--no-merges --cherry-pick"
fi fi
@ -746,7 +745,7 @@ do
preserve=t preserve=t
for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-) for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -s -f2-)
do do
if test -f "$rewritten"/$p -a \( $p != $onto -o $sha1 = $first_after_upstream \) if test -f "$rewritten"/$p
then then
preserve=f preserve=f
fi fi

View File

@ -295,7 +295,7 @@ test_expect_success 'preserve merges with -p' '
' '
test_expect_success 'edit ancestor with -p' ' test_expect_success 'edit ancestor with -p' '
FAKE_LINES="1 edit 2 3 4" git rebase -i -p HEAD~3 && FAKE_LINES="1 2 edit 3 4" git rebase -i -p HEAD~3 &&
echo 2 > unrelated-file && echo 2 > unrelated-file &&
test_tick && test_tick &&
git commit -m L2-modified --amend unrelated-file && git commit -m L2-modified --amend unrelated-file &&

View File

@ -37,7 +37,15 @@ export GIT_AUTHOR_EMAIL
# \ # \
# B2 <-- origin/topic # B2 <-- origin/topic
# #
# In all cases, 'topic' is rebased onto 'origin/topic'. # Clone 4 (merge using second parent as base):
#
# A1--A2--B3 <-- origin/master
# \
# B1--A3--M <-- topic
# \ /
# \--A4 <-- topic2
# \
# B2 <-- origin/topic
test_expect_success 'setup for merge-preserving rebase' \ test_expect_success 'setup for merge-preserving rebase' \
'echo First > A && 'echo First > A &&
@ -57,6 +65,13 @@ test_expect_success 'setup for merge-preserving rebase' \
git merge origin/master git merge origin/master
) && ) &&
git clone ./. clone4 &&
(
cd clone4 &&
git checkout -b topic origin/topic &&
git merge origin/master
) &&
echo Fifth > B && echo Fifth > B &&
git add B && git add B &&
git commit -m "Add different B" && git commit -m "Add different B" &&
@ -123,4 +138,15 @@ test_expect_success 'rebase -p preserves no-ff merges' '
) )
' '
test_expect_success 'rebase -p works when base inside second parent' '
(
cd clone4 &&
git fetch &&
git rebase -p HEAD^2 &&
test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) &&
test 1 = $(git rev-list --all --pretty=oneline | grep "Modify B" | wc -l) &&
test 1 = $(git rev-list --all --pretty=oneline | grep "Merge remote-tracking branch " | wc -l)
)
'
test_done test_done

View File

@ -37,7 +37,7 @@ test_expect_success 'setup' '
# -- C1 -- # -- C1 --
# #
test_expect_success 'squash F1 into D1' ' test_expect_success 'squash F1 into D1' '
FAKE_LINES="1 squash 3 2" git rebase -i -p B1 && FAKE_LINES="1 squash 4 2 3" git rebase -i -p B1 &&
test "$(git rev-parse HEAD^2)" = "$(git rev-parse C1)" && test "$(git rev-parse HEAD^2)" = "$(git rev-parse C1)" &&
test "$(git rev-parse HEAD~2)" = "$(git rev-parse B1)" && test "$(git rev-parse HEAD~2)" = "$(git rev-parse B1)" &&
git tag E2 git tag E2