Browse Source

Merge branch 'ic/fix-filter-branch-to-handle-tag-without-tagger'

"git filter-branch" cannot reproduce a history with a tag without
the tagger field, which only ancient versions of Git allowed to be
created.  This has been corrected.

* ic/fix-filter-branch-to-handle-tag-without-tagger:
  filter-branch: use hash-object instead of mktag
  filter-branch: stash away ref map in a branch
  filter-branch: preserve and restore $GIT_AUTHOR_* and $GIT_COMMITTER_*
  filter-branch: reset $GIT_* before cleaning up
maint
Junio C Hamano 8 years ago
parent
commit
386dd12b55
  1. 8
      Documentation/git-filter-branch.txt
  2. 94
      git-filter-branch.sh

8
Documentation/git-filter-branch.txt

@ -14,7 +14,7 @@ SYNOPSIS @@ -14,7 +14,7 @@ SYNOPSIS
[--commit-filter <command>] [--tag-name-filter <command>]
[--subdirectory-filter <directory>] [--prune-empty]
[--original <namespace>] [-d <directory>] [-f | --force]
[--] [<rev-list options>...]
[--state-branch <branch>] [--] [<rev-list options>...]

DESCRIPTION
-----------
@ -198,6 +198,12 @@ to other tags will be rewritten to point to the underlying commit. @@ -198,6 +198,12 @@ to other tags will be rewritten to point to the underlying commit.
directory or when there are already refs starting with
'refs/original/', unless forced.

--state-branch <branch>::
This option will cause the mapping from old to new objects to
be loaded from named branch upon startup and saved as a new
commit to that branch upon exit, enabling incremental of large
trees. If '<branch>' does not exist it will be created.

<rev-list options>...::
Arguments for 'git rev-list'. All positive refs included by
these options are rewritten. You may also specify options

94
git-filter-branch.sh

@ -86,7 +86,7 @@ USAGE="[--setup <command>] [--env-filter <command>] @@ -86,7 +86,7 @@ USAGE="[--setup <command>] [--env-filter <command>]
[--parent-filter <command>] [--msg-filter <command>]
[--commit-filter <command>] [--tag-name-filter <command>]
[--subdirectory-filter <directory>] [--original <namespace>]
[-d <directory>] [-f | --force]
[-d <directory>] [-f | --force] [--state-branch <branch>]
[--] [<rev-list options>...]"

OPTIONS_SPEC=
@ -106,6 +106,7 @@ filter_msg=cat @@ -106,6 +106,7 @@ filter_msg=cat
filter_commit=
filter_tag_name=
filter_subdir=
state_branch=
orig_namespace=refs/original/
force=
prune_empty=
@ -181,6 +182,9 @@ do @@ -181,6 +182,9 @@ do
--original)
orig_namespace=$(expr "$OPTARG/" : '\(.*[^/]\)/*$')/
;;
--state-branch)
state_branch="$OPTARG"
;;
*)
usage
;;
@ -219,6 +223,13 @@ trap 'cd "$orig_dir"; rm -rf "$tempdir"' 0 @@ -219,6 +223,13 @@ trap 'cd "$orig_dir"; rm -rf "$tempdir"' 0
ORIG_GIT_DIR="$GIT_DIR"
ORIG_GIT_WORK_TREE="$GIT_WORK_TREE"
ORIG_GIT_INDEX_FILE="$GIT_INDEX_FILE"
ORIG_GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME"
ORIG_GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL"
ORIG_GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE"
ORIG_GIT_COMMITTER_NAME="$GIT_COMMITTER_NAME"
ORIG_GIT_COMMITTER_EMAIL="$GIT_COMMITTER_EMAIL"
ORIG_GIT_COMMITTER_DATE="$GIT_COMMITTER_DATE"

GIT_WORK_TREE=.
export GIT_DIR GIT_WORK_TREE

@ -252,6 +263,26 @@ export GIT_INDEX_FILE @@ -252,6 +263,26 @@ export GIT_INDEX_FILE
# map old->new commit ids for rewriting parents
mkdir ../map || die "Could not create map/ directory"

