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>
This commit is contained in:
Devin J. Pohly 2017-02-23 02:27:35 -06:00 committed by Junio C Hamano
parent 4dacc8f11d
commit a582a82d24
3 changed files with 10 additions and 10 deletions

View file

@ -167,14 +167,12 @@ to other tags will be rewritten to point to the underlying commit.
project root. Implies <<Remap_to_ancestor>>. project root. Implies <<Remap_to_ancestor>>.
--prune-empty:: --prune-empty::
Some kind of filters will generate empty commits, that left the tree Some filters will generate empty commits that leave the tree untouched.
untouched. This switch allow git-filter-branch to ignore such This option instructs git-filter-branch to remove such commits if they
commits. Though, this switch only applies for commits that have one have exactly one or zero non-pruned parents; merge commits will
and only one parent, it will hence keep merges points. Also, this therefore remain intact. This option cannot be used together with
option is not compatible with the use of `--commit-filter`. Though you `--commit-filter`, though the same effect can be achieved by using the
just need to use the function 'git_commit_non_empty_tree "$@"' instead provided `git_commit_non_empty_tree` function in a commit filter.
of the `git commit-tree "$@"` idiom in your commit filter to make that
happen.
--original <namespace>:: --original <namespace>::
Use this option to set the namespace where the original commits Use this option to set the namespace where the original commits

View file

@ -46,6 +46,8 @@ git_commit_non_empty_tree()
{ {
if test $# = 3 && test "$1" = $(git rev-parse "$3^{tree}"); then if test $# = 3 && test "$1" = $(git rev-parse "$3^{tree}"); then
map "$3" map "$3"
elif test $# = 1 && test "$1" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904; then
:
else else
git commit-tree "$@" git commit-tree "$@"
fi fi

View file

@ -362,7 +362,7 @@ test_expect_success 'prune empty works even without index/tree filters' '
test_cmp expect actual test_cmp expect actual
' '
test_expect_failure '--prune-empty is able to prune root commit' ' test_expect_success '--prune-empty is able to prune root commit' '
git rev-list branch-no-a >expect && git rev-list branch-no-a >expect &&
git branch testing H && git branch testing H &&
git filter-branch -f --prune-empty --index-filter "git update-index --remove A.t" testing && 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' '
test_cmp expect actual test_cmp expect actual
' '
test_expect_failure '--prune-empty is able to prune entire branch' ' test_expect_success '--prune-empty is able to prune entire branch' '
git branch prune-entire B && git branch prune-entire B &&
git filter-branch -f --prune-empty --index-filter "git update-index --remove A.t B.t" prune-entire && git filter-branch -f --prune-empty --index-filter "git update-index --remove A.t B.t" prune-entire &&
test_path_is_missing .git/refs/heads/prune-entire && test_path_is_missing .git/refs/heads/prune-entire &&