Merge branch 'mb/filter-branch-optim'
authorJunio C Hamano <gitster@pobox.com>
Wed, 18 Jul 2018 19:20:32 +0000 (12:20 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 18 Jul 2018 19:20:32 +0000 (12:20 -0700)
"git filter-branch" when used with the "--state-branch" option
still attempted to rewrite the commits whose filtered result is
known from the previous attempt (which is recorded on the state
branch); the command has been corrected not to waste cycles doing
so.

* mb/filter-branch-optim:
filter-branch: skip commits present on --state-branch

1  2 
git-filter-branch.sh
t/t7003-filter-branch.sh
diff --combined git-filter-branch.sh
index ccceaf19a74373bb23b2a2b1aa71b7f0bb909d54,10096cb99910e23626ca0b6d93e43af52c5fe50e..5c5afa2b985e2e524601518bbb8fb8d3c8efda61
@@@ -11,8 -11,6 +11,8 @@@
  # The following functions will also be available in the commit filter:
  
  functions=$(cat << \EOF
 +EMPTY_TREE=$(git hash-object -t tree /dev/null)
 +
  warn () {
        echo "$*" >&2
  }
@@@ -48,7 -46,7 +48,7 @@@ 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
 +      elif test $# = 1 && test "$1" = $EMPTY_TREE; then
                :
        else
                git commit-tree "$@"
@@@ -253,18 -251,8 +253,18 @@@ done < "$tempdir"/backup-ref
  
  # The refs should be updated if their heads were rewritten
  git rev-parse --no-flags --revs-only --symbolic-full-name \
 -      --default HEAD "$@" > "$tempdir"/raw-heads || exit
 -sed -e '/^^/d' "$tempdir"/raw-heads >"$tempdir"/heads
 +      --default HEAD "$@" > "$tempdir"/raw-refs || exit
 +while read ref
 +do
 +      case "$ref" in ^?*) continue ;; esac
 +
 +      if git rev-parse --verify "$ref"^0 >/dev/null 2>&1
 +      then
 +              echo "$ref"
 +      else
 +              warn "WARNING: not rewriting '$ref' (not a committish)"
 +      fi
 +done >"$tempdir"/heads <"$tempdir"/raw-refs
  
  test -s "$tempdir"/heads ||
        die "You must specify a ref to rewrite."
@@@ -322,7 -310,7 +322,7 @@@ git rev-list --reverse --topo-order --d
        die "Could not get the commits"
  commits=$(wc -l <../revs | tr -d " ")
  
 -test $commits -eq 0 && die "Found nothing to rewrite"
 +test $commits -eq 0 && die_with_status 2 "Found nothing to rewrite"
  
  # Rewrite the commits
  report_progress ()
@@@ -372,6 -360,7 +372,7 @@@ while read commit parents; d
        git_filter_branch__commit_count=$(($git_filter_branch__commit_count+1))
  
        report_progress
+       test -f "$workdir"/../map/$commit && continue
  
        case "$filter_subdir" in
        "")
diff --combined t/t7003-filter-branch.sh
index ec4b160ddb9f966044e729f35cc1edfcc79eed14,451211280b84169213c439212715674f035eb13d..e23de7d0b5a4da29effb1e59426f857fed0e91e0
@@@ -107,6 -107,21 +107,21 @@@ test_expect_success 'test that the dire
        test dir/D = "$(cat diroh/D.t)"
  '
  
+ V=$(git rev-parse HEAD)
+ test_expect_success 'populate --state-branch' '
+       git filter-branch --state-branch state -f --tree-filter "touch file || :" HEAD
+ '
+ W=$(git rev-parse HEAD)
+ test_expect_success 'using --state-branch to skip already rewritten commits' '
+       test_when_finished git reset --hard $V &&
+       git reset --hard $V &&
+       git filter-branch --state-branch state -f --tree-filter "touch file || :" HEAD &&
+       test_cmp_rev $W HEAD
+ '
  git tag oldD HEAD~4
  test_expect_success 'rewrite one branch, keeping a side branch' '
        git branch modD oldD &&
@@@ -187,8 -202,7 +202,8 @@@ test_expect_success 'author informatio
                        test \$GIT_COMMIT != $(git rev-parse master) || \
                        echo Hallo" \
                preserved-author) &&
 -      test 1 = $(git rev-list --author="B V Uips" preserved-author | wc -l)
 +      git rev-list --author="B V Uips" preserved-author >actual &&
 +      test_line_count = 1 actual
  '
  
  test_expect_success "remove a certain author's commits" '
        cnt1=$(git rev-list master | wc -l) &&
        cnt2=$(git rev-list removed-author | wc -l) &&
        test $cnt1 -eq $(($cnt2 + 1)) &&
 -      test 0 = $(git rev-list --author="B V Uips" removed-author | wc -l)
 +      git rev-list --author="B V Uips" removed-author >actual &&
 +      test_line_count = 0 actual
  '
  
  test_expect_success 'barf on invalid name' '
@@@ -260,8 -273,7 +275,8 @@@ test_expect_success 'Subdirectory filte
        git commit -m "Re-adding foo" &&
  
        git filter-branch -f --subdirectory-filter foo &&
 -      test $(git rev-list master | wc -l) = 3
 +      git rev-list master >actual &&
 +      test_line_count = 3 actual
  '
  
  test_expect_success 'Tag name filtering retains tag message' '
@@@ -473,18 -485,4 +488,18 @@@ test_expect_success 'tree-filter deals 
        git show HEAD:$ambiguous
  '
  
 +test_expect_success 'rewrite repository including refs that point at non-commit object' '
 +      test_when_finished "git reset --hard original" &&
 +      tree=$(git rev-parse HEAD^{tree}) &&
 +      test_when_finished "git replace -d $tree" &&
 +      echo A >new &&
 +      git add new &&
 +      new_tree=$(git write-tree) &&
 +      git replace $tree $new_tree &&
 +      git tag -a -m "tag to a tree" treetag $new_tree &&
 +      git reset --hard HEAD &&
 +      git filter-branch -f -- --all >filter-output 2>&1 &&
 +      ! fgrep fatal filter-output
 +'
 +
  test_done