if test -n "$state_branch"
then
state_commit=$(git rev-parse --no-flags --revs-only "$state_branch")
if test -n "$state_commit"
then
echo "Populating map from $state_branch ($state_commit)" 1>&2
perl -e'open(MAP, "-|", "git show $ARGV[0]:filter.map") or die;
while (<MAP>) {
m/(.*):(.*)/ or die;
open F, ">../map/$1" or die;
print F "$2" or die;
close(F) or die;
}
close(MAP) or die;' "$state_commit" \
|| die "Unable to load state from $state_branch:filter.map"
else
echo "Branch $state_branch does not exist. Will create" 1>&2
fi
fi

# we need "--" only if there are no path arguments in $@
nonrevs=$(git rev-parse --no-revs "$@") || exit
if test -z "$nonrevs"
@ -530,7 +561,7 @@ if [ "$filter_tag_name" ]; then @@ -530,7 +561,7 @@ if [ "$filter_tag_name" ]; then
}' \
-e '/^-----BEGIN PGP SIGNATURE-----/q' \
-e 'p' ) |
git mktag) ||
git hash-object -t tag -w --stdin) ||
die "Could not create new tag object for $ref"
if git cat-file tag "$ref" | \
sane_grep '^-----BEGIN PGP SIGNATURE-----' >/dev/null 2>&1
@ -544,12 +575,9 @@ if [ "$filter_tag_name" ]; then @@ -544,12 +575,9 @@ if [ "$filter_tag_name" ]; then
done
fi

cd "$orig_dir"
rm -rf "$tempdir"

trap - 0

unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
unset GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
unset GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_COMMITTER_DATE
test -z "$ORIG_GIT_DIR" || {
GIT_DIR="$ORIG_GIT_DIR" && export GIT_DIR
}
@ -561,6 +589,58 @@ test -z "$ORIG_GIT_INDEX_FILE" || { @@ -561,6 +589,58 @@ test -z "$ORIG_GIT_INDEX_FILE" || {
GIT_INDEX_FILE="$ORIG_GIT_INDEX_FILE" &&
export GIT_INDEX_FILE
}
test -z "$ORIG_GIT_AUTHOR_NAME" || {
GIT_AUTHOR_NAME="$ORIG_GIT_AUTHOR_NAME" &&
export GIT_AUTHOR_NAME
}
test -z "$ORIG_GIT_AUTHOR_EMAIL" || {
GIT_AUTHOR_EMAIL="$ORIG_GIT_AUTHOR_EMAIL" &&
export GIT_AUTHOR_EMAIL
}
test -z "$ORIG_GIT_AUTHOR_DATE" || {
GIT_AUTHOR_DATE="$ORIG_GIT_AUTHOR_DATE" &&
export GIT_AUTHOR_DATE
}
test -z "$ORIG_GIT_COMMITTER_NAME" || {
GIT_COMMITTER_NAME="$ORIG_GIT_COMMITTER_NAME" &&
export GIT_COMMITTER_NAME
}
test -z "$ORIG_GIT_COMMITTER_EMAIL" || {
GIT_COMMITTER_EMAIL="$ORIG_GIT_COMMITTER_EMAIL" &&
export GIT_COMMITTER_EMAIL
}
test -z "$ORIG_GIT_COMMITTER_DATE" || {
GIT_COMMITTER_DATE="$ORIG_GIT_COMMITTER_DATE" &&
export GIT_COMMITTER_DATE
}

if test -n "$state_branch"
then
echo "Saving rewrite state to $state_branch" 1>&2
state_blob=$(
perl -e'opendir D, "../map" or die;
open H, "|-", "git hash-object -w --stdin" or die;
foreach (sort readdir(D)) {
next if m/^\.\.?$/;
open F, "<../map/$_" or die;
chomp($f = <F>);
print H "$_:$f\n" or die;
}
close(H) or die;' || die "Unable to save state")
state_tree=$(/bin/echo -e "100644 blob $state_blob\tfilter.map" | git mktree)
if test -n "$state_commit"
then
state_commit=$(/bin/echo "Sync" | git commit-tree "$state_tree" -p "$state_commit")
else
state_commit=$(/bin/echo "Sync" | git commit-tree "$state_tree" )
fi
git update-ref "$state_branch" "$state_commit"
fi

cd "$orig_dir"
rm -rf "$tempdir"

trap - 0

if [ "$(is_bare_repository)" = false ]; then
git read-tree -u -m HEAD || exit

Loading…
Cancel
Save