Allowing for incremental updates of large trees.

I have been using this as part of the device tree extraction from the Linux
kernel source since 2013, about time I sent the patch upstream!

Signed-off-by: Ian Campbell <i...@hellion.org.uk>
---
 git-filter-branch.sh | 39 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index 3a74602ef..d07db3fee 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -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
 filter_commit=
 filter_tag_name=
 filter_subdir=
+state_branch=
 orig_namespace=refs/original/
 force=
 prune_empty=
@@ -181,6 +182,9 @@ do
        --original)
                orig_namespace=$(expr "$OPTARG/" : '\(.*[^/]\)/*$')/
                ;;
+       --state-branch)
+               state_branch="$OPTARG"
+               ;;
        *)
                usage
                ;;
@@ -252,6 +256,20 @@ export GIT_INDEX_FILE
 # map old->new commit ids for rewriting parents
 mkdir ../map || die "Could not create map/ directory"
 
+if [ -n "$state_branch" ] ; then
+       state_commit=`git show-ref -s "$state_branch"`
+       if [ -n "$state_commit" ] ; then
+               echo "Populating map from $state_branch ($state_commit)" 1>&2
+               git show "$state_commit":filter.map |
+                   perl -n -e 'm/(.*):(.*)/ or die;
+                               open F, ">../map/$1" or die;
+                               print F "$2" or die;
+                               close(F) or die'
+       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"
@@ -544,6 +562,25 @@ if [ "$filter_tag_name" ]; then
        done
 fi
 
+if [ -n "$state_branch" ] ; then
+       echo "Saving rewrite state to $state_branch" 1>&2
+       STATE_BLOB=$(ls ../map |
+           perl -n -e 'chomp();
+                       open F, "<../map/$_" or die;
+                       chomp($f = <F>); print "$_:$f\n";' |
+           git hash-object -w --stdin )
+       STATE_TREE=$(/bin/echo -e "100644 blob $STATE_BLOB\tfilter.map" | git 
mktree)
+       STATE_PARENT=$(git show-ref -s "$state_branch")
+       unset GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
+       unset GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL GIT_COMMITTER_DATE
+       if [ -n "$STATE_PARENT" ] ; then
+           STATE_COMMIT=$(/bin/echo "Sync" | git commit-tree "$STATE_TREE" -p 
"$STATE_PARENT")
+       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"
 
-- 
2.11.0

Reply via email to