summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/git-filter-branch.txt14
-rwxr-xr-xgit-filter-branch.sh18
-rwxr-xr-xt/t7003-filter-branch.sh32
3 files changed, 58 insertions, 6 deletions
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index 6454e49bf2..8d80f0d074 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -133,10 +133,16 @@ use "--tag-name-filter cat" to simply update the tags. In this
case, be very careful and make sure you have the old tags
backed up in case the conversion has run afoul.
+
-Note that there is currently no support for proper rewriting of
-tag objects; in layman terms, if the tag has a message or signature
-attached, the rewritten tag won't have it. Sorry. (It is by
-definition impossible to preserve signatures at any rate.)
+Nearly proper rewriting of tag objects is supported. If the tag has
+a message attached, a new tag object will be created with the same message,
+author, and timestamp. If the tag has a signature attached, the
+signature will be stripped. It is by definition impossible to preserve
+signatures. The reason this is "nearly" proper, is because ideally if
+the tag did not change (points to the same object, has the same name, etc.)
+it should retain any signature. That is not the case, signatures will always
+be removed, buyer beware. There is also no support for changing the
+author or timestamp (or the tag message for that matter). Tags which point
+to other tags will be rewritten to point to the underlying commit.
--subdirectory-filter <directory>::
Only look at the history which touches the given subdirectory.
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index ea59015baa..333f6a8f3b 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -406,8 +406,22 @@ if [ "$filter_tag_name" ]; then
echo "$ref -> $new_ref ($sha1 -> $new_sha1)"
if [ "$type" = "tag" ]; then
- # Warn that we are not rewriting the tag object itself.
- warn "unreferencing tag object $sha1t"
+ new_sha1=$(git cat-file tag "$ref" |
+ sed -n \
+ -e "1,/^$/{
+ s/^object .*/object $new_sha1/
+ s/^type .*/type commit/
+ s/^tag .*/tag $new_ref/
+ }" \
+ -e '/^-----BEGIN PGP SIGNATURE-----/q' \
+ -e 'p' |
+ git mktag) ||
+ die "Could not create new tag object for $ref"
+ if git cat-file tag "$ref" | \
+ grep '^-----BEGIN PGP SIGNATURE-----' >/dev/null 2>&1
+ then
+ warn "gpg signature stripped from tag object $sha1t"
+ fi
fi
git update-ref "refs/tags/$new_ref" "$new_sha1" ||
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index efd658adb6..16df3d4adb 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -219,4 +219,36 @@ test_expect_success 'Subdirectory filter with disappearing trees' '
test $(git rev-list master | wc -l) = 3
'
+test_expect_success 'Tag name filtering retains tag message' '
+ git tag -m atag T &&
+ git cat-file tag T > expect &&
+ git filter-branch -f --tag-name-filter cat &&
+ git cat-file tag T > actual &&
+ git diff expect actual
+'
+
+faux_gpg_tag='object XXXXXX
+type commit
+tag S
+tagger T A Gger <tagger@example.com> 1206026339 -0500
+
+This is a faux gpg signed tag.
+-----BEGIN PGP SIGNATURE-----
+Version: FauxGPG v0.0.0 (FAUX/Linux)
+
+gdsfoewhxu/6l06f1kxyxhKdZkrcbaiOMtkJUA9ITAc1mlamh0ooasxkH1XwMbYQ
+acmwXaWET20H0GeAGP+7vow=
+=agpO
+-----END PGP SIGNATURE-----
+'
+test_expect_success 'Tag name filtering strips gpg signature' '
+ sha1=$(git rev-parse HEAD) &&
+ sha1t=$(echo "$faux_gpg_tag" | sed -e s/XXXXXX/$sha1/ | git mktag) &&
+ git update-ref "refs/tags/S" "$sha1t" &&
+ echo "$faux_gpg_tag" | sed -e s/XXXXXX/$sha1/ | head -n 6 > expect &&
+ git filter-branch -f --tag-name-filter cat &&
+ git cat-file tag S > actual &&
+ git diff expect actual
+'
+
test_done