(CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:test_description) op: Equal rhs: {(SQ <"git filter-branch">)} spids: [4] ) ] spids: [4] ) (C {(.)} {(./test-lib.sh)}) (C {(.)} {(DQ ($ VSub_Name "$TEST_DIRECTORY") (/lib-gpg.sh))}) (C {(test_expect_success)} {(SQ <setup>)} { (SQ <"\n"> <"\ttest_commit A &&\n"> <"\tGIT_COMMITTER_DATE=\"@0 +0000\" GIT_AUTHOR_DATE=\"@0 +0000\" &&\n"> <"\ttest_commit --notick B &&\n"> <"\tgit checkout -b branch B &&\n"> <"\ttest_commit D &&\n"> <"\tmkdir dir &&\n"> <"\ttest_commit dir/D &&\n"> <"\ttest_commit E &&\n"> <"\tgit checkout master &&\n"> <"\ttest_commit C &&\n"> <"\tgit checkout branch &&\n"> <"\tgit merge C &&\n"> <"\tgit tag F &&\n"> <"\ttest_commit G &&\n"> <"\ttest_commit H\n"> ) } ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:H) op: Equal rhs: { (CommandSubPart command_list: (CommandList children:[(C {(git)} {(rev-parse)} {(H)})]) left_token: <Left_CommandSub "$("> spids: [82 88] ) } spids: [81] ) ] spids: [81] ) (C {(test_expect_success)} {(SQ <"rewrite identically">)} {(SQ <"\n"> <"\tgit filter-branch branch\n">)} ) (C {(test_expect_success)} {(SQ <"result is really identical">)} {(SQ <"\n"> <"\ttest $H = $(git rev-parse HEAD)\n">)} ) (C {(test_expect_success)} {(SQ <"rewrite bare repository identically">)} { (SQ <"\n"> <"\t(git config core.bare true && cd .git &&\n"> <"\t git filter-branch branch > filter-output 2>&1 &&\n"> <"\t! fgrep fatal filter-output)\n"> ) } ) (C {(git)} {(config)} {(core.bare)} {(false)}) (C {(test_expect_success)} {(SQ <"result is really identical">)} {(SQ <"\n"> <"\ttest $H = $(git rev-parse HEAD)\n">)} ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:TRASHDIR) op: Equal rhs: { (CommandSubPart command_list: (CommandList children:[(C {(pwd)})]) left_token: <Left_CommandSub "$("> spids: [148 150] ) } spids: [147] ) ] spids: [147] ) (C {(test_expect_success)} {(SQ <"correct GIT_DIR while using -d">)} { (SQ <"\n"> <"\tmkdir drepo &&\n"> <"\t( cd drepo &&\n"> <"\tgit init &&\n"> <"\ttest_commit drepo &&\n"> <"\tgit filter-branch -d \"$TRASHDIR/dfoo\" \\\n"> <"\t\t--index-filter \"cp \\\"$TRASHDIR\\\"/dfoo/backup-refs \\\"$TRASHDIR\\\"\" \\\n"> <"\t) &&\n"> <"\tgrep drepo \"$TRASHDIR/backup-refs\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"tree-filter works with -d">)} { (SQ <"\n"> <"\tgit init drepo-tree &&\n"> <"\t(\n"> <"\t\tcd drepo-tree &&\n"> <"\t\ttest_commit one &&\n"> <"\t\tgit filter-branch -d \"$TRASHDIR/dfoo\" \\\n"> <"\t\t\t--tree-filter \"echo changed >one.t\" &&\n"> <"\t\techo changed >expect &&\n"> <"\t\tgit cat-file blob HEAD:one.t >actual &&\n"> <"\t\ttest_cmp expect actual &&\n"> <"\t\ttest_cmp one.t actual\n"> <"\t)\n"> ) } ) (C {(test_expect_success)} {(SQ <"Fail if commit filter fails">)} {(SQ <"\n"> <"\ttest_must_fail git filter-branch -f --commit-filter \"exit 1\" HEAD\n">)} ) (C {(test_expect_success)} {(SQ <"rewrite, renaming a specific file">)} {(SQ <"\n"> <"\tgit filter-branch -f --tree-filter \"mv D.t doh || :\" HEAD\n">)} ) (C {(test_expect_success)} {(SQ <"test that the file was renamed">)} { (SQ <"\n"> <"\ttest D = \"$(git show HEAD:doh --)\" &&\n"> <"\t! test -f D.t &&\n"> <"\ttest -f doh &&\n"> <"\ttest D = \"$(cat doh)\"\n"> ) } ) (C {(test_expect_success)} {(SQ <"rewrite, renaming a specific directory">)} {(SQ <"\n"> <"\tgit filter-branch -f --tree-filter \"mv dir diroh || :\" HEAD\n">)} ) (C {(test_expect_success)} {(SQ <"test that the directory was renamed">)} { (SQ <"\n"> <"\ttest dir/D = \"$(git show HEAD:diroh/D.t --)\" &&\n"> <"\t! test -d dir &&\n"> <"\ttest -d diroh &&\n"> <"\t! test -d diroh/dir &&\n"> <"\ttest -f diroh/D.t &&\n"> <"\ttest dir/D = \"$(cat diroh/D.t)\"\n"> ) } ) (C {(git)} {(tag)} {(oldD)} {(HEAD) (Lit_Tilde "~") (4)}) (C {(test_expect_success)} {(SQ <"rewrite one branch, keeping a side branch">)} { (SQ <"\n"> <"\tgit branch modD oldD &&\n"> <"\tgit filter-branch -f --tree-filter \"mv B.t boh || :\" D..modD\n"> ) } ) (C {(test_expect_success)} {(SQ <"common ancestor is still common (unchanged)">)} {(SQ <"\n"> <"\ttest \"$(git merge-base modD D)\" = \"$(git rev-parse B)\"\n">)} ) (C {(test_expect_success)} {(SQ <"filter subdirectory only">)} { (SQ <"\n"> <"\tmkdir subdir &&\n"> <"\ttouch subdir/new &&\n"> <"\tgit add subdir/new &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"subdir\" &&\n"> <"\techo H > A.t &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"not subdir\" A.t &&\n"> <"\techo A > subdir/new &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"again subdir\" subdir/new &&\n"> <"\tgit rm A.t &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"again not subdir\" &&\n"> <"\tgit branch sub &&\n"> <"\tgit branch sub-earlier HEAD~2 &&\n"> <"\tgit filter-branch -f --subdirectory-filter subdir \\\n"> <"\t\trefs/heads/sub refs/heads/sub-earlier\n"> ) } ) (C {(test_expect_success)} {(SQ <"subdirectory filter result looks okay">)} { (SQ <"\n"> <"\ttest 2 = $(git rev-list sub | wc -l) &&\n"> <"\tgit show sub:new &&\n"> <"\ttest_must_fail git show sub:subdir &&\n"> <"\tgit show sub-earlier:new &&\n"> <"\ttest_must_fail git show sub-earlier:subdir\n"> ) } ) (C {(test_expect_success)} {(SQ <"more setup">)} { (SQ <"\n"> <"\tgit checkout master &&\n"> <"\tmkdir subdir &&\n"> <"\techo A > subdir/new &&\n"> <"\tgit add subdir/new &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"subdir on master\" subdir/new &&\n"> <"\tgit rm A.t &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"again subdir on master\" &&\n"> <"\tgit merge branch\n"> ) } ) (C {(test_expect_success)} {(SQ <"use index-filter to move into a subdirectory">)} { (SQ <"\n"> <"\tgit branch directorymoved &&\n"> <"\tgit filter-branch -f --index-filter \\\n"> <"\t\t \"git ls-files -s | sed \\\"s-\t-&newsubdir/-\\\" |\n"> <"\t GIT_INDEX_FILE=\\$GIT_INDEX_FILE.new \\\n"> <"\t\t\tgit update-index --index-info &&\n"> < "\t\t mv \\\"\\$GIT_INDEX_FILE.new\\\" \\\"\\$GIT_INDEX_FILE\\\"\" directorymoved &&\n" > <"\tgit diff --exit-code HEAD directorymoved:newsubdir\n"> ) } ) (C {(test_expect_success)} {(SQ <"stops when msg filter fails">)} { (SQ <"\n"> <"\told=$(git rev-parse HEAD) &&\n"> <"\ttest_must_fail git filter-branch -f --msg-filter false HEAD &&\n"> <"\ttest $old = $(git rev-parse HEAD) &&\n"> <"\trm -rf .git-rewrite\n"> ) } ) (C {(test_expect_success)} {(SQ <"author information is preserved">)} { (SQ <"\n"> <"\t: > i &&\n"> <"\tgit add i &&\n"> <"\ttest_tick &&\n"> <"\tGIT_AUTHOR_NAME=\"B V Uips\" git commit -m bvuips &&\n"> <"\tgit branch preserved-author &&\n"> <"\t(sane_unset GIT_AUTHOR_NAME &&\n"> <"\t git filter-branch -f --msg-filter \"cat; \\\n"> <"\t\t\ttest \\$GIT_COMMIT != $(git rev-parse master) || \\\n"> <"\t\t\techo Hallo\" \\\n"> <"\t\tpreserved-author) &&\n"> <"\ttest 1 = $(git rev-list --author=\"B V Uips\" preserved-author | wc -l)\n"> ) } ) (C {(test_expect_success)} {(DQ ("remove a certain author's commits"))} { (SQ <"\n"> <"\techo i > i &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m i i &&\n"> <"\tgit branch removed-author &&\n"> <"\tgit filter-branch -f --commit-filter \"\\\n"> <"\t\tif [ \\\"\\$GIT_AUTHOR_NAME\\\" = \\\"B V Uips\\\" ];\\\n"> <"\t\tthen\\\n"> <"\t\t\tskip_commit \\\"\\$@\\\";\n"> <"\t\telse\\\n"> <"\t\t\tgit commit-tree \\\"\\$@\\\";\\\n"> <"\t\tfi\" removed-author &&\n"> <"\tcnt1=$(git rev-list master | wc -l) &&\n"> <"\tcnt2=$(git rev-list removed-author | wc -l) &&\n"> <"\ttest $cnt1 -eq $(($cnt2 + 1)) &&\n"> <"\ttest 0 = $(git rev-list --author=\"B V Uips\" removed-author | wc -l)\n"> ) } ) (C {(test_expect_success)} {(SQ <"barf on invalid name">)} { (SQ <"\n"> <"\ttest_must_fail git filter-branch -f master xy-problem &&\n"> <"\ttest_must_fail git filter-branch -f HEAD^\n"> ) } ) (C {(test_expect_success)} {(SQ <"\"map\" works in commit filter">)} { (SQ <"\n"> <"\tgit filter-branch -f --commit-filter \"\\\n"> <"\t\tparent=\\$(git rev-parse \\$GIT_COMMIT^) &&\n"> <"\t\tmapped=\\$(map \\$parent) &&\n"> <"\t\tactual=\\$(echo \\\"\\$@\\\" | sed \\\"s/^.*-p //\\\") &&\n"> <"\t\ttest \\$mapped = \\$actual &&\n"> <"\t\tgit commit-tree \\\"\\$@\\\";\" master~2..master &&\n"> <"\tgit rev-parse --verify master\n"> ) } ) (C {(test_expect_success)} {(SQ <"Name needing quotes">)} { (SQ <"\n"> <"\n"> <"\tgit checkout -b rerere A &&\n"> <"\tmkdir foo &&\n"> <"\tname=\"\u308c\u308c\u308c\" &&\n"> <"\t>foo/$name &&\n"> <"\tgit add foo &&\n"> <"\tgit commit -m \"Adding a file\" &&\n"> <"\tgit filter-branch --tree-filter \"rm -fr foo\" &&\n"> <"\ttest_must_fail git ls-files --error-unmatch \"foo/$name\" &&\n"> <"\ttest $(git rev-parse --verify rerere) != $(git rev-parse --verify A)\n"> <"\n"> ) } ) (C {(test_expect_success)} {(SQ <"Subdirectory filter with disappearing trees">)} { (SQ <"\n"> <"\tgit reset --hard &&\n"> <"\tgit checkout master &&\n"> <"\n"> <"\tmkdir foo &&\n"> <"\ttouch foo/bar &&\n"> <"\tgit add foo &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"Adding foo\" &&\n"> <"\n"> <"\tgit rm -r foo &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"Removing foo\" &&\n"> <"\n"> <"\tmkdir foo &&\n"> <"\ttouch foo/bar &&\n"> <"\tgit add foo &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -m \"Re-adding foo\" &&\n"> <"\n"> <"\tgit filter-branch -f --subdirectory-filter foo &&\n"> <"\ttest $(git rev-list master | wc -l) = 3\n"> ) } ) (C {(test_expect_success)} {(SQ <"Tag name filtering retains tag message">)} { (SQ <"\n"> <"\tgit tag -m atag T &&\n"> <"\tgit cat-file tag T > expect &&\n"> <"\tgit filter-branch -f --tag-name-filter cat &&\n"> <"\tgit cat-file tag T > actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:faux_gpg_tag) op: Equal rhs: { (SQ <"object XXXXXX\n"> <"type commit\n"> <"tag S\n"> <"tagger T A Gger <tagger@example.com> 1206026339 -0500\n"> <"\n"> <"This is a faux gpg signed tag.\n"> <"-----BEGIN PGP SIGNATURE-----\n"> <"Version: FauxGPG v0.0.0 (FAUX/Linux)\n"> <"\n"> <"gdsfoewhxu/6l06f1kxyxhKdZkrcbaiOMtkJUA9ITAc1mlamh0ooasxkH1XwMbYQ\n"> <"acmwXaWET20H0GeAGP+7vow=\n"> <"=agpO\n"> <"-----END PGP SIGNATURE-----\n"> ) } spids: [544] ) ] spids: [544] ) (C {(test_expect_success)} {(SQ <"Tag name filtering strips gpg signature">)} { (SQ <"\n"> <"\tsha1=$(git rev-parse HEAD) &&\n"> <"\tsha1t=$(echo \"$faux_gpg_tag\" | sed -e s/XXXXXX/$sha1/ | git mktag) &&\n"> <"\tgit update-ref \"refs/tags/S\" \"$sha1t\" &&\n"> <"\techo \"$faux_gpg_tag\" | sed -e s/XXXXXX/$sha1/ | head -n 6 > expect &&\n"> <"\tgit filter-branch -f --tag-name-filter cat &&\n"> <"\tgit cat-file tag S > actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(GPG)} {(SQ <"Filtering retains message of gpg signed commit">)} { (SQ <"\n"> <"\tmkdir gpg &&\n"> <"\ttouch gpg/foo &&\n"> <"\tgit add gpg &&\n"> <"\ttest_tick &&\n"> <"\tgit commit -S -m \"Adding gpg\" &&\n"> <"\n"> <"\tgit log -1 --format=\"%s\" > expect &&\n"> <"\tgit filter-branch -f --msg-filter \"cat\" &&\n"> <"\tgit log -1 --format=\"%s\" > actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"Tag name filtering allows slashes in tag names">)} { (SQ <"\n"> <"\tgit tag -m tag-with-slash X/1 &&\n"> <"\tgit cat-file tag X/1 | sed -e s,X/1,X/2, > expect &&\n"> <"\tgit filter-branch -f --tag-name-filter \"echo X/2\" &&\n"> <"\tgit cat-file tag X/2 > actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"Prune empty commits">)} { (SQ <"\n"> <"\tgit rev-list HEAD > expect &&\n"> <"\ttest_commit to_remove &&\n"> < "\tgit filter-branch -f --index-filter \"git update-index --remove to_remove.t\" --prune-empty HEAD &&\n" > <"\tgit rev-list HEAD > actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"prune empty collapsed merges">)} { (SQ <"\n"> <"\ttest_config merge.ff false &&\n"> <"\tgit rev-list HEAD >expect &&\n"> <"\ttest_commit to_remove_2 &&\n"> <"\tgit reset --hard HEAD^ &&\n"> <"\ttest_merge non-ff to_remove_2 &&\n"> < "\tgit filter-branch -f --index-filter \"git update-index --remove to_remove_2.t\" --prune-empty HEAD &&\n" > <"\tgit rev-list HEAD >actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"prune empty works even without index/tree filters">)} { (SQ <"\n"> <"\tgit rev-list HEAD >expect &&\n"> <"\tgit commit --allow-empty -m empty &&\n"> <"\tgit filter-branch -f --prune-empty HEAD &&\n"> <"\tgit rev-list HEAD >actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"--remap-to-ancestor with filename filters">)} { (SQ <"\n"> <"\tgit checkout master &&\n"> <"\tgit reset --hard A &&\n"> <"\ttest_commit add-foo foo 1 &&\n"> <"\tgit branch moved-foo &&\n"> <"\ttest_commit add-bar bar a &&\n"> <"\tgit branch invariant &&\n"> <"\torig_invariant=$(git rev-parse invariant) &&\n"> <"\tgit branch moved-bar &&\n"> <"\ttest_commit change-foo foo 2 &&\n"> <"\tgit filter-branch -f --remap-to-ancestor \\\n"> <"\t\tmoved-foo moved-bar A..master \\\n"> <"\t\t-- -- foo &&\n"> <"\ttest $(git rev-parse moved-foo) = $(git rev-parse moved-bar) &&\n"> <"\ttest $(git rev-parse moved-foo) = $(git rev-parse master^) &&\n"> <"\ttest $orig_invariant = $(git rev-parse invariant)\n"> ) } ) (C {(test_expect_success)} {(SQ <"automatic remapping to ancestor with filename filters">)} { (SQ <"\n"> <"\tgit checkout master &&\n"> <"\tgit reset --hard A &&\n"> <"\ttest_commit add-foo2 foo 1 &&\n"> <"\tgit branch moved-foo2 &&\n"> <"\ttest_commit add-bar2 bar a &&\n"> <"\tgit branch invariant2 &&\n"> <"\torig_invariant=$(git rev-parse invariant2) &&\n"> <"\tgit branch moved-bar2 &&\n"> <"\ttest_commit change-foo2 foo 2 &&\n"> <"\tgit filter-branch -f \\\n"> <"\t\tmoved-foo2 moved-bar2 A..master \\\n"> <"\t\t-- -- foo &&\n"> <"\ttest $(git rev-parse moved-foo2) = $(git rev-parse moved-bar2) &&\n"> <"\ttest $(git rev-parse moved-foo2) = $(git rev-parse master^) &&\n"> <"\ttest $orig_invariant = $(git rev-parse invariant2)\n"> ) } ) (C {(test_expect_success)} {(SQ <"setup submodule">)} { (SQ <"\n"> <"\trm -fr ?* .git &&\n"> <"\tgit init &&\n"> <"\ttest_commit file &&\n"> <"\tmkdir submod &&\n"> <"\tsubmodurl=\"$PWD/submod\" &&\n"> <"\t( cd submod &&\n"> <"\t git init &&\n"> <"\t test_commit file-in-submod ) &&\n"> <"\tgit submodule add \"$submodurl\" &&\n"> <"\tgit commit -m \"added submodule\" &&\n"> <"\ttest_commit add-file &&\n"> <"\t( cd submod && test_commit add-in-submodule ) &&\n"> <"\tgit add submod &&\n"> <"\tgit commit -m \"changed submodule\" &&\n"> <"\tgit branch original HEAD\n"> ) } ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:orig_head) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [(C {(git)} {(show-ref)} {(--hash)} {(--head)} {(HEAD)})] ) left_token: <Left_CommandSub "$("> spids: [748 758] ) } spids: [747] ) ] spids: [747] ) (C {(test_expect_success)} {(SQ <"rewrite submodule with another content">)} { (SQ <"\n"> <"\tgit filter-branch --tree-filter \"test -d submod && {\n"> <"\t\t\t\t\t rm -rf submod &&\n"> <"\t\t\t\t\t git rm -rf --quiet submod &&\n"> <"\t\t\t\t\t mkdir submod &&\n"> <"\t\t\t\t\t : > submod/file\n"> <"\t\t\t\t\t } || :\" HEAD &&\n"> <"\ttest $orig_head != $(git show-ref --hash --head HEAD)\n"> ) } ) (C {(test_expect_success)} {(SQ <"replace submodule revision">)} { (SQ <"\n"> <"\tgit reset --hard original &&\n"> <"\tgit filter-branch -f --tree-filter \\\n"> <"\t \"if git ls-files --error-unmatch -- submod > /dev/null 2>&1\n"> <"\t then git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 submod\n"> <"\t fi\" HEAD &&\n"> <"\ttest $orig_head != $(git show-ref --hash --head HEAD)\n"> ) } ) (C {(test_expect_success)} {(SQ <"filter commit message without trailing newline">)} { (SQ <"\n"> <"\tgit reset --hard original &&\n"> <"\tcommit=$(printf \"no newline\" | git commit-tree HEAD^{tree}) &&\n"> <"\tgit update-ref refs/heads/no-newline $commit &&\n"> <"\tgit filter-branch -f refs/heads/no-newline &&\n"> <"\techo $commit >expect &&\n"> <"\tgit rev-parse refs/heads/no-newline >actual &&\n"> <"\ttest_cmp expect actual\n"> ) } ) (C {(test_expect_success)} {(SQ <"tree-filter deals with object name vs pathname ambiguity">)} { (SQ <"\n"> <"\ttest_when_finished \"git reset --hard original\" &&\n"> <"\tambiguous=$(git rev-list -1 HEAD) &&\n"> <"\tgit filter-branch --tree-filter \"mv file.t $ambiguous\" HEAD^.. &&\n"> <"\tgit show HEAD:$ambiguous\n"> ) } ) (C {(test_done)}) ] )