rebase-i-p: only list commits that require rewriting in todo
This is heavily based on Stephan Beyer's git sequencer rewrite of rebase-i-p. Each commit is still found by rev-list UPSTREAM..HEAD, but a commit is only included in todo if at least one its parents has been marked for rewriting. Signed-off-by: Stephen Haberman <stephen@exigencecorp.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Stephen Haberman committed
Oct 15, 2008 at 02:44 UTC
acc8559aa33b7a1ea49b0841e0759ecf05c6f26e
1 file changed
+52
-25
git-rebase--interactive.sh
+52
-25
@@ -579,18 +579,67 @@ first and then run 'git rebase --continue' again."
579
echo $ONTO > "$REWRITTEN"/$c ||
580
die "Could not init rewritten commits"
581
done
582
+ # No cherry-pick because our first pass is to determine
583
+ # parents to rewrite and skipping dropped commits would
584
+ # prematurely end our probe
585
MERGES_OPTION=
586
else
584
- MERGES_OPTION=--no-merges
587
+ MERGES_OPTION="--no-merges --cherry-pick"
588
fi
589
590
SHORTUPSTREAM=$(git rev-parse --short $UPSTREAM)
591
SHORTHEAD=$(git rev-parse --short $HEAD)
592
SHORTONTO=$(git rev-parse --short $ONTO)
593
git rev-list $MERGES_OPTION --pretty=oneline --abbrev-commit \
591
- --abbrev=7 --reverse --left-right --cherry-pick \
594
+ --abbrev=7 --reverse --left-right --topo-order \
595
$UPSTREAM...$HEAD | \
593
- sed -n "s/^>/pick /p" > "$TODO"
596
+ sed -n "s/^>//p" | while read shortsha1 rest
597
+ do
598
+ if test t != "$PRESERVE_MERGES"
599
+ then
600
+ echo "pick $shortsha1 $rest" >> "$TODO"
601
+ else
602
+ sha1=$(git rev-parse $shortsha1)
603
+ preserve=t
604
+ for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
605
+ do
606
+ if test -f "$REWRITTEN"/$p
607
+ then
608
+ preserve=f
609
+ fi
610
+ done
611
+ if test f = "$preserve"
612
+ then
613
+ touch "$REWRITTEN"/$sha1
614
+ echo "pick $shortsha1 $rest" >> "$TODO"
615
+ fi
616
+ fi
617
+ done
618
+
619
+ # Watch for commits that been dropped by --cherry-pick
620
+ if test t = "$PRESERVE_MERGES"
621
+ then
622
+ mkdir "$DROPPED"
623
+ # Save all non-cherry-picked changes
624
+ git rev-list $UPSTREAM...$HEAD --left-right --cherry-pick | \
625
+ sed -n "s/^>//p" > "$DOTEST"/not-cherry-picks
626
+ # Now all commits and note which ones are missing in
627
+ # not-cherry-picks and hence being dropped
628
+ git rev-list $UPSTREAM...$HEAD --left-right | \
629
+ sed -n "s/^>//p" | while read rev
630
+ do
631
+ if test -f "$REWRITTEN"/$rev -a "$(grep "$rev" "$DOTEST"/not-cherry-picks)" = ""
632
+ then
633
+ # Use -f2 because if rev-list is telling us this commit is
634
+ # not worthwhile, we don't want to track its multiple heads,
635
+ # just the history of its first-parent for others that will
636
+ # be rebasing on top of it
637
+ git rev-list --parents -1 $rev | cut -d' ' -f2 > "$DROPPED"/$rev
638
+ cat "$TODO" | grep -v "${rev:0:7}" > "${TODO}2" ; mv "${TODO}2" "$TODO"
639
+ rm "$REWRITTEN"/$rev
640
+ fi
641
+ done
642
+ fi
643
test -s "$TODO" || echo noop >> "$TODO"
644
cat >> "$TODO" << EOF
645
@@ -606,28 +655,6 @@ first and then run 'git rebase --continue' again."
655
#
656
EOF
657
609
- # Watch for commits that been dropped by --cherry-pick
610
- if test t = "$PRESERVE_MERGES"
611
- then
612
- mkdir "$DROPPED"
613
- # drop the --cherry-pick parameter this time
614
- git rev-list $MERGES_OPTION --abbrev-commit \
615
- --abbrev=7 $UPSTREAM...$HEAD --left-right | \
616
- sed -n "s/^>//p" | while read rev
617
- do
618
- grep --quiet "$rev" "$TODO"
619
- if [ $? -ne 0 ]
620
- then
621
- # Use -f2 because if rev-list is telling this commit is not
622
- # worthwhile, we don't want to track its multiple heads,
623
- # just the history of its first-parent for others that will
624
- # be rebasing on top of us
625
- full=$(git rev-parse $rev)
626
- git rev-list --parents -1 $rev | cut -d' ' -f2 > "$DROPPED"/$full
627
- fi
628
- done
629
- fi
630
-
658
has_action "$TODO" ||
659
die_abort "Nothing to do"
660