filter-branch: fix behaviour of '-k'
The option '-k' says that the given commit and _all_ of its ancestors are kept as-is. However, if a to-be-rewritten commit branched from an ancestor of an ancestor of a commit given with '-k', filter-branch would fail. Example: A - B \ C If filter-branch was called with '-k B -s C', it would actually keep B (and A as its parent), but would rewrite C, and its parent. Noticed by Johannes Sixt. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
c12764b8b7
commit
9840906026
@ -327,11 +327,6 @@ ret=0
|
|||||||
|
|
||||||
mkdir ../map # map old->new commit ids for rewriting parents
|
mkdir ../map # map old->new commit ids for rewriting parents
|
||||||
|
|
||||||
# seed with identity mappings for the parents where we start off
|
|
||||||
for commit in $unchanged; do
|
|
||||||
echo $commit > ../map/$commit
|
|
||||||
done
|
|
||||||
|
|
||||||
git-rev-list --reverse --topo-order $srcbranch --not $unchanged >../revs
|
git-rev-list --reverse --topo-order $srcbranch --not $unchanged >../revs
|
||||||
commits=$(cat ../revs | wc -l | tr -d " ")
|
commits=$(cat ../revs | wc -l | tr -d " ")
|
||||||
|
|
||||||
@ -372,7 +367,8 @@ while read commit; do
|
|||||||
parentstr="$parentstr -p $reparent"
|
parentstr="$parentstr -p $reparent"
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
die "assertion failed: parent $parent for commit $commit not found in rewritten ones"
|
# if it was not rewritten, take the original
|
||||||
|
parentstr="$parentstr -p $parent"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if [ "$filter_parent" ]; then
|
if [ "$filter_parent" ]; then
|
||||||
@ -385,12 +381,21 @@ while read commit; do
|
|||||||
tee ../map/$commit
|
tee ../map/$commit
|
||||||
done <../revs
|
done <../revs
|
||||||
|
|
||||||
git-update-ref refs/heads/"$dstbranch" $(head -n 1 ../map/$(tail -n 1 ../revs))
|
src_head=$(tail -n 1 ../revs)
|
||||||
if [ "$(cat ../map/$(tail -n 1 ../revs) | wc -l)" -gt 1 ]; then
|
target_head=$(head -n 1 ../map/$src_head)
|
||||||
|
case "$target_head" in
|
||||||
|
'')
|
||||||
|
echo Nothing rewritten
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
git-update-ref refs/heads/"$dstbranch" $target_head
|
||||||
|
if [ $(cat ../map/$src_head | wc -l) -gt 1 ]; then
|
||||||
echo "WARNING: Your commit filter caused the head commit to expand to several rewritten commits. Only the first such commit was recorded as the current $dstbranch head but you will need to resolve the situation now (probably by manually merging the other commits). These are all the commits:" >&2
|
echo "WARNING: Your commit filter caused the head commit to expand to several rewritten commits. Only the first such commit was recorded as the current $dstbranch head but you will need to resolve the situation now (probably by manually merging the other commits). These are all the commits:" >&2
|
||||||
sed 's/^/ /' ../map/$(tail -n 1 ../revs) >&2
|
sed 's/^/ /' ../map/$src_head >&2
|
||||||
ret=1
|
ret=1
|
||||||
fi
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
if [ "$filter_tag_name" ]; then
|
if [ "$filter_tag_name" ]; then
|
||||||
git-for-each-ref --format='%(objectname) %(objecttype) %(refname)' refs/tags |
|
git-for-each-ref --format='%(objectname) %(objecttype) %(refname)' refs/tags |
|
||||||
|
@ -45,4 +45,13 @@ test_expect_success 'test that the file was renamed' '
|
|||||||
test d = $(git show H3:doh)
|
test d = $(git show H3:doh)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
git tag oldD H3~4
|
||||||
|
test_expect_success 'rewrite one branch, keeping a side branch' '
|
||||||
|
git-filter-branch --tree-filter "mv b boh || :" -k D -s oldD modD
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'common ancestor is still common (unchanged)' '
|
||||||
|
test "$(git-merge-base modD D)" = "$(git-rev-parse B)"
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Reference in New Issue
Block a user