[PATCH 2/2] filter-branch: nearest-ancestor rewriting outside subdir filter
- From
Thomas Rast <trast@student.ethz.ch>
- Date
- Oct 21, 2009, 18:16 UTC
- Message-ID
- <e1b4fcc7c167e8a7e49a2c2d6375045f6f481117.1256148512.git.trast@student.ethz.ch>
- In-Reply-To
- <95535b01e2181d321190c6d93b2834188612a389.1256148512.git.trast@student.ethz.ch>
Since a0e4639 (filter-branch: fix ref rewriting with --subdirectory-filter, 2008-08-12) git-filter-branch has done nearest-ancestor rewriting when using a --subdirectory-filter.
However, that rewriting strategy is also a useful building block in other tasks. For example, if you want to split out a subset of files from your history, you would typically call
git filter-branch <refs> -- -- <files>
But this fails for all refs that do not point directly to a commit that affects <files>, because their referenced commit will not be rewritten and the ref remains untouched.
The code was already there for the --subdirectory-filter case, so just introduce an option that enables it independently.
Signed-off-by: Thomas Rast <trast@student.ethz.ch> ---
This came up on IRC the other day (see a pattern?), when someone wanted to split out the history for a single file, and first had to point all relevant refs at the corresponding nearest relevant ancestor.
I think we could even make this option the default if it wasn't for backwards compatibility; after all, what use is rewriting the commits if you do not get a ref pointing to them?
Documentation/git-filter-branch.txt | 13 ++++++++++++- git-filter-branch.sh | 7 ++++++- t/t7003-filter-branch.sh | 18 ++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt index 2b40bab..394a77a 100644 --- a/Documentation/git-filter-branch.txt +++ b/Documentation/git-filter-branch.txt @@ -159,7 +159,18 @@ 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. The result will contain that directory (and only that) as its - project root. + project root. Implies --remap-to-ancestor. + +--remap-to-ancestor:: + Rewrite refs to the nearest rewritten ancestor instead of + ignoring them. ++ +Normally, positive refs on the command line are only changed if the +commit they point to was rewritten. However, you can limit the extent +of this rewriting by using linkgit:rev-list[1] arguments, e.g., path +limiters. Refs pointing to such excluded commits would then normally +be ignored. With this option, they are instead rewritten to point at +the nearest ancestor that was not excluded. --prune-empty:: Some kind of filters will generate empty commits, that left the tree diff --git a/git-filter-branch.sh b/git-filter-branch.sh index 3890c22..d18f82d 100755 --- a/git-filter-branch.sh +++ b/git-filter-branch.sh @@ -125,6 +125,7 @@ filter_subdir= orig_namespace=refs/original/ force= prune_empty= +remap_to_ancestor= while : do case "$1" in @@ -182,10 +183,14 @@ do ;; --subdirectory-filter) filter_subdir="$OPTARG" + remap_to_ancestor=t ;; --original) orig_namespace=$(expr "$OPTARG/" : '\(.*[^/]\)/*$')/ ;; + --remap-to-ancestor) + remap_to_ancestor=t + ;; *) usage ;; @@ -364,7 +369,7 @@ done <../revs # revision walker. Fix it by mapping these heads to the unique nearest # ancestor that survived the pruning. -if test "$filter_subdir" +if test "$remap_to_ancestor" = t then while read ref do diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index 329c851..9503875 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -288,4 +288,22 @@ test_expect_success 'Prune empty commits' ' test_cmp expect actual ' +test_expect_success '--remap-to-ancestor with filename filters' ' + git checkout master && + git reset --hard A && + test_commit add-foo foo 1 && + git branch moved-foo && + test_commit add-bar bar a && + git branch invariant && + orig_invariant=$(git rev-parse invariant) && + git branch moved-bar && + test_commit change-foo foo 2 && + git filter-branch -f --remap-to-ancestor \ + moved-foo moved-bar A..master \ + -- -- foo && + test $(git rev-parse moved-foo) = $(git rev-parse moved-bar) && + test $(git rev-parse moved-foo) = $(git rev-parse master^) && + test $orig_invariant = $(git rev-parse invariant) +' + test_done
-- 1.6.5.1.139.g12527