summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Bailey <cbailey32@bloomberg.net>2014-06-30 22:20:27 +0100
committerJunio C Hamano <gitster@pobox.com>2014-07-01 08:30:41 -0700
commit79bc4ef3686bc6795aa79a1d4aa6d3060a2cbd93 (patch)
tree51a1c1d703693b4e74a9bc728ea75e669cfbc1a0
parent341e7e8eda3dbeb6867f4f8f45b671201b807de5 (diff)
downloadgit-79bc4ef3686bc6795aa79a1d4aa6d3060a2cbd93.tar.gz
filter-branch: eliminate duplicate mapped parentscb/filter-branch-prune-empty-degenerate-merges
When multiple parents of a merge commit get mapped to the same commit, filter-branch used to pass all instances of the parent commit to the parent and commit filters and to "git commit-tree" or "git_commit_non_empty_tree". This can often happen when extracting a small project from a large repository; merges can join history with no commits on any branch which affect the paths being retained. Once the intermediate commits have been filtered out, all the immediate parents of the merge commit can end up being mapped to the same commit - either the original merge-base or an ancestor of it. "git commit-tree" would display an error but write the commit with the normalized parents in any case. "git_commit_non_empty_tree" would fail to notice that the commit being made was in fact a non-merge commit and would retain it even if a further pass with "--prune-empty" would discard the commit as empty. Ensure that duplicate parents are pruned before the parent filter to make "--prune-empty" idempotent, removing all empty non-merge commits in a singe pass. Signed-off-by: Charles Bailey <cbailey32@bloomberg.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rwxr-xr-xgit-filter-branch.sh8
-rwxr-xr-xt/t7003-filter-branch.sh11
2 files changed, 18 insertions, 1 deletions
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index 86d6994619..e6e99f5bb5 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -332,7 +332,13 @@ while read commit parents; do
parentstr=
for parent in $parents; do
for reparent in $(map "$parent"); do
- parentstr="$parentstr -p $reparent"
+ case "$parentstr " in
+ *" -p $reparent "*)
+ ;;
+ *)
+ parentstr="$parentstr -p $reparent"
+ ;;
+ esac
done
done
if [ "$filter_parent" ]; then
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index 9496736a89..66643e4bd7 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -308,6 +308,17 @@ test_expect_success 'Prune empty commits' '
test_cmp expect actual
'
+test_expect_success 'prune empty collapsed merges' '
+ test_config merge.ff false &&
+ git rev-list HEAD >expect &&
+ test_commit to_remove_2 &&
+ git reset --hard HEAD^ &&
+ test_merge non-ff to_remove_2 &&
+ git filter-branch -f --index-filter "git update-index --remove to_remove_2.t" --prune-empty HEAD &&
+ git rev-list HEAD >actual &&
+ test_cmp expect actual
+'
+
test_expect_success '--remap-to-ancestor with filename filters' '
git checkout master &&
git reset --hard A &&