filter-branch: stash away ref map in a branch
With "--state-branch=<branchname>" option, the mapping from old object names and filtered ones in ./map/ directory is stashed away in the object database, and the one from the previous run is read to populate the ./map/ directory, allowing for incremental updates of large trees. Signed-off-by: Ian Campbell <ijc@hellion.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Ian Campbell committed
Sep 21, 2017 at 08:49 UTC
bd2c79fbfef894d788c256d45cef05d99442407a
2 files changed
+55
-2
Documentation/git-filter-branch.txt
+7
-1
@@ -14,7 +14,7 @@ SYNOPSIS
14
[--commit-filter <command>] [--tag-name-filter <command>]
15
[--subdirectory-filter <directory>] [--prune-empty]
16
[--original <namespace>] [-d <directory>] [-f | --force]
17
- [--] [<rev-list options>...]
17
+ [--state-branch <branch>] [--] [<rev-list options>...]
18
19
DESCRIPTION
20
-----------
@@ -198,6 +198,12 @@ to other tags will be rewritten to point to the underlying commit.
198
directory or when there are already refs starting with
199
'refs/original/', unless forced.
200
201
+--state-branch <branch>::
202
+ This option will cause the mapping from old to new objects to
203
+ be loaded from named branch upon startup and saved as a new
204
+ commit to that branch upon exit, enabling incremental of large
205
+ trees. If '<branch>' does not exist it will be created.
206
+
207
<rev-list options>...::
208
Arguments for 'git rev-list'. All positive refs included by
209
these options are rewritten. You may also specify options
git-filter-branch.sh
+48
-1
@@ -86,7 +86,7 @@ USAGE="[--setup <command>] [--env-filter <command>]
86
[--parent-filter <command>] [--msg-filter <command>]
87
[--commit-filter <command>] [--tag-name-filter <command>]
88
[--subdirectory-filter <directory>] [--original <namespace>]
89
- [-d <directory>] [-f | --force]
89
+ [-d <directory>] [-f | --force] [--state-branch <branch>]
90
[--] [<rev-list options>...]"
91
92
OPTIONS_SPEC=
@@ -106,6 +106,7 @@ filter_msg=cat
106
filter_commit=
107
filter_tag_name=
108
filter_subdir=
109
+state_branch=
110
orig_namespace=refs/original/
111
force=
112
prune_empty=
@@ -181,6 +182,9 @@ do
182
--original)
183
orig_namespace=$(expr "$OPTARG/" : '\(.*[^/]\)/*$')/
184
;;
185
+ --state-branch)
186
+ state_branch="$OPTARG"
187
+ ;;
188
*)
189
usage
190
;;
@@ -259,6 +263,26 @@ export GIT_INDEX_FILE
263
# map old->new commit ids for rewriting parents
264
mkdir ../map || die "Could not create map/ directory"
265
266
+if test -n "$state_branch"
267
+then
268
+ state_commit=$(git rev-parse --no-flags --revs-only "$state_branch")
269
+ if test -n "$state_commit"
270
+ then
271
+ echo "Populating map from $state_branch ($state_commit)" 1>&2
272
+ perl -e'open(MAP, "-|", "git show $ARGV[0]:filter.map") or die;
273
+ while (<MAP>) {
274
+ m/(.*):(.*)/ or die;
275
+ open F, ">../map/$1" or die;
276
+ print F "$2" or die;
277
+ close(F) or die;
278
+ }
279
+ close(MAP) or die;' "$state_commit" \
280
+ || die "Unable to load state from $state_branch:filter.map"
281
+ else
282
+ echo "Branch $state_branch does not exist. Will create" 1>&2
283
+ fi
284
+fi
285
+
286
# we need "--" only if there are no path arguments in $@
287
nonrevs=$(git rev-parse --no-revs "$@") || exit
288
if test -z "$nonrevs"
@@ -590,6 +614,29 @@ test -z "$ORIG_GIT_COMMITTER_DATE" || {
614
export GIT_COMMITTER_DATE
615
}
616
617
+if test -n "$state_branch"
618
+then
619
+ echo "Saving rewrite state to $state_branch" 1>&2
620
+ state_blob=$(
621
+ perl -e'opendir D, "../map" or die;
622
+ open H, "|-", "git hash-object -w --stdin" or die;
623
+ foreach (sort readdir(D)) {
624
+ next if m/^\.\.?$/;
625
+ open F, "<../map/$_" or die;
626
+ chomp($f = <F>);
627
+ print H "$_:$f\n" or die;
628
+ }
629
+ close(H) or die;' || die "Unable to save state")
630
+ state_tree=$(/bin/echo -e "100644 blob $state_blob\tfilter.map" | git mktree)
631
+ if test -n "$state_commit"
632
+ then
633
+ state_commit=$(/bin/echo "Sync" | git commit-tree "$state_tree" -p "$state_commit")
634
+ else
635
+ state_commit=$(/bin/echo "Sync" | git commit-tree "$state_tree" )
636
+ fi
637
+ git update-ref "$state_branch" "$state_commit"
638
+fi
639
+
640
cd "$orig_dir"
641
rm -rf "$tempdir"
642