filter-branch: fix --prune-empty on parentless commits
authorDevin J. Pohly <djpohly@gmail.com>
Thu, 23 Feb 2017 08:27:35 +0000 (02:27 -0600)
committerJunio C Hamano <gitster@pobox.com>
Fri, 3 Mar 2017 20:43:37 +0000 (12:43 -0800)
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>
Documentation/git-filter-branch.txt
git-filter-branch.sh
t/t7003-filter-branch.sh
index 0a09698c033fb2e1cdf68aa33eed4f109a034d5f..6e4bb022043faeddd363c899872e7de96c926c1c 100644 (file)
@@ -167,14 +167,12 @@ to other tags will be rewritten to point to the underlying commit.
        project root. Implies <<Remap_to_ancestor>>.
 
 --prune-empty::
-       Some kind of filters will generate empty commits, that left the tree
-       untouched.  This switch allow git-filter-branch to ignore such
-       commits.  Though, this switch only applies for commits that have one
-       and only one parent, it will hence keep merges points. Also, this
-       option is not compatible with the use of `--commit-filter`. Though you
-       just need to use the function 'git_commit_non_empty_tree "$@"' instead
-       of the `git commit-tree "$@"` idiom in your commit filter to make that
-       happen.
+       Some filters will generate empty commits that leave the tree untouched.
+       This option instructs git-filter-branch to remove such commits if they
+       have exactly one or zero non-pruned parents; merge commits will
+       therefore remain intact.  This option cannot be used together with
+       `--commit-filter`, though the same effect can be achieved by using the
+       provided `git_commit_non_empty_tree` function in a commit filter.
 
 --original <namespace>::
        Use this option to set the namespace where the original commits
index 86b2ff1e07614846465109dcb4b9afed11013839..2b8cdba157d9cd822acc88b7ec58cecda0149b85 100755 (executable)
@@ -46,6 +46,8 @@ git_commit_non_empty_tree()
 {
        if test $# = 3 && test "$1" = $(git rev-parse "$3^{tree}"); then
                map "$3"
+       elif test $# = 1 && test "$1" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904; then
+               :
        else
                git commit-tree "$@"
        fi
index 40526d17162a8cddd578477629376c21f4ec2489..7cb60799be1a109e2210350137c8754a5bc4bb7d 100755 (executable)
@@ -362,7 +362,7 @@ test_expect_success 'prune empty works even without index/tree filters' '
        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 branch testing H &&
        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_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 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 &&