Re: [TOY PATCH] filter-branch: add option --delete-unchanged
From: Jan Wielemaker <hidden>
Date: 2016-06-15 22:45:08
Hi Thomas, On Friday 08 August 2008 10:10:24 pm Thomas Rast wrote:
With --delete-unchanged, we nuke refs whose targets did not change during rewriting. It is intended to be used along with --subdirectory-filter to clean out old refs from before the first commit to the filtered subdirectory. (They would otherwise keep the old history alive.) Obviously this is a rather dangerous mode of operation. Note the "sort -u" is required: Without it, --all includes 'origin/master' twice (from 'origin/master' and via 'origin/HEAD'), and the second pass concludes it is unchanged and nukes the ref. Signed-off-by: Thomas Rast <redacted> --- This applies on top of "filter-branch: be more helpful when an annotated tag changes". I'm not really sure if this should go in, but it might have solved Jan's problem.
I may hope it isn't just `my problem' :-) I tested with this patch, and I can confirm the following produces precisily what I want: git clone /home/git/pl.git/ cd pl git remote rm origin git filter-branch --subdirectory-filter packages/chr --tag-name-filter cat --delete-unchanged-refs -- --all rm -r .git/refs/original cd .. git clone file://pl chr chr is now a nice clean 2 MB repository, starting in 2004, the epoch of this directory rather than 1992 (the overall project epoch). B.t.w. Pretending a remote clone was the only way to get a nice 2MB repo. The initial is 140MB. After the filtering it is 62 MB. Funny: after a git gc it grows to 1.1 Gb!? Anyway, thanks a lot and I hope this makes it into the next git release! Cheers --- Jan
quoted hunk ↗ jump to hunk
git-filter-branch.sh | 33 +++++++++++++++++++++++---------- 1 files changed, 23 insertions(+), 10 deletions(-)diff --git a/git-filter-branch.sh b/git-filter-branch.sh index a140337..539b2e6 100755 --- a/git-filter-branch.sh +++ b/git-filter-branch.sh@@ -114,6 +114,7 @@ filter_tag_name= filter_subdir= orig_namespace=refs/original/ force= +delete_unchanged= while : do case "$1" in@@ -126,6 +127,11 @@ do force=t continue ;; + --delete-unchanged-refs) + shift + delete_unchanged=t + continue + ;; -*) ;; *)@@ -215,6 +221,7 @@ export GIT_DIR GIT_WORK_TREE # The refs should be updated if their heads were rewritten git rev-parse --no-flags --revs-only --symbolic-full-name --default HEAD"$@" | +sort -u | sed -e '/^^/d' >"$tempdir"/heads test -s "$tempdir"/heads ||@@ -344,7 +351,7 @@ do sha1=$(git rev-parse "$ref"^0) rewritten=$(map $sha1) - test $sha1 = "$rewritten" && + test $sha1 = "$rewritten" -a -z "$delete_unchanged" && warn "WARNING: Ref '$ref' is unchanged" && continue@@ -355,16 +362,22 @@ do die "Could not delete $ref" ;; $_x40) - echo "Ref '$ref' was rewritten" - if ! git update-ref -m "filter-branch: rewrite" \ - "$ref" $rewritten $sha1 2>/dev/null; then - if test $(git cat-file -t "$ref") = tag; then - if test -z "$filter_tag_name"; then - warn "WARNING: You said to rewrite tagged commits, but not thecorresponding tag." - warn "WARNING: Perhaps use '--tag-name-filter cat' to rewrite the tag." + if test "$delete_unchanged" -a $sha1 = "$rewritten"; then + echo "Ref '$ref' was deleted because it is unchanged" + git update-ref -m "filter-branch: delete" -d "$ref" $sha1 || + die "Could not delete $ref" + else + echo "Ref '$ref' was rewritten" + if ! git update-ref -m "filter-branch: rewrite" \ + "$ref" $rewritten $sha1 2>/dev/null; then + if test $(git cat-file -t "$ref") = tag; then + if test -z "$filter_tag_name"; then + warn "WARNING: You said to rewrite tagged commits, but not the corresponding tag." + warn "WARNING: Perhaps use '--tag-name-filter cat' to rewrite the tag." + fi + else + die "Could not rewrite $ref" fi - else - die "Could not rewrite $ref" fi fi ;;