diff options
author | Thomas Rast <trast@student.ethz.ch> | 2008-08-12 10:45:58 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2008-08-12 17:27:17 -0700 |
commit | a0e46390d397e71182e42930b98b6b59a1a84898 (patch) | |
tree | 9c38ceb70da87ef412ea2ce5eca887549f482a90 | |
parent | filter-branch: Extend test to show rewriting bug (diff) | |
download | tgif-a0e46390d397e71182e42930b98b6b59a1a84898.tar.xz |
filter-branch: fix ref rewriting with --subdirectory-filter
The previous ancestor discovery code failed on any refs that are
(pre-rewrite) ancestors of commits marked for rewriting. This means
that in a situation
A -- B(topic) -- C(master)
where B is dropped by --subdirectory-filter pruning, the 'topic' was
not moved up to A as intended, but left unrewritten because we asked
about 'git rev-list ^master topic', which does not return anything.
Instead, we use the straightforward
git rev-list -1 $ref -- $filter_subdir
to find the right ancestor. To justify this, note that the nearest
ancestor is unique: We use the output of
git rev-list --parents -- $filter_subdir
to rewrite commits in the first pass, before any ref rewriting. If B
is a non-merge commit, the only candidate is its parent. If it is a
merge, there are two cases:
- All sides of the merge bring the same subdirectory contents. Then
rev-list already pruned away the merge in favour for just one of its
parents, so there is only one candidate.
- Some merge sides, or the merge outcome, differ. Then the merge is
not pruned and can be rewritten directly.
So it is always safe to use rev-list -1.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rwxr-xr-x | git-filter-branch.sh | 27 | ||||
-rwxr-xr-x | t/t7003-filter-branch.sh | 2 |
2 files changed, 12 insertions, 17 deletions
diff --git a/git-filter-branch.sh b/git-filter-branch.sh index a324cf0596..a140337e35 100755 --- a/git-filter-branch.sh +++ b/git-filter-branch.sh @@ -317,24 +317,19 @@ done <../revs # In case of a subdirectory filter, it is possible that a specified head # is not in the set of rewritten commits, because it was pruned by the -# revision walker. Fix it by mapping these heads to the next rewritten -# ancestor(s), i.e. the boundaries in the set of rewritten commits. +# revision walker. Fix it by mapping these heads to the unique nearest +# ancestor that survived the pruning. -# NEEDSWORK: we should sort the unmapped refs topologically first -while read ref -do - sha1=$(git rev-parse "$ref"^0) - test -f "$workdir"/../map/$sha1 && continue - # Assign the boundarie(s) in the set of rewritten commits - # as the replacement commit(s). - # (This would look a bit nicer if --not --stdin worked.) - for p in $( (cd "$workdir"/../map; ls | sed "s/^/^/") | - git rev-list $ref --boundary --stdin | - sed -n "s/^-//p") +if test "$filter_subdir" +then + while read ref do - map $p >> "$workdir"/../map/$sha1 - done -done < "$tempdir"/heads + sha1=$(git rev-parse "$ref"^0) + test -f "$workdir"/../map/$sha1 && continue + ancestor=$(git rev-list -1 $ref -- "$filter_subdir") + test "$ancestor" && echo $(map $ancestor) >> "$workdir"/../map/$sha1 + done < "$tempdir"/heads +fi # Finally update the refs diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh index 4382baa27d..233254f2b5 100755 --- a/t/t7003-filter-branch.sh +++ b/t/t7003-filter-branch.sh @@ -101,7 +101,7 @@ test_expect_success 'filter subdirectory only' ' refs/heads/sub refs/heads/sub-earlier ' -test_expect_failure 'subdirectory filter result looks okay' ' +test_expect_success 'subdirectory filter result looks okay' ' test 2 = $(git rev-list sub | wc -l) && git show sub:new && test_must_fail git show sub:subdir && |