2018-11-05 15:30:50 +01:00
|
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
|
|
test_description='Basic filter-repo tests'
|
|
|
|
|
|
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
|
|
|
|
|
export PATH=$(dirname $TEST_DIRECTORY):$PATH # Put git-filter-repo in PATH
|
|
|
|
|
|
|
|
|
|
DATA="$TEST_DIRECTORY/t9390"
|
2019-08-19 22:36:07 +02:00
|
|
|
|
SQ="'"
|
2018-11-05 15:30:50 +01:00
|
|
|
|
|
|
|
|
|
filter_testcase() {
|
|
|
|
|
INPUT=$1
|
|
|
|
|
OUTPUT=$2
|
|
|
|
|
shift 2
|
|
|
|
|
REST=("$@")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
NAME="check: $INPUT -> $OUTPUT using '${REST[@]}'"
|
|
|
|
|
test_expect_success "$NAME" '
|
|
|
|
|
# Clean up from previous run
|
|
|
|
|
git pack-refs --all &&
|
|
|
|
|
rm .git/packed-refs &&
|
|
|
|
|
|
|
|
|
|
# Run the example
|
filter-repo: add --replace-refs option
This adds the ability to automatically add new replacement refs for each
rewritten commit (as well as delete or update replacement refs that
existed before the run). This will allow users to use either new or old
commit hashes to reference commits locally, though old commit hashes
will need to be unabbreviated. The only requirement for this to work,
is that the person who does the rewrite also needs to push the replace
refs up where other users can grab them, and users who want to use them
need to modify their fetch refspecs to grab the replace refs.
However, other tools external to git may not understand replace refs...
Tools like Gerrit and GitHub apparently do not yet natively understand
replace refs. Trying to view "commits" by the replacement ref will
yield various forms of "Not Found" in each tool. One has to instead try
to view it as a branch with an odd name (including "refs/replace/"), and
often branches are accessed via a different URL style than commits so it
becomes very non-obvious to users how to access the info associated with
an old commit hash.
* In Gerrit, instead of being able to search on the sha1sum or use a
pre-defined URL to search and auto-redirect to the appropriate code
review with
https://gerrit.SITE.COM/#/q/${OLD_SHA1SUM},n,z
one instead has to have a special plugin and go to a URL like
https://gerrit.SITE.COM/plugins/gitiles/ORG/REPO/+/refs/replace/${OLD_SHA1SUM}
but then the user isn't shown the actual code review and will need
to guess which link to click on to get to it (and it'll only be
there if the user included a Change-Id in the commit message).
* In GitHub, instead of being able to go to a URL like
https://github.SITE.COM/ORG/REPO/commit/${OLD_SHA1SUM}
one instead has to navigate based on branch using
https://github.SITE.COM/ORG/REPO/tree/refs/replace/${OLD_SHA1SUM}
but that will show a listing of commits instead of information about
a specific commit; the user has to manually click on the first commit
to get to the desired location.
For now, providing replace refs at least allows users to access
information locally using old IDs; perhaps in time as other external
tools will gain a better understanding of how to use replace refs, the
barrier to history rewrites will decrease enough that big projects that
really need it (e.g. those that have committed many sins by commiting
stupidly large useless binary blobs) can at least seriously contemplate
the undertaking. History rewrites will always have some drawbacks and
pain associated with them, as they should, but when warranted it's nice
to have transition plans that are more smooth than a massive flag day.
Signed-off-by: Elijah Newren <newren@gmail.com>
2019-05-02 19:05:15 +02:00
|
|
|
|
cat $DATA/$INPUT | git filter-repo --stdin --quiet --force --replace-refs delete-no-add "${REST[@]}" &&
|
2018-11-05 15:30:50 +01:00
|
|
|
|
|
|
|
|
|
# Compare the resulting repo to expected value
|
|
|
|
|
git fast-export --use-done-feature --all >compare &&
|
|
|
|
|
test_cmp $DATA/$OUTPUT compare
|
|
|
|
|
'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
filter_testcase basic basic-filename --path filename
|
|
|
|
|
filter_testcase basic basic-twenty --path twenty
|
|
|
|
|
filter_testcase basic basic-ten --path ten
|
2019-02-19 02:24:33 +01:00
|
|
|
|
filter_testcase basic basic-numbers --path ten --path twenty
|
|
|
|
|
filter_testcase basic basic-filename --invert-paths --path-glob 't*en*'
|
|
|
|
|
filter_testcase basic basic-numbers --invert-paths --path-regex 'f.*e.*e'
|
2019-01-29 02:26:49 +01:00
|
|
|
|
filter_testcase basic basic-mailmap --mailmap ../t9390/sample-mailmap
|
filter-repo: add text removal (or replacement) via file of expressions
Make it easy for users to search and replace text throughout the
repository history. Instead of inventing some new syntax, reuse the
same syntax used by BFG repo filter's --replace-text option, namely,
a file with one expression per line of the form
[regex:|glob:|literal:]$MATCH_EXPR[==>$REPLACEMENT_EXPR]
Where "$MATCH_EXPR" is by default considered to be literal text, but
could be a regex or a glob if the appropriate prefix is used. Also,
$REPLACEMENT_EXPR defaults to '***REMOVED***' if not specified. If
you want a literal '==>' to be part of your $MATCH_EXPR, then you
must also manually specify a replacement expression instead of taking
the default. Some examples:
sup3rs3kr3t
(replaces 'sup3rs3kr3t' with '***REMOVED***')
HeWhoShallNotBeNamed==>Voldemort
(replaces 'HeWhoShallNotBeNamed' with 'Voldemort')
very==>
(replaces 'very' with the empty string)
regex:(\d{2})/(\d{2})/(\d{4})==>\2/\1/\3
(replaces '05/17/2012' with '17/05/2012', and vice-versa)
The format for regex is as from
re.sub(<pattern>, <repl>, <string>) from
https://docs.python.org/2/library/re.html
The <string> comes from file contents of the repo, and you specify
the <pattern> and <repl>.
glob:Copy*t==>Cartel
(replaces 'Copyright' or 'Copyleft' or 'Copy my st' with 'Cartel')
Signed-off-by: Elijah Newren <newren@gmail.com>
2019-01-30 09:56:22 +01:00
|
|
|
|
filter_testcase basic basic-replace --replace-text ../t9390/sample-replace
|
2019-03-04 23:29:54 +01:00
|
|
|
|
filter_testcase empty empty-keepme --path keepme
|
2019-05-30 04:16:58 +02:00
|
|
|
|
filter_testcase empty more-empty-keepme --path keepme --prune-empty=always \
|
|
|
|
|
--prune-degenerate=always
|
|
|
|
|
filter_testcase empty less-empty-keepme --path keepme --prune-empty=never \
|
|
|
|
|
--prune-degenerate=never
|
2019-02-23 17:15:07 +01:00
|
|
|
|
filter_testcase degenerate degenerate-keepme --path moduleA/keepme
|
|
|
|
|
filter_testcase degenerate degenerate-moduleA --path moduleA
|
|
|
|
|
filter_testcase degenerate degenerate-globme --path-glob *me
|
filter-repo: add new --no-ff option
Some projects have a strict --no-ff merging policy. With the default
behavior of --prune-degenerate, we can prune merge commits in a way that
transforms the history into a fast-forward merge. Consider this
example:
* There are two independent commits or branches, named B & C, which
are both built on top of A so that history look like this diagram:
A
\ \
\ B
\
-C
* Someone runs the following sequence of commands:
* git checkout A
* git merge --no-ff B
* git merge --no-ff C
* This will result in a history that looks like:
A---AB---AC
\ \ / /
\ B /
\ /
-C-
* Later, someone comes along and runs filter-repo, specifying to
remove the only path(s) that were modified by B. That would
naturally remove commit B and the no-longer-necessary merge
commit AB. For someone using a strict no-ff policy, the desired
history is
A---AC
\ /
C
However, the default handling for --prune-degenerate would
notice that AC merely merges C into its own ancestor A, whereas
the original AC merged C into something separate (namely, AB).
So, it would say that AC has become degenerate and prune it,
leaving the simple history of
A
\
C
For projects not using a strict no-ff policy, this simpler history
is probably better, but for folks that want a strict no-ff policy,
it is unfortunate.
Provide a --no-ff option to tweak the --prune-degenerate behavior so
that it ignores the first parent being an ancestor of another parent
(leaving the first parent unpruned even if it is or becomes degenerate
in this fashion).
Signed-off-by: Elijah Newren <newren@gmail.com>
2020-01-01 19:49:56 +01:00
|
|
|
|
filter_testcase degenerate degenerate-keepme-noff --path moduleA/keepme --no-ff
|
2019-03-13 18:52:21 +01:00
|
|
|
|
filter_testcase unusual unusual-filtered --path ''
|
2019-12-11 05:27:53 +01:00
|
|
|
|
filter_testcase unusual unusual-mailmap --mailmap ../t9390/sample-mailmap
|
2018-11-05 15:30:50 +01:00
|
|
|
|
|
2019-03-07 19:49:39 +01:00
|
|
|
|
test_expect_success 'setup path_rename' '
|
|
|
|
|
test_create_repo path_rename &&
|
|
|
|
|
(
|
|
|
|
|
cd path_rename &&
|
|
|
|
|
mkdir sequences values &&
|
|
|
|
|
test_seq 1 10 >sequences/tiny &&
|
|
|
|
|
test_seq 100 110 >sequences/intermediate &&
|
|
|
|
|
test_seq 1000 1010 >sequences/large &&
|
|
|
|
|
test_seq 1000 1010 >values/large &&
|
|
|
|
|
test_seq 10000 10010 >values/huge &&
|
|
|
|
|
git add sequences values &&
|
|
|
|
|
git commit -m initial &&
|
|
|
|
|
|
|
|
|
|
git mv sequences/tiny sequences/small &&
|
|
|
|
|
cp sequences/intermediate sequences/medium &&
|
|
|
|
|
echo 10011 >values/huge &&
|
|
|
|
|
git add sequences values &&
|
|
|
|
|
git commit -m updates &&
|
|
|
|
|
|
|
|
|
|
git rm sequences/intermediate &&
|
|
|
|
|
echo 11 >sequences/small &&
|
|
|
|
|
git add sequences/small &&
|
|
|
|
|
git commit -m changes &&
|
|
|
|
|
|
|
|
|
|
echo 1011 >sequences/medium &&
|
|
|
|
|
git add sequences/medium &&
|
|
|
|
|
git commit -m final
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
test_expect_success '--path-rename sequences/tiny:sequences/small' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/path_rename path_rename_single &&
|
|
|
|
|
cd path_rename_single &&
|
|
|
|
|
git filter-repo --path-rename sequences/tiny:sequences/small &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 7 filenames &&
|
|
|
|
|
! grep sequences/tiny filenames &&
|
|
|
|
|
git rev-parse HEAD~3:sequences/small
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
test_expect_success '--path-rename sequences:numbers' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/path_rename path_rename_dir &&
|
|
|
|
|
cd path_rename_dir &&
|
|
|
|
|
git filter-repo --path-rename sequences:numbers &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 8 filenames &&
|
|
|
|
|
! grep sequences/ filenames &&
|
|
|
|
|
grep numbers/ filenames &&
|
|
|
|
|
grep values/ filenames
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
test_expect_success '--path-rename-prefix values:numbers' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/path_rename path_rename_dir_2 &&
|
|
|
|
|
cd path_rename_dir_2 &&
|
|
|
|
|
git filter-repo --path-rename values/:numbers/ &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 8 filenames &&
|
|
|
|
|
! grep values/ filenames &&
|
|
|
|
|
grep sequences/ filenames &&
|
|
|
|
|
grep numbers/ filenames
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
test_expect_success '--path-rename squashing' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/path_rename path_rename_squash &&
|
|
|
|
|
cd path_rename_squash &&
|
|
|
|
|
git filter-repo \
|
|
|
|
|
--path-rename sequences/tiny:sequences/small \
|
|
|
|
|
--path-rename sequences:numbers \
|
|
|
|
|
--path-rename values:numbers \
|
|
|
|
|
--path-rename numbers/intermediate:numbers/medium &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
# Just small, medium, large, huge, and a blank line...
|
|
|
|
|
test_line_count = 5 filenames &&
|
|
|
|
|
! grep sequences/ filenames &&
|
|
|
|
|
! grep values/ filenames &&
|
|
|
|
|
grep numbers/ filenames
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
test_expect_success '--path-rename inability to squash' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/path_rename path_rename_bad_squash &&
|
|
|
|
|
cd path_rename_bad_squash &&
|
|
|
|
|
test_must_fail git filter-repo \
|
|
|
|
|
--path-rename values/large:values/big \
|
|
|
|
|
--path-rename values/huge:values/big 2>../err &&
|
|
|
|
|
test_i18ngrep "File renaming caused colliding pathnames" ../err
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-05-21 16:37:59 +02:00
|
|
|
|
test_expect_success '--paths-from-file' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/path_rename paths_from_file &&
|
|
|
|
|
cd paths_from_file &&
|
|
|
|
|
|
|
|
|
|
cat >../path_changes <<-EOF &&
|
|
|
|
|
literal:values/huge
|
|
|
|
|
values/huge==>values/gargantuan
|
|
|
|
|
glob:*rge
|
|
|
|
|
|
|
|
|
|
regex:.*med.*
|
|
|
|
|
regex:^([^/]*)/(.*)ge$==>\2/\1/ge
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
git filter-repo --paths-from-file ../path_changes &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
# intermediate, medium, two larges, gargantuan, and a blank line
|
|
|
|
|
test_line_count = 6 filenames &&
|
|
|
|
|
! grep sequences/tiny filenames &&
|
|
|
|
|
grep sequences/intermediate filenames &&
|
|
|
|
|
grep lar/sequences/ge filenames &&
|
|
|
|
|
grep lar/values/ge filenames &&
|
|
|
|
|
grep values/gargantuan filenames &&
|
|
|
|
|
! grep sequences/small filenames &&
|
|
|
|
|
grep sequences/medium filenames &&
|
|
|
|
|
|
|
|
|
|
rm ../path_changes
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
filter-repo: add --replace-refs option
This adds the ability to automatically add new replacement refs for each
rewritten commit (as well as delete or update replacement refs that
existed before the run). This will allow users to use either new or old
commit hashes to reference commits locally, though old commit hashes
will need to be unabbreviated. The only requirement for this to work,
is that the person who does the rewrite also needs to push the replace
refs up where other users can grab them, and users who want to use them
need to modify their fetch refspecs to grab the replace refs.
However, other tools external to git may not understand replace refs...
Tools like Gerrit and GitHub apparently do not yet natively understand
replace refs. Trying to view "commits" by the replacement ref will
yield various forms of "Not Found" in each tool. One has to instead try
to view it as a branch with an odd name (including "refs/replace/"), and
often branches are accessed via a different URL style than commits so it
becomes very non-obvious to users how to access the info associated with
an old commit hash.
* In Gerrit, instead of being able to search on the sha1sum or use a
pre-defined URL to search and auto-redirect to the appropriate code
review with
https://gerrit.SITE.COM/#/q/${OLD_SHA1SUM},n,z
one instead has to have a special plugin and go to a URL like
https://gerrit.SITE.COM/plugins/gitiles/ORG/REPO/+/refs/replace/${OLD_SHA1SUM}
but then the user isn't shown the actual code review and will need
to guess which link to click on to get to it (and it'll only be
there if the user included a Change-Id in the commit message).
* In GitHub, instead of being able to go to a URL like
https://github.SITE.COM/ORG/REPO/commit/${OLD_SHA1SUM}
one instead has to navigate based on branch using
https://github.SITE.COM/ORG/REPO/tree/refs/replace/${OLD_SHA1SUM}
but that will show a listing of commits instead of information about
a specific commit; the user has to manually click on the first commit
to get to the desired location.
For now, providing replace refs at least allows users to access
information locally using old IDs; perhaps in time as other external
tools will gain a better understanding of how to use replace refs, the
barrier to history rewrites will decrease enough that big projects that
really need it (e.g. those that have committed many sins by commiting
stupidly large useless binary blobs) can at least seriously contemplate
the undertaking. History rewrites will always have some drawbacks and
pain associated with them, as they should, but when warranted it's nice
to have transition plans that are more smooth than a massive flag day.
Signed-off-by: Elijah Newren <newren@gmail.com>
2019-05-02 19:05:15 +02:00
|
|
|
|
test_expect_success 'setup metasyntactic repo' '
|
2019-03-08 02:38:12 +01:00
|
|
|
|
test_create_repo metasyntactic &&
|
2019-03-08 01:14:35 +01:00
|
|
|
|
(
|
2019-03-08 02:38:12 +01:00
|
|
|
|
cd metasyntactic &&
|
|
|
|
|
weird_name=$(printf "file\tna\nme") &&
|
|
|
|
|
echo "funny" >"$weird_name" &&
|
2019-03-08 01:14:35 +01:00
|
|
|
|
mkdir numbers &&
|
|
|
|
|
test_seq 1 10 >numbers/small &&
|
|
|
|
|
test_seq 100 110 >numbers/medium &&
|
2019-03-08 02:38:12 +01:00
|
|
|
|
git add "$weird_name" numbers &&
|
2019-03-08 01:14:35 +01:00
|
|
|
|
git commit -m initial &&
|
|
|
|
|
git tag v1.0 &&
|
2019-03-08 02:38:12 +01:00
|
|
|
|
git tag -a -m v1.1 v1.1 &&
|
2019-03-08 01:14:35 +01:00
|
|
|
|
|
|
|
|
|
mkdir words &&
|
|
|
|
|
echo foo >words/important &&
|
|
|
|
|
echo bar >words/whimsical &&
|
|
|
|
|
echo baz >words/sequences &&
|
|
|
|
|
git add words &&
|
|
|
|
|
git commit -m some.words &&
|
|
|
|
|
git branch another_branch &&
|
|
|
|
|
git tag v2.0 &&
|
|
|
|
|
|
|
|
|
|
echo spam >words/to &&
|
2019-03-08 02:38:12 +01:00
|
|
|
|
echo eggs >words/know &&
|
2019-03-08 01:14:35 +01:00
|
|
|
|
git add words
|
2019-03-08 02:38:12 +01:00
|
|
|
|
git rm "$weird_name" &&
|
2019-03-08 01:14:35 +01:00
|
|
|
|
git commit -m more.words &&
|
|
|
|
|
git tag -a -m "Look, ma, I made a tag" v3.0
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-08 02:38:12 +01:00
|
|
|
|
test_expect_success '--tag-rename' '
|
2019-03-08 01:14:35 +01:00
|
|
|
|
(
|
2019-03-08 02:38:12 +01:00
|
|
|
|
git clone file://"$(pwd)"/metasyntactic tag_rename &&
|
|
|
|
|
cd tag_rename &&
|
2019-03-08 01:14:35 +01:00
|
|
|
|
git filter-repo \
|
|
|
|
|
--tag-rename "":"myrepo-" \
|
|
|
|
|
--path words &&
|
|
|
|
|
test_must_fail git cat-file -t v1.0 &&
|
2019-03-08 02:38:12 +01:00
|
|
|
|
test_must_fail git cat-file -t v1.1 &&
|
2019-03-08 01:14:35 +01:00
|
|
|
|
test_must_fail git cat-file -t v2.0 &&
|
|
|
|
|
test_must_fail git cat-file -t v3.0 &&
|
|
|
|
|
test_must_fail git cat-file -t myrepo-v1.0 &&
|
2019-03-08 02:38:12 +01:00
|
|
|
|
test_must_fail git cat-file -t myrepo-v1.1 &&
|
2019-03-08 01:14:35 +01:00
|
|
|
|
test $(git cat-file -t myrepo-v2.0) = commit &&
|
|
|
|
|
test $(git cat-file -t myrepo-v3.0) = tag
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-08 02:38:12 +01:00
|
|
|
|
test_expect_success '--subdirectory-filter' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/metasyntactic subdir_filter &&
|
|
|
|
|
cd subdir_filter &&
|
|
|
|
|
git filter-repo \
|
|
|
|
|
--subdirectory-filter words &&
|
|
|
|
|
git cat-file --batch-check --batch-all-objects >all-objs &&
|
|
|
|
|
test_line_count = 10 all-objs &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 6 filenames &&
|
|
|
|
|
grep ^important$ filenames &&
|
|
|
|
|
test_must_fail git cat-file -t v1.0 &&
|
|
|
|
|
test_must_fail git cat-file -t v1.1 &&
|
|
|
|
|
test $(git cat-file -t v2.0) = commit &&
|
|
|
|
|
test $(git cat-file -t v3.0) = tag
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2020-01-22 01:51:28 +01:00
|
|
|
|
test_expect_success '--subdirectory-filter with trailing slash' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/metasyntactic subdir_filter_2 &&
|
|
|
|
|
cd subdir_filter_2 &&
|
|
|
|
|
git filter-repo \
|
|
|
|
|
--subdirectory-filter words/ &&
|
|
|
|
|
git cat-file --batch-check --batch-all-objects >all-objs &&
|
|
|
|
|
test_line_count = 10 all-objs &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 6 filenames &&
|
|
|
|
|
grep ^important$ filenames &&
|
|
|
|
|
test_must_fail git cat-file -t v1.0 &&
|
|
|
|
|
test_must_fail git cat-file -t v1.1 &&
|
|
|
|
|
test $(git cat-file -t v2.0) = commit &&
|
|
|
|
|
test $(git cat-file -t v3.0) = tag
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-08 02:38:12 +01:00
|
|
|
|
test_expect_success '--to-subdirectory-filter' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/metasyntactic to_subdir_filter &&
|
|
|
|
|
cd to_subdir_filter &&
|
|
|
|
|
git filter-repo \
|
2020-01-22 01:51:28 +01:00
|
|
|
|
--to-subdirectory-filter mysubdir/ &&
|
2019-03-08 02:38:12 +01:00
|
|
|
|
git cat-file --batch-check --batch-all-objects >all-objs &&
|
|
|
|
|
test_line_count = 22 all-objs &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 9 filenames &&
|
|
|
|
|
grep "^\"mysubdir/file\\\\tna\\\\nme\"$" filenames &&
|
|
|
|
|
grep ^mysubdir/words/important$ filenames &&
|
|
|
|
|
test $(git cat-file -t v1.0) = commit &&
|
|
|
|
|
test $(git cat-file -t v1.1) = tag &&
|
|
|
|
|
test $(git cat-file -t v2.0) = commit &&
|
|
|
|
|
test $(git cat-file -t v3.0) = tag
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-05-17 20:01:24 +02:00
|
|
|
|
test_expect_success '--use-base-name' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/metasyntactic use_base_name &&
|
|
|
|
|
cd use_base_name &&
|
|
|
|
|
git filter-repo --path small --path important --use-base-name &&
|
|
|
|
|
git cat-file --batch-check --batch-all-objects >all-objs &&
|
|
|
|
|
test_line_count = 10 all-objs &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 3 filenames &&
|
|
|
|
|
grep ^numbers/small$ filenames &&
|
|
|
|
|
grep ^words/important$ filenames &&
|
|
|
|
|
test $(git cat-file -t v1.0) = commit &&
|
|
|
|
|
test $(git cat-file -t v1.1) = tag &&
|
|
|
|
|
test $(git cat-file -t v2.0) = commit &&
|
|
|
|
|
test $(git cat-file -t v3.0) = tag
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-09 23:24:53 +01:00
|
|
|
|
test_expect_success 'refs/replace/ to skip a parent' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/metasyntactic replace_skip_ref &&
|
|
|
|
|
cd replace_skip_ref &&
|
|
|
|
|
|
|
|
|
|
git tag -d v2.0 &&
|
|
|
|
|
git replace HEAD~1 HEAD~2 &&
|
|
|
|
|
|
filter-repo: add --replace-refs option
This adds the ability to automatically add new replacement refs for each
rewritten commit (as well as delete or update replacement refs that
existed before the run). This will allow users to use either new or old
commit hashes to reference commits locally, though old commit hashes
will need to be unabbreviated. The only requirement for this to work,
is that the person who does the rewrite also needs to push the replace
refs up where other users can grab them, and users who want to use them
need to modify their fetch refspecs to grab the replace refs.
However, other tools external to git may not understand replace refs...
Tools like Gerrit and GitHub apparently do not yet natively understand
replace refs. Trying to view "commits" by the replacement ref will
yield various forms of "Not Found" in each tool. One has to instead try
to view it as a branch with an odd name (including "refs/replace/"), and
often branches are accessed via a different URL style than commits so it
becomes very non-obvious to users how to access the info associated with
an old commit hash.
* In Gerrit, instead of being able to search on the sha1sum or use a
pre-defined URL to search and auto-redirect to the appropriate code
review with
https://gerrit.SITE.COM/#/q/${OLD_SHA1SUM},n,z
one instead has to have a special plugin and go to a URL like
https://gerrit.SITE.COM/plugins/gitiles/ORG/REPO/+/refs/replace/${OLD_SHA1SUM}
but then the user isn't shown the actual code review and will need
to guess which link to click on to get to it (and it'll only be
there if the user included a Change-Id in the commit message).
* In GitHub, instead of being able to go to a URL like
https://github.SITE.COM/ORG/REPO/commit/${OLD_SHA1SUM}
one instead has to navigate based on branch using
https://github.SITE.COM/ORG/REPO/tree/refs/replace/${OLD_SHA1SUM}
but that will show a listing of commits instead of information about
a specific commit; the user has to manually click on the first commit
to get to the desired location.
For now, providing replace refs at least allows users to access
information locally using old IDs; perhaps in time as other external
tools will gain a better understanding of how to use replace refs, the
barrier to history rewrites will decrease enough that big projects that
really need it (e.g. those that have committed many sins by commiting
stupidly large useless binary blobs) can at least seriously contemplate
the undertaking. History rewrites will always have some drawbacks and
pain associated with them, as they should, but when warranted it's nice
to have transition plans that are more smooth than a massive flag day.
Signed-off-by: Elijah Newren <newren@gmail.com>
2019-05-02 19:05:15 +02:00
|
|
|
|
git filter-repo --replace-refs delete-no-add --path "" --force &&
|
2019-03-09 23:24:53 +01:00
|
|
|
|
test $(git rev-list --count HEAD) = 2 &&
|
|
|
|
|
git cat-file --batch-check --batch-all-objects >all-objs &&
|
|
|
|
|
test_line_count = 16 all-objs &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 9 filenames &&
|
|
|
|
|
test $(git cat-file -t v1.0) = commit &&
|
|
|
|
|
test $(git cat-file -t v1.1) = tag &&
|
|
|
|
|
test_must_fail git cat-file -t v2.0 &&
|
|
|
|
|
test $(git cat-file -t v3.0) = tag
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
test_expect_success 'refs/replace/ to add more initial history' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/metasyntactic replace_add_refs &&
|
|
|
|
|
cd replace_add_refs &&
|
|
|
|
|
|
|
|
|
|
git checkout --orphan new_root &&
|
|
|
|
|
rm .git/index &&
|
|
|
|
|
git add numbers/small &&
|
|
|
|
|
git clean -fd &&
|
|
|
|
|
git commit -m new.root &&
|
|
|
|
|
|
|
|
|
|
git replace --graft master~2 new_root &&
|
|
|
|
|
git checkout master &&
|
|
|
|
|
|
|
|
|
|
git --no-replace-objects cat-file -p master~2 >grandparent &&
|
|
|
|
|
! grep parent grandparent &&
|
|
|
|
|
|
filter-repo: add --replace-refs option
This adds the ability to automatically add new replacement refs for each
rewritten commit (as well as delete or update replacement refs that
existed before the run). This will allow users to use either new or old
commit hashes to reference commits locally, though old commit hashes
will need to be unabbreviated. The only requirement for this to work,
is that the person who does the rewrite also needs to push the replace
refs up where other users can grab them, and users who want to use them
need to modify their fetch refspecs to grab the replace refs.
However, other tools external to git may not understand replace refs...
Tools like Gerrit and GitHub apparently do not yet natively understand
replace refs. Trying to view "commits" by the replacement ref will
yield various forms of "Not Found" in each tool. One has to instead try
to view it as a branch with an odd name (including "refs/replace/"), and
often branches are accessed via a different URL style than commits so it
becomes very non-obvious to users how to access the info associated with
an old commit hash.
* In Gerrit, instead of being able to search on the sha1sum or use a
pre-defined URL to search and auto-redirect to the appropriate code
review with
https://gerrit.SITE.COM/#/q/${OLD_SHA1SUM},n,z
one instead has to have a special plugin and go to a URL like
https://gerrit.SITE.COM/plugins/gitiles/ORG/REPO/+/refs/replace/${OLD_SHA1SUM}
but then the user isn't shown the actual code review and will need
to guess which link to click on to get to it (and it'll only be
there if the user included a Change-Id in the commit message).
* In GitHub, instead of being able to go to a URL like
https://github.SITE.COM/ORG/REPO/commit/${OLD_SHA1SUM}
one instead has to navigate based on branch using
https://github.SITE.COM/ORG/REPO/tree/refs/replace/${OLD_SHA1SUM}
but that will show a listing of commits instead of information about
a specific commit; the user has to manually click on the first commit
to get to the desired location.
For now, providing replace refs at least allows users to access
information locally using old IDs; perhaps in time as other external
tools will gain a better understanding of how to use replace refs, the
barrier to history rewrites will decrease enough that big projects that
really need it (e.g. those that have committed many sins by commiting
stupidly large useless binary blobs) can at least seriously contemplate
the undertaking. History rewrites will always have some drawbacks and
pain associated with them, as they should, but when warranted it's nice
to have transition plans that are more smooth than a massive flag day.
Signed-off-by: Elijah Newren <newren@gmail.com>
2019-05-02 19:05:15 +02:00
|
|
|
|
git filter-repo --replace-refs delete-no-add --path "" --force &&
|
2019-03-09 23:24:53 +01:00
|
|
|
|
|
|
|
|
|
git --no-replace-objects cat-file -p master~2 >new-grandparent &&
|
|
|
|
|
grep parent new-grandparent &&
|
|
|
|
|
|
|
|
|
|
test $(git rev-list --count HEAD) = 4 &&
|
|
|
|
|
git cat-file --batch-check --batch-all-objects >all-objs &&
|
|
|
|
|
test_line_count = 22 all-objs &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 9 filenames &&
|
|
|
|
|
test $(git cat-file -t v1.0) = commit &&
|
|
|
|
|
test $(git cat-file -t v1.1) = tag &&
|
|
|
|
|
test $(git cat-file -t v2.0) = commit &&
|
|
|
|
|
test $(git cat-file -t v3.0) = tag
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
filter-repo: add --replace-refs option
This adds the ability to automatically add new replacement refs for each
rewritten commit (as well as delete or update replacement refs that
existed before the run). This will allow users to use either new or old
commit hashes to reference commits locally, though old commit hashes
will need to be unabbreviated. The only requirement for this to work,
is that the person who does the rewrite also needs to push the replace
refs up where other users can grab them, and users who want to use them
need to modify their fetch refspecs to grab the replace refs.
However, other tools external to git may not understand replace refs...
Tools like Gerrit and GitHub apparently do not yet natively understand
replace refs. Trying to view "commits" by the replacement ref will
yield various forms of "Not Found" in each tool. One has to instead try
to view it as a branch with an odd name (including "refs/replace/"), and
often branches are accessed via a different URL style than commits so it
becomes very non-obvious to users how to access the info associated with
an old commit hash.
* In Gerrit, instead of being able to search on the sha1sum or use a
pre-defined URL to search and auto-redirect to the appropriate code
review with
https://gerrit.SITE.COM/#/q/${OLD_SHA1SUM},n,z
one instead has to have a special plugin and go to a URL like
https://gerrit.SITE.COM/plugins/gitiles/ORG/REPO/+/refs/replace/${OLD_SHA1SUM}
but then the user isn't shown the actual code review and will need
to guess which link to click on to get to it (and it'll only be
there if the user included a Change-Id in the commit message).
* In GitHub, instead of being able to go to a URL like
https://github.SITE.COM/ORG/REPO/commit/${OLD_SHA1SUM}
one instead has to navigate based on branch using
https://github.SITE.COM/ORG/REPO/tree/refs/replace/${OLD_SHA1SUM}
but that will show a listing of commits instead of information about
a specific commit; the user has to manually click on the first commit
to get to the desired location.
For now, providing replace refs at least allows users to access
information locally using old IDs; perhaps in time as other external
tools will gain a better understanding of how to use replace refs, the
barrier to history rewrites will decrease enough that big projects that
really need it (e.g. those that have committed many sins by commiting
stupidly large useless binary blobs) can at least seriously contemplate
the undertaking. History rewrites will always have some drawbacks and
pain associated with them, as they should, but when warranted it's nice
to have transition plans that are more smooth than a massive flag day.
Signed-off-by: Elijah Newren <newren@gmail.com>
2019-05-02 19:05:15 +02:00
|
|
|
|
test_expect_success 'creation/deletion/updating of replace refs' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/metasyntactic replace_handling &&
|
|
|
|
|
|
|
|
|
|
# Same setup as "refs/replace/ to skip a parent", so we
|
|
|
|
|
# do not have to check that replacement refs were used
|
|
|
|
|
# correctly in the rewrite, just that replacement refs were
|
|
|
|
|
# deleted, added, or updated correctly.
|
|
|
|
|
cd replace_handling &&
|
|
|
|
|
git tag -d v2.0 &&
|
|
|
|
|
master=$(git rev-parse master) &&
|
|
|
|
|
master_1=$(git rev-parse master~1) &&
|
|
|
|
|
master_2=$(git rev-parse master~2) &&
|
|
|
|
|
git replace HEAD~1 HEAD~2 &&
|
|
|
|
|
cd .. &&
|
|
|
|
|
|
|
|
|
|
mkdir -p test_replace_refs &&
|
|
|
|
|
cd test_replace_refs &&
|
|
|
|
|
|
|
|
|
|
rsync -a --delete ../replace_handling/ ./ &&
|
|
|
|
|
git filter-repo --replace-refs delete-no-add --path-rename numbers:counting &&
|
|
|
|
|
git show-ref >output &&
|
|
|
|
|
! grep refs/replace/ output &&
|
|
|
|
|
|
|
|
|
|
rsync -a --delete ../replace_handling/ ./ &&
|
|
|
|
|
git filter-repo --replace-refs delete-and-add --path-rename numbers:counting &&
|
|
|
|
|
echo "$(git rev-parse master) refs/replace/$master" >out &&
|
|
|
|
|
echo "$(git rev-parse master~1) refs/replace/$master_1" >>out &&
|
|
|
|
|
echo "$(git rev-parse master~1) refs/replace/$master_2" >>out &&
|
|
|
|
|
sort -k 2 out >expect &&
|
|
|
|
|
git show-ref | grep refs/replace/ >output &&
|
|
|
|
|
test_cmp output expect &&
|
|
|
|
|
|
|
|
|
|
rsync -a --delete ../replace_handling/ ./ &&
|
|
|
|
|
git filter-repo --replace-refs update-no-add --path-rename numbers:counting &&
|
|
|
|
|
echo "$(git rev-parse master~1) refs/replace/$master_1" >expect &&
|
|
|
|
|
git show-ref | grep refs/replace/ >output &&
|
|
|
|
|
test_cmp output expect &&
|
|
|
|
|
|
|
|
|
|
rsync -a --delete ../replace_handling/ ./ &&
|
|
|
|
|
git filter-repo --replace-refs update-or-add --path-rename numbers:counting &&
|
|
|
|
|
echo "$(git rev-parse master) refs/replace/$master" >>out &&
|
|
|
|
|
echo "$(git rev-parse master~1) refs/replace/$master_1" >>out &&
|
|
|
|
|
sort -k 2 out >expect &&
|
|
|
|
|
git show-ref | grep refs/replace/ >output &&
|
|
|
|
|
test_cmp output expect &&
|
|
|
|
|
|
|
|
|
|
rsync -a --delete ../replace_handling/ ./ &&
|
|
|
|
|
git filter-repo --replace-refs update-and-add --path-rename numbers:counting &&
|
|
|
|
|
echo "$(git rev-parse master) refs/replace/$master" >>out &&
|
|
|
|
|
echo "$(git rev-parse master~1) refs/replace/$master_1" >>out &&
|
|
|
|
|
echo "$(git rev-parse master~1) refs/replace/$master_2" >>out &&
|
|
|
|
|
sort -k 2 out >expect &&
|
|
|
|
|
git show-ref | grep refs/replace/ >output &&
|
|
|
|
|
test_cmp output expect
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-13 15:39:33 +01:00
|
|
|
|
test_expect_success '--debug' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/metasyntactic debug &&
|
|
|
|
|
cd debug &&
|
|
|
|
|
|
|
|
|
|
git filter-repo --path words --debug &&
|
|
|
|
|
|
|
|
|
|
test $(git rev-list --count HEAD) = 2 &&
|
|
|
|
|
git cat-file --batch-check --batch-all-objects >all-objs &&
|
|
|
|
|
test_line_count = 12 all-objs &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 6 filenames &&
|
|
|
|
|
|
|
|
|
|
test_path_is_file .git/filter-repo/fast-export.original &&
|
|
|
|
|
grep "^commit " .git/filter-repo/fast-export.original >out &&
|
|
|
|
|
test_line_count = 3 out &&
|
|
|
|
|
test_path_is_file .git/filter-repo/fast-export.filtered &&
|
|
|
|
|
grep "^commit " .git/filter-repo/fast-export.filtered >out &&
|
|
|
|
|
test_line_count = 2 out
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
test_expect_success '--dry-run' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/metasyntactic dry_run &&
|
|
|
|
|
cd dry_run &&
|
|
|
|
|
|
|
|
|
|
git filter-repo --path words --dry-run &&
|
|
|
|
|
|
|
|
|
|
git show-ref | grep master >out &&
|
|
|
|
|
test_line_count = 2 out &&
|
|
|
|
|
awk "{print \$1}" out | uniq >out2 &&
|
2019-12-11 05:41:37 +01:00
|
|
|
|
test_line_count = 1 out2 &&
|
|
|
|
|
|
|
|
|
|
test $(git rev-list --count HEAD) = 3 &&
|
|
|
|
|
git cat-file --batch-check --batch-all-objects >all-objs &&
|
|
|
|
|
test_line_count = 19 all-objs &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 9 filenames &&
|
|
|
|
|
|
|
|
|
|
test_path_is_file .git/filter-repo/fast-export.original &&
|
|
|
|
|
grep "^commit " .git/filter-repo/fast-export.original >out &&
|
|
|
|
|
test_line_count = 3 out &&
|
|
|
|
|
test_path_is_file .git/filter-repo/fast-export.filtered &&
|
|
|
|
|
grep "^commit " .git/filter-repo/fast-export.filtered >out &&
|
|
|
|
|
test_line_count = 2 out
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
test_expect_success '--dry-run --debug' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/metasyntactic dry_run_debug &&
|
|
|
|
|
cd dry_run_debug &&
|
|
|
|
|
|
|
|
|
|
git filter-repo --path words --dry-run --debug &&
|
|
|
|
|
|
|
|
|
|
git show-ref | grep master >out &&
|
|
|
|
|
test_line_count = 2 out &&
|
|
|
|
|
awk "{print \$1}" out | uniq >out2 &&
|
2019-03-13 15:39:33 +01:00
|
|
|
|
test_line_count = 1 out2 &&
|
|
|
|
|
|
|
|
|
|
test $(git rev-list --count HEAD) = 3 &&
|
|
|
|
|
git cat-file --batch-check --batch-all-objects >all-objs &&
|
|
|
|
|
test_line_count = 19 all-objs &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 9 filenames &&
|
|
|
|
|
|
|
|
|
|
test_path_is_file .git/filter-repo/fast-export.original &&
|
|
|
|
|
grep "^commit " .git/filter-repo/fast-export.original >out &&
|
|
|
|
|
test_line_count = 3 out &&
|
|
|
|
|
test_path_is_file .git/filter-repo/fast-export.filtered &&
|
|
|
|
|
grep "^commit " .git/filter-repo/fast-export.filtered >out &&
|
|
|
|
|
test_line_count = 2 out
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
test_expect_success '--dry-run --stdin' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/metasyntactic dry_run_stdin &&
|
|
|
|
|
cd dry_run_stdin &&
|
|
|
|
|
|
|
|
|
|
git fast-export --all | git filter-repo --path words --dry-run --stdin &&
|
|
|
|
|
|
|
|
|
|
git show-ref | grep master >out &&
|
|
|
|
|
test_line_count = 2 out &&
|
|
|
|
|
awk "{print \$1}" out | uniq >out2 &&
|
|
|
|
|
test_line_count = 1 out2 &&
|
|
|
|
|
|
|
|
|
|
test $(git rev-list --count HEAD) = 3 &&
|
|
|
|
|
git cat-file --batch-check --batch-all-objects >all-objs &&
|
|
|
|
|
test_line_count = 19 all-objs &&
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >filenames &&
|
|
|
|
|
test_line_count = 9 filenames &&
|
|
|
|
|
|
|
|
|
|
test_path_is_missing .git/filter-repo/fast-export.original &&
|
|
|
|
|
test_path_is_file .git/filter-repo/fast-export.filtered &&
|
|
|
|
|
grep "^commit " .git/filter-repo/fast-export.filtered >out &&
|
|
|
|
|
test_line_count = 2 out
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-11 21:31:22 +01:00
|
|
|
|
test_expect_success 'setup analyze_me' '
|
|
|
|
|
test_create_repo analyze_me &&
|
|
|
|
|
(
|
|
|
|
|
cd analyze_me &&
|
|
|
|
|
mkdir numbers words &&
|
|
|
|
|
test_seq 1 10 >numbers/small.num &&
|
|
|
|
|
test_seq 100 110 >numbers/medium.num &&
|
|
|
|
|
echo spam >words/to &&
|
|
|
|
|
echo eggs >words/know &&
|
|
|
|
|
echo rename a lot >fickle &&
|
|
|
|
|
git add numbers words fickle &&
|
|
|
|
|
test_tick &&
|
|
|
|
|
git commit -m initial &&
|
|
|
|
|
|
2020-02-07 23:19:51 +01:00
|
|
|
|
git branch modify-fickle &&
|
2019-03-11 21:31:22 +01:00
|
|
|
|
git branch other &&
|
|
|
|
|
git mv fickle capricious &&
|
|
|
|
|
test_tick &&
|
|
|
|
|
git commit -m "rename on main branch" &&
|
|
|
|
|
|
|
|
|
|
git checkout other &&
|
|
|
|
|
echo random other change >whatever &&
|
|
|
|
|
git add whatever &&
|
|
|
|
|
git mv fickle capricious &&
|
|
|
|
|
test_tick &&
|
|
|
|
|
git commit -m "rename on other branch" &&
|
|
|
|
|
|
|
|
|
|
git checkout master &&
|
|
|
|
|
git merge --no-commit other &&
|
|
|
|
|
git mv capricious mercurial &&
|
|
|
|
|
test_tick &&
|
|
|
|
|
git commit &&
|
|
|
|
|
|
|
|
|
|
git mv words sequence &&
|
|
|
|
|
test_tick &&
|
|
|
|
|
git commit -m now.sequence &&
|
|
|
|
|
|
|
|
|
|
git rm -rf numbers &&
|
|
|
|
|
test_tick &&
|
|
|
|
|
git commit -m remove.words &&
|
|
|
|
|
|
|
|
|
|
mkdir words &&
|
|
|
|
|
echo no >words/know &&
|
|
|
|
|
git add words/know &&
|
|
|
|
|
test_tick &&
|
|
|
|
|
git commit -m "Recreated file previously renamed" &&
|
|
|
|
|
|
|
|
|
|
echo "160000 deadbeefdeadbeefdeadbeefdeadbeefdeadbeefQfake_submodule" | q_to_tab | git update-index --index-info &&
|
|
|
|
|
test_tick &&
|
|
|
|
|
git commit -m "Add a fake submodule" &&
|
|
|
|
|
|
|
|
|
|
test_tick &&
|
|
|
|
|
git commit --allow-empty -m "Final commit, empty" &&
|
|
|
|
|
|
2020-02-07 23:19:51 +01:00
|
|
|
|
git checkout modify-fickle &&
|
|
|
|
|
echo "more stuff" >>fickle &&
|
|
|
|
|
test_tick &&
|
|
|
|
|
git commit -am "another more stuff commit" &&
|
|
|
|
|
|
|
|
|
|
git checkout modify-fickle &&
|
|
|
|
|
echo "more stuff" >>fickle &&
|
|
|
|
|
test_tick &&
|
|
|
|
|
git commit -am "another more stuff commit" &&
|
|
|
|
|
|
|
|
|
|
test_tick &&
|
|
|
|
|
git commit --allow-empty -m "Final commit, empty" &&
|
|
|
|
|
|
|
|
|
|
git checkout master &&
|
|
|
|
|
|
2019-03-11 21:31:22 +01:00
|
|
|
|
# Add a random extra unreferenced object
|
|
|
|
|
echo foobar | git hash-object --stdin -w
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-17 07:40:01 +01:00
|
|
|
|
test_expect_success C_LOCALE_OUTPUT '--analyze' '
|
2019-03-11 21:31:22 +01:00
|
|
|
|
(
|
|
|
|
|
cd analyze_me &&
|
|
|
|
|
|
|
|
|
|
git filter-repo --analyze &&
|
|
|
|
|
|
|
|
|
|
# It should work and overwrite report if run again
|
|
|
|
|
git filter-repo --analyze &&
|
|
|
|
|
|
|
|
|
|
test -d .git/filter-repo/analysis &&
|
|
|
|
|
cd .git/filter-repo/analysis &&
|
|
|
|
|
|
|
|
|
|
cat >expect <<-EOF &&
|
|
|
|
|
fickle ->
|
|
|
|
|
capricious
|
|
|
|
|
mercurial
|
|
|
|
|
words/to ->
|
|
|
|
|
sequence/to
|
|
|
|
|
EOF
|
|
|
|
|
test_cmp expect renames.txt &&
|
|
|
|
|
|
|
|
|
|
cat >expect <<-EOF &&
|
2019-03-17 07:39:39 +01:00
|
|
|
|
== Overall Statistics ==
|
2020-02-07 23:19:51 +01:00
|
|
|
|
Number of commits: 12
|
2019-03-17 07:39:39 +01:00
|
|
|
|
Number of filenames: 10
|
|
|
|
|
Number of directories: 4
|
2019-03-11 21:31:22 +01:00
|
|
|
|
Number of file extensions: 2
|
|
|
|
|
|
2020-02-07 23:19:51 +01:00
|
|
|
|
Total unpacked size (bytes): 206
|
|
|
|
|
Total packed size (bytes): 387
|
2019-03-11 21:31:22 +01:00
|
|
|
|
|
|
|
|
|
EOF
|
|
|
|
|
head -n 9 README >actual &&
|
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
|
2019-04-28 00:18:59 +02:00
|
|
|
|
cat >expect <<-\EOF &&
|
2019-03-17 07:39:39 +01:00
|
|
|
|
=== Files by sha and associated pathnames in reverse size ===
|
2019-03-11 21:31:22 +01:00
|
|
|
|
Format: sha, unpacked size, packed size, filename(s) object stored as
|
|
|
|
|
a89c82a2d4b713a125a4323d25adda062cc0013d 44 48 numbers/medium.num
|
2020-02-07 23:19:51 +01:00
|
|
|
|
c58ae2ffaf8352bd9860bf4bbb6ea78238dca846 35 41 fickle
|
|
|
|
|
ccff62141ec7bae42e01a3dcb7615b38aa9fa5b3 24 40 fickle
|
2019-03-11 21:31:22 +01:00
|
|
|
|
f00c965d8307308469e537302baa73048488f162 21 37 numbers/small.num
|
|
|
|
|
2aa69a2a708eed00cb390e30f6bcc3eed773f390 20 36 whatever
|
2019-04-28 00:18:59 +02:00
|
|
|
|
51b95456de9274c9a95f756742808dfd480b9b35 13 29 [capricious, fickle, mercurial]
|
|
|
|
|
732c85a1b3d7ce40ec8f78fd9ffea32e9f45fae0 5 20 [sequence/know, words/know]
|
|
|
|
|
34b6a0c9d02cb6ef7f409f248c0c1224ce9dd373 5 20 [sequence/to, words/to]
|
2019-03-11 21:31:22 +01:00
|
|
|
|
7ecb56eb3fa3fa6f19dd48bca9f971950b119ede 3 18 words/know
|
|
|
|
|
EOF
|
|
|
|
|
test_cmp expect blob-shas-and-paths.txt &&
|
|
|
|
|
|
|
|
|
|
cat >expect <<-EOF &&
|
|
|
|
|
=== All directories by reverse size ===
|
|
|
|
|
Format: unpacked size, packed size, date deleted, directory name
|
2020-02-07 23:19:51 +01:00
|
|
|
|
206 387 <present> <toplevel>
|
2019-03-11 21:31:22 +01:00
|
|
|
|
65 85 2005-04-07 numbers
|
|
|
|
|
13 58 <present> words
|
|
|
|
|
10 40 <present> sequence
|
|
|
|
|
EOF
|
|
|
|
|
test_cmp expect directories-all-sizes.txt &&
|
|
|
|
|
|
|
|
|
|
cat >expect <<-EOF &&
|
|
|
|
|
=== Deleted directories by reverse size ===
|
|
|
|
|
Format: unpacked size, packed size, date deleted, directory name
|
|
|
|
|
65 85 2005-04-07 numbers
|
|
|
|
|
EOF
|
|
|
|
|
test_cmp expect directories-deleted-sizes.txt &&
|
|
|
|
|
|
|
|
|
|
cat >expect <<-EOF &&
|
|
|
|
|
=== All extensions by reverse size ===
|
|
|
|
|
Format: unpacked size, packed size, date deleted, extension name
|
2020-02-07 23:19:51 +01:00
|
|
|
|
141 302 <present> <no extension>
|
2019-03-11 21:31:22 +01:00
|
|
|
|
65 85 2005-04-07 .num
|
|
|
|
|
EOF
|
|
|
|
|
test_cmp expect extensions-all-sizes.txt &&
|
|
|
|
|
|
|
|
|
|
cat >expect <<-EOF &&
|
|
|
|
|
=== Deleted extensions by reverse size ===
|
|
|
|
|
Format: unpacked size, packed size, date deleted, extension name
|
|
|
|
|
65 85 2005-04-07 .num
|
|
|
|
|
EOF
|
|
|
|
|
test_cmp expect extensions-deleted-sizes.txt &&
|
|
|
|
|
|
|
|
|
|
cat >expect <<-EOF &&
|
|
|
|
|
=== All paths by reverse accumulated size ===
|
2020-01-04 01:01:34 +01:00
|
|
|
|
Format: unpacked size, packed size, date deleted, path name
|
2020-02-07 23:19:51 +01:00
|
|
|
|
72 110 <present> fickle
|
2019-03-11 21:31:22 +01:00
|
|
|
|
44 48 2005-04-07 numbers/medium.num
|
|
|
|
|
8 38 <present> words/know
|
|
|
|
|
21 37 2005-04-07 numbers/small.num
|
|
|
|
|
20 36 <present> whatever
|
|
|
|
|
13 29 <present> mercurial
|
|
|
|
|
13 29 <present> capricious
|
|
|
|
|
5 20 <present> words/to
|
|
|
|
|
5 20 <present> sequence/to
|
2019-04-01 19:58:16 +02:00
|
|
|
|
5 20 <present> sequence/know
|
2019-03-11 21:31:22 +01:00
|
|
|
|
EOF
|
|
|
|
|
test_cmp expect path-all-sizes.txt &&
|
|
|
|
|
|
|
|
|
|
cat >expect <<-EOF &&
|
|
|
|
|
=== Deleted paths by reverse accumulated size ===
|
|
|
|
|
Format: unpacked size, packed size, date deleted, path name(s)
|
|
|
|
|
44 48 2005-04-07 numbers/medium.num
|
|
|
|
|
21 37 2005-04-07 numbers/small.num
|
|
|
|
|
EOF
|
|
|
|
|
test_cmp expect path-deleted-sizes.txt
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-12 21:25:25 +01:00
|
|
|
|
test_expect_success '--replace-text all options' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/analyze_me replace_text &&
|
|
|
|
|
cd replace_text &&
|
|
|
|
|
|
|
|
|
|
cat >../replace-rules <<-\EOF &&
|
|
|
|
|
other
|
|
|
|
|
change==>variation
|
|
|
|
|
|
|
|
|
|
literal:spam==>foodstuff
|
|
|
|
|
glob:ran*m==>haphazard
|
|
|
|
|
regex:1(.[0-9])==>2\1
|
|
|
|
|
EOF
|
|
|
|
|
git filter-repo --replace-text ../replace-rules &&
|
|
|
|
|
|
|
|
|
|
test_seq 200 210 >expect &&
|
|
|
|
|
git show HEAD~4:numbers/medium.num >actual &&
|
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
|
|
|
|
|
echo "haphazard ***REMOVED*** variation" >expect &&
|
|
|
|
|
test_cmp expect whatever
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-05-29 02:37:34 +02:00
|
|
|
|
test_expect_success '--strip-blobs-bigger-than' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/analyze_me strip_big_blobs &&
|
|
|
|
|
cd strip_big_blobs &&
|
|
|
|
|
|
|
|
|
|
# Verify certain files are present initially
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >../filenames &&
|
|
|
|
|
test_line_count = 11 ../filenames &&
|
|
|
|
|
git rev-parse HEAD~7:numbers/medium.num &&
|
|
|
|
|
git rev-parse HEAD~7:numbers/small.num &&
|
|
|
|
|
git rev-parse HEAD~4:mercurial &&
|
|
|
|
|
test -f mercurial &&
|
|
|
|
|
|
|
|
|
|
# Make one of the current files be "really big"
|
|
|
|
|
test_seq 1 1000 >mercurial &&
|
|
|
|
|
git add mercurial &&
|
|
|
|
|
git commit --amend &&
|
|
|
|
|
|
|
|
|
|
# Strip "really big" files
|
|
|
|
|
git filter-repo --force --strip-blobs-bigger-than 3K --prune-empty never &&
|
|
|
|
|
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >../filenames &&
|
|
|
|
|
test_line_count = 11 ../filenames &&
|
|
|
|
|
# The "mercurial" file should still be around...
|
|
|
|
|
git rev-parse HEAD~4:mercurial &&
|
|
|
|
|
git rev-parse HEAD:mercurial &&
|
|
|
|
|
# ...but only with its old, smaller contents
|
|
|
|
|
test_line_count = 1 mercurial &&
|
|
|
|
|
|
|
|
|
|
# Strip files that are too big, verify they are gone
|
|
|
|
|
git filter-repo --strip-blobs-bigger-than 40 &&
|
|
|
|
|
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >../filenames &&
|
|
|
|
|
test_line_count = 10 ../filenames &&
|
|
|
|
|
test_must_fail git rev-parse HEAD~7:numbers/medium.num &&
|
|
|
|
|
|
|
|
|
|
# Do it again, this time with --replace-text since that means
|
|
|
|
|
# we are operating without --no-data and have to go through
|
|
|
|
|
# a different codepath. (The search/replace terms are bogus)
|
|
|
|
|
cat >../replace-rules <<-\EOF &&
|
|
|
|
|
not found==>was found
|
|
|
|
|
EOF
|
|
|
|
|
git filter-repo --strip-blobs-bigger-than 20 --replace-text ../replace-rules &&
|
|
|
|
|
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >../filenames &&
|
|
|
|
|
test_line_count = 9 ../filenames &&
|
|
|
|
|
test_must_fail git rev-parse HEAD~7:numbers/medium.num &&
|
|
|
|
|
test_must_fail git rev-parse HEAD~7:numbers/small.num &&
|
|
|
|
|
|
|
|
|
|
# Remove the temporary auxiliary files
|
|
|
|
|
rm ../replace-rules &&
|
|
|
|
|
rm ../filenames
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-05-31 04:42:57 +02:00
|
|
|
|
test_expect_success '--strip-blobs-with-ids' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/analyze_me strip_blobs_with_ids &&
|
|
|
|
|
cd strip_blobs_with_ids &&
|
|
|
|
|
|
|
|
|
|
# Verify certain files are present initially
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >../filenames &&
|
|
|
|
|
test_line_count = 11 ../filenames &&
|
|
|
|
|
grep fake_submodule ../filenames &&
|
|
|
|
|
|
|
|
|
|
# Strip "a certain file" files
|
|
|
|
|
git filter-repo --strip-blobs-with-ids <(echo deadbeefdeadbeefdeadbeefdeadbeefdeadbeef) &&
|
|
|
|
|
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >../filenames &&
|
|
|
|
|
test_line_count = 10 ../filenames &&
|
|
|
|
|
# Make sure fake_submodule was removed
|
|
|
|
|
! grep fake_submodule ../filenames &&
|
|
|
|
|
|
|
|
|
|
# Do it again, this time with --replace-text since that means
|
|
|
|
|
# we are operating without --no-data and have to go through
|
|
|
|
|
# a different codepath. (The search/replace terms are bogus)
|
|
|
|
|
cat >../bad-ids <<-\EOF &&
|
|
|
|
|
34b6a0c9d02cb6ef7f409f248c0c1224ce9dd373
|
|
|
|
|
51b95456de9274c9a95f756742808dfd480b9b35
|
|
|
|
|
EOF
|
|
|
|
|
cat >../replace-rules <<-\EOF &&
|
|
|
|
|
not found==>was found
|
|
|
|
|
EOF
|
|
|
|
|
git filter-repo --strip-blobs-with-ids ../bad-ids --replace-text ../replace-rules &&
|
|
|
|
|
|
|
|
|
|
git log --format=%n --name-only | sort | uniq >../filenames &&
|
|
|
|
|
test_line_count = 5 ../filenames &&
|
|
|
|
|
! grep sequence/to ../filenames &&
|
|
|
|
|
! grep words/to ../filenames &&
|
|
|
|
|
! grep capricious ../filenames &&
|
|
|
|
|
! grep fickle ../filenames &&
|
|
|
|
|
! grep mercurial ../filenames
|
|
|
|
|
|
|
|
|
|
# Remove the temporary auxiliary files
|
|
|
|
|
rm ../bad-ids &&
|
|
|
|
|
rm ../replace-rules &&
|
|
|
|
|
rm ../filenames
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-12 02:08:41 +01:00
|
|
|
|
test_expect_success 'setup commit message rewriting' '
|
|
|
|
|
test_create_repo commit_msg &&
|
|
|
|
|
(
|
|
|
|
|
cd commit_msg &&
|
|
|
|
|
echo two guys walking into a >bar &&
|
|
|
|
|
git add bar &&
|
|
|
|
|
git commit -m initial &&
|
|
|
|
|
|
|
|
|
|
test_commit another &&
|
|
|
|
|
|
|
|
|
|
name=$(git rev-parse HEAD) &&
|
|
|
|
|
echo hello >world &&
|
|
|
|
|
git add world &&
|
|
|
|
|
git commit -m "Commit referencing ${name:0:8}" &&
|
|
|
|
|
|
|
|
|
|
git revert HEAD &&
|
|
|
|
|
|
|
|
|
|
for i in $(test_seq 1 200)
|
|
|
|
|
do
|
|
|
|
|
git commit --allow-empty -m "another commit"
|
|
|
|
|
done &&
|
|
|
|
|
|
|
|
|
|
echo foo >bar &&
|
|
|
|
|
git add bar &&
|
|
|
|
|
git commit -m bar &&
|
|
|
|
|
|
|
|
|
|
git revert --no-commit HEAD &&
|
|
|
|
|
echo foo >baz &&
|
|
|
|
|
git add baz &&
|
|
|
|
|
git commit
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
test_expect_success 'commit message rewrite' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/commit_msg commit_msg_clone &&
|
|
|
|
|
cd commit_msg_clone &&
|
|
|
|
|
|
|
|
|
|
git filter-repo --invert-paths --path bar &&
|
|
|
|
|
|
|
|
|
|
git log --oneline >changes &&
|
|
|
|
|
test_line_count = 204 changes &&
|
|
|
|
|
|
2019-05-12 03:45:49 +02:00
|
|
|
|
# If a commit we reference is rewritten, we expect the
|
|
|
|
|
# reference to be rewritten.
|
2019-03-12 02:08:41 +01:00
|
|
|
|
name=$(git rev-parse HEAD~203) &&
|
|
|
|
|
echo "Commit referencing ${name:0:8}" >expect &&
|
|
|
|
|
git log --no-walk --format=%s HEAD~202 >actual &&
|
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
|
2019-05-12 03:45:49 +02:00
|
|
|
|
# If a commit we reference was pruned, then the reference
|
|
|
|
|
# has nothing to be rewritten to. Verify that the commit
|
|
|
|
|
# ID it points to does not exist.
|
2019-03-12 02:08:41 +01:00
|
|
|
|
latest=$(git log --no-walk | grep reverts | awk "{print \$4}" | tr -d '.') &&
|
|
|
|
|
test -n "$latest" &&
|
|
|
|
|
test_must_fail git cat-file -e "$latest"
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-05-12 03:45:49 +02:00
|
|
|
|
test_expect_success 'commit hash unchanged if requested' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/commit_msg commit_msg_clone_2 &&
|
|
|
|
|
cd commit_msg_clone_2 &&
|
|
|
|
|
|
|
|
|
|
name=$(git rev-parse HEAD~204) &&
|
|
|
|
|
git filter-repo --invert-paths --path bar --preserve-commit-hashes &&
|
|
|
|
|
|
|
|
|
|
git log --oneline >changes &&
|
|
|
|
|
test_line_count = 204 changes &&
|
|
|
|
|
|
|
|
|
|
echo "Commit referencing ${name:0:8}" >expect &&
|
|
|
|
|
git log --no-walk --format=%s HEAD~202 >actual &&
|
|
|
|
|
test_cmp expect actual
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-06-25 02:40:13 +02:00
|
|
|
|
test_expect_success 'commit message encoding preserved if requested' '
|
|
|
|
|
(
|
|
|
|
|
git init commit_message_encoding &&
|
|
|
|
|
cd commit_message_encoding &&
|
|
|
|
|
|
|
|
|
|
cat >input <<-\EOF &&
|
|
|
|
|
feature done
|
|
|
|
|
commit refs/heads/develop
|
|
|
|
|
mark :1
|
|
|
|
|
original-oid deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
|
|
|
|
|
author Just Me <just@here.org> 1234567890 -0200
|
|
|
|
|
committer Just Me <just@here.org> 1234567890 -0200
|
|
|
|
|
encoding iso-8859-7
|
|
|
|
|
data 5
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
printf "Pi: \360\n\ndone\n" >>input &&
|
|
|
|
|
|
|
|
|
|
cat input | git fast-import --quiet &&
|
|
|
|
|
git rev-parse develop >expect &&
|
|
|
|
|
|
|
|
|
|
git filter-repo --preserve-commit-encoding --force &&
|
|
|
|
|
git rev-parse develop >actual &&
|
|
|
|
|
test_cmp expect actual
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-12 02:08:41 +01:00
|
|
|
|
test_expect_success 'commit message rewrite unsuccessful' '
|
|
|
|
|
(
|
|
|
|
|
git init commit_msg_not_found &&
|
|
|
|
|
cd commit_msg_not_found &&
|
|
|
|
|
|
|
|
|
|
cat >input <<-\EOF &&
|
|
|
|
|
feature done
|
|
|
|
|
commit refs/heads/develop
|
|
|
|
|
mark :1
|
|
|
|
|
original-oid deadbeefdeadbeefdeadbeefdeadbeefdeadbeef
|
|
|
|
|
author Just Me <just@here.org> 1234567890 -0200
|
|
|
|
|
committer Just Me <just@here.org> 1234567890 -0200
|
|
|
|
|
data 2
|
|
|
|
|
A
|
|
|
|
|
|
|
|
|
|
commit refs/heads/develop
|
|
|
|
|
mark :2
|
|
|
|
|
original-oid deadbeefcafedeadbeefcafedeadbeefcafecafe
|
|
|
|
|
author Just Me <just@here.org> 1234567890 -0200
|
|
|
|
|
committer Just Me <just@here.org> 1234567890 -0200
|
|
|
|
|
data 2
|
|
|
|
|
B
|
|
|
|
|
|
|
|
|
|
commit refs/heads/develop
|
|
|
|
|
mark :3
|
|
|
|
|
original-oid 0000000000000000000000000000000000000004
|
|
|
|
|
author Just Me <just@here.org> 3980014290 -0200
|
|
|
|
|
committer Just Me <just@here.org> 3980014290 -0200
|
|
|
|
|
data 93
|
|
|
|
|
Four score and seven years ago, commit deadbeef ("B",
|
|
|
|
|
2009-02-13) messed up. This fixes it.
|
|
|
|
|
done
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
cat input | git filter-repo --stdin --path salutation --force &&
|
|
|
|
|
|
|
|
|
|
git log --oneline develop >changes &&
|
|
|
|
|
test_line_count = 3 changes &&
|
|
|
|
|
|
|
|
|
|
git log develop >out &&
|
|
|
|
|
grep deadbeef out
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-14 01:05:58 +01:00
|
|
|
|
test_expect_success 'startup sanity checks' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/analyze_me startup_sanity_checks &&
|
|
|
|
|
cd startup_sanity_checks &&
|
|
|
|
|
|
|
|
|
|
echo foobar | git hash-object -w --stdin &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>err &&
|
|
|
|
|
test_i18ngrep "expected freshly packed repo" err &&
|
|
|
|
|
git prune &&
|
|
|
|
|
|
|
|
|
|
git remote add another_remote /dev/null &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>err &&
|
|
|
|
|
test_i18ngrep "expected one remote, origin" err &&
|
|
|
|
|
git remote rm another_remote &&
|
|
|
|
|
|
|
|
|
|
git remote rename origin another_remote &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>err &&
|
|
|
|
|
test_i18ngrep "expected one remote, origin" err &&
|
|
|
|
|
git remote rename another_remote origin &&
|
|
|
|
|
|
|
|
|
|
cd words &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>err &&
|
|
|
|
|
test_i18ngrep "GIT_DIR must be .git" err &&
|
|
|
|
|
rm err &&
|
|
|
|
|
cd .. &&
|
|
|
|
|
|
|
|
|
|
git config core.bare true &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>err &&
|
|
|
|
|
test_i18ngrep "GIT_DIR must be ." err &&
|
|
|
|
|
git config core.bare false &&
|
|
|
|
|
|
|
|
|
|
git update-ref -m "Just Testing" refs/heads/master HEAD &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>err &&
|
|
|
|
|
test_i18ngrep "expected at most one entry in the reflog" err &&
|
|
|
|
|
git reflog expire --expire=now &&
|
|
|
|
|
|
|
|
|
|
echo yes >>words/know &&
|
|
|
|
|
git stash save random change &&
|
|
|
|
|
rm -rf .git/logs/ &&
|
|
|
|
|
git gc &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>err &&
|
|
|
|
|
test_i18ngrep "has stashed changes" err &&
|
|
|
|
|
git update-ref -d refs/stash &&
|
|
|
|
|
|
|
|
|
|
echo yes >>words/know &&
|
|
|
|
|
git add words/know &&
|
|
|
|
|
git gc --prune=now &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>err &&
|
|
|
|
|
test_i18ngrep "you have uncommitted changes" err &&
|
|
|
|
|
git checkout HEAD words/know &&
|
|
|
|
|
|
|
|
|
|
echo yes >>words/know &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>err &&
|
|
|
|
|
test_i18ngrep "you have unstaged changes" err &&
|
|
|
|
|
git checkout -- words/know &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>err &&
|
|
|
|
|
test_i18ngrep "you have untracked changes" err &&
|
|
|
|
|
rm err &&
|
|
|
|
|
|
2019-05-02 18:10:26 +02:00
|
|
|
|
git worktree add ../other-worktree HEAD &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>../err &&
|
|
|
|
|
test_i18ngrep "you have multiple worktrees" ../err &&
|
|
|
|
|
rm -rf ../err &&
|
|
|
|
|
git worktree remove ../other-worktree &&
|
|
|
|
|
|
2019-03-14 01:05:58 +01:00
|
|
|
|
git update-ref -d refs/remotes/origin/master &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>../err &&
|
|
|
|
|
test_i18ngrep "refs/heads/master exists, but refs/remotes/origin/master not found" ../err &&
|
|
|
|
|
git update-ref -m restoring refs/remotes/origin/master refs/heads/master &&
|
|
|
|
|
rm ../err &&
|
|
|
|
|
|
|
|
|
|
rm .git/logs/refs/remotes/origin/master &&
|
|
|
|
|
git update-ref -m funsies refs/remotes/origin/master refs/heads/master~1 &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>../err &&
|
|
|
|
|
test_i18ngrep "refs/heads/master does not match refs/remotes/origin/master" ../err &&
|
2020-05-16 08:47:49 +02:00
|
|
|
|
rm ../err &&
|
|
|
|
|
|
|
|
|
|
cd ../ &&
|
|
|
|
|
git -C analyze_me gc &&
|
|
|
|
|
echo foobar | git -C analyze_me hash-object -w --stdin &&
|
|
|
|
|
git clone analyze_me startup_sanity_checks2 &&
|
|
|
|
|
cd startup_sanity_checks2 &&
|
|
|
|
|
|
|
|
|
|
echo foobar | git hash-object -w --stdin &&
|
|
|
|
|
test_must_fail git filter-repo --path numbers 2>../err &&
|
|
|
|
|
test_i18ngrep "expected freshly packed repo" ../err &&
|
|
|
|
|
test_i18ngrep "when cloning local repositories" ../err &&
|
2019-03-14 01:05:58 +01:00
|
|
|
|
rm ../err
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-15 02:06:12 +01:00
|
|
|
|
test_expect_success 'other startup error cases and requests for help' '
|
|
|
|
|
(
|
|
|
|
|
git init startup_errors &&
|
|
|
|
|
cd startup_errors &&
|
|
|
|
|
|
|
|
|
|
git filter-repo -h >out &&
|
|
|
|
|
test_i18ngrep "filter-repo destructively rewrites history" out &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo 2>err &&
|
|
|
|
|
test_i18ngrep "No arguments specified." err &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --analyze 2>err &&
|
|
|
|
|
test_i18ngrep "Nothing to analyze; repository is empty" err &&
|
|
|
|
|
|
|
|
|
|
(
|
|
|
|
|
GIT_CEILING_DIRECTORIES=$(pwd) &&
|
|
|
|
|
export GIT_CEILING_DIRECTORIES &&
|
|
|
|
|
mkdir not_a_repo &&
|
|
|
|
|
cd not_a_repo &&
|
|
|
|
|
test_must_fail git filter-repo --dry-run 2>err &&
|
|
|
|
|
test_i18ngrep "returned non-zero exit status" err &&
|
|
|
|
|
rm err &&
|
|
|
|
|
cd .. &&
|
|
|
|
|
rmdir not_a_repo
|
|
|
|
|
) &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --analyze --path foobar 2>err &&
|
|
|
|
|
test_i18ngrep ": --analyze is incompatible with --path" err &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --analyze --stdin 2>err &&
|
2019-05-17 20:01:24 +02:00
|
|
|
|
test_i18ngrep ": --analyze is incompatible with --stdin" err &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --path-rename foo:bar --use-base-name 2>err &&
|
2019-05-20 19:04:57 +02:00
|
|
|
|
test_i18ngrep ": --use-base-name and --path-rename are incompatible" err &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --path-rename foo:bar/ 2>err &&
|
2019-05-21 16:37:59 +02:00
|
|
|
|
test_i18ngrep "either ends with a slash then both must." err &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --paths-from-file <(echo "foo==>bar/") 2>err &&
|
|
|
|
|
test_i18ngrep "either ends with a slash then both must." err &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --paths-from-file <(echo "glob:*.py==>newname") 2>err &&
|
2019-05-29 02:37:34 +02:00
|
|
|
|
test_i18ngrep "renaming globs makes no sense" err &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --strip-blobs-bigger-than 3GiB 2>err &&
|
2019-12-27 00:50:31 +01:00
|
|
|
|
test_i18ngrep "could not parse.*3GiB" err &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --path-rename foo/bar:. 2>err &&
|
2020-05-17 03:05:59 +02:00
|
|
|
|
test_i18ngrep "Invalid path component .\.. found in .foo/bar:\." err &&
|
2019-05-29 02:37:34 +02:00
|
|
|
|
|
2020-05-17 03:05:59 +02:00
|
|
|
|
test_must_fail git filter-repo --path /foo/bar 2>err &&
|
|
|
|
|
test_i18ngrep "Pathnames cannot begin with a ./" err &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --path-rename foo:/bar 2>err &&
|
|
|
|
|
test_i18ngrep "Pathnames cannot begin with a ./" err &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --path-rename /foo:bar 2>err &&
|
|
|
|
|
test_i18ngrep "Pathnames cannot begin with a ./" err &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --subdirectory-filter /foo 2>err &&
|
|
|
|
|
test_i18ngrep "Pathnames cannot begin with a ./" err &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --subdirectory-filter /foo 2>err &&
|
|
|
|
|
test_i18ngrep "Pathnames cannot begin with a ./" err
|
2019-03-15 02:06:12 +01:00
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-15 16:06:49 +01:00
|
|
|
|
test_expect_success 'invalid fast-import directives' '
|
|
|
|
|
(
|
|
|
|
|
git init invalid_directives &&
|
|
|
|
|
cd invalid_directives &&
|
|
|
|
|
|
|
|
|
|
echo "get-mark :15" | \
|
|
|
|
|
test_must_fail git filter-repo --stdin --force 2>err &&
|
|
|
|
|
test_i18ngrep "Unsupported command" err &&
|
|
|
|
|
|
|
|
|
|
echo "invalid-directive" | \
|
|
|
|
|
test_must_fail git filter-repo --stdin --force 2>err &&
|
|
|
|
|
test_i18ngrep "Could not parse line" err
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-14 03:30:24 +01:00
|
|
|
|
test_expect_success 'mailmap sanity checks' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/analyze_me mailmap_sanity_checks &&
|
|
|
|
|
cd mailmap_sanity_checks &&
|
|
|
|
|
|
|
|
|
|
test_must_fail git filter-repo --mailmap /fake/path 2>../err &&
|
|
|
|
|
test_i18ngrep "Cannot read /fake/path" ../err &&
|
|
|
|
|
|
|
|
|
|
echo "Total Bogus" >../whoopsies &&
|
|
|
|
|
test_must_fail git filter-repo --mailmap ../whoopsies 2>../err &&
|
|
|
|
|
test_i18ngrep "Unparseable mailmap file" ../err &&
|
|
|
|
|
rm ../err &&
|
|
|
|
|
rm ../whoopsies &&
|
|
|
|
|
|
|
|
|
|
echo "Me <me@site.com> Myself <yo@email.com> Extraneous" >../whoopsies &&
|
|
|
|
|
test_must_fail git filter-repo --mailmap ../whoopsies 2>../err &&
|
|
|
|
|
test_i18ngrep "Unparseable mailmap file" ../err &&
|
|
|
|
|
rm ../err &&
|
|
|
|
|
rm ../whoopsies
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-03-14 07:34:47 +01:00
|
|
|
|
test_expect_success 'incremental import' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/analyze_me incremental &&
|
|
|
|
|
cd incremental &&
|
|
|
|
|
|
|
|
|
|
original=$(git rev-parse master) &&
|
|
|
|
|
git fast-export --reference-excluded-parents master~2..master \
|
2019-04-28 00:18:59 +02:00
|
|
|
|
| git filter-repo --stdin --refname-callback "return b\"develop\"" &&
|
2019-03-14 07:34:47 +01:00
|
|
|
|
test "$(git rev-parse develop)" = "$original"
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-05-30 20:07:54 +02:00
|
|
|
|
test_expect_success '--target' '
|
|
|
|
|
git init target &&
|
|
|
|
|
(
|
|
|
|
|
cd target &&
|
|
|
|
|
git checkout -b other &&
|
|
|
|
|
echo hello >world &&
|
|
|
|
|
git add world &&
|
2019-06-21 21:25:19 +02:00
|
|
|
|
git commit -m init &&
|
|
|
|
|
git checkout -b unique
|
2019-05-30 20:07:54 +02:00
|
|
|
|
) &&
|
2019-06-21 21:25:19 +02:00
|
|
|
|
git -C target rev-parse unique >target/expect &&
|
2019-05-30 20:07:54 +02:00
|
|
|
|
git filter-repo --source analyze_me --target target --path fake_submodule --force --debug &&
|
2019-06-21 21:25:19 +02:00
|
|
|
|
test 2 = $(git -C target rev-list --count master) &&
|
|
|
|
|
test_must_fail git -C target rev-parse other &&
|
|
|
|
|
git -C target rev-parse unique >target/actual &&
|
|
|
|
|
test_cmp target/expect target/actual
|
2019-05-30 20:07:54 +02:00
|
|
|
|
'
|
|
|
|
|
|
2019-05-29 22:11:55 +02:00
|
|
|
|
test_expect_success '--refs' '
|
|
|
|
|
git init refs &&
|
|
|
|
|
(
|
|
|
|
|
cd refs &&
|
|
|
|
|
git checkout -b other &&
|
|
|
|
|
echo hello >world &&
|
|
|
|
|
git add world &&
|
|
|
|
|
git commit -m init
|
|
|
|
|
) &&
|
|
|
|
|
git -C refs rev-parse other >refs/expect &&
|
|
|
|
|
git -C analyze_me rev-parse master >refs/expect &&
|
|
|
|
|
git filter-repo --source analyze_me --target refs --refs master --force &&
|
|
|
|
|
git -C refs rev-parse other >refs/actual &&
|
|
|
|
|
git -C refs rev-parse master >refs/actual &&
|
|
|
|
|
test_cmp refs/expect refs/actual
|
|
|
|
|
'
|
|
|
|
|
|
2019-05-28 18:17:17 +02:00
|
|
|
|
test_expect_success 'reset to specific refs' '
|
|
|
|
|
test_create_repo reset_to_specific_refs &&
|
|
|
|
|
(
|
|
|
|
|
cd reset_to_specific_refs &&
|
|
|
|
|
|
|
|
|
|
git commit --allow-empty -m initial &&
|
|
|
|
|
INITIAL=$(git rev-parse HEAD) &&
|
|
|
|
|
echo "$INITIAL refs/heads/develop" >expect &&
|
|
|
|
|
|
|
|
|
|
cat >input <<-INPUT_END &&
|
|
|
|
|
reset refs/heads/develop
|
|
|
|
|
from $INITIAL
|
|
|
|
|
|
|
|
|
|
reset refs/heads/master
|
|
|
|
|
from 0000000000000000000000000000000000000000
|
|
|
|
|
INPUT_END
|
|
|
|
|
|
|
|
|
|
cat input | git filter-repo --force --stdin &&
|
|
|
|
|
git show-ref >actual &&
|
|
|
|
|
test_cmp expect actual
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-04-02 19:41:36 +02:00
|
|
|
|
test_expect_success 'setup handle funny characters' '
|
|
|
|
|
test_create_repo funny_chars &&
|
|
|
|
|
(
|
|
|
|
|
cd funny_chars &&
|
|
|
|
|
|
|
|
|
|
git symbolic-ref HEAD refs/heads/españa &&
|
|
|
|
|
|
|
|
|
|
printf "بتتكلم بالهندي؟\n" >señor &&
|
|
|
|
|
printf "Αυτά μου φαίνονται αλαμπουρνέζικα.\n" >>señor &&
|
|
|
|
|
printf "זה סינית בשבילי\n" >>señor &&
|
|
|
|
|
printf "ちんぷんかんぷん\n" >>señor &&
|
|
|
|
|
printf "За мене тоа е шпанско село\n" >>señor &&
|
|
|
|
|
printf "看起来像天书。\n" >>señor &&
|
|
|
|
|
printf "انگار ژاپنی حرف می زنه\n" >>señor &&
|
|
|
|
|
printf "Это для меня китайская грамота.\n" >>señor &&
|
|
|
|
|
printf "To mi je španska vas\n" >>señor &&
|
|
|
|
|
printf "Konuya Fransız kaldım\n" >>señor &&
|
|
|
|
|
printf "עס איז די שפּראַך פון גיבבעריש\n" >>señor &&
|
|
|
|
|
printf "Not even UTF-8:\xe0\x80\x80\x00\n" >>señor &&
|
|
|
|
|
|
|
|
|
|
cp señor señora &&
|
|
|
|
|
cp señor señorita &&
|
|
|
|
|
git add . &&
|
|
|
|
|
|
|
|
|
|
export GIT_AUTHOR_NAME="Nguyễn Arnfjörð Gábor" &&
|
|
|
|
|
export GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME &&
|
|
|
|
|
export GIT_AUTHOR_EMAIL="emails@are.ascii" &&
|
|
|
|
|
export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL" &&
|
|
|
|
|
git commit -m "€$£₽₪" &&
|
|
|
|
|
|
|
|
|
|
git tag -a -m "₪₽£€$" סְפָרַד
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
test_expect_success 'handle funny characters' '
|
|
|
|
|
(
|
|
|
|
|
git clone file://"$(pwd)"/funny_chars funny_chars_checks &&
|
|
|
|
|
cd funny_chars_checks &&
|
|
|
|
|
|
|
|
|
|
file_sha=$(git rev-parse :0:señor) &&
|
filter-repo: add --replace-refs option
This adds the ability to automatically add new replacement refs for each
rewritten commit (as well as delete or update replacement refs that
existed before the run). This will allow users to use either new or old
commit hashes to reference commits locally, though old commit hashes
will need to be unabbreviated. The only requirement for this to work,
is that the person who does the rewrite also needs to push the replace
refs up where other users can grab them, and users who want to use them
need to modify their fetch refspecs to grab the replace refs.
However, other tools external to git may not understand replace refs...
Tools like Gerrit and GitHub apparently do not yet natively understand
replace refs. Trying to view "commits" by the replacement ref will
yield various forms of "Not Found" in each tool. One has to instead try
to view it as a branch with an odd name (including "refs/replace/"), and
often branches are accessed via a different URL style than commits so it
becomes very non-obvious to users how to access the info associated with
an old commit hash.
* In Gerrit, instead of being able to search on the sha1sum or use a
pre-defined URL to search and auto-redirect to the appropriate code
review with
https://gerrit.SITE.COM/#/q/${OLD_SHA1SUM},n,z
one instead has to have a special plugin and go to a URL like
https://gerrit.SITE.COM/plugins/gitiles/ORG/REPO/+/refs/replace/${OLD_SHA1SUM}
but then the user isn't shown the actual code review and will need
to guess which link to click on to get to it (and it'll only be
there if the user included a Change-Id in the commit message).
* In GitHub, instead of being able to go to a URL like
https://github.SITE.COM/ORG/REPO/commit/${OLD_SHA1SUM}
one instead has to navigate based on branch using
https://github.SITE.COM/ORG/REPO/tree/refs/replace/${OLD_SHA1SUM}
but that will show a listing of commits instead of information about
a specific commit; the user has to manually click on the first commit
to get to the desired location.
For now, providing replace refs at least allows users to access
information locally using old IDs; perhaps in time as other external
tools will gain a better understanding of how to use replace refs, the
barrier to history rewrites will decrease enough that big projects that
really need it (e.g. those that have committed many sins by commiting
stupidly large useless binary blobs) can at least seriously contemplate
the undertaking. History rewrites will always have some drawbacks and
pain associated with them, as they should, but when warranted it's nice
to have transition plans that are more smooth than a massive flag day.
Signed-off-by: Elijah Newren <newren@gmail.com>
2019-05-02 19:05:15 +02:00
|
|
|
|
former_head_sha=$(git rev-parse HEAD) &&
|
2019-04-02 19:41:36 +02:00
|
|
|
|
git filter-repo --to-subdirectory-filter títulos &&
|
|
|
|
|
|
|
|
|
|
cat <<-EOF >expect &&
|
|
|
|
|
100644 $file_sha 0 "t\303\255tulos/se\303\261or"
|
|
|
|
|
100644 $file_sha 0 "t\303\255tulos/se\303\261ora"
|
|
|
|
|
100644 $file_sha 0 "t\303\255tulos/se\303\261orita"
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
git ls-files -s >actual &&
|
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
|
|
|
|
|
commit_sha=$(git rev-parse HEAD) &&
|
|
|
|
|
tag_sha=$(git rev-parse סְפָרַד) &&
|
|
|
|
|
cat <<-EOF >expect &&
|
|
|
|
|
$commit_sha refs/heads/españa
|
filter-repo: add --replace-refs option
This adds the ability to automatically add new replacement refs for each
rewritten commit (as well as delete or update replacement refs that
existed before the run). This will allow users to use either new or old
commit hashes to reference commits locally, though old commit hashes
will need to be unabbreviated. The only requirement for this to work,
is that the person who does the rewrite also needs to push the replace
refs up where other users can grab them, and users who want to use them
need to modify their fetch refspecs to grab the replace refs.
However, other tools external to git may not understand replace refs...
Tools like Gerrit and GitHub apparently do not yet natively understand
replace refs. Trying to view "commits" by the replacement ref will
yield various forms of "Not Found" in each tool. One has to instead try
to view it as a branch with an odd name (including "refs/replace/"), and
often branches are accessed via a different URL style than commits so it
becomes very non-obvious to users how to access the info associated with
an old commit hash.
* In Gerrit, instead of being able to search on the sha1sum or use a
pre-defined URL to search and auto-redirect to the appropriate code
review with
https://gerrit.SITE.COM/#/q/${OLD_SHA1SUM},n,z
one instead has to have a special plugin and go to a URL like
https://gerrit.SITE.COM/plugins/gitiles/ORG/REPO/+/refs/replace/${OLD_SHA1SUM}
but then the user isn't shown the actual code review and will need
to guess which link to click on to get to it (and it'll only be
there if the user included a Change-Id in the commit message).
* In GitHub, instead of being able to go to a URL like
https://github.SITE.COM/ORG/REPO/commit/${OLD_SHA1SUM}
one instead has to navigate based on branch using
https://github.SITE.COM/ORG/REPO/tree/refs/replace/${OLD_SHA1SUM}
but that will show a listing of commits instead of information about
a specific commit; the user has to manually click on the first commit
to get to the desired location.
For now, providing replace refs at least allows users to access
information locally using old IDs; perhaps in time as other external
tools will gain a better understanding of how to use replace refs, the
barrier to history rewrites will decrease enough that big projects that
really need it (e.g. those that have committed many sins by commiting
stupidly large useless binary blobs) can at least seriously contemplate
the undertaking. History rewrites will always have some drawbacks and
pain associated with them, as they should, but when warranted it's nice
to have transition plans that are more smooth than a massive flag day.
Signed-off-by: Elijah Newren <newren@gmail.com>
2019-05-02 19:05:15 +02:00
|
|
|
|
$commit_sha refs/replace/$former_head_sha
|
2019-04-02 19:41:36 +02:00
|
|
|
|
$tag_sha refs/tags/סְפָרַד
|
|
|
|
|
EOF
|
|
|
|
|
|
|
|
|
|
git show-ref >actual &&
|
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
|
|
|
|
|
echo "€$£₽₪" >expect &&
|
|
|
|
|
git cat-file -p HEAD | tail -n 1 >actual &&
|
|
|
|
|
|
|
|
|
|
echo "₪₽£€$" >expect &&
|
|
|
|
|
git cat-file -p סְפָרַד | tail -n 1 >actual
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-08-19 22:36:07 +02:00
|
|
|
|
test_expect_success '--state-branch with changing renames' '
|
|
|
|
|
test_create_repo state_branch_renames_export
|
|
|
|
|
test_create_repo state_branch_renames &&
|
|
|
|
|
(
|
|
|
|
|
cd state_branch_renames &&
|
|
|
|
|
git fast-import --quiet <$DATA/basic-numbers &&
|
|
|
|
|
git branch -d A &&
|
|
|
|
|
git branch -d B &&
|
|
|
|
|
git tag -d v1.0 &&
|
|
|
|
|
|
|
|
|
|
ORIG=$(git rev-parse master) &&
|
|
|
|
|
git reset --hard master~1 &&
|
|
|
|
|
git filter-repo --path-rename ten:zehn \
|
|
|
|
|
--state-branch state_info \
|
|
|
|
|
--target ../state_branch_renames_export &&
|
|
|
|
|
|
|
|
|
|
cd ../state_branch_renames_export &&
|
|
|
|
|
git log --format=%s --name-status >actual &&
|
|
|
|
|
cat <<-EOF >expect &&
|
|
|
|
|
Merge branch ${SQ}A${SQ} into B
|
|
|
|
|
add twenty
|
|
|
|
|
|
|
|
|
|
M twenty
|
|
|
|
|
add ten
|
|
|
|
|
|
|
|
|
|
M zehn
|
|
|
|
|
Initial
|
|
|
|
|
|
|
|
|
|
A twenty
|
|
|
|
|
A zehn
|
|
|
|
|
EOF
|
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
|
|
|
|
|
cd ../state_branch_renames &&
|
|
|
|
|
|
|
|
|
|
git reset --hard $ORIG &&
|
|
|
|
|
git filter-repo --path-rename twenty:veinte \
|
|
|
|
|
--state-branch state_info \
|
|
|
|
|
--target ../state_branch_renames_export &&
|
|
|
|
|
|
|
|
|
|
cd ../state_branch_renames_export &&
|
|
|
|
|
git log --format=%s --name-status >actual &&
|
|
|
|
|
cat <<-EOF >expect &&
|
|
|
|
|
whatever
|
|
|
|
|
|
|
|
|
|
A ten
|
|
|
|
|
A veinte
|
|
|
|
|
Merge branch ${SQ}A${SQ} into B
|
|
|
|
|
add twenty
|
|
|
|
|
|
|
|
|
|
M twenty
|
|
|
|
|
add ten
|
|
|
|
|
|
|
|
|
|
M zehn
|
|
|
|
|
Initial
|
|
|
|
|
|
|
|
|
|
A twenty
|
|
|
|
|
A zehn
|
|
|
|
|
EOF
|
|
|
|
|
test_cmp expect actual
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
|
|
|
|
test_expect_success '--state-branch with expanding paths and refs' '
|
|
|
|
|
test_create_repo state_branch_more_paths_export
|
|
|
|
|
test_create_repo state_branch_more_paths &&
|
|
|
|
|
(
|
|
|
|
|
cd state_branch_more_paths &&
|
|
|
|
|
git fast-import --quiet <$DATA/basic-numbers &&
|
|
|
|
|
|
|
|
|
|
git reset --hard master~1 &&
|
|
|
|
|
git filter-repo --path ten --state-branch state_info \
|
|
|
|
|
--target ../state_branch_more_paths_export \
|
|
|
|
|
--refs master &&
|
|
|
|
|
|
|
|
|
|
cd ../state_branch_more_paths_export &&
|
|
|
|
|
echo 2 >expect &&
|
|
|
|
|
git rev-list --count master >actual &&
|
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
test_must_fail git rev-parse master~1:twenty &&
|
|
|
|
|
test_must_fail git rev-parse master:twenty &&
|
|
|
|
|
|
|
|
|
|
cd ../state_branch_more_paths &&
|
|
|
|
|
|
|
|
|
|
git reset --hard v1.0 &&
|
|
|
|
|
git filter-repo --path ten --path twenty \
|
|
|
|
|
--state-branch state_info \
|
|
|
|
|
--target ../state_branch_more_paths_export &&
|
|
|
|
|
|
|
|
|
|
cd ../state_branch_more_paths_export &&
|
|
|
|
|
echo 3 >expect &&
|
|
|
|
|
git rev-list --count master >actual &&
|
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
test_must_fail git rev-parse master~2:twenty &&
|
|
|
|
|
git rev-parse master:twenty
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-10-04 03:10:47 +02:00
|
|
|
|
test_expect_success 'degenerate merge with non-matching filenames' '
|
|
|
|
|
test_create_repo degenerate_merge_differing_filenames &&
|
|
|
|
|
(
|
|
|
|
|
cd degenerate_merge_differing_filenames &&
|
|
|
|
|
|
|
|
|
|
touch "foo \"quote\" bar" &&
|
|
|
|
|
git add "foo \"quote\" bar" &&
|
|
|
|
|
git commit -m "Add foo \"quote\" bar"
|
|
|
|
|
git branch A &&
|
|
|
|
|
|
|
|
|
|
git checkout --orphan B &&
|
|
|
|
|
git reset --hard &&
|
|
|
|
|
mkdir -p pkg/list &&
|
|
|
|
|
test_commit pkg/list/whatever &&
|
2019-12-25 16:59:37 +01:00
|
|
|
|
test_commit unwanted_file &&
|
2019-10-04 03:10:47 +02:00
|
|
|
|
|
|
|
|
|
git checkout A &&
|
|
|
|
|
git merge --allow-unrelated-histories --no-commit B &&
|
|
|
|
|
>pkg/list/wanted &&
|
|
|
|
|
git add pkg/list/wanted &&
|
|
|
|
|
git rm -f pkg/list/whatever.t &&
|
|
|
|
|
git commit &&
|
|
|
|
|
|
|
|
|
|
git filter-repo --force --path pkg/list &&
|
|
|
|
|
! test_path_is_file pkg/list/whatever.t &&
|
2020-03-23 23:26:47 +01:00
|
|
|
|
git ls-files >actual &&
|
2019-12-25 16:59:37 +01:00
|
|
|
|
echo pkg/list/wanted >expect &&
|
|
|
|
|
test_cmp expect actual
|
2019-10-04 03:10:47 +02:00
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2020-03-23 22:47:43 +01:00
|
|
|
|
test_expect_success 'degenerate merge with typechange' '
|
|
|
|
|
test_create_repo degenerate_merge_with_typechange &&
|
|
|
|
|
(
|
|
|
|
|
cd degenerate_merge_with_typechange &&
|
|
|
|
|
|
|
|
|
|
touch irrelevant_file &&
|
|
|
|
|
git add irrelevant_file &&
|
|
|
|
|
git commit -m "Irrelevant, unwanted file"
|
|
|
|
|
git branch A &&
|
|
|
|
|
|
|
|
|
|
git checkout --orphan B &&
|
|
|
|
|
git reset --hard &&
|
|
|
|
|
echo hello >world &&
|
|
|
|
|
git add world &&
|
|
|
|
|
git commit -m "greeting" &&
|
|
|
|
|
echo goodbye >planet &&
|
|
|
|
|
git add planet &&
|
|
|
|
|
git commit -m "farewell" &&
|
|
|
|
|
|
|
|
|
|
git checkout A &&
|
|
|
|
|
git merge --allow-unrelated-histories --no-commit B &&
|
|
|
|
|
rm world &&
|
|
|
|
|
ln -s planet world &&
|
|
|
|
|
git add world &&
|
|
|
|
|
git commit &&
|
|
|
|
|
|
|
|
|
|
git filter-repo --force --path world &&
|
|
|
|
|
test_path_is_missing irrelevant_file &&
|
|
|
|
|
test_path_is_missing planet &&
|
|
|
|
|
echo world >expect &&
|
|
|
|
|
git ls-files >actual &&
|
|
|
|
|
test_cmp expect actual &&
|
|
|
|
|
|
|
|
|
|
test_line_count = 2 <(git log --oneline HEAD)
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2020-01-11 19:36:09 +01:00
|
|
|
|
test_expect_success 'Filtering a blob to make it match previous version' '
|
|
|
|
|
test_create_repo remove_unique_bits_of_blob &&
|
|
|
|
|
(
|
|
|
|
|
cd remove_unique_bits_of_blob &&
|
|
|
|
|
|
|
|
|
|
test_write_lines foo baz >metasyntactic_names &&
|
|
|
|
|
git add metasyntactic_names &&
|
|
|
|
|
git commit -m init &&
|
|
|
|
|
|
|
|
|
|
test_write_lines foo bar baz >metasyntactic_names &&
|
|
|
|
|
git add metasyntactic_names &&
|
|
|
|
|
git commit -m second &&
|
|
|
|
|
|
|
|
|
|
git filter-repo --force --blob-callback "blob.data = blob.data.replace(b\"\\nbar\", b\"\")"
|
|
|
|
|
|
|
|
|
|
echo 1 >expect &&
|
|
|
|
|
git rev-list --count HEAD >actual &&
|
|
|
|
|
test_cmp expect actual
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-10-18 00:23:31 +02:00
|
|
|
|
test_expect_success 'tweaking just a tag' '
|
|
|
|
|
test_create_repo tweaking_just_a_tag &&
|
|
|
|
|
(
|
|
|
|
|
cd tweaking_just_a_tag &&
|
|
|
|
|
|
|
|
|
|
test_commit foo &&
|
|
|
|
|
git tag -a -m "Here is a tag" mytag &&
|
|
|
|
|
|
|
|
|
|
git filter-repo --force --refs mytag ^mytag^{commit} --name-callback "return name.replace(b\"Mitter\", b\"L D\")" &&
|
|
|
|
|
|
|
|
|
|
git cat-file -p mytag | grep C.O.L.D
|
|
|
|
|
)
|
|
|
|
|
'
|
|
|
|
|
|
2019-10-18 18:07:46 +02:00
|
|
|
|
test_expect_success '--version' '
|
|
|
|
|
git filter-repo --version >actual &&
|
|
|
|
|
git hash-object ../../git-filter-repo | colrm 13 >expect &&
|
|
|
|
|
test_cmp expect actual
|
|
|
|
|
'
|
|
|
|
|
|
2018-11-05 15:30:50 +01:00
|
|
|
|
test_done
|