filter-branch: fix --prune-empty on parentless commits

Previously, the git_commit_non_empty_tree function would always pass any commit with no parents to git-commit-tree, regardless of whether the tree was nonempty. The new commit would then be recorded in the filter-branch revision map, and subsequent commits which leave the tree untouched would be correctly filtered. With this change, parentless commits with an empty tree are correctly pruned, and an empty file is recorded in the revision map, signifying that it was rewritten to "no commits." This works naturally with the parent mapping for subsequent commits. Signed-off-by: Devin J. Pohly <djpohly@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Devin J. Pohly committed Feb 23, 2017 at 02:27 UTC a582a82d2444b627260a764c17d3137d9d255531
3 files changed +10 -10
Documentation/git-filter-branch.txt
+6 -8
@@ -167,14 +167,12 @@ to other tags will be rewritten to point to the underlying commit.
167 project root. Implies <<Remap_to_ancestor>>.
168
169 --prune-empty::
170 - Some kind of filters will generate empty commits, that left the tree
171 - untouched. This switch allow git-filter-branch to ignore such
172 - commits. Though, this switch only applies for commits that have one
173 - and only one parent, it will hence keep merges points. Also, this
174 - option is not compatible with the use of `--commit-filter`. Though you
175 - just need to use the function 'git_commit_non_empty_tree "$@"' instead
176 - of the `git commit-tree "$@"` idiom in your commit filter to make that
177 - happen.
170 + Some filters will generate empty commits that leave the tree untouched.
171 + This option instructs git-filter-branch to remove such commits if they
172 + have exactly one or zero non-pruned parents; merge commits will
173 + therefore remain intact. This option cannot be used together with
174 + `--commit-filter`, though the same effect can be achieved by using the
175 + provided `git_commit_non_empty_tree` function in a commit filter.
176
177 --original <namespace>::
178 Use this option to set the namespace where the original commits
git-filter-branch.sh
+2
@@ -46,6 +46,8 @@ git_commit_non_empty_tree()
46 {
47 if test $# = 3 && test "$1" = $(git rev-parse "$3^{tree}"); then
48 map "$3"
49 + elif test $# = 1 && test "$1" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904; then
50 + :
51 else
52 git commit-tree "$@"
53 fi
t/t7003-filter-branch.sh
+2 -2
@@ -362,7 +362,7 @@ test_expect_success 'prune empty works even without index/tree filters' '
362 test_cmp expect actual
363 '
364
365 -test_expect_failure '--prune-empty is able to prune root commit' '
365 +test_expect_success '--prune-empty is able to prune root commit' '
366 git rev-list branch-no-a >expect &&
367 git branch testing H &&
368 git filter-branch -f --prune-empty --index-filter "git update-index --remove A.t" testing &&
@@ -371,7 +371,7 @@ test_expect_failure '--prune-empty is able to prune root commit' '
371 test_cmp expect actual
372 '
373
374 -test_expect_failure '--prune-empty is able to prune entire branch' '
374 +test_expect_success '--prune-empty is able to prune entire branch' '
375 git branch prune-entire B &&
376 git filter-branch -f --prune-empty --index-filter "git update-index --remove A.t B.t" prune-entire &&
377 test_path_is_missing .git/refs/heads/prune-entire &&