Package: git
Severity: wishlist
Tags: upstream patch

One of the annoying features of 'git filter-branch' is that it needlessly
rewrites signed commits (and signed tags) even if they would have no other
changes applied to them. That of course causes all their children to be
rewitten for the new parent commit, and so on.

The attached patch works for me as it reduces the amount of rewrites to
the commits that actually need changes to be applied (and their
descendants).

* if the only difference between the old and new commit object is the
  lack of the signature, continue using the old one
* if a tag has both old and new name and underlying old and new commit
  sha1 matching, don't attempt to rewrite the tag

* both cases could be made conditional on a new command line flag
  s.t. default behavior does not change
* the skipped tag rewrite could be wrong in the case
    tag2 --> tag1 --> commit0
  where commit0 and tag2 are unmodified but tag1 got rewritten:
  tag2 should be rewritten to point directly to commit0


Andreas
--- /usr/lib/git-core/git-filter-branch 2020-04-20 02:19:12.000000000 +0200
+++ /home/anbe/bin/git-my-filter-branch 2020-11-23 17:12:40.598592535 +0100
@@ -463,6 +463,21 @@
        workdir=$workdir /bin/sh -c "$filter_commit" "git commit-tree" \
                "$tree" $parentstr < ../message > ../map/$commit ||
                        die "could not write rewritten commit"
+       if true
+       then
+               read newcommit < ../map/$commit
+               if test "$commit" != "$newcommit"
+               then
+                       git cat-file commit "$newcommit" >../newcommit ||
+                               die "Cannot read new commit $newcommit"
+                       if sed -e '0,/^$/{/^gpgsig -----BEGIN PGP 
SIGNATURE-----$/,/^ -----END PGP SIGNATURE-----$/d}' ../commit | \
+                               cmp -s - ../newcommit
+                       then
+                               echo "preserving unchanged signed commit 
$commit"
+                               echo "$commit" > ../map/$commit
+                       fi
+               fi
+       fi
 done <../revs
 
 # If we are filtering for paths, as in the case of a subdirectory
@@ -560,6 +575,10 @@
                new_ref="$(echo "$ref" | eval "$filter_tag_name")" ||
                        die "tag name filter failed: $filter_tag_name"
 
+               if true; then
+                       [ "$ref" = "$new_ref" ] && [ "$sha1" = "$new_sha1" ] && 
continue
+               fi
+
                echo "$ref -> $new_ref ($sha1 -> $new_sha1)"
 
                if [ "$type" = "tag" ]; then

Reply via email to