{"thread":{"id":"55548","subject":"[PATCH 01/30] .gitignore: Ignore /git-subtree","startedAt":"2021-04-23T19:42:45Z","lastAt":"2021-04-30T16:49:03Z","messageCount":144,"participants":["Luke Shumaker","Eric Sunshine","Danny Lin","=?utf-8?B?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason","Ævar Arnfjörð Bjarmason","Junio C Hamano","Bagas Sanjaya"],"isPatch":true,"patchVersion":1,"patchTotal":30},"messages":[{"id":"422774","messageId":"20210423194230.1388945-2-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 01/30] .gitignore: Ignore /git-subtree","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:01Z","receivedAt":"2021-04-23T19:42:45Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nRunning `make -C contrib/subtree/ test` creates a `git-subtree` executable\nin the root of the repo.  Add it to the .gitignore so that anyone hacking\non subtree won't have to deal with that noise.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n .gitignore | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/.gitignore b/.gitignore\nindex 3dcdb6bb5a..a203678e9e 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -162,6 +162,7 @@\n /git-stripspace\n /git-submodule\n /git-submodule--helper\n+/git-subtree\n /git-svn\n /git-switch\n /git-symbolic-ref\n-- \n2.31.1\n\n"},{"id":"422775","messageId":"20210423194230.1388945-1-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":null,"subject":"[PATCH 00/30] subtree: clean up, improve UX","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:00Z","receivedAt":"2021-04-23T19:42:45Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nOstensibly, this patch set is about improving various aspects of `git\nsubtree`'s user interface (and it is!), but it's also mostly about\nsetting the foundation and being \"batch 1\" of a bunch more changes to\nsubtree that I'm getting queued up.  So please forgive the large\namount of churn in the leading clean-up commits, I promise that\nthere's more work coming on top of it (we've discovered lots of ways\nto break the \"subtree split\" algorithm, and come up with fixes for\nmost of them).  In the mean-time, I do think that the UX improvements\nin this patchset are already worth it themselves.\n\n - The first 11 commits improve subtree's tests, largely around the\n   code-quality of the tests, but a few of the commits do actually\n   improve what's being tested.\n\n - The middle 12 commits improve the code-quality of subtree's\n   implementation.\n\n - The final 7 commits improve various aspects of subtree's user\n   experience, from readability of the debug output, to documentation,\n   to option flag handling.\n\nThe very last commit is likely to be a little objectionable--it makes\nsome option flag parsing more strict, so there will probably be worry\nthat the change breaks existing users.  However, it's being strict\nabout arg combinations that were always invalid, the difference is\nthat now it reports that to the users and bails.  Those users were\nalready broken, they just didn't know it.  `git subtree` should tell\nthem.\n\nAs a final question, would it be all right to amend CI to run the\nsubtree tests?  And if so, what would be the best way to do it?  For\nmy own testing, I just made the following edit to the main Makefile,\nbut I'm not sure it's the mos appropriate approach:\n\n    --- a/Makefile\n    +++ b/Makefile\n    @@ -2836,6 +2836,7 @@\n     \n     test: all\n            $(MAKE) -C t/ all\n    +       $(MAKE) -C contrib/subtree/ test\n     \n     perf: all\n            $(MAKE) -C t/perf/ all\n\nThe first two commits are about getting that to pass.  I'd prefer to\navoid that type of bitrot in the future.\n\nLuke Shumaker (30):\n  .gitignore: Ignore /git-subtree\n  subtree: t7900: update for having the default branch name be 'main'\n  subtree: t7900: use test-lib.sh's test_count\n  subtree: t7900: use consistent formatting\n  subtree: t7900: comment subtree_test_create_repo\n  subtree: t7900: use 'test' for string equality\n  subtree: t7900: delete some dead code\n  subtree: t7900: fix 'verify one file change per commit'\n  subtree: t7900: rename last_commit_message to last_commit_subject\n  subtree: t7900: add a test for the -h flag\n  subtree: t7900: add porcelain tests for 'pull' and 'push'\n  subtree: don't have loose code outside of a function\n  subtree: more consistent error propagation\n  subtree: drop support for git < 1.7\n  subtree: use `git merge-base --is-ancestor`\n  subtree: use git-sh-setup's `say`\n  subtree: use more explicit variable names for cmdline args\n  subtree: use $* instead of $@ as appropriate\n  subtree: give `$(git --exec-path)` precedence over `$PATH`\n  subtree: use \"^{commit}\" instead of \"^0\"\n  subtree: parse revs in individual cmd_ functions\n  subtree: remove duplicate check\n  subtree: add comments and sanity checks\n  subtree: don't let debug and progress output clash\n  subtree: have $indent actually affect indentation\n  subtree: give the docs a once-over\n  subtree: allow --squash to be used with --rejoin\n  subtree: allow 'split' flags to be passed to 'push'\n  subtree: push: allow specifying a local rev other than HEAD\n  subtree: be stricter about validating flags\n\n .gitignore                         |    1 +\n contrib/subtree/git-subtree.sh     |  613 +++++++-----\n contrib/subtree/git-subtree.txt    |  184 ++--\n contrib/subtree/t/t7900-subtree.sh | 1421 ++++++++++++++++++----------\n 4 files changed, 1363 insertions(+), 856 deletions(-)\n\n-- \n2.31.1\n\nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422778","messageId":"20210423194230.1388945-3-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 02/30] subtree: t7900: update for having the default branch name be 'main'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:02Z","receivedAt":"2021-04-23T19:42:45Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nMost of the tests had been converted to support\n`GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main`, but `contrib/subtree/t/`\nhadn't.\n\nConvert it.  Most of the mentions of 'master' can just be replaced with\n'HEAD'.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 117 +++++++++++++++--------------\n 1 file changed, 59 insertions(+), 58 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 57ff4b25c1..4b982e6c2e 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -103,7 +103,7 @@ test_expect_success 'no merge from non-existent subtree' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\ttest_must_fail git subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t)\n '\n@@ -116,8 +116,8 @@ test_expect_success 'no pull from non-existent subtree' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n-\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" master\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD\n \t)'\n \n next_test\n@@ -128,7 +128,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n@@ -142,7 +142,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --me\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n \t)\n@@ -156,7 +156,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P an\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add -P \"sub dir\" -m \"Added subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n \t)\n@@ -170,7 +170,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject with squash\" --squash FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject with squash\"\n \t)\n@@ -188,13 +188,13 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n@@ -208,13 +208,13 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix and -\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject\"\n \t)\n@@ -228,13 +228,13 @@ test_expect_success 'merge new subproj history into sub dir/ with --squash and -\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject using squash\" --squash FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject using squash\"\n \t)\n@@ -248,7 +248,7 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\t# this shouldn not actually do anything, since FETCH_HEAD\n \t\t# is already a parent\n@@ -265,13 +265,13 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende\n \ttest_create_commit \"$test_count/subproj\" sub1 &&\n \t(\n \t\tcd \"$test_count\" &&\n-\t\tgit fetch ./subproj master &&\n+\t\tgit fetch ./subproj HEAD &&\n \t\tgit subtree add --prefix=subdir/ FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$test_count/subproj\" sub2 &&\n \t(\n \t\tcd \"$test_count\" &&\n-\t\tgit fetch ./subproj master &&\n+\t\tgit fetch ./subproj HEAD &&\n \t\tgit subtree merge --prefix=subdir/ FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n@@ -289,7 +289,7 @@ test_expect_success 'split requires option --prefix' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\techo \"You must provide the --prefix option.\" > expected &&\n \t\ttest_must_fail git subtree split > actual 2>&1 &&\n@@ -309,7 +309,7 @@ test_expect_success 'split requires path given by option --prefix must exist' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" > expected &&\n \t\ttest_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 &&\n@@ -329,7 +329,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -338,7 +338,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin &&\n@@ -370,7 +370,7 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -379,7 +379,7 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Split & rejoin\"\n@@ -394,7 +394,7 @@ test_expect_success 'split \"sub dir\"/ with --branch' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -403,7 +403,7 @@ test_expect_success 'split \"sub dir\"/ with --branch' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n@@ -419,7 +419,7 @@ test_expect_success 'check hash of split' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -428,7 +428,7 @@ test_expect_success 'check hash of split' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n@@ -451,7 +451,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch subproj-br FETCH_HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n@@ -461,7 +461,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n@@ -478,7 +478,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n \t(\n \t\tcd \"$subtree_test_count\" &&\n \t\tgit branch init HEAD &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -487,7 +487,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\ttest_must_fail git subtree split --prefix=\"sub dir\" --branch init\n \t)\n@@ -505,7 +505,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the sub\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -514,7 +514,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the sub\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -555,7 +555,7 @@ test_expect_success 'make sure the subproj *only* contains commits that affect t\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -564,7 +564,7 @@ test_expect_success 'make sure the subproj *only* contains commits that affect t\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -606,7 +606,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -615,7 +615,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -643,7 +643,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai\n \t) &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" master &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\ttest_write_lines main1 main2 >chkm &&\n \t\ttest_write_lines main-sub1 main-sub2 main-sub3 main-sub4 >chkms &&\n@@ -666,7 +666,7 @@ test_expect_success 'make sure each filename changed exactly once in the entire\n \t(\n \t\tcd \"$subtree_test_count\" &&\n \t\tgit config log.date relative &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -675,7 +675,7 @@ test_expect_success 'make sure each filename changed exactly once in the entire\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -703,7 +703,7 @@ test_expect_success 'make sure each filename changed exactly once in the entire\n \t) &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" master &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\ttest_write_lines main1 main2 >chkm &&\n \t\ttest_write_lines sub1 sub2 sub3 sub4 >chks &&\n@@ -731,7 +731,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -740,7 +740,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -768,7 +768,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'\n \t) &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" master &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \t\tcheck_equal \"$(git log --pretty=format:\"%s\" HEAD^2 | grep -i split)\" \"\"\n \t)\n '\n@@ -781,7 +781,7 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -790,7 +790,7 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -818,7 +818,7 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n \t) &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" master &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\t# They are meaningless to subproj since one side of the merge refers to the mainline\n \t\tcheck_equal \"$(git log --pretty=format:\"%s%n%b\" HEAD^2 | grep \"git-subtree.*:\")\" \"\"\n@@ -837,13 +837,13 @@ test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch subproj-ref FETCH_HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n@@ -853,7 +853,7 @@ test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n \t\tgit subtree split --prefix=\"sub dir\" --branch subproj-br &&\n \n \t\t# at this point, the new commit parent should be subproj-ref, if it is\n-\t\t# not, something went wrong (the \"newparent\" of \"master~\" commit should\n+\t\t# not, something went wrong (the \"newparent\" of \"HEAD~\" commit should\n \t\t# have been sub2, but it was not, because its cache was not set to\n \t\t# itself)\n \t\tcheck_equal \"$(git log --pretty=format:%P -1 subproj-br)\" \"$(git rev-parse subproj-ref)\"\n@@ -868,13 +868,13 @@ test_expect_success 'split a new subtree without --onto option' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -903,14 +903,14 @@ test_expect_success 'verify one file change per commit' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch sub1 FETCH_HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" sub1\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -947,7 +947,7 @@ test_expect_success 'push split to subproj' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -958,7 +958,7 @@ test_expect_success 'push split to subproj' '\n \t\tcd $subtree_test_count/\"sub proj\" &&\n                 git branch sub-branch-1 &&\n                 cd .. &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n@@ -994,6 +994,7 @@ test_expect_success 'push split to subproj' '\n next_test\n test_expect_success 'subtree descendant check' '\n \tsubtree_test_create_repo \"$subtree_test_count\" &&\n+\tdefaultBranch=$(sed \"s,ref: refs/heads/,,\" \"$subtree_test_count/.git/HEAD\") &&\n \ttest_create_commit \"$subtree_test_count\" folder_subtree/a &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n@@ -1010,7 +1011,7 @@ test_expect_success 'subtree descendant check' '\n \t(\n \t\tcd \"$subtree_test_count\" &&\n \t\tgit cherry-pick $cherry &&\n-\t\tgit checkout master &&\n+\t\tgit checkout $defaultBranch &&\n \t\tgit merge -m \"merge should be kept on subtree\" branch &&\n \t\tgit branch no_subtree_work_branch\n \t) &&\n@@ -1022,10 +1023,10 @@ test_expect_success 'subtree descendant check' '\n \ttest_create_commit \"$subtree_test_count\" not_a_subtree_change &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit checkout master &&\n+\t\tgit checkout $defaultBranch &&\n \t\tgit merge -m \"merge should be skipped on subtree\" no_subtree_work_branch &&\n \n-\t\tgit subtree split --prefix folder_subtree/ --branch subtree_tip master &&\n+\t\tgit subtree split --prefix folder_subtree/ --branch subtree_tip $defaultBranch &&\n \t\tgit subtree split --prefix folder_subtree/ --branch subtree_branch branch &&\n \t\tcheck_equal $(git rev-list --count subtree_tip..subtree_branch) 0\n \t)\n-- \n2.31.1\n\n"},{"id":"422776","messageId":"20210423194230.1388945-5-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 04/30] subtree: t7900: use consistent formatting","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:04Z","receivedAt":"2021-04-23T19:42:46Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThe formatting in t7900-subtree.sh isn't even consistent throughout the\nfile.  Fix that; make it consistent throughout the file.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 47 +++++++++++++-----------------\n 1 file changed, 21 insertions(+), 26 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex a6351d9195..74516513cd 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -11,11 +11,9 @@ and split subcommands of git subtree.\n \n TEST_DIRECTORY=$(pwd)/../../../t\n export TEST_DIRECTORY\n+. \"$TEST_DIRECTORY\"/test-lib.sh\n \n-. ../../../t/test-lib.sh\n-\n-subtree_test_create_repo()\n-{\n+subtree_test_create_repo () {\n \ttest_create_repo \"$1\" &&\n \t(\n \t\tcd \"$1\" &&\n@@ -23,26 +21,24 @@ subtree_test_create_repo()\n \t)\n }\n \n-create()\n-{\n+create () {\n \techo \"$1\" >\"$1\" &&\n \tgit add \"$1\"\n }\n \n-check_equal()\n-{\n+check_equal () {\n \ttest_debug 'echo'\n \ttest_debug \"echo \\\"check a:\\\" \\\"{$1}\\\"\"\n \ttest_debug \"echo \\\"      b:\\\" \\\"{$2}\\\"\"\n-\tif [ \"$1\" = \"$2\" ]; then\n+\tif [ \"$1\" = \"$2\" ]\n+\tthen\n \t\treturn 0\n \telse\n \t\treturn 1\n \tfi\n }\n \n-undo()\n-{\n+undo () {\n \tgit reset --hard HEAD~\n }\n \n@@ -50,8 +46,7 @@ undo()\n # The original set of commits changed only one file each.\n # A multi-file change would imply that we pruned commits\n # too aggressively.\n-join_commits()\n-{\n+join_commits () {\n \tcommit=\n \tall=\n \twhile read x y; do\n@@ -70,7 +65,7 @@ join_commits()\n \techo \"$commit $all\"\n }\n \n-test_create_commit() (\n+test_create_commit () (\n \trepo=$1 &&\n \tcommit=$2 &&\n \tcd \"$repo\" &&\n@@ -81,8 +76,7 @@ test_create_commit() (\n \tgit commit -m \"$commit\" || error \"Could not commit\"\n )\n \n-last_commit_message()\n-{\n+last_commit_message () {\n \tgit log --pretty=format:%s -1\n }\n \n@@ -111,7 +105,8 @@ test_expect_success 'no pull from non-existent subtree' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD\n-\t)'\n+\t)\n+'\n \n test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \tsubtree_test_create_repo \"$test_count\" &&\n@@ -325,7 +320,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n- '\n+'\n \n test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \tsubtree_test_create_repo \"$test_count\" &&\n@@ -340,7 +335,7 @@ test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \t\tgit subtree split --prefix=\"sub dir\" --rejoin &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n- '\n+'\n \n test_expect_success 'split sub dir/ with --rejoin and --message' '\n \tsubtree_test_create_repo \"$test_count\" &&\n@@ -921,18 +916,18 @@ test_expect_success 'push split to subproj' '\n \ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd $test_count/\"sub proj\" &&\n-                git branch sub-branch-1 &&\n-                cd .. &&\n+\t\tgit branch sub-branch-1 &&\n+\t\tcd .. &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n-        (\n+\t(\n \t\tcd \"$test_count\" &&\n-\t        git subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n-                cd ./\"sub proj\" &&\n-                git checkout sub-branch-1 &&\n-         \tcheck_equal \"$(last_commit_message)\" \"sub dir/main-sub3\"\n+\t\tgit subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n+\t\tcd ./\"sub proj\" &&\n+\t\tgit checkout sub-branch-1 &&\n+\t\tcheck_equal \"$(last_commit_message)\" \"sub dir/main-sub3\"\n \t)\n '\n \n-- \n2.31.1\n\n"},{"id":"422777","messageId":"20210423194230.1388945-6-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 05/30] subtree: t7900: comment subtree_test_create_repo","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:05Z","receivedAt":"2021-04-23T19:42:48Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nIt's unclear what the purpose of t7900-subtree.sh's\n`subtree_test_create_repo` helper function is.  It wraps test-lib.sh's,\n`test_create_repo` but follows that up by setting log.date=relative.  Why\ndoes it set log.date=relative?\n\nMy first guess was that at one point the tests required that, but no\nlonger do, and that the function is now vestigial.  I even wrote a patch\nto get rid of it and was moments away from `git send-email`ing it.\n\nHowever, by chance when looking for something else in the history, I\ndiscovered the true reason, from e7aac44ed2 (contrib/subtree: ignore\nlog.date configuration, 2015-07-21).  It's testing that setting\nlog.date=relative doesn't break `git subtree`, as at one point in the past\nthat did break `git subtree`.\n\nSo, add a comment about this, to avoid future such confusion.\n\nAnd while at it, go ahead and touch up the function to avoid a pointless\nsubshell.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 10 ++++++----\n 1 file changed, 6 insertions(+), 4 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 74516513cd..827bd3fcd8 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -13,12 +13,14 @@ TEST_DIRECTORY=$(pwd)/../../../t\n export TEST_DIRECTORY\n . \"$TEST_DIRECTORY\"/test-lib.sh\n \n+# Use our own wrapper around test-lib.sh's test_create_repo, in order\n+# to set log.date=relative.  `git subtree` parses the output of `git\n+# log`, and so it must be careful to not be affected by settings that\n+# change the `git log` output.  We test this by setting\n+# log.date=relative for every repo in the tests.\n subtree_test_create_repo () {\n \ttest_create_repo \"$1\" &&\n-\t(\n-\t\tcd \"$1\" &&\n-\t\tgit config log.date relative\n-\t)\n+\tgit -C \"$1\" config log.date relative\n }\n \n create () {\n-- \n2.31.1\n\n"},{"id":"422781","messageId":"20210423194230.1388945-4-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 03/30] subtree: t7900: use test-lib.sh's test_count","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:03Z","receivedAt":"2021-04-23T19:42:48Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nUse test-lib.sh's `test_count`, instead instead of having\nt7900-subtree.sh do its own book-keeping with `subtree_test_count` that\nhas to be explicitly incremented by calling `next_test`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 636 ++++++++++++++---------------\n 1 file changed, 300 insertions(+), 336 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 4b982e6c2e..a6351d9195 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -86,90 +86,79 @@ last_commit_message()\n \tgit log --pretty=format:%s -1\n }\n \n-subtree_test_count=0\n-next_test() {\n-\tsubtree_test_count=$(($subtree_test_count+1))\n-}\n-\n #\n # Tests for 'git subtree add'\n #\n \n-next_test\n test_expect_success 'no merge from non-existent subtree' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\ttest_must_fail git subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t)\n '\n \n-next_test\n test_expect_success 'no pull from non-existent subtree' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD\n \t)'\n \n-next_test\n test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n-next_test\n test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n \t)\n '\n \n-next_test\n test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P and --message as -m' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add -P \"sub dir\" -m \"Added subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n \t)\n '\n \n-next_test\n test_expect_success 'add subproj as subtree into sub dir/ with --squash and --prefix and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject with squash\" --squash FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject with squash\"\n@@ -180,74 +169,70 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n # Tests for 'git subtree merge'\n #\n \n-next_test\n test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n-next_test\n test_expect_success 'merge new subproj history into sub dir/ with --prefix and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject\"\n \t)\n '\n \n-next_test\n test_expect_success 'merge new subproj history into sub dir/ with --squash and --prefix and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject using squash\" --squash FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject using squash\"\n \t)\n '\n \n-next_test\n test_expect_success 'merge the added subproj again, should do nothing' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\t# this shouldn not actually do anything, since FETCH_HEAD\n@@ -257,7 +242,6 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n \t)\n '\n \n-next_test\n test_expect_success 'merge new subproj history into subdir/ with a slash appended to the argument of --prefix' '\n \ttest_create_repo \"$test_count\" &&\n \ttest_create_repo \"$test_count/subproj\" &&\n@@ -281,14 +265,13 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende\n # Tests for 'git subtree split'\n #\n \n-next_test\n test_expect_success 'split requires option --prefix' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\techo \"You must provide the --prefix option.\" > expected &&\n@@ -301,14 +284,13 @@ test_expect_success 'split requires option --prefix' '\n \t)\n '\n \n-next_test\n test_expect_success 'split requires path given by option --prefix must exist' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" > expected &&\n@@ -321,23 +303,22 @@ test_expect_success 'split requires path given by option --prefix must exist' '\n \t)\n '\n \n-next_test\n test_expect_success 'split sub dir/ with --rejoin' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n@@ -346,12 +327,11 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \t)\n  '\n \n-next_test\n test_expect_success 'split sub dir/ with --rejoin from scratch' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tmkdir \"sub dir\" &&\n \t\techo file >\"sub dir\"/file &&\n \t\tgit add \"sub dir/file\" &&\n@@ -362,23 +342,22 @@ test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \t)\n  '\n \n-next_test\n test_expect_success 'split sub dir/ with --rejoin and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin &&\n@@ -386,23 +365,22 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \t)\n '\n \n-next_test\n test_expect_success 'split \"sub dir\"/ with --branch' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n@@ -411,23 +389,22 @@ test_expect_success 'split \"sub dir\"/ with --branch' '\n \t)\n '\n \n-next_test\n test_expect_success 'check hash of split' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n@@ -443,24 +420,23 @@ test_expect_success 'check hash of split' '\n \t)\n '\n \n-next_test\n test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch subproj-br FETCH_HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n@@ -469,24 +445,23 @@ test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n \t)\n '\n \n-next_test\n test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit branch init HEAD &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\ttest_must_fail git subtree split --prefix=\"sub dir\" --branch init\n@@ -497,46 +472,45 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n # Validity checking\n #\n \n-next_test\n test_expect_success 'make sure exactly the right set of files ends up in the subproj' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD &&\n \n@@ -547,46 +521,45 @@ test_expect_success 'make sure exactly the right set of files ends up in the sub\n \t)\n '\n \n-next_test\n test_expect_success 'make sure the subproj *only* contains commits that affect the \"sub dir\"' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD &&\n \n@@ -598,51 +571,50 @@ test_expect_success 'make sure the subproj *only* contains commits that affect t\n \t)\n '\n \n-next_test\n test_expect_success 'make sure exactly the right set of files ends up in the mainline' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\ttest_write_lines main1 main2 >chkm &&\n@@ -657,52 +629,51 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai\n \t)\n '\n \n-next_test\n test_expect_success 'make sure each filename changed exactly once in the entire history' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit config log.date relative &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\ttest_write_lines main1 main2 >chkm &&\n@@ -723,101 +694,99 @@ test_expect_success 'make sure each filename changed exactly once in the entire\n \t)\n '\n \n-next_test\n test_expect_success 'make sure the --rejoin commits never make it into subproj' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \t\tcheck_equal \"$(git log --pretty=format:\"%s\" HEAD^2 | grep -i split)\" \"\"\n \t)\n '\n \n-next_test\n test_expect_success 'make sure no \"git subtree\" tagged commits make it into subproj' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\t git merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\t# They are meaningless to subproj since one side of the merge refers to the mainline\n@@ -829,27 +798,26 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n # A new set of tests\n #\n \n-next_test\n test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch subproj-ref FETCH_HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --branch subproj-br &&\n \n \t\t# at this point, the new commit parent should be subproj-ref, if it is\n@@ -860,32 +828,31 @@ test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n \t)\n '\n \n-next_test\n test_expect_success 'split a new subtree without --onto option' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --branch subproj-br\n \t) &&\n-\tmkdir \"$subtree_test_count\"/\"sub dir2\" &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir2\"/main-sub2 &&\n+\tmkdir \"$test_count\"/\"sub dir2\" &&\n+\ttest_create_commit \"$test_count\" \"sub dir2\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \n \t\t# also test that we still can split out an entirely new subtree\n \t\t# if the parent of the first commit in the tree is not empty,\n@@ -895,33 +862,32 @@ test_expect_success 'split a new subtree without --onto option' '\n \t)\n '\n \n-next_test\n test_expect_success 'verify one file change per commit' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch sub1 FETCH_HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" sub1\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --branch subproj-br\n \t) &&\n-\tmkdir \"$subtree_test_count\"/\"sub dir2\" &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir2\"/main-sub2 &&\n+\tmkdir \"$test_count\"/\"sub dir2\" &&\n+\ttest_create_commit \"$test_count\" \"sub dir2\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir2\" --branch subproj2-br &&\n \n \t\tx= &&\n@@ -939,31 +905,30 @@ test_expect_success 'verify one file change per commit' '\n \t)\n '\n \n-next_test\n test_expect_success 'push split to subproj' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd $subtree_test_count/\"sub proj\" &&\n+\t\tcd $test_count/\"sub proj\" &&\n                 git branch sub-branch-1 &&\n                 cd .. &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n         (\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t        git subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n                 cd ./\"sub proj\" &&\n                 git checkout sub-branch-1 &&\n@@ -991,38 +956,37 @@ test_expect_success 'push split to subproj' '\n #   set of commits.\n #\n \n-next_test\n test_expect_success 'subtree descendant check' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tdefaultBranch=$(sed \"s,ref: refs/heads/,,\" \"$subtree_test_count/.git/HEAD\") &&\n-\ttest_create_commit \"$subtree_test_count\" folder_subtree/a &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tdefaultBranch=$(sed \"s,ref: refs/heads/,,\" \"$test_count/.git/HEAD\") &&\n+\ttest_create_commit \"$test_count\" folder_subtree/a &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit branch branch\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" folder_subtree/0 &&\n-\ttest_create_commit \"$subtree_test_count\" folder_subtree/b &&\n-\tcherry=$(cd \"$subtree_test_count\"; git rev-parse HEAD) &&\n+\ttest_create_commit \"$test_count\" folder_subtree/0 &&\n+\ttest_create_commit \"$test_count\" folder_subtree/b &&\n+\tcherry=$(cd \"$test_count\"; git rev-parse HEAD) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit checkout branch\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" commit_on_branch &&\n+\ttest_create_commit \"$test_count\" commit_on_branch &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit cherry-pick $cherry &&\n \t\tgit checkout $defaultBranch &&\n \t\tgit merge -m \"merge should be kept on subtree\" branch &&\n \t\tgit branch no_subtree_work_branch\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" folder_subtree/d &&\n+\ttest_create_commit \"$test_count\" folder_subtree/d &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit checkout no_subtree_work_branch\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" not_a_subtree_change &&\n+\ttest_create_commit \"$test_count\" not_a_subtree_change &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit checkout $defaultBranch &&\n \t\tgit merge -m \"merge should be skipped on subtree\" no_subtree_work_branch &&\n \n-- \n2.31.1\n\n"},{"id":"422779","messageId":"20210423194230.1388945-7-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 06/30] subtree: t7900: use 'test' for string equality","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:06Z","receivedAt":"2021-04-23T19:42:49Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nt7900-subtree.sh defines its own `check_equal A B` function, instead of\njust using `test A = B` like all of the other tests.  Don't be special,\nget rid of `check_equal` in favor of `test`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 60 ++++++++++++------------------\n 1 file changed, 24 insertions(+), 36 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 827bd3fcd8..ae96c8cff5 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -28,18 +28,6 @@ create () {\n \tgit add \"$1\"\n }\n \n-check_equal () {\n-\ttest_debug 'echo'\n-\ttest_debug \"echo \\\"check a:\\\" \\\"{$1}\\\"\"\n-\ttest_debug \"echo \\\"      b:\\\" \\\"{$2}\\\"\"\n-\tif [ \"$1\" = \"$2\" ]\n-\tthen\n-\t\treturn 0\n-\telse\n-\t\treturn 1\n-\tfi\n-}\n-\n undo () {\n \tgit reset --hard HEAD~\n }\n@@ -119,7 +107,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -132,7 +120,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --me\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n+\t\ttest \"$(last_commit_message)\" = \"Added subproject\"\n \t)\n '\n \n@@ -145,7 +133,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P an\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add -P \"sub dir\" -m \"Added subproject\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n+\t\ttest \"$(last_commit_message)\" = \"Added subproject\"\n \t)\n '\n \n@@ -158,7 +146,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject with squash\" --squash FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Added subproject with squash\"\n+\t\ttest \"$(last_commit_message)\" = \"Added subproject with squash\"\n \t)\n '\n \n@@ -181,7 +169,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -200,7 +188,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix and -\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject\"\n+\t\ttest \"$(last_commit_message)\" = \"Merged changes from subproject\"\n \t)\n '\n \n@@ -219,7 +207,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --squash and -\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject using squash\" --squash FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject using squash\"\n+\t\ttest \"$(last_commit_message)\" = \"Merged changes from subproject using squash\"\n \t)\n '\n \n@@ -235,7 +223,7 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n \t\t# this shouldn not actually do anything, since FETCH_HEAD\n \t\t# is already a parent\n \t\tresult=$(git merge -s ours -m \"merge -s -ours\" FETCH_HEAD) &&\n-\t\tcheck_equal \"${result}\" \"Already up to date.\"\n+\t\ttest \"${result}\" = \"Already up to date.\"\n \t)\n '\n \n@@ -254,7 +242,7 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./subproj HEAD &&\n \t\tgit subtree merge --prefix=subdir/ FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -320,7 +308,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n '\n \n@@ -335,7 +323,7 @@ test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \t\tgit commit -m\"sub dir file\" &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --rejoin) &&\n \t\tgit subtree split --prefix=\"sub dir\" --rejoin &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n '\n \n@@ -358,7 +346,7 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Split & rejoin\"\n+\t\ttest \"$(last_commit_message)\" = \"Split & rejoin\"\n \t)\n '\n \n@@ -382,7 +370,7 @@ test_expect_success 'split \"sub dir\"/ with --branch' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n-\t\tcheck_equal \"$(git rev-parse subproj-br)\" \"$split_hash\"\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\"\n \t)\n '\n \n@@ -406,13 +394,13 @@ test_expect_success 'check hash of split' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n-\t\tcheck_equal \"$(git rev-parse subproj-br)\" \"$split_hash\" &&\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\" &&\n \t\t# Check hash of split\n \t\tnew_hash=$(git rev-parse subproj-br^2) &&\n \t\t(\n \t\t\tcd ./\"sub proj\" &&\n \t\t\tsubdir_hash=$(git rev-parse HEAD) &&\n-\t\t\tcheck_equal ''\"$new_hash\"'' \"$subdir_hash\"\n+\t\t\ttest ''\"$new_hash\"'' = \"$subdir_hash\"\n \t\t)\n \t)\n '\n@@ -438,7 +426,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n-\t\tcheck_equal \"$(git rev-parse subproj-br)\" \"$split_hash\"\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\"\n \t)\n '\n \n@@ -736,7 +724,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'\n \t(\n \t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n-\t\tcheck_equal \"$(git log --pretty=format:\"%s\" HEAD^2 | grep -i split)\" \"\"\n+\t\ttest \"$(git log --pretty=format:\"%s\" HEAD^2 | grep -i split)\" = \"\"\n \t)\n '\n \n@@ -787,7 +775,7 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\t# They are meaningless to subproj since one side of the merge refers to the mainline\n-\t\tcheck_equal \"$(git log --pretty=format:\"%s%n%b\" HEAD^2 | grep \"git-subtree.*:\")\" \"\"\n+\t\ttest \"$(git log --pretty=format:\"%s%n%b\" HEAD^2 | grep \"git-subtree.*:\")\" = \"\"\n \t)\n '\n \n@@ -821,7 +809,7 @@ test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n \t\t# not, something went wrong (the \"newparent\" of \"HEAD~\" commit should\n \t\t# have been sub2, but it was not, because its cache was not set to\n \t\t# itself)\n-\t\tcheck_equal \"$(git log --pretty=format:%P -1 subproj-br)\" \"$(git rev-parse subproj-ref)\"\n+\t\ttest \"$(git log --pretty=format:%P -1 subproj-br)\" = \"$(git rev-parse subproj-ref)\"\n \t)\n '\n \n@@ -855,7 +843,7 @@ test_expect_success 'split a new subtree without --onto option' '\n \t\t# if the parent of the first commit in the tree is not empty,\n \t\t# then the new subtree has accidentally been attached to something\n \t\tgit subtree split --prefix=\"sub dir2\" --branch subproj2-br &&\n-\t\tcheck_equal \"$(git log --pretty=format:%P -1 subproj2-br)\" \"\"\n+\t\ttest \"$(git log --pretty=format:%P -1 subproj2-br)\" = \"\"\n \t)\n '\n \n@@ -894,10 +882,10 @@ test_expect_success 'verify one file change per commit' '\n \t\t\t\ttest_debug \"echo Verifying commit $commit\"\n \t\t\t\ttest_debug \"echo a: $a\"\n \t\t\t\ttest_debug \"echo b: $b\"\n-\t\t\t\tcheck_equal \"$b\" \"\"\n+\t\t\t\ttest \"$b\" = \"\"\n \t\t\t\tx=1\n \t\t\tdone\n-\t\t\tcheck_equal \"$x\" 1\n+\t\t\ttest \"$x\" = 1\n \t\t)\n \t)\n '\n@@ -929,7 +917,7 @@ test_expect_success 'push split to subproj' '\n \t\tgit subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n \t\tcd ./\"sub proj\" &&\n \t\tgit checkout sub-branch-1 &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"sub dir/main-sub3\"\n+\t\ttest \"$(last_commit_message)\" = \"sub dir/main-sub3\"\n \t)\n '\n \n@@ -989,7 +977,7 @@ test_expect_success 'subtree descendant check' '\n \n \t\tgit subtree split --prefix folder_subtree/ --branch subtree_tip $defaultBranch &&\n \t\tgit subtree split --prefix folder_subtree/ --branch subtree_branch branch &&\n-\t\tcheck_equal $(git rev-list --count subtree_tip..subtree_branch) 0\n+\t\ttest $(git rev-list --count subtree_tip..subtree_branch) = 0\n \t)\n '\n \n-- \n2.31.1\n\n"},{"id":"422780","messageId":"20210423194230.1388945-8-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 07/30] subtree: t7900: delete some dead code","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:07Z","receivedAt":"2021-04-23T19:42:50Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 12 +-----------\n 1 file changed, 1 insertion(+), 11 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex ae96c8cff5..96acd4f8be 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -10,7 +10,6 @@ and split subcommands of git subtree.\n '\n \n TEST_DIRECTORY=$(pwd)/../../../t\n-export TEST_DIRECTORY\n . \"$TEST_DIRECTORY\"/test-lib.sh\n \n # Use our own wrapper around test-lib.sh's test_create_repo, in order\n@@ -23,15 +22,6 @@ subtree_test_create_repo () {\n \tgit -C \"$1\" config log.date relative\n }\n \n-create () {\n-\techo \"$1\" >\"$1\" &&\n-\tgit add \"$1\"\n-}\n-\n-undo () {\n-\tgit reset --hard HEAD~\n-}\n-\n # Make sure no patch changes more than one file.\n # The original set of commits changed only one file each.\n # A multi-file change would imply that we pruned commits\n@@ -400,7 +390,7 @@ test_expect_success 'check hash of split' '\n \t\t(\n \t\t\tcd ./\"sub proj\" &&\n \t\t\tsubdir_hash=$(git rev-parse HEAD) &&\n-\t\t\ttest ''\"$new_hash\"'' = \"$subdir_hash\"\n+\t\t\ttest \"$new_hash\" = \"$subdir_hash\"\n \t\t)\n \t)\n '\n-- \n2.31.1\n\n"},{"id":"422782","messageId":"20210423194230.1388945-9-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 08/30] subtree: t7900: fix 'verify one file change per commit'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:08Z","receivedAt":"2021-04-23T19:42:51Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nAs far as I can tell, this test isn't actually testing anything, because\nsomeone forgot to tack on `--name-only` to `git log`.  This seems to\nhave been the case since the test was first written, back in fa16ab36ad\n(\"test.sh: make sure no commit changes more than one file at a time.\",\n2009-04-26), unless `git log` used to do that by default and didn't need\nthe flag back then?\n\nConvincing myself that it's not actually testing anything was tricky,\nthe code is a little hard to reason about.  It can be made a lot simpler\nif instead of trying to parse all of the info from a single `git log`,\nwe're OK calling `git log` from inside of a loop.  And it's my opinion\nthat tests are not the place for clever optimized code.\n\nSo, fix and simplify the test, so that it's actually testing something\nand is simpler to reason about.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 41 +++++-------------------------\n 1 file changed, 6 insertions(+), 35 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 96acd4f8be..70be18246b 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -22,29 +22,6 @@ subtree_test_create_repo () {\n \tgit -C \"$1\" config log.date relative\n }\n \n-# Make sure no patch changes more than one file.\n-# The original set of commits changed only one file each.\n-# A multi-file change would imply that we pruned commits\n-# too aggressively.\n-join_commits () {\n-\tcommit=\n-\tall=\n-\twhile read x y; do\n-\t\tif [ -z \"$x\" ]; then\n-\t\t\tcontinue\n-\t\telif [ \"$x\" = \"commit:\" ]; then\n-\t\t\tif [ -n \"$commit\" ]; then\n-\t\t\t\techo \"$commit $all\"\n-\t\t\t\tall=\n-\t\t\tfi\n-\t\t\tcommit=\"$y\"\n-\t\telse\n-\t\t\tall=\"$all $y\"\n-\t\tfi\n-\tdone\n-\techo \"$commit $all\"\n-}\n-\n test_create_commit () (\n \trepo=$1 &&\n \tcommit=$2 &&\n@@ -865,18 +842,12 @@ test_expect_success 'verify one file change per commit' '\n \t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir2\" --branch subproj2-br &&\n \n-\t\tx= &&\n-\t\tgit log --pretty=format:\"commit: %H\" | join_commits |\n-\t\t(\n-\t\t\twhile read commit a b; do\n-\t\t\t\ttest_debug \"echo Verifying commit $commit\"\n-\t\t\t\ttest_debug \"echo a: $a\"\n-\t\t\t\ttest_debug \"echo b: $b\"\n-\t\t\t\ttest \"$b\" = \"\"\n-\t\t\t\tx=1\n-\t\t\tdone\n-\t\t\ttest \"$x\" = 1\n-\t\t)\n+\t\tgit log --format=\"%H\" > commit-list &&\n+\t\twhile read commit\n+\t\tdo\n+\t\t\tgit log -n1 --format=\"\" --name-only \"$commit\" >file-list &&\n+\t\t\ttest_line_count -le 1 file-list || return 1\n+\t\tdone <commit-list\n \t)\n '\n \n-- \n2.31.1\n\n"},{"id":"422783","messageId":"20210423194230.1388945-10-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 09/30] subtree: t7900: rename last_commit_message to last_commit_subject","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:09Z","receivedAt":"2021-04-23T19:42:52Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nt7900-subtree.sh defines a helper function named last_commit_message.\nHowever, it only returns the subject line of the commit message, not the\nentire commit message.  So rename it, to make the name less confusing.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 26 +++++++++++++-------------\n 1 file changed, 13 insertions(+), 13 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 70be18246b..4c4d6c8e6b 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -33,7 +33,7 @@ test_create_commit () (\n \tgit commit -m \"$commit\" || error \"Could not commit\"\n )\n \n-last_commit_message () {\n+last_commit_subject () {\n \tgit log --pretty=format:%s -1\n }\n \n@@ -74,7 +74,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -87,7 +87,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --me\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Added subproject\"\n+\t\ttest \"$(last_commit_subject)\" = \"Added subproject\"\n \t)\n '\n \n@@ -100,7 +100,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P an\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add -P \"sub dir\" -m \"Added subproject\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Added subproject\"\n+\t\ttest \"$(last_commit_subject)\" = \"Added subproject\"\n \t)\n '\n \n@@ -113,7 +113,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject with squash\" --squash FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Added subproject with squash\"\n+\t\ttest \"$(last_commit_subject)\" = \"Added subproject with squash\"\n \t)\n '\n \n@@ -136,7 +136,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -155,7 +155,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix and -\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Merged changes from subproject\"\n+\t\ttest \"$(last_commit_subject)\" = \"Merged changes from subproject\"\n \t)\n '\n \n@@ -174,7 +174,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --squash and -\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject using squash\" --squash FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Merged changes from subproject using squash\"\n+\t\ttest \"$(last_commit_subject)\" = \"Merged changes from subproject using squash\"\n \t)\n '\n \n@@ -209,7 +209,7 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./subproj HEAD &&\n \t\tgit subtree merge --prefix=subdir/ FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -275,7 +275,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin &&\n-\t\ttest \"$(last_commit_message)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n '\n \n@@ -290,7 +290,7 @@ test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \t\tgit commit -m\"sub dir file\" &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --rejoin) &&\n \t\tgit subtree split --prefix=\"sub dir\" --rejoin &&\n-\t\ttest \"$(last_commit_message)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n '\n \n@@ -313,7 +313,7 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin &&\n-\t\ttest \"$(last_commit_message)\" = \"Split & rejoin\"\n+\t\ttest \"$(last_commit_subject)\" = \"Split & rejoin\"\n \t)\n '\n \n@@ -878,7 +878,7 @@ test_expect_success 'push split to subproj' '\n \t\tgit subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n \t\tcd ./\"sub proj\" &&\n \t\tgit checkout sub-branch-1 &&\n-\t\ttest \"$(last_commit_message)\" = \"sub dir/main-sub3\"\n+\t\ttest \"$(last_commit_subject)\" = \"sub dir/main-sub3\"\n \t)\n '\n \n-- \n2.31.1\n\n"},{"id":"422784","messageId":"20210423194230.1388945-11-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 10/30] subtree: t7900: add a test for the -h flag","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:10Z","receivedAt":"2021-04-23T19:42:56Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nIt's a dumb test, but it's surprisingly easy to break.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 7 +++++++\n 1 file changed, 7 insertions(+)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 4c4d6c8e6b..6b655ab4b5 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -37,6 +37,13 @@ last_commit_subject () {\n \tgit log --pretty=format:%s -1\n }\n \n+test_expect_success 'shows short help text for -h' '\n+\ttest_expect_code 129 git subtree -h >out 2>err &&\n+\ttest_must_be_empty err &&\n+\tgrep -e \"^ *or: git subtree pull\" out &&\n+\tgrep -e --annotate out\n+'\n+\n #\n # Tests for 'git subtree add'\n #\n-- \n2.31.1\n\n"},{"id":"422785","messageId":"20210423194230.1388945-12-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 11/30] subtree: t7900: add porcelain tests for 'pull' and 'push'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:11Z","receivedAt":"2021-04-23T19:42:56Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThe 'pull' and 'push' subcommands deserve their own sections in the tests.\nAdd some basic tests for them.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 131 ++++++++++++++++++++++++++++-\n 1 file changed, 129 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 6b655ab4b5..3ee0524233 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -202,8 +202,8 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n '\n \n test_expect_success 'merge new subproj history into subdir/ with a slash appended to the argument of --prefix' '\n-\ttest_create_repo \"$test_count\" &&\n-\ttest_create_repo \"$test_count/subproj\" &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/subproj\" &&\n \ttest_create_commit \"$test_count\" main1 &&\n \ttest_create_commit \"$test_count/subproj\" sub1 &&\n \t(\n@@ -427,6 +427,133 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n \t)\n '\n \n+#\n+# Tests for 'git subtree pull'\n+#\n+\n+test_expect_success 'pull requires option --prefix' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\ttest_must_fail git subtree pull ./\"sub proj\" HEAD >out 2>err &&\n+\n+\t\techo \"You must provide the --prefix option.\" >expected &&\n+\t\ttest_must_be_empty out &&\n+\t\ttest_cmp expected err\n+\t)\n+'\n+\n+test_expect_success 'pull requires path given by option --prefix must exist' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD >out 2>err &&\n+\n+\t\techo \"'\\''sub dir'\\'' does not exist; use '\\''git subtree add'\\''\" > expected &&\n+\t\ttest_must_be_empty out &&\n+\t\ttest_cmp expected err\n+\t)\n+'\n+\n+test_expect_success 'pull basic operation' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\texp=$(git -C \"sub proj\" rev-parse --verify HEAD:) &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n+\t\tact=$(git rev-parse --verify HEAD:\"sub dir\") &&\n+\t\ttest \"$act\" = \"$exp\"\n+\t)\n+'\n+\n+#\n+# Tests for 'git subtree push'\n+#\n+\n+test_expect_success 'push requires option --prefix' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\techo \"You must provide the --prefix option.\" > expected &&\n+\t\ttest_must_fail git subtree push \"./sub proj\" from-mainline > actual 2>&1 &&\n+\t\ttest_debug \"printf '\"expected: \"'\" &&\n+\t\ttest_debug \"cat expected\" &&\n+\t\ttest_debug \"printf '\"actual: \"'\" &&\n+\t\ttest_debug \"cat actual\" &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n+test_expect_success 'push requires path given by option --prefix must exist' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" > expected &&\n+\t\ttest_must_fail git subtree push --prefix=non-existent-directory \"./sub proj\" from-mainline > actual 2>&1 &&\n+\t\ttest_debug \"printf '\"expected: \"'\" &&\n+\t\ttest_debug \"cat expected\" &&\n+\t\ttest_debug \"printf '\"actual: \"'\" &&\n+\t\ttest_debug \"cat actual\" &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n+test_expect_success 'push basic operation' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tbefore=$(git rev-parse --verify HEAD) &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" ./\"sub proj\" from-mainline &&\n+\t\ttest \"$before\" = \"$(git rev-parse --verify HEAD)\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n #\n # Validity checking\n #\n-- \n2.31.1\n\n"},{"id":"422786","messageId":"20210423194230.1388945-13-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 12/30] subtree: don't have loose code outside of a function","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:12Z","receivedAt":"2021-04-23T19:42:58Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nShove all of the loose code inside of a main() function.\n\n\"Ignore space change\" is probably helpful when viewing this diff.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 245 +++++++++++++++++----------------\n 1 file changed, 125 insertions(+), 120 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 868e18b9a1..d1ed7f9a6c 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -4,10 +4,7 @@\n #\n # Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com>\n #\n-if test $# -eq 0\n-then\n-\tset -- -h\n-fi\n+\n OPTS_SPEC=\"\\\n git subtree add   --prefix=<prefix> <commit>\n git subtree add   --prefix=<prefix> <repository> <ref>\n@@ -30,12 +27,8 @@ rejoin        merge the new branch back into HEAD\n  options for 'add', 'merge', and 'pull'\n squash        merge subtree changes as a single commit\n \"\n-eval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n \n PATH=$PATH:$(git --exec-path)\n-. git-sh-setup\n-\n-require_work_tree\n \n quiet=\n branch=\n@@ -84,126 +77,138 @@ ensure_single_rev () {\n \tfi\n }\n \n-while test $# -gt 0\n-do\n-\topt=\"$1\"\n-\tshift\n+main () {\n+\tif test $# -eq 0\n+\tthen\n+\t\tset -- -h\n+\tfi\n+\teval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n+\t. git-sh-setup\n+\trequire_work_tree\n \n-\tcase \"$opt\" in\n-\t-q)\n-\t\tquiet=1\n-\t\t;;\n-\t-d)\n-\t\tdebug=1\n-\t\t;;\n-\t--annotate)\n-\t\tannotate=\"$1\"\n-\t\tshift\n-\t\t;;\n-\t--no-annotate)\n-\t\tannotate=\n-\t\t;;\n-\t-b)\n-\t\tbranch=\"$1\"\n-\t\tshift\n-\t\t;;\n-\t-P)\n-\t\tprefix=\"${1%/}\"\n-\t\tshift\n-\t\t;;\n-\t-m)\n-\t\tmessage=\"$1\"\n-\t\tshift\n-\t\t;;\n-\t--no-prefix)\n-\t\tprefix=\n-\t\t;;\n-\t--onto)\n-\t\tonto=\"$1\"\n+\twhile test $# -gt 0\n+\tdo\n+\t\topt=\"$1\"\n \t\tshift\n+\n+\t\tcase \"$opt\" in\n+\t\t-q)\n+\t\t\tquiet=1\n+\t\t\t;;\n+\t\t-d)\n+\t\t\tdebug=1\n+\t\t\t;;\n+\t\t--annotate)\n+\t\t\tannotate=\"$1\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--no-annotate)\n+\t\t\tannotate=\n+\t\t\t;;\n+\t\t-b)\n+\t\t\tbranch=\"$1\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t-P)\n+\t\t\tprefix=\"${1%/}\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t-m)\n+\t\t\tmessage=\"$1\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--no-prefix)\n+\t\t\tprefix=\n+\t\t\t;;\n+\t\t--onto)\n+\t\t\tonto=\"$1\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--no-onto)\n+\t\t\tonto=\n+\t\t\t;;\n+\t\t--rejoin)\n+\t\t\trejoin=1\n+\t\t\t;;\n+\t\t--no-rejoin)\n+\t\t\trejoin=\n+\t\t\t;;\n+\t\t--ignore-joins)\n+\t\t\tignore_joins=1\n+\t\t\t;;\n+\t\t--no-ignore-joins)\n+\t\t\tignore_joins=\n+\t\t\t;;\n+\t\t--squash)\n+\t\t\tsquash=1\n+\t\t\t;;\n+\t\t--no-squash)\n+\t\t\tsquash=\n+\t\t\t;;\n+\t\t--)\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t*)\n+\t\t\tdie \"Unexpected option: $opt\"\n+\t\t\t;;\n+\t\tesac\n+\tdone\n+\n+\tcommand=\"$1\"\n+\tshift\n+\n+\tcase \"$command\" in\n+\tadd|merge|pull)\n+\t\tdefault=\n \t\t;;\n-\t--no-onto)\n-\t\tonto=\n-\t\t;;\n-\t--rejoin)\n-\t\trejoin=1\n-\t\t;;\n-\t--no-rejoin)\n-\t\trejoin=\n-\t\t;;\n-\t--ignore-joins)\n-\t\tignore_joins=1\n-\t\t;;\n-\t--no-ignore-joins)\n-\t\tignore_joins=\n-\t\t;;\n-\t--squash)\n-\t\tsquash=1\n+\tsplit|push)\n+\t\tdefault=\"--default HEAD\"\n \t\t;;\n-\t--no-squash)\n-\t\tsquash=\n+\t*)\n+\t\tdie \"Unknown command '$command'\"\n \t\t;;\n-\t--)\n-\t\tbreak\n+\tesac\n+\n+\tif test -z \"$prefix\"\n+\tthen\n+\t\tdie \"You must provide the --prefix option.\"\n+\tfi\n+\n+\tcase \"$command\" in\n+\tadd)\n+\t\ttest -e \"$prefix\" &&\n+\t\t\tdie \"prefix '$prefix' already exists.\"\n \t\t;;\n \t*)\n-\t\tdie \"Unexpected option: $opt\"\n+\t\ttest -e \"$prefix\" ||\n+\t\t\tdie \"'$prefix' does not exist; use 'git subtree add'\"\n \t\t;;\n \tesac\n-done\n-\n-command=\"$1\"\n-shift\n-\n-case \"$command\" in\n-add|merge|pull)\n-\tdefault=\n-\t;;\n-split|push)\n-\tdefault=\"--default HEAD\"\n-\t;;\n-*)\n-\tdie \"Unknown command '$command'\"\n-\t;;\n-esac\n-\n-if test -z \"$prefix\"\n-then\n-\tdie \"You must provide the --prefix option.\"\n-fi\n-\n-case \"$command\" in\n-add)\n-\ttest -e \"$prefix\" &&\n-\t\tdie \"prefix '$prefix' already exists.\"\n-\t;;\n-*)\n-\ttest -e \"$prefix\" ||\n-\t\tdie \"'$prefix' does not exist; use 'git subtree add'\"\n-\t;;\n-esac\n-\n-dir=\"$(dirname \"$prefix/.\")\"\n-\n-if test \"$command\" != \"pull\" &&\n-\t\ttest \"$command\" != \"add\" &&\n-\t\ttest \"$command\" != \"push\"\n-then\n-\trevs=$(git rev-parse $default --revs-only \"$@\") || exit $?\n-\tdirs=$(git rev-parse --no-revs --no-flags \"$@\") || exit $?\n-\tensure_single_rev $revs\n-\tif test -n \"$dirs\"\n-\tthen\n-\t\tdie \"Error: Use --prefix instead of bare filenames.\"\n-\tfi\n-fi\n-\n-debug \"command: {$command}\"\n-debug \"quiet: {$quiet}\"\n-debug \"revs: {$revs}\"\n-debug \"dir: {$dir}\"\n-debug \"opts: {$*}\"\n-debug\n+\n+\tdir=\"$(dirname \"$prefix/.\")\"\n+\n+\tif test \"$command\" != \"pull\" &&\n+\t\t\ttest \"$command\" != \"add\" &&\n+\t\t\ttest \"$command\" != \"push\"\n+\tthen\n+\t\trevs=$(git rev-parse $default --revs-only \"$@\") || exit $?\n+\t\tdirs=$(git rev-parse --no-revs --no-flags \"$@\") || exit $?\n+\t\tensure_single_rev $revs\n+\t\tif test -n \"$dirs\"\n+\t\tthen\n+\t\t\tdie \"Error: Use --prefix instead of bare filenames.\"\n+\t\tfi\n+\tfi\n+\n+\tdebug \"command: {$command}\"\n+\tdebug \"quiet: {$quiet}\"\n+\tdebug \"revs: {$revs}\"\n+\tdebug \"dir: {$dir}\"\n+\tdebug \"opts: {$*}\"\n+\tdebug\n+\n+\t\"cmd_$command\" \"$@\"\n+}\n \n cache_setup () {\n \tcachedir=\"$GIT_DIR/subtree-cache/$$\"\n@@ -898,4 +903,4 @@ cmd_push () {\n \tfi\n }\n \n-\"cmd_$command\" \"$@\"\n+main \"$@\"\n-- \n2.31.1\n\n"},{"id":"422787","messageId":"20210423194230.1388945-15-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 14/30] subtree: drop support for git < 1.7","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:14Z","receivedAt":"2021-04-23T19:43:00Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThat was nice to have when git-subtree lived out-of-tree.  But now that\nit lives in git.git, it's not nescessary to keep around.\n\n\"Ignore space change\" is probably helpful when viewing this diff.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 19 ++++---------------\n 1 file changed, 4 insertions(+), 15 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 9ca498f81c..4503564f7e 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -852,23 +852,12 @@ cmd_merge () {\n \t\trev=\"$new\"\n \tfi\n \n-\tversion=$(git version)\n-\tif test \"$version\" \\< \"git version 1.7\"\n+\tif test -n \"$message\"\n \tthen\n-\t\tif test -n \"$message\"\n-\t\tthen\n-\t\t\tgit merge -s subtree --message=\"$message\" \"$rev\"\n-\t\telse\n-\t\t\tgit merge -s subtree \"$rev\"\n-\t\tfi\n+\t\tgit merge -Xsubtree=\"$prefix\" \\\n+\t\t    --message=\"$message\" \"$rev\"\n \telse\n-\t\tif test -n \"$message\"\n-\t\tthen\n-\t\t\tgit merge -Xsubtree=\"$prefix\" \\\n-\t\t\t\t--message=\"$message\" \"$rev\"\n-\t\telse\n-\t\t\tgit merge -Xsubtree=\"$prefix\" $rev\n-\t\tfi\n+\t\tgit merge -Xsubtree=\"$prefix\" $rev\n \tfi\n }\n \n-- \n2.31.1\n\n"},{"id":"422788","messageId":"20210423194230.1388945-14-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 13/30] subtree: more consistent error propagation","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:13Z","receivedAt":"2021-04-23T19:43:01Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nEnsure that every $(subshell) that calls a function (as opposed to an\nexternal executable) is followed by `|| exit $?`.  Similarly, ensure that\nevery `cmd | while read; do ... done` loop is followed by `|| exit $?`.\n\nBoth of those constructs mean that it can miss `die` calls, and keep\nrunning when it shouldn't.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 28 ++++++++++++++--------------\n 1 file changed, 14 insertions(+), 14 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex d1ed7f9a6c..9ca498f81c 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -243,7 +243,7 @@ cache_miss () {\n }\n \n check_parents () {\n-\tmissed=$(cache_miss \"$1\")\n+\tmissed=$(cache_miss \"$1\") || exit $?\n \tlocal indent=$(($2 + 1))\n \tfor miss in $missed\n \tdo\n@@ -345,7 +345,7 @@ find_latest_squash () {\n \t\t\tsub=\n \t\t\t;;\n \t\tesac\n-\tdone\n+\tdone || exit $?\n }\n \n find_existing_splits () {\n@@ -394,7 +394,7 @@ find_existing_splits () {\n \t\t\tsub=\n \t\t\t;;\n \t\tesac\n-\tdone\n+\tdone || exit $?\n }\n \n copy_commit () {\n@@ -508,7 +508,7 @@ subtree_for_commit () {\n \t\ttest \"$type\" = \"commit\" && continue  # ignore submodules\n \t\techo $tree\n \t\tbreak\n-\tdone\n+\tdone || exit $?\n }\n \n tree_changed () {\n@@ -518,7 +518,7 @@ tree_changed () {\n \tthen\n \t\treturn 0   # weird parents, consider it changed\n \telse\n-\t\tptree=$(toptree_for_commit $1)\n+\t\tptree=$(toptree_for_commit $1) || exit $?\n \t\tif test \"$ptree\" != \"$tree\"\n \t\tthen\n \t\t\treturn 0   # changed\n@@ -652,7 +652,7 @@ process_split_commit () {\n \tprogress \"$revcount/$revmax ($createcount) [$extracount]\"\n \n \tdebug \"Processing commit: $rev\"\n-\texists=$(cache_get \"$rev\")\n+\texists=$(cache_get \"$rev\") || exit $?\n \tif test -n \"$exists\"\n \tthen\n \t\tdebug \"  prior: $exists\"\n@@ -661,10 +661,10 @@ process_split_commit () {\n \tcreatecount=$(($createcount + 1))\n \tdebug \"  parents: $parents\"\n \tcheck_parents \"$parents\" \"$indent\"\n-\tnewparents=$(cache_get $parents)\n+\tnewparents=$(cache_get $parents) || exit $?\n \tdebug \"  newparents: $newparents\"\n \n-\ttree=$(subtree_for_commit \"$rev\" \"$dir\")\n+\ttree=$(subtree_for_commit \"$rev\" \"$dir\") || exit $?\n \tdebug \"  tree is: $tree\"\n \n \t# ugly.  is there no better way to tell if this is a subtree\n@@ -750,7 +750,7 @@ cmd_add_commit () {\n \t\tcommit=$(add_squashed_msg \"$rev\" \"$dir\" |\n \t\t\tgit commit-tree \"$tree\" $headp -p \"$rev\") || exit $?\n \telse\n-\t\trevp=$(peel_committish \"$rev\") &&\n+\t\trevp=$(peel_committish \"$rev\") || exit $?\n \t\tcommit=$(add_msg \"$dir\" $headrev \"$rev\" |\n \t\t\tgit commit-tree \"$tree\" $headp -p \"$revp\") || exit $?\n \tfi\n@@ -773,10 +773,10 @@ cmd_split () {\n \t\t\t# any parent we find there can be used verbatim\n \t\t\tdebug \"  cache: $rev\"\n \t\t\tcache_set \"$rev\" \"$rev\"\n-\t\tdone\n+\t\tdone || exit $?\n \tfi\n \n-\tunrevs=\"$(find_existing_splits \"$dir\" \"$revs\")\"\n+\tunrevs=\"$(find_existing_splits \"$dir\" \"$revs\")\" || exit $?\n \n \t# We can't restrict rev-list to only $dir here, because some of our\n \t# parents have the $dir contents the root, and those won't match.\n@@ -792,7 +792,7 @@ cmd_split () {\n \t\tprocess_split_commit \"$rev\" \"$parents\" 0\n \tdone || exit $?\n \n-\tlatest_new=$(cache_get latest_new)\n+\tlatest_new=$(cache_get latest_new) || exit $?\n \tif test -z \"$latest_new\"\n \tthen\n \t\tdie \"No new revisions were found\"\n@@ -801,7 +801,7 @@ cmd_split () {\n \tif test -n \"$rejoin\"\n \tthen\n \t\tdebug \"Merging split branch into HEAD...\"\n-\t\tlatest_old=$(cache_get latest_old)\n+\t\tlatest_old=$(cache_get latest_old) || exit $?\n \t\tgit merge -s ours \\\n \t\t\t--allow-unrelated-histories \\\n \t\t\t-m \"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" \\\n@@ -834,7 +834,7 @@ cmd_merge () {\n \n \tif test -n \"$squash\"\n \tthen\n-\t\tfirst_split=\"$(find_latest_squash \"$dir\")\"\n+\t\tfirst_split=\"$(find_latest_squash \"$dir\")\" || exit $?\n \t\tif test -z \"$first_split\"\n \t\tthen\n \t\t\tdie \"Can't squash-merge: '$dir' was never added.\"\n-- \n2.31.1\n\n"},{"id":"422789","messageId":"20210423194230.1388945-16-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 15/30] subtree: use `git merge-base --is-ancestor`","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:15Z","receivedAt":"2021-04-23T19:43:02Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nInstead of writing a slow `rev_is_descendant_of_branch $a $b` function\nin shell, just use the fast `git merge-base --is-ancestor $b $a`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 16 +---------------\n 1 file changed, 1 insertion(+), 15 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 4503564f7e..70e16b807b 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -280,20 +280,6 @@ rev_exists () {\n \tfi\n }\n \n-rev_is_descendant_of_branch () {\n-\tnewrev=\"$1\"\n-\tbranch=\"$2\"\n-\tbranch_hash=$(git rev-parse \"$branch\")\n-\tmatch=$(git rev-list -1 \"$branch_hash\" \"^$newrev\")\n-\n-\tif test -z \"$match\"\n-\tthen\n-\t\treturn 0\n-\telse\n-\t\treturn 1\n-\tfi\n-}\n-\n # if a commit doesn't have a parent, this might not work.  But we only want\n # to remove the parent from the rev-list, and since it doesn't exist, it won't\n # be there anyway, so do nothing in that case.\n@@ -811,7 +797,7 @@ cmd_split () {\n \tthen\n \t\tif rev_exists \"refs/heads/$branch\"\n \t\tthen\n-\t\t\tif ! rev_is_descendant_of_branch \"$latest_new\" \"$branch\"\n+\t\t\tif ! git merge-base --is-ancestor \"$branch\" \"$latest_new\"\n \t\t\tthen\n \t\t\t\tdie \"Branch '$branch' is not an ancestor of commit '$latest_new'.\"\n \t\t\tfi\n-- \n2.31.1\n\n"},{"id":"422790","messageId":"20210423194230.1388945-17-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 16/30] subtree: use git-sh-setup's `say`","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:16Z","receivedAt":"2021-04-23T19:43:03Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nsubtree currently defines its own `say` implementation, rather than\nusing git-sh-setups's implementation.  Change that, don't re-invent the\nwheel.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 22 +++++++---------------\n 1 file changed, 7 insertions(+), 15 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 70e16b807b..bb4934dbc0 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -30,7 +30,6 @@ squash        merge subtree changes as a single commit\n \n PATH=$PATH:$(git --exec-path)\n \n-quiet=\n branch=\n debug=\n command=\n@@ -49,15 +48,8 @@ debug () {\n \tfi\n }\n \n-say () {\n-\tif test -z \"$quiet\"\n-\tthen\n-\t\tprintf \"%s\\n\" \"$*\" >&2\n-\tfi\n-}\n-\n progress () {\n-\tif test -z \"$quiet\"\n+\tif test -z \"$GIT_QUIET\"\n \tthen\n \t\tprintf \"%s\\r\" \"$*\" >&2\n \tfi\n@@ -93,7 +85,7 @@ main () {\n \n \t\tcase \"$opt\" in\n \t\t-q)\n-\t\t\tquiet=1\n+\t\t\tGIT_QUIET=1\n \t\t\t;;\n \t\t-d)\n \t\t\tdebug=1\n@@ -201,7 +193,7 @@ main () {\n \tfi\n \n \tdebug \"command: {$command}\"\n-\tdebug \"quiet: {$quiet}\"\n+\tdebug \"quiet: {$GIT_QUIET}\"\n \tdebug \"revs: {$revs}\"\n \tdebug \"dir: {$dir}\"\n \tdebug \"opts: {$*}\"\n@@ -698,7 +690,7 @@ cmd_add () {\n \n \t\tcmd_add_repository \"$@\"\n \telse\n-\t\tsay \"error: parameters were '$@'\"\n+\t\tsay >&2 \"error: parameters were '$@'\"\n \t\tdie \"Provide either a commit or a repository and commit.\"\n \tfi\n }\n@@ -742,7 +734,7 @@ cmd_add_commit () {\n \tfi\n \tgit reset \"$commit\" || exit $?\n \n-\tsay \"Added dir '$dir'\"\n+\tsay >&2 \"Added dir '$dir'\"\n }\n \n cmd_split () {\n@@ -807,7 +799,7 @@ cmd_split () {\n \t\tfi\n \t\tgit update-ref -m 'subtree split' \\\n \t\t\t\"refs/heads/$branch\" \"$latest_new\" || exit $?\n-\t\tsay \"$action branch '$branch'\"\n+\t\tsay >&2 \"$action branch '$branch'\"\n \tfi\n \techo \"$latest_new\"\n \texit 0\n@@ -830,7 +822,7 @@ cmd_merge () {\n \t\tsub=$2\n \t\tif test \"$sub\" = \"$rev\"\n \t\tthen\n-\t\t\tsay \"Subtree is already at commit $rev.\"\n+\t\t\tsay >&2 \"Subtree is already at commit $rev.\"\n \t\t\texit 0\n \t\tfi\n \t\tnew=$(new_squash_commit \"$old\" \"$sub\" \"$rev\") || exit $?\n-- \n2.31.1\n\n"},{"id":"422791","messageId":"20210423194230.1388945-18-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 17/30] subtree: use more explicit variable names for cmdline args","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:17Z","receivedAt":"2021-04-23T19:43:05Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nMake it painfully obvious when reading the code which variables are\ndirect parsings of command line arguments.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 132 ++++++++++++++++-----------------\n 1 file changed, 66 insertions(+), 66 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex bb4934dbc0..d7de4b0653 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -30,19 +30,19 @@ squash        merge subtree changes as a single commit\n \n PATH=$PATH:$(git --exec-path)\n \n-branch=\n-debug=\n-command=\n-onto=\n-rejoin=\n-ignore_joins=\n-annotate=\n-squash=\n-message=\n-prefix=\n+arg_debug=\n+arg_command=\n+arg_prefix=\n+arg_split_branch=\n+arg_split_onto=\n+arg_split_rejoin=\n+arg_split_ignore_joins=\n+arg_split_annotate=\n+arg_addmerge_squash=\n+arg_addmerge_message=\n \n debug () {\n-\tif test -n \"$debug\"\n+\tif test -n \"$arg_debug\"\n \tthen\n \t\tprintf \"%s\\n\" \"$*\" >&2\n \tfi\n@@ -88,54 +88,54 @@ main () {\n \t\t\tGIT_QUIET=1\n \t\t\t;;\n \t\t-d)\n-\t\t\tdebug=1\n+\t\t\targ_debug=1\n \t\t\t;;\n \t\t--annotate)\n-\t\t\tannotate=\"$1\"\n+\t\t\targ_split_annotate=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-annotate)\n-\t\t\tannotate=\n+\t\t\targ_split_annotate=\n \t\t\t;;\n \t\t-b)\n-\t\t\tbranch=\"$1\"\n+\t\t\targ_split_branch=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t-P)\n-\t\t\tprefix=\"${1%/}\"\n+\t\t\targ_prefix=\"${1%/}\"\n \t\t\tshift\n \t\t\t;;\n \t\t-m)\n-\t\t\tmessage=\"$1\"\n+\t\t\targ_addmerge_message=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-prefix)\n-\t\t\tprefix=\n+\t\t\targ_prefix=\n \t\t\t;;\n \t\t--onto)\n-\t\t\tonto=\"$1\"\n+\t\t\targ_split_onto=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-onto)\n-\t\t\tonto=\n+\t\t\targ_split_onto=\n \t\t\t;;\n \t\t--rejoin)\n-\t\t\trejoin=1\n+\t\t\targ_split_rejoin=1\n \t\t\t;;\n \t\t--no-rejoin)\n-\t\t\trejoin=\n+\t\t\targ_split_rejoin=\n \t\t\t;;\n \t\t--ignore-joins)\n-\t\t\tignore_joins=1\n+\t\t\targ_split_ignore_joins=1\n \t\t\t;;\n \t\t--no-ignore-joins)\n-\t\t\tignore_joins=\n+\t\t\targ_split_ignore_joins=\n \t\t\t;;\n \t\t--squash)\n-\t\t\tsquash=1\n+\t\t\targ_addmerge_squash=1\n \t\t\t;;\n \t\t--no-squash)\n-\t\t\tsquash=\n+\t\t\targ_addmerge_squash=\n \t\t\t;;\n \t\t--)\n \t\t\tbreak\n@@ -146,10 +146,10 @@ main () {\n \t\tesac\n \tdone\n \n-\tcommand=\"$1\"\n+\targ_command=\"$1\"\n \tshift\n \n-\tcase \"$command\" in\n+\tcase \"$arg_command\" in\n \tadd|merge|pull)\n \t\tdefault=\n \t\t;;\n@@ -157,31 +157,31 @@ main () {\n \t\tdefault=\"--default HEAD\"\n \t\t;;\n \t*)\n-\t\tdie \"Unknown command '$command'\"\n+\t\tdie \"Unknown command '$arg_command'\"\n \t\t;;\n \tesac\n \n-\tif test -z \"$prefix\"\n+\tif test -z \"$arg_prefix\"\n \tthen\n \t\tdie \"You must provide the --prefix option.\"\n \tfi\n \n-\tcase \"$command\" in\n+\tcase \"$arg_command\" in\n \tadd)\n-\t\ttest -e \"$prefix\" &&\n-\t\t\tdie \"prefix '$prefix' already exists.\"\n+\t\ttest -e \"$arg_prefix\" &&\n+\t\t\tdie \"prefix '$arg_prefix' already exists.\"\n \t\t;;\n \t*)\n-\t\ttest -e \"$prefix\" ||\n-\t\t\tdie \"'$prefix' does not exist; use 'git subtree add'\"\n+\t\ttest -e \"$arg_prefix\" ||\n+\t\t\tdie \"'$arg_prefix' does not exist; use 'git subtree add'\"\n \t\t;;\n \tesac\n \n-\tdir=\"$(dirname \"$prefix/.\")\"\n+\tdir=\"$(dirname \"$arg_prefix/.\")\"\n \n-\tif test \"$command\" != \"pull\" &&\n-\t\t\ttest \"$command\" != \"add\" &&\n-\t\t\ttest \"$command\" != \"push\"\n+\tif test \"$arg_command\" != \"pull\" &&\n+\t\t\ttest \"$arg_command\" != \"add\" &&\n+\t\t\ttest \"$arg_command\" != \"push\"\n \tthen\n \t\trevs=$(git rev-parse $default --revs-only \"$@\") || exit $?\n \t\tdirs=$(git rev-parse --no-revs --no-flags \"$@\") || exit $?\n@@ -192,14 +192,14 @@ main () {\n \t\tfi\n \tfi\n \n-\tdebug \"command: {$command}\"\n+\tdebug \"command: {$arg_command}\"\n \tdebug \"quiet: {$GIT_QUIET}\"\n \tdebug \"revs: {$revs}\"\n \tdebug \"dir: {$dir}\"\n \tdebug \"opts: {$*}\"\n \tdebug\n \n-\t\"cmd_$command\" \"$@\"\n+\t\"cmd_$arg_command\" \"$@\"\n }\n \n cache_setup () {\n@@ -333,7 +333,7 @@ find_existing_splits () {\n \tmain=\n \tsub=\n \tlocal grep_format=\"^git-subtree-dir: $dir/*\\$\"\n-\tif test -n \"$ignore_joins\"\n+\tif test -n \"$arg_split_ignore_joins\"\n \tthen\n \t\tgrep_format=\"^Add '$dir/' from commit '\"\n \tfi\n@@ -394,7 +394,7 @@ copy_commit () {\n \t\t\tGIT_COMMITTER_EMAIL \\\n \t\t\tGIT_COMMITTER_DATE\n \t\t(\n-\t\t\tprintf \"%s\" \"$annotate\"\n+\t\t\tprintf \"%s\" \"$arg_split_annotate\"\n \t\t\tcat\n \t\t) |\n \t\tgit commit-tree \"$2\" $3  # reads the rest of stdin\n@@ -405,9 +405,9 @@ add_msg () {\n \tdir=\"$1\"\n \tlatest_old=\"$2\"\n \tlatest_new=\"$3\"\n-\tif test -n \"$message\"\n+\tif test -n \"$arg_addmerge_message\"\n \tthen\n-\t\tcommit_message=\"$message\"\n+\t\tcommit_message=\"$arg_addmerge_message\"\n \telse\n \t\tcommit_message=\"Add '$dir/' from commit '$latest_new'\"\n \tfi\n@@ -421,9 +421,9 @@ add_msg () {\n }\n \n add_squashed_msg () {\n-\tif test -n \"$message\"\n+\tif test -n \"$arg_addmerge_message\"\n \tthen\n-\t\techo \"$message\"\n+\t\techo \"$arg_addmerge_message\"\n \telse\n \t\techo \"Merge commit '$1' as '$2'\"\n \tfi\n@@ -433,9 +433,9 @@ rejoin_msg () {\n \tdir=\"$1\"\n \tlatest_old=\"$2\"\n \tlatest_new=\"$3\"\n-\tif test -n \"$message\"\n+\tif test -n \"$arg_addmerge_message\"\n \tthen\n-\t\tcommit_message=\"$message\"\n+\t\tcommit_message=\"$arg_addmerge_message\"\n \telse\n \t\tcommit_message=\"Split '$dir/' into commit '$latest_new'\"\n \tfi\n@@ -722,7 +722,7 @@ cmd_add_commit () {\n \t\theadp=\n \tfi\n \n-\tif test -n \"$squash\"\n+\tif test -n \"$arg_addmerge_squash\"\n \tthen\n \t\trev=$(new_squash_commit \"\" \"\" \"$rev\") || exit $?\n \t\tcommit=$(add_squashed_msg \"$rev\" \"$dir\" |\n@@ -741,10 +741,10 @@ cmd_split () {\n \tdebug \"Splitting $dir...\"\n \tcache_setup || exit $?\n \n-\tif test -n \"$onto\"\n+\tif test -n \"$arg_split_onto\"\n \tthen\n-\t\tdebug \"Reading history for --onto=$onto...\"\n-\t\tgit rev-list $onto |\n+\t\tdebug \"Reading history for --onto=$arg_split_onto...\"\n+\t\tgit rev-list $arg_split_onto |\n \t\twhile read rev\n \t\tdo\n \t\t\t# the 'onto' history is already just the subdir, so\n@@ -776,7 +776,7 @@ cmd_split () {\n \t\tdie \"No new revisions were found\"\n \tfi\n \n-\tif test -n \"$rejoin\"\n+\tif test -n \"$arg_split_rejoin\"\n \tthen\n \t\tdebug \"Merging split branch into HEAD...\"\n \t\tlatest_old=$(cache_get latest_old) || exit $?\n@@ -785,21 +785,21 @@ cmd_split () {\n \t\t\t-m \"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" \\\n \t\t\t\"$latest_new\" >&2 || exit $?\n \tfi\n-\tif test -n \"$branch\"\n+\tif test -n \"$arg_split_branch\"\n \tthen\n-\t\tif rev_exists \"refs/heads/$branch\"\n+\t\tif rev_exists \"refs/heads/$arg_split_branch\"\n \t\tthen\n-\t\t\tif ! git merge-base --is-ancestor \"$branch\" \"$latest_new\"\n+\t\t\tif ! git merge-base --is-ancestor \"$arg_split_branch\" \"$latest_new\"\n \t\t\tthen\n-\t\t\t\tdie \"Branch '$branch' is not an ancestor of commit '$latest_new'.\"\n+\t\t\t\tdie \"Branch '$arg_split_branch' is not an ancestor of commit '$latest_new'.\"\n \t\t\tfi\n \t\t\taction='Updated'\n \t\telse\n \t\t\taction='Created'\n \t\tfi\n \t\tgit update-ref -m 'subtree split' \\\n-\t\t\t\"refs/heads/$branch\" \"$latest_new\" || exit $?\n-\t\tsay >&2 \"$action branch '$branch'\"\n+\t\t\t\"refs/heads/$arg_split_branch\" \"$latest_new\" || exit $?\n+\t\tsay >&2 \"$action branch '$arg_split_branch'\"\n \tfi\n \techo \"$latest_new\"\n \texit 0\n@@ -810,7 +810,7 @@ cmd_merge () {\n \tensure_single_rev $rev\n \tensure_clean\n \n-\tif test -n \"$squash\"\n+\tif test -n \"$arg_addmerge_squash\"\n \tthen\n \t\tfirst_split=\"$(find_latest_squash \"$dir\")\" || exit $?\n \t\tif test -z \"$first_split\"\n@@ -830,12 +830,12 @@ cmd_merge () {\n \t\trev=\"$new\"\n \tfi\n \n-\tif test -n \"$message\"\n+\tif test -n \"$arg_addmerge_message\"\n \tthen\n-\t\tgit merge -Xsubtree=\"$prefix\" \\\n-\t\t    --message=\"$message\" \"$rev\"\n+\t\tgit merge -Xsubtree=\"$arg_prefix\" \\\n+\t\t\t--message=\"$arg_addmerge_message\" \"$rev\"\n \telse\n-\t\tgit merge -Xsubtree=\"$prefix\" $rev\n+\t\tgit merge -Xsubtree=\"$arg_prefix\" $rev\n \tfi\n }\n \n@@ -863,7 +863,7 @@ cmd_push () {\n \t\trepository=$1\n \t\trefspec=$2\n \t\techo \"git push using: \" \"$repository\" \"$refspec\"\n-\t\tlocalrev=$(git subtree split --prefix=\"$prefix\") || die\n+\t\tlocalrev=$(git subtree split --prefix=\"$arg_prefix\") || die\n \t\tgit push \"$repository\" \"$localrev\":\"refs/heads/$refspec\"\n \telse\n \t\tdie \"'$dir' must already exist. Try 'git subtree add'.\"\n-- \n2.31.1\n\n"},{"id":"422792","messageId":"20210423194230.1388945-19-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 18/30] subtree: use $* instead of $@ as appropriate","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:18Z","receivedAt":"2021-04-23T19:43:06Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\n$* is for when you want to smash things together, whitespace-separated;\n$@ is for when you want them to be separate strings.  There are a couple\nof places in subtree that erroneously use $@ when smashing args together\nin to an error message.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex d7de4b0653..3105eb8033 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -58,14 +58,14 @@ progress () {\n assert () {\n \tif ! \"$@\"\n \tthen\n-\t\tdie \"assertion failed: \" \"$@\"\n+\t\tdie \"assertion failed: $*\"\n \tfi\n }\n \n ensure_single_rev () {\n \tif test $# -ne 1\n \tthen\n-\t\tdie \"You must provide exactly one revision.  Got: '$@'\"\n+\t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n \tfi\n }\n \n@@ -690,7 +690,7 @@ cmd_add () {\n \n \t\tcmd_add_repository \"$@\"\n \telse\n-\t\tsay >&2 \"error: parameters were '$@'\"\n+\t\tsay >&2 \"error: parameters were '$*'\"\n \t\tdie \"Provide either a commit or a repository and commit.\"\n \tfi\n }\n-- \n2.31.1\n\n"},{"id":"422793","messageId":"20210423194230.1388945-20-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 19/30] subtree: give `$(git --exec-path)` precedence over `$PATH`","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:19Z","receivedAt":"2021-04-23T19:43:07Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nOther Git commands implemented in shell give `git --exec-path`\nprecedence over the existing $PATH, but subtree gives the existing $PATH\nprecedence.  Flip subtree's PATH around to match what other commands do.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 3105eb8033..9d365c9f2f 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -28,7 +28,7 @@ rejoin        merge the new branch back into HEAD\n squash        merge subtree changes as a single commit\n \"\n \n-PATH=$PATH:$(git --exec-path)\n+PATH=$(git --exec-path):$PATH\n \n arg_debug=\n arg_command=\n-- \n2.31.1\n\n"},{"id":"422794","messageId":"20210423194230.1388945-21-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 20/30] subtree: use \"^{commit}\" instead of \"^0\"","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:20Z","receivedAt":"2021-04-23T19:43:09Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThey are synonyms.  Both are used in the file.  ^{commit} is clearer, so\n\"standardize\" on that.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 9d365c9f2f..d200fbfed7 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -302,7 +302,7 @@ find_latest_squash () {\n \t\t\tmain=\"$b\"\n \t\t\t;;\n \t\tgit-subtree-split:)\n-\t\t\tsub=\"$(git rev-parse \"$b^0\")\" ||\n+\t\t\tsub=\"$(git rev-parse \"$b^{commit}\")\" ||\n \t\t\tdie \"could not rev-parse split hash $b from commit $sq\"\n \t\t\t;;\n \t\tEND)\n@@ -349,7 +349,7 @@ find_existing_splits () {\n \t\t\tmain=\"$b\"\n \t\t\t;;\n \t\tgit-subtree-split:)\n-\t\t\tsub=\"$(git rev-parse \"$b^0\")\" ||\n+\t\t\tsub=\"$(git rev-parse \"$b^{commit}\")\" ||\n \t\t\tdie \"could not rev-parse split hash $b from commit $sq\"\n \t\t\t;;\n \t\tEND)\n-- \n2.31.1\n\n"},{"id":"422795","messageId":"20210423194230.1388945-22-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 21/30] subtree: parse revs in individual cmd_ functions","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:21Z","receivedAt":"2021-04-23T19:43:11Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThe main argument parser goes ahead and tries to parse revs to make\nthings simpler for the sub-command implementations.  But, it includes\nenough special cases for different sub-commands.  And it's difficult\nhaving having to think about \"is this info coming from an argument, or a\nglobal variable?\".  So the main argument parser's effort to make things\n\"simpler\" ends up just making it more confusing and complicated.\n\nBegone with the 'revs' global variable; parse 'rev=$(...)' as needed in\nindividual 'cmd_*' functions.\n\nBegone with the 'default' global variable.  Its would-be value is\nknowable just from which function we're in.\n\nBegone with the 'ensure_single_rev' function.  Its functionality can be\nachieved by passing '--verify' to 'git rev-parse'.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 62 +++++++++++++---------------------\n 1 file changed, 24 insertions(+), 38 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex d200fbfed7..2efad85768 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -62,13 +62,6 @@ assert () {\n \tfi\n }\n \n-ensure_single_rev () {\n-\tif test $# -ne 1\n-\tthen\n-\t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n-\tfi\n-}\n-\n main () {\n \tif test $# -eq 0\n \tthen\n@@ -150,11 +143,8 @@ main () {\n \tshift\n \n \tcase \"$arg_command\" in\n-\tadd|merge|pull)\n-\t\tdefault=\n-\t\t;;\n-\tsplit|push)\n-\t\tdefault=\"--default HEAD\"\n+\tadd|merge|pull|split|push)\n+\t\t:\n \t\t;;\n \t*)\n \t\tdie \"Unknown command '$arg_command'\"\n@@ -179,22 +169,8 @@ main () {\n \n \tdir=\"$(dirname \"$arg_prefix/.\")\"\n \n-\tif test \"$arg_command\" != \"pull\" &&\n-\t\t\ttest \"$arg_command\" != \"add\" &&\n-\t\t\ttest \"$arg_command\" != \"push\"\n-\tthen\n-\t\trevs=$(git rev-parse $default --revs-only \"$@\") || exit $?\n-\t\tdirs=$(git rev-parse --no-revs --no-flags \"$@\") || exit $?\n-\t\tensure_single_rev $revs\n-\t\tif test -n \"$dirs\"\n-\t\tthen\n-\t\t\tdie \"Error: Use --prefix instead of bare filenames.\"\n-\t\tfi\n-\tfi\n-\n \tdebug \"command: {$arg_command}\"\n \tdebug \"quiet: {$GIT_QUIET}\"\n-\tdebug \"revs: {$revs}\"\n \tdebug \"dir: {$dir}\"\n \tdebug \"opts: {$*}\"\n \tdebug\n@@ -700,14 +676,13 @@ cmd_add_repository () {\n \trepository=$1\n \trefspec=$2\n \tgit fetch \"$@\" || exit $?\n-\trevs=FETCH_HEAD\n-\tset -- $revs\n-\tcmd_add_commit \"$@\"\n+\tcmd_add_commit FETCH_HEAD\n }\n \n cmd_add_commit () {\n-\trev=$(git rev-parse $default --revs-only \"$@\") || exit $?\n-\tensure_single_rev $rev\n+\t# The rev has already been validated by cmd_add(), we just\n+\t# need to normalize it.\n+\trev=$(git rev-parse --verify \"$1^{commit}\") || exit $?\n \n \tdebug \"Adding $dir as '$rev'...\"\n \tgit read-tree --prefix=\"$dir\" $rev || exit $?\n@@ -738,6 +713,17 @@ cmd_add_commit () {\n }\n \n cmd_split () {\n+\tif test $# -eq 0\n+\tthen\n+\t\trev=$(git rev-parse HEAD)\n+\telif test $# -eq 1\n+\tthen\n+\t\trev=$(git rev-parse -q --verify \"$1^{commit}\") ||\n+\t\t\tdie \"'$1' does not refer to a commit\"\n+\telse\n+\t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n+\tfi\n+\n \tdebug \"Splitting $dir...\"\n \tcache_setup || exit $?\n \n@@ -754,12 +740,12 @@ cmd_split () {\n \t\tdone || exit $?\n \tfi\n \n-\tunrevs=\"$(find_existing_splits \"$dir\" \"$revs\")\" || exit $?\n+\tunrevs=\"$(find_existing_splits \"$dir\" \"$rev\")\" || exit $?\n \n \t# We can't restrict rev-list to only $dir here, because some of our\n \t# parents have the $dir contents the root, and those won't match.\n \t# (and rev-list --follow doesn't seem to solve this)\n-\tgrl='git rev-list --topo-order --reverse --parents $revs $unrevs'\n+\tgrl='git rev-list --topo-order --reverse --parents $rev $unrevs'\n \trevmax=$(eval \"$grl\" | wc -l)\n \trevcount=0\n \tcreatecount=0\n@@ -806,8 +792,10 @@ cmd_split () {\n }\n \n cmd_merge () {\n-\trev=$(git rev-parse $default --revs-only \"$@\") || exit $?\n-\tensure_single_rev $rev\n+\ttest $# -eq 1 ||\n+\t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n+\trev=$(git rev-parse -q --verify \"$1^{commit}\") ||\n+\t\tdie \"'$1' does not refer to a commit\"\n \tensure_clean\n \n \tif test -n \"$arg_addmerge_squash\"\n@@ -847,9 +835,7 @@ cmd_pull () {\n \tensure_clean\n \tensure_valid_ref_format \"$2\"\n \tgit fetch \"$@\" || exit $?\n-\trevs=FETCH_HEAD\n-\tset -- $revs\n-\tcmd_merge \"$@\"\n+\tcmd_merge FETCH_HEAD\n }\n \n cmd_push () {\n-- \n2.31.1\n\n"},{"id":"422796","messageId":"20210423194230.1388945-23-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 22/30] subtree: remove duplicate check","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:22Z","receivedAt":"2021-04-23T19:43:17Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\n`cmd_add` starts with a check that the directory doesn't yet exist.\nHowever, the `main` function performs the exact same check before\ncalling `cmd_add`.  So remove the check from `cmd_add`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 4 ----\n 1 file changed, 4 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 2efad85768..04dfaf443e 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -641,10 +641,6 @@ process_split_commit () {\n }\n \n cmd_add () {\n-\tif test -e \"$dir\"\n-\tthen\n-\t\tdie \"'$dir' already exists.  Cannot add.\"\n-\tfi\n \n \tensure_clean\n \n-- \n2.31.1\n\n"},{"id":"422797","messageId":"20210423194230.1388945-24-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 23/30] subtree: add comments and sanity checks","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:23Z","receivedAt":"2021-04-23T19:43:19Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 62 ++++++++++++++++++++++++++++++++--\n 1 file changed, 60 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 04dfaf443e..ddfa74c3bf 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -41,6 +41,7 @@ arg_split_annotate=\n arg_addmerge_squash=\n arg_addmerge_message=\n \n+# Usage: debug [MSG...]\n debug () {\n \tif test -n \"$arg_debug\"\n \tthen\n@@ -48,6 +49,7 @@ debug () {\n \tfi\n }\n \n+# Usage: progress [MSG...]\n progress () {\n \tif test -z \"$GIT_QUIET\"\n \tthen\n@@ -55,6 +57,7 @@ progress () {\n \tfi\n }\n \n+# Usage: assert CMD...\n assert () {\n \tif ! \"$@\"\n \tthen\n@@ -178,7 +181,9 @@ main () {\n \t\"cmd_$arg_command\" \"$@\"\n }\n \n+# Usage: cache_setup\n cache_setup () {\n+\tassert test $# = 0\n \tcachedir=\"$GIT_DIR/subtree-cache/$$\"\n \trm -rf \"$cachedir\" ||\n \t\tdie \"Can't delete old cachedir: $cachedir\"\n@@ -189,6 +194,7 @@ cache_setup () {\n \tdebug \"Using cachedir: $cachedir\" >&2\n }\n \n+# Usage: cache_get [REVS...]\n cache_get () {\n \tfor oldrev in \"$@\"\n \tdo\n@@ -200,6 +206,7 @@ cache_get () {\n \tdone\n }\n \n+# Usage: cache_miss [REVS...]\n cache_miss () {\n \tfor oldrev in \"$@\"\n \tdo\n@@ -210,7 +217,9 @@ cache_miss () {\n \tdone\n }\n \n+# Usage: check_parents PARENTS_EXPR INDENT\n check_parents () {\n+\tassert test $# = 2\n \tmissed=$(cache_miss \"$1\") || exit $?\n \tlocal indent=$(($2 + 1))\n \tfor miss in $missed\n@@ -223,11 +232,15 @@ check_parents () {\n \tdone\n }\n \n+# Usage: set_notree REV\n set_notree () {\n+\tassert test $# = 1\n \techo \"1\" > \"$cachedir/notree/$1\"\n }\n \n+# Usage: cache_set OLDREV NEWREV\n cache_set () {\n+\tassert test $# = 2\n \toldrev=\"$1\"\n \tnewrev=\"$2\"\n \tif test \"$oldrev\" != \"latest_old\" &&\n@@ -239,7 +252,9 @@ cache_set () {\n \techo \"$newrev\" >\"$cachedir/$oldrev\"\n }\n \n+# Usage: rev_exists REV\n rev_exists () {\n+\tassert test $# = 1\n \tif git rev-parse \"$1\" >/dev/null 2>&1\n \tthen\n \t\treturn 0\n@@ -248,17 +263,22 @@ rev_exists () {\n \tfi\n }\n \n+# Usage: try_remove_previous REV\n+#\n # if a commit doesn't have a parent, this might not work.  But we only want\n # to remove the parent from the rev-list, and since it doesn't exist, it won't\n # be there anyway, so do nothing in that case.\n try_remove_previous () {\n+\tassert test $# = 1\n \tif rev_exists \"$1^\"\n \tthen\n \t\techo \"^$1^\"\n \tfi\n }\n \n+# Usage: find_latest_squash DIR\n find_latest_squash () {\n+\tassert test $# = 1\n \tdebug \"Looking for latest squash ($dir)...\"\n \tdir=\"$1\"\n \tsq=\n@@ -302,10 +322,12 @@ find_latest_squash () {\n \tdone || exit $?\n }\n \n+# Usage: find_existing_splits DIR REV\n find_existing_splits () {\n+\tassert test $# = 2\n \tdebug \"Looking for prior splits...\"\n \tdir=\"$1\"\n-\trevs=\"$2\"\n+\trev=\"$2\"\n \tmain=\n \tsub=\n \tlocal grep_format=\"^git-subtree-dir: $dir/*\\$\"\n@@ -314,7 +336,7 @@ find_existing_splits () {\n \t\tgrep_format=\"^Add '$dir/' from commit '\"\n \tfi\n \tgit log --grep=\"$grep_format\" \\\n-\t\t--no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' $revs |\n+\t\t--no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' \"$rev\" |\n \twhile read a b junk\n \tdo\n \t\tcase \"$a\" in\n@@ -351,7 +373,9 @@ find_existing_splits () {\n \tdone || exit $?\n }\n \n+# Usage: copy_commit REV TREE FLAGS_STR\n copy_commit () {\n+\tassert test $# = 3\n \t# We're going to set some environment vars here, so\n \t# do it in a subshell to get rid of them safely later\n \tdebug copy_commit \"{$1}\" \"{$2}\" \"{$3}\"\n@@ -377,7 +401,9 @@ copy_commit () {\n \t) || die \"Can't copy commit $1\"\n }\n \n+# Usage: add_msg DIR LATEST_OLD LATEST_NEW\n add_msg () {\n+\tassert test $# = 3\n \tdir=\"$1\"\n \tlatest_old=\"$2\"\n \tlatest_new=\"$3\"\n@@ -396,7 +422,9 @@ add_msg () {\n \tEOF\n }\n \n+# Usage: add_squashed_msg REV DIR\n add_squashed_msg () {\n+\tassert test $# = 2\n \tif test -n \"$arg_addmerge_message\"\n \tthen\n \t\techo \"$arg_addmerge_message\"\n@@ -405,7 +433,9 @@ add_squashed_msg () {\n \tfi\n }\n \n+# Usage: rejoin_msg DIR LATEST_OLD LATEST_NEW\n rejoin_msg () {\n+\tassert test $# = 3\n \tdir=\"$1\"\n \tlatest_old=\"$2\"\n \tlatest_new=\"$3\"\n@@ -424,7 +454,9 @@ rejoin_msg () {\n \tEOF\n }\n \n+# Usage: squash_msg DIR OLD_SUBTREE_COMMIT NEW_SUBTREE_COMMIT\n squash_msg () {\n+\tassert test $# = 3\n \tdir=\"$1\"\n \toldsub=\"$2\"\n \tnewsub=\"$3\"\n@@ -446,12 +478,16 @@ squash_msg () {\n \techo \"git-subtree-split: $newsub\"\n }\n \n+# Usage: toptree_for_commit COMMIT\n toptree_for_commit () {\n+\tassert test $# = 1\n \tcommit=\"$1\"\n \tgit rev-parse --verify \"$commit^{tree}\" || exit $?\n }\n \n+# Usage: subtree_for_commit COMMIT DIR\n subtree_for_commit () {\n+\tassert test $# = 2\n \tcommit=\"$1\"\n \tdir=\"$2\"\n \tgit ls-tree \"$commit\" -- \"$dir\" |\n@@ -465,7 +501,9 @@ subtree_for_commit () {\n \tdone || exit $?\n }\n \n+# Usage: tree_changed TREE [PARENTS...]\n tree_changed () {\n+\tassert test $# -gt 0\n \ttree=$1\n \tshift\n \tif test $# -ne 1\n@@ -482,7 +520,9 @@ tree_changed () {\n \tfi\n }\n \n+# Usage: new_squash_commit OLD_SQUASHED_COMMIT OLD_NONSQUASHED_COMMIT NEW_NONSQUASHED_COMMIT\n new_squash_commit () {\n+\tassert test $# = 3\n \told=\"$1\"\n \toldsub=\"$2\"\n \tnewsub=\"$3\"\n@@ -497,7 +537,9 @@ new_squash_commit () {\n \tfi\n }\n \n+# Usage: copy_or_skip REV TREE NEWPARENTS\n copy_or_skip () {\n+\tassert test $# = 3\n \trev=\"$1\"\n \ttree=\"$2\"\n \tnewparents=\"$3\"\n@@ -572,7 +614,9 @@ copy_or_skip () {\n \tfi\n }\n \n+# Usage: ensure_clean\n ensure_clean () {\n+\tassert test $# = 0\n \tif ! git diff-index HEAD --exit-code --quiet 2>&1\n \tthen\n \t\tdie \"Working tree has modifications.  Cannot add.\"\n@@ -583,12 +627,16 @@ ensure_clean () {\n \tfi\n }\n \n+# Usage: ensure_valid_ref_format REF\n ensure_valid_ref_format () {\n+\tassert test $# = 1\n \tgit check-ref-format \"refs/heads/$1\" ||\n \t\tdie \"'$1' does not look like a ref\"\n }\n \n+# Usage: process_split_commit REV PARENTS INDENT\n process_split_commit () {\n+\tassert test $# = 3\n \tlocal rev=\"$1\"\n \tlocal parents=\"$2\"\n \tlocal indent=$3\n@@ -640,6 +688,8 @@ process_split_commit () {\n \tcache_set latest_old \"$rev\"\n }\n \n+# Usage: cmd_add REV\n+#    Or: cmd_add REPOSITORY REF\n cmd_add () {\n \n \tensure_clean\n@@ -667,7 +717,9 @@ cmd_add () {\n \tfi\n }\n \n+# Usage: cmd_add_repository REPOSITORY REFSPEC\n cmd_add_repository () {\n+\tassert test $# = 2\n \techo \"git fetch\" \"$@\"\n \trepository=$1\n \trefspec=$2\n@@ -675,9 +727,11 @@ cmd_add_repository () {\n \tcmd_add_commit FETCH_HEAD\n }\n \n+# Usage: cmd_add_commit REV\n cmd_add_commit () {\n \t# The rev has already been validated by cmd_add(), we just\n \t# need to normalize it.\n+\tassert test $# = 1\n \trev=$(git rev-parse --verify \"$1^{commit}\") || exit $?\n \n \tdebug \"Adding $dir as '$rev'...\"\n@@ -708,6 +762,7 @@ cmd_add_commit () {\n \tsay >&2 \"Added dir '$dir'\"\n }\n \n+# Usage: cmd_split [REV]\n cmd_split () {\n \tif test $# -eq 0\n \tthen\n@@ -787,6 +842,7 @@ cmd_split () {\n \texit 0\n }\n \n+# Usage: cmd_merge REV\n cmd_merge () {\n \ttest $# -eq 1 ||\n \t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n@@ -823,6 +879,7 @@ cmd_merge () {\n \tfi\n }\n \n+# Usage: cmd_pull REPOSITORY REMOTEREF\n cmd_pull () {\n \tif test $# -ne 2\n \tthen\n@@ -834,6 +891,7 @@ cmd_pull () {\n \tcmd_merge FETCH_HEAD\n }\n \n+# Usage: cmd_push REPOSITORY REMOTEREF\n cmd_push () {\n \tif test $# -ne 2\n \tthen\n-- \n2.31.1\n\n"},{"id":"422798","messageId":"20210423194230.1388945-25-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 24/30] subtree: don't let debug and progress output clash","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:24Z","receivedAt":"2021-04-23T19:43:19Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nCurrently, debug output (triggered by passing '-d') and progress output\nstomp on eachother.  The debug output is just streamed as lines to\nstderr, and the progress output is sent to stderr as '%s\\r'.  It is\ndifficult to distinguish between the debug output and a progress line.\nWhen writing to a terminal the debug lines hide progress lines.\n\nSo, when '-d' has been passed, spit out progress as 'progress: %s\\n',\ninstead of as '%s\\r', so that it can be detected, and so that the debug\nlines don't overwrite the progress when written to a terminal.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 7 ++++++-\n 1 file changed, 6 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex ddfa74c3bf..62cf54928e 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -53,7 +53,12 @@ debug () {\n progress () {\n \tif test -z \"$GIT_QUIET\"\n \tthen\n-\t\tprintf \"%s\\r\" \"$*\" >&2\n+\t\tif test -n \"$arg_debug\"\n+\t\tthen\n+\t\t\tprintf \"progress: %s\\n\" \"$*\" >&2\n+\t\telse\n+\t\t\tprintf \"%s\\r\" \"$*\" >&2\n+\t\tfi\n \tfi\n }\n \n-- \n2.31.1\n\n"},{"id":"422799","messageId":"20210423194230.1388945-26-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 25/30] subtree: have $indent actually affect indentation","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:25Z","receivedAt":"2021-04-23T19:43:20Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nCurrently, the $indent variable is just used to track how deeply we're\nnested, and the debug log is indented by things like\n\n   debug \"  foo\"\n\nThat is: The indentation-level is hard-coded.  It used to be that the\ncode couldn't recurse, so the indentation level could be known\nstatically, so it made sense to just hard-code it in the\noutput. However, since 315a84f9aa (\"subtree: use commits before rejoins\nfor splits\", 2018-09-28), it can now recurse, and the debug log is\nmisleading.\n\nSo fix that.  Indent according to $indent.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 42 +++++++++++++++++++---------------\n 1 file changed, 24 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 62cf54928e..54e904516b 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -41,11 +41,13 @@ arg_split_annotate=\n arg_addmerge_squash=\n arg_addmerge_message=\n \n+indent=0\n+\n # Usage: debug [MSG...]\n debug () {\n \tif test -n \"$arg_debug\"\n \tthen\n-\t\tprintf \"%s\\n\" \"$*\" >&2\n+\t\tprintf \"%$(($indent * 2))s%s\\n\" '' \"$*\" >&2\n \tfi\n }\n \n@@ -222,17 +224,17 @@ cache_miss () {\n \tdone\n }\n \n-# Usage: check_parents PARENTS_EXPR INDENT\n+# Usage: check_parents PARENTS_EXPR\n check_parents () {\n-\tassert test $# = 2\n+\tassert test $# = 1\n \tmissed=$(cache_miss \"$1\") || exit $?\n-\tlocal indent=$(($2 + 1))\n+\tlocal indent=$(($indent + 1))\n \tfor miss in $missed\n \tdo\n \t\tif ! test -r \"$cachedir/notree/$miss\"\n \t\tthen\n-\t\t\tdebug \"  incorrect order: $miss\"\n-\t\t\tprocess_split_commit \"$miss\" \"\" \"$indent\"\n+\t\t\tdebug \"incorrect order: $miss\"\n+\t\t\tprocess_split_commit \"$miss\" \"\"\n \t\tfi\n \tdone\n }\n@@ -285,6 +287,8 @@ try_remove_previous () {\n find_latest_squash () {\n \tassert test $# = 1\n \tdebug \"Looking for latest squash ($dir)...\"\n+\tlocal indent=$(($indent + 1))\n+\n \tdir=\"$1\"\n \tsq=\n \tmain=\n@@ -331,6 +335,8 @@ find_latest_squash () {\n find_existing_splits () {\n \tassert test $# = 2\n \tdebug \"Looking for prior splits...\"\n+\tlocal indent=$(($indent + 1))\n+\n \tdir=\"$1\"\n \trev=\"$2\"\n \tmain=\n@@ -356,7 +362,7 @@ find_existing_splits () {\n \t\t\tdie \"could not rev-parse split hash $b from commit $sq\"\n \t\t\t;;\n \t\tEND)\n-\t\t\tdebug \"  Main is: '$main'\"\n+\t\t\tdebug \"Main is: '$main'\"\n \t\t\tif test -z \"$main\" -a -n \"$sub\"\n \t\t\tthen\n \t\t\t\t# squash commits refer to a subtree\n@@ -639,12 +645,11 @@ ensure_valid_ref_format () {\n \t\tdie \"'$1' does not look like a ref\"\n }\n \n-# Usage: process_split_commit REV PARENTS INDENT\n+# Usage: process_split_commit REV PARENTS\n process_split_commit () {\n-\tassert test $# = 3\n+\tassert test $# = 2\n \tlocal rev=\"$1\"\n \tlocal parents=\"$2\"\n-\tlocal indent=$3\n \n \tif test $indent -eq 0\n \tthen\n@@ -659,20 +664,21 @@ process_split_commit () {\n \tprogress \"$revcount/$revmax ($createcount) [$extracount]\"\n \n \tdebug \"Processing commit: $rev\"\n+\tlocal indent=$(($indent + 1))\n \texists=$(cache_get \"$rev\") || exit $?\n \tif test -n \"$exists\"\n \tthen\n-\t\tdebug \"  prior: $exists\"\n+\t\tdebug \"prior: $exists\"\n \t\treturn\n \tfi\n \tcreatecount=$(($createcount + 1))\n-\tdebug \"  parents: $parents\"\n-\tcheck_parents \"$parents\" \"$indent\"\n+\tdebug \"parents: $parents\"\n+\tcheck_parents \"$parents\"\n \tnewparents=$(cache_get $parents) || exit $?\n-\tdebug \"  newparents: $newparents\"\n+\tdebug \"newparents: $newparents\"\n \n \ttree=$(subtree_for_commit \"$rev\" \"$dir\") || exit $?\n-\tdebug \"  tree is: $tree\"\n+\tdebug \"tree is: $tree\"\n \n \t# ugly.  is there no better way to tell if this is a subtree\n \t# vs. a mainline commit?  Does it matter?\n@@ -687,7 +693,7 @@ process_split_commit () {\n \tfi\n \n \tnewrev=$(copy_or_skip \"$rev\" \"$tree\" \"$newparents\") || exit $?\n-\tdebug \"  newrev is: $newrev\"\n+\tdebug \"newrev is: $newrev\"\n \tcache_set \"$rev\" \"$newrev\"\n \tcache_set latest_new \"$newrev\"\n \tcache_set latest_old \"$rev\"\n@@ -791,7 +797,7 @@ cmd_split () {\n \t\tdo\n \t\t\t# the 'onto' history is already just the subdir, so\n \t\t\t# any parent we find there can be used verbatim\n-\t\t\tdebug \"  cache: $rev\"\n+\t\t\tdebug \"cache: $rev\"\n \t\t\tcache_set \"$rev\" \"$rev\"\n \t\tdone || exit $?\n \tfi\n@@ -809,7 +815,7 @@ cmd_split () {\n \teval \"$grl\" |\n \twhile read rev parents\n \tdo\n-\t\tprocess_split_commit \"$rev\" \"$parents\" 0\n+\t\tprocess_split_commit \"$rev\" \"$parents\"\n \tdone || exit $?\n \n \tlatest_new=$(cache_get latest_new) || exit $?\n-- \n2.31.1\n\n"},{"id":"422801","messageId":"20210423194230.1388945-27-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 26/30] subtree: give the docs a once-over","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:26Z","receivedAt":"2021-04-23T19:43:22Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nJust went through the docs looking for anything inaccurate or that can\nbe improved.\n\nIn the '-h' text, in the man page synopsis, and in the man page\ndescription: Normalize the ordering of the list of sub-commands: 'add',\n'merge', 'split', 'pull', 'push'.  This allows us to kinda separate the\nlower-level add/merge/split from the higher-level pull/push.\n\n'-h' text:\n - correction: Indicate that split's arg is optional.\n - clarity: Emphasize that 'pull' takes the 'add'/'merge' flags.\n\nman page:\n\n - correction: State that all subcommands take options (it seemed to\n   indicate that only 'split' takes any options other than '-P').\n - correction: 'split' only guarantees that the results are identical if\n   the flags are identical.\n - completeness: Clarify that 'push' always operates on HEAD, and that\n   'split' operates on HEAD if no local commit is given.\n - clarity: In the description, when listing commands, repeat what their\n   arguments are.  This way the reader doesn't need to flip back and\n   forth between the command description and the synopsis and the full\n   description to understand what's being said.\n - clarity: In the <variables> used to give command arguments, give\n   slightly longer, descriptive names.  Like <local-commit> instead of\n   just <commit>.\n - clarity: Emphasize that 'pull' takes the 'add'/'merge' flags.\n - style: In the synopsis, list options before the subcommand.  This\n   makes things line up and be much more readable when shown\n   non-monospace (such as in `make html`), and also more closely matches\n   other man pages (like `git-submodule.txt`).\n - style: Use the correct syntax for indicating the options ([<options>]\n   instead of [OPTIONS]).\n - style: In the synopsis, separate 'pull' and 'push' from the other\n   lower-level commands.  I think this helps readability.\n - style: Code-quote things in prose that seem like they should be\n   code-quoted, like '.gitmodules', flags, or full commands.\n - style: Minor wording improvements, like more consistent mood (many\n   of the command descriptions start in the imperative mood and switch\n   to the indicative mode by the end).  That sort of thing.\n - style: Capitalize \"ID\".\n - style: Remove the \"This option is only valid for XXX command\" remarks\n   from each option, and instead rely on the section headings.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh  |   4 +-\n contrib/subtree/git-subtree.txt | 162 +++++++++++++++-----------------\n 2 files changed, 80 insertions(+), 86 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 54e904516b..4d0be1ad5c 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -9,9 +9,9 @@ OPTS_SPEC=\"\\\n git subtree add   --prefix=<prefix> <commit>\n git subtree add   --prefix=<prefix> <repository> <ref>\n git subtree merge --prefix=<prefix> <commit>\n+git subtree split --prefix=<prefix> [<commit>]\n git subtree pull  --prefix=<prefix> <repository> <ref>\n git subtree push  --prefix=<prefix> <repository> <ref>\n-git subtree split --prefix=<prefix> <commit>\n --\n h,help        show the help\n q             quiet\n@@ -24,7 +24,7 @@ b,branch=     create a new branch from the split subtree\n ignore-joins  ignore prior --rejoin commits\n onto=         try connecting new tree to an existing one\n rejoin        merge the new branch back into HEAD\n- options for 'add', 'merge', and 'pull'\n+ options for 'add' and 'merge' (also: 'pull')\n squash        merge subtree changes as a single commit\n \"\n \ndiff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt\nindex 0db02fe3c0..5728778bdf 100644\n--- a/contrib/subtree/git-subtree.txt\n+++ b/contrib/subtree/git-subtree.txt\n@@ -9,13 +9,14 @@ git-subtree - Merge subtrees together and split repository into subtrees\n SYNOPSIS\n --------\n [verse]\n-'git subtree' add   -P <prefix> <commit>\n-'git subtree' add   -P <prefix> <repository> <ref>\n-'git subtree' pull  -P <prefix> <repository> <ref>\n-'git subtree' push  -P <prefix> <repository> <ref>\n-'git subtree' merge -P <prefix> <commit>\n-'git subtree' split -P <prefix> [OPTIONS] [<commit>]\n+'git subtree' [<options>] -P <prefix> add <local-commit>\n+'git subtree' [<options>] -P <prefix> add <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> merge <local-commit>\n+'git subtree' [<options>] -P <prefix> split [<local-commit>]\n \n+[verse]\n+'git subtree' [<options>] -P <prefix> pull <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> push <repository> <remote-ref>\n \n DESCRIPTION\n -----------\n@@ -28,7 +29,7 @@ as a subdirectory of your application.\n \n Subtrees are not to be confused with submodules, which are meant for\n the same task. Unlike submodules, subtrees do not need any special\n-constructions (like .gitmodules files or gitlinks) be present in\n+constructions (like '.gitmodules' files or gitlinks) be present in\n your repository, and do not force end-users of your\n repository to do anything special or to understand how subtrees\n work. A subtree is just a subdirectory that can be\n@@ -59,27 +60,28 @@ project as much as possible.  That is, if you make a change that\n affects both the library and the main application, commit it in\n two pieces.  That way, when you split the library commits out\n later, their descriptions will still make sense.  But if this\n-isn't important to you, it's not *necessary*.  git subtree will\n+isn't important to you, it's not *necessary*.  'git subtree' will\n simply leave out the non-library-related parts of the commit\n when it splits it out into the subproject later.\n \n \n COMMANDS\n --------\n-add::\n+add <local-commit>::\n+add <repository> <remote-ref>::\n \tCreate the <prefix> subtree by importing its contents\n-\tfrom the given <commit> or <repository> and remote <ref>.\n+\tfrom the given <local-commit> or <repository> and <remote-ref>.\n \tA new commit is created\tautomatically, joining the imported\n-\tproject's history with your own.  With '--squash', imports\n+\tproject's history with your own.  With '--squash', import\n \tonly a single commit from the subproject, rather than its\n \tentire history.\n \n-merge::\n-\tMerge recent changes up to <commit> into the <prefix>\n+merge <local-commit>::\n+\tMerge recent changes up to <local-commit> into the <prefix>\n \tsubtree.  As with normal 'git merge', this doesn't\n \tremove your own local changes; it just merges those\n-\tchanges into the latest <commit>.  With '--squash',\n-\tcreates only one commit that contains all the changes,\n+\tchanges into the latest <local-commit>.  With '--squash',\n+\tcreate only one commit that contains all the changes,\n \trather than merging in the entire history.\n +\n If you use '--squash', the merge direction doesn't always have to be\n@@ -87,39 +89,40 @@ forward; you can use this command to go back in time from v2.5 to v2.4,\n for example.  If your merge introduces a conflict, you can resolve it in\n the usual ways.\n \t\n-pull::\n-\tExactly like 'merge', but parallels 'git pull' in that\n-\tit fetches the given ref from the specified remote\n-\trepository.\n-\t\n-push::\n-\tDoes a 'split' (see below) using the <prefix> supplied\n-\tand then does a 'git push' to push the result to the \n-\trepository and ref. This can be used to push your\n-\tsubtree to different branches of the remote repository.\n-\n-split::\n+split [<local-commit>]::\n \tExtract a new, synthetic project history from the\n-\thistory of the <prefix> subtree.  The new history\n+\thistory of the <prefix> subtree of <local-commit>, or of\n+\tHEAD if no <local-commit> is given.  The new history\n \tincludes only the commits (including merges) that\n \taffected <prefix>, and each of those commits now has the\n \tcontents of <prefix> at the root of the project instead\n \tof in a subdirectory.  Thus, the newly created history\n \tis suitable for export as a separate git repository.\n +\n-After splitting successfully, a single commit id is printed to stdout.\n+After splitting successfully, a single commit ID is printed to stdout.\n This corresponds to the HEAD of the newly created tree, which you can\n manipulate however you want.\n +\n Repeated splits of exactly the same history are guaranteed to be\n-identical (i.e. to produce the same commit ids).  Because of this, if\n-you add new commits and then re-split, the new commits will be attached\n-as commits on top of the history you generated last time, so 'git merge'\n-and friends will work as expected.\n+identical (i.e. to produce the same commit IDs) as long as the\n+settings passed to 'split' (such as '--annotate') are the same.\n+Because of this, if you add new commits and then re-split, the new\n+commits will be attached as commits on top of the history you\n+generated last time, so 'git merge' and friends will work as expected.\n +\n Note that if you use '--squash' when you merge, you should usually not\n just '--rejoin' when you split.\n \n+pull <repository> <remote-ref>::\n+\tExactly like 'merge', but parallels 'git pull' in that\n+\tit fetches the given ref from the specified remote\n+\trepository.\n+\n+push <repository> <remote-ref>::\n+\tDoes a 'split' using the <prefix> subtree of HEAD and then\n+\tdoes a 'git push' to push the result to the <repository> and\n+\t<remote-ref>.  This can be used to push your subtree to\n+\tdifferent branches of the remote repository.\n \n OPTIONS\n -------\n@@ -139,19 +142,18 @@ OPTIONS\n \n -m <message>::\n --message=<message>::\n-\tThis option is only valid for add, merge, pull, and split --rejoin.\n+\tThis option is only valid for 'add', 'merge', 'pull', and 'split --rejoin'.\n \tSpecify <message> as the commit message for the merge commit.\n \n+OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull')\n+--------------------------------------------\n+These options for 'add' and 'merge' may also be given to 'pull' (which\n+wraps 'merge').\n \n-OPTIONS FOR add, merge, and pull\n---------------------------------\n --squash::\n-\tThis option is only valid for add, merge, and pull\n-\tcommands.\n-+\n-Instead of merging the entire history from the subtree project, produce\n-only a single commit that contains all the differences you want to\n-merge, and then merge that new commit into your project.\n+\tInstead of merging the entire history from the subtree project, produce\n+\tonly a single commit that contains all the differences you want to\n+\tmerge, and then merge that new commit into your project.\n +\n Using this option helps to reduce log clutter. People rarely want to see\n every change that happened between v1.0 and v1.1 of the library they're\n@@ -175,56 +177,48 @@ remain intact and can be later split and send upstream to the\n subproject.\n \n \n-OPTIONS FOR split\n------------------\n+OPTIONS FOR 'split'\n+-------------------\n+These options are only valid for 'split'.\n+\n --annotate=<annotation>::\n-\tThis option is only valid for the split command.\n-+\n-When generating synthetic history, add <annotation> as a prefix to each\n-commit message.  Since we're creating new commits with the same commit\n-message, but possibly different content, from the original commits, this\n-can help to differentiate them and avoid confusion.\n+\tWhen generating synthetic history, add <annotation> as a prefix to each\n+\tcommit message.  Since we're creating new commits with the same commit\n+\tmessage, but possibly different content, from the original commits, this\n+\tcan help to differentiate them and avoid confusion.\n +\n Whenever you split, you need to use the same <annotation>, or else you\n don't have a guarantee that the new re-created history will be identical\n to the old one.  That will prevent merging from working correctly.  git\n-subtree tries to make it work anyway, particularly if you use --rejoin,\n+subtree tries to make it work anyway, particularly if you use '--rejoin',\n but it may not always be effective.\n \n -b <branch>::\n --branch=<branch>::\n-\tThis option is only valid for the split command.\n-+\n-After generating the synthetic history, create a new branch called\n-<branch> that contains the new history.  This is suitable for immediate\n-pushing upstream.  <branch> must not already exist.\n+\tAfter generating the synthetic history, create a new branch called\n+\t<branch> that contains the new history.  This is suitable for immediate\n+\tpushing upstream.  <branch> must not already exist.\n \n --ignore-joins::\n-\tThis option is only valid for the split command.\n-+\n-If you use '--rejoin', git subtree attempts to optimize its history\n-reconstruction to generate only the new commits since the last\n-'--rejoin'.  '--ignore-join' disables this behaviour, forcing it to\n-regenerate the entire history.  In a large project, this can take a long\n-time.\n+\tIf you use '--rejoin', git subtree attempts to optimize its history\n+\treconstruction to generate only the new commits since the last\n+\t'--rejoin'.  '--ignore-join' disables this behaviour, forcing it to\n+\tregenerate the entire history.  In a large project, this can take a long\n+\ttime.\n \n --onto=<onto>::\n-\tThis option is only valid for the split command.\n-+\n-If your subtree was originally imported using something other than git\n-subtree, its history may not match what git subtree is expecting.  In\n-that case, you can specify the commit id <onto> that corresponds to the\n-first revision of the subproject's history that was imported into your\n-project, and git subtree will attempt to build its history from there.\n+\tIf your subtree was originally imported using something other than git\n+\tsubtree, its history may not match what git subtree is expecting.  In\n+\tthat case, you can specify the commit ID <onto> that corresponds to the\n+\tfirst revision of the subproject's history that was imported into your\n+\tproject, and git subtree will attempt to build its history from there.\n +\n If you used 'git subtree add', you should never need this option.\n \n --rejoin::\n-\tThis option is only valid for the split command.\n-+\n-After splitting, merge the newly created synthetic history back into\n-your main project.  That way, future splits can search only the part of\n-history that has been added since the most recent --rejoin.\n+\tAfter splitting, merge the newly created synthetic history back into\n+\tyour main project.  That way, future splits can search only the part of\n+\thistory that has been added since the most recent '--rejoin'.\n +\n If your split commits end up merged into the upstream subproject, and\n then you want to get the latest upstream version, this will allow git's\n@@ -240,8 +234,8 @@ split, because you don't want the subproject's history to be part of\n your project anyway.\n \n \n-EXAMPLE 1. Add command\n-----------------------\n+EXAMPLE 1. 'add' command\n+------------------------\n Let's assume that you have a local repository that you would like\n to add an external vendor library to. In this case we will add the\n git-subtree repository as a subdirectory of your already existing\n@@ -253,15 +247,15 @@ git-extensions repository in ~/git-extensions/:\n 'master' needs to be a valid remote ref and can be a different branch\n name\n \n-You can omit the --squash flag, but doing so will increase the number\n+You can omit the '--squash' flag, but doing so will increase the number\n of commits that are included in your local repository.\n \n We now have a ~/git-extensions/git-subtree directory containing code\n from the master branch of git://github.com/apenwarr/git-subtree.git\n in our git-extensions repository.\n \n-EXAMPLE 2. Extract a subtree using commit, merge and pull\n----------------------------------------------------------\n+EXAMPLE 2. Extract a subtree using 'commit', 'merge' and 'pull'\n+---------------------------------------------------------------\n Let's use the repository for the git source code as an example.\n First, get your own copy of the git.git repository:\n \n@@ -284,9 +278,9 @@ the upstream.  You could do this:\n 0a8f4f0 to the current version, including 0a8f4f0 itself.\")\n \n If gitweb had originally been merged using 'git subtree add' (or\n-a previous split had already been done with --rejoin specified)\n+a previous split had already been done with '--rejoin' specified)\n then you can do all your splits without having to remember any\n-weird commit ids:\n+weird commit IDs:\n \n \t$ git subtree split --prefix=gitweb --annotate='(split) ' --rejoin \\\n \t\t--branch gitweb-latest2\n@@ -321,8 +315,8 @@ the standard gitweb:\n \n \tgit log gitweb-latest..$(git subtree split --prefix=gitweb)\n \n-EXAMPLE 3. Extract a subtree using branch\n------------------------------------------\n+EXAMPLE 3. Extract a subtree using a branch\n+-------------------------------------------\n Suppose you have a source directory with many files and\n subdirectories, and you want to extract the lib directory to its own\n git project. Here's a short way to do it:\n-- \n2.31.1\n\n"},{"id":"422800","messageId":"20210423194230.1388945-28-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 27/30] subtree: allow --squash to be used with --rejoin","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:27Z","receivedAt":"2021-04-23T19:43:23Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nBesides being a genuinely useful thing to do, this also just makes sense\nand harmonizes which flags may be used when.  `git subtree split\n--rejoin` amounts to \"automatically go ahead and do a `git subtree\nmerge` after doing the main `git subtree split`\", so it's weird and\narbitrary that you can't pass `--squash` to `git subtree split --rejoin`\nlike you can `git subtree merge`.  It's weird that `git subtree split\n--rejoin` inherits `git subtree merge`'s `--message` but not `--squash`.\n\nReconcile the situation by just having `split --rejoin` actually just\ncall `merge` internally (or call `add` instead, as appropriate), so it\ncan get access to the full `merge` behavior, including `--squash`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh     | 33 ++++++++++++++++++++++------\n contrib/subtree/git-subtree.txt    | 27 ++++++++++-------------\n contrib/subtree/t/t7900-subtree.sh | 35 ++++++++++++++++++++++++++++++\n 3 files changed, 72 insertions(+), 23 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 4d0be1ad5c..ff54009c49 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -17,15 +17,15 @@ h,help        show the help\n q             quiet\n d             show debug messages\n P,prefix=     the name of the subdir to split out\n-m,message=    use the given message as the commit message for the merge commit\n  options for 'split'\n annotate=     add a prefix to commit message of new commits\n b,branch=     create a new branch from the split subtree\n ignore-joins  ignore prior --rejoin commits\n onto=         try connecting new tree to an existing one\n rejoin        merge the new branch back into HEAD\n- options for 'add' and 'merge' (also: 'pull')\n+ options for 'add' and 'merge' (also: 'pull' and 'split --rejoin')\n squash        merge subtree changes as a single commit\n+m,message=    use the given message as the commit message for the merge commit\n \"\n \n PATH=$(git --exec-path):$PATH\n@@ -424,6 +424,13 @@ add_msg () {\n \telse\n \t\tcommit_message=\"Add '$dir/' from commit '$latest_new'\"\n \tfi\n+\tif test -n \"$arg_split_rejoin\"\n+\tthen\n+\t\t# If this is from a --rejoin, then rejoin_msg has\n+\t\t# already inserted the `git-subtree-xxx:` tags\n+\t\techo \"$commit_message\"\n+\t\treturn\n+\tfi\n \tcat <<-EOF\n \t\t$commit_message\n \n@@ -746,7 +753,12 @@ cmd_add_commit () {\n \trev=$(git rev-parse --verify \"$1^{commit}\") || exit $?\n \n \tdebug \"Adding $dir as '$rev'...\"\n-\tgit read-tree --prefix=\"$dir\" $rev || exit $?\n+\tif test -z \"$arg_split_rejoin\"\n+\tthen\n+\t\t# Only bother doing this if this is a genuine 'add',\n+\t\t# not a synthetic 'add' from '--rejoin'.\n+\t\tgit read-tree --prefix=\"$dir\" $rev || exit $?\n+\tfi\n \tgit checkout -- \"$dir\" || exit $?\n \ttree=$(git write-tree) || exit $?\n \n@@ -786,6 +798,11 @@ cmd_split () {\n \t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n \tfi\n \n+\tif test -n \"$arg_split_rejoin\"\n+\tthen\n+\t\tensure_clean\n+\tfi\n+\n \tdebug \"Splitting $dir...\"\n \tcache_setup || exit $?\n \n@@ -828,10 +845,12 @@ cmd_split () {\n \tthen\n \t\tdebug \"Merging split branch into HEAD...\"\n \t\tlatest_old=$(cache_get latest_old) || exit $?\n-\t\tgit merge -s ours \\\n-\t\t\t--allow-unrelated-histories \\\n-\t\t\t-m \"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" \\\n-\t\t\t\"$latest_new\" >&2 || exit $?\n+\t\targ_addmerge_message=\"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" || exit $?\n+\t\tif test -z \"$(find_latest_squash \"$dir\")\"; then\n+\t\t\tcmd_add \"$latest_new\" >&2 || exit $?\n+\t\telse\n+\t\t\tcmd_merge \"$latest_new\" >&2 || exit $?\n+\t\tfi\n \tfi\n \tif test -n \"$arg_split_branch\"\n \tthen\ndiff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt\nindex 5728778bdf..b03ef88e1a 100644\n--- a/contrib/subtree/git-subtree.txt\n+++ b/contrib/subtree/git-subtree.txt\n@@ -109,9 +109,6 @@ settings passed to 'split' (such as '--annotate') are the same.\n Because of this, if you add new commits and then re-split, the new\n commits will be attached as commits on top of the history you\n generated last time, so 'git merge' and friends will work as expected.\n-+\n-Note that if you use '--squash' when you merge, you should usually not\n-just '--rejoin' when you split.\n \n pull <repository> <remote-ref>::\n \tExactly like 'merge', but parallels 'git pull' in that\n@@ -124,8 +121,8 @@ push <repository> <remote-ref>::\n \t<remote-ref>.  This can be used to push your subtree to\n \tdifferent branches of the remote repository.\n \n-OPTIONS\n--------\n+OPTIONS FOR ALL COMMANDS\n+------------------------\n -q::\n --quiet::\n \tSuppress unnecessary output messages on stderr.\n@@ -140,15 +137,11 @@ OPTIONS\n \twant to manipulate.  This option is mandatory\n \tfor all commands.\n \n--m <message>::\n---message=<message>::\n-\tThis option is only valid for 'add', 'merge', 'pull', and 'split --rejoin'.\n-\tSpecify <message> as the commit message for the merge commit.\n-\n-OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull')\n---------------------------------------------\n+OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull' AND 'split --rejoin')\n+-----------------------------------------------------------------\n These options for 'add' and 'merge' may also be given to 'pull' (which\n-wraps 'merge').\n+wraps 'merge') and 'split --rejoin' (which wraps either 'add' or\n+'merge' as appropriate).\n \n --squash::\n \tInstead of merging the entire history from the subtree project, produce\n@@ -176,6 +169,9 @@ Whether or not you use '--squash', changes made in your local repository\n remain intact and can be later split and send upstream to the\n subproject.\n \n+-m <message>::\n+--message=<message>::\n+\tSpecify <message> as the commit message for the merge commit.\n \n OPTIONS FOR 'split'\n -------------------\n@@ -229,9 +225,8 @@ Unfortunately, using this option results in 'git log' showing an extra\n copy of every new commit that was created (the original, and the\n synthetic one).\n +\n-If you do all your merges with '--squash', don't use '--rejoin' when you\n-split, because you don't want the subproject's history to be part of\n-your project anyway.\n+If you do all your merges with '--squash', make sure you also use\n+'--squash' when you 'split --rejoin'.\n \n \n EXAMPLE 1. 'add' command\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 3ee0524233..e5467c117b 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -324,6 +324,41 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \t)\n '\n \n+test_expect_success 'split \"sub dir\"/ with --rejoin and --squash' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" --squash FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit subtree pull --prefix=\"sub dir\" --squash ./\"sub proj\" HEAD &&\n+\t\tMAIN=$(git rev-parse --verify HEAD) &&\n+\t\tSUB=$(git -C \"sub proj\" rev-parse --verify HEAD) &&\n+\n+\t\tSPLIT=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin --squash) &&\n+\n+\t\t! git merge-base --is-ancestor $SUB HEAD &&\n+\t\t! git merge-base --is-ancestor $SPLIT HEAD &&\n+\t\tgit rev-list HEAD ^$MAIN >commit-list &&\n+\t\ttest_line_count = 2 commit-list &&\n+\t\ttest \"$(git rev-parse --verify HEAD:)\"           = \"$(git rev-parse --verify $MAIN:)\" &&\n+\t\ttest \"$(git rev-parse --verify HEAD:\"sub dir\")\"  = \"$(git rev-parse --verify $SPLIT:)\" &&\n+\t\ttest \"$(git rev-parse --verify HEAD^1)\"          = $MAIN &&\n+\t\ttest \"$(git rev-parse --verify HEAD^2)\"         != $SPLIT &&\n+\t\ttest \"$(git rev-parse --verify HEAD^2:)\"         = \"$(git rev-parse --verify $SPLIT:)\" &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$SPLIT'\\''\"\n+\t)\n+'\n+\n test_expect_success 'split \"sub dir\"/ with --branch' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n-- \n2.31.1\n\n"},{"id":"422802","messageId":"20210423194230.1388945-29-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 28/30] subtree: allow 'split' flags to be passed to 'push'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:28Z","receivedAt":"2021-04-23T19:43:23Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\n'push' does a 'split' internally, but it doesn't pass flags through to the\n'split'.  This is silly, if you need to pass flags to 'split', then it\nmeans that you can't use 'push'!\n\nSo, have 'push' accept 'split' flags, and pass them through to 'split'.\n\nAdd tests for this by copying split's tests with minimal modification.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh     |   6 +-\n contrib/subtree/git-subtree.txt    |  15 +-\n contrib/subtree/t/t7900-subtree.sh | 214 ++++++++++++++++++++++++++++-\n 3 files changed, 223 insertions(+), 12 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex ff54009c49..2846bd21b4 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -17,13 +17,13 @@ h,help        show the help\n q             quiet\n d             show debug messages\n P,prefix=     the name of the subdir to split out\n- options for 'split'\n+ options for 'split' (also: 'push')\n annotate=     add a prefix to commit message of new commits\n b,branch=     create a new branch from the split subtree\n ignore-joins  ignore prior --rejoin commits\n onto=         try connecting new tree to an existing one\n rejoin        merge the new branch back into HEAD\n- options for 'add' and 'merge' (also: 'pull' and 'split --rejoin')\n+ options for 'add' and 'merge' (also: 'pull', 'split --rejoin', and 'push --rejoin')\n squash        merge subtree changes as a single commit\n m,message=    use the given message as the commit message for the merge commit\n \"\n@@ -933,7 +933,7 @@ cmd_push () {\n \t\trepository=$1\n \t\trefspec=$2\n \t\techo \"git push using: \" \"$repository\" \"$refspec\"\n-\t\tlocalrev=$(git subtree split --prefix=\"$arg_prefix\") || die\n+\t\tlocalrev=$(cmd_split) || die\n \t\tgit push \"$repository\" \"$localrev\":\"refs/heads/$refspec\"\n \telse\n \t\tdie \"'$dir' must already exist. Try 'git subtree add'.\"\ndiff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt\nindex b03ef88e1a..a597d61d0f 100644\n--- a/contrib/subtree/git-subtree.txt\n+++ b/contrib/subtree/git-subtree.txt\n@@ -137,11 +137,11 @@ OPTIONS FOR ALL COMMANDS\n \twant to manipulate.  This option is mandatory\n \tfor all commands.\n \n-OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull' AND 'split --rejoin')\n------------------------------------------------------------------\n+OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull', 'split --rejoin', AND 'push --rejoin')\n+-----------------------------------------------------------------------------------\n These options for 'add' and 'merge' may also be given to 'pull' (which\n-wraps 'merge') and 'split --rejoin' (which wraps either 'add' or\n-'merge' as appropriate).\n+wraps 'merge'), 'split --rejoin' (which wraps either 'add' or 'merge'\n+as appropriate), and 'push --rejoin' (which wraps 'split --rejoin').\n \n --squash::\n \tInstead of merging the entire history from the subtree project, produce\n@@ -173,9 +173,10 @@ subproject.\n --message=<message>::\n \tSpecify <message> as the commit message for the merge commit.\n \n-OPTIONS FOR 'split'\n--------------------\n-These options are only valid for 'split'.\n+OPTIONS FOR 'split' (ALSO: 'push')\n+----------------------------------\n+These options for 'split' may also be given to 'push' (which wraps\n+'split').\n \n --annotate=<annotation>::\n \tWhen generating synthetic history, add <annotation> as a prefix to each\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex e5467c117b..e89e46fe65 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -5,8 +5,8 @@\n #\n test_description='Basic porcelain support for subtrees\n \n-This test verifies the basic operation of the add, pull, merge\n-and split subcommands of git subtree.\n+This test verifies the basic operation of the add, merge, split, pull,\n+and push subcommands of git subtree.\n '\n \n TEST_DIRECTORY=$(pwd)/../../../t\n@@ -589,6 +589,216 @@ test_expect_success 'push basic operation' '\n \t)\n '\n \n+test_expect_success 'push sub dir/ with --rejoin' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --rejoin ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push sub dir/ with --rejoin from scratch' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tmkdir \"sub dir\" &&\n+\t\techo file >\"sub dir\"/file &&\n+\t\tgit add \"sub dir/file\" &&\n+\t\tgit commit -m\"sub dir file\" &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --rejoin) &&\n+\t\tgit init --bare \"sub proj.git\" &&\n+\t\tgit subtree push --prefix=\"sub dir\" --rejoin ./\"sub proj.git\" from-mainline &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj.git\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push sub dir/ with --rejoin and --message' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tgit subtree push --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split & rejoin\" &&\n+\t\tsplit_hash=\"$(git rev-parse --verify HEAD^2)\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push \"sub dir\"/ with --rejoin and --squash' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" --squash FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit subtree pull --prefix=\"sub dir\" --squash ./\"sub proj\" HEAD &&\n+\t\tMAIN=$(git rev-parse --verify HEAD) &&\n+\t\tSUB=$(git -C \"sub proj\" rev-parse --verify HEAD) &&\n+\n+\t\tSPLIT=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --rejoin --squash ./\"sub proj\" from-mainline &&\n+\n+\t\t! git merge-base --is-ancestor $SUB HEAD &&\n+\t\t! git merge-base --is-ancestor $SPLIT HEAD &&\n+\t\tgit rev-list HEAD ^$MAIN >commit-list &&\n+\t\ttest_line_count = 2 commit-list &&\n+\t\ttest \"$(git rev-parse --verify HEAD:)\"           = \"$(git rev-parse --verify $MAIN:)\" &&\n+\t\ttest \"$(git rev-parse --verify HEAD:\"sub dir\")\"  = \"$(git rev-parse --verify $SPLIT:)\" &&\n+\t\ttest \"$(git rev-parse --verify HEAD^1)\"          = $MAIN &&\n+\t\ttest \"$(git rev-parse --verify HEAD^2)\"         != $SPLIT &&\n+\t\ttest \"$(git rev-parse --verify HEAD^2:)\"         = \"$(git rev-parse --verify $SPLIT:)\" &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$SPLIT'\\''\" &&\n+\t\ttest \"$SPLIT\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push \"sub dir\"/ with --branch' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'check hash of push' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\" &&\n+\t\t# Check hash of split\n+\t\tnew_hash=$(git rev-parse subproj-br^2) &&\n+\t\t(\n+\t\t\tcd ./\"sub proj\" &&\n+\t\t\tsubdir_hash=$(git rev-parse HEAD) &&\n+\t\t\ttest \"$new_hash\" = \"$subdir_hash\"\n+\t\t) &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push \"sub dir\"/ with --branch for an existing branch' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit branch subproj-br FETCH_HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push \"sub dir\"/ with --branch for an incompatible branch' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit branch init HEAD &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\ttest_must_fail git subtree push --prefix=\"sub dir\" --branch init \"./sub proj\" from-mainline\n+\t)\n+'\n+\n #\n # Validity checking\n #\n-- \n2.31.1\n\n"},{"id":"422803","messageId":"20210423194230.1388945-30-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 29/30] subtree: push: allow specifying a local rev other than HEAD","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:29Z","receivedAt":"2021-04-23T19:43:25Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\n'git subtree split' lets you specify a rev other than HEAD.  'git push'\nlets you specify a mapping between a local thing and a remot ref.  So\nsmash those together, and have 'git subtree push' let you specify which\nlocal thing to run split on and push the result of that split to the\nremote ref.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh     | 24 +++++++++++++++++-------\n contrib/subtree/git-subtree.txt    | 14 ++++++++------\n contrib/subtree/t/t7900-subtree.sh | 22 ++++++++++++++++++++++\n 3 files changed, 47 insertions(+), 13 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 2846bd21b4..7361d8de3f 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -11,7 +11,7 @@ git subtree add   --prefix=<prefix> <repository> <ref>\n git subtree merge --prefix=<prefix> <commit>\n git subtree split --prefix=<prefix> [<commit>]\n git subtree pull  --prefix=<prefix> <repository> <ref>\n-git subtree push  --prefix=<prefix> <repository> <ref>\n+git subtree push  --prefix=<prefix> <repository> <refspec>\n --\n h,help        show the help\n q             quiet\n@@ -921,20 +921,30 @@ cmd_pull () {\n \tcmd_merge FETCH_HEAD\n }\n \n-# Usage: cmd_push REPOSITORY REMOTEREF\n+# Usage: cmd_push REPOSITORY [+][LOCALREV:]REMOTEREF\n cmd_push () {\n \tif test $# -ne 2\n \tthen\n-\t\tdie \"You must provide <repository> <ref>\"\n+\t\tdie \"You must provide <repository> <refspec>\"\n \tfi\n-\tensure_valid_ref_format \"$2\"\n \tif test -e \"$dir\"\n \tthen\n \t\trepository=$1\n-\t\trefspec=$2\n+\t\trefspec=${2#+}\n+\t\tremoteref=${refspec#*:}\n+\t\tif test \"$remoteref\" = \"$refspec\"\n+\t\tthen\n+\t\t\tlocalrevname_presplit=HEAD\n+\t\telse\n+\t\t\tlocalrevname_presplit=${refspec%%:*}\n+\t\tfi\n+\t\tensure_valid_ref_format \"$remoteref\"\n+\t\tlocalrev_presplit=$(git rev-parse -q --verify \"$localrevname_presplit^{commit}\") ||\n+\t\t\tdie \"'$localrevname_presplit' does not refer to a commit\"\n+\n \t\techo \"git push using: \" \"$repository\" \"$refspec\"\n-\t\tlocalrev=$(cmd_split) || die\n-\t\tgit push \"$repository\" \"$localrev\":\"refs/heads/$refspec\"\n+\t\tlocalrev=$(cmd_split \"$localrev_presplit\") || die\n+\t\tgit push \"$repository\" \"$localrev\":\"refs/heads/$remoteref\"\n \telse\n \t\tdie \"'$dir' must already exist. Try 'git subtree add'.\"\n \tfi\ndiff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt\nindex a597d61d0f..c049827cb5 100644\n--- a/contrib/subtree/git-subtree.txt\n+++ b/contrib/subtree/git-subtree.txt\n@@ -16,7 +16,7 @@ SYNOPSIS\n \n [verse]\n 'git subtree' [<options>] -P <prefix> pull <repository> <remote-ref>\n-'git subtree' [<options>] -P <prefix> push <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> push <repository> <refspec>\n \n DESCRIPTION\n -----------\n@@ -115,11 +115,13 @@ pull <repository> <remote-ref>::\n \tit fetches the given ref from the specified remote\n \trepository.\n \n-push <repository> <remote-ref>::\n-\tDoes a 'split' using the <prefix> subtree of HEAD and then\n-\tdoes a 'git push' to push the result to the <repository> and\n-\t<remote-ref>.  This can be used to push your subtree to\n-\tdifferent branches of the remote repository.\n+push <repository> [+][<local-commit>:]<remote-ref>::\n+\tDoes a 'split' using the <prefix> subtree of <local-commit>\n+\tand then does a 'git push' to push the result to the\n+\t<repository> and <remote-ref>.  This can be used to push your\n+\tsubtree to different branches of the remote repository.  Just\n+\tas with 'split', if no <local-commit> is given, then HEAD is\n+\tused.  The optional leading '+' is ignored.\n \n OPTIONS FOR ALL COMMANDS\n ------------------------\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex e89e46fe65..fb85eed5fc 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -799,6 +799,28 @@ test_expect_success 'push \"sub dir\"/ with --branch for an incompatible branch' '\n \t)\n '\n \n+test_expect_success 'push \"sub dir\"/ with a local rev' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tbad_tree=$(git rev-parse --verify HEAD:\"sub dir\") &&\n+\t\tgood_tree=$(git rev-parse --verify HEAD^:\"sub dir\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" ./\"sub proj\" HEAD^:from-mainline &&\n+\t\tsplit_tree=$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline:) &&\n+\t\ttest \"$split_tree\" = \"$good_tree\"\n+\t)\n+'\n+\n #\n # Validity checking\n #\n-- \n2.31.1\n\n"},{"id":"422804","messageId":"20210423194230.1388945-31-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH 30/30] subtree: be stricter about validating flags","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T19:42:30Z","receivedAt":"2021-04-23T19:43:25Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nDon't silently ignore a flag that's invalid for a given subcommand.  The\nuser expected it to do something; we should tell the user that they are\nmistaken, instead of surprising the user.\n\nIt could be argued that this change might break existing users.  I'd\nargue that those existing users are already broken, and they just don't\nknow it.  Let them know that they're broken.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh     |  89 ++++++++++++++++-------\n contrib/subtree/t/t7900-subtree.sh | 111 +++++++++++++++++++++++++++++\n 2 files changed, 175 insertions(+), 25 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 7361d8de3f..5073d82b2e 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -30,17 +30,6 @@ m,message=    use the given message as the commit message for the merge commit\n \n PATH=$(git --exec-path):$PATH\n \n-arg_debug=\n-arg_command=\n-arg_prefix=\n-arg_split_branch=\n-arg_split_onto=\n-arg_split_rejoin=\n-arg_split_ignore_joins=\n-arg_split_annotate=\n-arg_addmerge_squash=\n-arg_addmerge_message=\n-\n indent=0\n \n # Usage: debug [MSG...]\n@@ -77,10 +66,61 @@ main () {\n \tthen\n \t\tset -- -h\n \tfi\n-\teval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n+\tset_args=\"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n+\teval \"$set_args\"\n \t. git-sh-setup\n \trequire_work_tree\n \n+\t# First figure out the command and whether we use --rejoin, so\n+\t# that we can provide more helpful validation when we do the\n+\t# \"real\" flag parsing.\n+\targ_split_rejoin=\n+\tallow_split=\n+\tallow_addmerge=\n+\twhile test $# -gt 0\n+\tdo\n+\t\topt=\"$1\"\n+\t\tshift\n+\t\tcase \"$opt\" in\n+\t\t\t--annotate|-b|-P|-m|--onto)\n+\t\t\t\tshift\n+\t\t\t\t;;\n+\t\t\t--rejoin)\n+\t\t\t\targ_split_rejoin=1\n+\t\t\t\t;;\n+\t\t\t--no-rejoin)\n+\t\t\t\targ_split_rejoin=\n+\t\t\t\t;;\n+\t\t\t--)\n+\t\t\t\tbreak\n+\t\t\t\t;;\n+\t\tesac\n+\tdone\n+\targ_command=$1\n+\tcase \"$arg_command\" in\n+\tadd|merge|pull)\n+\t\tallow_addmerge=1\n+\t\t;;\n+\tsplit|push)\n+\t\tallow_split=1\n+\t\tallow_addmerge=$arg_split_rejoin\n+\t\t;;\n+\t*)\n+\t\tdie \"Unknown command '$arg_command'\"\n+\t\t;;\n+\tesac\n+\t# Reset the arguments array for \"real\" flag parsing.\n+\teval \"$set_args\"\n+\n+\t# Begin \"real\" flag parsing.\n+\targ_debug=\n+\targ_prefix=\n+\targ_split_branch=\n+\targ_split_onto=\n+\targ_split_ignore_joins=\n+\targ_split_annotate=\n+\targ_addmerge_squash=\n+\targ_addmerge_message=\n \twhile test $# -gt 0\n \tdo\n \t\topt=\"$1\"\n@@ -94,13 +134,16 @@ main () {\n \t\t\targ_debug=1\n \t\t\t;;\n \t\t--annotate)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_annotate=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-annotate)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_annotate=\n \t\t\t;;\n \t\t-b)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_branch=\"$1\"\n \t\t\tshift\n \t\t\t;;\n@@ -109,6 +152,7 @@ main () {\n \t\t\tshift\n \t\t\t;;\n \t\t-m)\n+\t\t\ttest -n \"$allow_addmerge\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_addmerge_message=\"$1\"\n \t\t\tshift\n \t\t\t;;\n@@ -116,28 +160,34 @@ main () {\n \t\t\targ_prefix=\n \t\t\t;;\n \t\t--onto)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_onto=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-onto)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_onto=\n \t\t\t;;\n \t\t--rejoin)\n-\t\t\targ_split_rejoin=1\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\t;;\n \t\t--no-rejoin)\n-\t\t\targ_split_rejoin=\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\t;;\n \t\t--ignore-joins)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_ignore_joins=1\n \t\t\t;;\n \t\t--no-ignore-joins)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_ignore_joins=\n \t\t\t;;\n \t\t--squash)\n+\t\t\ttest -n \"$allow_addmerge\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_addmerge_squash=1\n \t\t\t;;\n \t\t--no-squash)\n+\t\t\ttest -n \"$allow_addmerge\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_addmerge_squash=\n \t\t\t;;\n \t\t--)\n@@ -148,19 +198,8 @@ main () {\n \t\t\t;;\n \t\tesac\n \tdone\n-\n-\targ_command=\"$1\"\n \tshift\n \n-\tcase \"$arg_command\" in\n-\tadd|merge|pull|split|push)\n-\t\t:\n-\t\t;;\n-\t*)\n-\t\tdie \"Unknown command '$arg_command'\"\n-\t\t;;\n-\tesac\n-\n \tif test -z \"$arg_prefix\"\n \tthen\n \t\tdie \"You must provide the --prefix option.\"\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex fb85eed5fc..f83c491a61 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -33,6 +33,12 @@ test_create_commit () (\n \tgit commit -m \"$commit\" || error \"Could not commit\"\n )\n \n+test_wrong_flag() {\n+\ttest_must_fail \"$@\" >out 2>err &&\n+\ttest_must_be_empty out &&\n+\tgrep \"flag does not make sense with\" err\n+}\n+\n last_commit_subject () {\n \tgit log --pretty=format:%s -1\n }\n@@ -72,6 +78,22 @@ test_expect_success 'no pull from non-existent subtree' '\n \t)\n '\n \n+test_expect_success 'add rejects flags for split' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --annotate=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --branch=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --ignore-joins FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --onto=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --rejoin FETCH_HEAD\n+\t)\n+'\n+\n test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n@@ -128,6 +150,28 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n # Tests for 'git subtree merge'\n #\n \n+test_expect_success 'merge rejects flags for split' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --annotate=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --branch=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --ignore-joins FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --onto=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --rejoin FETCH_HEAD\n+\t)\n+'\n+\n test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n@@ -262,6 +306,30 @@ test_expect_success 'split requires path given by option --prefix must exist' '\n \t)\n '\n \n+test_expect_success 'split rejects flags for add' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\ttest_wrong_flag git subtree split --prefix=\"sub dir\" --squash &&\n+\t\ttest_wrong_flag git subtree split --prefix=\"sub dir\" --message=foo\n+\t)\n+'\n+\n test_expect_success 'split sub dir/ with --rejoin' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n@@ -521,6 +589,26 @@ test_expect_success 'pull basic operation' '\n \t)\n '\n \n+test_expect_success 'pull rejects flags for split' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --annotate=foo ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --branch=foo ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --ignore-joins ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --onto=foo ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --rejoin ./\"sub proj\" HEAD\n+\t)\n+'\n+\n #\n # Tests for 'git subtree push'\n #\n@@ -563,6 +651,29 @@ test_expect_success 'push requires path given by option --prefix must exist' '\n \t)\n '\n \n+test_expect_success 'push rejects flags for add' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree split --prefix=\"sub dir\" --squash ./\"sub proj\" from-mainline &&\n+\t\ttest_wrong_flag git subtree split --prefix=\"sub dir\" --message=foo ./\"sub proj\" from-mainline\n+\t)\n+'\n+\n test_expect_success 'push basic operation' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n-- \n2.31.1\n\n"},{"id":"422807","messageId":"87zgxo22cr.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-13-lukeshu@lukeshu.com","subject":"Re: [PATCH 12/30] subtree: don't have loose code outside of a function","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T20:05:40Z","receivedAt":"2021-04-23T20:05:44Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 13:42:12 -0600,\nLuke Shumaker wrote:\n> \"Ignore space change\" is probably helpful when viewing this diff.\n\nFor mailing-list reading, the `git show -w` is\n\n---\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 868e18b9a1..d1ed7f9a6c 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -4,10 +4,7 @@\n #\n # Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com>\n #\n-if test $# -eq 0\n-then\n-\tset -- -h\n-fi\n+\n OPTS_SPEC=\"\\\n git subtree add   --prefix=<prefix> <commit>\n git subtree add   --prefix=<prefix> <repository> <ref>\n@@ -30,12 +27,8 @@ rejoin        merge the new branch back into HEAD\n  options for 'add', 'merge', and 'pull'\n squash        merge subtree changes as a single commit\n \"\n-eval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n \n PATH=$PATH:$(git --exec-path)\n-. git-sh-setup\n-\n-require_work_tree\n \n quiet=\n branch=\n@@ -84,6 +77,15 @@ ensure_single_rev () {\n \tfi\n }\n \n+main () {\n+\tif test $# -eq 0\n+\tthen\n+\t\tset -- -h\n+\tfi\n+\teval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n+\t. git-sh-setup\n+\trequire_work_tree\n+\n \twhile test $# -gt 0\n \tdo\n \t\topt=\"$1\"\n@@ -205,6 +207,9 @@ debug \"dir: {$dir}\"\n \tdebug \"opts: {$*}\"\n \tdebug\n \n+\t\"cmd_$command\" \"$@\"\n+}\n+\n cache_setup () {\n \tcachedir=\"$GIT_DIR/subtree-cache/$$\"\n \trm -rf \"$cachedir\" ||\n@@ -898,4 +903,4 @@ cmd_push () {\n \tfi\n }\n \n-\"cmd_$command\" \"$@\"\n+main \"$@\"\n"},{"id":"422808","messageId":"87y2d822a7.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-15-lukeshu@lukeshu.com","subject":"Re: [PATCH 14/30] subtree: drop support for git < 1.7","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T20:07:12Z","receivedAt":"2021-04-23T20:07:19Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 13:42:14 -0600,\nLuke Shumaker wrote:\n> \"Ignore space change\" is probably helpful when viewing this diff.\n\nFor mailing-list reading, the `git show -w` is:\n\n---\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 9ca498f81c..4503564f7e 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -852,16 +852,6 @@ cmd_merge () {\n \t\trev=\"$new\"\n \tfi\n \n-\tversion=$(git version)\n-\tif test \"$version\" \\< \"git version 1.7\"\n-\tthen\n-\t\tif test -n \"$message\"\n-\t\tthen\n-\t\t\tgit merge -s subtree --message=\"$message\" \"$rev\"\n-\t\telse\n-\t\t\tgit merge -s subtree \"$rev\"\n-\t\tfi\n-\telse\n \tif test -n \"$message\"\n \tthen\n \t\tgit merge -Xsubtree=\"$prefix\" \\\n@@ -869,7 +859,6 @@ cmd_merge () {\n \telse\n \t\tgit merge -Xsubtree=\"$prefix\" $rev\n \tfi\n-\tfi\n }\n \n cmd_pull () {\n"},{"id":"422810","messageId":"87wnss2219.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"Re: [PATCH 00/30] subtree: clean up, improve UX","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T20:12:34Z","receivedAt":"2021-04-23T20:12:36Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 13:42:00 -0600,\nLuke Shumaker wrote:\n>                                                  I promise that\n> there's more work coming on top of it (we've discovered lots of ways\n> to break the \"subtree split\" algorithm, and come up with fixes for\n> most of them).\n\nFollow-up question: If in that work I changed the shebang from\n\"#!/bin/sh\" to \"#!/usr/bin/env bash\" and started using Bash arrays,\nwould that be so bad?  Would that be land-able?\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422812","messageId":"CAPig+cRoxCUcVkLch70x+nUzJbTiyT4KtLDsJ0vZNJD1NboyYQ@mail.gmail.com","threadId":"55548","inReplyTo":"20210423194230.1388945-12-lukeshu@lukeshu.com","subject":"Re: [PATCH 11/30] subtree: t7900: add porcelain tests for 'pull' and 'push'","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-04-23T20:19:28Z","receivedAt":"2021-04-23T20:19:45Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> The 'pull' and 'push' subcommands deserve their own sections in the tests.\n> Add some basic tests for them.\n>\n> Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> ---\n> diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\n> @@ -202,8 +202,8 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n>  test_expect_success 'merge new subproj history into subdir/ with a slash appended to the argument of --prefix' '\n> -       test_create_repo \"$test_count\" &&\n> -       test_create_repo \"$test_count/subproj\" &&\n> +       subtree_test_create_repo \"$test_count\" &&\n> +       subtree_test_create_repo \"$test_count/subproj\" &&\n>         test_create_commit \"$test_count\" main1 &&\n>         test_create_commit \"$test_count/subproj\" sub1 &&\n\nThis change doesn't seem to be related to the stated purpose of this\npatch. Was it included by accident or is it just a drive-by \"while at\nit\" fix that seems somewhat related since you're using\nsubtree_test_create_repo() in the newly-added tests? It might deserve\nmention in the commit message.\n\n> @@ -427,6 +427,133 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n> +test_expect_success 'pull requires path given by option --prefix must exist' '\n> +       test_create_commit \"$test_count/sub proj\" sub1 &&\n> +       (\n> +               test_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD >out 2>err &&\n> +\n> +               echo \"'\\''sub dir'\\'' does not exist; use '\\''git subtree add'\\''\" > expected &&\n> +               test_must_be_empty out &&\n> +               test_cmp expected err\n> +       )\n> +'\n\nThe use of single-quotes and escaped single-quotes within the\nsingle-quoted test body is breaking my brain. Perhaps take advantage\nof SQ from test-lib.sh and interoplate it into the string rather than\ndealing with raw single-quotes?\n\n    echo \"this $SQ is a single-quote\"\n\n(After writing the above, I now see that you are just mirroring\nexisting practice in this test script. The single-quotes are\nconfusing, but following existing style may be important -- or not.)\n\n> +test_expect_success 'pull basic operation' '\n> +       subtree_test_create_repo \"$test_count\" &&\n> +       subtree_test_create_repo \"$test_count/sub proj\" &&\n> +       test_create_commit \"$test_count\" main1 &&\n> +       test_create_commit \"$test_count/sub proj\" sub1 &&\n> +       (\n> +               cd \"$test_count\" &&\n> +               git fetch ./\"sub proj\" HEAD &&\n\nI was going to comment on the unusual:\n\n    ./\"sub proj\"\n\nrather than the more typical:\n\n    \"./sub proj\"\n\nbut I see that that also is mirroring existing practice in this\nscript, so... [intentionally left blank]\n\n> +test_expect_success 'push requires option --prefix' '\n> +       subtree_test_create_repo \"$test_count\" &&\n> +       subtree_test_create_repo \"$test_count/sub proj\" &&\n> +       test_create_commit \"$test_count\" main1 &&\n> +       test_create_commit \"$test_count/sub proj\" sub1 &&\n> +       (\n> +               cd \"$test_count\" &&\n> +               git fetch ./\"sub proj\" HEAD &&\n> +               git subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n> +               echo \"You must provide the --prefix option.\" > expected &&\n> +               test_must_fail git subtree push \"./sub proj\" from-mainline > actual 2>&1 &&\n\nStyle: There is an inconsistent mix of \"> foo\" and \">foo\" formatting\nin the newly-added tests. These days, we prefer \">foo\".\n"},{"id":"422814","messageId":"CAPig+cQLP1XFnMFWOp4Zj-Ku8M-aqgE5DmpgEy=UWLqpBBW8Ng@mail.gmail.com","threadId":"55548","inReplyTo":"20210423194230.1388945-13-lukeshu@lukeshu.com","subject":"Re: [PATCH 12/30] subtree: don't have loose code outside of a function","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-04-23T20:23:18Z","receivedAt":"2021-04-23T20:23:38Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> Shove all of the loose code inside of a main() function.\n>\n> \"Ignore space change\" is probably helpful when viewing this diff.\n>\n> Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n\nWhat is the purpose of this change? Does some subsequent commit depend\nupon this or is it just a personal preference? The commit message\nexplains the \"what\" of the change but not the \"why\".\n"},{"id":"422815","messageId":"CAPig+cRcBA1y0WY_k4fge1KiRcLrW7PMeOS=Ns8bMa4VMdyy2w@mail.gmail.com","threadId":"55548","inReplyTo":"20210423194230.1388945-15-lukeshu@lukeshu.com","subject":"Re: [PATCH 14/30] subtree: drop support for git < 1.7","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-04-23T20:31:46Z","receivedAt":"2021-04-23T20:32:02Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> That was nice to have when git-subtree lived out-of-tree.  But now that\n> it lives in git.git, it's not nescessary to keep around.\n\ns/nescessary/necessary/\n\n> Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n\nIs there a higher reason for this change aside from \"let's do it\nbecause we can\"? For instance, are subsequent changes going to take\nadvantage of features only present in more recent Git versions which\nwould be painful or impossible to support with the older Git?\n\nThe downside of this change is that, while git-subtree may live in\ngit.git, it's still just \"contrib\", so people might grab git-subtree\nfrom a modern git.git but then end up using it with an older Git\ninstallation. That's not to say that doing such a thing is guaranteed\nto work anyhow, but we don't need to make it harder on people if there\nisn't a good reason (hence my question about whether subsequent\nchanges will actually take advantage of newer Git features).\n"},{"id":"422816","messageId":"CAPig+cTb-h=Qb9asvh+MVH2s5uj7szP_QOPpcm1bqdE6DK9V7g@mail.gmail.com","threadId":"55548","inReplyTo":"20210423194230.1388945-19-lukeshu@lukeshu.com","subject":"Re: [PATCH 18/30] subtree: use $* instead of $@ as appropriate","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-04-23T20:40:31Z","receivedAt":"2021-04-23T20:40:45Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> $* is for when you want to smash things together, whitespace-separated;\n> $@ is for when you want them to be separate strings.  There are a couple\n> of places in subtree that erroneously use $@ when smashing args together\n> in to an error message.\n\nCan we be explicit and say \"$@\" in the commit message rather than bare\n$@ since the unquoted form is not magical and acts exactly like $*.\n\nAlso: s/in to/into/\n\nNit: I have some trouble following what the commit message is actually\ntrying to say with \"smash things\" and \"separate strings\". It might be\nsimpler to say merely that use of \"$@\" in these particular instances\nis overkill and possibly misleading to readers not familiar with the\nfiner details of $* vs. \"$@\".\n\nThe patch itself makes sense.\n"},{"id":"422817","messageId":"CAPig+cQmTTdVKQptQY_tT_x4DCduRh=Mq6QZ1vUsc790-0yTQw@mail.gmail.com","threadId":"55548","inReplyTo":"20210423194230.1388945-24-lukeshu@lukeshu.com","subject":"Re: [PATCH 23/30] subtree: add comments and sanity checks","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-04-23T20:58:34Z","receivedAt":"2021-04-23T20:58:49Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> ---\n> diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\n> @@ -248,17 +263,22 @@ rev_exists () {\n> +# Usage: try_remove_previous REV\n> +#\n>  # if a commit doesn't have a parent, this might not work.  But we only want\n\ns/if/If/ perhaps\n\n>  # to remove the parent from the rev-list, and since it doesn't exist, it won't\n>  # be there anyway, so do nothing in that case.\n> @@ -302,10 +322,12 @@ find_latest_squash () {\n> +# Usage: find_existing_splits DIR REV\n>  find_existing_splits () {\n> +       assert test $# = 2\n>         debug \"Looking for prior splits...\"\n>         dir=\"$1\"\n> -       revs=\"$2\"\n> +       rev=\"$2\"\n> @@ -314,7 +336,7 @@ find_existing_splits () {\n>         git log --grep=\"$grep_format\" \\\n> -               --no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' $revs |\n> +               --no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' \"$rev\" |\n\nThe caller of this function is passing in \"$revs\". Did you make this\nsemantic change because the caller's `revs` is guaranteed to be a\nsingle rev? In any case, this change may deserve mention in the commit\nmessage so readers don't have to wonder about it.\n"},{"id":"422818","messageId":"CAPig+cRaQnZ7DWYdU+efNpMgxdniXNQdF43TSFiaj6ezLELC_g@mail.gmail.com","threadId":"55548","inReplyTo":"20210423194230.1388945-25-lukeshu@lukeshu.com","subject":"Re: [PATCH 24/30] subtree: don't let debug and progress output clash","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-04-23T21:07:12Z","receivedAt":"2021-04-23T21:07:58Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> Currently, debug output (triggered by passing '-d') and progress output\n> stomp on eachother.  The debug output is just streamed as lines to\n\ns/eachother/each other/\n\n> stderr, and the progress output is sent to stderr as '%s\\r'.  It is\n> difficult to distinguish between the debug output and a progress line.\n> When writing to a terminal the debug lines hide progress lines.\n>\n> So, when '-d' has been passed, spit out progress as 'progress: %s\\n',\n> instead of as '%s\\r', so that it can be detected, and so that the debug\n> lines don't overwrite the progress when written to a terminal.\n\nMakes perfect sense when output is to a terminal, though might be\nannoying for the person who redirects stderr to a file. Just idly\nwondering if it makes sense to take that case into consideration...\n(but maybe it doesn't matter much when someone is working at debugging\na problem).\n\n> Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> ---\n> diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\n> @@ -53,7 +53,12 @@ debug () {\n>  progress () {\n>         if test -z \"$GIT_QUIET\"\n>         then\n> -               printf \"%s\\r\" \"$*\" >&2\n> +               if test -n \"$arg_debug\"\n> +               then\n> +                       printf \"progress: %s\\n\" \"$*\" >&2\n> +               else\n> +                       printf \"%s\\r\" \"$*\" >&2\n> +               fi\n>         fi\n>  }\n\nSubjective (not necessarily worth changing): An `echo` would suffice\nin place of `printf \"...\\n\"`:\n\n    echo \"progress: $*\" >&2\n\nIt _might_ be worthwhile to have an in-code comment here explaining\nwhy progress() behaves differently in debug mode, especially if the\nreader is confused about why one case explicitly emits \"progress:\" and\nthe other doesn't.\n"},{"id":"422830","messageId":"CAPig+cT=jZdq=oDSHRF6DnvqZVo4OiPGy7x7AzTzdcy6RV76kw@mail.gmail.com","threadId":"55548","inReplyTo":"20210423194230.1388945-5-lukeshu@lukeshu.com","subject":"Re: [PATCH 04/30] subtree: t7900: use consistent formatting","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-04-23T21:51:53Z","receivedAt":"2021-04-23T21:52:06Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> The formatting in t7900-subtree.sh isn't even consistent throughout the\n> file.  Fix that; make it consistent throughout the file.\n>\n> Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> ---\n> diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\n> @@ -23,26 +21,24 @@ subtree_test_create_repo()\n> -check_equal()\n> -{\n> +check_equal () {\n>         test_debug 'echo'\n>         test_debug \"echo \\\"check a:\\\" \\\"{$1}\\\"\"\n>         test_debug \"echo \\\"      b:\\\" \\\"{$2}\\\"\"\n> -       if [ \"$1\" = \"$2\" ]; then\n> +       if [ \"$1\" = \"$2\" ]\n> +       then\n\nWe prefer `test` over `[`, so it might make sense to update that, as\nwell, along with these other style cleanups.\n"},{"id":"422831","messageId":"87v98c1vsd.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"CAPig+cRoxCUcVkLch70x+nUzJbTiyT4KtLDsJ0vZNJD1NboyYQ@mail.gmail.com","subject":"Re: [PATCH 11/30] subtree: t7900: add porcelain tests for 'pull' and 'push'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T22:27:30Z","receivedAt":"2021-04-23T22:27:38Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 14:19:28 -0600,\nEric Sunshine wrote:\n> \n> On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> > The 'pull' and 'push' subcommands deserve their own sections in the tests.\n> > Add some basic tests for them.\n> >\n> > Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> > ---\n> > diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\n> > @@ -202,8 +202,8 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n> >  test_expect_success 'merge new subproj history into subdir/ with a slash appended to the argument of --prefix' '\n> > -       test_create_repo \"$test_count\" &&\n> > -       test_create_repo \"$test_count/subproj\" &&\n> > +       subtree_test_create_repo \"$test_count\" &&\n> > +       subtree_test_create_repo \"$test_count/subproj\" &&\n> >         test_create_commit \"$test_count\" main1 &&\n> >         test_create_commit \"$test_count/subproj\" sub1 &&\n> \n> This change doesn't seem to be related to the stated purpose of this\n> patch. Was it included by accident or is it just a drive-by \"while at\n> it\" fix that seems somewhat related since you're using\n> subtree_test_create_repo() in the newly-added tests? It might deserve\n> mention in the commit message.\n\nIt was included by accident.  I guess I'll move it to be in the\n\"comment subtree_test_create_repo\" commit, and mention it in the\ncommit message there.\n\n> > @@ -427,6 +427,133 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n> > +test_expect_success 'pull requires path given by option --prefix must exist' '\n> > +       test_create_commit \"$test_count/sub proj\" sub1 &&\n> > +       (\n> > +               test_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD >out 2>err &&\n> > +\n> > +               echo \"'\\''sub dir'\\'' does not exist; use '\\''git subtree add'\\''\" > expected &&\n> > +               test_must_be_empty out &&\n> > +               test_cmp expected err\n> > +       )\n> > +'\n> \n> The use of single-quotes and escaped single-quotes within the\n> single-quoted test body is breaking my brain. Perhaps take advantage\n> of SQ from test-lib.sh and interoplate it into the string rather than\n> dealing with raw single-quotes?\n> \n>     echo \"this $SQ is a single-quote\"\n> \n> (After writing the above, I now see that you are just mirroring\n> existing practice in this test script. The single-quotes are\n> confusing, but following existing style may be important -- or not.)\n\nI don't think I'll change it, for consistency with the rest of the\nfile... and I don't want to change the rest of the file, because\nthere's enough churn already.  But thanks for the tip, I wasn't aware\nof $SQ.\n\n> > +test_expect_success 'pull basic operation' '\n> > +       subtree_test_create_repo \"$test_count\" &&\n> > +       subtree_test_create_repo \"$test_count/sub proj\" &&\n> > +       test_create_commit \"$test_count\" main1 &&\n> > +       test_create_commit \"$test_count/sub proj\" sub1 &&\n> > +       (\n> > +               cd \"$test_count\" &&\n> > +               git fetch ./\"sub proj\" HEAD &&\n> \n> I was going to comment on the unusual:\n> \n>     ./\"sub proj\"\n> \n> rather than the more typical:\n> \n>     \"./sub proj\"\n> \n> but I see that that also is mirroring existing practice in this\n> script, so... [intentionally left blank]\n\n...yeah\n\n> > +test_expect_success 'push requires option --prefix' '\n> > +       subtree_test_create_repo \"$test_count\" &&\n> > +       subtree_test_create_repo \"$test_count/sub proj\" &&\n> > +       test_create_commit \"$test_count\" main1 &&\n> > +       test_create_commit \"$test_count/sub proj\" sub1 &&\n> > +       (\n> > +               cd \"$test_count\" &&\n> > +               git fetch ./\"sub proj\" HEAD &&\n> > +               git subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n> > +               echo \"You must provide the --prefix option.\" > expected &&\n> > +               test_must_fail git subtree push \"./sub proj\" from-mainline > actual 2>&1 &&\n> \n> Style: There is an inconsistent mix of \"> foo\" and \">foo\" formatting\n> in the newly-added tests. These days, we prefer \">foo\".\n\nIndeed, so do I :) That test was copied with minimal modification from\nthe pre-existing 'split requires option --prefix' test, which wrote it\nthat way.  I guess I'll update the formatting commit to also normalize\naway the whitespace after \">\"s.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422832","messageId":"87tunw1v1l.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"CAPig+cQLP1XFnMFWOp4Zj-Ku8M-aqgE5DmpgEy=UWLqpBBW8Ng@mail.gmail.com","subject":"Re: [PATCH 12/30] subtree: don't have loose code outside of a function","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T22:43:34Z","receivedAt":"2021-04-23T22:43:47Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 14:23:18 -0600,\nEric Sunshine wrote:\n> \n> On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> > Shove all of the loose code inside of a main() function.\n> >\n> > \"Ignore space change\" is probably helpful when viewing this diff.\n> >\n> > Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> \n> What is the purpose of this change? Does some subsequent commit depend\n> upon this or is it just a personal preference? The commit message\n> explains the \"what\" of the change but not the \"why\".\n\nDropping the commit would surely cause me much trouble with rebasing\nboth the subsequent commits in this patchset and the commits I haven't\nyet submitted.  But I don't think they \"depend\" on it.\n\nI guess it is personal preference... one that I've developed from\nyears of maintaining Bash scripts.  It's in a nearby part of my brain\nto \"avoid global variables\".  It's related to my notion that the\nreason most people think shell scripts are so terrible is that most\npeople don't treat it like a real programming language and don't apply\nnormal programming best practices; that not littering code around\noutside of a function is part of treating it like a real language (at\nleast once the program grows beyond a certain size, which git-subtree\nsurely has).  It's probably related to the Python idiom\n\n    if __name__ == \"__main__\":\n        main()\n\nthat is often seen at the bottom of Python scripts.\n\nIn this specific case, it's also moving the `set -- -h`, the `git\nrev-parse --parseopt`, and the `. git-sh-setup` to be closer to all\nthe rest of the argument parsing, which is a readability win on its\nown, IMO.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422833","messageId":"87sg3g1uk5.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"CAPig+cT=jZdq=oDSHRF6DnvqZVo4OiPGy7x7AzTzdcy6RV76kw@mail.gmail.com","subject":"Re: [PATCH 04/30] subtree: t7900: use consistent formatting","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T22:54:02Z","receivedAt":"2021-04-23T22:54:10Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 15:51:53 -0600,\nEric Sunshine wrote:\n> \n> On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> > The formatting in t7900-subtree.sh isn't even consistent throughout the\n> > file.  Fix that; make it consistent throughout the file.\n> >\n> > Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> > ---\n> > diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\n> > @@ -23,26 +21,24 @@ subtree_test_create_repo()\n> > -check_equal()\n> > -{\n> > +check_equal () {\n> >         test_debug 'echo'\n> >         test_debug \"echo \\\"check a:\\\" \\\"{$1}\\\"\"\n> >         test_debug \"echo \\\"      b:\\\" \\\"{$2}\\\"\"\n> > -       if [ \"$1\" = \"$2\" ]; then\n> > +       if [ \"$1\" = \"$2\" ]\n> > +       then\n> \n> We prefer `test` over `[`, so it might make sense to update that, as\n> well, along with these other style cleanups.\n\nOK, I'll include that in this commit.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422834","messageId":"CAPig+cTnqYnxPpcn1GTDOpzb2mHAseA694cc-d3mP0JD7VNU5A@mail.gmail.com","threadId":"55548","inReplyTo":"87tunw1v1l.wl-lukeshu@lukeshu.com","subject":"Re: [PATCH 12/30] subtree: don't have loose code outside of a function","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-04-23T23:11:11Z","receivedAt":"2021-04-23T23:11:40Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 23, 2021 at 6:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> On Fri, 23 Apr 2021 14:23:18 -0600, Eric Sunshine wrote:\n> > What is the purpose of this change? Does some subsequent commit depend\n> > upon this or is it just a personal preference? The commit message\n> > explains the \"what\" of the change but not the \"why\".\n>\n> Dropping the commit would surely cause me much trouble with rebasing\n> both the subsequent commits in this patchset and the commits I haven't\n> yet submitted.  But I don't think they \"depend\" on it.\n>\n> I guess it is personal preference... [...]\n\nThat's fine. I wasn't suggesting removing the commit but was\ninterested in having the commit message explain the reason for the\nchange, which is often the most important part of the commit message\nto convince readers (reviewers) that the patch isn't just needless\nnoise. Obviously, if changes in subsequent patches become easier by\nmaking this change, then that's easier to explain than something which\nis mere personal preference -- which isn't to say that such preference\nisn't important, especially if you're going to be living in the code\nfor a while.\n\n> In this specific case, it's also moving the `set -- -h`, the `git\n> rev-parse --parseopt`, and the `. git-sh-setup` to be closer to all\n> the rest of the argument parsing, which is a readability win on its\n> own, IMO.\n\nIf you happen to re-roll, perhaps update the commit message to include\na small bit of your explanation (which I've mostly snipped here). The\nlast bit about moving `set -- -h` and whatnot closer to the rest of\nthe argument parsing -- basically improving encapsulation -- may be\njustification enough for readers.\n"},{"id":"422835","messageId":"8735vgbmy6.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"CAPig+cRcBA1y0WY_k4fge1KiRcLrW7PMeOS=Ns8bMa4VMdyy2w@mail.gmail.com","subject":"Re: [PATCH 14/30] subtree: drop support for git < 1.7","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T23:28:17Z","receivedAt":"2021-04-23T23:28:30Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 14:31:46 -0600,\nEric Sunshine wrote:\n> \n> On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> > That was nice to have when git-subtree lived out-of-tree.  But now that\n> > it lives in git.git, it's not nescessary to keep around.\n> \n> s/nescessary/necessary/\n\nAck.\n\n> > Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> \n> Is there a higher reason for this change aside from \"let's do it\n> because we can\"? For instance, are subsequent changes going to take\n> advantage of features only present in more recent Git versions which\n> would be painful or impossible to support with the older Git?\n> \n> The downside of this change is that, while git-subtree may live in\n> git.git, it's still just \"contrib\", so people might grab git-subtree\n> from a modern git.git but then end up using it with an older Git\n> installation. That's not to say that doing such a thing is guaranteed\n> to work anyhow, but we don't need to make it harder on people if there\n> isn't a good reason (hence my question about whether subsequent\n> changes will actually take advantage of newer Git features).\n\nWith the goal of making the whole thing easier to hack on, this just\nseemed like an easy (if small) piece of fat to trim.\n\nI guess I should include here that my bias is: With the 'git' package\nthat Parabola inherits from Arch Linux, you install 'git', you get a\nworking 'git subtree'.  If you want 'git send-email' to work, you also\nneed to install several other Perl packages.  Like, it might live in\nthe \"contrib\" directory, but it's de-facto at least as much a \"part\nof\" Git as send-email is.\n\nSo that's the mindset I started from.  It looks like the latest macOS\nsupports me on that, but other distros like Fedora don't (Fedora has a\nseparate 'git-subtree' package).  If I take a step back, I realize\nthat mindset is flawed, but that's where I started from.\n\nI don't think any of the other work depends on this (I think the only\ncommit that will conflict if we drop it is the \"rename a some\nvariables\" commit in this patchset).  It's very possible that\nsomething else I do relies on newer git features (I'm not testing\nagainst older git), but that's not something I did intentionally.\n\nI just figured this would be a welcome piece of cleanup.  If that's\nnot the case, I don't have a problem dropping it.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422836","messageId":"871rb0bmjd.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"CAPig+cTnqYnxPpcn1GTDOpzb2mHAseA694cc-d3mP0JD7VNU5A@mail.gmail.com","subject":"Re: [PATCH 12/30] subtree: don't have loose code outside of a function","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T23:37:10Z","receivedAt":"2021-04-23T23:38:15Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 17:11:11 -0600,\nEric Sunshine wrote:\n> If you happen to re-roll, perhaps update the commit message to include\n> a small bit of your explanation (which I've mostly snipped here). The\n> last bit about moving `set -- -h` and whatnot closer to the rest of\n> the argument parsing -- basically improving encapsulation -- may be\n> justification enough for readers.\n\nWhenever I end up explaining something on-list, I assume that I should\nupdate either a comment or a commit-message when I re-roll :)\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422837","messageId":"CAPig+cRutK=C6WcnFyh+AJO0G5iyAUV1Us4U_F8gtDZK1+s1cg@mail.gmail.com","threadId":"55548","inReplyTo":"8735vgbmy6.wl-lukeshu@lukeshu.com","subject":"Re: [PATCH 14/30] subtree: drop support for git < 1.7","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-04-23T23:50:11Z","receivedAt":"2021-04-23T23:50:34Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 23, 2021 at 7:28 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> On Fri, 23 Apr 2021 14:31:46 -0600, Eric Sunshine wrote:\n> > Is there a higher reason for this change aside from \"let's do it\n> > because we can\"? For instance, are subsequent changes going to take\n> > advantage of features only present in more recent Git versions which\n> > would be painful or impossible to support with the older Git?\n> >\n> > The downside of this change is that, while git-subtree may live in\n> > git.git, it's still just \"contrib\", so people might grab git-subtree\n> > from a modern git.git but then end up using it with an older Git\n> > installation. That's not to say that doing such a thing is guaranteed\n> > to work anyhow, but we don't need to make it harder on people if there\n> > isn't a good reason (hence my question about whether subsequent\n> > changes will actually take advantage of newer Git features).\n>\n> With the goal of making the whole thing easier to hack on, this just\n> seemed like an easy (if small) piece of fat to trim.\n>\n> I guess I should include here that my bias is: With the 'git' package\n> that Parabola inherits from Arch Linux, you install 'git', you get a\n> working 'git subtree'.  If you want 'git send-email' to work, you also\n> need to install several other Perl packages.  Like, it might live in\n> the \"contrib\" directory, but it's de-facto at least as much a \"part\n> of\" Git as send-email is.\n>\n> So that's the mindset I started from.  It looks like the latest macOS\n> supports me on that, but other distros like Fedora don't (Fedora has a\n> separate 'git-subtree' package).  If I take a step back, I realize\n> that mindset is flawed, but that's where I started from.\n>\n> I don't think any of the other work depends on this (I think the only\n> commit that will conflict if we drop it is the \"rename a some\n> variables\" commit in this patchset).  It's very possible that\n> something else I do relies on newer git features (I'm not testing\n> against older git), but that's not something I did intentionally.\n>\n> I just figured this would be a welcome piece of cleanup.  If that's\n> not the case, I don't have a problem dropping it.\n\nAs a person who does not and has never used git-subtree, I don't have\na strong opinion, and any git-subtree opinion I might have wouldn't\ncarry any weight. I do have a bit of reflexive negative reaction to\nsuch removals in general if there's no clear and strong benefit,\nperhaps because my daily-use computers are old (perhaps ancient, as in\n10-25 years old), so I am regularly stung by support being dropped by\npackages I use. That's why I was asking if later patches would take\nadvantage of some newer Git feature.\n\nAnyhow, I wasn't specifically asking for the patch to be dropped. As a\nreviewer I rather wanted to better understand the reason for the\nchange beyond the somewhat hand-wavy \"git-subtree now lives in-tree\".\nIf you happen to re-roll, perhaps you can expand the commit message a\nbit with something more concrete (for instance, how some packagers\ninclude git-subtree by default) to better sell the patch to reviewers\nwho actually have investment in git-subtree (of which I am not one).\nConsidering how old Git <1.7 is, it's quite likely that no current\ngit-subtree users/reviewers would care about dropping support for such\nold versions.\n"},{"id":"422838","messageId":"87zgxoa7cj.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"CAPig+cTb-h=Qb9asvh+MVH2s5uj7szP_QOPpcm1bqdE6DK9V7g@mail.gmail.com","subject":"Re: [PATCH 18/30] subtree: use $* instead of $@ as appropriate","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T23:50:36Z","receivedAt":"2021-04-23T23:50:47Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 14:40:31 -0600,\nEric Sunshine wrote:\n> \n> On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> > $* is for when you want to smash things together, whitespace-separated;\n> > $@ is for when you want them to be separate strings.  There are a couple\n> > of places in subtree that erroneously use $@ when smashing args together\n> > in to an error message.\n> \n> Can we be explicit and say \"$@\" in the commit message rather than bare\n> $@ since the unquoted form is not magical and acts exactly like $*.\n> \n> Also: s/in to/into/\n> \n> Nit: I have some trouble following what the commit message is actually\n> trying to say with \"smash things\" and \"separate strings\". It might be\n> simpler to say merely that use of \"$@\" in these particular instances\n> is overkill and possibly misleading to readers not familiar with the\n> finer details of $* vs. \"$@\".\n> \n> The patch itself makes sense.\n\nHow's this:\n\n---\nsubtree: use \"$*\" instead of \"$@\" as appropriate\n\n\"$*\" is for when you want to concatenate the args together,\nwhitespace-separated; and \"$@\" is for when you want them to be separate\nstrings.\n\nThere are several places in subtree that erroneously use $@ when\nconcatenating args together into an error message.\n\nFor instance, if the args are argv[1]=\"dead\" and argv[2]=\"beef\", then\nthe line\n\n    die \"You must provide exactly one revision.  Got: '$@'\"\n\nsurely intends to call 'die' with the argument\n\n    argv[1]=\"You must provide exactly one revision.  Got: 'dead beef'\"\n\nhowever, because the line used $@ instead of $*, it will actually call\n'die' with the arguments\n\n    argv[1]=\"You must provide exactly one revision.  Got: 'dead\"\n    argv[2]=\"beef'\"\n\nThis isn't a big deal, because 'die' concatenates its arguments together\nanyway (using \"$*\").  But that doesn't change the fact that it was a\nmistake to use $@ instead of $*, even though in the end $@ still ended\nup doing the right thing.\n---\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422839","messageId":"87y2d8a6zn.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"CAPig+cQmTTdVKQptQY_tT_x4DCduRh=Mq6QZ1vUsc790-0yTQw@mail.gmail.com","subject":"Re: [PATCH 23/30] subtree: add comments and sanity checks","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-23T23:58:20Z","receivedAt":"2021-04-23T23:58:26Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 14:58:34 -0600,\nEric Sunshine wrote:\n> \n> On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> > Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> > ---\n> > diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\n> > @@ -248,17 +263,22 @@ rev_exists () {\n> > +# Usage: try_remove_previous REV\n> > +#\n> >  # if a commit doesn't have a parent, this might not work.  But we only want\n> \n> s/if/If/ perhaps\n\nAck.\n\n> >  # to remove the parent from the rev-list, and since it doesn't exist, it won't\n> >  # be there anyway, so do nothing in that case.\n> > @@ -302,10 +322,12 @@ find_latest_squash () {\n> > +# Usage: find_existing_splits DIR REV\n> >  find_existing_splits () {\n> > +       assert test $# = 2\n> >         debug \"Looking for prior splits...\"\n> >         dir=\"$1\"\n> > -       revs=\"$2\"\n> > +       rev=\"$2\"\n> > @@ -314,7 +336,7 @@ find_existing_splits () {\n> >         git log --grep=\"$grep_format\" \\\n> > -               --no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' $revs |\n> > +               --no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' \"$rev\" |\n> \n> The caller of this function is passing in \"$revs\". Did you make this\n> semantic change because the caller's `revs` is guaranteed to be a\n> single rev? In any case, this change may deserve mention in the commit\n> message so readers don't have to wonder about it.\n\nNo it's not?  The only caller is\n\n\tunrevs=\"$(find_existing_splits \"$dir\" \"$rev\")\" || exit $?\n\nBut yeah, this would be a good thing for me to call out in the commit\nmessage.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422840","messageId":"87wnssa5xz.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"CAPig+cRutK=C6WcnFyh+AJO0G5iyAUV1Us4U_F8gtDZK1+s1cg@mail.gmail.com","subject":"Re: [PATCH 14/30] subtree: drop support for git < 1.7","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-24T00:20:56Z","receivedAt":"2021-04-24T00:21:06Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 17:50:11 -0600,\nEric Sunshine wrote:\n> \n> On Fri, Apr 23, 2021 at 7:28 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> > On Fri, 23 Apr 2021 14:31:46 -0600, Eric Sunshine wrote:\n> > > Is there a higher reason for this change aside from \"let's do it\n> > > because we can\"? For instance, are subsequent changes going to take\n> > > advantage of features only present in more recent Git versions which\n> > > would be painful or impossible to support with the older Git?\n> > >\n> > > The downside of this change is that, while git-subtree may live in\n> > > git.git, it's still just \"contrib\", so people might grab git-subtree\n> > > from a modern git.git but then end up using it with an older Git\n> > > installation. That's not to say that doing such a thing is guaranteed\n> > > to work anyhow, but we don't need to make it harder on people if there\n> > > isn't a good reason (hence my question about whether subsequent\n> > > changes will actually take advantage of newer Git features).\n> >\n> > With the goal of making the whole thing easier to hack on, this just\n> > seemed like an easy (if small) piece of fat to trim.\n> >\n> > I guess I should include here that my bias is: With the 'git' package\n> > that Parabola inherits from Arch Linux, you install 'git', you get a\n> > working 'git subtree'.  If you want 'git send-email' to work, you also\n> > need to install several other Perl packages.  Like, it might live in\n> > the \"contrib\" directory, but it's de-facto at least as much a \"part\n> > of\" Git as send-email is.\n> >\n> > So that's the mindset I started from.  It looks like the latest macOS\n> > supports me on that, but other distros like Fedora don't (Fedora has a\n> > separate 'git-subtree' package).  If I take a step back, I realize\n> > that mindset is flawed, but that's where I started from.\n> >\n> > I don't think any of the other work depends on this (I think the only\n> > commit that will conflict if we drop it is the \"rename a some\n> > variables\" commit in this patchset).  It's very possible that\n> > something else I do relies on newer git features (I'm not testing\n> > against older git), but that's not something I did intentionally.\n> >\n> > I just figured this would be a welcome piece of cleanup.  If that's\n> > not the case, I don't have a problem dropping it.\n> \n> As a person who does not and has never used git-subtree, I don't have\n> a strong opinion, and any git-subtree opinion I might have wouldn't\n> carry any weight. I do have a bit of reflexive negative reaction to\n> such removals in general if there's no clear and strong benefit,\n> perhaps because my daily-use computers are old (perhaps ancient, as in\n> 10-25 years old), so I am regularly stung by support being dropped by\n> packages I use. That's why I was asking if later patches would take\n> advantage of some newer Git feature.\n\nI'm sending this from my work laptop, which is a little newer (2015),\nbut my personal laptop (2007) is sitting on the end-table.  So I\ncommiserate.  I'm a modern-software on old-hardware kind of guy\nthough, so I don't mind dropping support for old software versions.\n\n> Anyhow, I wasn't specifically asking for the patch to be dropped. As a\n> reviewer I rather wanted to better understand the reason for the\n> change beyond the somewhat hand-wavy \"git-subtree now lives in-tree\".\n> If you happen to re-roll, perhaps you can expand the commit message a\n> bit with something more concrete (for instance, how some packagers\n> include git-subtree by default) to better sell the patch to reviewers\n> who actually have investment in git-subtree (of which I am not one).\n> Considering how old Git <1.7 is, it's quite likely that no current\n> git-subtree users/reviewers would care about dropping support for such\n> old versions.\n\nI'll expand the commit message.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422842","messageId":"87v98ca4uf.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"CAPig+cRaQnZ7DWYdU+efNpMgxdniXNQdF43TSFiaj6ezLELC_g@mail.gmail.com","subject":"Re: [PATCH 24/30] subtree: don't let debug and progress output clash","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-24T00:44:40Z","receivedAt":"2021-04-24T00:46:06Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 15:07:12 -0600,\nEric Sunshine wrote:\n> \n> On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> > Currently, debug output (triggered by passing '-d') and progress output\n> > stomp on eachother.  The debug output is just streamed as lines to\n> \n> s/eachother/each other/\n\nAck.\n\n> > stderr, and the progress output is sent to stderr as '%s\\r'.  It is\n> > difficult to distinguish between the debug output and a progress line.\n> > When writing to a terminal the debug lines hide progress lines.\n> >\n> > So, when '-d' has been passed, spit out progress as 'progress: %s\\n',\n> > instead of as '%s\\r', so that it can be detected, and so that the debug\n> > lines don't overwrite the progress when written to a terminal.\n> \n> Makes perfect sense when output is to a terminal, though might be\n> annoying for the person who redirects stderr to a file. Just idly\n> wondering if it makes sense to take that case into consideration...\n> (but maybe it doesn't matter much when someone is working at debugging\n> a problem).\n\nThe '%s\\r' isn't really useful when written to a file, so this change\nis useful in the file case too.  I'll add a comment and update the\ncommit-message.\n\n> > Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> > ---\n> > diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\n> > @@ -53,7 +53,12 @@ debug () {\n> >  progress () {\n> >         if test -z \"$GIT_QUIET\"\n> >         then\n> > -               printf \"%s\\r\" \"$*\" >&2\n> > +               if test -n \"$arg_debug\"\n> > +               then\n> > +                       printf \"progress: %s\\n\" \"$*\" >&2\n> > +               else\n> > +                       printf \"%s\\r\" \"$*\" >&2\n> > +               fi\n> >         fi\n> >  }\n> \n> Subjective (not necessarily worth changing): An `echo` would suffice\n> in place of `printf \"...\\n\"`:\n> \n>     echo \"progress: $*\" >&2\n\necho would suffice, but I prefer the printf.\n\n> It _might_ be worthwhile to have an in-code comment here explaining\n> why progress() behaves differently in debug mode, especially if the\n> reader is confused about why one case explicitly emits \"progress:\" and\n> the other doesn't.\n\nAdding a comment is a good idea, I'll do that.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422849","messageId":"CAPig+cSJJ9EXRN4p2MYcMGVe8sCutdZ4NGZYfX+E0mLSuFA6SQ@mail.gmail.com","threadId":"55548","inReplyTo":"87v98ca4uf.wl-lukeshu@lukeshu.com","subject":"Re: [PATCH 24/30] subtree: don't let debug and progress output clash","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-04-24T04:54:35Z","receivedAt":"2021-04-24T04:54:50Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 23, 2021 at 8:44 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> On Fri, 23 Apr 2021 15:07:12 -0600, Eric Sunshine wrote:\n> > Makes perfect sense when output is to a terminal, though might be\n> > annoying for the person who redirects stderr to a file. Just idly\n> > wondering if it makes sense to take that case into consideration...\n> > (but maybe it doesn't matter much when someone is working at debugging\n> > a problem).\n>\n> The '%s\\r' isn't really useful when written to a file, so this change\n> is useful in the file case too.  I'll add a comment and update the\n> commit-message.\n\nAh, right. I didn't pay close enough attention to really notice that\nthe \"\\r\"-terminated line was going to stderr, so ignore that bit in my\nreview comment.\n"},{"id":"422850","messageId":"CAPig+cQ_7eVgdYuci1JeVwU89VOeOU6kzZ9=yw1ySR9RXzjuTA@mail.gmail.com","threadId":"55548","inReplyTo":"87zgxoa7cj.wl-lukeshu@lukeshu.com","subject":"Re: [PATCH 18/30] subtree: use $* instead of $@ as appropriate","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-04-24T05:18:33Z","receivedAt":"2021-04-24T05:19:42Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 23, 2021 at 7:50 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> On Fri, 23 Apr 2021 14:40:31 -0600, Eric Sunshine wrote:\n> > Nit: I have some trouble following what the commit message is actually\n> > trying to say with \"smash things\" and \"separate strings\". It might be\n> > simpler to say merely that use of \"$@\" in these particular instances\n> > is overkill and possibly misleading to readers not familiar with the\n> > finer details of $* vs. \"$@\".\n\nOof, I somehow misread the code this patch is touching and ended up\nconfusing myself, and the confusion bled into my review comments.\nSorry.\n\n> How's this:\n> ---\n> subtree: use \"$*\" instead of \"$@\" as appropriate\n>\n> \"$*\" is for when you want to concatenate the args together,\n> whitespace-separated; and \"$@\" is for when you want them to be separate\n> strings.\n>\n> There are several places in subtree that erroneously use $@ when\n> concatenating args together into an error message.\n>\n> For instance, if the args are argv[1]=\"dead\" and argv[2]=\"beef\", then\n> the line\n>\n>     die \"You must provide exactly one revision.  Got: '$@'\"\n>\n> surely intends to call 'die' with the argument\n>\n>     argv[1]=\"You must provide exactly one revision.  Got: 'dead beef'\"\n>\n> however, because the line used $@ instead of $*, it will actually call\n> 'die' with the arguments\n>\n>     argv[1]=\"You must provide exactly one revision.  Got: 'dead\"\n>     argv[2]=\"beef'\"\n>\n> This isn't a big deal, because 'die' concatenates its arguments together\n> anyway (using \"$*\").  But that doesn't change the fact that it was a\n> mistake to use $@ instead of $*, even though in the end $@ still ended\n> up doing the right thing.\n\nThis explanation spells out the problem nicely.\n"},{"id":"422851","messageId":"CAPig+cTdTTq+W-QM3y60621GqqgXiHOueKF_Yk35=bL5p8o9uw@mail.gmail.com","threadId":"55548","inReplyTo":"20210423194230.1388945-28-lukeshu@lukeshu.com","subject":"Re: [PATCH 27/30] subtree: allow --squash to be used with --rejoin","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2021-04-24T05:50:08Z","receivedAt":"2021-04-24T05:52:50Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> Besides being a genuinely useful thing to do, this also just makes sense\n> and harmonizes which flags may be used when.  `git subtree split\n> --rejoin` amounts to \"automatically go ahead and do a `git subtree\n> merge` after doing the main `git subtree split`\", so it's weird and\n> arbitrary that you can't pass `--squash` to `git subtree split --rejoin`\n> like you can `git subtree merge`.  It's weird that `git subtree split\n> --rejoin` inherits `git subtree merge`'s `--message` but not `--squash`.\n>\n> Reconcile the situation by just having `split --rejoin` actually just\n> call `merge` internally (or call `add` instead, as appropriate), so it\n> can get access to the full `merge` behavior, including `--squash`.\n>\n> Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> ---\n> diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\n> @@ -324,6 +324,41 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n> +test_expect_success 'split \"sub dir\"/ with --rejoin and --squash' '\n> +       [...]\n> +               SPLIT=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin --squash) &&\n> +\n> +               ! git merge-base --is-ancestor $SUB HEAD &&\n> +               ! git merge-base --is-ancestor $SPLIT HEAD &&\n\nIt's preferable to use `test_must_fail` rather than `!` for Git\ncommands (but not for non-Git commands) since `test_must_fail`\ncorrectly distinguishes between an expected failure and an unexpected\none such as a crash, whereas `!` can't make that distinction and would\neven consider a crashed Git invocation to be successful.\n\nExisting tests in this script already employ `test_must_fail` rather\nthan `!`, so using `test_must_fail` would also match precedent.\n"},{"id":"422865","messageId":"87tunv9qmg.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"CAPig+cTdTTq+W-QM3y60621GqqgXiHOueKF_Yk35=bL5p8o9uw@mail.gmail.com","subject":"Re: [PATCH 27/30] subtree: allow --squash to be used with --rejoin","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-25T00:04:07Z","receivedAt":"2021-04-25T00:04:15Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 23 Apr 2021 23:50:08 -0600,\nEric Sunshine wrote:\n> On Fri, Apr 23, 2021 at 3:43 PM Luke Shumaker <lukeshu@lukeshu.com> wrote:\n> > +               ! git merge-base --is-ancestor $SUB HEAD &&\n> > +               ! git merge-base --is-ancestor $SPLIT HEAD &&\n> \n> It's preferable to use `test_must_fail` rather than `!` for Git\n> commands\n\nIndeed, this was an oversight on my part.  I'll adjust it.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422867","messageId":"CAMbsUu7PQ+Ni-fhGa3Fbc3YTODETYaPYGLPW9jqGgo=TcdPaAA@mail.gmail.com","threadId":"55548","inReplyTo":"20210423194230.1388945-31-lukeshu@lukeshu.com","subject":"Re: [PATCH 30/30] subtree: be stricter about validating flags","fromName":"Danny Lin","fromEmail":"danny0838@gmail.com","sentAt":"2021-04-25T02:55:17Z","receivedAt":"2021-04-25T02:55:35Z","isPatch":true,"sender":{"key":"danny0838@gmail.com","avatar":"https://avatars.githubusercontent.com/u/531417?v=4"},"body":">\n> From: Luke Shumaker <lukeshu@datawire.io>\n>\n> Don't silently ignore a flag that's invalid for a given subcommand.  The\n> user expected it to do something; we should tell the user that they are\n> mistaken, instead of surprising the user.\n>\n> It could be argued that this change might break existing users.  I'd\n> argue that those existing users are already broken, and they just don't\n> know it.  Let them know that they're broken.\n>\n> Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> ......\n\nThank you for the recent works, Luke.\n\nI'd like to know if you are aware or working on the issue that branches\nbefore \"git subtree add --squash\" are pushed via \"git subtree push\",\nwhich has been reported by me at Tue, 16 Jul 2019 02:30:44 +0800, as I\nhaven't seen an obvious fix about it in the recent patches in a quick\nglance.\n\nBelow is the original report (with a slight modification):\n\n-----------------------------------------------------------------------\n\nSay we have a repository with \"master\" and \"sub\" branches like below:\n\n    A---B---C---D---E---F  master\n               /\n          X---Y\n\n    X---Y  sub\n\nwhere commits A and B include changes in subdirectory \"sub\", commit C\nremoves subdirectory \"sub\", commit D is generated by \"git subtree add\n-P sub Y\", and commits E and F also include changes in subdirectory\n\"sub\".\n\nWe'd get this if we run \"git subtree push -P sub . sub\" on master at F:\n\n    X---Y---E'--F'  sub (after push)\n\nOn the other hand, if we have simliar trees except that commit D is\ngenerated by \"git subtree add --squash -P sub Y\":\n\n    A---B---C---D---E---F  master\n               /\n              Y'\n\n    X---Y  sub\n\nWe'd expect to get this after we run \"git subtree push -P sub . sub\" on\nmaster at F:\n\n    X---Y---E'--F'  sub (after push, expected)\n\nBut actually we get this (in Git 2.22.0):\n\n    A---B---C---D'--E'--F'  sub (after push, actual)\n               /\n          X---Y\n\nThis seems to be a side effect of 2.7.0 -> 2.7.1 in which a change is\nmade to include merged branches in \"git subtree push\", but mistakenly\ncauses branches before \"git subtree add --squash\" be included.\n\n\n\nThis bug is especially obvious if we simply run `git subtree push`\nafter a `git subtree add --squash`:\n\nIf master is at commit D, which is generated by\n`git subtree add --squash -P sub Y`:\n\n    A---B---C---D  master\n               /\n              Y'\n\n    X---Y  sub\n\nAfter running `git subtree push -P sub . sub`, we get:\n\n    A---B---C---D'  sub (after push, actual)\n               /\n          X---Y\n\nWhile the sub branch should not change at all!\n\nThis bug, seemingly introduced by 933cfeb90b5d03b4096db6d60494a6eedea25d03\ncritically makes --squash approach for `git subtree` almost unusable.\n"},{"id":"422915","messageId":"87bla11oo3.fsf@evledraar.gmail.com","threadId":"55548","inReplyTo":"20210423194230.1388945-20-lukeshu@lukeshu.com","subject":"Re: [PATCH 19/30] subtree: give `$(git --exec-path)` precedence over `$PATH`","fromName":"=?utf-8?B?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-04-26T08:27:06Z","receivedAt":"2021-04-26T08:27:11Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Apr 23 2021, Luke Shumaker wrote:\n\n> From: Luke Shumaker <lukeshu@datawire.io>\n>\n> Other Git commands implemented in shell give `git --exec-path`\n> precedence over the existing $PATH, but subtree gives the existing $PATH\n> precedence.  Flip subtree's PATH around to match what other commands do.\n>\n> Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> ---\n>  contrib/subtree/git-subtree.sh | 2 +-\n>  1 file changed, 1 insertion(+), 1 deletion(-)\n>\n> diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\n> index 3105eb8033..9d365c9f2f 100755\n> --- a/contrib/subtree/git-subtree.sh\n> +++ b/contrib/subtree/git-subtree.sh\n> @@ -28,7 +28,7 @@ rejoin        merge the new branch back into HEAD\n>  squash        merge subtree changes as a single commit\n>  \"\n>  \n> -PATH=$PATH:$(git --exec-path)\n> +PATH=$(git --exec-path):$PATH\n\nThe history of git-subtree.sh suggests that instead of this change we'd\nbe better of removing this PATH assignment, and then later doing:\n\n    . \"$(git --exec-path)/git-sh-setup\"\n\nIsn't that closer to what git-subtree.sh wants here?\n"},{"id":"422916","messageId":"875z091nuj.fsf@evledraar.gmail.com","threadId":"55548","inReplyTo":"87wnss2219.wl-lukeshu@lukeshu.com","subject":"Re: [PATCH 00/30] subtree: clean up, improve UX","fromName":"=?utf-8?B?w4Z2YXIgQXJuZmrDtnLDsA==?= Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-04-26T07:55:48Z","receivedAt":"2021-04-26T08:40:52Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Apr 23 2021, Luke Shumaker wrote:\n\n> On Fri, 23 Apr 2021 13:42:00 -0600,\n> Luke Shumaker wrote:\n>>                                                  I promise that\n>> there's more work coming on top of it (we've discovered lots of ways\n>> to break the \"subtree split\" algorithm, and come up with fixes for\n>> most of them).\n>\n> Follow-up question: If in that work I changed the shebang from\n> \"#!/bin/sh\" to \"#!/usr/bin/env bash\" and started using Bash arrays,\n> would that be so bad?  Would that be land-able?\n\nIt's in contrib, so personally I don't care much. But e.g. on OSX that\nmeans targeting some ancient (and going away?) version of bash + having\n*BSDs needing to install bash for this etc.\n\nBash or not it seems to me like that argument parsing code could be much\nsimplified by simply declaring strings of arguments accepted for each\nsub-command, and then parsing those arguments + dying on unknown ones.\n"},{"id":"422918","messageId":"878s551oet.fsf@evledraar.gmail.com","threadId":"55548","inReplyTo":"20210423194230.1388945-21-lukeshu@lukeshu.com","subject":"Re: [PATCH 20/30] subtree: use \"^{commit}\" instead of \"^0\"","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-04-26T07:43:38Z","receivedAt":"2021-04-26T08:43:18Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Fri, Apr 23 2021, Luke Shumaker wrote:\n\n> From: Luke Shumaker <lukeshu@datawire.io>\n>\n> They are synonyms.  Both are used in the file.  ^{commit} is clearer, so\n> \"standardize\" on that.\n>\n> Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> ---\n>  contrib/subtree/git-subtree.sh | 4 ++--\n>  1 file changed, 2 insertions(+), 2 deletions(-)\n>\n> diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\n> index 9d365c9f2f..d200fbfed7 100755\n> --- a/contrib/subtree/git-subtree.sh\n> +++ b/contrib/subtree/git-subtree.sh\n> @@ -302,7 +302,7 @@ find_latest_squash () {\n>  \t\t\tmain=\"$b\"\n>  \t\t\t;;\n>  \t\tgit-subtree-split:)\n> -\t\t\tsub=\"$(git rev-parse \"$b^0\")\" ||\n> +\t\t\tsub=\"$(git rev-parse \"$b^{commit}\")\" ||\n>  \t\t\tdie \"could not rev-parse split hash $b from commit $sq\"\n>  \t\t\t;;\n>  \t\tEND)\n> @@ -349,7 +349,7 @@ find_existing_splits () {\n>  \t\t\tmain=\"$b\"\n>  \t\t\t;;\n>  \t\tgit-subtree-split:)\n> -\t\t\tsub=\"$(git rev-parse \"$b^0\")\" ||\n> +\t\t\tsub=\"$(git rev-parse \"$b^{commit}\")\" ||\n>  \t\t\tdie \"could not rev-parse split hash $b from commit $sq\"\n>  \t\t\t;;\n>  \t\tEND)\n\nNot a new problem, but those error messages seem weird/bad, isn't that\nmessage originally from find_existing_splits() and copied over to\nfind_latest_squash() where talking about \"split hash\" doesn't make\nsense?\n\nI'd expect something like \"could not peel $b to commit\" as the error for\nboth.\n"},{"id":"422989","messageId":"87pmyh9cf4.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"CAMbsUu7PQ+Ni-fhGa3Fbc3YTODETYaPYGLPW9jqGgo=TcdPaAA@mail.gmail.com","subject":"Re: [PATCH 30/30] subtree: be stricter about validating flags","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:35:27Z","receivedAt":"2021-04-26T17:35:34Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Sat, 24 Apr 2021 20:55:17 -0600,\nDanny Lin wrote:\n> Thank you for the recent works, Luke.\n> \n> I'd like to know if you are aware or working on the issue that branches\n> before \"git subtree add --squash\" are pushed via \"git subtree push\",\n> which has been reported by me at Tue, 16 Jul 2019 02:30:44 +0800, as I\n> haven't seen an obvious fix about it in the recent patches in a quick\n> glance.\n\nI'm not sure if I was aware of it before, but I'll be sure to keep it\nin mind when I'm updating my (yet to be submitted) fixes to the\n'split' algorithm.\n\nThanks for the additional test-case!\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422992","messageId":"20210426174525.3937858-1-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210423194230.1388945-1-lukeshu@lukeshu.com","subject":"[PATCH v2 00/30] subtree: clean up, improve UX","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:44:55Z","receivedAt":"2021-04-26T17:47:32Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThe diff between v1 and v2 is largely stylistic.  The only\nnon-stylistic changes are fixing the tests to use `test_must_fail`\ninstead of `!`, and re-thinking the commit about fussing with PATH.\n\nOstensibly, this patch set is about improving various aspects of `git\nsubtree`'s user interface (and it is!), but it's also mostly about\nsetting the foundation and being \"batch 1\" of a bunch more changes to\nsubtree that I'm getting queued up.  So please forgive the large\namount of churn in the leading clean-up commits, I promise that\nthere's more work coming on top of it (we've discovered lots of ways\nto break the \"subtree split\" algorithm, and come up with fixes for\nmost of them).  In the mean-time, I do think that the UX improvements\nin this patchset are already worth it themselves.\n\n - The first 11 commits improve subtree's tests, largely around the\n   code-quality of the tests, but a few of the commits do actually\n   improve what's being tested.\n\n - The middle 12 commits improve the code-quality of subtree's\n   implementation.\n\n - The final 7 commits improve various aspects of subtree's user\n   experience, from readability of the debug output, to documentation,\n   to option flag handling.\n\nThe very last commit is likely to be a little objectionable--it makes\nsome option flag parsing more strict, so there will probably be worry\nthat the change breaks existing users.  However, it's being strict\nabout arg combinations that were always invalid, the difference is\nthat now it reports that to the users and bails.  Those users were\nalready broken, they just didn't know it.  `git subtree` should tell\nthem.\n\nFinally, two questions for my continuing work:\n\n1. Would it be all right to amend CI to run the subtree tests?  And if\nso, what would be the best way to do it?  For my own testing, I just\nmade the following edit to the main Makefile, but I'm not sure it's\nthe mos appropriate approach:\n\n    --- a/Makefile\n    +++ b/Makefile\n    @@ -2836,6 +2836,7 @@\n     \n     test: all\n            $(MAKE) -C t/ all\n    +       $(MAKE) -C contrib/subtree/ test\n     \n     perf: all\n            $(MAKE) -C t/perf/ all\n\nThe first two commits are about getting that to pass.  I'd prefer to\navoid that type of bitrot in the future.\n\n2. If in that work I changed the shebang from \"#!/bin/sh\" to\n\"#!/usr/bin/env bash\" and started using Bash arrays, would that be so\nbad?  Would that be land-able?\n\nLuke Shumaker (30):\n  .gitignore: Ignore /git-subtree\n  subtree: t7900: update for having the default branch name be 'main'\n  subtree: t7900: use test-lib.sh's test_count\n  subtree: t7900: use consistent formatting\n    v2:\n     - Also normalize on `test X` instead of `[ X ]`.\n     - Also normalize on `>FILENAME` with no spaces.\n     - Fix a few if statements with `if` and `then` on the same line\n       that I missed in v1.\n  subtree: t7900: comment subtree_test_create_repo\n    v2:\n     - Also switch the few uses of vanilla test_create_repo over to\n       subtree_test_create_repo.  In v1 this was erroneously included\n       in a different commit.\n  subtree: t7900: use 'test' for string equality\n  subtree: t7900: delete some dead code\n  subtree: t7900: fix 'verify one file change per commit'\n    v2:\n     - Fix whitespace.\n  subtree: t7900: rename last_commit_message to last_commit_subject\n  subtree: t7900: add a test for the -h flag\n  subtree: t7900: add porcelain tests for 'pull' and 'push'\n    v2:\n     - Don't switch unrelated uses of vanilla test_create_repo over to\n       subtree_test_create_repo; this has been moved to happen in an\n       earlier commit.\n     - Fix whitespace.\n  subtree: don't have loose code outside of a function\n    v2:\n     - Include rationale in the the commit message.\n  subtree: more consistent error propagation\n  subtree: drop support for git < 1.7\n    v2:\n     - Include rationale in the the commit message.\n  subtree: use `git merge-base --is-ancestor`\n  subtree: use git-sh-setup's `say`\n  subtree: use more explicit variable names for cmdline args\n  subtree: use \"$*\" instead of \"$@\" as appropriate\n    v2:\n     - Improve the commit message with quoting and clearer\n       explanation.\n  subtree: Don't fuss with PATH\n    v2:\n     - This commit changed entirely.  In v1 it changed how git-subtree\n       adjusts the PATH.  In v2, it removes any fussing with the PATH,\n       and in its place adds a pre-flight sanity check that it doesn't\n       need to fuss with the PATH.\n  subtree: use \"^{commit}\" instead of \"^0\"\n  subtree: parse revs in individual cmd_ functions\n  subtree: remove duplicate check\n  subtree: add comments and sanity checks\n    v2:\n     - Expand on the the commit message.\n     - Fix capitalization in one of the comments.\n  subtree: don't let debug and progress output clash\n    v2:\n     - Reword the commit message to be clearer.\n     - Add comments to the code.\n     - Flip the `if` and `else` cases around, so that the comments\n       read better.\n  subtree: have $indent actually affect indentation\n  subtree: give the docs a once-over\n    v2:\n     - behaviour -> behavior\n  subtree: allow --squash to be used with --rejoin\n    v2:\n     - In the added tests, use `test_must_fail` instead of `!`, as\n       appropriate.\n  subtree: allow 'split' flags to be passed to 'push'\n    v2:\n     - In the added tests, use `test_must_fail` instead of `!`, as\n       appropriate.\n  subtree: push: allow specifying a local rev other than HEAD\n  subtree: be stricter about validating flags\n\n .gitignore                         |    1 +\n contrib/subtree/git-subtree.sh     |  638 ++++++++-----\n contrib/subtree/git-subtree.txt    |  184 ++--\n contrib/subtree/t/t7900-subtree.sh | 1429 ++++++++++++++++++----------\n 4 files changed, 1394 insertions(+), 858 deletions(-)\n\n-- \n2.31.1\n\nHappy hacking,\n~ Luke Shumaker\n"},{"id":"422993","messageId":"20210426174525.3937858-2-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 01/30] .gitignore: Ignore /git-subtree","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:44:56Z","receivedAt":"2021-04-26T17:47:38Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nRunning `make -C contrib/subtree/ test` creates a `git-subtree` executable\nin the root of the repo.  Add it to the .gitignore so that anyone hacking\non subtree won't have to deal with that noise.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n .gitignore | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/.gitignore b/.gitignore\nindex 3dcdb6bb5a..a203678e9e 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -162,6 +162,7 @@\n /git-stripspace\n /git-submodule\n /git-submodule--helper\n+/git-subtree\n /git-svn\n /git-switch\n /git-symbolic-ref\n-- \n2.31.1\n\n"},{"id":"422994","messageId":"20210426174525.3937858-3-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 02/30] subtree: t7900: update for having the default branch name be 'main'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:44:57Z","receivedAt":"2021-04-26T17:47:43Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nMost of the tests had been converted to support\n`GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main`, but `contrib/subtree/t/`\nhadn't.\n\nConvert it.  Most of the mentions of 'master' can just be replaced with\n'HEAD'.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 117 +++++++++++++++--------------\n 1 file changed, 59 insertions(+), 58 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 57ff4b25c1..4b982e6c2e 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -103,7 +103,7 @@ test_expect_success 'no merge from non-existent subtree' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\ttest_must_fail git subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t)\n '\n@@ -116,8 +116,8 @@ test_expect_success 'no pull from non-existent subtree' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n-\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" master\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD\n \t)'\n \n next_test\n@@ -128,7 +128,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n@@ -142,7 +142,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --me\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n \t)\n@@ -156,7 +156,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P an\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add -P \"sub dir\" -m \"Added subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n \t)\n@@ -170,7 +170,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject with squash\" --squash FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject with squash\"\n \t)\n@@ -188,13 +188,13 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n@@ -208,13 +208,13 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix and -\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject\"\n \t)\n@@ -228,13 +228,13 @@ test_expect_success 'merge new subproj history into sub dir/ with --squash and -\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject using squash\" --squash FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject using squash\"\n \t)\n@@ -248,7 +248,7 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\t# this shouldn not actually do anything, since FETCH_HEAD\n \t\t# is already a parent\n@@ -265,13 +265,13 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende\n \ttest_create_commit \"$test_count/subproj\" sub1 &&\n \t(\n \t\tcd \"$test_count\" &&\n-\t\tgit fetch ./subproj master &&\n+\t\tgit fetch ./subproj HEAD &&\n \t\tgit subtree add --prefix=subdir/ FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$test_count/subproj\" sub2 &&\n \t(\n \t\tcd \"$test_count\" &&\n-\t\tgit fetch ./subproj master &&\n+\t\tgit fetch ./subproj HEAD &&\n \t\tgit subtree merge --prefix=subdir/ FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n@@ -289,7 +289,7 @@ test_expect_success 'split requires option --prefix' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\techo \"You must provide the --prefix option.\" > expected &&\n \t\ttest_must_fail git subtree split > actual 2>&1 &&\n@@ -309,7 +309,7 @@ test_expect_success 'split requires path given by option --prefix must exist' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" > expected &&\n \t\ttest_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 &&\n@@ -329,7 +329,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -338,7 +338,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin &&\n@@ -370,7 +370,7 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -379,7 +379,7 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Split & rejoin\"\n@@ -394,7 +394,7 @@ test_expect_success 'split \"sub dir\"/ with --branch' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -403,7 +403,7 @@ test_expect_success 'split \"sub dir\"/ with --branch' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n@@ -419,7 +419,7 @@ test_expect_success 'check hash of split' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -428,7 +428,7 @@ test_expect_success 'check hash of split' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n@@ -451,7 +451,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch subproj-br FETCH_HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n@@ -461,7 +461,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n@@ -478,7 +478,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n \t(\n \t\tcd \"$subtree_test_count\" &&\n \t\tgit branch init HEAD &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -487,7 +487,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\ttest_must_fail git subtree split --prefix=\"sub dir\" --branch init\n \t)\n@@ -505,7 +505,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the sub\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -514,7 +514,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the sub\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -555,7 +555,7 @@ test_expect_success 'make sure the subproj *only* contains commits that affect t\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -564,7 +564,7 @@ test_expect_success 'make sure the subproj *only* contains commits that affect t\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -606,7 +606,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -615,7 +615,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -643,7 +643,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai\n \t) &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" master &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\ttest_write_lines main1 main2 >chkm &&\n \t\ttest_write_lines main-sub1 main-sub2 main-sub3 main-sub4 >chkms &&\n@@ -666,7 +666,7 @@ test_expect_success 'make sure each filename changed exactly once in the entire\n \t(\n \t\tcd \"$subtree_test_count\" &&\n \t\tgit config log.date relative &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -675,7 +675,7 @@ test_expect_success 'make sure each filename changed exactly once in the entire\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -703,7 +703,7 @@ test_expect_success 'make sure each filename changed exactly once in the entire\n \t) &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" master &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\ttest_write_lines main1 main2 >chkm &&\n \t\ttest_write_lines sub1 sub2 sub3 sub4 >chks &&\n@@ -731,7 +731,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -740,7 +740,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -768,7 +768,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'\n \t) &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" master &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \t\tcheck_equal \"$(git log --pretty=format:\"%s\" HEAD^2 | grep -i split)\" \"\"\n \t)\n '\n@@ -781,7 +781,7 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -790,7 +790,7 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -818,7 +818,7 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n \t) &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" master &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\t# They are meaningless to subproj since one side of the merge refers to the mainline\n \t\tcheck_equal \"$(git log --pretty=format:\"%s%n%b\" HEAD^2 | grep \"git-subtree.*:\")\" \"\"\n@@ -837,13 +837,13 @@ test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch subproj-ref FETCH_HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n@@ -853,7 +853,7 @@ test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n \t\tgit subtree split --prefix=\"sub dir\" --branch subproj-br &&\n \n \t\t# at this point, the new commit parent should be subproj-ref, if it is\n-\t\t# not, something went wrong (the \"newparent\" of \"master~\" commit should\n+\t\t# not, something went wrong (the \"newparent\" of \"HEAD~\" commit should\n \t\t# have been sub2, but it was not, because its cache was not set to\n \t\t# itself)\n \t\tcheck_equal \"$(git log --pretty=format:%P -1 subproj-br)\" \"$(git rev-parse subproj-ref)\"\n@@ -868,13 +868,13 @@ test_expect_success 'split a new subtree without --onto option' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -903,14 +903,14 @@ test_expect_success 'verify one file change per commit' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch sub1 FETCH_HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" sub1\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -947,7 +947,7 @@ test_expect_success 'push split to subproj' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -958,7 +958,7 @@ test_expect_success 'push split to subproj' '\n \t\tcd $subtree_test_count/\"sub proj\" &&\n                 git branch sub-branch-1 &&\n                 cd .. &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n@@ -994,6 +994,7 @@ test_expect_success 'push split to subproj' '\n next_test\n test_expect_success 'subtree descendant check' '\n \tsubtree_test_create_repo \"$subtree_test_count\" &&\n+\tdefaultBranch=$(sed \"s,ref: refs/heads/,,\" \"$subtree_test_count/.git/HEAD\") &&\n \ttest_create_commit \"$subtree_test_count\" folder_subtree/a &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n@@ -1010,7 +1011,7 @@ test_expect_success 'subtree descendant check' '\n \t(\n \t\tcd \"$subtree_test_count\" &&\n \t\tgit cherry-pick $cherry &&\n-\t\tgit checkout master &&\n+\t\tgit checkout $defaultBranch &&\n \t\tgit merge -m \"merge should be kept on subtree\" branch &&\n \t\tgit branch no_subtree_work_branch\n \t) &&\n@@ -1022,10 +1023,10 @@ test_expect_success 'subtree descendant check' '\n \ttest_create_commit \"$subtree_test_count\" not_a_subtree_change &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit checkout master &&\n+\t\tgit checkout $defaultBranch &&\n \t\tgit merge -m \"merge should be skipped on subtree\" no_subtree_work_branch &&\n \n-\t\tgit subtree split --prefix folder_subtree/ --branch subtree_tip master &&\n+\t\tgit subtree split --prefix folder_subtree/ --branch subtree_tip $defaultBranch &&\n \t\tgit subtree split --prefix folder_subtree/ --branch subtree_branch branch &&\n \t\tcheck_equal $(git rev-list --count subtree_tip..subtree_branch) 0\n \t)\n-- \n2.31.1\n\n"},{"id":"422995","messageId":"20210426174525.3937858-5-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 04/30] subtree: t7900: use consistent formatting","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:44:59Z","receivedAt":"2021-04-26T17:47:44Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThe formatting in t7900-subtree.sh isn't even consistent throughout the\nfile.  Fix that; make it consistent throughout the file.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Also normalize on `test X` instead of `[ X ]`.\n - Also normalize on `>FILENAME` with no spaces.\n - Fix a few if statements with `if` and `then` on the same line\n   that I missed in v1.\n\n contrib/subtree/t/t7900-subtree.sh | 64 +++++++++++++++---------------\n 1 file changed, 31 insertions(+), 33 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex a6351d9195..5e1390c287 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -11,11 +11,9 @@ and split subcommands of git subtree.\n \n TEST_DIRECTORY=$(pwd)/../../../t\n export TEST_DIRECTORY\n+. \"$TEST_DIRECTORY\"/test-lib.sh\n \n-. ../../../t/test-lib.sh\n-\n-subtree_test_create_repo()\n-{\n+subtree_test_create_repo () {\n \ttest_create_repo \"$1\" &&\n \t(\n \t\tcd \"$1\" &&\n@@ -23,26 +21,24 @@ subtree_test_create_repo()\n \t)\n }\n \n-create()\n-{\n+create () {\n \techo \"$1\" >\"$1\" &&\n \tgit add \"$1\"\n }\n \n-check_equal()\n-{\n+check_equal () {\n \ttest_debug 'echo'\n \ttest_debug \"echo \\\"check a:\\\" \\\"{$1}\\\"\"\n \ttest_debug \"echo \\\"      b:\\\" \\\"{$2}\\\"\"\n-\tif [ \"$1\" = \"$2\" ]; then\n+\tif test \"$1\" = \"$2\"\n+\tthen\n \t\treturn 0\n \telse\n \t\treturn 1\n \tfi\n }\n \n-undo()\n-{\n+undo () {\n \tgit reset --hard HEAD~\n }\n \n@@ -50,15 +46,17 @@ undo()\n # The original set of commits changed only one file each.\n # A multi-file change would imply that we pruned commits\n # too aggressively.\n-join_commits()\n-{\n+join_commits () {\n \tcommit=\n \tall=\n \twhile read x y; do\n-\t\tif [ -z \"$x\" ]; then\n+\t\tif test -z \"$x\"\n+\t\tthen\n \t\t\tcontinue\n-\t\telif [ \"$x\" = \"commit:\" ]; then\n-\t\t\tif [ -n \"$commit\" ]; then\n+\t\telif test \"$x\" = \"commit:\"\n+\t\tthen\n+\t\t\tif test -n \"$commit\"\n+\t\t\tthen\n \t\t\t\techo \"$commit $all\"\n \t\t\t\tall=\n \t\t\tfi\n@@ -70,7 +68,7 @@ join_commits()\n \techo \"$commit $all\"\n }\n \n-test_create_commit() (\n+test_create_commit () (\n \trepo=$1 &&\n \tcommit=$2 &&\n \tcd \"$repo\" &&\n@@ -81,8 +79,7 @@ test_create_commit() (\n \tgit commit -m \"$commit\" || error \"Could not commit\"\n )\n \n-last_commit_message()\n-{\n+last_commit_message () {\n \tgit log --pretty=format:%s -1\n }\n \n@@ -111,7 +108,8 @@ test_expect_success 'no pull from non-existent subtree' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD\n-\t)'\n+\t)\n+'\n \n test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \tsubtree_test_create_repo \"$test_count\" &&\n@@ -274,8 +272,8 @@ test_expect_success 'split requires option --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\techo \"You must provide the --prefix option.\" > expected &&\n-\t\ttest_must_fail git subtree split > actual 2>&1 &&\n+\t\techo \"You must provide the --prefix option.\" >expected &&\n+\t\ttest_must_fail git subtree split >actual 2>&1 &&\n \t\ttest_debug \"printf '\"expected: \"'\" &&\n \t\ttest_debug \"cat expected\" &&\n \t\ttest_debug \"printf '\"actual: \"'\" &&\n@@ -293,8 +291,8 @@ test_expect_success 'split requires path given by option --prefix must exist' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" > expected &&\n-\t\ttest_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 &&\n+\t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" >expected &&\n+\t\ttest_must_fail git subtree split --prefix=non-existent-directory >actual 2>&1 &&\n \t\ttest_debug \"printf '\"expected: \"'\" &&\n \t\ttest_debug \"cat expected\" &&\n \t\ttest_debug \"printf '\"actual: \"'\" &&\n@@ -325,7 +323,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n- '\n+'\n \n test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \tsubtree_test_create_repo \"$test_count\" &&\n@@ -340,7 +338,7 @@ test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \t\tgit subtree split --prefix=\"sub dir\" --rejoin &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n- '\n+'\n \n test_expect_success 'split sub dir/ with --rejoin and --message' '\n \tsubtree_test_create_repo \"$test_count\" &&\n@@ -921,18 +919,18 @@ test_expect_success 'push split to subproj' '\n \ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd $test_count/\"sub proj\" &&\n-                git branch sub-branch-1 &&\n-                cd .. &&\n+\t\tgit branch sub-branch-1 &&\n+\t\tcd .. &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n-        (\n+\t(\n \t\tcd \"$test_count\" &&\n-\t        git subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n-                cd ./\"sub proj\" &&\n-                git checkout sub-branch-1 &&\n-         \tcheck_equal \"$(last_commit_message)\" \"sub dir/main-sub3\"\n+\t\tgit subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n+\t\tcd ./\"sub proj\" &&\n+\t\tgit checkout sub-branch-1 &&\n+\t\tcheck_equal \"$(last_commit_message)\" \"sub dir/main-sub3\"\n \t)\n '\n \n-- \n2.31.1\n\n"},{"id":"422996","messageId":"20210426174525.3937858-4-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 03/30] subtree: t7900: use test-lib.sh's test_count","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:44:58Z","receivedAt":"2021-04-26T17:47:47Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nUse test-lib.sh's `test_count`, instead instead of having\nt7900-subtree.sh do its own book-keeping with `subtree_test_count` that\nhas to be explicitly incremented by calling `next_test`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 636 ++++++++++++++---------------\n 1 file changed, 300 insertions(+), 336 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 4b982e6c2e..a6351d9195 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -86,90 +86,79 @@ last_commit_message()\n \tgit log --pretty=format:%s -1\n }\n \n-subtree_test_count=0\n-next_test() {\n-\tsubtree_test_count=$(($subtree_test_count+1))\n-}\n-\n #\n # Tests for 'git subtree add'\n #\n \n-next_test\n test_expect_success 'no merge from non-existent subtree' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\ttest_must_fail git subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t)\n '\n \n-next_test\n test_expect_success 'no pull from non-existent subtree' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD\n \t)'\n \n-next_test\n test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n-next_test\n test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n \t)\n '\n \n-next_test\n test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P and --message as -m' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add -P \"sub dir\" -m \"Added subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n \t)\n '\n \n-next_test\n test_expect_success 'add subproj as subtree into sub dir/ with --squash and --prefix and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject with squash\" --squash FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject with squash\"\n@@ -180,74 +169,70 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n # Tests for 'git subtree merge'\n #\n \n-next_test\n test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n-next_test\n test_expect_success 'merge new subproj history into sub dir/ with --prefix and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject\"\n \t)\n '\n \n-next_test\n test_expect_success 'merge new subproj history into sub dir/ with --squash and --prefix and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject using squash\" --squash FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject using squash\"\n \t)\n '\n \n-next_test\n test_expect_success 'merge the added subproj again, should do nothing' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\t# this shouldn not actually do anything, since FETCH_HEAD\n@@ -257,7 +242,6 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n \t)\n '\n \n-next_test\n test_expect_success 'merge new subproj history into subdir/ with a slash appended to the argument of --prefix' '\n \ttest_create_repo \"$test_count\" &&\n \ttest_create_repo \"$test_count/subproj\" &&\n@@ -281,14 +265,13 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende\n # Tests for 'git subtree split'\n #\n \n-next_test\n test_expect_success 'split requires option --prefix' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\techo \"You must provide the --prefix option.\" > expected &&\n@@ -301,14 +284,13 @@ test_expect_success 'split requires option --prefix' '\n \t)\n '\n \n-next_test\n test_expect_success 'split requires path given by option --prefix must exist' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" > expected &&\n@@ -321,23 +303,22 @@ test_expect_success 'split requires path given by option --prefix must exist' '\n \t)\n '\n \n-next_test\n test_expect_success 'split sub dir/ with --rejoin' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n@@ -346,12 +327,11 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \t)\n  '\n \n-next_test\n test_expect_success 'split sub dir/ with --rejoin from scratch' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tmkdir \"sub dir\" &&\n \t\techo file >\"sub dir\"/file &&\n \t\tgit add \"sub dir/file\" &&\n@@ -362,23 +342,22 @@ test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \t)\n  '\n \n-next_test\n test_expect_success 'split sub dir/ with --rejoin and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin &&\n@@ -386,23 +365,22 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \t)\n '\n \n-next_test\n test_expect_success 'split \"sub dir\"/ with --branch' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n@@ -411,23 +389,22 @@ test_expect_success 'split \"sub dir\"/ with --branch' '\n \t)\n '\n \n-next_test\n test_expect_success 'check hash of split' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n@@ -443,24 +420,23 @@ test_expect_success 'check hash of split' '\n \t)\n '\n \n-next_test\n test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch subproj-br FETCH_HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n@@ -469,24 +445,23 @@ test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n \t)\n '\n \n-next_test\n test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit branch init HEAD &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\ttest_must_fail git subtree split --prefix=\"sub dir\" --branch init\n@@ -497,46 +472,45 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n # Validity checking\n #\n \n-next_test\n test_expect_success 'make sure exactly the right set of files ends up in the subproj' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD &&\n \n@@ -547,46 +521,45 @@ test_expect_success 'make sure exactly the right set of files ends up in the sub\n \t)\n '\n \n-next_test\n test_expect_success 'make sure the subproj *only* contains commits that affect the \"sub dir\"' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD &&\n \n@@ -598,51 +571,50 @@ test_expect_success 'make sure the subproj *only* contains commits that affect t\n \t)\n '\n \n-next_test\n test_expect_success 'make sure exactly the right set of files ends up in the mainline' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\ttest_write_lines main1 main2 >chkm &&\n@@ -657,52 +629,51 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai\n \t)\n '\n \n-next_test\n test_expect_success 'make sure each filename changed exactly once in the entire history' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit config log.date relative &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\ttest_write_lines main1 main2 >chkm &&\n@@ -723,101 +694,99 @@ test_expect_success 'make sure each filename changed exactly once in the entire\n \t)\n '\n \n-next_test\n test_expect_success 'make sure the --rejoin commits never make it into subproj' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \t\tcheck_equal \"$(git log --pretty=format:\"%s\" HEAD^2 | grep -i split)\" \"\"\n \t)\n '\n \n-next_test\n test_expect_success 'make sure no \"git subtree\" tagged commits make it into subproj' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\t git merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\t# They are meaningless to subproj since one side of the merge refers to the mainline\n@@ -829,27 +798,26 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n # A new set of tests\n #\n \n-next_test\n test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch subproj-ref FETCH_HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --branch subproj-br &&\n \n \t\t# at this point, the new commit parent should be subproj-ref, if it is\n@@ -860,32 +828,31 @@ test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n \t)\n '\n \n-next_test\n test_expect_success 'split a new subtree without --onto option' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --branch subproj-br\n \t) &&\n-\tmkdir \"$subtree_test_count\"/\"sub dir2\" &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir2\"/main-sub2 &&\n+\tmkdir \"$test_count\"/\"sub dir2\" &&\n+\ttest_create_commit \"$test_count\" \"sub dir2\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \n \t\t# also test that we still can split out an entirely new subtree\n \t\t# if the parent of the first commit in the tree is not empty,\n@@ -895,33 +862,32 @@ test_expect_success 'split a new subtree without --onto option' '\n \t)\n '\n \n-next_test\n test_expect_success 'verify one file change per commit' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch sub1 FETCH_HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" sub1\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --branch subproj-br\n \t) &&\n-\tmkdir \"$subtree_test_count\"/\"sub dir2\" &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir2\"/main-sub2 &&\n+\tmkdir \"$test_count\"/\"sub dir2\" &&\n+\ttest_create_commit \"$test_count\" \"sub dir2\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir2\" --branch subproj2-br &&\n \n \t\tx= &&\n@@ -939,31 +905,30 @@ test_expect_success 'verify one file change per commit' '\n \t)\n '\n \n-next_test\n test_expect_success 'push split to subproj' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd $subtree_test_count/\"sub proj\" &&\n+\t\tcd $test_count/\"sub proj\" &&\n                 git branch sub-branch-1 &&\n                 cd .. &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n         (\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t        git subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n                 cd ./\"sub proj\" &&\n                 git checkout sub-branch-1 &&\n@@ -991,38 +956,37 @@ test_expect_success 'push split to subproj' '\n #   set of commits.\n #\n \n-next_test\n test_expect_success 'subtree descendant check' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tdefaultBranch=$(sed \"s,ref: refs/heads/,,\" \"$subtree_test_count/.git/HEAD\") &&\n-\ttest_create_commit \"$subtree_test_count\" folder_subtree/a &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tdefaultBranch=$(sed \"s,ref: refs/heads/,,\" \"$test_count/.git/HEAD\") &&\n+\ttest_create_commit \"$test_count\" folder_subtree/a &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit branch branch\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" folder_subtree/0 &&\n-\ttest_create_commit \"$subtree_test_count\" folder_subtree/b &&\n-\tcherry=$(cd \"$subtree_test_count\"; git rev-parse HEAD) &&\n+\ttest_create_commit \"$test_count\" folder_subtree/0 &&\n+\ttest_create_commit \"$test_count\" folder_subtree/b &&\n+\tcherry=$(cd \"$test_count\"; git rev-parse HEAD) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit checkout branch\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" commit_on_branch &&\n+\ttest_create_commit \"$test_count\" commit_on_branch &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit cherry-pick $cherry &&\n \t\tgit checkout $defaultBranch &&\n \t\tgit merge -m \"merge should be kept on subtree\" branch &&\n \t\tgit branch no_subtree_work_branch\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" folder_subtree/d &&\n+\ttest_create_commit \"$test_count\" folder_subtree/d &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit checkout no_subtree_work_branch\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" not_a_subtree_change &&\n+\ttest_create_commit \"$test_count\" not_a_subtree_change &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit checkout $defaultBranch &&\n \t\tgit merge -m \"merge should be skipped on subtree\" no_subtree_work_branch &&\n \n-- \n2.31.1\n\n"},{"id":"422997","messageId":"20210426174525.3937858-6-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 05/30] subtree: t7900: comment subtree_test_create_repo","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:00Z","receivedAt":"2021-04-26T17:47:49Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nIt's unclear what the purpose of t7900-subtree.sh's\n`subtree_test_create_repo` helper function is.  It wraps test-lib.sh's,\n`test_create_repo` but follows that up by setting log.date=relative.  Why\ndoes it set log.date=relative?\n\nMy first guess was that at one point the tests required that, but no\nlonger do, and that the function is now vestigial.  I even wrote a patch\nto get rid of it and was moments away from `git send-email`ing it.\n\nHowever, by chance when looking for something else in the history, I\ndiscovered the true reason, from e7aac44ed2 (contrib/subtree: ignore\nlog.date configuration, 2015-07-21).  It's testing that setting\nlog.date=relative doesn't break `git subtree`, as at one point in the past\nthat did break `git subtree`.\n\nSo, add a comment about this, to avoid future such confusion.\n\nAnd while at it, go ahead and (1) touch up the function to avoid a\npointless subshell and (2) update the one test that didn't use it.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Also switch the few uses of vanilla test_create_repo over to\n   subtree_test_create_repo.  In v1 this was erroneously included\n   in a different commit.\n\n contrib/subtree/t/t7900-subtree.sh | 14 ++++++++------\n 1 file changed, 8 insertions(+), 6 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 5e1390c287..cac08af7f7 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -13,12 +13,14 @@ TEST_DIRECTORY=$(pwd)/../../../t\n export TEST_DIRECTORY\n . \"$TEST_DIRECTORY\"/test-lib.sh\n \n+# Use our own wrapper around test-lib.sh's test_create_repo, in order\n+# to set log.date=relative.  `git subtree` parses the output of `git\n+# log`, and so it must be careful to not be affected by settings that\n+# change the `git log` output.  We test this by setting\n+# log.date=relative for every repo in the tests.\n subtree_test_create_repo () {\n \ttest_create_repo \"$1\" &&\n-\t(\n-\t\tcd \"$1\" &&\n-\t\tgit config log.date relative\n-\t)\n+\tgit -C \"$1\" config log.date relative\n }\n \n create () {\n@@ -241,8 +243,8 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n '\n \n test_expect_success 'merge new subproj history into subdir/ with a slash appended to the argument of --prefix' '\n-\ttest_create_repo \"$test_count\" &&\n-\ttest_create_repo \"$test_count/subproj\" &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/subproj\" &&\n \ttest_create_commit \"$test_count\" main1 &&\n \ttest_create_commit \"$test_count/subproj\" sub1 &&\n \t(\n-- \n2.31.1\n\n"},{"id":"422998","messageId":"20210426174525.3937858-7-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 06/30] subtree: t7900: use 'test' for string equality","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:01Z","receivedAt":"2021-04-26T17:47:50Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nt7900-subtree.sh defines its own `check_equal A B` function, instead of\njust using `test A = B` like all of the other tests.  Don't be special,\nget rid of `check_equal` in favor of `test`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 60 ++++++++++++------------------\n 1 file changed, 24 insertions(+), 36 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex cac08af7f7..3aa5545e5e 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -28,18 +28,6 @@ create () {\n \tgit add \"$1\"\n }\n \n-check_equal () {\n-\ttest_debug 'echo'\n-\ttest_debug \"echo \\\"check a:\\\" \\\"{$1}\\\"\"\n-\ttest_debug \"echo \\\"      b:\\\" \\\"{$2}\\\"\"\n-\tif test \"$1\" = \"$2\"\n-\tthen\n-\t\treturn 0\n-\telse\n-\t\treturn 1\n-\tfi\n-}\n-\n undo () {\n \tgit reset --hard HEAD~\n }\n@@ -122,7 +110,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -135,7 +123,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --me\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n+\t\ttest \"$(last_commit_message)\" = \"Added subproject\"\n \t)\n '\n \n@@ -148,7 +136,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P an\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add -P \"sub dir\" -m \"Added subproject\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n+\t\ttest \"$(last_commit_message)\" = \"Added subproject\"\n \t)\n '\n \n@@ -161,7 +149,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject with squash\" --squash FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Added subproject with squash\"\n+\t\ttest \"$(last_commit_message)\" = \"Added subproject with squash\"\n \t)\n '\n \n@@ -184,7 +172,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -203,7 +191,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix and -\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject\"\n+\t\ttest \"$(last_commit_message)\" = \"Merged changes from subproject\"\n \t)\n '\n \n@@ -222,7 +210,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --squash and -\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject using squash\" --squash FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject using squash\"\n+\t\ttest \"$(last_commit_message)\" = \"Merged changes from subproject using squash\"\n \t)\n '\n \n@@ -238,7 +226,7 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n \t\t# this shouldn not actually do anything, since FETCH_HEAD\n \t\t# is already a parent\n \t\tresult=$(git merge -s ours -m \"merge -s -ours\" FETCH_HEAD) &&\n-\t\tcheck_equal \"${result}\" \"Already up to date.\"\n+\t\ttest \"${result}\" = \"Already up to date.\"\n \t)\n '\n \n@@ -257,7 +245,7 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./subproj HEAD &&\n \t\tgit subtree merge --prefix=subdir/ FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -323,7 +311,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n '\n \n@@ -338,7 +326,7 @@ test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \t\tgit commit -m\"sub dir file\" &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --rejoin) &&\n \t\tgit subtree split --prefix=\"sub dir\" --rejoin &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n '\n \n@@ -361,7 +349,7 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Split & rejoin\"\n+\t\ttest \"$(last_commit_message)\" = \"Split & rejoin\"\n \t)\n '\n \n@@ -385,7 +373,7 @@ test_expect_success 'split \"sub dir\"/ with --branch' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n-\t\tcheck_equal \"$(git rev-parse subproj-br)\" \"$split_hash\"\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\"\n \t)\n '\n \n@@ -409,13 +397,13 @@ test_expect_success 'check hash of split' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n-\t\tcheck_equal \"$(git rev-parse subproj-br)\" \"$split_hash\" &&\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\" &&\n \t\t# Check hash of split\n \t\tnew_hash=$(git rev-parse subproj-br^2) &&\n \t\t(\n \t\t\tcd ./\"sub proj\" &&\n \t\t\tsubdir_hash=$(git rev-parse HEAD) &&\n-\t\t\tcheck_equal ''\"$new_hash\"'' \"$subdir_hash\"\n+\t\t\ttest ''\"$new_hash\"'' = \"$subdir_hash\"\n \t\t)\n \t)\n '\n@@ -441,7 +429,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n-\t\tcheck_equal \"$(git rev-parse subproj-br)\" \"$split_hash\"\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\"\n \t)\n '\n \n@@ -739,7 +727,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'\n \t(\n \t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n-\t\tcheck_equal \"$(git log --pretty=format:\"%s\" HEAD^2 | grep -i split)\" \"\"\n+\t\ttest \"$(git log --pretty=format:\"%s\" HEAD^2 | grep -i split)\" = \"\"\n \t)\n '\n \n@@ -790,7 +778,7 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\t# They are meaningless to subproj since one side of the merge refers to the mainline\n-\t\tcheck_equal \"$(git log --pretty=format:\"%s%n%b\" HEAD^2 | grep \"git-subtree.*:\")\" \"\"\n+\t\ttest \"$(git log --pretty=format:\"%s%n%b\" HEAD^2 | grep \"git-subtree.*:\")\" = \"\"\n \t)\n '\n \n@@ -824,7 +812,7 @@ test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n \t\t# not, something went wrong (the \"newparent\" of \"HEAD~\" commit should\n \t\t# have been sub2, but it was not, because its cache was not set to\n \t\t# itself)\n-\t\tcheck_equal \"$(git log --pretty=format:%P -1 subproj-br)\" \"$(git rev-parse subproj-ref)\"\n+\t\ttest \"$(git log --pretty=format:%P -1 subproj-br)\" = \"$(git rev-parse subproj-ref)\"\n \t)\n '\n \n@@ -858,7 +846,7 @@ test_expect_success 'split a new subtree without --onto option' '\n \t\t# if the parent of the first commit in the tree is not empty,\n \t\t# then the new subtree has accidentally been attached to something\n \t\tgit subtree split --prefix=\"sub dir2\" --branch subproj2-br &&\n-\t\tcheck_equal \"$(git log --pretty=format:%P -1 subproj2-br)\" \"\"\n+\t\ttest \"$(git log --pretty=format:%P -1 subproj2-br)\" = \"\"\n \t)\n '\n \n@@ -897,10 +885,10 @@ test_expect_success 'verify one file change per commit' '\n \t\t\t\ttest_debug \"echo Verifying commit $commit\"\n \t\t\t\ttest_debug \"echo a: $a\"\n \t\t\t\ttest_debug \"echo b: $b\"\n-\t\t\t\tcheck_equal \"$b\" \"\"\n+\t\t\t\ttest \"$b\" = \"\"\n \t\t\t\tx=1\n \t\t\tdone\n-\t\t\tcheck_equal \"$x\" 1\n+\t\t\ttest \"$x\" = 1\n \t\t)\n \t)\n '\n@@ -932,7 +920,7 @@ test_expect_success 'push split to subproj' '\n \t\tgit subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n \t\tcd ./\"sub proj\" &&\n \t\tgit checkout sub-branch-1 &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"sub dir/main-sub3\"\n+\t\ttest \"$(last_commit_message)\" = \"sub dir/main-sub3\"\n \t)\n '\n \n@@ -992,7 +980,7 @@ test_expect_success 'subtree descendant check' '\n \n \t\tgit subtree split --prefix folder_subtree/ --branch subtree_tip $defaultBranch &&\n \t\tgit subtree split --prefix folder_subtree/ --branch subtree_branch branch &&\n-\t\tcheck_equal $(git rev-list --count subtree_tip..subtree_branch) 0\n+\t\ttest $(git rev-list --count subtree_tip..subtree_branch) = 0\n \t)\n '\n \n-- \n2.31.1\n\n"},{"id":"422999","messageId":"20210426174525.3937858-8-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 07/30] subtree: t7900: delete some dead code","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:02Z","receivedAt":"2021-04-26T17:47:52Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 12 +-----------\n 1 file changed, 1 insertion(+), 11 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 3aa5545e5e..c8bd58cedb 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -10,7 +10,6 @@ and split subcommands of git subtree.\n '\n \n TEST_DIRECTORY=$(pwd)/../../../t\n-export TEST_DIRECTORY\n . \"$TEST_DIRECTORY\"/test-lib.sh\n \n # Use our own wrapper around test-lib.sh's test_create_repo, in order\n@@ -23,15 +22,6 @@ subtree_test_create_repo () {\n \tgit -C \"$1\" config log.date relative\n }\n \n-create () {\n-\techo \"$1\" >\"$1\" &&\n-\tgit add \"$1\"\n-}\n-\n-undo () {\n-\tgit reset --hard HEAD~\n-}\n-\n # Make sure no patch changes more than one file.\n # The original set of commits changed only one file each.\n # A multi-file change would imply that we pruned commits\n@@ -403,7 +393,7 @@ test_expect_success 'check hash of split' '\n \t\t(\n \t\t\tcd ./\"sub proj\" &&\n \t\t\tsubdir_hash=$(git rev-parse HEAD) &&\n-\t\t\ttest ''\"$new_hash\"'' = \"$subdir_hash\"\n+\t\t\ttest \"$new_hash\" = \"$subdir_hash\"\n \t\t)\n \t)\n '\n-- \n2.31.1\n\n"},{"id":"423000","messageId":"20210426174525.3937858-9-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 08/30] subtree: t7900: fix 'verify one file change per commit'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:03Z","receivedAt":"2021-04-26T17:47:54Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nAs far as I can tell, this test isn't actually testing anything, because\nsomeone forgot to tack on `--name-only` to `git log`.  This seems to\nhave been the case since the test was first written, back in fa16ab36ad\n(\"test.sh: make sure no commit changes more than one file at a time.\",\n2009-04-26), unless `git log` used to do that by default and didn't need\nthe flag back then?\n\nConvincing myself that it's not actually testing anything was tricky,\nthe code is a little hard to reason about.  It can be made a lot simpler\nif instead of trying to parse all of the info from a single `git log`,\nwe're OK calling `git log` from inside of a loop.  And it's my opinion\nthat tests are not the place for clever optimized code.\n\nSo, fix and simplify the test, so that it's actually testing something\nand is simpler to reason about.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Fix whitespace.\n\n contrib/subtree/t/t7900-subtree.sh | 44 ++++--------------------------\n 1 file changed, 6 insertions(+), 38 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex c8bd58cedb..1c717fcb96 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -22,32 +22,6 @@ subtree_test_create_repo () {\n \tgit -C \"$1\" config log.date relative\n }\n \n-# Make sure no patch changes more than one file.\n-# The original set of commits changed only one file each.\n-# A multi-file change would imply that we pruned commits\n-# too aggressively.\n-join_commits () {\n-\tcommit=\n-\tall=\n-\twhile read x y; do\n-\t\tif test -z \"$x\"\n-\t\tthen\n-\t\t\tcontinue\n-\t\telif test \"$x\" = \"commit:\"\n-\t\tthen\n-\t\t\tif test -n \"$commit\"\n-\t\t\tthen\n-\t\t\t\techo \"$commit $all\"\n-\t\t\t\tall=\n-\t\t\tfi\n-\t\t\tcommit=\"$y\"\n-\t\telse\n-\t\t\tall=\"$all $y\"\n-\t\tfi\n-\tdone\n-\techo \"$commit $all\"\n-}\n-\n test_create_commit () (\n \trepo=$1 &&\n \tcommit=$2 &&\n@@ -868,18 +842,12 @@ test_expect_success 'verify one file change per commit' '\n \t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir2\" --branch subproj2-br &&\n \n-\t\tx= &&\n-\t\tgit log --pretty=format:\"commit: %H\" | join_commits |\n-\t\t(\n-\t\t\twhile read commit a b; do\n-\t\t\t\ttest_debug \"echo Verifying commit $commit\"\n-\t\t\t\ttest_debug \"echo a: $a\"\n-\t\t\t\ttest_debug \"echo b: $b\"\n-\t\t\t\ttest \"$b\" = \"\"\n-\t\t\t\tx=1\n-\t\t\tdone\n-\t\t\ttest \"$x\" = 1\n-\t\t)\n+\t\tgit log --format=\"%H\" >commit-list &&\n+\t\twhile read commit\n+\t\tdo\n+\t\t\tgit log -n1 --format=\"\" --name-only \"$commit\" >file-list &&\n+\t\t\ttest_line_count -le 1 file-list || return 1\n+\t\tdone <commit-list\n \t)\n '\n \n-- \n2.31.1\n\n"},{"id":"423001","messageId":"20210426174525.3937858-10-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 09/30] subtree: t7900: rename last_commit_message to last_commit_subject","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:04Z","receivedAt":"2021-04-26T17:47:58Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nt7900-subtree.sh defines a helper function named last_commit_message.\nHowever, it only returns the subject line of the commit message, not the\nentire commit message.  So rename it, to make the name less confusing.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 26 +++++++++++++-------------\n 1 file changed, 13 insertions(+), 13 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 1c717fcb96..5c2510f1f5 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -33,7 +33,7 @@ test_create_commit () (\n \tgit commit -m \"$commit\" || error \"Could not commit\"\n )\n \n-last_commit_message () {\n+last_commit_subject () {\n \tgit log --pretty=format:%s -1\n }\n \n@@ -74,7 +74,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -87,7 +87,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --me\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Added subproject\"\n+\t\ttest \"$(last_commit_subject)\" = \"Added subproject\"\n \t)\n '\n \n@@ -100,7 +100,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P an\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add -P \"sub dir\" -m \"Added subproject\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Added subproject\"\n+\t\ttest \"$(last_commit_subject)\" = \"Added subproject\"\n \t)\n '\n \n@@ -113,7 +113,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject with squash\" --squash FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Added subproject with squash\"\n+\t\ttest \"$(last_commit_subject)\" = \"Added subproject with squash\"\n \t)\n '\n \n@@ -136,7 +136,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -155,7 +155,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix and -\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Merged changes from subproject\"\n+\t\ttest \"$(last_commit_subject)\" = \"Merged changes from subproject\"\n \t)\n '\n \n@@ -174,7 +174,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --squash and -\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject using squash\" --squash FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Merged changes from subproject using squash\"\n+\t\ttest \"$(last_commit_subject)\" = \"Merged changes from subproject using squash\"\n \t)\n '\n \n@@ -209,7 +209,7 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./subproj HEAD &&\n \t\tgit subtree merge --prefix=subdir/ FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -275,7 +275,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin &&\n-\t\ttest \"$(last_commit_message)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n '\n \n@@ -290,7 +290,7 @@ test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \t\tgit commit -m\"sub dir file\" &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --rejoin) &&\n \t\tgit subtree split --prefix=\"sub dir\" --rejoin &&\n-\t\ttest \"$(last_commit_message)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n '\n \n@@ -313,7 +313,7 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin &&\n-\t\ttest \"$(last_commit_message)\" = \"Split & rejoin\"\n+\t\ttest \"$(last_commit_subject)\" = \"Split & rejoin\"\n \t)\n '\n \n@@ -878,7 +878,7 @@ test_expect_success 'push split to subproj' '\n \t\tgit subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n \t\tcd ./\"sub proj\" &&\n \t\tgit checkout sub-branch-1 &&\n-\t\ttest \"$(last_commit_message)\" = \"sub dir/main-sub3\"\n+\t\ttest \"$(last_commit_subject)\" = \"sub dir/main-sub3\"\n \t)\n '\n \n-- \n2.31.1\n\n"},{"id":"423002","messageId":"20210426174525.3937858-11-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 10/30] subtree: t7900: add a test for the -h flag","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:05Z","receivedAt":"2021-04-26T17:48:02Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nIt's a dumb test, but it's surprisingly easy to break.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 7 +++++++\n 1 file changed, 7 insertions(+)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 5c2510f1f5..9afba2f282 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -37,6 +37,13 @@ last_commit_subject () {\n \tgit log --pretty=format:%s -1\n }\n \n+test_expect_success 'shows short help text for -h' '\n+\ttest_expect_code 129 git subtree -h >out 2>err &&\n+\ttest_must_be_empty err &&\n+\tgrep -e \"^ *or: git subtree pull\" out &&\n+\tgrep -e --annotate out\n+'\n+\n #\n # Tests for 'git subtree add'\n #\n-- \n2.31.1\n\n"},{"id":"423003","messageId":"20210426174525.3937858-12-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 11/30] subtree: t7900: add porcelain tests for 'pull' and 'push'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:06Z","receivedAt":"2021-04-26T17:48:04Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThe 'pull' and 'push' subcommands deserve their own sections in the tests.\nAdd some basic tests for them.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Don't switch unrelated uses of vanilla test_create_repo over to\n   subtree_test_create_repo; this has been moved to happen in an\n   earlier commit.\n - Fix whitespace.\n\n contrib/subtree/t/t7900-subtree.sh | 127 +++++++++++++++++++++++++++++\n 1 file changed, 127 insertions(+)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 9afba2f282..ce6861c22d 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -427,6 +427,133 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n \t)\n '\n \n+#\n+# Tests for 'git subtree pull'\n+#\n+\n+test_expect_success 'pull requires option --prefix' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\ttest_must_fail git subtree pull ./\"sub proj\" HEAD >out 2>err &&\n+\n+\t\techo \"You must provide the --prefix option.\" >expected &&\n+\t\ttest_must_be_empty out &&\n+\t\ttest_cmp expected err\n+\t)\n+'\n+\n+test_expect_success 'pull requires path given by option --prefix must exist' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD >out 2>err &&\n+\n+\t\techo \"'\\''sub dir'\\'' does not exist; use '\\''git subtree add'\\''\" >expected &&\n+\t\ttest_must_be_empty out &&\n+\t\ttest_cmp expected err\n+\t)\n+'\n+\n+test_expect_success 'pull basic operation' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\texp=$(git -C \"sub proj\" rev-parse --verify HEAD:) &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n+\t\tact=$(git rev-parse --verify HEAD:\"sub dir\") &&\n+\t\ttest \"$act\" = \"$exp\"\n+\t)\n+'\n+\n+#\n+# Tests for 'git subtree push'\n+#\n+\n+test_expect_success 'push requires option --prefix' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\techo \"You must provide the --prefix option.\" >expected &&\n+\t\ttest_must_fail git subtree push \"./sub proj\" from-mainline >actual 2>&1 &&\n+\t\ttest_debug \"printf '\"expected: \"'\" &&\n+\t\ttest_debug \"cat expected\" &&\n+\t\ttest_debug \"printf '\"actual: \"'\" &&\n+\t\ttest_debug \"cat actual\" &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n+test_expect_success 'push requires path given by option --prefix must exist' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" >expected &&\n+\t\ttest_must_fail git subtree push --prefix=non-existent-directory \"./sub proj\" from-mainline >actual 2>&1 &&\n+\t\ttest_debug \"printf '\"expected: \"'\" &&\n+\t\ttest_debug \"cat expected\" &&\n+\t\ttest_debug \"printf '\"actual: \"'\" &&\n+\t\ttest_debug \"cat actual\" &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n+test_expect_success 'push basic operation' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tbefore=$(git rev-parse --verify HEAD) &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" ./\"sub proj\" from-mainline &&\n+\t\ttest \"$before\" = \"$(git rev-parse --verify HEAD)\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n #\n # Validity checking\n #\n-- \n2.31.1\n\n"},{"id":"423004","messageId":"20210426174525.3937858-13-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 12/30] subtree: don't have loose code outside of a function","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:07Z","receivedAt":"2021-04-26T17:48:05Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nShove all of the loose code inside of a main() function.\n\nThis comes down to personal preference more than anything else.  A\npreference that I've developed over years of maintaining large Bash\nscripts, but still a mere personal preference.\n\nIn this specific case, it's also moving the `set -- -h`, the `git\nrev-parse --parseopt`, and the `. git-sh-setup` to be closer to all\nthe rest of the argument parsing, which is a readability win on its\nown, IMO.\n\n\"Ignore space change\" is probably helpful when viewing this diff.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Include rationale in the the commit message.\n\n contrib/subtree/git-subtree.sh | 245 +++++++++++++++++----------------\n 1 file changed, 125 insertions(+), 120 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 868e18b9a1..d1ed7f9a6c 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -4,10 +4,7 @@\n #\n # Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com>\n #\n-if test $# -eq 0\n-then\n-\tset -- -h\n-fi\n+\n OPTS_SPEC=\"\\\n git subtree add   --prefix=<prefix> <commit>\n git subtree add   --prefix=<prefix> <repository> <ref>\n@@ -30,12 +27,8 @@ rejoin        merge the new branch back into HEAD\n  options for 'add', 'merge', and 'pull'\n squash        merge subtree changes as a single commit\n \"\n-eval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n \n PATH=$PATH:$(git --exec-path)\n-. git-sh-setup\n-\n-require_work_tree\n \n quiet=\n branch=\n@@ -84,126 +77,138 @@ ensure_single_rev () {\n \tfi\n }\n \n-while test $# -gt 0\n-do\n-\topt=\"$1\"\n-\tshift\n+main () {\n+\tif test $# -eq 0\n+\tthen\n+\t\tset -- -h\n+\tfi\n+\teval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n+\t. git-sh-setup\n+\trequire_work_tree\n \n-\tcase \"$opt\" in\n-\t-q)\n-\t\tquiet=1\n-\t\t;;\n-\t-d)\n-\t\tdebug=1\n-\t\t;;\n-\t--annotate)\n-\t\tannotate=\"$1\"\n-\t\tshift\n-\t\t;;\n-\t--no-annotate)\n-\t\tannotate=\n-\t\t;;\n-\t-b)\n-\t\tbranch=\"$1\"\n-\t\tshift\n-\t\t;;\n-\t-P)\n-\t\tprefix=\"${1%/}\"\n-\t\tshift\n-\t\t;;\n-\t-m)\n-\t\tmessage=\"$1\"\n-\t\tshift\n-\t\t;;\n-\t--no-prefix)\n-\t\tprefix=\n-\t\t;;\n-\t--onto)\n-\t\tonto=\"$1\"\n+\twhile test $# -gt 0\n+\tdo\n+\t\topt=\"$1\"\n \t\tshift\n+\n+\t\tcase \"$opt\" in\n+\t\t-q)\n+\t\t\tquiet=1\n+\t\t\t;;\n+\t\t-d)\n+\t\t\tdebug=1\n+\t\t\t;;\n+\t\t--annotate)\n+\t\t\tannotate=\"$1\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--no-annotate)\n+\t\t\tannotate=\n+\t\t\t;;\n+\t\t-b)\n+\t\t\tbranch=\"$1\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t-P)\n+\t\t\tprefix=\"${1%/}\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t-m)\n+\t\t\tmessage=\"$1\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--no-prefix)\n+\t\t\tprefix=\n+\t\t\t;;\n+\t\t--onto)\n+\t\t\tonto=\"$1\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--no-onto)\n+\t\t\tonto=\n+\t\t\t;;\n+\t\t--rejoin)\n+\t\t\trejoin=1\n+\t\t\t;;\n+\t\t--no-rejoin)\n+\t\t\trejoin=\n+\t\t\t;;\n+\t\t--ignore-joins)\n+\t\t\tignore_joins=1\n+\t\t\t;;\n+\t\t--no-ignore-joins)\n+\t\t\tignore_joins=\n+\t\t\t;;\n+\t\t--squash)\n+\t\t\tsquash=1\n+\t\t\t;;\n+\t\t--no-squash)\n+\t\t\tsquash=\n+\t\t\t;;\n+\t\t--)\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t*)\n+\t\t\tdie \"Unexpected option: $opt\"\n+\t\t\t;;\n+\t\tesac\n+\tdone\n+\n+\tcommand=\"$1\"\n+\tshift\n+\n+\tcase \"$command\" in\n+\tadd|merge|pull)\n+\t\tdefault=\n \t\t;;\n-\t--no-onto)\n-\t\tonto=\n-\t\t;;\n-\t--rejoin)\n-\t\trejoin=1\n-\t\t;;\n-\t--no-rejoin)\n-\t\trejoin=\n-\t\t;;\n-\t--ignore-joins)\n-\t\tignore_joins=1\n-\t\t;;\n-\t--no-ignore-joins)\n-\t\tignore_joins=\n-\t\t;;\n-\t--squash)\n-\t\tsquash=1\n+\tsplit|push)\n+\t\tdefault=\"--default HEAD\"\n \t\t;;\n-\t--no-squash)\n-\t\tsquash=\n+\t*)\n+\t\tdie \"Unknown command '$command'\"\n \t\t;;\n-\t--)\n-\t\tbreak\n+\tesac\n+\n+\tif test -z \"$prefix\"\n+\tthen\n+\t\tdie \"You must provide the --prefix option.\"\n+\tfi\n+\n+\tcase \"$command\" in\n+\tadd)\n+\t\ttest -e \"$prefix\" &&\n+\t\t\tdie \"prefix '$prefix' already exists.\"\n \t\t;;\n \t*)\n-\t\tdie \"Unexpected option: $opt\"\n+\t\ttest -e \"$prefix\" ||\n+\t\t\tdie \"'$prefix' does not exist; use 'git subtree add'\"\n \t\t;;\n \tesac\n-done\n-\n-command=\"$1\"\n-shift\n-\n-case \"$command\" in\n-add|merge|pull)\n-\tdefault=\n-\t;;\n-split|push)\n-\tdefault=\"--default HEAD\"\n-\t;;\n-*)\n-\tdie \"Unknown command '$command'\"\n-\t;;\n-esac\n-\n-if test -z \"$prefix\"\n-then\n-\tdie \"You must provide the --prefix option.\"\n-fi\n-\n-case \"$command\" in\n-add)\n-\ttest -e \"$prefix\" &&\n-\t\tdie \"prefix '$prefix' already exists.\"\n-\t;;\n-*)\n-\ttest -e \"$prefix\" ||\n-\t\tdie \"'$prefix' does not exist; use 'git subtree add'\"\n-\t;;\n-esac\n-\n-dir=\"$(dirname \"$prefix/.\")\"\n-\n-if test \"$command\" != \"pull\" &&\n-\t\ttest \"$command\" != \"add\" &&\n-\t\ttest \"$command\" != \"push\"\n-then\n-\trevs=$(git rev-parse $default --revs-only \"$@\") || exit $?\n-\tdirs=$(git rev-parse --no-revs --no-flags \"$@\") || exit $?\n-\tensure_single_rev $revs\n-\tif test -n \"$dirs\"\n-\tthen\n-\t\tdie \"Error: Use --prefix instead of bare filenames.\"\n-\tfi\n-fi\n-\n-debug \"command: {$command}\"\n-debug \"quiet: {$quiet}\"\n-debug \"revs: {$revs}\"\n-debug \"dir: {$dir}\"\n-debug \"opts: {$*}\"\n-debug\n+\n+\tdir=\"$(dirname \"$prefix/.\")\"\n+\n+\tif test \"$command\" != \"pull\" &&\n+\t\t\ttest \"$command\" != \"add\" &&\n+\t\t\ttest \"$command\" != \"push\"\n+\tthen\n+\t\trevs=$(git rev-parse $default --revs-only \"$@\") || exit $?\n+\t\tdirs=$(git rev-parse --no-revs --no-flags \"$@\") || exit $?\n+\t\tensure_single_rev $revs\n+\t\tif test -n \"$dirs\"\n+\t\tthen\n+\t\t\tdie \"Error: Use --prefix instead of bare filenames.\"\n+\t\tfi\n+\tfi\n+\n+\tdebug \"command: {$command}\"\n+\tdebug \"quiet: {$quiet}\"\n+\tdebug \"revs: {$revs}\"\n+\tdebug \"dir: {$dir}\"\n+\tdebug \"opts: {$*}\"\n+\tdebug\n+\n+\t\"cmd_$command\" \"$@\"\n+}\n \n cache_setup () {\n \tcachedir=\"$GIT_DIR/subtree-cache/$$\"\n@@ -898,4 +903,4 @@ cmd_push () {\n \tfi\n }\n \n-\"cmd_$command\" \"$@\"\n+main \"$@\"\n-- \n2.31.1\n\n"},{"id":"423005","messageId":"20210426174525.3937858-14-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 13/30] subtree: more consistent error propagation","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:08Z","receivedAt":"2021-04-26T17:48:06Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nEnsure that every $(subshell) that calls a function (as opposed to an\nexternal executable) is followed by `|| exit $?`.  Similarly, ensure that\nevery `cmd | while read; do ... done` loop is followed by `|| exit $?`.\n\nBoth of those constructs mean that it can miss `die` calls, and keep\nrunning when it shouldn't.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 28 ++++++++++++++--------------\n 1 file changed, 14 insertions(+), 14 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex d1ed7f9a6c..9ca498f81c 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -243,7 +243,7 @@ cache_miss () {\n }\n \n check_parents () {\n-\tmissed=$(cache_miss \"$1\")\n+\tmissed=$(cache_miss \"$1\") || exit $?\n \tlocal indent=$(($2 + 1))\n \tfor miss in $missed\n \tdo\n@@ -345,7 +345,7 @@ find_latest_squash () {\n \t\t\tsub=\n \t\t\t;;\n \t\tesac\n-\tdone\n+\tdone || exit $?\n }\n \n find_existing_splits () {\n@@ -394,7 +394,7 @@ find_existing_splits () {\n \t\t\tsub=\n \t\t\t;;\n \t\tesac\n-\tdone\n+\tdone || exit $?\n }\n \n copy_commit () {\n@@ -508,7 +508,7 @@ subtree_for_commit () {\n \t\ttest \"$type\" = \"commit\" && continue  # ignore submodules\n \t\techo $tree\n \t\tbreak\n-\tdone\n+\tdone || exit $?\n }\n \n tree_changed () {\n@@ -518,7 +518,7 @@ tree_changed () {\n \tthen\n \t\treturn 0   # weird parents, consider it changed\n \telse\n-\t\tptree=$(toptree_for_commit $1)\n+\t\tptree=$(toptree_for_commit $1) || exit $?\n \t\tif test \"$ptree\" != \"$tree\"\n \t\tthen\n \t\t\treturn 0   # changed\n@@ -652,7 +652,7 @@ process_split_commit () {\n \tprogress \"$revcount/$revmax ($createcount) [$extracount]\"\n \n \tdebug \"Processing commit: $rev\"\n-\texists=$(cache_get \"$rev\")\n+\texists=$(cache_get \"$rev\") || exit $?\n \tif test -n \"$exists\"\n \tthen\n \t\tdebug \"  prior: $exists\"\n@@ -661,10 +661,10 @@ process_split_commit () {\n \tcreatecount=$(($createcount + 1))\n \tdebug \"  parents: $parents\"\n \tcheck_parents \"$parents\" \"$indent\"\n-\tnewparents=$(cache_get $parents)\n+\tnewparents=$(cache_get $parents) || exit $?\n \tdebug \"  newparents: $newparents\"\n \n-\ttree=$(subtree_for_commit \"$rev\" \"$dir\")\n+\ttree=$(subtree_for_commit \"$rev\" \"$dir\") || exit $?\n \tdebug \"  tree is: $tree\"\n \n \t# ugly.  is there no better way to tell if this is a subtree\n@@ -750,7 +750,7 @@ cmd_add_commit () {\n \t\tcommit=$(add_squashed_msg \"$rev\" \"$dir\" |\n \t\t\tgit commit-tree \"$tree\" $headp -p \"$rev\") || exit $?\n \telse\n-\t\trevp=$(peel_committish \"$rev\") &&\n+\t\trevp=$(peel_committish \"$rev\") || exit $?\n \t\tcommit=$(add_msg \"$dir\" $headrev \"$rev\" |\n \t\t\tgit commit-tree \"$tree\" $headp -p \"$revp\") || exit $?\n \tfi\n@@ -773,10 +773,10 @@ cmd_split () {\n \t\t\t# any parent we find there can be used verbatim\n \t\t\tdebug \"  cache: $rev\"\n \t\t\tcache_set \"$rev\" \"$rev\"\n-\t\tdone\n+\t\tdone || exit $?\n \tfi\n \n-\tunrevs=\"$(find_existing_splits \"$dir\" \"$revs\")\"\n+\tunrevs=\"$(find_existing_splits \"$dir\" \"$revs\")\" || exit $?\n \n \t# We can't restrict rev-list to only $dir here, because some of our\n \t# parents have the $dir contents the root, and those won't match.\n@@ -792,7 +792,7 @@ cmd_split () {\n \t\tprocess_split_commit \"$rev\" \"$parents\" 0\n \tdone || exit $?\n \n-\tlatest_new=$(cache_get latest_new)\n+\tlatest_new=$(cache_get latest_new) || exit $?\n \tif test -z \"$latest_new\"\n \tthen\n \t\tdie \"No new revisions were found\"\n@@ -801,7 +801,7 @@ cmd_split () {\n \tif test -n \"$rejoin\"\n \tthen\n \t\tdebug \"Merging split branch into HEAD...\"\n-\t\tlatest_old=$(cache_get latest_old)\n+\t\tlatest_old=$(cache_get latest_old) || exit $?\n \t\tgit merge -s ours \\\n \t\t\t--allow-unrelated-histories \\\n \t\t\t-m \"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" \\\n@@ -834,7 +834,7 @@ cmd_merge () {\n \n \tif test -n \"$squash\"\n \tthen\n-\t\tfirst_split=\"$(find_latest_squash \"$dir\")\"\n+\t\tfirst_split=\"$(find_latest_squash \"$dir\")\" || exit $?\n \t\tif test -z \"$first_split\"\n \t\tthen\n \t\t\tdie \"Can't squash-merge: '$dir' was never added.\"\n-- \n2.31.1\n\n"},{"id":"423006","messageId":"20210426174525.3937858-17-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 16/30] subtree: use git-sh-setup's `say`","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:11Z","receivedAt":"2021-04-26T17:48:08Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nsubtree currently defines its own `say` implementation, rather than\nusing git-sh-setups's implementation.  Change that, don't re-invent the\nwheel.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 22 +++++++---------------\n 1 file changed, 7 insertions(+), 15 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 70e16b807b..bb4934dbc0 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -30,7 +30,6 @@ squash        merge subtree changes as a single commit\n \n PATH=$PATH:$(git --exec-path)\n \n-quiet=\n branch=\n debug=\n command=\n@@ -49,15 +48,8 @@ debug () {\n \tfi\n }\n \n-say () {\n-\tif test -z \"$quiet\"\n-\tthen\n-\t\tprintf \"%s\\n\" \"$*\" >&2\n-\tfi\n-}\n-\n progress () {\n-\tif test -z \"$quiet\"\n+\tif test -z \"$GIT_QUIET\"\n \tthen\n \t\tprintf \"%s\\r\" \"$*\" >&2\n \tfi\n@@ -93,7 +85,7 @@ main () {\n \n \t\tcase \"$opt\" in\n \t\t-q)\n-\t\t\tquiet=1\n+\t\t\tGIT_QUIET=1\n \t\t\t;;\n \t\t-d)\n \t\t\tdebug=1\n@@ -201,7 +193,7 @@ main () {\n \tfi\n \n \tdebug \"command: {$command}\"\n-\tdebug \"quiet: {$quiet}\"\n+\tdebug \"quiet: {$GIT_QUIET}\"\n \tdebug \"revs: {$revs}\"\n \tdebug \"dir: {$dir}\"\n \tdebug \"opts: {$*}\"\n@@ -698,7 +690,7 @@ cmd_add () {\n \n \t\tcmd_add_repository \"$@\"\n \telse\n-\t\tsay \"error: parameters were '$@'\"\n+\t\tsay >&2 \"error: parameters were '$@'\"\n \t\tdie \"Provide either a commit or a repository and commit.\"\n \tfi\n }\n@@ -742,7 +734,7 @@ cmd_add_commit () {\n \tfi\n \tgit reset \"$commit\" || exit $?\n \n-\tsay \"Added dir '$dir'\"\n+\tsay >&2 \"Added dir '$dir'\"\n }\n \n cmd_split () {\n@@ -807,7 +799,7 @@ cmd_split () {\n \t\tfi\n \t\tgit update-ref -m 'subtree split' \\\n \t\t\t\"refs/heads/$branch\" \"$latest_new\" || exit $?\n-\t\tsay \"$action branch '$branch'\"\n+\t\tsay >&2 \"$action branch '$branch'\"\n \tfi\n \techo \"$latest_new\"\n \texit 0\n@@ -830,7 +822,7 @@ cmd_merge () {\n \t\tsub=$2\n \t\tif test \"$sub\" = \"$rev\"\n \t\tthen\n-\t\t\tsay \"Subtree is already at commit $rev.\"\n+\t\t\tsay >&2 \"Subtree is already at commit $rev.\"\n \t\t\texit 0\n \t\tfi\n \t\tnew=$(new_squash_commit \"$old\" \"$sub\" \"$rev\") || exit $?\n-- \n2.31.1\n\n"},{"id":"423007","messageId":"20210426174525.3937858-15-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 14/30] subtree: drop support for git < 1.7","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:09Z","receivedAt":"2021-04-26T17:48:09Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nSuport for Git versions older than 1.7.0 (older than February 2010) was\nnice to have when git-subtree lived out-of-tree.  But now that it lives\nin git.git, it's not necessary to keep around.  While it's technically\nin contrib, with the standard 'git' packages for common systems\n(including Arch Linux and macOS) including git-subtree, it seems\nvanishingly likely to me that people are separately installing\ngit-subtree from git.git alongside an older 'git' install (although it\nalso seems vanishingly likely that people are still using >11 year old\ngit installs).\n\nNot that there's much reason to remove it either, it's not much code,\nand none of my changes depend on a newer git (to my knowledge, anyway;\nI'm not actually testing against older git).  I just figure it's an easy\npiece of fat to trim, in the journey to making the whole thing easier to\nhack on.\n\n\"Ignore space change\" is probably helpful when viewing this diff.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Include rationale in the the commit message.\n\n contrib/subtree/git-subtree.sh | 19 ++++---------------\n 1 file changed, 4 insertions(+), 15 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 9ca498f81c..4503564f7e 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -852,23 +852,12 @@ cmd_merge () {\n \t\trev=\"$new\"\n \tfi\n \n-\tversion=$(git version)\n-\tif test \"$version\" \\< \"git version 1.7\"\n+\tif test -n \"$message\"\n \tthen\n-\t\tif test -n \"$message\"\n-\t\tthen\n-\t\t\tgit merge -s subtree --message=\"$message\" \"$rev\"\n-\t\telse\n-\t\t\tgit merge -s subtree \"$rev\"\n-\t\tfi\n+\t\tgit merge -Xsubtree=\"$prefix\" \\\n+\t\t    --message=\"$message\" \"$rev\"\n \telse\n-\t\tif test -n \"$message\"\n-\t\tthen\n-\t\t\tgit merge -Xsubtree=\"$prefix\" \\\n-\t\t\t\t--message=\"$message\" \"$rev\"\n-\t\telse\n-\t\t\tgit merge -Xsubtree=\"$prefix\" $rev\n-\t\tfi\n+\t\tgit merge -Xsubtree=\"$prefix\" $rev\n \tfi\n }\n \n-- \n2.31.1\n\n"},{"id":"423008","messageId":"20210426174525.3937858-18-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 17/30] subtree: use more explicit variable names for cmdline args","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:12Z","receivedAt":"2021-04-26T17:48:12Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nMake it painfully obvious when reading the code which variables are\ndirect parsings of command line arguments.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 132 ++++++++++++++++-----------------\n 1 file changed, 66 insertions(+), 66 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex bb4934dbc0..d7de4b0653 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -30,19 +30,19 @@ squash        merge subtree changes as a single commit\n \n PATH=$PATH:$(git --exec-path)\n \n-branch=\n-debug=\n-command=\n-onto=\n-rejoin=\n-ignore_joins=\n-annotate=\n-squash=\n-message=\n-prefix=\n+arg_debug=\n+arg_command=\n+arg_prefix=\n+arg_split_branch=\n+arg_split_onto=\n+arg_split_rejoin=\n+arg_split_ignore_joins=\n+arg_split_annotate=\n+arg_addmerge_squash=\n+arg_addmerge_message=\n \n debug () {\n-\tif test -n \"$debug\"\n+\tif test -n \"$arg_debug\"\n \tthen\n \t\tprintf \"%s\\n\" \"$*\" >&2\n \tfi\n@@ -88,54 +88,54 @@ main () {\n \t\t\tGIT_QUIET=1\n \t\t\t;;\n \t\t-d)\n-\t\t\tdebug=1\n+\t\t\targ_debug=1\n \t\t\t;;\n \t\t--annotate)\n-\t\t\tannotate=\"$1\"\n+\t\t\targ_split_annotate=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-annotate)\n-\t\t\tannotate=\n+\t\t\targ_split_annotate=\n \t\t\t;;\n \t\t-b)\n-\t\t\tbranch=\"$1\"\n+\t\t\targ_split_branch=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t-P)\n-\t\t\tprefix=\"${1%/}\"\n+\t\t\targ_prefix=\"${1%/}\"\n \t\t\tshift\n \t\t\t;;\n \t\t-m)\n-\t\t\tmessage=\"$1\"\n+\t\t\targ_addmerge_message=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-prefix)\n-\t\t\tprefix=\n+\t\t\targ_prefix=\n \t\t\t;;\n \t\t--onto)\n-\t\t\tonto=\"$1\"\n+\t\t\targ_split_onto=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-onto)\n-\t\t\tonto=\n+\t\t\targ_split_onto=\n \t\t\t;;\n \t\t--rejoin)\n-\t\t\trejoin=1\n+\t\t\targ_split_rejoin=1\n \t\t\t;;\n \t\t--no-rejoin)\n-\t\t\trejoin=\n+\t\t\targ_split_rejoin=\n \t\t\t;;\n \t\t--ignore-joins)\n-\t\t\tignore_joins=1\n+\t\t\targ_split_ignore_joins=1\n \t\t\t;;\n \t\t--no-ignore-joins)\n-\t\t\tignore_joins=\n+\t\t\targ_split_ignore_joins=\n \t\t\t;;\n \t\t--squash)\n-\t\t\tsquash=1\n+\t\t\targ_addmerge_squash=1\n \t\t\t;;\n \t\t--no-squash)\n-\t\t\tsquash=\n+\t\t\targ_addmerge_squash=\n \t\t\t;;\n \t\t--)\n \t\t\tbreak\n@@ -146,10 +146,10 @@ main () {\n \t\tesac\n \tdone\n \n-\tcommand=\"$1\"\n+\targ_command=\"$1\"\n \tshift\n \n-\tcase \"$command\" in\n+\tcase \"$arg_command\" in\n \tadd|merge|pull)\n \t\tdefault=\n \t\t;;\n@@ -157,31 +157,31 @@ main () {\n \t\tdefault=\"--default HEAD\"\n \t\t;;\n \t*)\n-\t\tdie \"Unknown command '$command'\"\n+\t\tdie \"Unknown command '$arg_command'\"\n \t\t;;\n \tesac\n \n-\tif test -z \"$prefix\"\n+\tif test -z \"$arg_prefix\"\n \tthen\n \t\tdie \"You must provide the --prefix option.\"\n \tfi\n \n-\tcase \"$command\" in\n+\tcase \"$arg_command\" in\n \tadd)\n-\t\ttest -e \"$prefix\" &&\n-\t\t\tdie \"prefix '$prefix' already exists.\"\n+\t\ttest -e \"$arg_prefix\" &&\n+\t\t\tdie \"prefix '$arg_prefix' already exists.\"\n \t\t;;\n \t*)\n-\t\ttest -e \"$prefix\" ||\n-\t\t\tdie \"'$prefix' does not exist; use 'git subtree add'\"\n+\t\ttest -e \"$arg_prefix\" ||\n+\t\t\tdie \"'$arg_prefix' does not exist; use 'git subtree add'\"\n \t\t;;\n \tesac\n \n-\tdir=\"$(dirname \"$prefix/.\")\"\n+\tdir=\"$(dirname \"$arg_prefix/.\")\"\n \n-\tif test \"$command\" != \"pull\" &&\n-\t\t\ttest \"$command\" != \"add\" &&\n-\t\t\ttest \"$command\" != \"push\"\n+\tif test \"$arg_command\" != \"pull\" &&\n+\t\t\ttest \"$arg_command\" != \"add\" &&\n+\t\t\ttest \"$arg_command\" != \"push\"\n \tthen\n \t\trevs=$(git rev-parse $default --revs-only \"$@\") || exit $?\n \t\tdirs=$(git rev-parse --no-revs --no-flags \"$@\") || exit $?\n@@ -192,14 +192,14 @@ main () {\n \t\tfi\n \tfi\n \n-\tdebug \"command: {$command}\"\n+\tdebug \"command: {$arg_command}\"\n \tdebug \"quiet: {$GIT_QUIET}\"\n \tdebug \"revs: {$revs}\"\n \tdebug \"dir: {$dir}\"\n \tdebug \"opts: {$*}\"\n \tdebug\n \n-\t\"cmd_$command\" \"$@\"\n+\t\"cmd_$arg_command\" \"$@\"\n }\n \n cache_setup () {\n@@ -333,7 +333,7 @@ find_existing_splits () {\n \tmain=\n \tsub=\n \tlocal grep_format=\"^git-subtree-dir: $dir/*\\$\"\n-\tif test -n \"$ignore_joins\"\n+\tif test -n \"$arg_split_ignore_joins\"\n \tthen\n \t\tgrep_format=\"^Add '$dir/' from commit '\"\n \tfi\n@@ -394,7 +394,7 @@ copy_commit () {\n \t\t\tGIT_COMMITTER_EMAIL \\\n \t\t\tGIT_COMMITTER_DATE\n \t\t(\n-\t\t\tprintf \"%s\" \"$annotate\"\n+\t\t\tprintf \"%s\" \"$arg_split_annotate\"\n \t\t\tcat\n \t\t) |\n \t\tgit commit-tree \"$2\" $3  # reads the rest of stdin\n@@ -405,9 +405,9 @@ add_msg () {\n \tdir=\"$1\"\n \tlatest_old=\"$2\"\n \tlatest_new=\"$3\"\n-\tif test -n \"$message\"\n+\tif test -n \"$arg_addmerge_message\"\n \tthen\n-\t\tcommit_message=\"$message\"\n+\t\tcommit_message=\"$arg_addmerge_message\"\n \telse\n \t\tcommit_message=\"Add '$dir/' from commit '$latest_new'\"\n \tfi\n@@ -421,9 +421,9 @@ add_msg () {\n }\n \n add_squashed_msg () {\n-\tif test -n \"$message\"\n+\tif test -n \"$arg_addmerge_message\"\n \tthen\n-\t\techo \"$message\"\n+\t\techo \"$arg_addmerge_message\"\n \telse\n \t\techo \"Merge commit '$1' as '$2'\"\n \tfi\n@@ -433,9 +433,9 @@ rejoin_msg () {\n \tdir=\"$1\"\n \tlatest_old=\"$2\"\n \tlatest_new=\"$3\"\n-\tif test -n \"$message\"\n+\tif test -n \"$arg_addmerge_message\"\n \tthen\n-\t\tcommit_message=\"$message\"\n+\t\tcommit_message=\"$arg_addmerge_message\"\n \telse\n \t\tcommit_message=\"Split '$dir/' into commit '$latest_new'\"\n \tfi\n@@ -722,7 +722,7 @@ cmd_add_commit () {\n \t\theadp=\n \tfi\n \n-\tif test -n \"$squash\"\n+\tif test -n \"$arg_addmerge_squash\"\n \tthen\n \t\trev=$(new_squash_commit \"\" \"\" \"$rev\") || exit $?\n \t\tcommit=$(add_squashed_msg \"$rev\" \"$dir\" |\n@@ -741,10 +741,10 @@ cmd_split () {\n \tdebug \"Splitting $dir...\"\n \tcache_setup || exit $?\n \n-\tif test -n \"$onto\"\n+\tif test -n \"$arg_split_onto\"\n \tthen\n-\t\tdebug \"Reading history for --onto=$onto...\"\n-\t\tgit rev-list $onto |\n+\t\tdebug \"Reading history for --onto=$arg_split_onto...\"\n+\t\tgit rev-list $arg_split_onto |\n \t\twhile read rev\n \t\tdo\n \t\t\t# the 'onto' history is already just the subdir, so\n@@ -776,7 +776,7 @@ cmd_split () {\n \t\tdie \"No new revisions were found\"\n \tfi\n \n-\tif test -n \"$rejoin\"\n+\tif test -n \"$arg_split_rejoin\"\n \tthen\n \t\tdebug \"Merging split branch into HEAD...\"\n \t\tlatest_old=$(cache_get latest_old) || exit $?\n@@ -785,21 +785,21 @@ cmd_split () {\n \t\t\t-m \"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" \\\n \t\t\t\"$latest_new\" >&2 || exit $?\n \tfi\n-\tif test -n \"$branch\"\n+\tif test -n \"$arg_split_branch\"\n \tthen\n-\t\tif rev_exists \"refs/heads/$branch\"\n+\t\tif rev_exists \"refs/heads/$arg_split_branch\"\n \t\tthen\n-\t\t\tif ! git merge-base --is-ancestor \"$branch\" \"$latest_new\"\n+\t\t\tif ! git merge-base --is-ancestor \"$arg_split_branch\" \"$latest_new\"\n \t\t\tthen\n-\t\t\t\tdie \"Branch '$branch' is not an ancestor of commit '$latest_new'.\"\n+\t\t\t\tdie \"Branch '$arg_split_branch' is not an ancestor of commit '$latest_new'.\"\n \t\t\tfi\n \t\t\taction='Updated'\n \t\telse\n \t\t\taction='Created'\n \t\tfi\n \t\tgit update-ref -m 'subtree split' \\\n-\t\t\t\"refs/heads/$branch\" \"$latest_new\" || exit $?\n-\t\tsay >&2 \"$action branch '$branch'\"\n+\t\t\t\"refs/heads/$arg_split_branch\" \"$latest_new\" || exit $?\n+\t\tsay >&2 \"$action branch '$arg_split_branch'\"\n \tfi\n \techo \"$latest_new\"\n \texit 0\n@@ -810,7 +810,7 @@ cmd_merge () {\n \tensure_single_rev $rev\n \tensure_clean\n \n-\tif test -n \"$squash\"\n+\tif test -n \"$arg_addmerge_squash\"\n \tthen\n \t\tfirst_split=\"$(find_latest_squash \"$dir\")\" || exit $?\n \t\tif test -z \"$first_split\"\n@@ -830,12 +830,12 @@ cmd_merge () {\n \t\trev=\"$new\"\n \tfi\n \n-\tif test -n \"$message\"\n+\tif test -n \"$arg_addmerge_message\"\n \tthen\n-\t\tgit merge -Xsubtree=\"$prefix\" \\\n-\t\t    --message=\"$message\" \"$rev\"\n+\t\tgit merge -Xsubtree=\"$arg_prefix\" \\\n+\t\t\t--message=\"$arg_addmerge_message\" \"$rev\"\n \telse\n-\t\tgit merge -Xsubtree=\"$prefix\" $rev\n+\t\tgit merge -Xsubtree=\"$arg_prefix\" $rev\n \tfi\n }\n \n@@ -863,7 +863,7 @@ cmd_push () {\n \t\trepository=$1\n \t\trefspec=$2\n \t\techo \"git push using: \" \"$repository\" \"$refspec\"\n-\t\tlocalrev=$(git subtree split --prefix=\"$prefix\") || die\n+\t\tlocalrev=$(git subtree split --prefix=\"$arg_prefix\") || die\n \t\tgit push \"$repository\" \"$localrev\":\"refs/heads/$refspec\"\n \telse\n \t\tdie \"'$dir' must already exist. Try 'git subtree add'.\"\n-- \n2.31.1\n\n"},{"id":"423009","messageId":"20210426174525.3937858-16-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 15/30] subtree: use `git merge-base --is-ancestor`","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:10Z","receivedAt":"2021-04-26T17:48:13Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nInstead of writing a slow `rev_is_descendant_of_branch $a $b` function\nin shell, just use the fast `git merge-base --is-ancestor $b $a`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 16 +---------------\n 1 file changed, 1 insertion(+), 15 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 4503564f7e..70e16b807b 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -280,20 +280,6 @@ rev_exists () {\n \tfi\n }\n \n-rev_is_descendant_of_branch () {\n-\tnewrev=\"$1\"\n-\tbranch=\"$2\"\n-\tbranch_hash=$(git rev-parse \"$branch\")\n-\tmatch=$(git rev-list -1 \"$branch_hash\" \"^$newrev\")\n-\n-\tif test -z \"$match\"\n-\tthen\n-\t\treturn 0\n-\telse\n-\t\treturn 1\n-\tfi\n-}\n-\n # if a commit doesn't have a parent, this might not work.  But we only want\n # to remove the parent from the rev-list, and since it doesn't exist, it won't\n # be there anyway, so do nothing in that case.\n@@ -811,7 +797,7 @@ cmd_split () {\n \tthen\n \t\tif rev_exists \"refs/heads/$branch\"\n \t\tthen\n-\t\t\tif ! rev_is_descendant_of_branch \"$latest_new\" \"$branch\"\n+\t\t\tif ! git merge-base --is-ancestor \"$branch\" \"$latest_new\"\n \t\t\tthen\n \t\t\t\tdie \"Branch '$branch' is not an ancestor of commit '$latest_new'.\"\n \t\t\tfi\n-- \n2.31.1\n\n"},{"id":"423010","messageId":"20210426174525.3937858-19-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 18/30] subtree: use \"$*\" instead of \"$@\" as appropriate","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:13Z","receivedAt":"2021-04-26T17:48:14Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\n\"$*\" is for when you want to concatenate the args together,\nwhitespace-separated; and \"$@\" is for when you want them to be separate\nstrings.\n\nThere are several places in subtree that erroneously use $@ when\nconcatenating args together into an error message.\n\nFor instance, if the args are argv[1]=\"dead\" and argv[2]=\"beef\", then\nthe line\n\n    die \"You must provide exactly one revision.  Got: '$@'\"\n\nsurely intends to call 'die' with the argument\n\n    argv[1]=\"You must provide exactly one revision.  Got: 'dead beef'\"\n\nhowever, because the line used $@ instead of $*, it will actually call\n'die' with the arguments\n\n    argv[1]=\"You must provide exactly one revision.  Got: 'dead\"\n    argv[2]=\"beef'\"\n\nThis isn't a big deal, because 'die' concatenates its arguments together\nanyway (using \"$*\").  But that doesn't change the fact that it was a\nmistake to use $@ instead of $*, even though in the end $@ still ended\nup doing the right thing.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Improve the commit message with quoting and clearer\n   explanation.\n\n contrib/subtree/git-subtree.sh | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex d7de4b0653..3105eb8033 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -58,14 +58,14 @@ progress () {\n assert () {\n \tif ! \"$@\"\n \tthen\n-\t\tdie \"assertion failed: \" \"$@\"\n+\t\tdie \"assertion failed: $*\"\n \tfi\n }\n \n ensure_single_rev () {\n \tif test $# -ne 1\n \tthen\n-\t\tdie \"You must provide exactly one revision.  Got: '$@'\"\n+\t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n \tfi\n }\n \n@@ -690,7 +690,7 @@ cmd_add () {\n \n \t\tcmd_add_repository \"$@\"\n \telse\n-\t\tsay >&2 \"error: parameters were '$@'\"\n+\t\tsay >&2 \"error: parameters were '$*'\"\n \t\tdie \"Provide either a commit or a repository and commit.\"\n \tfi\n }\n-- \n2.31.1\n\n"},{"id":"423011","messageId":"20210426174525.3937858-21-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 20/30] subtree: use \"^{commit}\" instead of \"^0\"","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:15Z","receivedAt":"2021-04-26T17:48:15Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThey are synonyms.  Both are used in the file.  ^{commit} is clearer, so\n\"standardize\" on that.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex af636fbb43..ee7fda3672 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -316,7 +316,7 @@ find_latest_squash () {\n \t\t\tmain=\"$b\"\n \t\t\t;;\n \t\tgit-subtree-split:)\n-\t\t\tsub=\"$(git rev-parse \"$b^0\")\" ||\n+\t\t\tsub=\"$(git rev-parse \"$b^{commit}\")\" ||\n \t\t\tdie \"could not rev-parse split hash $b from commit $sq\"\n \t\t\t;;\n \t\tEND)\n@@ -363,7 +363,7 @@ find_existing_splits () {\n \t\t\tmain=\"$b\"\n \t\t\t;;\n \t\tgit-subtree-split:)\n-\t\t\tsub=\"$(git rev-parse \"$b^0\")\" ||\n+\t\t\tsub=\"$(git rev-parse \"$b^{commit}\")\" ||\n \t\t\tdie \"could not rev-parse split hash $b from commit $sq\"\n \t\t\t;;\n \t\tEND)\n-- \n2.31.1\n\n"},{"id":"423012","messageId":"20210426174525.3937858-22-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 21/30] subtree: parse revs in individual cmd_ functions","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:16Z","receivedAt":"2021-04-26T17:48:16Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThe main argument parser goes ahead and tries to parse revs to make\nthings simpler for the sub-command implementations.  But, it includes\nenough special cases for different sub-commands.  And it's difficult\nhaving having to think about \"is this info coming from an argument, or a\nglobal variable?\".  So the main argument parser's effort to make things\n\"simpler\" ends up just making it more confusing and complicated.\n\nBegone with the 'revs' global variable; parse 'rev=$(...)' as needed in\nindividual 'cmd_*' functions.\n\nBegone with the 'default' global variable.  Its would-be value is\nknowable just from which function we're in.\n\nBegone with the 'ensure_single_rev' function.  Its functionality can be\nachieved by passing '--verify' to 'git rev-parse'.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 62 +++++++++++++---------------------\n 1 file changed, 24 insertions(+), 38 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex ee7fda3672..0df8d1b7d4 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -76,13 +76,6 @@ assert () {\n \tfi\n }\n \n-ensure_single_rev () {\n-\tif test $# -ne 1\n-\tthen\n-\t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n-\tfi\n-}\n-\n main () {\n \tif test $# -eq 0\n \tthen\n@@ -164,11 +157,8 @@ main () {\n \tshift\n \n \tcase \"$arg_command\" in\n-\tadd|merge|pull)\n-\t\tdefault=\n-\t\t;;\n-\tsplit|push)\n-\t\tdefault=\"--default HEAD\"\n+\tadd|merge|pull|split|push)\n+\t\t:\n \t\t;;\n \t*)\n \t\tdie \"Unknown command '$arg_command'\"\n@@ -193,22 +183,8 @@ main () {\n \n \tdir=\"$(dirname \"$arg_prefix/.\")\"\n \n-\tif test \"$arg_command\" != \"pull\" &&\n-\t\t\ttest \"$arg_command\" != \"add\" &&\n-\t\t\ttest \"$arg_command\" != \"push\"\n-\tthen\n-\t\trevs=$(git rev-parse $default --revs-only \"$@\") || exit $?\n-\t\tdirs=$(git rev-parse --no-revs --no-flags \"$@\") || exit $?\n-\t\tensure_single_rev $revs\n-\t\tif test -n \"$dirs\"\n-\t\tthen\n-\t\t\tdie \"Error: Use --prefix instead of bare filenames.\"\n-\t\tfi\n-\tfi\n-\n \tdebug \"command: {$arg_command}\"\n \tdebug \"quiet: {$GIT_QUIET}\"\n-\tdebug \"revs: {$revs}\"\n \tdebug \"dir: {$dir}\"\n \tdebug \"opts: {$*}\"\n \tdebug\n@@ -714,14 +690,13 @@ cmd_add_repository () {\n \trepository=$1\n \trefspec=$2\n \tgit fetch \"$@\" || exit $?\n-\trevs=FETCH_HEAD\n-\tset -- $revs\n-\tcmd_add_commit \"$@\"\n+\tcmd_add_commit FETCH_HEAD\n }\n \n cmd_add_commit () {\n-\trev=$(git rev-parse $default --revs-only \"$@\") || exit $?\n-\tensure_single_rev $rev\n+\t# The rev has already been validated by cmd_add(), we just\n+\t# need to normalize it.\n+\trev=$(git rev-parse --verify \"$1^{commit}\") || exit $?\n \n \tdebug \"Adding $dir as '$rev'...\"\n \tgit read-tree --prefix=\"$dir\" $rev || exit $?\n@@ -752,6 +727,17 @@ cmd_add_commit () {\n }\n \n cmd_split () {\n+\tif test $# -eq 0\n+\tthen\n+\t\trev=$(git rev-parse HEAD)\n+\telif test $# -eq 1\n+\tthen\n+\t\trev=$(git rev-parse -q --verify \"$1^{commit}\") ||\n+\t\t\tdie \"'$1' does not refer to a commit\"\n+\telse\n+\t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n+\tfi\n+\n \tdebug \"Splitting $dir...\"\n \tcache_setup || exit $?\n \n@@ -768,12 +754,12 @@ cmd_split () {\n \t\tdone || exit $?\n \tfi\n \n-\tunrevs=\"$(find_existing_splits \"$dir\" \"$revs\")\" || exit $?\n+\tunrevs=\"$(find_existing_splits \"$dir\" \"$rev\")\" || exit $?\n \n \t# We can't restrict rev-list to only $dir here, because some of our\n \t# parents have the $dir contents the root, and those won't match.\n \t# (and rev-list --follow doesn't seem to solve this)\n-\tgrl='git rev-list --topo-order --reverse --parents $revs $unrevs'\n+\tgrl='git rev-list --topo-order --reverse --parents $rev $unrevs'\n \trevmax=$(eval \"$grl\" | wc -l)\n \trevcount=0\n \tcreatecount=0\n@@ -820,8 +806,10 @@ cmd_split () {\n }\n \n cmd_merge () {\n-\trev=$(git rev-parse $default --revs-only \"$@\") || exit $?\n-\tensure_single_rev $rev\n+\ttest $# -eq 1 ||\n+\t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n+\trev=$(git rev-parse -q --verify \"$1^{commit}\") ||\n+\t\tdie \"'$1' does not refer to a commit\"\n \tensure_clean\n \n \tif test -n \"$arg_addmerge_squash\"\n@@ -861,9 +849,7 @@ cmd_pull () {\n \tensure_clean\n \tensure_valid_ref_format \"$2\"\n \tgit fetch \"$@\" || exit $?\n-\trevs=FETCH_HEAD\n-\tset -- $revs\n-\tcmd_merge \"$@\"\n+\tcmd_merge FETCH_HEAD\n }\n \n cmd_push () {\n-- \n2.31.1\n\n"},{"id":"423013","messageId":"20210426174525.3937858-20-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 19/30] subtree: Don't fuss with PATH","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:14Z","receivedAt":"2021-04-26T17:48:17Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nScripts needing to fuss with with adding $(git --exec-prefix) PATH\nbefore loading git-sh-setup is a thing of the past.  As far as I can\ntell, it's been a thing of the past since since Git v1.2.0 (2006-02-12),\nor more specifically, since 77cb17e940 (Exec git programs without using\nPATH, 2006-01-10).  However, it stuck around in contrib scripts and in\nthird-party scripts for long enough that it wasn't unusual to see.\n\nOriginally `git subtree` didn't fuss with PATH, but when people\n(including the original subtree author) had problems, because it was a\ncommon thing to see, it seemed that having subtree fuss with PATH was a\nreasonable solution.\n\nHere is an abridged history of fussing with PATH in subtree:\n\n  2987e6add3 (Add explicit path of git installation by 'git --exec-path', Gianluca Pacchiella, 2009-08-20)\n\n    As pointed out by documentation, the correct use of 'git-sh-setup' is\n    using $(git --exec-path) to avoid problems with not standard\n    installations.\n\n    -. git-sh-setup\n    +. $(git --exec-path)/git-sh-setup\n\n  33aaa697a2 (Improve patch to use git --exec-path: add to PATH instead, Avery Pennarun, 2009-08-26)\n\n    If you (like me) are using a modified git straight out of its source\n    directory (ie. without installing), then --exec-path isn't actually correct.\n    Add it to the PATH instead, so if it is correct, it'll work, but if it's\n    not, we fall back to the previous behaviour.\n\n    -. $(git --exec-path)/git-sh-setup\n    +PATH=$(git --exec-path):$PATH\n    +. git-sh-setup\n\n  9c632ea29c ((Hopefully) fix PATH setting for msysgit, Avery Pennarun, 2010-06-24)\n\n    Reported by Evan Shaw.  The problem is that $(git --exec-path) includes a\n    'git' binary which is incompatible with the one in /usr/bin; if you run it,\n    it gives you an error about libiconv2.dll.\n\n    +OPATH=$PATH\n     PATH=$(git --exec-path):$PATH\n     . git-sh-setup\n    +PATH=$OPATH  # apparently needed for some versions of msysgit\n\n  df2302d774 (Another fix for PATH and msysgit, Avery Pennarun, 2010-06-24)\n\n    Evan Shaw tells me the previous fix didn't work.  Let's use this one\n    instead, which he says does work.\n\n    This fix is kind of wrong because it will run the \"correct\" git-sh-setup\n    *after* the one in /usr/bin, if there is one, which could be weird if you\n    have multiple versions of git installed.  But it works on my Linux and his\n    msysgit, so it's obviously better than what we had before.\n\n    -OPATH=$PATH\n    -PATH=$(git --exec-path):$PATH\n    +PATH=$PATH:$(git --exec-path)\n     . git-sh-setup\n    -PATH=$OPATH  # apparently needed for some versions of msysgit\n\nFirst of all, I disagree with Gianluca's reading of the documentation:\n - I haven't gone back to read what the documentation said in 2009, but\n   in my reading of the 2021 documentation is that it includes \"$(git\n   --exec-path)/\" in the synopsis for illustrative purposes, not to say\n   it's the proper way.\n - After being executed by `git`, the git exec path should be the very\n   first entry in PATH, so it shouldn't matter.\n - None of the scripts that are part of git do it that way.\n\nBut secondly, the root reason for fussing with PATH seems to be that\nAvery didn't know that he needs to set GIT_EXEC_PATH if he's going to\nuse git from the source directory without installing.\n\nAnd finally, Evan's issue is clearly just a bug in msysgit.  I assume\nthat msysgit has since fixed the issue, and also msysgit has been\ndeprecated for 6 years now, so let's drop the workaround for it.\n\nSo, remove the line fussing with PATH.  However, since subtree *is* in\n'contrib/' and it might get installed in funny ways by users\nafter-the-fact, add a sanity check to the top of the script, checking\nthat it is installed correctly.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 18 ++++++++++++++++--\n 1 file changed, 16 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 3105eb8033..af636fbb43 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -5,6 +5,22 @@\n # Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com>\n #\n \n+if test -z \"$GIT_EXEC_PATH\" || test \"${PATH#\"${GIT_EXEC_PATH}:\"}\" = \"$PATH\" || ! test -f \"$GIT_EXEC_PATH/git-sh-setup\"\n+then\n+\techo >&2 'It looks like either your git installation or your'\n+\techo >&2 'git-subtree installation is broken.'\n+\techo >&2\n+\techo >&2 \"Tips:\"\n+\techo >&2 \" - If \\`git --exec-path\\` does not print the correct path to\"\n+\techo >&2 \"   your git install directory, then set the GIT_EXEC_PATH\"\n+\techo >&2 \"   environment variable to the correct directory.\"\n+\techo >&2 \" - Make sure that your \\`${0##*/}\\` file is either in your\"\n+\techo >&2 \"   PATH or in your git exec path (\\`$(git --exec-path)\\`).\"\n+\techo >&2 \" - You should run git-subtree as \\`git ${0##*/git-}\\`,\"\n+\techo >&2 \"   not as \\`${0##*/}\\`.\" >&2\n+\texit 126\n+fi\n+\n OPTS_SPEC=\"\\\n git subtree add   --prefix=<prefix> <commit>\n git subtree add   --prefix=<prefix> <repository> <ref>\n@@ -28,8 +44,6 @@ rejoin        merge the new branch back into HEAD\n squash        merge subtree changes as a single commit\n \"\n \n-PATH=$PATH:$(git --exec-path)\n-\n arg_debug=\n arg_command=\n arg_prefix=\n-- \n2.31.1\n\n"},{"id":"423014","messageId":"20210426174525.3937858-23-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 22/30] subtree: remove duplicate check","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:17Z","receivedAt":"2021-04-26T17:48:18Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\n`cmd_add` starts with a check that the directory doesn't yet exist.\nHowever, the `main` function performs the exact same check before\ncalling `cmd_add`.  So remove the check from `cmd_add`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 4 ----\n 1 file changed, 4 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 0df8d1b7d4..7fbd8481ed 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -655,10 +655,6 @@ process_split_commit () {\n }\n \n cmd_add () {\n-\tif test -e \"$dir\"\n-\tthen\n-\t\tdie \"'$dir' already exists.  Cannot add.\"\n-\tfi\n \n \tensure_clean\n \n-- \n2.31.1\n\n"},{"id":"423015","messageId":"20210426174525.3937858-29-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 28/30] subtree: allow 'split' flags to be passed to 'push'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:23Z","receivedAt":"2021-04-26T17:48:19Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\n'push' does a 'split' internally, but it doesn't pass flags through to the\n'split'.  This is silly, if you need to pass flags to 'split', then it\nmeans that you can't use 'push'!\n\nSo, have 'push' accept 'split' flags, and pass them through to 'split'.\n\nAdd tests for this by copying split's tests with minimal modification.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - In the added tests, use `test_must_fail` instead of `!`, as\n   appropriate.\n\n contrib/subtree/git-subtree.sh     |   6 +-\n contrib/subtree/git-subtree.txt    |  15 +-\n contrib/subtree/t/t7900-subtree.sh | 214 ++++++++++++++++++++++++++++-\n 3 files changed, 223 insertions(+), 12 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 74b02c69b3..1e5ac82f9b 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -33,13 +33,13 @@ h,help        show the help\n q             quiet\n d             show debug messages\n P,prefix=     the name of the subdir to split out\n- options for 'split'\n+ options for 'split' (also: 'push')\n annotate=     add a prefix to commit message of new commits\n b,branch=     create a new branch from the split subtree\n ignore-joins  ignore prior --rejoin commits\n onto=         try connecting new tree to an existing one\n rejoin        merge the new branch back into HEAD\n- options for 'add' and 'merge' (also: 'pull' and 'split --rejoin')\n+ options for 'add' and 'merge' (also: 'pull', 'split --rejoin', and 'push --rejoin')\n squash        merge subtree changes as a single commit\n m,message=    use the given message as the commit message for the merge commit\n \"\n@@ -962,7 +962,7 @@ cmd_push () {\n \t\trepository=$1\n \t\trefspec=$2\n \t\techo \"git push using: \" \"$repository\" \"$refspec\"\n-\t\tlocalrev=$(git subtree split --prefix=\"$arg_prefix\") || die\n+\t\tlocalrev=$(cmd_split) || die\n \t\tgit push \"$repository\" \"$localrev\":\"refs/heads/$refspec\"\n \telse\n \t\tdie \"'$dir' must already exist. Try 'git subtree add'.\"\ndiff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt\nindex 743e1bbc9e..1282aa705f 100644\n--- a/contrib/subtree/git-subtree.txt\n+++ b/contrib/subtree/git-subtree.txt\n@@ -137,11 +137,11 @@ OPTIONS FOR ALL COMMANDS\n \twant to manipulate.  This option is mandatory\n \tfor all commands.\n \n-OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull' AND 'split --rejoin')\n------------------------------------------------------------------\n+OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull', 'split --rejoin', AND 'push --rejoin')\n+-----------------------------------------------------------------------------------\n These options for 'add' and 'merge' may also be given to 'pull' (which\n-wraps 'merge') and 'split --rejoin' (which wraps either 'add' or\n-'merge' as appropriate).\n+wraps 'merge'), 'split --rejoin' (which wraps either 'add' or 'merge'\n+as appropriate), and 'push --rejoin' (which wraps 'split --rejoin').\n \n --squash::\n \tInstead of merging the entire history from the subtree project, produce\n@@ -173,9 +173,10 @@ subproject.\n --message=<message>::\n \tSpecify <message> as the commit message for the merge commit.\n \n-OPTIONS FOR 'split'\n--------------------\n-These options are only valid for 'split'.\n+OPTIONS FOR 'split' (ALSO: 'push')\n+----------------------------------\n+These options for 'split' may also be given to 'push' (which wraps\n+'split').\n \n --annotate=<annotation>::\n \tWhen generating synthetic history, add <annotation> as a prefix to each\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 6f1529935f..8bc0e488aa 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -5,8 +5,8 @@\n #\n test_description='Basic porcelain support for subtrees\n \n-This test verifies the basic operation of the add, pull, merge\n-and split subcommands of git subtree.\n+This test verifies the basic operation of the add, merge, split, pull,\n+and push subcommands of git subtree.\n '\n \n TEST_DIRECTORY=$(pwd)/../../../t\n@@ -589,6 +589,216 @@ test_expect_success 'push basic operation' '\n \t)\n '\n \n+test_expect_success 'push sub dir/ with --rejoin' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --rejoin ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push sub dir/ with --rejoin from scratch' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tmkdir \"sub dir\" &&\n+\t\techo file >\"sub dir\"/file &&\n+\t\tgit add \"sub dir/file\" &&\n+\t\tgit commit -m\"sub dir file\" &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --rejoin) &&\n+\t\tgit init --bare \"sub proj.git\" &&\n+\t\tgit subtree push --prefix=\"sub dir\" --rejoin ./\"sub proj.git\" from-mainline &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj.git\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push sub dir/ with --rejoin and --message' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tgit subtree push --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split & rejoin\" &&\n+\t\tsplit_hash=\"$(git rev-parse --verify HEAD^2)\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push \"sub dir\"/ with --rejoin and --squash' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" --squash FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit subtree pull --prefix=\"sub dir\" --squash ./\"sub proj\" HEAD &&\n+\t\tMAIN=$(git rev-parse --verify HEAD) &&\n+\t\tSUB=$(git -C \"sub proj\" rev-parse --verify HEAD) &&\n+\n+\t\tSPLIT=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --rejoin --squash ./\"sub proj\" from-mainline &&\n+\n+\t\ttest_must_fail git merge-base --is-ancestor $SUB HEAD &&\n+\t\ttest_must_fail git merge-base --is-ancestor $SPLIT HEAD &&\n+\t\tgit rev-list HEAD ^$MAIN >commit-list &&\n+\t\ttest_line_count = 2 commit-list &&\n+\t\ttest \"$(git rev-parse --verify HEAD:)\"           = \"$(git rev-parse --verify $MAIN:)\" &&\n+\t\ttest \"$(git rev-parse --verify HEAD:\"sub dir\")\"  = \"$(git rev-parse --verify $SPLIT:)\" &&\n+\t\ttest \"$(git rev-parse --verify HEAD^1)\"          = $MAIN &&\n+\t\ttest \"$(git rev-parse --verify HEAD^2)\"         != $SPLIT &&\n+\t\ttest \"$(git rev-parse --verify HEAD^2:)\"         = \"$(git rev-parse --verify $SPLIT:)\" &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$SPLIT'\\''\" &&\n+\t\ttest \"$SPLIT\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push \"sub dir\"/ with --branch' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'check hash of push' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\" &&\n+\t\t# Check hash of split\n+\t\tnew_hash=$(git rev-parse subproj-br^2) &&\n+\t\t(\n+\t\t\tcd ./\"sub proj\" &&\n+\t\t\tsubdir_hash=$(git rev-parse HEAD) &&\n+\t\t\ttest \"$new_hash\" = \"$subdir_hash\"\n+\t\t) &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push \"sub dir\"/ with --branch for an existing branch' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit branch subproj-br FETCH_HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push \"sub dir\"/ with --branch for an incompatible branch' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit branch init HEAD &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\ttest_must_fail git subtree push --prefix=\"sub dir\" --branch init \"./sub proj\" from-mainline\n+\t)\n+'\n+\n #\n # Validity checking\n #\n-- \n2.31.1\n\n"},{"id":"423016","messageId":"20210426174525.3937858-25-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 24/30] subtree: don't let debug and progress output clash","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:19Z","receivedAt":"2021-04-26T17:48:21Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nCurrently, debug output (triggered by passing '-d') and progress output\nstomp on each other.  The debug output is just streamed as lines to\nstderr, and the progress output is sent to stderr as '%s\\r'.  When\nwriting to a file, it is awkward to read and difficult to distinguish\nbetween the debug output and a progress line.  When writing to a\nterminal the debug lines hide progress lines.\n\nSo, when '-d' has been passed, spit out progress as 'progress: %s\\n',\ninstead of as '%s\\r', so that it can be detected, and so that the debug\nlines don't overwrite the progress when written to a terminal.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Reword the commit message to be clearer.\n - Add comments to the code.\n - Flip the `if` and `else` cases around, so that the comments\n   read better.\n\n contrib/subtree/git-subtree.sh | 22 +++++++++++++++++++++-\n 1 file changed, 21 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 441571c85a..53a1a025f5 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -67,7 +67,27 @@ debug () {\n progress () {\n \tif test -z \"$GIT_QUIET\"\n \tthen\n-\t\tprintf \"%s\\r\" \"$*\" >&2\n+\t\tif test -z \"$arg_debug\"\n+\t\tthen\n+\t\t\t# Debug mode is off.\n+\t\t\t#\n+\t\t\t# Print one progress line that we keep updating (use\n+\t\t\t# \"\\r\" to return to the beginning of the line, rather\n+\t\t\t# than \"\\n\" to start a new line).  This only really\n+\t\t\t# works when stderr is a terminal.\n+\t\t\tprintf \"%s\\r\" \"$*\" >&2\n+\t\telse\n+\t\t\t# Debug mode is on.  The `debug` function is regularly\n+\t\t\t# printing to stderr.\n+\t\t\t#\n+\t\t\t# Don't do the one-line-with-\"\\r\" thing, because on a\n+\t\t\t# terminal the debug output would overwrite and hide the\n+\t\t\t# progress output.  Add a \"progress:\" prefix to make the\n+\t\t\t# progress output and the debug output easy to\n+\t\t\t# distinguish.  This ensures maximum readability whether\n+\t\t\t# stderr is a terminal or a file.\n+\t\t\tprintf \"progress: %s\\n\" \"$*\" >&2\n+\t\tfi\n \tfi\n }\n \n-- \n2.31.1\n\n"},{"id":"423017","messageId":"20210426174525.3937858-24-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 23/30] subtree: add comments and sanity checks","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:18Z","receivedAt":"2021-04-26T17:48:21Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nFor each function in subtree, add a usage comment saying what the\narguments are, and add an `assert` checking the number of arguments.\n\nIn figuring out each thing's arguments in order to write those comments\nand assertions, it turns out that find_existing_splits is written as if\nit takes multiple 'revs', but it is in fact only ever passed a single\n'rev':\n\n\tunrevs=\"$(find_existing_splits \"$dir\" \"$rev\")\" || exit $?\n\nSo go ahead and codify that by documenting and asserting that it takes\nexactly two arguments, one dir and one rev.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Expand on the the commit message.\n - Fix capitalization in one of the comments.\n\n contrib/subtree/git-subtree.sh | 64 ++++++++++++++++++++++++++++++++--\n 1 file changed, 61 insertions(+), 3 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 7fbd8481ed..441571c85a 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -55,6 +55,7 @@ arg_split_annotate=\n arg_addmerge_squash=\n arg_addmerge_message=\n \n+# Usage: debug [MSG...]\n debug () {\n \tif test -n \"$arg_debug\"\n \tthen\n@@ -62,6 +63,7 @@ debug () {\n \tfi\n }\n \n+# Usage: progress [MSG...]\n progress () {\n \tif test -z \"$GIT_QUIET\"\n \tthen\n@@ -69,6 +71,7 @@ progress () {\n \tfi\n }\n \n+# Usage: assert CMD...\n assert () {\n \tif ! \"$@\"\n \tthen\n@@ -192,7 +195,9 @@ main () {\n \t\"cmd_$arg_command\" \"$@\"\n }\n \n+# Usage: cache_setup\n cache_setup () {\n+\tassert test $# = 0\n \tcachedir=\"$GIT_DIR/subtree-cache/$$\"\n \trm -rf \"$cachedir\" ||\n \t\tdie \"Can't delete old cachedir: $cachedir\"\n@@ -203,6 +208,7 @@ cache_setup () {\n \tdebug \"Using cachedir: $cachedir\" >&2\n }\n \n+# Usage: cache_get [REVS...]\n cache_get () {\n \tfor oldrev in \"$@\"\n \tdo\n@@ -214,6 +220,7 @@ cache_get () {\n \tdone\n }\n \n+# Usage: cache_miss [REVS...]\n cache_miss () {\n \tfor oldrev in \"$@\"\n \tdo\n@@ -224,7 +231,9 @@ cache_miss () {\n \tdone\n }\n \n+# Usage: check_parents PARENTS_EXPR INDENT\n check_parents () {\n+\tassert test $# = 2\n \tmissed=$(cache_miss \"$1\") || exit $?\n \tlocal indent=$(($2 + 1))\n \tfor miss in $missed\n@@ -237,11 +246,15 @@ check_parents () {\n \tdone\n }\n \n+# Usage: set_notree REV\n set_notree () {\n+\tassert test $# = 1\n \techo \"1\" > \"$cachedir/notree/$1\"\n }\n \n+# Usage: cache_set OLDREV NEWREV\n cache_set () {\n+\tassert test $# = 2\n \toldrev=\"$1\"\n \tnewrev=\"$2\"\n \tif test \"$oldrev\" != \"latest_old\" &&\n@@ -253,7 +266,9 @@ cache_set () {\n \techo \"$newrev\" >\"$cachedir/$oldrev\"\n }\n \n+# Usage: rev_exists REV\n rev_exists () {\n+\tassert test $# = 1\n \tif git rev-parse \"$1\" >/dev/null 2>&1\n \tthen\n \t\treturn 0\n@@ -262,17 +277,22 @@ rev_exists () {\n \tfi\n }\n \n-# if a commit doesn't have a parent, this might not work.  But we only want\n+# Usage: try_remove_previous REV\n+#\n+# If a commit doesn't have a parent, this might not work.  But we only want\n # to remove the parent from the rev-list, and since it doesn't exist, it won't\n # be there anyway, so do nothing in that case.\n try_remove_previous () {\n+\tassert test $# = 1\n \tif rev_exists \"$1^\"\n \tthen\n \t\techo \"^$1^\"\n \tfi\n }\n \n+# Usage: find_latest_squash DIR\n find_latest_squash () {\n+\tassert test $# = 1\n \tdebug \"Looking for latest squash ($dir)...\"\n \tdir=\"$1\"\n \tsq=\n@@ -316,10 +336,12 @@ find_latest_squash () {\n \tdone || exit $?\n }\n \n+# Usage: find_existing_splits DIR REV\n find_existing_splits () {\n+\tassert test $# = 2\n \tdebug \"Looking for prior splits...\"\n \tdir=\"$1\"\n-\trevs=\"$2\"\n+\trev=\"$2\"\n \tmain=\n \tsub=\n \tlocal grep_format=\"^git-subtree-dir: $dir/*\\$\"\n@@ -328,7 +350,7 @@ find_existing_splits () {\n \t\tgrep_format=\"^Add '$dir/' from commit '\"\n \tfi\n \tgit log --grep=\"$grep_format\" \\\n-\t\t--no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' $revs |\n+\t\t--no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' \"$rev\" |\n \twhile read a b junk\n \tdo\n \t\tcase \"$a\" in\n@@ -365,7 +387,9 @@ find_existing_splits () {\n \tdone || exit $?\n }\n \n+# Usage: copy_commit REV TREE FLAGS_STR\n copy_commit () {\n+\tassert test $# = 3\n \t# We're going to set some environment vars here, so\n \t# do it in a subshell to get rid of them safely later\n \tdebug copy_commit \"{$1}\" \"{$2}\" \"{$3}\"\n@@ -391,7 +415,9 @@ copy_commit () {\n \t) || die \"Can't copy commit $1\"\n }\n \n+# Usage: add_msg DIR LATEST_OLD LATEST_NEW\n add_msg () {\n+\tassert test $# = 3\n \tdir=\"$1\"\n \tlatest_old=\"$2\"\n \tlatest_new=\"$3\"\n@@ -410,7 +436,9 @@ add_msg () {\n \tEOF\n }\n \n+# Usage: add_squashed_msg REV DIR\n add_squashed_msg () {\n+\tassert test $# = 2\n \tif test -n \"$arg_addmerge_message\"\n \tthen\n \t\techo \"$arg_addmerge_message\"\n@@ -419,7 +447,9 @@ add_squashed_msg () {\n \tfi\n }\n \n+# Usage: rejoin_msg DIR LATEST_OLD LATEST_NEW\n rejoin_msg () {\n+\tassert test $# = 3\n \tdir=\"$1\"\n \tlatest_old=\"$2\"\n \tlatest_new=\"$3\"\n@@ -438,7 +468,9 @@ rejoin_msg () {\n \tEOF\n }\n \n+# Usage: squash_msg DIR OLD_SUBTREE_COMMIT NEW_SUBTREE_COMMIT\n squash_msg () {\n+\tassert test $# = 3\n \tdir=\"$1\"\n \toldsub=\"$2\"\n \tnewsub=\"$3\"\n@@ -460,12 +492,16 @@ squash_msg () {\n \techo \"git-subtree-split: $newsub\"\n }\n \n+# Usage: toptree_for_commit COMMIT\n toptree_for_commit () {\n+\tassert test $# = 1\n \tcommit=\"$1\"\n \tgit rev-parse --verify \"$commit^{tree}\" || exit $?\n }\n \n+# Usage: subtree_for_commit COMMIT DIR\n subtree_for_commit () {\n+\tassert test $# = 2\n \tcommit=\"$1\"\n \tdir=\"$2\"\n \tgit ls-tree \"$commit\" -- \"$dir\" |\n@@ -479,7 +515,9 @@ subtree_for_commit () {\n \tdone || exit $?\n }\n \n+# Usage: tree_changed TREE [PARENTS...]\n tree_changed () {\n+\tassert test $# -gt 0\n \ttree=$1\n \tshift\n \tif test $# -ne 1\n@@ -496,7 +534,9 @@ tree_changed () {\n \tfi\n }\n \n+# Usage: new_squash_commit OLD_SQUASHED_COMMIT OLD_NONSQUASHED_COMMIT NEW_NONSQUASHED_COMMIT\n new_squash_commit () {\n+\tassert test $# = 3\n \told=\"$1\"\n \toldsub=\"$2\"\n \tnewsub=\"$3\"\n@@ -511,7 +551,9 @@ new_squash_commit () {\n \tfi\n }\n \n+# Usage: copy_or_skip REV TREE NEWPARENTS\n copy_or_skip () {\n+\tassert test $# = 3\n \trev=\"$1\"\n \ttree=\"$2\"\n \tnewparents=\"$3\"\n@@ -586,7 +628,9 @@ copy_or_skip () {\n \tfi\n }\n \n+# Usage: ensure_clean\n ensure_clean () {\n+\tassert test $# = 0\n \tif ! git diff-index HEAD --exit-code --quiet 2>&1\n \tthen\n \t\tdie \"Working tree has modifications.  Cannot add.\"\n@@ -597,12 +641,16 @@ ensure_clean () {\n \tfi\n }\n \n+# Usage: ensure_valid_ref_format REF\n ensure_valid_ref_format () {\n+\tassert test $# = 1\n \tgit check-ref-format \"refs/heads/$1\" ||\n \t\tdie \"'$1' does not look like a ref\"\n }\n \n+# Usage: process_split_commit REV PARENTS INDENT\n process_split_commit () {\n+\tassert test $# = 3\n \tlocal rev=\"$1\"\n \tlocal parents=\"$2\"\n \tlocal indent=$3\n@@ -654,6 +702,8 @@ process_split_commit () {\n \tcache_set latest_old \"$rev\"\n }\n \n+# Usage: cmd_add REV\n+#    Or: cmd_add REPOSITORY REF\n cmd_add () {\n \n \tensure_clean\n@@ -681,7 +731,9 @@ cmd_add () {\n \tfi\n }\n \n+# Usage: cmd_add_repository REPOSITORY REFSPEC\n cmd_add_repository () {\n+\tassert test $# = 2\n \techo \"git fetch\" \"$@\"\n \trepository=$1\n \trefspec=$2\n@@ -689,9 +741,11 @@ cmd_add_repository () {\n \tcmd_add_commit FETCH_HEAD\n }\n \n+# Usage: cmd_add_commit REV\n cmd_add_commit () {\n \t# The rev has already been validated by cmd_add(), we just\n \t# need to normalize it.\n+\tassert test $# = 1\n \trev=$(git rev-parse --verify \"$1^{commit}\") || exit $?\n \n \tdebug \"Adding $dir as '$rev'...\"\n@@ -722,6 +776,7 @@ cmd_add_commit () {\n \tsay >&2 \"Added dir '$dir'\"\n }\n \n+# Usage: cmd_split [REV]\n cmd_split () {\n \tif test $# -eq 0\n \tthen\n@@ -801,6 +856,7 @@ cmd_split () {\n \texit 0\n }\n \n+# Usage: cmd_merge REV\n cmd_merge () {\n \ttest $# -eq 1 ||\n \t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n@@ -837,6 +893,7 @@ cmd_merge () {\n \tfi\n }\n \n+# Usage: cmd_pull REPOSITORY REMOTEREF\n cmd_pull () {\n \tif test $# -ne 2\n \tthen\n@@ -848,6 +905,7 @@ cmd_pull () {\n \tcmd_merge FETCH_HEAD\n }\n \n+# Usage: cmd_push REPOSITORY REMOTEREF\n cmd_push () {\n \tif test $# -ne 2\n \tthen\n-- \n2.31.1\n\n"},{"id":"423018","messageId":"20210426174525.3937858-31-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 30/30] subtree: be stricter about validating flags","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:25Z","receivedAt":"2021-04-26T17:48:49Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nDon't silently ignore a flag that's invalid for a given subcommand.  The\nuser expected it to do something; we should tell the user that they are\nmistaken, instead of surprising the user.\n\nIt could be argued that this change might break existing users.  I'd\nargue that those existing users are already broken, and they just don't\nknow it.  Let them know that they're broken.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh     |  89 ++++++++++++++++-------\n contrib/subtree/t/t7900-subtree.sh | 111 +++++++++++++++++++++++++++++\n 2 files changed, 175 insertions(+), 25 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 678dd1dc19..1fd3c287dd 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -44,17 +44,6 @@ squash        merge subtree changes as a single commit\n m,message=    use the given message as the commit message for the merge commit\n \"\n \n-arg_debug=\n-arg_command=\n-arg_prefix=\n-arg_split_branch=\n-arg_split_onto=\n-arg_split_rejoin=\n-arg_split_ignore_joins=\n-arg_split_annotate=\n-arg_addmerge_squash=\n-arg_addmerge_message=\n-\n indent=0\n \n # Usage: debug [MSG...]\n@@ -106,10 +95,61 @@ main () {\n \tthen\n \t\tset -- -h\n \tfi\n-\teval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n+\tset_args=\"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n+\teval \"$set_args\"\n \t. git-sh-setup\n \trequire_work_tree\n \n+\t# First figure out the command and whether we use --rejoin, so\n+\t# that we can provide more helpful validation when we do the\n+\t# \"real\" flag parsing.\n+\targ_split_rejoin=\n+\tallow_split=\n+\tallow_addmerge=\n+\twhile test $# -gt 0\n+\tdo\n+\t\topt=\"$1\"\n+\t\tshift\n+\t\tcase \"$opt\" in\n+\t\t\t--annotate|-b|-P|-m|--onto)\n+\t\t\t\tshift\n+\t\t\t\t;;\n+\t\t\t--rejoin)\n+\t\t\t\targ_split_rejoin=1\n+\t\t\t\t;;\n+\t\t\t--no-rejoin)\n+\t\t\t\targ_split_rejoin=\n+\t\t\t\t;;\n+\t\t\t--)\n+\t\t\t\tbreak\n+\t\t\t\t;;\n+\t\tesac\n+\tdone\n+\targ_command=$1\n+\tcase \"$arg_command\" in\n+\tadd|merge|pull)\n+\t\tallow_addmerge=1\n+\t\t;;\n+\tsplit|push)\n+\t\tallow_split=1\n+\t\tallow_addmerge=$arg_split_rejoin\n+\t\t;;\n+\t*)\n+\t\tdie \"Unknown command '$arg_command'\"\n+\t\t;;\n+\tesac\n+\t# Reset the arguments array for \"real\" flag parsing.\n+\teval \"$set_args\"\n+\n+\t# Begin \"real\" flag parsing.\n+\targ_debug=\n+\targ_prefix=\n+\targ_split_branch=\n+\targ_split_onto=\n+\targ_split_ignore_joins=\n+\targ_split_annotate=\n+\targ_addmerge_squash=\n+\targ_addmerge_message=\n \twhile test $# -gt 0\n \tdo\n \t\topt=\"$1\"\n@@ -123,13 +163,16 @@ main () {\n \t\t\targ_debug=1\n \t\t\t;;\n \t\t--annotate)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_annotate=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-annotate)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_annotate=\n \t\t\t;;\n \t\t-b)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_branch=\"$1\"\n \t\t\tshift\n \t\t\t;;\n@@ -138,6 +181,7 @@ main () {\n \t\t\tshift\n \t\t\t;;\n \t\t-m)\n+\t\t\ttest -n \"$allow_addmerge\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_addmerge_message=\"$1\"\n \t\t\tshift\n \t\t\t;;\n@@ -145,28 +189,34 @@ main () {\n \t\t\targ_prefix=\n \t\t\t;;\n \t\t--onto)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_onto=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-onto)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_onto=\n \t\t\t;;\n \t\t--rejoin)\n-\t\t\targ_split_rejoin=1\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\t;;\n \t\t--no-rejoin)\n-\t\t\targ_split_rejoin=\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\t;;\n \t\t--ignore-joins)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_ignore_joins=1\n \t\t\t;;\n \t\t--no-ignore-joins)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_ignore_joins=\n \t\t\t;;\n \t\t--squash)\n+\t\t\ttest -n \"$allow_addmerge\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_addmerge_squash=1\n \t\t\t;;\n \t\t--no-squash)\n+\t\t\ttest -n \"$allow_addmerge\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_addmerge_squash=\n \t\t\t;;\n \t\t--)\n@@ -177,19 +227,8 @@ main () {\n \t\t\t;;\n \t\tesac\n \tdone\n-\n-\targ_command=\"$1\"\n \tshift\n \n-\tcase \"$arg_command\" in\n-\tadd|merge|pull|split|push)\n-\t\t:\n-\t\t;;\n-\t*)\n-\t\tdie \"Unknown command '$arg_command'\"\n-\t\t;;\n-\tesac\n-\n \tif test -z \"$arg_prefix\"\n \tthen\n \t\tdie \"You must provide the --prefix option.\"\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 8a3530305e..6348c13c5c 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -33,6 +33,12 @@ test_create_commit () (\n \tgit commit -m \"$commit\" || error \"Could not commit\"\n )\n \n+test_wrong_flag() {\n+\ttest_must_fail \"$@\" >out 2>err &&\n+\ttest_must_be_empty out &&\n+\tgrep \"flag does not make sense with\" err\n+}\n+\n last_commit_subject () {\n \tgit log --pretty=format:%s -1\n }\n@@ -72,6 +78,22 @@ test_expect_success 'no pull from non-existent subtree' '\n \t)\n '\n \n+test_expect_success 'add rejects flags for split' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --annotate=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --branch=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --ignore-joins FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --onto=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --rejoin FETCH_HEAD\n+\t)\n+'\n+\n test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n@@ -128,6 +150,28 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n # Tests for 'git subtree merge'\n #\n \n+test_expect_success 'merge rejects flags for split' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --annotate=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --branch=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --ignore-joins FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --onto=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --rejoin FETCH_HEAD\n+\t)\n+'\n+\n test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n@@ -262,6 +306,30 @@ test_expect_success 'split requires path given by option --prefix must exist' '\n \t)\n '\n \n+test_expect_success 'split rejects flags for add' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\ttest_wrong_flag git subtree split --prefix=\"sub dir\" --squash &&\n+\t\ttest_wrong_flag git subtree split --prefix=\"sub dir\" --message=foo\n+\t)\n+'\n+\n test_expect_success 'split sub dir/ with --rejoin' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n@@ -521,6 +589,26 @@ test_expect_success 'pull basic operation' '\n \t)\n '\n \n+test_expect_success 'pull rejects flags for split' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --annotate=foo ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --branch=foo ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --ignore-joins ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --onto=foo ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --rejoin ./\"sub proj\" HEAD\n+\t)\n+'\n+\n #\n # Tests for 'git subtree push'\n #\n@@ -563,6 +651,29 @@ test_expect_success 'push requires path given by option --prefix must exist' '\n \t)\n '\n \n+test_expect_success 'push rejects flags for add' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree split --prefix=\"sub dir\" --squash ./\"sub proj\" from-mainline &&\n+\t\ttest_wrong_flag git subtree split --prefix=\"sub dir\" --message=foo ./\"sub proj\" from-mainline\n+\t)\n+'\n+\n test_expect_success 'push basic operation' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n-- \n2.31.1\n\n"},{"id":"423020","messageId":"20210426174525.3937858-30-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 29/30] subtree: push: allow specifying a local rev other than HEAD","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:24Z","receivedAt":"2021-04-26T17:48:49Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\n'git subtree split' lets you specify a rev other than HEAD.  'git push'\nlets you specify a mapping between a local thing and a remot ref.  So\nsmash those together, and have 'git subtree push' let you specify which\nlocal thing to run split on and push the result of that split to the\nremote ref.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh     | 24 +++++++++++++++++-------\n contrib/subtree/git-subtree.txt    | 14 ++++++++------\n contrib/subtree/t/t7900-subtree.sh | 22 ++++++++++++++++++++++\n 3 files changed, 47 insertions(+), 13 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 1e5ac82f9b..678dd1dc19 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -27,7 +27,7 @@ git subtree add   --prefix=<prefix> <repository> <ref>\n git subtree merge --prefix=<prefix> <commit>\n git subtree split --prefix=<prefix> [<commit>]\n git subtree pull  --prefix=<prefix> <repository> <ref>\n-git subtree push  --prefix=<prefix> <repository> <ref>\n+git subtree push  --prefix=<prefix> <repository> <refspec>\n --\n h,help        show the help\n q             quiet\n@@ -950,20 +950,30 @@ cmd_pull () {\n \tcmd_merge FETCH_HEAD\n }\n \n-# Usage: cmd_push REPOSITORY REMOTEREF\n+# Usage: cmd_push REPOSITORY [+][LOCALREV:]REMOTEREF\n cmd_push () {\n \tif test $# -ne 2\n \tthen\n-\t\tdie \"You must provide <repository> <ref>\"\n+\t\tdie \"You must provide <repository> <refspec>\"\n \tfi\n-\tensure_valid_ref_format \"$2\"\n \tif test -e \"$dir\"\n \tthen\n \t\trepository=$1\n-\t\trefspec=$2\n+\t\trefspec=${2#+}\n+\t\tremoteref=${refspec#*:}\n+\t\tif test \"$remoteref\" = \"$refspec\"\n+\t\tthen\n+\t\t\tlocalrevname_presplit=HEAD\n+\t\telse\n+\t\t\tlocalrevname_presplit=${refspec%%:*}\n+\t\tfi\n+\t\tensure_valid_ref_format \"$remoteref\"\n+\t\tlocalrev_presplit=$(git rev-parse -q --verify \"$localrevname_presplit^{commit}\") ||\n+\t\t\tdie \"'$localrevname_presplit' does not refer to a commit\"\n+\n \t\techo \"git push using: \" \"$repository\" \"$refspec\"\n-\t\tlocalrev=$(cmd_split) || die\n-\t\tgit push \"$repository\" \"$localrev\":\"refs/heads/$refspec\"\n+\t\tlocalrev=$(cmd_split \"$localrev_presplit\") || die\n+\t\tgit push \"$repository\" \"$localrev\":\"refs/heads/$remoteref\"\n \telse\n \t\tdie \"'$dir' must already exist. Try 'git subtree add'.\"\n \tfi\ndiff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt\nindex 1282aa705f..559b64aa96 100644\n--- a/contrib/subtree/git-subtree.txt\n+++ b/contrib/subtree/git-subtree.txt\n@@ -16,7 +16,7 @@ SYNOPSIS\n \n [verse]\n 'git subtree' [<options>] -P <prefix> pull <repository> <remote-ref>\n-'git subtree' [<options>] -P <prefix> push <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> push <repository> <refspec>\n \n DESCRIPTION\n -----------\n@@ -115,11 +115,13 @@ pull <repository> <remote-ref>::\n \tit fetches the given ref from the specified remote\n \trepository.\n \n-push <repository> <remote-ref>::\n-\tDoes a 'split' using the <prefix> subtree of HEAD and then\n-\tdoes a 'git push' to push the result to the <repository> and\n-\t<remote-ref>.  This can be used to push your subtree to\n-\tdifferent branches of the remote repository.\n+push <repository> [+][<local-commit>:]<remote-ref>::\n+\tDoes a 'split' using the <prefix> subtree of <local-commit>\n+\tand then does a 'git push' to push the result to the\n+\t<repository> and <remote-ref>.  This can be used to push your\n+\tsubtree to different branches of the remote repository.  Just\n+\tas with 'split', if no <local-commit> is given, then HEAD is\n+\tused.  The optional leading '+' is ignored.\n \n OPTIONS FOR ALL COMMANDS\n ------------------------\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 8bc0e488aa..8a3530305e 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -799,6 +799,28 @@ test_expect_success 'push \"sub dir\"/ with --branch for an incompatible branch' '\n \t)\n '\n \n+test_expect_success 'push \"sub dir\"/ with a local rev' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tbad_tree=$(git rev-parse --verify HEAD:\"sub dir\") &&\n+\t\tgood_tree=$(git rev-parse --verify HEAD^:\"sub dir\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" ./\"sub proj\" HEAD^:from-mainline &&\n+\t\tsplit_tree=$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline:) &&\n+\t\ttest \"$split_tree\" = \"$good_tree\"\n+\t)\n+'\n+\n #\n # Validity checking\n #\n-- \n2.31.1\n\n"},{"id":"423019","messageId":"20210426174525.3937858-26-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 25/30] subtree: have $indent actually affect indentation","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:20Z","receivedAt":"2021-04-26T17:48:51Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nCurrently, the $indent variable is just used to track how deeply we're\nnested, and the debug log is indented by things like\n\n   debug \"  foo\"\n\nThat is: The indentation-level is hard-coded.  It used to be that the\ncode couldn't recurse, so the indentation level could be known\nstatically, so it made sense to just hard-code it in the\noutput. However, since 315a84f9aa (\"subtree: use commits before rejoins\nfor splits\", 2018-09-28), it can now recurse, and the debug log is\nmisleading.\n\nSo fix that.  Indent according to $indent.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 42 +++++++++++++++++++---------------\n 1 file changed, 24 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 53a1a025f5..768fa7b6b6 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -55,11 +55,13 @@ arg_split_annotate=\n arg_addmerge_squash=\n arg_addmerge_message=\n \n+indent=0\n+\n # Usage: debug [MSG...]\n debug () {\n \tif test -n \"$arg_debug\"\n \tthen\n-\t\tprintf \"%s\\n\" \"$*\" >&2\n+\t\tprintf \"%$(($indent * 2))s%s\\n\" '' \"$*\" >&2\n \tfi\n }\n \n@@ -251,17 +253,17 @@ cache_miss () {\n \tdone\n }\n \n-# Usage: check_parents PARENTS_EXPR INDENT\n+# Usage: check_parents PARENTS_EXPR\n check_parents () {\n-\tassert test $# = 2\n+\tassert test $# = 1\n \tmissed=$(cache_miss \"$1\") || exit $?\n-\tlocal indent=$(($2 + 1))\n+\tlocal indent=$(($indent + 1))\n \tfor miss in $missed\n \tdo\n \t\tif ! test -r \"$cachedir/notree/$miss\"\n \t\tthen\n-\t\t\tdebug \"  incorrect order: $miss\"\n-\t\t\tprocess_split_commit \"$miss\" \"\" \"$indent\"\n+\t\t\tdebug \"incorrect order: $miss\"\n+\t\t\tprocess_split_commit \"$miss\" \"\"\n \t\tfi\n \tdone\n }\n@@ -314,6 +316,8 @@ try_remove_previous () {\n find_latest_squash () {\n \tassert test $# = 1\n \tdebug \"Looking for latest squash ($dir)...\"\n+\tlocal indent=$(($indent + 1))\n+\n \tdir=\"$1\"\n \tsq=\n \tmain=\n@@ -360,6 +364,8 @@ find_latest_squash () {\n find_existing_splits () {\n \tassert test $# = 2\n \tdebug \"Looking for prior splits...\"\n+\tlocal indent=$(($indent + 1))\n+\n \tdir=\"$1\"\n \trev=\"$2\"\n \tmain=\n@@ -385,7 +391,7 @@ find_existing_splits () {\n \t\t\tdie \"could not rev-parse split hash $b from commit $sq\"\n \t\t\t;;\n \t\tEND)\n-\t\t\tdebug \"  Main is: '$main'\"\n+\t\t\tdebug \"Main is: '$main'\"\n \t\t\tif test -z \"$main\" -a -n \"$sub\"\n \t\t\tthen\n \t\t\t\t# squash commits refer to a subtree\n@@ -668,12 +674,11 @@ ensure_valid_ref_format () {\n \t\tdie \"'$1' does not look like a ref\"\n }\n \n-# Usage: process_split_commit REV PARENTS INDENT\n+# Usage: process_split_commit REV PARENTS\n process_split_commit () {\n-\tassert test $# = 3\n+\tassert test $# = 2\n \tlocal rev=\"$1\"\n \tlocal parents=\"$2\"\n-\tlocal indent=$3\n \n \tif test $indent -eq 0\n \tthen\n@@ -688,20 +693,21 @@ process_split_commit () {\n \tprogress \"$revcount/$revmax ($createcount) [$extracount]\"\n \n \tdebug \"Processing commit: $rev\"\n+\tlocal indent=$(($indent + 1))\n \texists=$(cache_get \"$rev\") || exit $?\n \tif test -n \"$exists\"\n \tthen\n-\t\tdebug \"  prior: $exists\"\n+\t\tdebug \"prior: $exists\"\n \t\treturn\n \tfi\n \tcreatecount=$(($createcount + 1))\n-\tdebug \"  parents: $parents\"\n-\tcheck_parents \"$parents\" \"$indent\"\n+\tdebug \"parents: $parents\"\n+\tcheck_parents \"$parents\"\n \tnewparents=$(cache_get $parents) || exit $?\n-\tdebug \"  newparents: $newparents\"\n+\tdebug \"newparents: $newparents\"\n \n \ttree=$(subtree_for_commit \"$rev\" \"$dir\") || exit $?\n-\tdebug \"  tree is: $tree\"\n+\tdebug \"tree is: $tree\"\n \n \t# ugly.  is there no better way to tell if this is a subtree\n \t# vs. a mainline commit?  Does it matter?\n@@ -716,7 +722,7 @@ process_split_commit () {\n \tfi\n \n \tnewrev=$(copy_or_skip \"$rev\" \"$tree\" \"$newparents\") || exit $?\n-\tdebug \"  newrev is: $newrev\"\n+\tdebug \"newrev is: $newrev\"\n \tcache_set \"$rev\" \"$newrev\"\n \tcache_set latest_new \"$newrev\"\n \tcache_set latest_old \"$rev\"\n@@ -820,7 +826,7 @@ cmd_split () {\n \t\tdo\n \t\t\t# the 'onto' history is already just the subdir, so\n \t\t\t# any parent we find there can be used verbatim\n-\t\t\tdebug \"  cache: $rev\"\n+\t\t\tdebug \"cache: $rev\"\n \t\t\tcache_set \"$rev\" \"$rev\"\n \t\tdone || exit $?\n \tfi\n@@ -838,7 +844,7 @@ cmd_split () {\n \teval \"$grl\" |\n \twhile read rev parents\n \tdo\n-\t\tprocess_split_commit \"$rev\" \"$parents\" 0\n+\t\tprocess_split_commit \"$rev\" \"$parents\"\n \tdone || exit $?\n \n \tlatest_new=$(cache_get latest_new) || exit $?\n-- \n2.31.1\n\n"},{"id":"423021","messageId":"20210426174525.3937858-28-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 27/30] subtree: allow --squash to be used with --rejoin","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:22Z","receivedAt":"2021-04-26T17:48:51Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nBesides being a genuinely useful thing to do, this also just makes sense\nand harmonizes which flags may be used when.  `git subtree split\n--rejoin` amounts to \"automatically go ahead and do a `git subtree\nmerge` after doing the main `git subtree split`\", so it's weird and\narbitrary that you can't pass `--squash` to `git subtree split --rejoin`\nlike you can `git subtree merge`.  It's weird that `git subtree split\n--rejoin` inherits `git subtree merge`'s `--message` but not `--squash`.\n\nReconcile the situation by just having `split --rejoin` actually just\ncall `merge` internally (or call `add` instead, as appropriate), so it\ncan get access to the full `merge` behavior, including `--squash`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - In the added tests, use `test_must_fail` instead of `!`, as\n   appropriate.\n\n contrib/subtree/git-subtree.sh     | 33 ++++++++++++++++++++++------\n contrib/subtree/git-subtree.txt    | 27 ++++++++++-------------\n contrib/subtree/t/t7900-subtree.sh | 35 ++++++++++++++++++++++++++++++\n 3 files changed, 72 insertions(+), 23 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 3bffddf277..74b02c69b3 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -33,15 +33,15 @@ h,help        show the help\n q             quiet\n d             show debug messages\n P,prefix=     the name of the subdir to split out\n-m,message=    use the given message as the commit message for the merge commit\n  options for 'split'\n annotate=     add a prefix to commit message of new commits\n b,branch=     create a new branch from the split subtree\n ignore-joins  ignore prior --rejoin commits\n onto=         try connecting new tree to an existing one\n rejoin        merge the new branch back into HEAD\n- options for 'add' and 'merge' (also: 'pull')\n+ options for 'add' and 'merge' (also: 'pull' and 'split --rejoin')\n squash        merge subtree changes as a single commit\n+m,message=    use the given message as the commit message for the merge commit\n \"\n \n arg_debug=\n@@ -453,6 +453,13 @@ add_msg () {\n \telse\n \t\tcommit_message=\"Add '$dir/' from commit '$latest_new'\"\n \tfi\n+\tif test -n \"$arg_split_rejoin\"\n+\tthen\n+\t\t# If this is from a --rejoin, then rejoin_msg has\n+\t\t# already inserted the `git-subtree-xxx:` tags\n+\t\techo \"$commit_message\"\n+\t\treturn\n+\tfi\n \tcat <<-EOF\n \t\t$commit_message\n \n@@ -775,7 +782,12 @@ cmd_add_commit () {\n \trev=$(git rev-parse --verify \"$1^{commit}\") || exit $?\n \n \tdebug \"Adding $dir as '$rev'...\"\n-\tgit read-tree --prefix=\"$dir\" $rev || exit $?\n+\tif test -z \"$arg_split_rejoin\"\n+\tthen\n+\t\t# Only bother doing this if this is a genuine 'add',\n+\t\t# not a synthetic 'add' from '--rejoin'.\n+\t\tgit read-tree --prefix=\"$dir\" $rev || exit $?\n+\tfi\n \tgit checkout -- \"$dir\" || exit $?\n \ttree=$(git write-tree) || exit $?\n \n@@ -815,6 +827,11 @@ cmd_split () {\n \t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n \tfi\n \n+\tif test -n \"$arg_split_rejoin\"\n+\tthen\n+\t\tensure_clean\n+\tfi\n+\n \tdebug \"Splitting $dir...\"\n \tcache_setup || exit $?\n \n@@ -857,10 +874,12 @@ cmd_split () {\n \tthen\n \t\tdebug \"Merging split branch into HEAD...\"\n \t\tlatest_old=$(cache_get latest_old) || exit $?\n-\t\tgit merge -s ours \\\n-\t\t\t--allow-unrelated-histories \\\n-\t\t\t-m \"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" \\\n-\t\t\t\"$latest_new\" >&2 || exit $?\n+\t\targ_addmerge_message=\"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" || exit $?\n+\t\tif test -z \"$(find_latest_squash \"$dir\")\"; then\n+\t\t\tcmd_add \"$latest_new\" >&2 || exit $?\n+\t\telse\n+\t\t\tcmd_merge \"$latest_new\" >&2 || exit $?\n+\t\tfi\n \tfi\n \tif test -n \"$arg_split_branch\"\n \tthen\ndiff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt\nindex 7baac17260..743e1bbc9e 100644\n--- a/contrib/subtree/git-subtree.txt\n+++ b/contrib/subtree/git-subtree.txt\n@@ -109,9 +109,6 @@ settings passed to 'split' (such as '--annotate') are the same.\n Because of this, if you add new commits and then re-split, the new\n commits will be attached as commits on top of the history you\n generated last time, so 'git merge' and friends will work as expected.\n-+\n-Note that if you use '--squash' when you merge, you should usually not\n-just '--rejoin' when you split.\n \n pull <repository> <remote-ref>::\n \tExactly like 'merge', but parallels 'git pull' in that\n@@ -124,8 +121,8 @@ push <repository> <remote-ref>::\n \t<remote-ref>.  This can be used to push your subtree to\n \tdifferent branches of the remote repository.\n \n-OPTIONS\n--------\n+OPTIONS FOR ALL COMMANDS\n+------------------------\n -q::\n --quiet::\n \tSuppress unnecessary output messages on stderr.\n@@ -140,15 +137,11 @@ OPTIONS\n \twant to manipulate.  This option is mandatory\n \tfor all commands.\n \n--m <message>::\n---message=<message>::\n-\tThis option is only valid for 'add', 'merge', 'pull', and 'split --rejoin'.\n-\tSpecify <message> as the commit message for the merge commit.\n-\n-OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull')\n---------------------------------------------\n+OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull' AND 'split --rejoin')\n+-----------------------------------------------------------------\n These options for 'add' and 'merge' may also be given to 'pull' (which\n-wraps 'merge').\n+wraps 'merge') and 'split --rejoin' (which wraps either 'add' or\n+'merge' as appropriate).\n \n --squash::\n \tInstead of merging the entire history from the subtree project, produce\n@@ -176,6 +169,9 @@ Whether or not you use '--squash', changes made in your local repository\n remain intact and can be later split and send upstream to the\n subproject.\n \n+-m <message>::\n+--message=<message>::\n+\tSpecify <message> as the commit message for the merge commit.\n \n OPTIONS FOR 'split'\n -------------------\n@@ -229,9 +225,8 @@ Unfortunately, using this option results in 'git log' showing an extra\n copy of every new commit that was created (the original, and the\n synthetic one).\n +\n-If you do all your merges with '--squash', don't use '--rejoin' when you\n-split, because you don't want the subproject's history to be part of\n-your project anyway.\n+If you do all your merges with '--squash', make sure you also use\n+'--squash' when you 'split --rejoin'.\n \n \n EXAMPLE 1. 'add' command\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex ce6861c22d..6f1529935f 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -324,6 +324,41 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \t)\n '\n \n+test_expect_success 'split \"sub dir\"/ with --rejoin and --squash' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" --squash FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit subtree pull --prefix=\"sub dir\" --squash ./\"sub proj\" HEAD &&\n+\t\tMAIN=$(git rev-parse --verify HEAD) &&\n+\t\tSUB=$(git -C \"sub proj\" rev-parse --verify HEAD) &&\n+\n+\t\tSPLIT=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin --squash) &&\n+\n+\t\ttest_must_fail git merge-base --is-ancestor $SUB HEAD &&\n+\t\ttest_must_fail git merge-base --is-ancestor $SPLIT HEAD &&\n+\t\tgit rev-list HEAD ^$MAIN >commit-list &&\n+\t\ttest_line_count = 2 commit-list &&\n+\t\ttest \"$(git rev-parse --verify HEAD:)\"           = \"$(git rev-parse --verify $MAIN:)\" &&\n+\t\ttest \"$(git rev-parse --verify HEAD:\"sub dir\")\"  = \"$(git rev-parse --verify $SPLIT:)\" &&\n+\t\ttest \"$(git rev-parse --verify HEAD^1)\"          = $MAIN &&\n+\t\ttest \"$(git rev-parse --verify HEAD^2)\"         != $SPLIT &&\n+\t\ttest \"$(git rev-parse --verify HEAD^2:)\"         = \"$(git rev-parse --verify $SPLIT:)\" &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$SPLIT'\\''\"\n+\t)\n+'\n+\n test_expect_success 'split \"sub dir\"/ with --branch' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n-- \n2.31.1\n\n"},{"id":"423022","messageId":"20210426174525.3937858-27-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v2 26/30] subtree: give the docs a once-over","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T17:45:21Z","receivedAt":"2021-04-26T17:48:53Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nJust went through the docs looking for anything inaccurate or that can\nbe improved.\n\nIn the '-h' text, in the man page synopsis, and in the man page\ndescription: Normalize the ordering of the list of sub-commands: 'add',\n'merge', 'split', 'pull', 'push'.  This allows us to kinda separate the\nlower-level add/merge/split from the higher-level pull/push.\n\n'-h' text:\n - correction: Indicate that split's arg is optional.\n - clarity: Emphasize that 'pull' takes the 'add'/'merge' flags.\n\nman page:\n\n - correction: State that all subcommands take options (it seemed to\n   indicate that only 'split' takes any options other than '-P').\n - correction: 'split' only guarantees that the results are identical if\n   the flags are identical.\n - completeness: Clarify that 'push' always operates on HEAD, and that\n   'split' operates on HEAD if no local commit is given.\n - clarity: In the description, when listing commands, repeat what their\n   arguments are.  This way the reader doesn't need to flip back and\n   forth between the command description and the synopsis and the full\n   description to understand what's being said.\n - clarity: In the <variables> used to give command arguments, give\n   slightly longer, descriptive names.  Like <local-commit> instead of\n   just <commit>.\n - clarity: Emphasize that 'pull' takes the 'add'/'merge' flags.\n - style: In the synopsis, list options before the subcommand.  This\n   makes things line up and be much more readable when shown\n   non-monospace (such as in `make html`), and also more closely matches\n   other man pages (like `git-submodule.txt`).\n - style: Use the correct syntax for indicating the options ([<options>]\n   instead of [OPTIONS]).\n - style: In the synopsis, separate 'pull' and 'push' from the other\n   lower-level commands.  I think this helps readability.\n - style: Code-quote things in prose that seem like they should be\n   code-quoted, like '.gitmodules', flags, or full commands.\n - style: Minor wording improvements, like more consistent mood (many\n   of the command descriptions start in the imperative mood and switch\n   to the indicative mode by the end).  That sort of thing.\n - style: Capitalize \"ID\".\n - style: Remove the \"This option is only valid for XXX command\" remarks\n   from each option, and instead rely on the section headings.\n - style: Since that line is getting edited anyway, switch \"behaviour\" to\n   American \"behavior\".\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - behaviour -> behavior\n\n contrib/subtree/git-subtree.sh  |   4 +-\n contrib/subtree/git-subtree.txt | 162 +++++++++++++++-----------------\n 2 files changed, 80 insertions(+), 86 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 768fa7b6b6..3bffddf277 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -25,9 +25,9 @@ OPTS_SPEC=\"\\\n git subtree add   --prefix=<prefix> <commit>\n git subtree add   --prefix=<prefix> <repository> <ref>\n git subtree merge --prefix=<prefix> <commit>\n+git subtree split --prefix=<prefix> [<commit>]\n git subtree pull  --prefix=<prefix> <repository> <ref>\n git subtree push  --prefix=<prefix> <repository> <ref>\n-git subtree split --prefix=<prefix> <commit>\n --\n h,help        show the help\n q             quiet\n@@ -40,7 +40,7 @@ b,branch=     create a new branch from the split subtree\n ignore-joins  ignore prior --rejoin commits\n onto=         try connecting new tree to an existing one\n rejoin        merge the new branch back into HEAD\n- options for 'add', 'merge', and 'pull'\n+ options for 'add' and 'merge' (also: 'pull')\n squash        merge subtree changes as a single commit\n \"\n \ndiff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt\nindex 0db02fe3c0..7baac17260 100644\n--- a/contrib/subtree/git-subtree.txt\n+++ b/contrib/subtree/git-subtree.txt\n@@ -9,13 +9,14 @@ git-subtree - Merge subtrees together and split repository into subtrees\n SYNOPSIS\n --------\n [verse]\n-'git subtree' add   -P <prefix> <commit>\n-'git subtree' add   -P <prefix> <repository> <ref>\n-'git subtree' pull  -P <prefix> <repository> <ref>\n-'git subtree' push  -P <prefix> <repository> <ref>\n-'git subtree' merge -P <prefix> <commit>\n-'git subtree' split -P <prefix> [OPTIONS] [<commit>]\n+'git subtree' [<options>] -P <prefix> add <local-commit>\n+'git subtree' [<options>] -P <prefix> add <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> merge <local-commit>\n+'git subtree' [<options>] -P <prefix> split [<local-commit>]\n \n+[verse]\n+'git subtree' [<options>] -P <prefix> pull <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> push <repository> <remote-ref>\n \n DESCRIPTION\n -----------\n@@ -28,7 +29,7 @@ as a subdirectory of your application.\n \n Subtrees are not to be confused with submodules, which are meant for\n the same task. Unlike submodules, subtrees do not need any special\n-constructions (like .gitmodules files or gitlinks) be present in\n+constructions (like '.gitmodules' files or gitlinks) be present in\n your repository, and do not force end-users of your\n repository to do anything special or to understand how subtrees\n work. A subtree is just a subdirectory that can be\n@@ -59,27 +60,28 @@ project as much as possible.  That is, if you make a change that\n affects both the library and the main application, commit it in\n two pieces.  That way, when you split the library commits out\n later, their descriptions will still make sense.  But if this\n-isn't important to you, it's not *necessary*.  git subtree will\n+isn't important to you, it's not *necessary*.  'git subtree' will\n simply leave out the non-library-related parts of the commit\n when it splits it out into the subproject later.\n \n \n COMMANDS\n --------\n-add::\n+add <local-commit>::\n+add <repository> <remote-ref>::\n \tCreate the <prefix> subtree by importing its contents\n-\tfrom the given <commit> or <repository> and remote <ref>.\n+\tfrom the given <local-commit> or <repository> and <remote-ref>.\n \tA new commit is created\tautomatically, joining the imported\n-\tproject's history with your own.  With '--squash', imports\n+\tproject's history with your own.  With '--squash', import\n \tonly a single commit from the subproject, rather than its\n \tentire history.\n \n-merge::\n-\tMerge recent changes up to <commit> into the <prefix>\n+merge <local-commit>::\n+\tMerge recent changes up to <local-commit> into the <prefix>\n \tsubtree.  As with normal 'git merge', this doesn't\n \tremove your own local changes; it just merges those\n-\tchanges into the latest <commit>.  With '--squash',\n-\tcreates only one commit that contains all the changes,\n+\tchanges into the latest <local-commit>.  With '--squash',\n+\tcreate only one commit that contains all the changes,\n \trather than merging in the entire history.\n +\n If you use '--squash', the merge direction doesn't always have to be\n@@ -87,39 +89,40 @@ forward; you can use this command to go back in time from v2.5 to v2.4,\n for example.  If your merge introduces a conflict, you can resolve it in\n the usual ways.\n \t\n-pull::\n-\tExactly like 'merge', but parallels 'git pull' in that\n-\tit fetches the given ref from the specified remote\n-\trepository.\n-\t\n-push::\n-\tDoes a 'split' (see below) using the <prefix> supplied\n-\tand then does a 'git push' to push the result to the \n-\trepository and ref. This can be used to push your\n-\tsubtree to different branches of the remote repository.\n-\n-split::\n+split [<local-commit>]::\n \tExtract a new, synthetic project history from the\n-\thistory of the <prefix> subtree.  The new history\n+\thistory of the <prefix> subtree of <local-commit>, or of\n+\tHEAD if no <local-commit> is given.  The new history\n \tincludes only the commits (including merges) that\n \taffected <prefix>, and each of those commits now has the\n \tcontents of <prefix> at the root of the project instead\n \tof in a subdirectory.  Thus, the newly created history\n \tis suitable for export as a separate git repository.\n +\n-After splitting successfully, a single commit id is printed to stdout.\n+After splitting successfully, a single commit ID is printed to stdout.\n This corresponds to the HEAD of the newly created tree, which you can\n manipulate however you want.\n +\n Repeated splits of exactly the same history are guaranteed to be\n-identical (i.e. to produce the same commit ids).  Because of this, if\n-you add new commits and then re-split, the new commits will be attached\n-as commits on top of the history you generated last time, so 'git merge'\n-and friends will work as expected.\n+identical (i.e. to produce the same commit IDs) as long as the\n+settings passed to 'split' (such as '--annotate') are the same.\n+Because of this, if you add new commits and then re-split, the new\n+commits will be attached as commits on top of the history you\n+generated last time, so 'git merge' and friends will work as expected.\n +\n Note that if you use '--squash' when you merge, you should usually not\n just '--rejoin' when you split.\n \n+pull <repository> <remote-ref>::\n+\tExactly like 'merge', but parallels 'git pull' in that\n+\tit fetches the given ref from the specified remote\n+\trepository.\n+\n+push <repository> <remote-ref>::\n+\tDoes a 'split' using the <prefix> subtree of HEAD and then\n+\tdoes a 'git push' to push the result to the <repository> and\n+\t<remote-ref>.  This can be used to push your subtree to\n+\tdifferent branches of the remote repository.\n \n OPTIONS\n -------\n@@ -139,19 +142,18 @@ OPTIONS\n \n -m <message>::\n --message=<message>::\n-\tThis option is only valid for add, merge, pull, and split --rejoin.\n+\tThis option is only valid for 'add', 'merge', 'pull', and 'split --rejoin'.\n \tSpecify <message> as the commit message for the merge commit.\n \n+OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull')\n+--------------------------------------------\n+These options for 'add' and 'merge' may also be given to 'pull' (which\n+wraps 'merge').\n \n-OPTIONS FOR add, merge, and pull\n---------------------------------\n --squash::\n-\tThis option is only valid for add, merge, and pull\n-\tcommands.\n-+\n-Instead of merging the entire history from the subtree project, produce\n-only a single commit that contains all the differences you want to\n-merge, and then merge that new commit into your project.\n+\tInstead of merging the entire history from the subtree project, produce\n+\tonly a single commit that contains all the differences you want to\n+\tmerge, and then merge that new commit into your project.\n +\n Using this option helps to reduce log clutter. People rarely want to see\n every change that happened between v1.0 and v1.1 of the library they're\n@@ -175,56 +177,48 @@ remain intact and can be later split and send upstream to the\n subproject.\n \n \n-OPTIONS FOR split\n------------------\n+OPTIONS FOR 'split'\n+-------------------\n+These options are only valid for 'split'.\n+\n --annotate=<annotation>::\n-\tThis option is only valid for the split command.\n-+\n-When generating synthetic history, add <annotation> as a prefix to each\n-commit message.  Since we're creating new commits with the same commit\n-message, but possibly different content, from the original commits, this\n-can help to differentiate them and avoid confusion.\n+\tWhen generating synthetic history, add <annotation> as a prefix to each\n+\tcommit message.  Since we're creating new commits with the same commit\n+\tmessage, but possibly different content, from the original commits, this\n+\tcan help to differentiate them and avoid confusion.\n +\n Whenever you split, you need to use the same <annotation>, or else you\n don't have a guarantee that the new re-created history will be identical\n to the old one.  That will prevent merging from working correctly.  git\n-subtree tries to make it work anyway, particularly if you use --rejoin,\n+subtree tries to make it work anyway, particularly if you use '--rejoin',\n but it may not always be effective.\n \n -b <branch>::\n --branch=<branch>::\n-\tThis option is only valid for the split command.\n-+\n-After generating the synthetic history, create a new branch called\n-<branch> that contains the new history.  This is suitable for immediate\n-pushing upstream.  <branch> must not already exist.\n+\tAfter generating the synthetic history, create a new branch called\n+\t<branch> that contains the new history.  This is suitable for immediate\n+\tpushing upstream.  <branch> must not already exist.\n \n --ignore-joins::\n-\tThis option is only valid for the split command.\n-+\n-If you use '--rejoin', git subtree attempts to optimize its history\n-reconstruction to generate only the new commits since the last\n-'--rejoin'.  '--ignore-join' disables this behaviour, forcing it to\n-regenerate the entire history.  In a large project, this can take a long\n-time.\n+\tIf you use '--rejoin', git subtree attempts to optimize its history\n+\treconstruction to generate only the new commits since the last\n+\t'--rejoin'.  '--ignore-join' disables this behavior, forcing it to\n+\tregenerate the entire history.  In a large project, this can take a long\n+\ttime.\n \n --onto=<onto>::\n-\tThis option is only valid for the split command.\n-+\n-If your subtree was originally imported using something other than git\n-subtree, its history may not match what git subtree is expecting.  In\n-that case, you can specify the commit id <onto> that corresponds to the\n-first revision of the subproject's history that was imported into your\n-project, and git subtree will attempt to build its history from there.\n+\tIf your subtree was originally imported using something other than git\n+\tsubtree, its history may not match what git subtree is expecting.  In\n+\tthat case, you can specify the commit ID <onto> that corresponds to the\n+\tfirst revision of the subproject's history that was imported into your\n+\tproject, and git subtree will attempt to build its history from there.\n +\n If you used 'git subtree add', you should never need this option.\n \n --rejoin::\n-\tThis option is only valid for the split command.\n-+\n-After splitting, merge the newly created synthetic history back into\n-your main project.  That way, future splits can search only the part of\n-history that has been added since the most recent --rejoin.\n+\tAfter splitting, merge the newly created synthetic history back into\n+\tyour main project.  That way, future splits can search only the part of\n+\thistory that has been added since the most recent '--rejoin'.\n +\n If your split commits end up merged into the upstream subproject, and\n then you want to get the latest upstream version, this will allow git's\n@@ -240,8 +234,8 @@ split, because you don't want the subproject's history to be part of\n your project anyway.\n \n \n-EXAMPLE 1. Add command\n-----------------------\n+EXAMPLE 1. 'add' command\n+------------------------\n Let's assume that you have a local repository that you would like\n to add an external vendor library to. In this case we will add the\n git-subtree repository as a subdirectory of your already existing\n@@ -253,15 +247,15 @@ git-extensions repository in ~/git-extensions/:\n 'master' needs to be a valid remote ref and can be a different branch\n name\n \n-You can omit the --squash flag, but doing so will increase the number\n+You can omit the '--squash' flag, but doing so will increase the number\n of commits that are included in your local repository.\n \n We now have a ~/git-extensions/git-subtree directory containing code\n from the master branch of git://github.com/apenwarr/git-subtree.git\n in our git-extensions repository.\n \n-EXAMPLE 2. Extract a subtree using commit, merge and pull\n----------------------------------------------------------\n+EXAMPLE 2. Extract a subtree using 'commit', 'merge' and 'pull'\n+---------------------------------------------------------------\n Let's use the repository for the git source code as an example.\n First, get your own copy of the git.git repository:\n \n@@ -284,9 +278,9 @@ the upstream.  You could do this:\n 0a8f4f0 to the current version, including 0a8f4f0 itself.\")\n \n If gitweb had originally been merged using 'git subtree add' (or\n-a previous split had already been done with --rejoin specified)\n+a previous split had already been done with '--rejoin' specified)\n then you can do all your splits without having to remember any\n-weird commit ids:\n+weird commit IDs:\n \n \t$ git subtree split --prefix=gitweb --annotate='(split) ' --rejoin \\\n \t\t--branch gitweb-latest2\n@@ -321,8 +315,8 @@ the standard gitweb:\n \n \tgit log gitweb-latest..$(git subtree split --prefix=gitweb)\n \n-EXAMPLE 3. Extract a subtree using branch\n------------------------------------------\n+EXAMPLE 3. Extract a subtree using a branch\n+-------------------------------------------\n Suppose you have a source directory with many files and\n subdirectories, and you want to extract the lib directory to its own\n git project. Here's a short way to do it:\n-- \n2.31.1\n\n"},{"id":"423031","messageId":"87o8e0akeb.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-5-lukeshu@lukeshu.com","subject":"Re: [PATCH v2 04/30] subtree: t7900: use consistent formatting","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T19:57:48Z","receivedAt":"2021-04-26T19:57:53Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Mon, 26 Apr 2021 11:44:59 -0600,\nLuke Shumaker wrote:\n> @@ -50,15 +46,17 @@ undo()\n>  # The original set of commits changed only one file each.\n>  # A multi-file change would imply that we pruned commits\n>  # too aggressively.\n> -join_commits()\n> -{\n> +join_commits () {\n>  \tcommit=\n>  \tall=\n>  \twhile read x y; do\n> -\t\tif [ -z \"$x\" ]; then\n> +\t\tif test -z \"$x\"\n> +\t\tthen\n>  \t\t\tcontinue\n> -\t\telif [ \"$x\" = \"commit:\" ]; then\n> -\t\t\tif [ -n \"$commit\" ]; then\n> +\t\telif test \"$x\" = \"commit:\"\n> +\t\tthen\n> +\t\t\tif test -n \"$commit\"\n> +\t\t\tthen\n>  \t\t\t\techo \"$commit $all\"\n>  \t\t\t\tall=\n>  \t\t\tfi\n\nWhoops, I should have changed those 1-line `while ...; do`'s, in\naddition to the 1-line `if ...; then`'s.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"423032","messageId":"87mttkakcp.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-28-lukeshu@lukeshu.com","subject":"Re: [PATCH v2 27/30] subtree: allow --squash to be used with --rejoin","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T19:58:46Z","receivedAt":"2021-04-26T19:58:49Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Mon, 26 Apr 2021 11:45:22 -0600,\nLuke Shumaker wrote:\n> @@ -857,10 +874,12 @@ cmd_split () {\n>  \tthen\n>  \t\tdebug \"Merging split branch into HEAD...\"\n>  \t\tlatest_old=$(cache_get latest_old) || exit $?\n> -\t\tgit merge -s ours \\\n> -\t\t\t--allow-unrelated-histories \\\n> -\t\t\t-m \"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" \\\n> -\t\t\t\"$latest_new\" >&2 || exit $?\n> +\t\targ_addmerge_message=\"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" || exit $?\n> +\t\tif test -z \"$(find_latest_squash \"$dir\")\"; then\n> +\t\t\tcmd_add \"$latest_new\" >&2 || exit $?\n> +\t\telse\n> +\t\t\tcmd_merge \"$latest_new\" >&2 || exit $?\n> +\t\tfi\n>  \tfi\n>  \tif test -n \"$arg_split_branch\"\n>  \tthen\n\nWhoops, that `if ...; then` should put the `then` on its own line.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"423049","messageId":"87lf94ab7c.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-20-lukeshu@lukeshu.com","subject":"Re: [PATCH v2 19/30] subtree: Don't fuss with PATH","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-26T23:16:23Z","receivedAt":"2021-04-26T23:16:42Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Mon, 26 Apr 2021 11:45:14 -0600,\nLuke Shumaker wrote:\n> Subject: [PATCH v2 19/30] subtree: Don't fuss with PATH\n\nWhoops, I shouldn't have capitalized \"Don't\".\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"423061","messageId":"xmqqpmygdwml.fsf@gitster.g","threadId":"55548","inReplyTo":"CAPig+cT=jZdq=oDSHRF6DnvqZVo4OiPGy7x7AzTzdcy6RV76kw@mail.gmail.com","subject":"Re: [PATCH 04/30] subtree: t7900: use consistent formatting","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-04-27T07:17:38Z","receivedAt":"2021-04-27T07:17:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Sunshine <sunshine@sunshineco.com> writes:\n\n>> +check_equal () {\n>>         test_debug 'echo'\n>>         test_debug \"echo \\\"check a:\\\" \\\"{$1}\\\"\"\n>>         test_debug \"echo \\\"      b:\\\" \\\"{$2}\\\"\"\n>> -       if [ \"$1\" = \"$2\" ]; then\n>> +       if [ \"$1\" = \"$2\" ]\n>> +       then\n>\n> We prefer `test` over `[`, so it might make sense to update that, as\n> well, along with these other style cleanups.\n\nIf I were working on this, I wouldn't bother.\n\nAs far as I am concerned, contrib/subtree has always been treated as\na borrowed code [*] that is written in a dialect of shell that is\ndifferent from what our scripts are written in, and there are too\nmany style differences (I wouldn't call them violations---nobody has\nexpected the code there to follow our style, or attempted to enforce\nour style there) to bother coercing.\n\nIf Luke is volunteering to take over its maintainership, it would be\nappreciated by its users.  It has been in the \"abandonware\" status\nfor too long.\n\n\n[Footnote]\n\n* ... as opposed to a properly maintained part of the git-core\n  proper.\n"},{"id":"423063","messageId":"xmqqlf94dw5e.fsf@gitster.g","threadId":"55548","inReplyTo":"87wnss2219.wl-lukeshu@lukeshu.com","subject":"Re: [PATCH 00/30] subtree: clean up, improve UX","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-04-27T07:27:57Z","receivedAt":"2021-04-27T07:28:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Luke Shumaker <lukeshu@lukeshu.com> writes:\n\n> On Fri, 23 Apr 2021 13:42:00 -0600,\n> Luke Shumaker wrote:\n>>                                                  I promise that\n>> there's more work coming on top of it (we've discovered lots of ways\n>> to break the \"subtree split\" algorithm, and come up with fixes for\n>> most of them).\n>\n> Follow-up question: If in that work I changed the shebang from\n> \"#!/bin/sh\" to \"#!/usr/bin/env bash\" and started using Bash arrays,\n> would that be so bad?  Would that be land-able?\n\nI'd rather see \"git subtree\" tool taken out of my tree and flourish\nas a standalone project of its own.\n\nOver its long history, from time to time people stepped in only to\nscratch their own itch and then went away.  Without having continued\npresense of an area expert (or two) who can give consistent guidance\nto the tool's evolution, I feel that Git project itself failed to\ngive sufficient service to users of \"git subtree\".\n\nAs I won't be that area expert, and we do not seem to be growing\nsuch an area expert who can be responsible for the tool in the long\nhaul, it probably is a disservice to its users to keep it in my tree\nand pretend that it is maintained to the same degree as the rest of\nGit.\n\nIf those who are interested and/or have stake in the \"git subtree\"\ntool can unite and take its development in their hands, with their\nown style, that might be better for the health of the \"git subtree\"\ntool in the long run.\n\nThanks.\n\n\n\n"},{"id":"423129","messageId":"87k0ona2a5.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"xmqqpmygdwml.fsf@gitster.g","subject":"Re: [PATCH 04/30] subtree: t7900: use consistent formatting","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T20:41:22Z","receivedAt":"2021-04-27T20:41:34Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Tue, 27 Apr 2021 01:17:38 -0600,\nJunio C Hamano wrote:\n> \n> Eric Sunshine <sunshine@sunshineco.com> writes:\n> \n> >> +check_equal () {\n> >>         test_debug 'echo'\n> >>         test_debug \"echo \\\"check a:\\\" \\\"{$1}\\\"\"\n> >>         test_debug \"echo \\\"      b:\\\" \\\"{$2}\\\"\"\n> >> -       if [ \"$1\" = \"$2\" ]; then\n> >> +       if [ \"$1\" = \"$2\" ]\n> >> +       then\n> >\n> > We prefer `test` over `[`, so it might make sense to update that, as\n> > well, along with these other style cleanups.\n> \n> If I were working on this, I wouldn't bother.\n\nIn this case, it's not just about consistency with git-core, it's\nabout consistency within contrib/subtree; there were just 2 or 3\nplaces where it used `[` instead of `test`.\n\n> If Luke is volunteering to take over its maintainership, it would be\n> appreciated by its users.  It has been in the \"abandonware\" status\n> for too long.\n\nI think I am volunteering.\n\nWe have been using git-subtree increasingly heavily at Ambassador Labs\n(née Datawire) for about 2 years now, and I don't see that changing.\nWhat I'm doing now is trying to get >2 years of accumulated patches in\nto a submittable state (a lot of the patches were bad; for instance on\nmy main branch `git subtree add` is broken, but that's fine, because\nyou don't use `add` all the time like you do `split` or `merge`, but\nthat's something I need to fix before submitting it).  Assuming that\nwe're going to continue being heavy users of it, and are going to\ncontinue to patch issues with it, I'd rather let that live upstream\nrather than telling all of my coworkers to get it from\n<https://github.com/LukeShu/git>.\n\nWith a recent change in project scheduling, I anticipate that I'll\nhave bandwidth to be able to handle that.  (It's what's giving me\nadequate time to work through this pile of existing patches, anyway.)\n\nWhat does being a maintainer consist of?  Are there standups that I\nshould join?\n\n> As far as I am concerned, contrib/subtree has always been treated as\n> a borrowed code [*] that is written in a dialect of shell that is\n> different from what our scripts are written in, and there are too\n> many style differences (I wouldn't call them violations---nobody has\n> expected the code there to follow our style, or attempted to enforce\n> our style there) to bother coercing.\n> \n> [Footnote]\n> \n> * ... as opposed to a properly maintained part of the git-core\n>   proper.\n\nElsewhere in the thread, you suggested that subtree be taken out of\ngit.git, and live as a standalone project.\n\nI'm not entirely opposed to that, but\n\n 1. I'm not sure how whoever picks it up (me) establishes their\n    git-subtree as the \"real\" subtree (get a blessing from Avery?).\n\n 2. I think a lot of the reason why more people don't use git-subtree\n    is that the core 'split' operation doesn't quite work reliably\n    (and also it can be quite slow), and so it doesn't get\n    recommended.  I would like nothing more than to improve the\n    'split' reliability to where it does start to gain adoption, to\n    where we can think about it graduating from contrib/ to git-core.\n\n 3. Many systems (Arch Linux and macOS, at least) give users\n    git-subtree as part of the stock Git install.  If I'm interested\n    in growing git-subtree adoption, I'd be a fool to give that up :)\n\nOn the other hand, I think that in the long-ish term git-subtree wants\nto be rewritten in a better-suited language.  My personal inclination\nwould be Go, but if I ever want it to graduate to git-core, it'd have\nto be C, huh?\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"423131","messageId":"20210427211748.2607474-1-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210426174525.3937858-1-lukeshu@lukeshu.com","subject":"[PATCH v3 00/30] subtree: clean up, improve UX","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:18Z","receivedAt":"2021-04-27T21:18:25Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThe diff between v1 and v2 is largely stylistic.  The only\nnon-stylistic changes are fixing the tests to use `test_must_fail`\ninstead of `!`, and re-thinking the commit about fussing with PATH.\n\nThe diff between v2 and v3 contains a few stylistic changes, but the\nmeat of it is that it fixes a bug with `--squash` and `--rejoin` being\nused together, and that it fixes a mistake in the man page.\n\nOstensibly, this patch set is about improving various aspects of `git\nsubtree`'s user interface (and it is!), but it's also mostly about\nsetting the foundation and being \"batch 1\" of a bunch more changes to\nsubtree that I'm getting queued up.  So please forgive the large\namount of churn in the leading clean-up commits, I promise that\nthere's more work coming on top of it (we've discovered lots of ways\nto break the \"subtree split\" algorithm, and come up with fixes for\nmost of them).  In the mean-time, I do think that the UX improvements\nin this patchset are already worth it themselves.\n\n - The first 11 commits improve subtree's tests, largely around the\n   code-quality of the tests, but a few of the commits do actually\n   improve what's being tested.\n\n - The middle 12 commits improve the code-quality of subtree's\n   implementation.\n\n - The final 7 commits improve various aspects of subtree's user\n   experience, from readability of the debug output, to documentation,\n   to option flag handling.\n\nThe very last commit is likely to be a little objectionable--it makes\nsome option flag parsing more strict, so there will probably be worry\nthat the change breaks existing users.  However, it's being strict\nabout arg combinations that were always invalid, the difference is\nthat now it reports that to the users and bails.  Those users were\nalready broken, they just didn't know it.  `git subtree` should tell\nthem.\n\nLuke Shumaker (30):\n  .gitignore: Ignore /git-subtree\n  subtree: t7900: update for having the default branch name be 'main'\n  subtree: t7900: use test-lib.sh's test_count\n  subtree: t7900: use consistent formatting\n    v2:\n     - Also normalize on `test X` instead of `[ X ]`.\n     - Also normalize on `>FILENAME` with no spaces.\n     - Fix a few if statements with `if` and `then` on the same line\n       that I missed in v1.\n    v3:\n     - Consistently put the `do` of a loop on its own line.\n  subtree: t7900: comment subtree_test_create_repo\n    v2:\n     - Also switch the few uses of vanilla test_create_repo over to\n       subtree_test_create_repo.  In v1 this was erroneously included\n       in a different commit.\n  subtree: t7900: use 'test' for string equality\n  subtree: t7900: delete some dead code\n  subtree: t7900: fix 'verify one file change per commit'\n    v2:\n     - Fix whitespace.\n  subtree: t7900: rename last_commit_message to last_commit_subject\n  subtree: t7900: add a test for the -h flag\n  subtree: t7900: add porcelain tests for 'pull' and 'push'\n    v2:\n     - Don't switch unrelated uses of vanilla test_create_repo over to\n       subtree_test_create_repo; this has been moved to happen in an\n       earlier commit.\n     - Fix whitespace.\n  subtree: don't have loose code outside of a function\n    v2:\n     - Include rationale in the the commit message.\n  subtree: more consistent error propagation\n  subtree: drop support for git < 1.7\n    v2:\n     - Include rationale in the the commit message.\n  subtree: use `git merge-base --is-ancestor`\n  subtree: use git-sh-setup's `say`\n  subtree: use more explicit variable names for cmdline args\n  subtree: use \"$*\" instead of \"$@\" as appropriate\n    v2:\n     - Improve the commit message with quoting and clearer\n       explanation.\n  subtree: don't fuss with PATH\n    v2:\n     - This commit changed entirely.  In v1 it changed how git-subtree\n       adjusts the PATH.  In v2, it removes any fussing with the PATH,\n       and in its place adds a pre-flight sanity check that it doesn't\n       need to fuss with the PATH.\n    v3:\n     - Fix capitalization in the commit message.\n  subtree: use \"^{commit}\" instead of \"^0\"\n  subtree: parse revs in individual cmd_ functions\n  subtree: remove duplicate check\n  subtree: add comments and sanity checks\n    v2:\n     - Expand on the the commit message.\n     - Fix capitalization in one of the comments.\n  subtree: don't let debug and progress output clash\n    v2:\n     - Reword the commit message to be clearer.\n     - Add comments to the code.\n     - Flip the `if` and `else` cases around, so that the comments\n       read better.\n  subtree: have $indent actually affect indentation\n  subtree: give the docs a once-over\n    v2:\n     - behaviour -> behavior\n    v3:\n     - Trim trailing whitespace.\n     - Fix the man page saying \"--ignore-join\" instead of \"--ignore-joins\".\n  subtree: allow --squash to be used with --rejoin\n    v2:\n     - In the added tests, use `test_must_fail` instead of `!`, as\n       appropriate.\n    v3:\n     - Style: Put the `then` of an `if/then` on its own line.\n     - Fix a bug (and add a test) where the resulting commits confuse a\n       subsequent `git subtree merge --squash`.\n  subtree: allow 'split' flags to be passed to 'push'\n    v2:\n     - In the added tests, use `test_must_fail` instead of `!`, as\n       appropriate.\n  subtree: push: allow specifying a local rev other than HEAD\n  subtree: be stricter about validating flags\n\n .gitignore                         |    1 +\n contrib/subtree/git-subtree.sh     |  642 +++++++-----\n contrib/subtree/git-subtree.txt    |  192 ++--\n contrib/subtree/t/t7900-subtree.sh | 1450 ++++++++++++++++++----------\n contrib/subtree/todo               |    6 +-\n 5 files changed, 1425 insertions(+), 866 deletions(-)\n\n-- \n2.31.1\n\nHappy hacking,\n~ Luke Shumaker\n"},{"id":"423132","messageId":"20210427211748.2607474-2-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 01/30] .gitignore: Ignore /git-subtree","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:19Z","receivedAt":"2021-04-27T21:18:26Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nRunning `make -C contrib/subtree/ test` creates a `git-subtree` executable\nin the root of the repo.  Add it to the .gitignore so that anyone hacking\non subtree won't have to deal with that noise.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n .gitignore | 1 +\n 1 file changed, 1 insertion(+)\n\ndiff --git a/.gitignore b/.gitignore\nindex 3dcdb6bb5a..a203678e9e 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -162,6 +162,7 @@\n /git-stripspace\n /git-submodule\n /git-submodule--helper\n+/git-subtree\n /git-svn\n /git-switch\n /git-symbolic-ref\n-- \n2.31.1\n\n"},{"id":"423133","messageId":"20210427211748.2607474-3-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 02/30] subtree: t7900: update for having the default branch name be 'main'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:20Z","receivedAt":"2021-04-27T21:18:30Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nMost of the tests had been converted to support\n`GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main`, but `contrib/subtree/t/`\nhadn't.\n\nConvert it.  Most of the mentions of 'master' can just be replaced with\n'HEAD'.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 117 +++++++++++++++--------------\n 1 file changed, 59 insertions(+), 58 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 57ff4b25c1..4b982e6c2e 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -103,7 +103,7 @@ test_expect_success 'no merge from non-existent subtree' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\ttest_must_fail git subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t)\n '\n@@ -116,8 +116,8 @@ test_expect_success 'no pull from non-existent subtree' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n-\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" master\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD\n \t)'\n \n next_test\n@@ -128,7 +128,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n@@ -142,7 +142,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --me\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n \t)\n@@ -156,7 +156,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P an\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add -P \"sub dir\" -m \"Added subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n \t)\n@@ -170,7 +170,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject with squash\" --squash FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject with squash\"\n \t)\n@@ -188,13 +188,13 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n@@ -208,13 +208,13 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix and -\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject\"\n \t)\n@@ -228,13 +228,13 @@ test_expect_success 'merge new subproj history into sub dir/ with --squash and -\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject using squash\" --squash FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject using squash\"\n \t)\n@@ -248,7 +248,7 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\t# this shouldn not actually do anything, since FETCH_HEAD\n \t\t# is already a parent\n@@ -265,13 +265,13 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende\n \ttest_create_commit \"$test_count/subproj\" sub1 &&\n \t(\n \t\tcd \"$test_count\" &&\n-\t\tgit fetch ./subproj master &&\n+\t\tgit fetch ./subproj HEAD &&\n \t\tgit subtree add --prefix=subdir/ FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$test_count/subproj\" sub2 &&\n \t(\n \t\tcd \"$test_count\" &&\n-\t\tgit fetch ./subproj master &&\n+\t\tgit fetch ./subproj HEAD &&\n \t\tgit subtree merge --prefix=subdir/ FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n@@ -289,7 +289,7 @@ test_expect_success 'split requires option --prefix' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\techo \"You must provide the --prefix option.\" > expected &&\n \t\ttest_must_fail git subtree split > actual 2>&1 &&\n@@ -309,7 +309,7 @@ test_expect_success 'split requires path given by option --prefix must exist' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" > expected &&\n \t\ttest_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 &&\n@@ -329,7 +329,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -338,7 +338,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin &&\n@@ -370,7 +370,7 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -379,7 +379,7 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Split & rejoin\"\n@@ -394,7 +394,7 @@ test_expect_success 'split \"sub dir\"/ with --branch' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -403,7 +403,7 @@ test_expect_success 'split \"sub dir\"/ with --branch' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n@@ -419,7 +419,7 @@ test_expect_success 'check hash of split' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -428,7 +428,7 @@ test_expect_success 'check hash of split' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n@@ -451,7 +451,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch subproj-br FETCH_HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n@@ -461,7 +461,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n@@ -478,7 +478,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n \t(\n \t\tcd \"$subtree_test_count\" &&\n \t\tgit branch init HEAD &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -487,7 +487,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\ttest_must_fail git subtree split --prefix=\"sub dir\" --branch init\n \t)\n@@ -505,7 +505,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the sub\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -514,7 +514,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the sub\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -555,7 +555,7 @@ test_expect_success 'make sure the subproj *only* contains commits that affect t\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -564,7 +564,7 @@ test_expect_success 'make sure the subproj *only* contains commits that affect t\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -606,7 +606,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -615,7 +615,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -643,7 +643,7 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai\n \t) &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" master &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\ttest_write_lines main1 main2 >chkm &&\n \t\ttest_write_lines main-sub1 main-sub2 main-sub3 main-sub4 >chkms &&\n@@ -666,7 +666,7 @@ test_expect_success 'make sure each filename changed exactly once in the entire\n \t(\n \t\tcd \"$subtree_test_count\" &&\n \t\tgit config log.date relative &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -675,7 +675,7 @@ test_expect_success 'make sure each filename changed exactly once in the entire\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -703,7 +703,7 @@ test_expect_success 'make sure each filename changed exactly once in the entire\n \t) &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" master &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\ttest_write_lines main1 main2 >chkm &&\n \t\ttest_write_lines sub1 sub2 sub3 sub4 >chks &&\n@@ -731,7 +731,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -740,7 +740,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -768,7 +768,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'\n \t) &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" master &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \t\tcheck_equal \"$(git log --pretty=format:\"%s\" HEAD^2 | grep -i split)\" \"\"\n \t)\n '\n@@ -781,7 +781,7 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -790,7 +790,7 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n@@ -818,7 +818,7 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n \t) &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" master &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\t# They are meaningless to subproj since one side of the merge refers to the mainline\n \t\tcheck_equal \"$(git log --pretty=format:\"%s%n%b\" HEAD^2 | grep \"git-subtree.*:\")\" \"\"\n@@ -837,13 +837,13 @@ test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch subproj-ref FETCH_HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n@@ -853,7 +853,7 @@ test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n \t\tgit subtree split --prefix=\"sub dir\" --branch subproj-br &&\n \n \t\t# at this point, the new commit parent should be subproj-ref, if it is\n-\t\t# not, something went wrong (the \"newparent\" of \"master~\" commit should\n+\t\t# not, something went wrong (the \"newparent\" of \"HEAD~\" commit should\n \t\t# have been sub2, but it was not, because its cache was not set to\n \t\t# itself)\n \t\tcheck_equal \"$(git log --pretty=format:%P -1 subproj-br)\" \"$(git rev-parse subproj-ref)\"\n@@ -868,13 +868,13 @@ test_expect_success 'split a new subtree without --onto option' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -903,14 +903,14 @@ test_expect_success 'verify one file change per commit' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch sub1 FETCH_HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" sub1\n \t) &&\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -947,7 +947,7 @@ test_expect_success 'push split to subproj' '\n \ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n@@ -958,7 +958,7 @@ test_expect_success 'push split to subproj' '\n \t\tcd $subtree_test_count/\"sub proj\" &&\n                 git branch sub-branch-1 &&\n                 cd .. &&\n-\t\tgit fetch ./\"sub proj\" master &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n@@ -994,6 +994,7 @@ test_expect_success 'push split to subproj' '\n next_test\n test_expect_success 'subtree descendant check' '\n \tsubtree_test_create_repo \"$subtree_test_count\" &&\n+\tdefaultBranch=$(sed \"s,ref: refs/heads/,,\" \"$subtree_test_count/.git/HEAD\") &&\n \ttest_create_commit \"$subtree_test_count\" folder_subtree/a &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n@@ -1010,7 +1011,7 @@ test_expect_success 'subtree descendant check' '\n \t(\n \t\tcd \"$subtree_test_count\" &&\n \t\tgit cherry-pick $cherry &&\n-\t\tgit checkout master &&\n+\t\tgit checkout $defaultBranch &&\n \t\tgit merge -m \"merge should be kept on subtree\" branch &&\n \t\tgit branch no_subtree_work_branch\n \t) &&\n@@ -1022,10 +1023,10 @@ test_expect_success 'subtree descendant check' '\n \ttest_create_commit \"$subtree_test_count\" not_a_subtree_change &&\n \t(\n \t\tcd \"$subtree_test_count\" &&\n-\t\tgit checkout master &&\n+\t\tgit checkout $defaultBranch &&\n \t\tgit merge -m \"merge should be skipped on subtree\" no_subtree_work_branch &&\n \n-\t\tgit subtree split --prefix folder_subtree/ --branch subtree_tip master &&\n+\t\tgit subtree split --prefix folder_subtree/ --branch subtree_tip $defaultBranch &&\n \t\tgit subtree split --prefix folder_subtree/ --branch subtree_branch branch &&\n \t\tcheck_equal $(git rev-list --count subtree_tip..subtree_branch) 0\n \t)\n-- \n2.31.1\n\n"},{"id":"423135","messageId":"20210427211748.2607474-4-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 03/30] subtree: t7900: use test-lib.sh's test_count","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:21Z","receivedAt":"2021-04-27T21:18:31Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nUse test-lib.sh's `test_count`, instead instead of having\nt7900-subtree.sh do its own book-keeping with `subtree_test_count` that\nhas to be explicitly incremented by calling `next_test`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 636 ++++++++++++++---------------\n 1 file changed, 300 insertions(+), 336 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 4b982e6c2e..a6351d9195 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -86,90 +86,79 @@ last_commit_message()\n \tgit log --pretty=format:%s -1\n }\n \n-subtree_test_count=0\n-next_test() {\n-\tsubtree_test_count=$(($subtree_test_count+1))\n-}\n-\n #\n # Tests for 'git subtree add'\n #\n \n-next_test\n test_expect_success 'no merge from non-existent subtree' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\ttest_must_fail git subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t)\n '\n \n-next_test\n test_expect_success 'no pull from non-existent subtree' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD\n \t)'\n \n-next_test\n test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n-next_test\n test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n \t)\n '\n \n-next_test\n test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P and --message as -m' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add -P \"sub dir\" -m \"Added subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n \t)\n '\n \n-next_test\n test_expect_success 'add subproj as subtree into sub dir/ with --squash and --prefix and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject with squash\" --squash FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Added subproject with squash\"\n@@ -180,74 +169,70 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n # Tests for 'git subtree merge'\n #\n \n-next_test\n test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n-next_test\n test_expect_success 'merge new subproj history into sub dir/ with --prefix and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject\" FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject\"\n \t)\n '\n \n-next_test\n test_expect_success 'merge new subproj history into sub dir/ with --squash and --prefix and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject using squash\" --squash FETCH_HEAD &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject using squash\"\n \t)\n '\n \n-next_test\n test_expect_success 'merge the added subproj again, should do nothing' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\t# this shouldn not actually do anything, since FETCH_HEAD\n@@ -257,7 +242,6 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n \t)\n '\n \n-next_test\n test_expect_success 'merge new subproj history into subdir/ with a slash appended to the argument of --prefix' '\n \ttest_create_repo \"$test_count\" &&\n \ttest_create_repo \"$test_count/subproj\" &&\n@@ -281,14 +265,13 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende\n # Tests for 'git subtree split'\n #\n \n-next_test\n test_expect_success 'split requires option --prefix' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\techo \"You must provide the --prefix option.\" > expected &&\n@@ -301,14 +284,13 @@ test_expect_success 'split requires option --prefix' '\n \t)\n '\n \n-next_test\n test_expect_success 'split requires path given by option --prefix must exist' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n \t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" > expected &&\n@@ -321,23 +303,22 @@ test_expect_success 'split requires path given by option --prefix must exist' '\n \t)\n '\n \n-next_test\n test_expect_success 'split sub dir/ with --rejoin' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n@@ -346,12 +327,11 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \t)\n  '\n \n-next_test\n test_expect_success 'split sub dir/ with --rejoin from scratch' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tmkdir \"sub dir\" &&\n \t\techo file >\"sub dir\"/file &&\n \t\tgit add \"sub dir/file\" &&\n@@ -362,23 +342,22 @@ test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \t)\n  '\n \n-next_test\n test_expect_success 'split sub dir/ with --rejoin and --message' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin &&\n@@ -386,23 +365,22 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \t)\n '\n \n-next_test\n test_expect_success 'split \"sub dir\"/ with --branch' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n@@ -411,23 +389,22 @@ test_expect_success 'split \"sub dir\"/ with --branch' '\n \t)\n '\n \n-next_test\n test_expect_success 'check hash of split' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n@@ -443,24 +420,23 @@ test_expect_success 'check hash of split' '\n \t)\n '\n \n-next_test\n test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch subproj-br FETCH_HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n@@ -469,24 +445,23 @@ test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n \t)\n '\n \n-next_test\n test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit branch init HEAD &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\ttest_must_fail git subtree split --prefix=\"sub dir\" --branch init\n@@ -497,46 +472,45 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n # Validity checking\n #\n \n-next_test\n test_expect_success 'make sure exactly the right set of files ends up in the subproj' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD &&\n \n@@ -547,46 +521,45 @@ test_expect_success 'make sure exactly the right set of files ends up in the sub\n \t)\n '\n \n-next_test\n test_expect_success 'make sure the subproj *only* contains commits that affect the \"sub dir\"' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD &&\n \n@@ -598,51 +571,50 @@ test_expect_success 'make sure the subproj *only* contains commits that affect t\n \t)\n '\n \n-next_test\n test_expect_success 'make sure exactly the right set of files ends up in the mainline' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\ttest_write_lines main1 main2 >chkm &&\n@@ -657,52 +629,51 @@ test_expect_success 'make sure exactly the right set of files ends up in the mai\n \t)\n '\n \n-next_test\n test_expect_success 'make sure each filename changed exactly once in the entire history' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit config log.date relative &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\ttest_write_lines main1 main2 >chkm &&\n@@ -723,101 +694,99 @@ test_expect_success 'make sure each filename changed exactly once in the entire\n \t)\n '\n \n-next_test\n test_expect_success 'make sure the --rejoin commits never make it into subproj' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \t\tcheck_equal \"$(git log --pretty=format:\"%s\" HEAD^2 | grep -i split)\" \"\"\n \t)\n '\n \n-next_test\n test_expect_success 'make sure no \"git subtree\" tagged commits make it into subproj' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub3 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\t git merge FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub4 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub4 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub4 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br --rejoin\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count/sub proj\" &&\n+\t\tcd \"$test_count/sub proj\" &&\n \t\tgit fetch .. subproj-br &&\n \t\tgit merge FETCH_HEAD\n \t) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\t# They are meaningless to subproj since one side of the merge refers to the mainline\n@@ -829,27 +798,26 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n # A new set of tests\n #\n \n-next_test\n test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch subproj-ref FETCH_HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --branch subproj-br &&\n \n \t\t# at this point, the new commit parent should be subproj-ref, if it is\n@@ -860,32 +828,31 @@ test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n \t)\n '\n \n-next_test\n test_expect_success 'split a new subtree without --onto option' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --branch subproj-br\n \t) &&\n-\tmkdir \"$subtree_test_count\"/\"sub dir2\" &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir2\"/main-sub2 &&\n+\tmkdir \"$test_count\"/\"sub dir2\" &&\n+\ttest_create_commit \"$test_count\" \"sub dir2\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \n \t\t# also test that we still can split out an entirely new subtree\n \t\t# if the parent of the first commit in the tree is not empty,\n@@ -895,33 +862,32 @@ test_expect_success 'split a new subtree without --onto option' '\n \t)\n '\n \n-next_test\n test_expect_success 'verify one file change per commit' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit branch sub1 FETCH_HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" sub1\n \t) &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir\" --branch subproj-br\n \t) &&\n-\tmkdir \"$subtree_test_count\"/\"sub dir2\" &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir2\"/main-sub2 &&\n+\tmkdir \"$test_count\"/\"sub dir2\" &&\n+\ttest_create_commit \"$test_count\" \"sub dir2\"/main-sub2 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir2\" --branch subproj2-br &&\n \n \t\tx= &&\n@@ -939,31 +905,30 @@ test_expect_success 'verify one file change per commit' '\n \t)\n '\n \n-next_test\n test_expect_success 'push split to subproj' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tsubtree_test_create_repo \"$subtree_test_count/sub proj\" &&\n-\ttest_create_commit \"$subtree_test_count\" main1 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub1 &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub1 &&\n-\ttest_create_commit \"$subtree_test_count\" main2 &&\n-\ttest_create_commit \"$subtree_test_count/sub proj\" sub2 &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n-\t\tcd $subtree_test_count/\"sub proj\" &&\n+\t\tcd $test_count/\"sub proj\" &&\n                 git branch sub-branch-1 &&\n                 cd .. &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" \"sub dir\"/main-sub3 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n         (\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t        git subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n                 cd ./\"sub proj\" &&\n                 git checkout sub-branch-1 &&\n@@ -991,38 +956,37 @@ test_expect_success 'push split to subproj' '\n #   set of commits.\n #\n \n-next_test\n test_expect_success 'subtree descendant check' '\n-\tsubtree_test_create_repo \"$subtree_test_count\" &&\n-\tdefaultBranch=$(sed \"s,ref: refs/heads/,,\" \"$subtree_test_count/.git/HEAD\") &&\n-\ttest_create_commit \"$subtree_test_count\" folder_subtree/a &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tdefaultBranch=$(sed \"s,ref: refs/heads/,,\" \"$test_count/.git/HEAD\") &&\n+\ttest_create_commit \"$test_count\" folder_subtree/a &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit branch branch\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" folder_subtree/0 &&\n-\ttest_create_commit \"$subtree_test_count\" folder_subtree/b &&\n-\tcherry=$(cd \"$subtree_test_count\"; git rev-parse HEAD) &&\n+\ttest_create_commit \"$test_count\" folder_subtree/0 &&\n+\ttest_create_commit \"$test_count\" folder_subtree/b &&\n+\tcherry=$(cd \"$test_count\"; git rev-parse HEAD) &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit checkout branch\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" commit_on_branch &&\n+\ttest_create_commit \"$test_count\" commit_on_branch &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit cherry-pick $cherry &&\n \t\tgit checkout $defaultBranch &&\n \t\tgit merge -m \"merge should be kept on subtree\" branch &&\n \t\tgit branch no_subtree_work_branch\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" folder_subtree/d &&\n+\ttest_create_commit \"$test_count\" folder_subtree/d &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit checkout no_subtree_work_branch\n \t) &&\n-\ttest_create_commit \"$subtree_test_count\" not_a_subtree_change &&\n+\ttest_create_commit \"$test_count\" not_a_subtree_change &&\n \t(\n-\t\tcd \"$subtree_test_count\" &&\n+\t\tcd \"$test_count\" &&\n \t\tgit checkout $defaultBranch &&\n \t\tgit merge -m \"merge should be skipped on subtree\" no_subtree_work_branch &&\n \n-- \n2.31.1\n\n"},{"id":"423134","messageId":"20210427211748.2607474-5-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 04/30] subtree: t7900: use consistent formatting","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:22Z","receivedAt":"2021-04-27T21:18:32Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThe formatting in t7900-subtree.sh isn't even consistent throughout the\nfile.  Fix that; make it consistent throughout the file.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Also normalize on `test X` instead of `[ X ]`.\n - Also normalize on `>FILENAME` with no spaces.\n - Fix a few if statements with `if` and `then` on the same line\n   that I missed in v1.\nv3:\n - Consistently put the `do` of a loop on its own line.\n\n contrib/subtree/t/t7900-subtree.sh | 70 +++++++++++++++---------------\n 1 file changed, 35 insertions(+), 35 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex a6351d9195..2319c3fd1c 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -11,11 +11,9 @@ and split subcommands of git subtree.\n \n TEST_DIRECTORY=$(pwd)/../../../t\n export TEST_DIRECTORY\n+. \"$TEST_DIRECTORY\"/test-lib.sh\n \n-. ../../../t/test-lib.sh\n-\n-subtree_test_create_repo()\n-{\n+subtree_test_create_repo () {\n \ttest_create_repo \"$1\" &&\n \t(\n \t\tcd \"$1\" &&\n@@ -23,26 +21,24 @@ subtree_test_create_repo()\n \t)\n }\n \n-create()\n-{\n+create () {\n \techo \"$1\" >\"$1\" &&\n \tgit add \"$1\"\n }\n \n-check_equal()\n-{\n+check_equal () {\n \ttest_debug 'echo'\n \ttest_debug \"echo \\\"check a:\\\" \\\"{$1}\\\"\"\n \ttest_debug \"echo \\\"      b:\\\" \\\"{$2}\\\"\"\n-\tif [ \"$1\" = \"$2\" ]; then\n+\tif test \"$1\" = \"$2\"\n+\tthen\n \t\treturn 0\n \telse\n \t\treturn 1\n \tfi\n }\n \n-undo()\n-{\n+undo () {\n \tgit reset --hard HEAD~\n }\n \n@@ -50,15 +46,18 @@ undo()\n # The original set of commits changed only one file each.\n # A multi-file change would imply that we pruned commits\n # too aggressively.\n-join_commits()\n-{\n+join_commits () {\n \tcommit=\n \tall=\n-\twhile read x y; do\n-\t\tif [ -z \"$x\" ]; then\n+\twhile read x y\n+\tdo\n+\t\tif test -z \"$x\"\n+\t\tthen\n \t\t\tcontinue\n-\t\telif [ \"$x\" = \"commit:\" ]; then\n-\t\t\tif [ -n \"$commit\" ]; then\n+\t\telif test \"$x\" = \"commit:\"\n+\t\tthen\n+\t\t\tif test -n \"$commit\"\n+\t\t\tthen\n \t\t\t\techo \"$commit $all\"\n \t\t\t\tall=\n \t\t\tfi\n@@ -70,7 +69,7 @@ join_commits()\n \techo \"$commit $all\"\n }\n \n-test_create_commit() (\n+test_create_commit () (\n \trepo=$1 &&\n \tcommit=$2 &&\n \tcd \"$repo\" &&\n@@ -81,8 +80,7 @@ test_create_commit() (\n \tgit commit -m \"$commit\" || error \"Could not commit\"\n )\n \n-last_commit_message()\n-{\n+last_commit_message () {\n \tgit log --pretty=format:%s -1\n }\n \n@@ -111,7 +109,8 @@ test_expect_success 'no pull from non-existent subtree' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD\n-\t)'\n+\t)\n+'\n \n test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \tsubtree_test_create_repo \"$test_count\" &&\n@@ -274,8 +273,8 @@ test_expect_success 'split requires option --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\techo \"You must provide the --prefix option.\" > expected &&\n-\t\ttest_must_fail git subtree split > actual 2>&1 &&\n+\t\techo \"You must provide the --prefix option.\" >expected &&\n+\t\ttest_must_fail git subtree split >actual 2>&1 &&\n \t\ttest_debug \"printf '\"expected: \"'\" &&\n \t\ttest_debug \"cat expected\" &&\n \t\ttest_debug \"printf '\"actual: \"'\" &&\n@@ -293,8 +292,8 @@ test_expect_success 'split requires path given by option --prefix must exist' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" > expected &&\n-\t\ttest_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 &&\n+\t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" >expected &&\n+\t\ttest_must_fail git subtree split --prefix=non-existent-directory >actual 2>&1 &&\n \t\ttest_debug \"printf '\"expected: \"'\" &&\n \t\ttest_debug \"cat expected\" &&\n \t\ttest_debug \"printf '\"actual: \"'\" &&\n@@ -325,7 +324,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n- '\n+'\n \n test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \tsubtree_test_create_repo \"$test_count\" &&\n@@ -340,7 +339,7 @@ test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \t\tgit subtree split --prefix=\"sub dir\" --rejoin &&\n \t\tcheck_equal \"$(last_commit_message)\" \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n- '\n+'\n \n test_expect_success 'split sub dir/ with --rejoin and --message' '\n \tsubtree_test_create_repo \"$test_count\" &&\n@@ -893,7 +892,8 @@ test_expect_success 'verify one file change per commit' '\n \t\tx= &&\n \t\tgit log --pretty=format:\"commit: %H\" | join_commits |\n \t\t(\n-\t\t\twhile read commit a b; do\n+\t\t\twhile read commit a b\n+\t\t\tdo\n \t\t\t\ttest_debug \"echo Verifying commit $commit\"\n \t\t\t\ttest_debug \"echo a: $a\"\n \t\t\t\ttest_debug \"echo b: $b\"\n@@ -921,18 +921,18 @@ test_expect_success 'push split to subproj' '\n \ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n \t(\n \t\tcd $test_count/\"sub proj\" &&\n-                git branch sub-branch-1 &&\n-                cd .. &&\n+\t\tgit branch sub-branch-1 &&\n+\t\tcd .. &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD\n \t) &&\n \ttest_create_commit \"$test_count\" \"sub dir\"/main-sub3 &&\n-        (\n+\t(\n \t\tcd \"$test_count\" &&\n-\t        git subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n-                cd ./\"sub proj\" &&\n-                git checkout sub-branch-1 &&\n-         \tcheck_equal \"$(last_commit_message)\" \"sub dir/main-sub3\"\n+\t\tgit subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n+\t\tcd ./\"sub proj\" &&\n+\t\tgit checkout sub-branch-1 &&\n+\t\tcheck_equal \"$(last_commit_message)\" \"sub dir/main-sub3\"\n \t)\n '\n \n-- \n2.31.1\n\n"},{"id":"423136","messageId":"20210427211748.2607474-6-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 05/30] subtree: t7900: comment subtree_test_create_repo","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:23Z","receivedAt":"2021-04-27T21:18:33Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nIt's unclear what the purpose of t7900-subtree.sh's\n`subtree_test_create_repo` helper function is.  It wraps test-lib.sh's,\n`test_create_repo` but follows that up by setting log.date=relative.  Why\ndoes it set log.date=relative?\n\nMy first guess was that at one point the tests required that, but no\nlonger do, and that the function is now vestigial.  I even wrote a patch\nto get rid of it and was moments away from `git send-email`ing it.\n\nHowever, by chance when looking for something else in the history, I\ndiscovered the true reason, from e7aac44ed2 (contrib/subtree: ignore\nlog.date configuration, 2015-07-21).  It's testing that setting\nlog.date=relative doesn't break `git subtree`, as at one point in the past\nthat did break `git subtree`.\n\nSo, add a comment about this, to avoid future such confusion.\n\nAnd while at it, go ahead and (1) touch up the function to avoid a\npointless subshell and (2) update the one test that didn't use it.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Also switch the few uses of vanilla test_create_repo over to\n   subtree_test_create_repo.  In v1 this was erroneously included\n   in a different commit.\n\n contrib/subtree/t/t7900-subtree.sh | 14 ++++++++------\n 1 file changed, 8 insertions(+), 6 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 2319c3fd1c..12b8cb03c7 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -13,12 +13,14 @@ TEST_DIRECTORY=$(pwd)/../../../t\n export TEST_DIRECTORY\n . \"$TEST_DIRECTORY\"/test-lib.sh\n \n+# Use our own wrapper around test-lib.sh's test_create_repo, in order\n+# to set log.date=relative.  `git subtree` parses the output of `git\n+# log`, and so it must be careful to not be affected by settings that\n+# change the `git log` output.  We test this by setting\n+# log.date=relative for every repo in the tests.\n subtree_test_create_repo () {\n \ttest_create_repo \"$1\" &&\n-\t(\n-\t\tcd \"$1\" &&\n-\t\tgit config log.date relative\n-\t)\n+\tgit -C \"$1\" config log.date relative\n }\n \n create () {\n@@ -242,8 +244,8 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n '\n \n test_expect_success 'merge new subproj history into subdir/ with a slash appended to the argument of --prefix' '\n-\ttest_create_repo \"$test_count\" &&\n-\ttest_create_repo \"$test_count/subproj\" &&\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/subproj\" &&\n \ttest_create_commit \"$test_count\" main1 &&\n \ttest_create_commit \"$test_count/subproj\" sub1 &&\n \t(\n-- \n2.31.1\n\n"},{"id":"423137","messageId":"20210427211748.2607474-7-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 06/30] subtree: t7900: use 'test' for string equality","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:24Z","receivedAt":"2021-04-27T21:18:36Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nt7900-subtree.sh defines its own `check_equal A B` function, instead of\njust using `test A = B` like all of the other tests.  Don't be special,\nget rid of `check_equal` in favor of `test`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 60 ++++++++++++------------------\n 1 file changed, 24 insertions(+), 36 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 12b8cb03c7..76183153c9 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -28,18 +28,6 @@ create () {\n \tgit add \"$1\"\n }\n \n-check_equal () {\n-\ttest_debug 'echo'\n-\ttest_debug \"echo \\\"check a:\\\" \\\"{$1}\\\"\"\n-\ttest_debug \"echo \\\"      b:\\\" \\\"{$2}\\\"\"\n-\tif test \"$1\" = \"$2\"\n-\tthen\n-\t\treturn 0\n-\telse\n-\t\treturn 1\n-\tfi\n-}\n-\n undo () {\n \tgit reset --hard HEAD~\n }\n@@ -123,7 +111,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -136,7 +124,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --me\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n+\t\ttest \"$(last_commit_message)\" = \"Added subproject\"\n \t)\n '\n \n@@ -149,7 +137,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P an\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add -P \"sub dir\" -m \"Added subproject\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Added subproject\"\n+\t\ttest \"$(last_commit_message)\" = \"Added subproject\"\n \t)\n '\n \n@@ -162,7 +150,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject with squash\" --squash FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Added subproject with squash\"\n+\t\ttest \"$(last_commit_message)\" = \"Added subproject with squash\"\n \t)\n '\n \n@@ -185,7 +173,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -204,7 +192,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix and -\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject\" FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject\"\n+\t\ttest \"$(last_commit_message)\" = \"Merged changes from subproject\"\n \t)\n '\n \n@@ -223,7 +211,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --squash and -\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject using squash\" --squash FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Merged changes from subproject using squash\"\n+\t\ttest \"$(last_commit_message)\" = \"Merged changes from subproject using squash\"\n \t)\n '\n \n@@ -239,7 +227,7 @@ test_expect_success 'merge the added subproj again, should do nothing' '\n \t\t# this shouldn not actually do anything, since FETCH_HEAD\n \t\t# is already a parent\n \t\tresult=$(git merge -s ours -m \"merge -s -ours\" FETCH_HEAD) &&\n-\t\tcheck_equal \"${result}\" \"Already up to date.\"\n+\t\ttest \"${result}\" = \"Already up to date.\"\n \t)\n '\n \n@@ -258,7 +246,7 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./subproj HEAD &&\n \t\tgit subtree merge --prefix=subdir/ FETCH_HEAD &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -324,7 +312,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n '\n \n@@ -339,7 +327,7 @@ test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \t\tgit commit -m\"sub dir file\" &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --rejoin) &&\n \t\tgit subtree split --prefix=\"sub dir\" --rejoin &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n+\t\ttest \"$(last_commit_message)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n '\n \n@@ -362,7 +350,7 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"Split & rejoin\"\n+\t\ttest \"$(last_commit_message)\" = \"Split & rejoin\"\n \t)\n '\n \n@@ -386,7 +374,7 @@ test_expect_success 'split \"sub dir\"/ with --branch' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n-\t\tcheck_equal \"$(git rev-parse subproj-br)\" \"$split_hash\"\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\"\n \t)\n '\n \n@@ -410,13 +398,13 @@ test_expect_success 'check hash of split' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n-\t\tcheck_equal \"$(git rev-parse subproj-br)\" \"$split_hash\" &&\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\" &&\n \t\t# Check hash of split\n \t\tnew_hash=$(git rev-parse subproj-br^2) &&\n \t\t(\n \t\t\tcd ./\"sub proj\" &&\n \t\t\tsubdir_hash=$(git rev-parse HEAD) &&\n-\t\t\tcheck_equal ''\"$new_hash\"'' \"$subdir_hash\"\n+\t\t\ttest ''\"$new_hash\"'' = \"$subdir_hash\"\n \t\t)\n \t)\n '\n@@ -442,7 +430,7 @@ test_expect_success 'split \"sub dir\"/ with --branch for an existing branch' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br &&\n-\t\tcheck_equal \"$(git rev-parse subproj-br)\" \"$split_hash\"\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\"\n \t)\n '\n \n@@ -740,7 +728,7 @@ test_expect_success 'make sure the --rejoin commits never make it into subproj'\n \t(\n \t\tcd \"$test_count\" &&\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n-\t\tcheck_equal \"$(git log --pretty=format:\"%s\" HEAD^2 | grep -i split)\" \"\"\n+\t\ttest \"$(git log --pretty=format:\"%s\" HEAD^2 | grep -i split)\" = \"\"\n \t)\n '\n \n@@ -791,7 +779,7 @@ test_expect_success 'make sure no \"git subtree\" tagged commits make it into subp\n \t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n \n \t\t# They are meaningless to subproj since one side of the merge refers to the mainline\n-\t\tcheck_equal \"$(git log --pretty=format:\"%s%n%b\" HEAD^2 | grep \"git-subtree.*:\")\" \"\"\n+\t\ttest \"$(git log --pretty=format:\"%s%n%b\" HEAD^2 | grep \"git-subtree.*:\")\" = \"\"\n \t)\n '\n \n@@ -825,7 +813,7 @@ test_expect_success 'make sure \"git subtree split\" find the correct parent' '\n \t\t# not, something went wrong (the \"newparent\" of \"HEAD~\" commit should\n \t\t# have been sub2, but it was not, because its cache was not set to\n \t\t# itself)\n-\t\tcheck_equal \"$(git log --pretty=format:%P -1 subproj-br)\" \"$(git rev-parse subproj-ref)\"\n+\t\ttest \"$(git log --pretty=format:%P -1 subproj-br)\" = \"$(git rev-parse subproj-ref)\"\n \t)\n '\n \n@@ -859,7 +847,7 @@ test_expect_success 'split a new subtree without --onto option' '\n \t\t# if the parent of the first commit in the tree is not empty,\n \t\t# then the new subtree has accidentally been attached to something\n \t\tgit subtree split --prefix=\"sub dir2\" --branch subproj2-br &&\n-\t\tcheck_equal \"$(git log --pretty=format:%P -1 subproj2-br)\" \"\"\n+\t\ttest \"$(git log --pretty=format:%P -1 subproj2-br)\" = \"\"\n \t)\n '\n \n@@ -899,10 +887,10 @@ test_expect_success 'verify one file change per commit' '\n \t\t\t\ttest_debug \"echo Verifying commit $commit\"\n \t\t\t\ttest_debug \"echo a: $a\"\n \t\t\t\ttest_debug \"echo b: $b\"\n-\t\t\t\tcheck_equal \"$b\" \"\"\n+\t\t\t\ttest \"$b\" = \"\"\n \t\t\t\tx=1\n \t\t\tdone\n-\t\t\tcheck_equal \"$x\" 1\n+\t\t\ttest \"$x\" = 1\n \t\t)\n \t)\n '\n@@ -934,7 +922,7 @@ test_expect_success 'push split to subproj' '\n \t\tgit subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n \t\tcd ./\"sub proj\" &&\n \t\tgit checkout sub-branch-1 &&\n-\t\tcheck_equal \"$(last_commit_message)\" \"sub dir/main-sub3\"\n+\t\ttest \"$(last_commit_message)\" = \"sub dir/main-sub3\"\n \t)\n '\n \n@@ -994,7 +982,7 @@ test_expect_success 'subtree descendant check' '\n \n \t\tgit subtree split --prefix folder_subtree/ --branch subtree_tip $defaultBranch &&\n \t\tgit subtree split --prefix folder_subtree/ --branch subtree_branch branch &&\n-\t\tcheck_equal $(git rev-list --count subtree_tip..subtree_branch) 0\n+\t\ttest $(git rev-list --count subtree_tip..subtree_branch) = 0\n \t)\n '\n \n-- \n2.31.1\n\n"},{"id":"423138","messageId":"20210427211748.2607474-8-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 07/30] subtree: t7900: delete some dead code","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:25Z","receivedAt":"2021-04-27T21:18:39Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 12 +-----------\n 1 file changed, 1 insertion(+), 11 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 76183153c9..421ed9f003 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -10,7 +10,6 @@ and split subcommands of git subtree.\n '\n \n TEST_DIRECTORY=$(pwd)/../../../t\n-export TEST_DIRECTORY\n . \"$TEST_DIRECTORY\"/test-lib.sh\n \n # Use our own wrapper around test-lib.sh's test_create_repo, in order\n@@ -23,15 +22,6 @@ subtree_test_create_repo () {\n \tgit -C \"$1\" config log.date relative\n }\n \n-create () {\n-\techo \"$1\" >\"$1\" &&\n-\tgit add \"$1\"\n-}\n-\n-undo () {\n-\tgit reset --hard HEAD~\n-}\n-\n # Make sure no patch changes more than one file.\n # The original set of commits changed only one file each.\n # A multi-file change would imply that we pruned commits\n@@ -404,7 +394,7 @@ test_expect_success 'check hash of split' '\n \t\t(\n \t\t\tcd ./\"sub proj\" &&\n \t\t\tsubdir_hash=$(git rev-parse HEAD) &&\n-\t\t\ttest ''\"$new_hash\"'' = \"$subdir_hash\"\n+\t\t\ttest \"$new_hash\" = \"$subdir_hash\"\n \t\t)\n \t)\n '\n-- \n2.31.1\n\n"},{"id":"423139","messageId":"20210427211748.2607474-9-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 08/30] subtree: t7900: fix 'verify one file change per commit'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:26Z","receivedAt":"2021-04-27T21:18:40Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nAs far as I can tell, this test isn't actually testing anything, because\nsomeone forgot to tack on `--name-only` to `git log`.  This seems to\nhave been the case since the test was first written, back in fa16ab36ad\n(\"test.sh: make sure no commit changes more than one file at a time.\",\n2009-04-26), unless `git log` used to do that by default and didn't need\nthe flag back then?\n\nConvincing myself that it's not actually testing anything was tricky,\nthe code is a little hard to reason about.  It can be made a lot simpler\nif instead of trying to parse all of the info from a single `git log`,\nwe're OK calling `git log` from inside of a loop.  And it's my opinion\nthat tests are not the place for clever optimized code.\n\nSo, fix and simplify the test, so that it's actually testing something\nand is simpler to reason about.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 46 ++++--------------------------\n 1 file changed, 6 insertions(+), 40 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 421ed9f003..1c717fcb96 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -22,33 +22,6 @@ subtree_test_create_repo () {\n \tgit -C \"$1\" config log.date relative\n }\n \n-# Make sure no patch changes more than one file.\n-# The original set of commits changed only one file each.\n-# A multi-file change would imply that we pruned commits\n-# too aggressively.\n-join_commits () {\n-\tcommit=\n-\tall=\n-\twhile read x y\n-\tdo\n-\t\tif test -z \"$x\"\n-\t\tthen\n-\t\t\tcontinue\n-\t\telif test \"$x\" = \"commit:\"\n-\t\tthen\n-\t\t\tif test -n \"$commit\"\n-\t\t\tthen\n-\t\t\t\techo \"$commit $all\"\n-\t\t\t\tall=\n-\t\t\tfi\n-\t\t\tcommit=\"$y\"\n-\t\telse\n-\t\t\tall=\"$all $y\"\n-\t\tfi\n-\tdone\n-\techo \"$commit $all\"\n-}\n-\n test_create_commit () (\n \trepo=$1 &&\n \tcommit=$2 &&\n@@ -869,19 +842,12 @@ test_expect_success 'verify one file change per commit' '\n \t\tcd \"$test_count\" &&\n \t\tgit subtree split --prefix=\"sub dir2\" --branch subproj2-br &&\n \n-\t\tx= &&\n-\t\tgit log --pretty=format:\"commit: %H\" | join_commits |\n-\t\t(\n-\t\t\twhile read commit a b\n-\t\t\tdo\n-\t\t\t\ttest_debug \"echo Verifying commit $commit\"\n-\t\t\t\ttest_debug \"echo a: $a\"\n-\t\t\t\ttest_debug \"echo b: $b\"\n-\t\t\t\ttest \"$b\" = \"\"\n-\t\t\t\tx=1\n-\t\t\tdone\n-\t\t\ttest \"$x\" = 1\n-\t\t)\n+\t\tgit log --format=\"%H\" >commit-list &&\n+\t\twhile read commit\n+\t\tdo\n+\t\t\tgit log -n1 --format=\"\" --name-only \"$commit\" >file-list &&\n+\t\t\ttest_line_count -le 1 file-list || return 1\n+\t\tdone <commit-list\n \t)\n '\n \n-- \n2.31.1\n\n"},{"id":"423140","messageId":"20210427211748.2607474-10-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 09/30] subtree: t7900: rename last_commit_message to last_commit_subject","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:27Z","receivedAt":"2021-04-27T21:18:41Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nt7900-subtree.sh defines a helper function named last_commit_message.\nHowever, it only returns the subject line of the commit message, not the\nentire commit message.  So rename it, to make the name less confusing.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 26 +++++++++++++-------------\n 1 file changed, 13 insertions(+), 13 deletions(-)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 1c717fcb96..5c2510f1f5 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -33,7 +33,7 @@ test_create_commit () (\n \tgit commit -m \"$commit\" || error \"Could not commit\"\n )\n \n-last_commit_message () {\n+last_commit_subject () {\n \tgit log --pretty=format:%s -1\n }\n \n@@ -74,7 +74,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Add '\\''sub dir/'\\'' from commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -87,7 +87,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix and --me\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Added subproject\"\n+\t\ttest \"$(last_commit_subject)\" = \"Added subproject\"\n \t)\n '\n \n@@ -100,7 +100,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --prefix as -P an\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add -P \"sub dir\" -m \"Added subproject\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Added subproject\"\n+\t\ttest \"$(last_commit_subject)\" = \"Added subproject\"\n \t)\n '\n \n@@ -113,7 +113,7 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree add --prefix=\"sub dir\" --message=\"Added subproject with squash\" --squash FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Added subproject with squash\"\n+\t\ttest \"$(last_commit_subject)\" = \"Added subproject with squash\"\n \t)\n '\n \n@@ -136,7 +136,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -155,7 +155,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --prefix and -\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject\" FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Merged changes from subproject\"\n+\t\ttest \"$(last_commit_subject)\" = \"Merged changes from subproject\"\n \t)\n '\n \n@@ -174,7 +174,7 @@ test_expect_success 'merge new subproj history into sub dir/ with --squash and -\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" --message=\"Merged changes from subproject using squash\" --squash FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Merged changes from subproject using squash\"\n+\t\ttest \"$(last_commit_subject)\" = \"Merged changes from subproject using squash\"\n \t)\n '\n \n@@ -209,7 +209,7 @@ test_expect_success 'merge new subproj history into subdir/ with a slash appende\n \t\tcd \"$test_count\" &&\n \t\tgit fetch ./subproj HEAD &&\n \t\tgit subtree merge --prefix=subdir/ FETCH_HEAD &&\n-\t\ttest \"$(last_commit_message)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Merge commit '\\''$(git rev-parse FETCH_HEAD)'\\''\"\n \t)\n '\n \n@@ -275,7 +275,7 @@ test_expect_success 'split sub dir/ with --rejoin' '\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n \t\tgit subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin &&\n-\t\ttest \"$(last_commit_message)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n '\n \n@@ -290,7 +290,7 @@ test_expect_success 'split sub dir/ with --rejoin from scratch' '\n \t\tgit commit -m\"sub dir file\" &&\n \t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --rejoin) &&\n \t\tgit subtree split --prefix=\"sub dir\" --rejoin &&\n-\t\ttest \"$(last_commit_message)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\"\n \t)\n '\n \n@@ -313,7 +313,7 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \t\tgit fetch ./\"sub proj\" HEAD &&\n \t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n \t\tgit subtree split --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin &&\n-\t\ttest \"$(last_commit_message)\" = \"Split & rejoin\"\n+\t\ttest \"$(last_commit_subject)\" = \"Split & rejoin\"\n \t)\n '\n \n@@ -878,7 +878,7 @@ test_expect_success 'push split to subproj' '\n \t\tgit subtree push ./\"sub proj\" --prefix \"sub dir\" sub-branch-1 &&\n \t\tcd ./\"sub proj\" &&\n \t\tgit checkout sub-branch-1 &&\n-\t\ttest \"$(last_commit_message)\" = \"sub dir/main-sub3\"\n+\t\ttest \"$(last_commit_subject)\" = \"sub dir/main-sub3\"\n \t)\n '\n \n-- \n2.31.1\n\n"},{"id":"423141","messageId":"20210427211748.2607474-11-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 10/30] subtree: t7900: add a test for the -h flag","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:28Z","receivedAt":"2021-04-27T21:18:42Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nIt's a dumb test, but it's surprisingly easy to break.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/t/t7900-subtree.sh | 7 +++++++\n 1 file changed, 7 insertions(+)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 5c2510f1f5..9afba2f282 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -37,6 +37,13 @@ last_commit_subject () {\n \tgit log --pretty=format:%s -1\n }\n \n+test_expect_success 'shows short help text for -h' '\n+\ttest_expect_code 129 git subtree -h >out 2>err &&\n+\ttest_must_be_empty err &&\n+\tgrep -e \"^ *or: git subtree pull\" out &&\n+\tgrep -e --annotate out\n+'\n+\n #\n # Tests for 'git subtree add'\n #\n-- \n2.31.1\n\n"},{"id":"423142","messageId":"20210427211748.2607474-12-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 11/30] subtree: t7900: add porcelain tests for 'pull' and 'push'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:29Z","receivedAt":"2021-04-27T21:18:44Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThe 'pull' and 'push' subcommands deserve their own sections in the tests.\nAdd some basic tests for them.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Don't switch unrelated uses of vanilla test_create_repo over to\n   subtree_test_create_repo; this has been moved to happen in an\n   earlier commit.\n - Fix whitespace.\n\n contrib/subtree/t/t7900-subtree.sh | 127 +++++++++++++++++++++++++++++\n 1 file changed, 127 insertions(+)\n\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 9afba2f282..ce6861c22d 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -427,6 +427,133 @@ test_expect_success 'split \"sub dir\"/ with --branch for an incompatible branch'\n \t)\n '\n \n+#\n+# Tests for 'git subtree pull'\n+#\n+\n+test_expect_success 'pull requires option --prefix' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\ttest_must_fail git subtree pull ./\"sub proj\" HEAD >out 2>err &&\n+\n+\t\techo \"You must provide the --prefix option.\" >expected &&\n+\t\ttest_must_be_empty out &&\n+\t\ttest_cmp expected err\n+\t)\n+'\n+\n+test_expect_success 'pull requires path given by option --prefix must exist' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD >out 2>err &&\n+\n+\t\techo \"'\\''sub dir'\\'' does not exist; use '\\''git subtree add'\\''\" >expected &&\n+\t\ttest_must_be_empty out &&\n+\t\ttest_cmp expected err\n+\t)\n+'\n+\n+test_expect_success 'pull basic operation' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\texp=$(git -C \"sub proj\" rev-parse --verify HEAD:) &&\n+\t\tgit subtree pull --prefix=\"sub dir\" ./\"sub proj\" HEAD &&\n+\t\tact=$(git rev-parse --verify HEAD:\"sub dir\") &&\n+\t\ttest \"$act\" = \"$exp\"\n+\t)\n+'\n+\n+#\n+# Tests for 'git subtree push'\n+#\n+\n+test_expect_success 'push requires option --prefix' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\techo \"You must provide the --prefix option.\" >expected &&\n+\t\ttest_must_fail git subtree push \"./sub proj\" from-mainline >actual 2>&1 &&\n+\t\ttest_debug \"printf '\"expected: \"'\" &&\n+\t\ttest_debug \"cat expected\" &&\n+\t\ttest_debug \"printf '\"actual: \"'\" &&\n+\t\ttest_debug \"cat actual\" &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n+test_expect_success 'push requires path given by option --prefix must exist' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\techo \"'\\''non-existent-directory'\\'' does not exist; use '\\''git subtree add'\\''\" >expected &&\n+\t\ttest_must_fail git subtree push --prefix=non-existent-directory \"./sub proj\" from-mainline >actual 2>&1 &&\n+\t\ttest_debug \"printf '\"expected: \"'\" &&\n+\t\ttest_debug \"cat expected\" &&\n+\t\ttest_debug \"printf '\"actual: \"'\" &&\n+\t\ttest_debug \"cat actual\" &&\n+\t\ttest_cmp expected actual\n+\t)\n+'\n+\n+test_expect_success 'push basic operation' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tbefore=$(git rev-parse --verify HEAD) &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" ./\"sub proj\" from-mainline &&\n+\t\ttest \"$before\" = \"$(git rev-parse --verify HEAD)\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n #\n # Validity checking\n #\n-- \n2.31.1\n\n"},{"id":"423143","messageId":"20210427211748.2607474-13-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 12/30] subtree: don't have loose code outside of a function","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:30Z","receivedAt":"2021-04-27T21:18:46Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nShove all of the loose code inside of a main() function.\n\nThis comes down to personal preference more than anything else.  A\npreference that I've developed over years of maintaining large Bash\nscripts, but still a mere personal preference.\n\nIn this specific case, it's also moving the `set -- -h`, the `git\nrev-parse --parseopt`, and the `. git-sh-setup` to be closer to all\nthe rest of the argument parsing, which is a readability win on its\nown, IMO.\n\n\"Ignore space change\" is probably helpful when viewing this diff.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Include rationale in the the commit message.\n\n contrib/subtree/git-subtree.sh | 245 +++++++++++++++++----------------\n 1 file changed, 125 insertions(+), 120 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 868e18b9a1..d1ed7f9a6c 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -4,10 +4,7 @@\n #\n # Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com>\n #\n-if test $# -eq 0\n-then\n-\tset -- -h\n-fi\n+\n OPTS_SPEC=\"\\\n git subtree add   --prefix=<prefix> <commit>\n git subtree add   --prefix=<prefix> <repository> <ref>\n@@ -30,12 +27,8 @@ rejoin        merge the new branch back into HEAD\n  options for 'add', 'merge', and 'pull'\n squash        merge subtree changes as a single commit\n \"\n-eval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n \n PATH=$PATH:$(git --exec-path)\n-. git-sh-setup\n-\n-require_work_tree\n \n quiet=\n branch=\n@@ -84,126 +77,138 @@ ensure_single_rev () {\n \tfi\n }\n \n-while test $# -gt 0\n-do\n-\topt=\"$1\"\n-\tshift\n+main () {\n+\tif test $# -eq 0\n+\tthen\n+\t\tset -- -h\n+\tfi\n+\teval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n+\t. git-sh-setup\n+\trequire_work_tree\n \n-\tcase \"$opt\" in\n-\t-q)\n-\t\tquiet=1\n-\t\t;;\n-\t-d)\n-\t\tdebug=1\n-\t\t;;\n-\t--annotate)\n-\t\tannotate=\"$1\"\n-\t\tshift\n-\t\t;;\n-\t--no-annotate)\n-\t\tannotate=\n-\t\t;;\n-\t-b)\n-\t\tbranch=\"$1\"\n-\t\tshift\n-\t\t;;\n-\t-P)\n-\t\tprefix=\"${1%/}\"\n-\t\tshift\n-\t\t;;\n-\t-m)\n-\t\tmessage=\"$1\"\n-\t\tshift\n-\t\t;;\n-\t--no-prefix)\n-\t\tprefix=\n-\t\t;;\n-\t--onto)\n-\t\tonto=\"$1\"\n+\twhile test $# -gt 0\n+\tdo\n+\t\topt=\"$1\"\n \t\tshift\n+\n+\t\tcase \"$opt\" in\n+\t\t-q)\n+\t\t\tquiet=1\n+\t\t\t;;\n+\t\t-d)\n+\t\t\tdebug=1\n+\t\t\t;;\n+\t\t--annotate)\n+\t\t\tannotate=\"$1\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--no-annotate)\n+\t\t\tannotate=\n+\t\t\t;;\n+\t\t-b)\n+\t\t\tbranch=\"$1\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t-P)\n+\t\t\tprefix=\"${1%/}\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t-m)\n+\t\t\tmessage=\"$1\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--no-prefix)\n+\t\t\tprefix=\n+\t\t\t;;\n+\t\t--onto)\n+\t\t\tonto=\"$1\"\n+\t\t\tshift\n+\t\t\t;;\n+\t\t--no-onto)\n+\t\t\tonto=\n+\t\t\t;;\n+\t\t--rejoin)\n+\t\t\trejoin=1\n+\t\t\t;;\n+\t\t--no-rejoin)\n+\t\t\trejoin=\n+\t\t\t;;\n+\t\t--ignore-joins)\n+\t\t\tignore_joins=1\n+\t\t\t;;\n+\t\t--no-ignore-joins)\n+\t\t\tignore_joins=\n+\t\t\t;;\n+\t\t--squash)\n+\t\t\tsquash=1\n+\t\t\t;;\n+\t\t--no-squash)\n+\t\t\tsquash=\n+\t\t\t;;\n+\t\t--)\n+\t\t\tbreak\n+\t\t\t;;\n+\t\t*)\n+\t\t\tdie \"Unexpected option: $opt\"\n+\t\t\t;;\n+\t\tesac\n+\tdone\n+\n+\tcommand=\"$1\"\n+\tshift\n+\n+\tcase \"$command\" in\n+\tadd|merge|pull)\n+\t\tdefault=\n \t\t;;\n-\t--no-onto)\n-\t\tonto=\n-\t\t;;\n-\t--rejoin)\n-\t\trejoin=1\n-\t\t;;\n-\t--no-rejoin)\n-\t\trejoin=\n-\t\t;;\n-\t--ignore-joins)\n-\t\tignore_joins=1\n-\t\t;;\n-\t--no-ignore-joins)\n-\t\tignore_joins=\n-\t\t;;\n-\t--squash)\n-\t\tsquash=1\n+\tsplit|push)\n+\t\tdefault=\"--default HEAD\"\n \t\t;;\n-\t--no-squash)\n-\t\tsquash=\n+\t*)\n+\t\tdie \"Unknown command '$command'\"\n \t\t;;\n-\t--)\n-\t\tbreak\n+\tesac\n+\n+\tif test -z \"$prefix\"\n+\tthen\n+\t\tdie \"You must provide the --prefix option.\"\n+\tfi\n+\n+\tcase \"$command\" in\n+\tadd)\n+\t\ttest -e \"$prefix\" &&\n+\t\t\tdie \"prefix '$prefix' already exists.\"\n \t\t;;\n \t*)\n-\t\tdie \"Unexpected option: $opt\"\n+\t\ttest -e \"$prefix\" ||\n+\t\t\tdie \"'$prefix' does not exist; use 'git subtree add'\"\n \t\t;;\n \tesac\n-done\n-\n-command=\"$1\"\n-shift\n-\n-case \"$command\" in\n-add|merge|pull)\n-\tdefault=\n-\t;;\n-split|push)\n-\tdefault=\"--default HEAD\"\n-\t;;\n-*)\n-\tdie \"Unknown command '$command'\"\n-\t;;\n-esac\n-\n-if test -z \"$prefix\"\n-then\n-\tdie \"You must provide the --prefix option.\"\n-fi\n-\n-case \"$command\" in\n-add)\n-\ttest -e \"$prefix\" &&\n-\t\tdie \"prefix '$prefix' already exists.\"\n-\t;;\n-*)\n-\ttest -e \"$prefix\" ||\n-\t\tdie \"'$prefix' does not exist; use 'git subtree add'\"\n-\t;;\n-esac\n-\n-dir=\"$(dirname \"$prefix/.\")\"\n-\n-if test \"$command\" != \"pull\" &&\n-\t\ttest \"$command\" != \"add\" &&\n-\t\ttest \"$command\" != \"push\"\n-then\n-\trevs=$(git rev-parse $default --revs-only \"$@\") || exit $?\n-\tdirs=$(git rev-parse --no-revs --no-flags \"$@\") || exit $?\n-\tensure_single_rev $revs\n-\tif test -n \"$dirs\"\n-\tthen\n-\t\tdie \"Error: Use --prefix instead of bare filenames.\"\n-\tfi\n-fi\n-\n-debug \"command: {$command}\"\n-debug \"quiet: {$quiet}\"\n-debug \"revs: {$revs}\"\n-debug \"dir: {$dir}\"\n-debug \"opts: {$*}\"\n-debug\n+\n+\tdir=\"$(dirname \"$prefix/.\")\"\n+\n+\tif test \"$command\" != \"pull\" &&\n+\t\t\ttest \"$command\" != \"add\" &&\n+\t\t\ttest \"$command\" != \"push\"\n+\tthen\n+\t\trevs=$(git rev-parse $default --revs-only \"$@\") || exit $?\n+\t\tdirs=$(git rev-parse --no-revs --no-flags \"$@\") || exit $?\n+\t\tensure_single_rev $revs\n+\t\tif test -n \"$dirs\"\n+\t\tthen\n+\t\t\tdie \"Error: Use --prefix instead of bare filenames.\"\n+\t\tfi\n+\tfi\n+\n+\tdebug \"command: {$command}\"\n+\tdebug \"quiet: {$quiet}\"\n+\tdebug \"revs: {$revs}\"\n+\tdebug \"dir: {$dir}\"\n+\tdebug \"opts: {$*}\"\n+\tdebug\n+\n+\t\"cmd_$command\" \"$@\"\n+}\n \n cache_setup () {\n \tcachedir=\"$GIT_DIR/subtree-cache/$$\"\n@@ -898,4 +903,4 @@ cmd_push () {\n \tfi\n }\n \n-\"cmd_$command\" \"$@\"\n+main \"$@\"\n-- \n2.31.1\n\n"},{"id":"423144","messageId":"20210427211748.2607474-15-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 14/30] subtree: drop support for git < 1.7","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:32Z","receivedAt":"2021-04-27T21:18:47Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nSuport for Git versions older than 1.7.0 (older than February 2010) was\nnice to have when git-subtree lived out-of-tree.  But now that it lives\nin git.git, it's not necessary to keep around.  While it's technically\nin contrib, with the standard 'git' packages for common systems\n(including Arch Linux and macOS) including git-subtree, it seems\nvanishingly likely to me that people are separately installing\ngit-subtree from git.git alongside an older 'git' install (although it\nalso seems vanishingly likely that people are still using >11 year old\ngit installs).\n\nNot that there's much reason to remove it either, it's not much code,\nand none of my changes depend on a newer git (to my knowledge, anyway;\nI'm not actually testing against older git).  I just figure it's an easy\npiece of fat to trim, in the journey to making the whole thing easier to\nhack on.\n\n\"Ignore space change\" is probably helpful when viewing this diff.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Include rationale in the the commit message.\n\n contrib/subtree/git-subtree.sh | 19 ++++---------------\n 1 file changed, 4 insertions(+), 15 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 9ca498f81c..4503564f7e 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -852,23 +852,12 @@ cmd_merge () {\n \t\trev=\"$new\"\n \tfi\n \n-\tversion=$(git version)\n-\tif test \"$version\" \\< \"git version 1.7\"\n+\tif test -n \"$message\"\n \tthen\n-\t\tif test -n \"$message\"\n-\t\tthen\n-\t\t\tgit merge -s subtree --message=\"$message\" \"$rev\"\n-\t\telse\n-\t\t\tgit merge -s subtree \"$rev\"\n-\t\tfi\n+\t\tgit merge -Xsubtree=\"$prefix\" \\\n+\t\t    --message=\"$message\" \"$rev\"\n \telse\n-\t\tif test -n \"$message\"\n-\t\tthen\n-\t\t\tgit merge -Xsubtree=\"$prefix\" \\\n-\t\t\t\t--message=\"$message\" \"$rev\"\n-\t\telse\n-\t\t\tgit merge -Xsubtree=\"$prefix\" $rev\n-\t\tfi\n+\t\tgit merge -Xsubtree=\"$prefix\" $rev\n \tfi\n }\n \n-- \n2.31.1\n\n"},{"id":"423145","messageId":"20210427211748.2607474-14-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 13/30] subtree: more consistent error propagation","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:31Z","receivedAt":"2021-04-27T21:18:48Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nEnsure that every $(subshell) that calls a function (as opposed to an\nexternal executable) is followed by `|| exit $?`.  Similarly, ensure that\nevery `cmd | while read; do ... done` loop is followed by `|| exit $?`.\n\nBoth of those constructs mean that it can miss `die` calls, and keep\nrunning when it shouldn't.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 28 ++++++++++++++--------------\n 1 file changed, 14 insertions(+), 14 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex d1ed7f9a6c..9ca498f81c 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -243,7 +243,7 @@ cache_miss () {\n }\n \n check_parents () {\n-\tmissed=$(cache_miss \"$1\")\n+\tmissed=$(cache_miss \"$1\") || exit $?\n \tlocal indent=$(($2 + 1))\n \tfor miss in $missed\n \tdo\n@@ -345,7 +345,7 @@ find_latest_squash () {\n \t\t\tsub=\n \t\t\t;;\n \t\tesac\n-\tdone\n+\tdone || exit $?\n }\n \n find_existing_splits () {\n@@ -394,7 +394,7 @@ find_existing_splits () {\n \t\t\tsub=\n \t\t\t;;\n \t\tesac\n-\tdone\n+\tdone || exit $?\n }\n \n copy_commit () {\n@@ -508,7 +508,7 @@ subtree_for_commit () {\n \t\ttest \"$type\" = \"commit\" && continue  # ignore submodules\n \t\techo $tree\n \t\tbreak\n-\tdone\n+\tdone || exit $?\n }\n \n tree_changed () {\n@@ -518,7 +518,7 @@ tree_changed () {\n \tthen\n \t\treturn 0   # weird parents, consider it changed\n \telse\n-\t\tptree=$(toptree_for_commit $1)\n+\t\tptree=$(toptree_for_commit $1) || exit $?\n \t\tif test \"$ptree\" != \"$tree\"\n \t\tthen\n \t\t\treturn 0   # changed\n@@ -652,7 +652,7 @@ process_split_commit () {\n \tprogress \"$revcount/$revmax ($createcount) [$extracount]\"\n \n \tdebug \"Processing commit: $rev\"\n-\texists=$(cache_get \"$rev\")\n+\texists=$(cache_get \"$rev\") || exit $?\n \tif test -n \"$exists\"\n \tthen\n \t\tdebug \"  prior: $exists\"\n@@ -661,10 +661,10 @@ process_split_commit () {\n \tcreatecount=$(($createcount + 1))\n \tdebug \"  parents: $parents\"\n \tcheck_parents \"$parents\" \"$indent\"\n-\tnewparents=$(cache_get $parents)\n+\tnewparents=$(cache_get $parents) || exit $?\n \tdebug \"  newparents: $newparents\"\n \n-\ttree=$(subtree_for_commit \"$rev\" \"$dir\")\n+\ttree=$(subtree_for_commit \"$rev\" \"$dir\") || exit $?\n \tdebug \"  tree is: $tree\"\n \n \t# ugly.  is there no better way to tell if this is a subtree\n@@ -750,7 +750,7 @@ cmd_add_commit () {\n \t\tcommit=$(add_squashed_msg \"$rev\" \"$dir\" |\n \t\t\tgit commit-tree \"$tree\" $headp -p \"$rev\") || exit $?\n \telse\n-\t\trevp=$(peel_committish \"$rev\") &&\n+\t\trevp=$(peel_committish \"$rev\") || exit $?\n \t\tcommit=$(add_msg \"$dir\" $headrev \"$rev\" |\n \t\t\tgit commit-tree \"$tree\" $headp -p \"$revp\") || exit $?\n \tfi\n@@ -773,10 +773,10 @@ cmd_split () {\n \t\t\t# any parent we find there can be used verbatim\n \t\t\tdebug \"  cache: $rev\"\n \t\t\tcache_set \"$rev\" \"$rev\"\n-\t\tdone\n+\t\tdone || exit $?\n \tfi\n \n-\tunrevs=\"$(find_existing_splits \"$dir\" \"$revs\")\"\n+\tunrevs=\"$(find_existing_splits \"$dir\" \"$revs\")\" || exit $?\n \n \t# We can't restrict rev-list to only $dir here, because some of our\n \t# parents have the $dir contents the root, and those won't match.\n@@ -792,7 +792,7 @@ cmd_split () {\n \t\tprocess_split_commit \"$rev\" \"$parents\" 0\n \tdone || exit $?\n \n-\tlatest_new=$(cache_get latest_new)\n+\tlatest_new=$(cache_get latest_new) || exit $?\n \tif test -z \"$latest_new\"\n \tthen\n \t\tdie \"No new revisions were found\"\n@@ -801,7 +801,7 @@ cmd_split () {\n \tif test -n \"$rejoin\"\n \tthen\n \t\tdebug \"Merging split branch into HEAD...\"\n-\t\tlatest_old=$(cache_get latest_old)\n+\t\tlatest_old=$(cache_get latest_old) || exit $?\n \t\tgit merge -s ours \\\n \t\t\t--allow-unrelated-histories \\\n \t\t\t-m \"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" \\\n@@ -834,7 +834,7 @@ cmd_merge () {\n \n \tif test -n \"$squash\"\n \tthen\n-\t\tfirst_split=\"$(find_latest_squash \"$dir\")\"\n+\t\tfirst_split=\"$(find_latest_squash \"$dir\")\" || exit $?\n \t\tif test -z \"$first_split\"\n \t\tthen\n \t\t\tdie \"Can't squash-merge: '$dir' was never added.\"\n-- \n2.31.1\n\n"},{"id":"423146","messageId":"20210427211748.2607474-16-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 15/30] subtree: use `git merge-base --is-ancestor`","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:33Z","receivedAt":"2021-04-27T21:18:48Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nInstead of writing a slow `rev_is_descendant_of_branch $a $b` function\nin shell, just use the fast `git merge-base --is-ancestor $b $a`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 16 +---------------\n 1 file changed, 1 insertion(+), 15 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 4503564f7e..70e16b807b 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -280,20 +280,6 @@ rev_exists () {\n \tfi\n }\n \n-rev_is_descendant_of_branch () {\n-\tnewrev=\"$1\"\n-\tbranch=\"$2\"\n-\tbranch_hash=$(git rev-parse \"$branch\")\n-\tmatch=$(git rev-list -1 \"$branch_hash\" \"^$newrev\")\n-\n-\tif test -z \"$match\"\n-\tthen\n-\t\treturn 0\n-\telse\n-\t\treturn 1\n-\tfi\n-}\n-\n # if a commit doesn't have a parent, this might not work.  But we only want\n # to remove the parent from the rev-list, and since it doesn't exist, it won't\n # be there anyway, so do nothing in that case.\n@@ -811,7 +797,7 @@ cmd_split () {\n \tthen\n \t\tif rev_exists \"refs/heads/$branch\"\n \t\tthen\n-\t\t\tif ! rev_is_descendant_of_branch \"$latest_new\" \"$branch\"\n+\t\t\tif ! git merge-base --is-ancestor \"$branch\" \"$latest_new\"\n \t\t\tthen\n \t\t\t\tdie \"Branch '$branch' is not an ancestor of commit '$latest_new'.\"\n \t\t\tfi\n-- \n2.31.1\n\n"},{"id":"423147","messageId":"20210427211748.2607474-17-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 16/30] subtree: use git-sh-setup's `say`","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:34Z","receivedAt":"2021-04-27T21:18:49Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nsubtree currently defines its own `say` implementation, rather than\nusing git-sh-setups's implementation.  Change that, don't re-invent the\nwheel.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 22 +++++++---------------\n 1 file changed, 7 insertions(+), 15 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 70e16b807b..bb4934dbc0 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -30,7 +30,6 @@ squash        merge subtree changes as a single commit\n \n PATH=$PATH:$(git --exec-path)\n \n-quiet=\n branch=\n debug=\n command=\n@@ -49,15 +48,8 @@ debug () {\n \tfi\n }\n \n-say () {\n-\tif test -z \"$quiet\"\n-\tthen\n-\t\tprintf \"%s\\n\" \"$*\" >&2\n-\tfi\n-}\n-\n progress () {\n-\tif test -z \"$quiet\"\n+\tif test -z \"$GIT_QUIET\"\n \tthen\n \t\tprintf \"%s\\r\" \"$*\" >&2\n \tfi\n@@ -93,7 +85,7 @@ main () {\n \n \t\tcase \"$opt\" in\n \t\t-q)\n-\t\t\tquiet=1\n+\t\t\tGIT_QUIET=1\n \t\t\t;;\n \t\t-d)\n \t\t\tdebug=1\n@@ -201,7 +193,7 @@ main () {\n \tfi\n \n \tdebug \"command: {$command}\"\n-\tdebug \"quiet: {$quiet}\"\n+\tdebug \"quiet: {$GIT_QUIET}\"\n \tdebug \"revs: {$revs}\"\n \tdebug \"dir: {$dir}\"\n \tdebug \"opts: {$*}\"\n@@ -698,7 +690,7 @@ cmd_add () {\n \n \t\tcmd_add_repository \"$@\"\n \telse\n-\t\tsay \"error: parameters were '$@'\"\n+\t\tsay >&2 \"error: parameters were '$@'\"\n \t\tdie \"Provide either a commit or a repository and commit.\"\n \tfi\n }\n@@ -742,7 +734,7 @@ cmd_add_commit () {\n \tfi\n \tgit reset \"$commit\" || exit $?\n \n-\tsay \"Added dir '$dir'\"\n+\tsay >&2 \"Added dir '$dir'\"\n }\n \n cmd_split () {\n@@ -807,7 +799,7 @@ cmd_split () {\n \t\tfi\n \t\tgit update-ref -m 'subtree split' \\\n \t\t\t\"refs/heads/$branch\" \"$latest_new\" || exit $?\n-\t\tsay \"$action branch '$branch'\"\n+\t\tsay >&2 \"$action branch '$branch'\"\n \tfi\n \techo \"$latest_new\"\n \texit 0\n@@ -830,7 +822,7 @@ cmd_merge () {\n \t\tsub=$2\n \t\tif test \"$sub\" = \"$rev\"\n \t\tthen\n-\t\t\tsay \"Subtree is already at commit $rev.\"\n+\t\t\tsay >&2 \"Subtree is already at commit $rev.\"\n \t\t\texit 0\n \t\tfi\n \t\tnew=$(new_squash_commit \"$old\" \"$sub\" \"$rev\") || exit $?\n-- \n2.31.1\n\n"},{"id":"423148","messageId":"20210427211748.2607474-18-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 17/30] subtree: use more explicit variable names for cmdline args","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:35Z","receivedAt":"2021-04-27T21:18:49Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nMake it painfully obvious when reading the code which variables are\ndirect parsings of command line arguments.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 132 ++++++++++++++++-----------------\n 1 file changed, 66 insertions(+), 66 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex bb4934dbc0..d7de4b0653 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -30,19 +30,19 @@ squash        merge subtree changes as a single commit\n \n PATH=$PATH:$(git --exec-path)\n \n-branch=\n-debug=\n-command=\n-onto=\n-rejoin=\n-ignore_joins=\n-annotate=\n-squash=\n-message=\n-prefix=\n+arg_debug=\n+arg_command=\n+arg_prefix=\n+arg_split_branch=\n+arg_split_onto=\n+arg_split_rejoin=\n+arg_split_ignore_joins=\n+arg_split_annotate=\n+arg_addmerge_squash=\n+arg_addmerge_message=\n \n debug () {\n-\tif test -n \"$debug\"\n+\tif test -n \"$arg_debug\"\n \tthen\n \t\tprintf \"%s\\n\" \"$*\" >&2\n \tfi\n@@ -88,54 +88,54 @@ main () {\n \t\t\tGIT_QUIET=1\n \t\t\t;;\n \t\t-d)\n-\t\t\tdebug=1\n+\t\t\targ_debug=1\n \t\t\t;;\n \t\t--annotate)\n-\t\t\tannotate=\"$1\"\n+\t\t\targ_split_annotate=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-annotate)\n-\t\t\tannotate=\n+\t\t\targ_split_annotate=\n \t\t\t;;\n \t\t-b)\n-\t\t\tbranch=\"$1\"\n+\t\t\targ_split_branch=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t-P)\n-\t\t\tprefix=\"${1%/}\"\n+\t\t\targ_prefix=\"${1%/}\"\n \t\t\tshift\n \t\t\t;;\n \t\t-m)\n-\t\t\tmessage=\"$1\"\n+\t\t\targ_addmerge_message=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-prefix)\n-\t\t\tprefix=\n+\t\t\targ_prefix=\n \t\t\t;;\n \t\t--onto)\n-\t\t\tonto=\"$1\"\n+\t\t\targ_split_onto=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-onto)\n-\t\t\tonto=\n+\t\t\targ_split_onto=\n \t\t\t;;\n \t\t--rejoin)\n-\t\t\trejoin=1\n+\t\t\targ_split_rejoin=1\n \t\t\t;;\n \t\t--no-rejoin)\n-\t\t\trejoin=\n+\t\t\targ_split_rejoin=\n \t\t\t;;\n \t\t--ignore-joins)\n-\t\t\tignore_joins=1\n+\t\t\targ_split_ignore_joins=1\n \t\t\t;;\n \t\t--no-ignore-joins)\n-\t\t\tignore_joins=\n+\t\t\targ_split_ignore_joins=\n \t\t\t;;\n \t\t--squash)\n-\t\t\tsquash=1\n+\t\t\targ_addmerge_squash=1\n \t\t\t;;\n \t\t--no-squash)\n-\t\t\tsquash=\n+\t\t\targ_addmerge_squash=\n \t\t\t;;\n \t\t--)\n \t\t\tbreak\n@@ -146,10 +146,10 @@ main () {\n \t\tesac\n \tdone\n \n-\tcommand=\"$1\"\n+\targ_command=\"$1\"\n \tshift\n \n-\tcase \"$command\" in\n+\tcase \"$arg_command\" in\n \tadd|merge|pull)\n \t\tdefault=\n \t\t;;\n@@ -157,31 +157,31 @@ main () {\n \t\tdefault=\"--default HEAD\"\n \t\t;;\n \t*)\n-\t\tdie \"Unknown command '$command'\"\n+\t\tdie \"Unknown command '$arg_command'\"\n \t\t;;\n \tesac\n \n-\tif test -z \"$prefix\"\n+\tif test -z \"$arg_prefix\"\n \tthen\n \t\tdie \"You must provide the --prefix option.\"\n \tfi\n \n-\tcase \"$command\" in\n+\tcase \"$arg_command\" in\n \tadd)\n-\t\ttest -e \"$prefix\" &&\n-\t\t\tdie \"prefix '$prefix' already exists.\"\n+\t\ttest -e \"$arg_prefix\" &&\n+\t\t\tdie \"prefix '$arg_prefix' already exists.\"\n \t\t;;\n \t*)\n-\t\ttest -e \"$prefix\" ||\n-\t\t\tdie \"'$prefix' does not exist; use 'git subtree add'\"\n+\t\ttest -e \"$arg_prefix\" ||\n+\t\t\tdie \"'$arg_prefix' does not exist; use 'git subtree add'\"\n \t\t;;\n \tesac\n \n-\tdir=\"$(dirname \"$prefix/.\")\"\n+\tdir=\"$(dirname \"$arg_prefix/.\")\"\n \n-\tif test \"$command\" != \"pull\" &&\n-\t\t\ttest \"$command\" != \"add\" &&\n-\t\t\ttest \"$command\" != \"push\"\n+\tif test \"$arg_command\" != \"pull\" &&\n+\t\t\ttest \"$arg_command\" != \"add\" &&\n+\t\t\ttest \"$arg_command\" != \"push\"\n \tthen\n \t\trevs=$(git rev-parse $default --revs-only \"$@\") || exit $?\n \t\tdirs=$(git rev-parse --no-revs --no-flags \"$@\") || exit $?\n@@ -192,14 +192,14 @@ main () {\n \t\tfi\n \tfi\n \n-\tdebug \"command: {$command}\"\n+\tdebug \"command: {$arg_command}\"\n \tdebug \"quiet: {$GIT_QUIET}\"\n \tdebug \"revs: {$revs}\"\n \tdebug \"dir: {$dir}\"\n \tdebug \"opts: {$*}\"\n \tdebug\n \n-\t\"cmd_$command\" \"$@\"\n+\t\"cmd_$arg_command\" \"$@\"\n }\n \n cache_setup () {\n@@ -333,7 +333,7 @@ find_existing_splits () {\n \tmain=\n \tsub=\n \tlocal grep_format=\"^git-subtree-dir: $dir/*\\$\"\n-\tif test -n \"$ignore_joins\"\n+\tif test -n \"$arg_split_ignore_joins\"\n \tthen\n \t\tgrep_format=\"^Add '$dir/' from commit '\"\n \tfi\n@@ -394,7 +394,7 @@ copy_commit () {\n \t\t\tGIT_COMMITTER_EMAIL \\\n \t\t\tGIT_COMMITTER_DATE\n \t\t(\n-\t\t\tprintf \"%s\" \"$annotate\"\n+\t\t\tprintf \"%s\" \"$arg_split_annotate\"\n \t\t\tcat\n \t\t) |\n \t\tgit commit-tree \"$2\" $3  # reads the rest of stdin\n@@ -405,9 +405,9 @@ add_msg () {\n \tdir=\"$1\"\n \tlatest_old=\"$2\"\n \tlatest_new=\"$3\"\n-\tif test -n \"$message\"\n+\tif test -n \"$arg_addmerge_message\"\n \tthen\n-\t\tcommit_message=\"$message\"\n+\t\tcommit_message=\"$arg_addmerge_message\"\n \telse\n \t\tcommit_message=\"Add '$dir/' from commit '$latest_new'\"\n \tfi\n@@ -421,9 +421,9 @@ add_msg () {\n }\n \n add_squashed_msg () {\n-\tif test -n \"$message\"\n+\tif test -n \"$arg_addmerge_message\"\n \tthen\n-\t\techo \"$message\"\n+\t\techo \"$arg_addmerge_message\"\n \telse\n \t\techo \"Merge commit '$1' as '$2'\"\n \tfi\n@@ -433,9 +433,9 @@ rejoin_msg () {\n \tdir=\"$1\"\n \tlatest_old=\"$2\"\n \tlatest_new=\"$3\"\n-\tif test -n \"$message\"\n+\tif test -n \"$arg_addmerge_message\"\n \tthen\n-\t\tcommit_message=\"$message\"\n+\t\tcommit_message=\"$arg_addmerge_message\"\n \telse\n \t\tcommit_message=\"Split '$dir/' into commit '$latest_new'\"\n \tfi\n@@ -722,7 +722,7 @@ cmd_add_commit () {\n \t\theadp=\n \tfi\n \n-\tif test -n \"$squash\"\n+\tif test -n \"$arg_addmerge_squash\"\n \tthen\n \t\trev=$(new_squash_commit \"\" \"\" \"$rev\") || exit $?\n \t\tcommit=$(add_squashed_msg \"$rev\" \"$dir\" |\n@@ -741,10 +741,10 @@ cmd_split () {\n \tdebug \"Splitting $dir...\"\n \tcache_setup || exit $?\n \n-\tif test -n \"$onto\"\n+\tif test -n \"$arg_split_onto\"\n \tthen\n-\t\tdebug \"Reading history for --onto=$onto...\"\n-\t\tgit rev-list $onto |\n+\t\tdebug \"Reading history for --onto=$arg_split_onto...\"\n+\t\tgit rev-list $arg_split_onto |\n \t\twhile read rev\n \t\tdo\n \t\t\t# the 'onto' history is already just the subdir, so\n@@ -776,7 +776,7 @@ cmd_split () {\n \t\tdie \"No new revisions were found\"\n \tfi\n \n-\tif test -n \"$rejoin\"\n+\tif test -n \"$arg_split_rejoin\"\n \tthen\n \t\tdebug \"Merging split branch into HEAD...\"\n \t\tlatest_old=$(cache_get latest_old) || exit $?\n@@ -785,21 +785,21 @@ cmd_split () {\n \t\t\t-m \"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" \\\n \t\t\t\"$latest_new\" >&2 || exit $?\n \tfi\n-\tif test -n \"$branch\"\n+\tif test -n \"$arg_split_branch\"\n \tthen\n-\t\tif rev_exists \"refs/heads/$branch\"\n+\t\tif rev_exists \"refs/heads/$arg_split_branch\"\n \t\tthen\n-\t\t\tif ! git merge-base --is-ancestor \"$branch\" \"$latest_new\"\n+\t\t\tif ! git merge-base --is-ancestor \"$arg_split_branch\" \"$latest_new\"\n \t\t\tthen\n-\t\t\t\tdie \"Branch '$branch' is not an ancestor of commit '$latest_new'.\"\n+\t\t\t\tdie \"Branch '$arg_split_branch' is not an ancestor of commit '$latest_new'.\"\n \t\t\tfi\n \t\t\taction='Updated'\n \t\telse\n \t\t\taction='Created'\n \t\tfi\n \t\tgit update-ref -m 'subtree split' \\\n-\t\t\t\"refs/heads/$branch\" \"$latest_new\" || exit $?\n-\t\tsay >&2 \"$action branch '$branch'\"\n+\t\t\t\"refs/heads/$arg_split_branch\" \"$latest_new\" || exit $?\n+\t\tsay >&2 \"$action branch '$arg_split_branch'\"\n \tfi\n \techo \"$latest_new\"\n \texit 0\n@@ -810,7 +810,7 @@ cmd_merge () {\n \tensure_single_rev $rev\n \tensure_clean\n \n-\tif test -n \"$squash\"\n+\tif test -n \"$arg_addmerge_squash\"\n \tthen\n \t\tfirst_split=\"$(find_latest_squash \"$dir\")\" || exit $?\n \t\tif test -z \"$first_split\"\n@@ -830,12 +830,12 @@ cmd_merge () {\n \t\trev=\"$new\"\n \tfi\n \n-\tif test -n \"$message\"\n+\tif test -n \"$arg_addmerge_message\"\n \tthen\n-\t\tgit merge -Xsubtree=\"$prefix\" \\\n-\t\t    --message=\"$message\" \"$rev\"\n+\t\tgit merge -Xsubtree=\"$arg_prefix\" \\\n+\t\t\t--message=\"$arg_addmerge_message\" \"$rev\"\n \telse\n-\t\tgit merge -Xsubtree=\"$prefix\" $rev\n+\t\tgit merge -Xsubtree=\"$arg_prefix\" $rev\n \tfi\n }\n \n@@ -863,7 +863,7 @@ cmd_push () {\n \t\trepository=$1\n \t\trefspec=$2\n \t\techo \"git push using: \" \"$repository\" \"$refspec\"\n-\t\tlocalrev=$(git subtree split --prefix=\"$prefix\") || die\n+\t\tlocalrev=$(git subtree split --prefix=\"$arg_prefix\") || die\n \t\tgit push \"$repository\" \"$localrev\":\"refs/heads/$refspec\"\n \telse\n \t\tdie \"'$dir' must already exist. Try 'git subtree add'.\"\n-- \n2.31.1\n\n"},{"id":"423149","messageId":"20210427211748.2607474-19-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 18/30] subtree: use \"$*\" instead of \"$@\" as appropriate","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:36Z","receivedAt":"2021-04-27T21:18:51Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\n\"$*\" is for when you want to concatenate the args together,\nwhitespace-separated; and \"$@\" is for when you want them to be separate\nstrings.\n\nThere are several places in subtree that erroneously use $@ when\nconcatenating args together into an error message.\n\nFor instance, if the args are argv[1]=\"dead\" and argv[2]=\"beef\", then\nthe line\n\n    die \"You must provide exactly one revision.  Got: '$@'\"\n\nsurely intends to call 'die' with the argument\n\n    argv[1]=\"You must provide exactly one revision.  Got: 'dead beef'\"\n\nhowever, because the line used $@ instead of $*, it will actually call\n'die' with the arguments\n\n    argv[1]=\"You must provide exactly one revision.  Got: 'dead\"\n    argv[2]=\"beef'\"\n\nThis isn't a big deal, because 'die' concatenates its arguments together\nanyway (using \"$*\").  But that doesn't change the fact that it was a\nmistake to use $@ instead of $*, even though in the end $@ still ended\nup doing the right thing.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Improve the commit message with quoting and clearer\n   explanation.\n\n contrib/subtree/git-subtree.sh | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex d7de4b0653..3105eb8033 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -58,14 +58,14 @@ progress () {\n assert () {\n \tif ! \"$@\"\n \tthen\n-\t\tdie \"assertion failed: \" \"$@\"\n+\t\tdie \"assertion failed: $*\"\n \tfi\n }\n \n ensure_single_rev () {\n \tif test $# -ne 1\n \tthen\n-\t\tdie \"You must provide exactly one revision.  Got: '$@'\"\n+\t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n \tfi\n }\n \n@@ -690,7 +690,7 @@ cmd_add () {\n \n \t\tcmd_add_repository \"$@\"\n \telse\n-\t\tsay >&2 \"error: parameters were '$@'\"\n+\t\tsay >&2 \"error: parameters were '$*'\"\n \t\tdie \"Provide either a commit or a repository and commit.\"\n \tfi\n }\n-- \n2.31.1\n\n"},{"id":"423150","messageId":"20210427211748.2607474-20-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 19/30] subtree: don't fuss with PATH","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:37Z","receivedAt":"2021-04-27T21:18:52Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nScripts needing to fuss with with adding $(git --exec-prefix) PATH\nbefore loading git-sh-setup is a thing of the past.  As far as I can\ntell, it's been a thing of the past since since Git v1.2.0 (2006-02-12),\nor more specifically, since 77cb17e940 (Exec git programs without using\nPATH, 2006-01-10).  However, it stuck around in contrib scripts and in\nthird-party scripts for long enough that it wasn't unusual to see.\n\nOriginally `git subtree` didn't fuss with PATH, but when people\n(including the original subtree author) had problems, because it was a\ncommon thing to see, it seemed that having subtree fuss with PATH was a\nreasonable solution.\n\nHere is an abridged history of fussing with PATH in subtree:\n\n  2987e6add3 (Add explicit path of git installation by 'git --exec-path', Gianluca Pacchiella, 2009-08-20)\n\n    As pointed out by documentation, the correct use of 'git-sh-setup' is\n    using $(git --exec-path) to avoid problems with not standard\n    installations.\n\n    -. git-sh-setup\n    +. $(git --exec-path)/git-sh-setup\n\n  33aaa697a2 (Improve patch to use git --exec-path: add to PATH instead, Avery Pennarun, 2009-08-26)\n\n    If you (like me) are using a modified git straight out of its source\n    directory (ie. without installing), then --exec-path isn't actually correct.\n    Add it to the PATH instead, so if it is correct, it'll work, but if it's\n    not, we fall back to the previous behaviour.\n\n    -. $(git --exec-path)/git-sh-setup\n    +PATH=$(git --exec-path):$PATH\n    +. git-sh-setup\n\n  9c632ea29c ((Hopefully) fix PATH setting for msysgit, Avery Pennarun, 2010-06-24)\n\n    Reported by Evan Shaw.  The problem is that $(git --exec-path) includes a\n    'git' binary which is incompatible with the one in /usr/bin; if you run it,\n    it gives you an error about libiconv2.dll.\n\n    +OPATH=$PATH\n     PATH=$(git --exec-path):$PATH\n     . git-sh-setup\n    +PATH=$OPATH  # apparently needed for some versions of msysgit\n\n  df2302d774 (Another fix for PATH and msysgit, Avery Pennarun, 2010-06-24)\n\n    Evan Shaw tells me the previous fix didn't work.  Let's use this one\n    instead, which he says does work.\n\n    This fix is kind of wrong because it will run the \"correct\" git-sh-setup\n    *after* the one in /usr/bin, if there is one, which could be weird if you\n    have multiple versions of git installed.  But it works on my Linux and his\n    msysgit, so it's obviously better than what we had before.\n\n    -OPATH=$PATH\n    -PATH=$(git --exec-path):$PATH\n    +PATH=$PATH:$(git --exec-path)\n     . git-sh-setup\n    -PATH=$OPATH  # apparently needed for some versions of msysgit\n\nFirst of all, I disagree with Gianluca's reading of the documentation:\n - I haven't gone back to read what the documentation said in 2009, but\n   in my reading of the 2021 documentation is that it includes \"$(git\n   --exec-path)/\" in the synopsis for illustrative purposes, not to say\n   it's the proper way.\n - After being executed by `git`, the git exec path should be the very\n   first entry in PATH, so it shouldn't matter.\n - None of the scripts that are part of git do it that way.\n\nBut secondly, the root reason for fussing with PATH seems to be that\nAvery didn't know that he needs to set GIT_EXEC_PATH if he's going to\nuse git from the source directory without installing.\n\nAnd finally, Evan's issue is clearly just a bug in msysgit.  I assume\nthat msysgit has since fixed the issue, and also msysgit has been\ndeprecated for 6 years now, so let's drop the workaround for it.\n\nSo, remove the line fussing with PATH.  However, since subtree *is* in\n'contrib/' and it might get installed in funny ways by users\nafter-the-fact, add a sanity check to the top of the script, checking\nthat it is installed correctly.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv3:\n - Fix capitalization in the commit message.\n\n contrib/subtree/git-subtree.sh | 18 ++++++++++++++++--\n 1 file changed, 16 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 3105eb8033..af636fbb43 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -5,6 +5,22 @@\n # Copyright (C) 2009 Avery Pennarun <apenwarr@gmail.com>\n #\n \n+if test -z \"$GIT_EXEC_PATH\" || test \"${PATH#\"${GIT_EXEC_PATH}:\"}\" = \"$PATH\" || ! test -f \"$GIT_EXEC_PATH/git-sh-setup\"\n+then\n+\techo >&2 'It looks like either your git installation or your'\n+\techo >&2 'git-subtree installation is broken.'\n+\techo >&2\n+\techo >&2 \"Tips:\"\n+\techo >&2 \" - If \\`git --exec-path\\` does not print the correct path to\"\n+\techo >&2 \"   your git install directory, then set the GIT_EXEC_PATH\"\n+\techo >&2 \"   environment variable to the correct directory.\"\n+\techo >&2 \" - Make sure that your \\`${0##*/}\\` file is either in your\"\n+\techo >&2 \"   PATH or in your git exec path (\\`$(git --exec-path)\\`).\"\n+\techo >&2 \" - You should run git-subtree as \\`git ${0##*/git-}\\`,\"\n+\techo >&2 \"   not as \\`${0##*/}\\`.\" >&2\n+\texit 126\n+fi\n+\n OPTS_SPEC=\"\\\n git subtree add   --prefix=<prefix> <commit>\n git subtree add   --prefix=<prefix> <repository> <ref>\n@@ -28,8 +44,6 @@ rejoin        merge the new branch back into HEAD\n squash        merge subtree changes as a single commit\n \"\n \n-PATH=$PATH:$(git --exec-path)\n-\n arg_debug=\n arg_command=\n arg_prefix=\n-- \n2.31.1\n\n"},{"id":"423151","messageId":"20210427211748.2607474-21-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 20/30] subtree: use \"^{commit}\" instead of \"^0\"","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:38Z","receivedAt":"2021-04-27T21:18:54Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThey are synonyms.  Both are used in the file.  ^{commit} is clearer, so\n\"standardize\" on that.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex af636fbb43..ee7fda3672 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -316,7 +316,7 @@ find_latest_squash () {\n \t\t\tmain=\"$b\"\n \t\t\t;;\n \t\tgit-subtree-split:)\n-\t\t\tsub=\"$(git rev-parse \"$b^0\")\" ||\n+\t\t\tsub=\"$(git rev-parse \"$b^{commit}\")\" ||\n \t\t\tdie \"could not rev-parse split hash $b from commit $sq\"\n \t\t\t;;\n \t\tEND)\n@@ -363,7 +363,7 @@ find_existing_splits () {\n \t\t\tmain=\"$b\"\n \t\t\t;;\n \t\tgit-subtree-split:)\n-\t\t\tsub=\"$(git rev-parse \"$b^0\")\" ||\n+\t\t\tsub=\"$(git rev-parse \"$b^{commit}\")\" ||\n \t\t\tdie \"could not rev-parse split hash $b from commit $sq\"\n \t\t\t;;\n \t\tEND)\n-- \n2.31.1\n\n"},{"id":"423152","messageId":"20210427211748.2607474-22-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 21/30] subtree: parse revs in individual cmd_ functions","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:39Z","receivedAt":"2021-04-27T21:18:54Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nThe main argument parser goes ahead and tries to parse revs to make\nthings simpler for the sub-command implementations.  But, it includes\nenough special cases for different sub-commands.  And it's difficult\nhaving having to think about \"is this info coming from an argument, or a\nglobal variable?\".  So the main argument parser's effort to make things\n\"simpler\" ends up just making it more confusing and complicated.\n\nBegone with the 'revs' global variable; parse 'rev=$(...)' as needed in\nindividual 'cmd_*' functions.\n\nBegone with the 'default' global variable.  Its would-be value is\nknowable just from which function we're in.\n\nBegone with the 'ensure_single_rev' function.  Its functionality can be\nachieved by passing '--verify' to 'git rev-parse'.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 62 +++++++++++++---------------------\n 1 file changed, 24 insertions(+), 38 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex ee7fda3672..0df8d1b7d4 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -76,13 +76,6 @@ assert () {\n \tfi\n }\n \n-ensure_single_rev () {\n-\tif test $# -ne 1\n-\tthen\n-\t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n-\tfi\n-}\n-\n main () {\n \tif test $# -eq 0\n \tthen\n@@ -164,11 +157,8 @@ main () {\n \tshift\n \n \tcase \"$arg_command\" in\n-\tadd|merge|pull)\n-\t\tdefault=\n-\t\t;;\n-\tsplit|push)\n-\t\tdefault=\"--default HEAD\"\n+\tadd|merge|pull|split|push)\n+\t\t:\n \t\t;;\n \t*)\n \t\tdie \"Unknown command '$arg_command'\"\n@@ -193,22 +183,8 @@ main () {\n \n \tdir=\"$(dirname \"$arg_prefix/.\")\"\n \n-\tif test \"$arg_command\" != \"pull\" &&\n-\t\t\ttest \"$arg_command\" != \"add\" &&\n-\t\t\ttest \"$arg_command\" != \"push\"\n-\tthen\n-\t\trevs=$(git rev-parse $default --revs-only \"$@\") || exit $?\n-\t\tdirs=$(git rev-parse --no-revs --no-flags \"$@\") || exit $?\n-\t\tensure_single_rev $revs\n-\t\tif test -n \"$dirs\"\n-\t\tthen\n-\t\t\tdie \"Error: Use --prefix instead of bare filenames.\"\n-\t\tfi\n-\tfi\n-\n \tdebug \"command: {$arg_command}\"\n \tdebug \"quiet: {$GIT_QUIET}\"\n-\tdebug \"revs: {$revs}\"\n \tdebug \"dir: {$dir}\"\n \tdebug \"opts: {$*}\"\n \tdebug\n@@ -714,14 +690,13 @@ cmd_add_repository () {\n \trepository=$1\n \trefspec=$2\n \tgit fetch \"$@\" || exit $?\n-\trevs=FETCH_HEAD\n-\tset -- $revs\n-\tcmd_add_commit \"$@\"\n+\tcmd_add_commit FETCH_HEAD\n }\n \n cmd_add_commit () {\n-\trev=$(git rev-parse $default --revs-only \"$@\") || exit $?\n-\tensure_single_rev $rev\n+\t# The rev has already been validated by cmd_add(), we just\n+\t# need to normalize it.\n+\trev=$(git rev-parse --verify \"$1^{commit}\") || exit $?\n \n \tdebug \"Adding $dir as '$rev'...\"\n \tgit read-tree --prefix=\"$dir\" $rev || exit $?\n@@ -752,6 +727,17 @@ cmd_add_commit () {\n }\n \n cmd_split () {\n+\tif test $# -eq 0\n+\tthen\n+\t\trev=$(git rev-parse HEAD)\n+\telif test $# -eq 1\n+\tthen\n+\t\trev=$(git rev-parse -q --verify \"$1^{commit}\") ||\n+\t\t\tdie \"'$1' does not refer to a commit\"\n+\telse\n+\t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n+\tfi\n+\n \tdebug \"Splitting $dir...\"\n \tcache_setup || exit $?\n \n@@ -768,12 +754,12 @@ cmd_split () {\n \t\tdone || exit $?\n \tfi\n \n-\tunrevs=\"$(find_existing_splits \"$dir\" \"$revs\")\" || exit $?\n+\tunrevs=\"$(find_existing_splits \"$dir\" \"$rev\")\" || exit $?\n \n \t# We can't restrict rev-list to only $dir here, because some of our\n \t# parents have the $dir contents the root, and those won't match.\n \t# (and rev-list --follow doesn't seem to solve this)\n-\tgrl='git rev-list --topo-order --reverse --parents $revs $unrevs'\n+\tgrl='git rev-list --topo-order --reverse --parents $rev $unrevs'\n \trevmax=$(eval \"$grl\" | wc -l)\n \trevcount=0\n \tcreatecount=0\n@@ -820,8 +806,10 @@ cmd_split () {\n }\n \n cmd_merge () {\n-\trev=$(git rev-parse $default --revs-only \"$@\") || exit $?\n-\tensure_single_rev $rev\n+\ttest $# -eq 1 ||\n+\t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n+\trev=$(git rev-parse -q --verify \"$1^{commit}\") ||\n+\t\tdie \"'$1' does not refer to a commit\"\n \tensure_clean\n \n \tif test -n \"$arg_addmerge_squash\"\n@@ -861,9 +849,7 @@ cmd_pull () {\n \tensure_clean\n \tensure_valid_ref_format \"$2\"\n \tgit fetch \"$@\" || exit $?\n-\trevs=FETCH_HEAD\n-\tset -- $revs\n-\tcmd_merge \"$@\"\n+\tcmd_merge FETCH_HEAD\n }\n \n cmd_push () {\n-- \n2.31.1\n\n"},{"id":"423153","messageId":"20210427211748.2607474-23-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 22/30] subtree: remove duplicate check","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:40Z","receivedAt":"2021-04-27T21:18:55Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\n`cmd_add` starts with a check that the directory doesn't yet exist.\nHowever, the `main` function performs the exact same check before\ncalling `cmd_add`.  So remove the check from `cmd_add`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 4 ----\n 1 file changed, 4 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 0df8d1b7d4..7fbd8481ed 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -655,10 +655,6 @@ process_split_commit () {\n }\n \n cmd_add () {\n-\tif test -e \"$dir\"\n-\tthen\n-\t\tdie \"'$dir' already exists.  Cannot add.\"\n-\tfi\n \n \tensure_clean\n \n-- \n2.31.1\n\n"},{"id":"423154","messageId":"20210427211748.2607474-25-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 24/30] subtree: don't let debug and progress output clash","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:42Z","receivedAt":"2021-04-27T21:18:56Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nCurrently, debug output (triggered by passing '-d') and progress output\nstomp on each other.  The debug output is just streamed as lines to\nstderr, and the progress output is sent to stderr as '%s\\r'.  When\nwriting to a file, it is awkward to read and difficult to distinguish\nbetween the debug output and a progress line.  When writing to a\nterminal the debug lines hide progress lines.\n\nSo, when '-d' has been passed, spit out progress as 'progress: %s\\n',\ninstead of as '%s\\r', so that it can be detected, and so that the debug\nlines don't overwrite the progress when written to a terminal.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Reword the commit message to be clearer.\n - Add comments to the code.\n - Flip the `if` and `else` cases around, so that the comments\n   read better.\n\n contrib/subtree/git-subtree.sh | 22 +++++++++++++++++++++-\n 1 file changed, 21 insertions(+), 1 deletion(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 441571c85a..53a1a025f5 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -67,7 +67,27 @@ debug () {\n progress () {\n \tif test -z \"$GIT_QUIET\"\n \tthen\n-\t\tprintf \"%s\\r\" \"$*\" >&2\n+\t\tif test -z \"$arg_debug\"\n+\t\tthen\n+\t\t\t# Debug mode is off.\n+\t\t\t#\n+\t\t\t# Print one progress line that we keep updating (use\n+\t\t\t# \"\\r\" to return to the beginning of the line, rather\n+\t\t\t# than \"\\n\" to start a new line).  This only really\n+\t\t\t# works when stderr is a terminal.\n+\t\t\tprintf \"%s\\r\" \"$*\" >&2\n+\t\telse\n+\t\t\t# Debug mode is on.  The `debug` function is regularly\n+\t\t\t# printing to stderr.\n+\t\t\t#\n+\t\t\t# Don't do the one-line-with-\"\\r\" thing, because on a\n+\t\t\t# terminal the debug output would overwrite and hide the\n+\t\t\t# progress output.  Add a \"progress:\" prefix to make the\n+\t\t\t# progress output and the debug output easy to\n+\t\t\t# distinguish.  This ensures maximum readability whether\n+\t\t\t# stderr is a terminal or a file.\n+\t\t\tprintf \"progress: %s\\n\" \"$*\" >&2\n+\t\tfi\n \tfi\n }\n \n-- \n2.31.1\n\n"},{"id":"423155","messageId":"20210427211748.2607474-26-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 25/30] subtree: have $indent actually affect indentation","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:43Z","receivedAt":"2021-04-27T21:18:56Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nCurrently, the $indent variable is just used to track how deeply we're\nnested, and the debug log is indented by things like\n\n   debug \"  foo\"\n\nThat is: The indentation-level is hard-coded.  It used to be that the\ncode couldn't recurse, so the indentation level could be known\nstatically, so it made sense to just hard-code it in the\noutput. However, since 315a84f9aa (\"subtree: use commits before rejoins\nfor splits\", 2018-09-28), it can now recurse, and the debug log is\nmisleading.\n\nSo fix that.  Indent according to $indent.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh | 42 +++++++++++++++++++---------------\n 1 file changed, 24 insertions(+), 18 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 53a1a025f5..768fa7b6b6 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -55,11 +55,13 @@ arg_split_annotate=\n arg_addmerge_squash=\n arg_addmerge_message=\n \n+indent=0\n+\n # Usage: debug [MSG...]\n debug () {\n \tif test -n \"$arg_debug\"\n \tthen\n-\t\tprintf \"%s\\n\" \"$*\" >&2\n+\t\tprintf \"%$(($indent * 2))s%s\\n\" '' \"$*\" >&2\n \tfi\n }\n \n@@ -251,17 +253,17 @@ cache_miss () {\n \tdone\n }\n \n-# Usage: check_parents PARENTS_EXPR INDENT\n+# Usage: check_parents PARENTS_EXPR\n check_parents () {\n-\tassert test $# = 2\n+\tassert test $# = 1\n \tmissed=$(cache_miss \"$1\") || exit $?\n-\tlocal indent=$(($2 + 1))\n+\tlocal indent=$(($indent + 1))\n \tfor miss in $missed\n \tdo\n \t\tif ! test -r \"$cachedir/notree/$miss\"\n \t\tthen\n-\t\t\tdebug \"  incorrect order: $miss\"\n-\t\t\tprocess_split_commit \"$miss\" \"\" \"$indent\"\n+\t\t\tdebug \"incorrect order: $miss\"\n+\t\t\tprocess_split_commit \"$miss\" \"\"\n \t\tfi\n \tdone\n }\n@@ -314,6 +316,8 @@ try_remove_previous () {\n find_latest_squash () {\n \tassert test $# = 1\n \tdebug \"Looking for latest squash ($dir)...\"\n+\tlocal indent=$(($indent + 1))\n+\n \tdir=\"$1\"\n \tsq=\n \tmain=\n@@ -360,6 +364,8 @@ find_latest_squash () {\n find_existing_splits () {\n \tassert test $# = 2\n \tdebug \"Looking for prior splits...\"\n+\tlocal indent=$(($indent + 1))\n+\n \tdir=\"$1\"\n \trev=\"$2\"\n \tmain=\n@@ -385,7 +391,7 @@ find_existing_splits () {\n \t\t\tdie \"could not rev-parse split hash $b from commit $sq\"\n \t\t\t;;\n \t\tEND)\n-\t\t\tdebug \"  Main is: '$main'\"\n+\t\t\tdebug \"Main is: '$main'\"\n \t\t\tif test -z \"$main\" -a -n \"$sub\"\n \t\t\tthen\n \t\t\t\t# squash commits refer to a subtree\n@@ -668,12 +674,11 @@ ensure_valid_ref_format () {\n \t\tdie \"'$1' does not look like a ref\"\n }\n \n-# Usage: process_split_commit REV PARENTS INDENT\n+# Usage: process_split_commit REV PARENTS\n process_split_commit () {\n-\tassert test $# = 3\n+\tassert test $# = 2\n \tlocal rev=\"$1\"\n \tlocal parents=\"$2\"\n-\tlocal indent=$3\n \n \tif test $indent -eq 0\n \tthen\n@@ -688,20 +693,21 @@ process_split_commit () {\n \tprogress \"$revcount/$revmax ($createcount) [$extracount]\"\n \n \tdebug \"Processing commit: $rev\"\n+\tlocal indent=$(($indent + 1))\n \texists=$(cache_get \"$rev\") || exit $?\n \tif test -n \"$exists\"\n \tthen\n-\t\tdebug \"  prior: $exists\"\n+\t\tdebug \"prior: $exists\"\n \t\treturn\n \tfi\n \tcreatecount=$(($createcount + 1))\n-\tdebug \"  parents: $parents\"\n-\tcheck_parents \"$parents\" \"$indent\"\n+\tdebug \"parents: $parents\"\n+\tcheck_parents \"$parents\"\n \tnewparents=$(cache_get $parents) || exit $?\n-\tdebug \"  newparents: $newparents\"\n+\tdebug \"newparents: $newparents\"\n \n \ttree=$(subtree_for_commit \"$rev\" \"$dir\") || exit $?\n-\tdebug \"  tree is: $tree\"\n+\tdebug \"tree is: $tree\"\n \n \t# ugly.  is there no better way to tell if this is a subtree\n \t# vs. a mainline commit?  Does it matter?\n@@ -716,7 +722,7 @@ process_split_commit () {\n \tfi\n \n \tnewrev=$(copy_or_skip \"$rev\" \"$tree\" \"$newparents\") || exit $?\n-\tdebug \"  newrev is: $newrev\"\n+\tdebug \"newrev is: $newrev\"\n \tcache_set \"$rev\" \"$newrev\"\n \tcache_set latest_new \"$newrev\"\n \tcache_set latest_old \"$rev\"\n@@ -820,7 +826,7 @@ cmd_split () {\n \t\tdo\n \t\t\t# the 'onto' history is already just the subdir, so\n \t\t\t# any parent we find there can be used verbatim\n-\t\t\tdebug \"  cache: $rev\"\n+\t\t\tdebug \"cache: $rev\"\n \t\t\tcache_set \"$rev\" \"$rev\"\n \t\tdone || exit $?\n \tfi\n@@ -838,7 +844,7 @@ cmd_split () {\n \teval \"$grl\" |\n \twhile read rev parents\n \tdo\n-\t\tprocess_split_commit \"$rev\" \"$parents\" 0\n+\t\tprocess_split_commit \"$rev\" \"$parents\"\n \tdone || exit $?\n \n \tlatest_new=$(cache_get latest_new) || exit $?\n-- \n2.31.1\n\n"},{"id":"423156","messageId":"20210427211748.2607474-24-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 23/30] subtree: add comments and sanity checks","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:41Z","receivedAt":"2021-04-27T21:18:57Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nFor each function in subtree, add a usage comment saying what the\narguments are, and add an `assert` checking the number of arguments.\n\nIn figuring out each thing's arguments in order to write those comments\nand assertions, it turns out that find_existing_splits is written as if\nit takes multiple 'revs', but it is in fact only ever passed a single\n'rev':\n\n\tunrevs=\"$(find_existing_splits \"$dir\" \"$rev\")\" || exit $?\n\nSo go ahead and codify that by documenting and asserting that it takes\nexactly two arguments, one dir and one rev.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - Expand on the the commit message.\n - Fix capitalization in one of the comments.\n\n contrib/subtree/git-subtree.sh | 64 ++++++++++++++++++++++++++++++++--\n 1 file changed, 61 insertions(+), 3 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 7fbd8481ed..441571c85a 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -55,6 +55,7 @@ arg_split_annotate=\n arg_addmerge_squash=\n arg_addmerge_message=\n \n+# Usage: debug [MSG...]\n debug () {\n \tif test -n \"$arg_debug\"\n \tthen\n@@ -62,6 +63,7 @@ debug () {\n \tfi\n }\n \n+# Usage: progress [MSG...]\n progress () {\n \tif test -z \"$GIT_QUIET\"\n \tthen\n@@ -69,6 +71,7 @@ progress () {\n \tfi\n }\n \n+# Usage: assert CMD...\n assert () {\n \tif ! \"$@\"\n \tthen\n@@ -192,7 +195,9 @@ main () {\n \t\"cmd_$arg_command\" \"$@\"\n }\n \n+# Usage: cache_setup\n cache_setup () {\n+\tassert test $# = 0\n \tcachedir=\"$GIT_DIR/subtree-cache/$$\"\n \trm -rf \"$cachedir\" ||\n \t\tdie \"Can't delete old cachedir: $cachedir\"\n@@ -203,6 +208,7 @@ cache_setup () {\n \tdebug \"Using cachedir: $cachedir\" >&2\n }\n \n+# Usage: cache_get [REVS...]\n cache_get () {\n \tfor oldrev in \"$@\"\n \tdo\n@@ -214,6 +220,7 @@ cache_get () {\n \tdone\n }\n \n+# Usage: cache_miss [REVS...]\n cache_miss () {\n \tfor oldrev in \"$@\"\n \tdo\n@@ -224,7 +231,9 @@ cache_miss () {\n \tdone\n }\n \n+# Usage: check_parents PARENTS_EXPR INDENT\n check_parents () {\n+\tassert test $# = 2\n \tmissed=$(cache_miss \"$1\") || exit $?\n \tlocal indent=$(($2 + 1))\n \tfor miss in $missed\n@@ -237,11 +246,15 @@ check_parents () {\n \tdone\n }\n \n+# Usage: set_notree REV\n set_notree () {\n+\tassert test $# = 1\n \techo \"1\" > \"$cachedir/notree/$1\"\n }\n \n+# Usage: cache_set OLDREV NEWREV\n cache_set () {\n+\tassert test $# = 2\n \toldrev=\"$1\"\n \tnewrev=\"$2\"\n \tif test \"$oldrev\" != \"latest_old\" &&\n@@ -253,7 +266,9 @@ cache_set () {\n \techo \"$newrev\" >\"$cachedir/$oldrev\"\n }\n \n+# Usage: rev_exists REV\n rev_exists () {\n+\tassert test $# = 1\n \tif git rev-parse \"$1\" >/dev/null 2>&1\n \tthen\n \t\treturn 0\n@@ -262,17 +277,22 @@ rev_exists () {\n \tfi\n }\n \n-# if a commit doesn't have a parent, this might not work.  But we only want\n+# Usage: try_remove_previous REV\n+#\n+# If a commit doesn't have a parent, this might not work.  But we only want\n # to remove the parent from the rev-list, and since it doesn't exist, it won't\n # be there anyway, so do nothing in that case.\n try_remove_previous () {\n+\tassert test $# = 1\n \tif rev_exists \"$1^\"\n \tthen\n \t\techo \"^$1^\"\n \tfi\n }\n \n+# Usage: find_latest_squash DIR\n find_latest_squash () {\n+\tassert test $# = 1\n \tdebug \"Looking for latest squash ($dir)...\"\n \tdir=\"$1\"\n \tsq=\n@@ -316,10 +336,12 @@ find_latest_squash () {\n \tdone || exit $?\n }\n \n+# Usage: find_existing_splits DIR REV\n find_existing_splits () {\n+\tassert test $# = 2\n \tdebug \"Looking for prior splits...\"\n \tdir=\"$1\"\n-\trevs=\"$2\"\n+\trev=\"$2\"\n \tmain=\n \tsub=\n \tlocal grep_format=\"^git-subtree-dir: $dir/*\\$\"\n@@ -328,7 +350,7 @@ find_existing_splits () {\n \t\tgrep_format=\"^Add '$dir/' from commit '\"\n \tfi\n \tgit log --grep=\"$grep_format\" \\\n-\t\t--no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' $revs |\n+\t\t--no-show-signature --pretty=format:'START %H%n%s%n%n%b%nEND%n' \"$rev\" |\n \twhile read a b junk\n \tdo\n \t\tcase \"$a\" in\n@@ -365,7 +387,9 @@ find_existing_splits () {\n \tdone || exit $?\n }\n \n+# Usage: copy_commit REV TREE FLAGS_STR\n copy_commit () {\n+\tassert test $# = 3\n \t# We're going to set some environment vars here, so\n \t# do it in a subshell to get rid of them safely later\n \tdebug copy_commit \"{$1}\" \"{$2}\" \"{$3}\"\n@@ -391,7 +415,9 @@ copy_commit () {\n \t) || die \"Can't copy commit $1\"\n }\n \n+# Usage: add_msg DIR LATEST_OLD LATEST_NEW\n add_msg () {\n+\tassert test $# = 3\n \tdir=\"$1\"\n \tlatest_old=\"$2\"\n \tlatest_new=\"$3\"\n@@ -410,7 +436,9 @@ add_msg () {\n \tEOF\n }\n \n+# Usage: add_squashed_msg REV DIR\n add_squashed_msg () {\n+\tassert test $# = 2\n \tif test -n \"$arg_addmerge_message\"\n \tthen\n \t\techo \"$arg_addmerge_message\"\n@@ -419,7 +447,9 @@ add_squashed_msg () {\n \tfi\n }\n \n+# Usage: rejoin_msg DIR LATEST_OLD LATEST_NEW\n rejoin_msg () {\n+\tassert test $# = 3\n \tdir=\"$1\"\n \tlatest_old=\"$2\"\n \tlatest_new=\"$3\"\n@@ -438,7 +468,9 @@ rejoin_msg () {\n \tEOF\n }\n \n+# Usage: squash_msg DIR OLD_SUBTREE_COMMIT NEW_SUBTREE_COMMIT\n squash_msg () {\n+\tassert test $# = 3\n \tdir=\"$1\"\n \toldsub=\"$2\"\n \tnewsub=\"$3\"\n@@ -460,12 +492,16 @@ squash_msg () {\n \techo \"git-subtree-split: $newsub\"\n }\n \n+# Usage: toptree_for_commit COMMIT\n toptree_for_commit () {\n+\tassert test $# = 1\n \tcommit=\"$1\"\n \tgit rev-parse --verify \"$commit^{tree}\" || exit $?\n }\n \n+# Usage: subtree_for_commit COMMIT DIR\n subtree_for_commit () {\n+\tassert test $# = 2\n \tcommit=\"$1\"\n \tdir=\"$2\"\n \tgit ls-tree \"$commit\" -- \"$dir\" |\n@@ -479,7 +515,9 @@ subtree_for_commit () {\n \tdone || exit $?\n }\n \n+# Usage: tree_changed TREE [PARENTS...]\n tree_changed () {\n+\tassert test $# -gt 0\n \ttree=$1\n \tshift\n \tif test $# -ne 1\n@@ -496,7 +534,9 @@ tree_changed () {\n \tfi\n }\n \n+# Usage: new_squash_commit OLD_SQUASHED_COMMIT OLD_NONSQUASHED_COMMIT NEW_NONSQUASHED_COMMIT\n new_squash_commit () {\n+\tassert test $# = 3\n \told=\"$1\"\n \toldsub=\"$2\"\n \tnewsub=\"$3\"\n@@ -511,7 +551,9 @@ new_squash_commit () {\n \tfi\n }\n \n+# Usage: copy_or_skip REV TREE NEWPARENTS\n copy_or_skip () {\n+\tassert test $# = 3\n \trev=\"$1\"\n \ttree=\"$2\"\n \tnewparents=\"$3\"\n@@ -586,7 +628,9 @@ copy_or_skip () {\n \tfi\n }\n \n+# Usage: ensure_clean\n ensure_clean () {\n+\tassert test $# = 0\n \tif ! git diff-index HEAD --exit-code --quiet 2>&1\n \tthen\n \t\tdie \"Working tree has modifications.  Cannot add.\"\n@@ -597,12 +641,16 @@ ensure_clean () {\n \tfi\n }\n \n+# Usage: ensure_valid_ref_format REF\n ensure_valid_ref_format () {\n+\tassert test $# = 1\n \tgit check-ref-format \"refs/heads/$1\" ||\n \t\tdie \"'$1' does not look like a ref\"\n }\n \n+# Usage: process_split_commit REV PARENTS INDENT\n process_split_commit () {\n+\tassert test $# = 3\n \tlocal rev=\"$1\"\n \tlocal parents=\"$2\"\n \tlocal indent=$3\n@@ -654,6 +702,8 @@ process_split_commit () {\n \tcache_set latest_old \"$rev\"\n }\n \n+# Usage: cmd_add REV\n+#    Or: cmd_add REPOSITORY REF\n cmd_add () {\n \n \tensure_clean\n@@ -681,7 +731,9 @@ cmd_add () {\n \tfi\n }\n \n+# Usage: cmd_add_repository REPOSITORY REFSPEC\n cmd_add_repository () {\n+\tassert test $# = 2\n \techo \"git fetch\" \"$@\"\n \trepository=$1\n \trefspec=$2\n@@ -689,9 +741,11 @@ cmd_add_repository () {\n \tcmd_add_commit FETCH_HEAD\n }\n \n+# Usage: cmd_add_commit REV\n cmd_add_commit () {\n \t# The rev has already been validated by cmd_add(), we just\n \t# need to normalize it.\n+\tassert test $# = 1\n \trev=$(git rev-parse --verify \"$1^{commit}\") || exit $?\n \n \tdebug \"Adding $dir as '$rev'...\"\n@@ -722,6 +776,7 @@ cmd_add_commit () {\n \tsay >&2 \"Added dir '$dir'\"\n }\n \n+# Usage: cmd_split [REV]\n cmd_split () {\n \tif test $# -eq 0\n \tthen\n@@ -801,6 +856,7 @@ cmd_split () {\n \texit 0\n }\n \n+# Usage: cmd_merge REV\n cmd_merge () {\n \ttest $# -eq 1 ||\n \t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n@@ -837,6 +893,7 @@ cmd_merge () {\n \tfi\n }\n \n+# Usage: cmd_pull REPOSITORY REMOTEREF\n cmd_pull () {\n \tif test $# -ne 2\n \tthen\n@@ -848,6 +905,7 @@ cmd_pull () {\n \tcmd_merge FETCH_HEAD\n }\n \n+# Usage: cmd_push REPOSITORY REMOTEREF\n cmd_push () {\n \tif test $# -ne 2\n \tthen\n-- \n2.31.1\n\n"},{"id":"423157","messageId":"20210427211748.2607474-27-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 26/30] subtree: give the docs a once-over","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:44Z","receivedAt":"2021-04-27T21:18:58Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nJust went through the docs looking for anything inaccurate or that can\nbe improved.\n\nIn the '-h' text, in the man page synopsis, and in the man page\ndescription: Normalize the ordering of the list of sub-commands: 'add',\n'merge', 'split', 'pull', 'push'.  This allows us to kinda separate the\nlower-level add/merge/split from the higher-level pull/push.\n\n'-h' text:\n - correction: Indicate that split's arg is optional.\n - clarity: Emphasize that 'pull' takes the 'add'/'merge' flags.\n\nman page:\n\n - correction: State that all subcommands take options (it seemed to\n   indicate that only 'split' takes any options other than '-P').\n - correction: 'split' only guarantees that the results are identical if\n   the flags are identical.\n - correction: The flag is named '--ignore-joins', not '--ignore-join'.\n - completeness: Clarify that 'push' always operates on HEAD, and that\n   'split' operates on HEAD if no local commit is given.\n - clarity: In the description, when listing commands, repeat what their\n   arguments are.  This way the reader doesn't need to flip back and\n   forth between the command description and the synopsis and the full\n   description to understand what's being said.\n - clarity: In the <variables> used to give command arguments, give\n   slightly longer, descriptive names.  Like <local-commit> instead of\n   just <commit>.\n - clarity: Emphasize that 'pull' takes the 'add'/'merge' flags.\n - style: In the synopsis, list options before the subcommand.  This\n   makes things line up and be much more readable when shown\n   non-monospace (such as in `make html`), and also more closely matches\n   other man pages (like `git-submodule.txt`).\n - style: Use the correct syntax for indicating the options ([<options>]\n   instead of [OPTIONS]).\n - style: In the synopsis, separate 'pull' and 'push' from the other\n   lower-level commands.  I think this helps readability.\n - style: Code-quote things in prose that seem like they should be\n   code-quoted, like '.gitmodules', flags, or full commands.\n - style: Minor wording improvements, like more consistent mood (many\n   of the command descriptions start in the imperative mood and switch\n   to the indicative mode by the end).  That sort of thing.\n - style: Capitalize \"ID\".\n - style: Remove the \"This option is only valid for XXX command\" remarks\n   from each option, and instead rely on the section headings.\n - style: Since that line is getting edited anyway, switch \"behaviour\" to\n   American \"behavior\".\n - style: Trim trailing whitespace.\n\n`todo`:\n - style: Trim trailing whitespace.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - behaviour -> behavior\nv3:\n - Trim trailing whitespace.\n - Fix the man page saying \"--ignore-join\" instead of \"--ignore-joins\".\n\n contrib/subtree/git-subtree.sh  |   4 +-\n contrib/subtree/git-subtree.txt | 170 +++++++++++++++-----------------\n contrib/subtree/todo            |   6 +-\n 3 files changed, 87 insertions(+), 93 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 768fa7b6b6..3bffddf277 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -25,9 +25,9 @@ OPTS_SPEC=\"\\\n git subtree add   --prefix=<prefix> <commit>\n git subtree add   --prefix=<prefix> <repository> <ref>\n git subtree merge --prefix=<prefix> <commit>\n+git subtree split --prefix=<prefix> [<commit>]\n git subtree pull  --prefix=<prefix> <repository> <ref>\n git subtree push  --prefix=<prefix> <repository> <ref>\n-git subtree split --prefix=<prefix> <commit>\n --\n h,help        show the help\n q             quiet\n@@ -40,7 +40,7 @@ b,branch=     create a new branch from the split subtree\n ignore-joins  ignore prior --rejoin commits\n onto=         try connecting new tree to an existing one\n rejoin        merge the new branch back into HEAD\n- options for 'add', 'merge', and 'pull'\n+ options for 'add' and 'merge' (also: 'pull')\n squash        merge subtree changes as a single commit\n \"\n \ndiff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt\nindex 0db02fe3c0..78baac1e6b 100644\n--- a/contrib/subtree/git-subtree.txt\n+++ b/contrib/subtree/git-subtree.txt\n@@ -9,13 +9,14 @@ git-subtree - Merge subtrees together and split repository into subtrees\n SYNOPSIS\n --------\n [verse]\n-'git subtree' add   -P <prefix> <commit>\n-'git subtree' add   -P <prefix> <repository> <ref>\n-'git subtree' pull  -P <prefix> <repository> <ref>\n-'git subtree' push  -P <prefix> <repository> <ref>\n-'git subtree' merge -P <prefix> <commit>\n-'git subtree' split -P <prefix> [OPTIONS] [<commit>]\n+'git subtree' [<options>] -P <prefix> add <local-commit>\n+'git subtree' [<options>] -P <prefix> add <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> merge <local-commit>\n+'git subtree' [<options>] -P <prefix> split [<local-commit>]\n \n+[verse]\n+'git subtree' [<options>] -P <prefix> pull <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> push <repository> <remote-ref>\n \n DESCRIPTION\n -----------\n@@ -28,7 +29,7 @@ as a subdirectory of your application.\n \n Subtrees are not to be confused with submodules, which are meant for\n the same task. Unlike submodules, subtrees do not need any special\n-constructions (like .gitmodules files or gitlinks) be present in\n+constructions (like '.gitmodules' files or gitlinks) be present in\n your repository, and do not force end-users of your\n repository to do anything special or to understand how subtrees\n work. A subtree is just a subdirectory that can be\n@@ -59,67 +60,69 @@ project as much as possible.  That is, if you make a change that\n affects both the library and the main application, commit it in\n two pieces.  That way, when you split the library commits out\n later, their descriptions will still make sense.  But if this\n-isn't important to you, it's not *necessary*.  git subtree will\n+isn't important to you, it's not *necessary*.  'git subtree' will\n simply leave out the non-library-related parts of the commit\n when it splits it out into the subproject later.\n \n \n COMMANDS\n --------\n-add::\n+add <local-commit>::\n+add <repository> <remote-ref>::\n \tCreate the <prefix> subtree by importing its contents\n-\tfrom the given <commit> or <repository> and remote <ref>.\n+\tfrom the given <local-commit> or <repository> and <remote-ref>.\n \tA new commit is created\tautomatically, joining the imported\n-\tproject's history with your own.  With '--squash', imports\n+\tproject's history with your own.  With '--squash', import\n \tonly a single commit from the subproject, rather than its\n \tentire history.\n \n-merge::\n-\tMerge recent changes up to <commit> into the <prefix>\n+merge <local-commit>::\n+\tMerge recent changes up to <local-commit> into the <prefix>\n \tsubtree.  As with normal 'git merge', this doesn't\n \tremove your own local changes; it just merges those\n-\tchanges into the latest <commit>.  With '--squash',\n-\tcreates only one commit that contains all the changes,\n+\tchanges into the latest <local-commit>.  With '--squash',\n+\tcreate only one commit that contains all the changes,\n \trather than merging in the entire history.\n +\n If you use '--squash', the merge direction doesn't always have to be\n forward; you can use this command to go back in time from v2.5 to v2.4,\n for example.  If your merge introduces a conflict, you can resolve it in\n the usual ways.\n-\t\n-pull::\n-\tExactly like 'merge', but parallels 'git pull' in that\n-\tit fetches the given ref from the specified remote\n-\trepository.\n-\t\n-push::\n-\tDoes a 'split' (see below) using the <prefix> supplied\n-\tand then does a 'git push' to push the result to the \n-\trepository and ref. This can be used to push your\n-\tsubtree to different branches of the remote repository.\n-\n-split::\n+\n+split [<local-commit>]::\n \tExtract a new, synthetic project history from the\n-\thistory of the <prefix> subtree.  The new history\n+\thistory of the <prefix> subtree of <local-commit>, or of\n+\tHEAD if no <local-commit> is given.  The new history\n \tincludes only the commits (including merges) that\n \taffected <prefix>, and each of those commits now has the\n \tcontents of <prefix> at the root of the project instead\n \tof in a subdirectory.  Thus, the newly created history\n \tis suitable for export as a separate git repository.\n +\n-After splitting successfully, a single commit id is printed to stdout.\n+After splitting successfully, a single commit ID is printed to stdout.\n This corresponds to the HEAD of the newly created tree, which you can\n manipulate however you want.\n +\n Repeated splits of exactly the same history are guaranteed to be\n-identical (i.e. to produce the same commit ids).  Because of this, if\n-you add new commits and then re-split, the new commits will be attached\n-as commits on top of the history you generated last time, so 'git merge'\n-and friends will work as expected.\n+identical (i.e. to produce the same commit IDs) as long as the\n+settings passed to 'split' (such as '--annotate') are the same.\n+Because of this, if you add new commits and then re-split, the new\n+commits will be attached as commits on top of the history you\n+generated last time, so 'git merge' and friends will work as expected.\n +\n Note that if you use '--squash' when you merge, you should usually not\n just '--rejoin' when you split.\n \n+pull <repository> <remote-ref>::\n+\tExactly like 'merge', but parallels 'git pull' in that\n+\tit fetches the given ref from the specified remote\n+\trepository.\n+\n+push <repository> <remote-ref>::\n+\tDoes a 'split' using the <prefix> subtree of HEAD and then\n+\tdoes a 'git push' to push the result to the <repository> and\n+\t<remote-ref>.  This can be used to push your subtree to\n+\tdifferent branches of the remote repository.\n \n OPTIONS\n -------\n@@ -139,19 +142,18 @@ OPTIONS\n \n -m <message>::\n --message=<message>::\n-\tThis option is only valid for add, merge, pull, and split --rejoin.\n+\tThis option is only valid for 'add', 'merge', 'pull', and 'split --rejoin'.\n \tSpecify <message> as the commit message for the merge commit.\n \n+OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull')\n+--------------------------------------------\n+These options for 'add' and 'merge' may also be given to 'pull' (which\n+wraps 'merge').\n \n-OPTIONS FOR add, merge, and pull\n---------------------------------\n --squash::\n-\tThis option is only valid for add, merge, and pull\n-\tcommands.\n-+\n-Instead of merging the entire history from the subtree project, produce\n-only a single commit that contains all the differences you want to\n-merge, and then merge that new commit into your project.\n+\tInstead of merging the entire history from the subtree project, produce\n+\tonly a single commit that contains all the differences you want to\n+\tmerge, and then merge that new commit into your project.\n +\n Using this option helps to reduce log clutter. People rarely want to see\n every change that happened between v1.0 and v1.1 of the library they're\n@@ -175,56 +177,48 @@ remain intact and can be later split and send upstream to the\n subproject.\n \n \n-OPTIONS FOR split\n------------------\n+OPTIONS FOR 'split'\n+-------------------\n+These options are only valid for 'split'.\n+\n --annotate=<annotation>::\n-\tThis option is only valid for the split command.\n-+\n-When generating synthetic history, add <annotation> as a prefix to each\n-commit message.  Since we're creating new commits with the same commit\n-message, but possibly different content, from the original commits, this\n-can help to differentiate them and avoid confusion.\n+\tWhen generating synthetic history, add <annotation> as a prefix to each\n+\tcommit message.  Since we're creating new commits with the same commit\n+\tmessage, but possibly different content, from the original commits, this\n+\tcan help to differentiate them and avoid confusion.\n +\n Whenever you split, you need to use the same <annotation>, or else you\n don't have a guarantee that the new re-created history will be identical\n to the old one.  That will prevent merging from working correctly.  git\n-subtree tries to make it work anyway, particularly if you use --rejoin,\n+subtree tries to make it work anyway, particularly if you use '--rejoin',\n but it may not always be effective.\n \n -b <branch>::\n --branch=<branch>::\n-\tThis option is only valid for the split command.\n-+\n-After generating the synthetic history, create a new branch called\n-<branch> that contains the new history.  This is suitable for immediate\n-pushing upstream.  <branch> must not already exist.\n+\tAfter generating the synthetic history, create a new branch called\n+\t<branch> that contains the new history.  This is suitable for immediate\n+\tpushing upstream.  <branch> must not already exist.\n \n --ignore-joins::\n-\tThis option is only valid for the split command.\n-+\n-If you use '--rejoin', git subtree attempts to optimize its history\n-reconstruction to generate only the new commits since the last\n-'--rejoin'.  '--ignore-join' disables this behaviour, forcing it to\n-regenerate the entire history.  In a large project, this can take a long\n-time.\n+\tIf you use '--rejoin', git subtree attempts to optimize its history\n+\treconstruction to generate only the new commits since the last\n+\t'--rejoin'.  '--ignore-joins' disables this behavior, forcing it to\n+\tregenerate the entire history.  In a large project, this can take a long\n+\ttime.\n \n --onto=<onto>::\n-\tThis option is only valid for the split command.\n-+\n-If your subtree was originally imported using something other than git\n-subtree, its history may not match what git subtree is expecting.  In\n-that case, you can specify the commit id <onto> that corresponds to the\n-first revision of the subproject's history that was imported into your\n-project, and git subtree will attempt to build its history from there.\n+\tIf your subtree was originally imported using something other than git\n+\tsubtree, its history may not match what git subtree is expecting.  In\n+\tthat case, you can specify the commit ID <onto> that corresponds to the\n+\tfirst revision of the subproject's history that was imported into your\n+\tproject, and git subtree will attempt to build its history from there.\n +\n If you used 'git subtree add', you should never need this option.\n \n --rejoin::\n-\tThis option is only valid for the split command.\n-+\n-After splitting, merge the newly created synthetic history back into\n-your main project.  That way, future splits can search only the part of\n-history that has been added since the most recent --rejoin.\n+\tAfter splitting, merge the newly created synthetic history back into\n+\tyour main project.  That way, future splits can search only the part of\n+\thistory that has been added since the most recent '--rejoin'.\n +\n If your split commits end up merged into the upstream subproject, and\n then you want to get the latest upstream version, this will allow git's\n@@ -240,8 +234,8 @@ split, because you don't want the subproject's history to be part of\n your project anyway.\n \n \n-EXAMPLE 1. Add command\n-----------------------\n+EXAMPLE 1. 'add' command\n+------------------------\n Let's assume that you have a local repository that you would like\n to add an external vendor library to. In this case we will add the\n git-subtree repository as a subdirectory of your already existing\n@@ -253,15 +247,15 @@ git-extensions repository in ~/git-extensions/:\n 'master' needs to be a valid remote ref and can be a different branch\n name\n \n-You can omit the --squash flag, but doing so will increase the number\n+You can omit the '--squash' flag, but doing so will increase the number\n of commits that are included in your local repository.\n \n We now have a ~/git-extensions/git-subtree directory containing code\n from the master branch of git://github.com/apenwarr/git-subtree.git\n in our git-extensions repository.\n \n-EXAMPLE 2. Extract a subtree using commit, merge and pull\n----------------------------------------------------------\n+EXAMPLE 2. Extract a subtree using 'commit', 'merge' and 'pull'\n+---------------------------------------------------------------\n Let's use the repository for the git source code as an example.\n First, get your own copy of the git.git repository:\n \n@@ -269,7 +263,7 @@ First, get your own copy of the git.git repository:\n \t$ cd test-git\n \n gitweb (commit 1130ef3) was merged into git as of commit\n-0a8f4f0, after which it was no longer maintained separately. \n+0a8f4f0, after which it was no longer maintained separately.\n But imagine it had been maintained separately, and we wanted to\n extract git's changes to gitweb since that time, to share with\n the upstream.  You could do this:\n@@ -279,14 +273,14 @@ the upstream.  You could do this:\n         \t--branch gitweb-latest\n         $ gitk gitweb-latest\n         $ git push git@github.com:whatever/gitweb.git gitweb-latest:master\n-        \n+\n (We use '0a8f4f0^..' because that means \"all the changes from\n 0a8f4f0 to the current version, including 0a8f4f0 itself.\")\n \n If gitweb had originally been merged using 'git subtree add' (or\n-a previous split had already been done with --rejoin specified)\n+a previous split had already been done with '--rejoin' specified)\n then you can do all your splits without having to remember any\n-weird commit ids:\n+weird commit IDs:\n \n \t$ git subtree split --prefix=gitweb --annotate='(split) ' --rejoin \\\n \t\t--branch gitweb-latest2\n@@ -313,7 +307,7 @@ And fast forward again:\n \t$ git subtree merge --prefix=gitweb --squash gitweb-latest\n \n And notice that your change is still intact:\n-\t\n+\n \t$ ls -l gitweb/myfile\n \n And you can split it out and look at your changes versus\n@@ -321,8 +315,8 @@ the standard gitweb:\n \n \tgit log gitweb-latest..$(git subtree split --prefix=gitweb)\n \n-EXAMPLE 3. Extract a subtree using branch\n------------------------------------------\n+EXAMPLE 3. Extract a subtree using a branch\n+-------------------------------------------\n Suppose you have a source directory with many files and\n subdirectories, and you want to extract the lib directory to its own\n git project. Here's a short way to do it:\ndiff --git a/contrib/subtree/todo b/contrib/subtree/todo\nindex 0d0e777651..32d2ce3a40 100644\n--- a/contrib/subtree/todo\n+++ b/contrib/subtree/todo\n@@ -23,9 +23,9 @@\n \n \t\"pull\" and \"merge\" commands should fail if you've never merged\n \t\tthat --prefix before\n-\t\t\n+\n \tdocs should provide an example of \"add\"\n-\t\n+\n \tnote that the initial split doesn't *have* to have a commitid\n \t\tspecified... that's just an optimization\n \n@@ -33,7 +33,7 @@\n \t\tget a misleading \"prefix must end with /\" message from\n \t\tone of the other git tools that git-subtree calls.  Should\n \t\tdetect this situation and print the *real* problem.\n-\t\n+\n \t\"pull --squash\" should do fetch-synthesize-merge, but instead just\n \t\tdoes \"pull\" directly, which doesn't work at all.\n \n-- \n2.31.1\n\n"},{"id":"423158","messageId":"20210427211748.2607474-29-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 28/30] subtree: allow 'split' flags to be passed to 'push'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:46Z","receivedAt":"2021-04-27T21:18:59Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\n'push' does a 'split' internally, but it doesn't pass flags through to the\n'split'.  This is silly, if you need to pass flags to 'split', then it\nmeans that you can't use 'push'!\n\nSo, have 'push' accept 'split' flags, and pass them through to 'split'.\n\nAdd tests for this by copying split's tests with minimal modification.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - In the added tests, use `test_must_fail` instead of `!`, as\n   appropriate.\n\n contrib/subtree/git-subtree.sh     |   6 +-\n contrib/subtree/git-subtree.txt    |  15 +-\n contrib/subtree/t/t7900-subtree.sh | 214 ++++++++++++++++++++++++++++-\n 3 files changed, 223 insertions(+), 12 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 25d69d7973..431214a1d3 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -33,13 +33,13 @@ h,help        show the help\n q             quiet\n d             show debug messages\n P,prefix=     the name of the subdir to split out\n- options for 'split'\n+ options for 'split' (also: 'push')\n annotate=     add a prefix to commit message of new commits\n b,branch=     create a new branch from the split subtree\n ignore-joins  ignore prior --rejoin commits\n onto=         try connecting new tree to an existing one\n rejoin        merge the new branch back into HEAD\n- options for 'add' and 'merge' (also: 'pull' and 'split --rejoin')\n+ options for 'add' and 'merge' (also: 'pull', 'split --rejoin', and 'push --rejoin')\n squash        merge subtree changes as a single commit\n m,message=    use the given message as the commit message for the merge commit\n \"\n@@ -964,7 +964,7 @@ cmd_push () {\n \t\trepository=$1\n \t\trefspec=$2\n \t\techo \"git push using: \" \"$repository\" \"$refspec\"\n-\t\tlocalrev=$(git subtree split --prefix=\"$arg_prefix\") || die\n+\t\tlocalrev=$(cmd_split) || die\n \t\tgit push \"$repository\" \"$localrev\":\"refs/heads/$refspec\"\n \telse\n \t\tdie \"'$dir' must already exist. Try 'git subtree add'.\"\ndiff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt\nindex d7e6e7867c..fbb52f127b 100644\n--- a/contrib/subtree/git-subtree.txt\n+++ b/contrib/subtree/git-subtree.txt\n@@ -137,11 +137,11 @@ OPTIONS FOR ALL COMMANDS\n \twant to manipulate.  This option is mandatory\n \tfor all commands.\n \n-OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull' AND 'split --rejoin')\n------------------------------------------------------------------\n+OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull', 'split --rejoin', AND 'push --rejoin')\n+-----------------------------------------------------------------------------------\n These options for 'add' and 'merge' may also be given to 'pull' (which\n-wraps 'merge') and 'split --rejoin' (which wraps either 'add' or\n-'merge' as appropriate).\n+wraps 'merge'), 'split --rejoin' (which wraps either 'add' or 'merge'\n+as appropriate), and 'push --rejoin' (which wraps 'split --rejoin').\n \n --squash::\n \tInstead of merging the entire history from the subtree project, produce\n@@ -173,9 +173,10 @@ subproject.\n --message=<message>::\n \tSpecify <message> as the commit message for the merge commit.\n \n-OPTIONS FOR 'split'\n--------------------\n-These options are only valid for 'split'.\n+OPTIONS FOR 'split' (ALSO: 'push')\n+----------------------------------\n+These options for 'split' may also be given to 'push' (which wraps\n+'split').\n \n --annotate=<annotation>::\n \tWhen generating synthetic history, add <annotation> as a prefix to each\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 2561e25f43..5a6541437b 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -5,8 +5,8 @@\n #\n test_description='Basic porcelain support for subtrees\n \n-This test verifies the basic operation of the add, pull, merge\n-and split subcommands of git subtree.\n+This test verifies the basic operation of the add, merge, split, pull,\n+and push subcommands of git subtree.\n '\n \n TEST_DIRECTORY=$(pwd)/../../../t\n@@ -610,6 +610,216 @@ test_expect_success 'push basic operation' '\n \t)\n '\n \n+test_expect_success 'push sub dir/ with --rejoin' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --rejoin ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push sub dir/ with --rejoin from scratch' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tmkdir \"sub dir\" &&\n+\t\techo file >\"sub dir\"/file &&\n+\t\tgit add \"sub dir/file\" &&\n+\t\tgit commit -m\"sub dir file\" &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --rejoin) &&\n+\t\tgit init --bare \"sub proj.git\" &&\n+\t\tgit subtree push --prefix=\"sub dir\" --rejoin ./\"sub proj.git\" from-mainline &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$split_hash'\\''\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj.git\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push sub dir/ with --rejoin and --message' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tgit subtree push --prefix=\"sub dir\" --message=\"Split & rejoin\" --annotate=\"*\" --rejoin ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split & rejoin\" &&\n+\t\tsplit_hash=\"$(git rev-parse --verify HEAD^2)\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push \"sub dir\"/ with --rejoin and --squash' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" --squash FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit subtree pull --prefix=\"sub dir\" --squash ./\"sub proj\" HEAD &&\n+\t\tMAIN=$(git rev-parse --verify HEAD) &&\n+\t\tSUB=$(git -C \"sub proj\" rev-parse --verify HEAD) &&\n+\n+\t\tSPLIT=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --rejoin --squash ./\"sub proj\" from-mainline &&\n+\n+\t\ttest_must_fail git merge-base --is-ancestor $SUB HEAD &&\n+\t\ttest_must_fail git merge-base --is-ancestor $SPLIT HEAD &&\n+\t\tgit rev-list HEAD ^$MAIN >commit-list &&\n+\t\ttest_line_count = 2 commit-list &&\n+\t\ttest \"$(git rev-parse --verify HEAD:)\"           = \"$(git rev-parse --verify $MAIN:)\" &&\n+\t\ttest \"$(git rev-parse --verify HEAD:\"sub dir\")\"  = \"$(git rev-parse --verify $SPLIT:)\" &&\n+\t\ttest \"$(git rev-parse --verify HEAD^1)\"          = $MAIN &&\n+\t\ttest \"$(git rev-parse --verify HEAD^2)\"         != $SPLIT &&\n+\t\ttest \"$(git rev-parse --verify HEAD^2:)\"         = \"$(git rev-parse --verify $SPLIT:)\" &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$SPLIT'\\''\" &&\n+\t\ttest \"$SPLIT\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push \"sub dir\"/ with --branch' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'check hash of push' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\" &&\n+\t\t# Check hash of split\n+\t\tnew_hash=$(git rev-parse subproj-br^2) &&\n+\t\t(\n+\t\t\tcd ./\"sub proj\" &&\n+\t\t\tsubdir_hash=$(git rev-parse HEAD) &&\n+\t\t\ttest \"$new_hash\" = \"$subdir_hash\"\n+\t\t) &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push \"sub dir\"/ with --branch for an existing branch' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit branch subproj-br FETCH_HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" --branch subproj-br ./\"sub proj\" from-mainline &&\n+\t\ttest \"$(git rev-parse subproj-br)\" = \"$split_hash\" &&\n+\t\ttest \"$split_hash\" = \"$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline)\"\n+\t)\n+'\n+\n+test_expect_success 'push \"sub dir\"/ with --branch for an incompatible branch' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit branch init HEAD &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\ttest_must_fail git subtree push --prefix=\"sub dir\" --branch init \"./sub proj\" from-mainline\n+\t)\n+'\n+\n #\n # Validity checking\n #\n-- \n2.31.1\n\n"},{"id":"423159","messageId":"20210427211748.2607474-30-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 29/30] subtree: push: allow specifying a local rev other than HEAD","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:47Z","receivedAt":"2021-04-27T21:19:01Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\n'git subtree split' lets you specify a rev other than HEAD.  'git push'\nlets you specify a mapping between a local thing and a remot ref.  So\nsmash those together, and have 'git subtree push' let you specify which\nlocal thing to run split on and push the result of that split to the\nremote ref.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh     | 24 +++++++++++++++++-------\n contrib/subtree/git-subtree.txt    | 14 ++++++++------\n contrib/subtree/t/t7900-subtree.sh | 22 ++++++++++++++++++++++\n 3 files changed, 47 insertions(+), 13 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 431214a1d3..9e4d9a0619 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -27,7 +27,7 @@ git subtree add   --prefix=<prefix> <repository> <ref>\n git subtree merge --prefix=<prefix> <commit>\n git subtree split --prefix=<prefix> [<commit>]\n git subtree pull  --prefix=<prefix> <repository> <ref>\n-git subtree push  --prefix=<prefix> <repository> <ref>\n+git subtree push  --prefix=<prefix> <repository> <refspec>\n --\n h,help        show the help\n q             quiet\n@@ -952,20 +952,30 @@ cmd_pull () {\n \tcmd_merge FETCH_HEAD\n }\n \n-# Usage: cmd_push REPOSITORY REMOTEREF\n+# Usage: cmd_push REPOSITORY [+][LOCALREV:]REMOTEREF\n cmd_push () {\n \tif test $# -ne 2\n \tthen\n-\t\tdie \"You must provide <repository> <ref>\"\n+\t\tdie \"You must provide <repository> <refspec>\"\n \tfi\n-\tensure_valid_ref_format \"$2\"\n \tif test -e \"$dir\"\n \tthen\n \t\trepository=$1\n-\t\trefspec=$2\n+\t\trefspec=${2#+}\n+\t\tremoteref=${refspec#*:}\n+\t\tif test \"$remoteref\" = \"$refspec\"\n+\t\tthen\n+\t\t\tlocalrevname_presplit=HEAD\n+\t\telse\n+\t\t\tlocalrevname_presplit=${refspec%%:*}\n+\t\tfi\n+\t\tensure_valid_ref_format \"$remoteref\"\n+\t\tlocalrev_presplit=$(git rev-parse -q --verify \"$localrevname_presplit^{commit}\") ||\n+\t\t\tdie \"'$localrevname_presplit' does not refer to a commit\"\n+\n \t\techo \"git push using: \" \"$repository\" \"$refspec\"\n-\t\tlocalrev=$(cmd_split) || die\n-\t\tgit push \"$repository\" \"$localrev\":\"refs/heads/$refspec\"\n+\t\tlocalrev=$(cmd_split \"$localrev_presplit\") || die\n+\t\tgit push \"$repository\" \"$localrev\":\"refs/heads/$remoteref\"\n \telse\n \t\tdie \"'$dir' must already exist. Try 'git subtree add'.\"\n \tfi\ndiff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt\nindex fbb52f127b..9cddfa2654 100644\n--- a/contrib/subtree/git-subtree.txt\n+++ b/contrib/subtree/git-subtree.txt\n@@ -16,7 +16,7 @@ SYNOPSIS\n \n [verse]\n 'git subtree' [<options>] -P <prefix> pull <repository> <remote-ref>\n-'git subtree' [<options>] -P <prefix> push <repository> <remote-ref>\n+'git subtree' [<options>] -P <prefix> push <repository> <refspec>\n \n DESCRIPTION\n -----------\n@@ -115,11 +115,13 @@ pull <repository> <remote-ref>::\n \tit fetches the given ref from the specified remote\n \trepository.\n \n-push <repository> <remote-ref>::\n-\tDoes a 'split' using the <prefix> subtree of HEAD and then\n-\tdoes a 'git push' to push the result to the <repository> and\n-\t<remote-ref>.  This can be used to push your subtree to\n-\tdifferent branches of the remote repository.\n+push <repository> [+][<local-commit>:]<remote-ref>::\n+\tDoes a 'split' using the <prefix> subtree of <local-commit>\n+\tand then does a 'git push' to push the result to the\n+\t<repository> and <remote-ref>.  This can be used to push your\n+\tsubtree to different branches of the remote repository.  Just\n+\tas with 'split', if no <local-commit> is given, then HEAD is\n+\tused.  The optional leading '+' is ignored.\n \n OPTIONS FOR ALL COMMANDS\n ------------------------\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex 5a6541437b..d7ad6ffff0 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -820,6 +820,28 @@ test_expect_success 'push \"sub dir\"/ with --branch for an incompatible branch' '\n \t)\n '\n \n+test_expect_success 'push \"sub dir\"/ with a local rev' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tbad_tree=$(git rev-parse --verify HEAD:\"sub dir\") &&\n+\t\tgood_tree=$(git rev-parse --verify HEAD^:\"sub dir\") &&\n+\t\tgit subtree push --prefix=\"sub dir\" --annotate=\"*\" ./\"sub proj\" HEAD^:from-mainline &&\n+\t\tsplit_tree=$(git -C \"sub proj\" rev-parse --verify refs/heads/from-mainline:) &&\n+\t\ttest \"$split_tree\" = \"$good_tree\"\n+\t)\n+'\n+\n #\n # Validity checking\n #\n-- \n2.31.1\n\n"},{"id":"423160","messageId":"20210427211748.2607474-28-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 27/30] subtree: allow --squash to be used with --rejoin","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:45Z","receivedAt":"2021-04-27T21:19:02Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nBesides being a genuinely useful thing to do, this also just makes sense\nand harmonizes which flags may be used when.  `git subtree split\n--rejoin` amounts to \"automatically go ahead and do a `git subtree\nmerge` after doing the main `git subtree split`\", so it's weird and\narbitrary that you can't pass `--squash` to `git subtree split --rejoin`\nlike you can `git subtree merge`.  It's weird that `git subtree split\n--rejoin` inherits `git subtree merge`'s `--message` but not `--squash`.\n\nReconcile the situation by just having `split --rejoin` actually just\ncall `merge` internally (or call `add` instead, as appropriate), so it\ncan get access to the full `merge` behavior, including `--squash`.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\nv2:\n - In the added tests, use `test_must_fail` instead of `!`, as\n   appropriate.\nv3:\n - Style: Put the `then` of an `if/then` on its own line.\n - Fix a bug (and add a test) where the resulting commits confuse a\n   subsequent `git subtree merge --squash`.\n\n contrib/subtree/git-subtree.sh     | 37 +++++++++++++++-----\n contrib/subtree/git-subtree.txt    | 27 ++++++--------\n contrib/subtree/t/t7900-subtree.sh | 56 ++++++++++++++++++++++++++++++\n 3 files changed, 96 insertions(+), 24 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 3bffddf277..25d69d7973 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -33,15 +33,15 @@ h,help        show the help\n q             quiet\n d             show debug messages\n P,prefix=     the name of the subdir to split out\n-m,message=    use the given message as the commit message for the merge commit\n  options for 'split'\n annotate=     add a prefix to commit message of new commits\n b,branch=     create a new branch from the split subtree\n ignore-joins  ignore prior --rejoin commits\n onto=         try connecting new tree to an existing one\n rejoin        merge the new branch back into HEAD\n- options for 'add' and 'merge' (also: 'pull')\n+ options for 'add' and 'merge' (also: 'pull' and 'split --rejoin')\n squash        merge subtree changes as a single commit\n+m,message=    use the given message as the commit message for the merge commit\n \"\n \n arg_debug=\n@@ -346,7 +346,8 @@ find_latest_squash () {\n \t\t\t\tthen\n \t\t\t\t\t# a rejoin commit?\n \t\t\t\t\t# Pretend its sub was a squash.\n-\t\t\t\t\tsq=\"$sub\"\n+\t\t\t\t\tsq=$(git rev-parse --verify \"$sq^2\") ||\n+\t\t\t\t\t\tdie\n \t\t\t\tfi\n \t\t\t\tdebug \"Squash found: $sq $sub\"\n \t\t\t\techo \"$sq\" \"$sub\"\n@@ -453,6 +454,13 @@ add_msg () {\n \telse\n \t\tcommit_message=\"Add '$dir/' from commit '$latest_new'\"\n \tfi\n+\tif test -n \"$arg_split_rejoin\"\n+\tthen\n+\t\t# If this is from a --rejoin, then rejoin_msg has\n+\t\t# already inserted the `git-subtree-xxx:` tags\n+\t\techo \"$commit_message\"\n+\t\treturn\n+\tfi\n \tcat <<-EOF\n \t\t$commit_message\n \n@@ -775,7 +783,12 @@ cmd_add_commit () {\n \trev=$(git rev-parse --verify \"$1^{commit}\") || exit $?\n \n \tdebug \"Adding $dir as '$rev'...\"\n-\tgit read-tree --prefix=\"$dir\" $rev || exit $?\n+\tif test -z \"$arg_split_rejoin\"\n+\tthen\n+\t\t# Only bother doing this if this is a genuine 'add',\n+\t\t# not a synthetic 'add' from '--rejoin'.\n+\t\tgit read-tree --prefix=\"$dir\" $rev || exit $?\n+\tfi\n \tgit checkout -- \"$dir\" || exit $?\n \ttree=$(git write-tree) || exit $?\n \n@@ -815,6 +828,11 @@ cmd_split () {\n \t\tdie \"You must provide exactly one revision.  Got: '$*'\"\n \tfi\n \n+\tif test -n \"$arg_split_rejoin\"\n+\tthen\n+\t\tensure_clean\n+\tfi\n+\n \tdebug \"Splitting $dir...\"\n \tcache_setup || exit $?\n \n@@ -857,10 +875,13 @@ cmd_split () {\n \tthen\n \t\tdebug \"Merging split branch into HEAD...\"\n \t\tlatest_old=$(cache_get latest_old) || exit $?\n-\t\tgit merge -s ours \\\n-\t\t\t--allow-unrelated-histories \\\n-\t\t\t-m \"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" \\\n-\t\t\t\"$latest_new\" >&2 || exit $?\n+\t\targ_addmerge_message=\"$(rejoin_msg \"$dir\" \"$latest_old\" \"$latest_new\")\" || exit $?\n+\t\tif test -z \"$(find_latest_squash \"$dir\")\"\n+\t\tthen\n+\t\t\tcmd_add \"$latest_new\" >&2 || exit $?\n+\t\telse\n+\t\t\tcmd_merge \"$latest_new\" >&2 || exit $?\n+\t\tfi\n \tfi\n \tif test -n \"$arg_split_branch\"\n \tthen\ndiff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt\nindex 78baac1e6b..d7e6e7867c 100644\n--- a/contrib/subtree/git-subtree.txt\n+++ b/contrib/subtree/git-subtree.txt\n@@ -109,9 +109,6 @@ settings passed to 'split' (such as '--annotate') are the same.\n Because of this, if you add new commits and then re-split, the new\n commits will be attached as commits on top of the history you\n generated last time, so 'git merge' and friends will work as expected.\n-+\n-Note that if you use '--squash' when you merge, you should usually not\n-just '--rejoin' when you split.\n \n pull <repository> <remote-ref>::\n \tExactly like 'merge', but parallels 'git pull' in that\n@@ -124,8 +121,8 @@ push <repository> <remote-ref>::\n \t<remote-ref>.  This can be used to push your subtree to\n \tdifferent branches of the remote repository.\n \n-OPTIONS\n--------\n+OPTIONS FOR ALL COMMANDS\n+------------------------\n -q::\n --quiet::\n \tSuppress unnecessary output messages on stderr.\n@@ -140,15 +137,11 @@ OPTIONS\n \twant to manipulate.  This option is mandatory\n \tfor all commands.\n \n--m <message>::\n---message=<message>::\n-\tThis option is only valid for 'add', 'merge', 'pull', and 'split --rejoin'.\n-\tSpecify <message> as the commit message for the merge commit.\n-\n-OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull')\n---------------------------------------------\n+OPTIONS FOR 'add' AND 'merge' (ALSO: 'pull' AND 'split --rejoin')\n+-----------------------------------------------------------------\n These options for 'add' and 'merge' may also be given to 'pull' (which\n-wraps 'merge').\n+wraps 'merge') and 'split --rejoin' (which wraps either 'add' or\n+'merge' as appropriate).\n \n --squash::\n \tInstead of merging the entire history from the subtree project, produce\n@@ -176,6 +169,9 @@ Whether or not you use '--squash', changes made in your local repository\n remain intact and can be later split and send upstream to the\n subproject.\n \n+-m <message>::\n+--message=<message>::\n+\tSpecify <message> as the commit message for the merge commit.\n \n OPTIONS FOR 'split'\n -------------------\n@@ -229,9 +225,8 @@ Unfortunately, using this option results in 'git log' showing an extra\n copy of every new commit that was created (the original, and the\n synthetic one).\n +\n-If you do all your merges with '--squash', don't use '--rejoin' when you\n-split, because you don't want the subproject's history to be part of\n-your project anyway.\n+If you do all your merges with '--squash', make sure you also use\n+'--squash' when you 'split --rejoin'.\n \n \n EXAMPLE 1. 'add' command\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex ce6861c22d..2561e25f43 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -324,6 +324,62 @@ test_expect_success 'split sub dir/ with --rejoin and --message' '\n \t)\n '\n \n+test_expect_success 'split \"sub dir\"/ with --rejoin and --squash' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" --squash FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit subtree pull --prefix=\"sub dir\" --squash ./\"sub proj\" HEAD &&\n+\t\tMAIN=$(git rev-parse --verify HEAD) &&\n+\t\tSUB=$(git -C \"sub proj\" rev-parse --verify HEAD) &&\n+\n+\t\tSPLIT=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\" --rejoin --squash) &&\n+\n+\t\ttest_must_fail git merge-base --is-ancestor $SUB HEAD &&\n+\t\ttest_must_fail git merge-base --is-ancestor $SPLIT HEAD &&\n+\t\tgit rev-list HEAD ^$MAIN >commit-list &&\n+\t\ttest_line_count = 2 commit-list &&\n+\t\ttest \"$(git rev-parse --verify HEAD:)\"           = \"$(git rev-parse --verify $MAIN:)\" &&\n+\t\ttest \"$(git rev-parse --verify HEAD:\"sub dir\")\"  = \"$(git rev-parse --verify $SPLIT:)\" &&\n+\t\ttest \"$(git rev-parse --verify HEAD^1)\"          = $MAIN &&\n+\t\ttest \"$(git rev-parse --verify HEAD^2)\"         != $SPLIT &&\n+\t\ttest \"$(git rev-parse --verify HEAD^2:)\"         = \"$(git rev-parse --verify $SPLIT:)\" &&\n+\t\ttest \"$(last_commit_subject)\" = \"Split '\\''sub dir/'\\'' into commit '\\''$SPLIT'\\''\"\n+\t)\n+'\n+\n+test_expect_success 'split then pull \"sub dir\"/ with --rejoin and --squash' '\n+\t# 1. \"add\"\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\tgit -C \"$test_count\" subtree --prefix=\"sub dir\" add --squash ./\"sub proj\" HEAD &&\n+\n+\t# 2. commit from parent\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\n+\t# 3. \"split --rejoin --squash\"\n+\tgit -C \"$test_count\" subtree --prefix=\"sub dir\" split --rejoin --squash &&\n+\n+\t# 4. \"pull --squash\"\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\tgit -C \"$test_count\" subtree -d --prefix=\"sub dir\" pull --squash ./\"sub proj\" HEAD &&\n+\n+\ttest_must_fail git merge-base HEAD FETCH_HEAD\n+'\n+\n test_expect_success 'split \"sub dir\"/ with --branch' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n-- \n2.31.1\n\n"},{"id":"423161","messageId":"20210427211748.2607474-31-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"20210427211748.2607474-1-lukeshu@lukeshu.com","subject":"[PATCH v3 30/30] subtree: be stricter about validating flags","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-27T21:17:48Z","receivedAt":"2021-04-27T21:19:03Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"From: Luke Shumaker <lukeshu@datawire.io>\n\nDon't silently ignore a flag that's invalid for a given subcommand.  The\nuser expected it to do something; we should tell the user that they are\nmistaken, instead of surprising the user.\n\nIt could be argued that this change might break existing users.  I'd\nargue that those existing users are already broken, and they just don't\nknow it.  Let them know that they're broken.\n\nSigned-off-by: Luke Shumaker <lukeshu@datawire.io>\n---\n contrib/subtree/git-subtree.sh     |  89 ++++++++++++++++-------\n contrib/subtree/t/t7900-subtree.sh | 111 +++++++++++++++++++++++++++++\n 2 files changed, 175 insertions(+), 25 deletions(-)\n\ndiff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh\nindex 9e4d9a0619..b06782bc79 100755\n--- a/contrib/subtree/git-subtree.sh\n+++ b/contrib/subtree/git-subtree.sh\n@@ -44,17 +44,6 @@ squash        merge subtree changes as a single commit\n m,message=    use the given message as the commit message for the merge commit\n \"\n \n-arg_debug=\n-arg_command=\n-arg_prefix=\n-arg_split_branch=\n-arg_split_onto=\n-arg_split_rejoin=\n-arg_split_ignore_joins=\n-arg_split_annotate=\n-arg_addmerge_squash=\n-arg_addmerge_message=\n-\n indent=0\n \n # Usage: debug [MSG...]\n@@ -106,10 +95,61 @@ main () {\n \tthen\n \t\tset -- -h\n \tfi\n-\teval \"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n+\tset_args=\"$(echo \"$OPTS_SPEC\" | git rev-parse --parseopt -- \"$@\" || echo exit $?)\"\n+\teval \"$set_args\"\n \t. git-sh-setup\n \trequire_work_tree\n \n+\t# First figure out the command and whether we use --rejoin, so\n+\t# that we can provide more helpful validation when we do the\n+\t# \"real\" flag parsing.\n+\targ_split_rejoin=\n+\tallow_split=\n+\tallow_addmerge=\n+\twhile test $# -gt 0\n+\tdo\n+\t\topt=\"$1\"\n+\t\tshift\n+\t\tcase \"$opt\" in\n+\t\t\t--annotate|-b|-P|-m|--onto)\n+\t\t\t\tshift\n+\t\t\t\t;;\n+\t\t\t--rejoin)\n+\t\t\t\targ_split_rejoin=1\n+\t\t\t\t;;\n+\t\t\t--no-rejoin)\n+\t\t\t\targ_split_rejoin=\n+\t\t\t\t;;\n+\t\t\t--)\n+\t\t\t\tbreak\n+\t\t\t\t;;\n+\t\tesac\n+\tdone\n+\targ_command=$1\n+\tcase \"$arg_command\" in\n+\tadd|merge|pull)\n+\t\tallow_addmerge=1\n+\t\t;;\n+\tsplit|push)\n+\t\tallow_split=1\n+\t\tallow_addmerge=$arg_split_rejoin\n+\t\t;;\n+\t*)\n+\t\tdie \"Unknown command '$arg_command'\"\n+\t\t;;\n+\tesac\n+\t# Reset the arguments array for \"real\" flag parsing.\n+\teval \"$set_args\"\n+\n+\t# Begin \"real\" flag parsing.\n+\targ_debug=\n+\targ_prefix=\n+\targ_split_branch=\n+\targ_split_onto=\n+\targ_split_ignore_joins=\n+\targ_split_annotate=\n+\targ_addmerge_squash=\n+\targ_addmerge_message=\n \twhile test $# -gt 0\n \tdo\n \t\topt=\"$1\"\n@@ -123,13 +163,16 @@ main () {\n \t\t\targ_debug=1\n \t\t\t;;\n \t\t--annotate)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_annotate=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-annotate)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_annotate=\n \t\t\t;;\n \t\t-b)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_branch=\"$1\"\n \t\t\tshift\n \t\t\t;;\n@@ -138,6 +181,7 @@ main () {\n \t\t\tshift\n \t\t\t;;\n \t\t-m)\n+\t\t\ttest -n \"$allow_addmerge\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_addmerge_message=\"$1\"\n \t\t\tshift\n \t\t\t;;\n@@ -145,28 +189,34 @@ main () {\n \t\t\targ_prefix=\n \t\t\t;;\n \t\t--onto)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_onto=\"$1\"\n \t\t\tshift\n \t\t\t;;\n \t\t--no-onto)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_onto=\n \t\t\t;;\n \t\t--rejoin)\n-\t\t\targ_split_rejoin=1\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\t;;\n \t\t--no-rejoin)\n-\t\t\targ_split_rejoin=\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\t;;\n \t\t--ignore-joins)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_ignore_joins=1\n \t\t\t;;\n \t\t--no-ignore-joins)\n+\t\t\ttest -n \"$allow_split\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_split_ignore_joins=\n \t\t\t;;\n \t\t--squash)\n+\t\t\ttest -n \"$allow_addmerge\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_addmerge_squash=1\n \t\t\t;;\n \t\t--no-squash)\n+\t\t\ttest -n \"$allow_addmerge\" || die \"The '$opt' flag does not make sense with 'git subtree $arg_command'.\"\n \t\t\targ_addmerge_squash=\n \t\t\t;;\n \t\t--)\n@@ -177,19 +227,8 @@ main () {\n \t\t\t;;\n \t\tesac\n \tdone\n-\n-\targ_command=\"$1\"\n \tshift\n \n-\tcase \"$arg_command\" in\n-\tadd|merge|pull|split|push)\n-\t\t:\n-\t\t;;\n-\t*)\n-\t\tdie \"Unknown command '$arg_command'\"\n-\t\t;;\n-\tesac\n-\n \tif test -z \"$arg_prefix\"\n \tthen\n \t\tdie \"You must provide the --prefix option.\"\ndiff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\nindex d7ad6ffff0..4153b65321 100755\n--- a/contrib/subtree/t/t7900-subtree.sh\n+++ b/contrib/subtree/t/t7900-subtree.sh\n@@ -33,6 +33,12 @@ test_create_commit () (\n \tgit commit -m \"$commit\" || error \"Could not commit\"\n )\n \n+test_wrong_flag() {\n+\ttest_must_fail \"$@\" >out 2>err &&\n+\ttest_must_be_empty out &&\n+\tgrep \"flag does not make sense with\" err\n+}\n+\n last_commit_subject () {\n \tgit log --pretty=format:%s -1\n }\n@@ -72,6 +78,22 @@ test_expect_success 'no pull from non-existent subtree' '\n \t)\n '\n \n+test_expect_success 'add rejects flags for split' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --annotate=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --branch=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --ignore-joins FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --onto=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree add --prefix=\"sub dir\" --rejoin FETCH_HEAD\n+\t)\n+'\n+\n test_expect_success 'add subproj as subtree into sub dir/ with --prefix' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n@@ -128,6 +150,28 @@ test_expect_success 'add subproj as subtree into sub dir/ with --squash and --pr\n # Tests for 'git subtree merge'\n #\n \n+test_expect_success 'merge rejects flags for split' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --annotate=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --branch=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --ignore-joins FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --onto=foo FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree merge --prefix=\"sub dir\" --rejoin FETCH_HEAD\n+\t)\n+'\n+\n test_expect_success 'merge new subproj history into sub dir/ with --prefix' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n@@ -262,6 +306,30 @@ test_expect_success 'split requires path given by option --prefix must exist' '\n \t)\n '\n \n+test_expect_success 'split rejects flags for add' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\tsplit_hash=$(git subtree split --prefix=\"sub dir\" --annotate=\"*\") &&\n+\t\ttest_wrong_flag git subtree split --prefix=\"sub dir\" --squash &&\n+\t\ttest_wrong_flag git subtree split --prefix=\"sub dir\" --message=foo\n+\t)\n+'\n+\n test_expect_success 'split sub dir/ with --rejoin' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n@@ -542,6 +610,26 @@ test_expect_success 'pull basic operation' '\n \t)\n '\n \n+test_expect_success 'pull rejects flags for split' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\t(\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --annotate=foo ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --branch=foo ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --ignore-joins ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --onto=foo ./\"sub proj\" HEAD &&\n+\t\ttest_must_fail git subtree pull --prefix=\"sub dir\" --rejoin ./\"sub proj\" HEAD\n+\t)\n+'\n+\n #\n # Tests for 'git subtree push'\n #\n@@ -584,6 +672,29 @@ test_expect_success 'push requires path given by option --prefix must exist' '\n \t)\n '\n \n+test_expect_success 'push rejects flags for add' '\n+\tsubtree_test_create_repo \"$test_count\" &&\n+\tsubtree_test_create_repo \"$test_count/sub proj\" &&\n+\ttest_create_commit \"$test_count\" main1 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub1 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree add --prefix=\"sub dir\" FETCH_HEAD\n+\t) &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub1 &&\n+\ttest_create_commit \"$test_count\" main2 &&\n+\ttest_create_commit \"$test_count/sub proj\" sub2 &&\n+\ttest_create_commit \"$test_count\" \"sub dir\"/main-sub2 &&\n+\t(\n+\t\tcd \"$test_count\" &&\n+\t\tgit fetch ./\"sub proj\" HEAD &&\n+\t\tgit subtree merge --prefix=\"sub dir\" FETCH_HEAD &&\n+\t\ttest_wrong_flag git subtree split --prefix=\"sub dir\" --squash ./\"sub proj\" from-mainline &&\n+\t\ttest_wrong_flag git subtree split --prefix=\"sub dir\" --message=foo ./\"sub proj\" from-mainline\n+\t)\n+'\n+\n test_expect_success 'push basic operation' '\n \tsubtree_test_create_repo \"$test_count\" &&\n \tsubtree_test_create_repo \"$test_count/sub proj\" &&\n-- \n2.31.1\n\n"},{"id":"423162","messageId":"87im479rz0.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"CAAgkN4cKUSPKpwuaLG-vR5Z7WFUZ81QXuRcsX-10obaRBAvwBA@mail.gmail.com","subject":"Re: [PATCH v3 30/30] subtree: be stricter about validating flags","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-28T00:24:03Z","receivedAt":"2021-04-28T00:24:13Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Tue, 27 Apr 2021 15:38:01 -0600,\nJakub Suder wrote:\n\n> Sorry for the contributing to the problem, but whom do I have to\n> bribe to finally stop getting these emails that started filling my\n> inbox last week?… I have a vague memory that I might have done\n> something with git-subtree once a long time ago, but I'm not\n> generally a contributor to git and I don't know what I'm doing here\n> or how to get out…\n> \n> JS\n\nMy apologies.  I'll stop CC'ing you on my emails and further revisions\nof the patcheset.  You may yet get a few straggling emails as others\nreply-all to emails that have already been sent (unless they manually\nremove you from the CC list).\n\nAs explanation (but not excuse): The usual etiquette is to CC recent\nor substantial contributors to the code area, and because subtree\nhasn't been touched in a while, I reached back further in to the\nhistory than usual when creating the CC list.\n\nAgain, I'm sorry for bothering you.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"423173","messageId":"xmqqv987auzh.fsf@gitster.g","threadId":"55548","inReplyTo":"87k0ona2a5.wl-lukeshu@lukeshu.com","subject":"Re: [PATCH 04/30] subtree: t7900: use consistent formatting","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2021-04-28T04:33:38Z","receivedAt":"2021-04-28T04:33:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Luke Shumaker <lukeshu@lukeshu.com> writes:\n\n>> If Luke is volunteering to take over its maintainership, it would be\n>> appreciated by its users.  It has been in the \"abandonware\" status\n>> for too long.\n>\n> I think I am volunteering.\n\nWonderful, and thanks.\n\n> Elsewhere in the thread, you suggested that subtree be taken out of\n> git.git, and live as a standalone project.\n>\n> I'm not entirely opposed to that, but\n>\n>  1. I'm not sure how whoever picks it up (me) establishes their\n>     git-subtree as the \"real\" subtree (get a blessing from Avery?).\n\nAvery is so distant a past, but a work like this series, while we\nstill have it in contrib/ in my tree, will help build necessary\ntrust in you by the Git user/developer community, and when that\nhappens, it would be obvious to everybody that you would be the new\nowner of the tool.\n\nAnd when that happens while the tool is in the contrib/ in my tree,\nand you'd be an established trusted member of the development\ncommunity by then, I do not mind if you take it and maintain out of\ntree, if you keep working on the tool still in contrib/, or if you\npolish it to the main porcelain status and take it out of contrib/\nand make it part of the git-core proper.\n\n> On the other hand, I think that in the long-ish term git-subtree wants\n> to be rewritten in a better-suited language.  My personal inclination\n> would be Go, but if I ever want it to graduate to git-core, it'd have\n> to be C, huh?\n\nIf somebody is willing to do a rewrite and will maintain it for a\nlong haul, I'd say that it would not necessarily have to be in C\nespecially if it is not performance sensitive.\n\nAs long as it is done in a widely available language, that is (which\nused to man Perl or Python, but my persoonal preference won't carry\nthat much weight these days ;-)\n\nThen folks who really want it in C can rewrite the rewrite on their\nown after that.\n\nOne advantage you may have if you choose to take it out of my tree\nand make it a standalone project is that you have more latitude on\nthe future implementation technology, but we'd need to start from\nhelping you earn the trust by convincing others that \"subtree\" would\nbe in good hands with your volunteering ;-)\n\nThanks.\n\n"},{"id":"423325","messageId":"87zgxgxg3t.fsf@evledraar.gmail.com","threadId":"55548","inReplyTo":"20210427211748.2607474-3-lukeshu@lukeshu.com","subject":"Re: [PATCH v3 02/30] subtree: t7900: update for having the default branch name be 'main'","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-04-30T09:38:52Z","receivedAt":"2021-04-30T09:43:24Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Apr 27 2021, Luke Shumaker wrote:\n\n> From: Luke Shumaker <lukeshu@datawire.io>\n>\n> Most of the tests had been converted to support\n> `GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main`, but `contrib/subtree/t/`\n> hadn't.\n>\n> Convert it.  Most of the mentions of 'master' can just be replaced with\n> 'HEAD'.\n\nLooks good to me. FWIW (without having looked carefully) I'd have\nprobably just set up a \"sub-proj\" remote and done a \"git fetch\" after\nconfiguring a refspec during the setup, but just s/master/HEAD/ is the\nsmaller change to just fix the \"bug\".\n\n> [...]\n> @@ -994,6 +994,7 @@ test_expect_success 'push split to subproj' '\n>  next_test\n>  test_expect_success 'subtree descendant check' '\n>  \tsubtree_test_create_repo \"$subtree_test_count\" &&\n> +\tdefaultBranch=$(sed \"s,ref: refs/heads/,,\" \"$subtree_test_count/.git/HEAD\") &&\n>  \ttest_create_commit \"$subtree_test_count\" folder_subtree/a &&\n>  \t(\n>  \t\tcd \"$subtree_test_count\" &&\n\nThis though needlessly peeks into the raw refstore. Use branch=$(git\nsymbolic-ref --short HEAD) instead. See e.g. my\nhttps://lore.kernel.org/git/patch-08.11-7fb8849ce66-20210423T072006Z-avarab@gmail.com/\n"},{"id":"423326","messageId":"87wnskxfwo.fsf@evledraar.gmail.com","threadId":"55548","inReplyTo":"20210427211748.2607474-4-lukeshu@lukeshu.com","subject":"Re: [PATCH v3 03/30] subtree: t7900: use test-lib.sh's test_count","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-04-30T09:45:10Z","receivedAt":"2021-04-30T09:47:39Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Apr 27 2021, Luke Shumaker wrote:\n\n> From: Luke Shumaker <lukeshu@datawire.io>\n>\n> Use test-lib.sh's `test_count`, instead instead of having\n> t7900-subtree.sh do its own book-keeping with `subtree_test_count` that\n> has to be explicitly incremented by calling `next_test`.\n\nThis just retains an existing pattern and all that, but I think this\npattern of testing makes for hard to read & maintain tests. It looks\nlike all of these could just be:\n\n    test_when_finished \"rm -rf repo\" &&\n    git init repo &&\n    [...]\n\nI.e. the only thing that's being done here is to piggy-back on the test\ncount to create a unique repo.\n"},{"id":"423327","messageId":"87tunoxfls.fsf@evledraar.gmail.com","threadId":"55548","inReplyTo":"20210427211748.2607474-6-lukeshu@lukeshu.com","subject":"Re: [PATCH v3 05/30] subtree: t7900: comment subtree_test_create_repo","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-04-30T09:48:36Z","receivedAt":"2021-04-30T09:54:12Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Apr 27 2021, Luke Shumaker wrote:\n\n> It's unclear what the purpose of t7900-subtree.sh's\n> `subtree_test_create_repo` helper function is.  It wraps test-lib.sh's,\n> `test_create_repo` but follows that up by setting log.date=relative.  Why\n> does it set log.date=relative?\n>\n> My first guess was that at one point the tests required that, but no\n> longer do, and that the function is now vestigial.  I even wrote a patch\n> to get rid of it and was moments away from `git send-email`ing it.\n>\n> However, by chance when looking for something else in the history, I\n> discovered the true reason, from e7aac44ed2 (contrib/subtree: ignore\n> log.date configuration, 2015-07-21).  It's testing that setting\n> log.date=relative doesn't break `git subtree`, as at one point in the past\n> that did break `git subtree`.\n\nThis commit message is too much about describing the journey IMO. We\ncould just get straight to the point, e.g. something like:\n\n    Add a comment about why the git-subtree.sh tests set\n    log.relative. It's to test that we don't have a regression of the\n    bug fixed in e7aac44ed2 [...].\n\nFWIW I think just having an isolated test for this would be better, but\nsince you're just refactoring existing code I think this is fine.\n\nI.e. we'd use \"git init\" in the rest, and just have a test that stresses\nthis specifically. Or is the entry into git-subtree.sh so varied that we\nneed to \"fuzz\" all the tests like this to fully test it? I haven't\nchecked.\n"},{"id":"423329","messageId":"87r1isxffw.fsf@evledraar.gmail.com","threadId":"55548","inReplyTo":"20210427211748.2607474-7-lukeshu@lukeshu.com","subject":"Re: [PATCH v3 06/30] subtree: t7900: use 'test' for string equality","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-04-30T09:55:04Z","receivedAt":"2021-04-30T09:57:44Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Apr 27 2021, Luke Shumaker wrote:\n\n> From: Luke Shumaker <lukeshu@datawire.io>\n>\n> t7900-subtree.sh defines its own `check_equal A B` function, instead of\n> just using `test A = B` like all of the other tests.  Don't be special,\n> get rid of `check_equal` in favor of `test`.\n>\n> Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> ---\n>  contrib/subtree/t/t7900-subtree.sh | 60 ++++++++++++------------------\n>  1 file changed, 24 insertions(+), 36 deletions(-)\n>\n> diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\n> index 12b8cb03c7..76183153c9 100755\n> --- a/contrib/subtree/t/t7900-subtree.sh\n> +++ b/contrib/subtree/t/t7900-subtree.sh\n> @@ -28,18 +28,6 @@ create () {\n>  \tgit add \"$1\"\n>  }\n>  \n> -check_equal () {\n> -\ttest_debug 'echo'\n> -\ttest_debug \"echo \\\"check a:\\\" \\\"{$1}\\\"\"\n> -\ttest_debug \"echo \\\"      b:\\\" \\\"{$2}\\\"\"\n> -\tif test \"$1\" = \"$2\"\n> -\tthen\n> -\t\treturn 0\n> -\telse\n> -\t\treturn 1\n> -\tfi\n> -}\n\nIt looks like the reason this was used because when this fails just\nhaving the \"test\" makes for bad debugging. I.e. if the values don't\nmatch the $1 and $2 are not aligned, so it's hard to eyeball what went\nwrong.\n\nThese days this is more idiomatic:\n\n    echo \"Add [...]\" >expected\n    last_commit_message >actual &&\n    test_cmp expected actual\n\nSo I think in this case a better narrower improvement would be to keep\nthe check_equal function. I wonder if we shouldn't just in general in\nt/test-lib.sh have a test_cmp_str for this use-case. I.e. a trivial\nwrapper that echos the two strings to a file for you, before running\ndiff(1).\n"},{"id":"423330","messageId":"87o8dwxfco.fsf@evledraar.gmail.com","threadId":"55548","inReplyTo":"20210427211748.2607474-10-lukeshu@lukeshu.com","subject":"Re: [PATCH v3 09/30] subtree: t7900: rename last_commit_message to last_commit_subject","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-04-30T09:59:10Z","receivedAt":"2021-04-30T09:59:39Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Apr 27 2021, Luke Shumaker wrote:\n\n> From: Luke Shumaker <lukeshu@datawire.io>\n>\n> t7900-subtree.sh defines a helper function named last_commit_message.\n> However, it only returns the subject line of the commit message, not the\n> entire commit message.  So rename it, to make the name less confusing.\n\nThis and 06/30 (which I also had a comment on) would be less churn if it\nwere arranged to e.g. use the helper / only touch all these lines once.\n"},{"id":"423331","messageId":"87lf90xf83.fsf@evledraar.gmail.com","threadId":"55548","inReplyTo":"20210427211748.2607474-11-lukeshu@lukeshu.com","subject":"Re: [PATCH v3 10/30] subtree: t7900: add a test for the -h flag","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2021-04-30T10:01:50Z","receivedAt":"2021-04-30T10:02:24Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"\nOn Tue, Apr 27 2021, Luke Shumaker wrote:\n\n> From: Luke Shumaker <lukeshu@datawire.io>\n>\n> It's a dumb test, but it's surprisingly easy to break.\n>\n> Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> ---\n>  contrib/subtree/t/t7900-subtree.sh | 7 +++++++\n>  1 file changed, 7 insertions(+)\n>\n> diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\n> index 5c2510f1f5..9afba2f282 100755\n> --- a/contrib/subtree/t/t7900-subtree.sh\n> +++ b/contrib/subtree/t/t7900-subtree.sh\n> @@ -37,6 +37,13 @@ last_commit_subject () {\n>  \tgit log --pretty=format:%s -1\n>  }\n>  \n> +test_expect_success 'shows short help text for -h' '\n> +\ttest_expect_code 129 git subtree -h >out 2>err &&\n> +\ttest_must_be_empty err &&\n> +\tgrep -e \"^ *or: git subtree pull\" out &&\n> +\tgrep -e --annotate out\n\nI wonder if \"grep -e --could-be-an-option-if-not-for-e\" is portable,\nprobably....\n"},{"id":"423335","messageId":"565bbf80-9bdb-699c-ed27-107923e4b94a@gmail.com","threadId":"55548","inReplyTo":"20210427211748.2607474-11-lukeshu@lukeshu.com","subject":"Re: [PATCH v3 10/30] subtree: t7900: add a test for the -h flag","fromName":"Bagas Sanjaya","fromEmail":"bagasdotme@gmail.com","sentAt":"2021-04-30T12:22:50Z","receivedAt":"2021-04-30T12:23:03Z","isPatch":true,"sender":{"key":"bagasdotme@gmail.com","avatar":"https://avatars.githubusercontent.com/u/40219486?v=4"},"body":"On 28/04/21 04.17, Luke Shumaker wrote:\n> It's a dumb test, but it's surprisingly easy to break.\n\nWhy did you say that? Very sensitive?\n\n-- \nAn old man doll... just what I always wanted! - Clara\n"},{"id":"423350","messageId":"87mttfpxgw.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"87zgxgxg3t.fsf@evledraar.gmail.com","subject":"Re: [PATCH v3 02/30] subtree: t7900: update for having the default branch name be 'main'","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-30T16:07:43Z","receivedAt":"2021-04-30T16:07:53Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 30 Apr 2021 03:38:52 -0600,\nÆvar Arnfjörð Bjarmason wrote:\n> > @@ -994,6 +994,7 @@ test_expect_success 'push split to subproj' '\n> >  next_test\n> >  test_expect_success 'subtree descendant check' '\n> >  \tsubtree_test_create_repo \"$subtree_test_count\" &&\n> > +\tdefaultBranch=$(sed \"s,ref: refs/heads/,,\" \"$subtree_test_count/.git/HEAD\") &&\n> >  \ttest_create_commit \"$subtree_test_count\" folder_subtree/a &&\n> >  \t(\n> >  \t\tcd \"$subtree_test_count\" &&\n> \n> This though needlessly peeks into the raw refstore. Use branch=$(git\n> symbolic-ref --short HEAD) instead. See e.g. my\n> https://lore.kernel.org/git/patch-08.11-7fb8849ce66-20210423T072006Z-avarab@gmail.com/\n\nI was about to say that doesn't work with a freshly initialized repo\nwithout a commit yet, but I'm thinking of `git rev-parse --abbrev-ref\nHEAD`.\n\nI'll change it if I have to re-roll for another reason.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"423351","messageId":"87lf8zpxd3.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"87wnskxfwo.fsf@evledraar.gmail.com","subject":"Re: [PATCH v3 03/30] subtree: t7900: use test-lib.sh's test_count","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-30T16:10:00Z","receivedAt":"2021-04-30T16:10:06Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 30 Apr 2021 03:45:10 -0600,\nÆvar Arnfjörð Bjarmason wrote:\n> On Tue, Apr 27 2021, Luke Shumaker wrote:\n> > Use test-lib.sh's `test_count`, instead instead of having\n> > t7900-subtree.sh do its own book-keeping with `subtree_test_count` that\n> > has to be explicitly incremented by calling `next_test`.\n> \n> This just retains an existing pattern and all that, but I think this\n> pattern of testing makes for hard to read & maintain tests. It looks\n> like all of these could just be:\n> \n>     test_when_finished \"rm -rf repo\" &&\n>     git init repo &&\n>     [...]\n> \n> I.e. the only thing that's being done here is to piggy-back on the test\n> count to create a unique repo.\n\nThanks for the tip, I'll do that for any new tests I add, going\nforward.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"423352","messageId":"87k0ojpx6x.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"87tunoxfls.fsf@evledraar.gmail.com","subject":"Re: [PATCH v3 05/30] subtree: t7900: comment subtree_test_create_repo","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-30T16:13:42Z","receivedAt":"2021-04-30T16:13:49Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 30 Apr 2021 03:48:36 -0600,\nÆvar Arnfjörð Bjarmason wrote:\n> On Tue, Apr 27 2021, Luke Shumaker wrote:\n> > It's unclear what the purpose of t7900-subtree.sh's\n> > `subtree_test_create_repo` helper function is.  It wraps test-lib.sh's,\n> > `test_create_repo` but follows that up by setting log.date=relative.  Why\n> > does it set log.date=relative?\n> >\n> > My first guess was that at one point the tests required that, but no\n> > longer do, and that the function is now vestigial.  I even wrote a patch\n> > to get rid of it and was moments away from `git send-email`ing it.\n> >\n> > However, by chance when looking for something else in the history, I\n> > discovered the true reason, from e7aac44ed2 (contrib/subtree: ignore\n> > log.date configuration, 2015-07-21).  It's testing that setting\n> > log.date=relative doesn't break `git subtree`, as at one point in the past\n> > that did break `git subtree`.\n> \n> This commit message is too much about describing the journey IMO. We\n> could just get straight to the point, e.g. something like:\n> \n>     Add a comment about why the git-subtree.sh tests set\n>     log.relative. It's to test that we don't have a regression of the\n>     bug fixed in e7aac44ed2 [...].\n\nOK, I'll reword it if I re-roll.\n\n> FWIW I think just having an isolated test for this would be better, but\n> since you're just refactoring existing code I think this is fine.\n> \n> I.e. we'd use \"git init\" in the rest, and just have a test that stresses\n> this specifically. Or is the entry into git-subtree.sh so varied that we\n> need to \"fuzz\" all the tests like this to fully test it? I haven't\n> checked.\n\nI'd have to examine it a bit more to be sure, but I think that you're\nright.  That as long as the test does a 'split' that creates new\ncommits, then just one test should be fine.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"423355","messageId":"87im43pwah.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"87r1isxffw.fsf@evledraar.gmail.com","subject":"Re: [PATCH v3 06/30] subtree: t7900: use 'test' for string equality","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-30T16:33:10Z","receivedAt":"2021-04-30T16:33:26Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 30 Apr 2021 03:55:04 -0600,\nÆvar Arnfjörð Bjarmason wrote:\n> \n> \n> On Tue, Apr 27 2021, Luke Shumaker wrote:\n> \n> > From: Luke Shumaker <lukeshu@datawire.io>\n> >\n> > t7900-subtree.sh defines its own `check_equal A B` function, instead of\n> > just using `test A = B` like all of the other tests.  Don't be special,\n> > get rid of `check_equal` in favor of `test`.\n> >\n> > Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> > ---\n> >  contrib/subtree/t/t7900-subtree.sh | 60 ++++++++++++------------------\n> >  1 file changed, 24 insertions(+), 36 deletions(-)\n> >\n> > diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\n> > index 12b8cb03c7..76183153c9 100755\n> > --- a/contrib/subtree/t/t7900-subtree.sh\n> > +++ b/contrib/subtree/t/t7900-subtree.sh\n> > @@ -28,18 +28,6 @@ create () {\n> >  \tgit add \"$1\"\n> >  }\n> >  \n> > -check_equal () {\n> > -\ttest_debug 'echo'\n> > -\ttest_debug \"echo \\\"check a:\\\" \\\"{$1}\\\"\"\n> > -\ttest_debug \"echo \\\"      b:\\\" \\\"{$2}\\\"\"\n> > -\tif test \"$1\" = \"$2\"\n> > -\tthen\n> > -\t\treturn 0\n> > -\telse\n> > -\t\treturn 1\n> > -\tfi\n> > -}\n> \n> It looks like the reason this was used because when this fails just\n> having the \"test\" makes for bad debugging. I.e. if the values don't\n> match the $1 and $2 are not aligned, so it's hard to eyeball what went\n> wrong.\n\nIt's easy to make that assumption, but looking at the history it seems\nthe \"actual\" reason it exists is that it's vestigial from before the\nsubtree tests used test-lib.sh, and echoing it like that was the only\nway you'd get feedback.\n\n> These days this is more idiomatic:\n> \n>     echo \"Add [...]\" >expected\n>     last_commit_message >actual &&\n>     test_cmp expected actual\n> \n> So I think in this case a better narrower improvement would be to keep\n> the check_equal function. I wonder if we shouldn't just in general in\n> t/test-lib.sh have a test_cmp_str for this use-case. I.e. a trivial\n> wrapper that echos the two strings to a file for you, before running\n> diff(1).\n\nBut it's been my experience that the tests are already impossible to\ndebug without passing `-x`, so everything from `check_equal` ends up\nbeing just noise.\n\nAnd also I figured if `test` is good enough for t9350-fast-export.sh,\nthen it's good enough for t7900-subtree.sh... after working with\nsubtree, I'd accidentally written a couple of the checks in one of my\nfast-export patchsets using `check_equal`.  Being special makes things\nharder to hack on.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"423357","messageId":"87h7jnpvyd.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"87lf90xf83.fsf@evledraar.gmail.com","subject":"Re: [PATCH v3 10/30] subtree: t7900: add a test for the -h flag","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-30T16:40:26Z","receivedAt":"2021-04-30T16:40:32Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 30 Apr 2021 04:01:50 -0600,\nÆvar Arnfjörð Bjarmason wrote:\n> \n> \n> On Tue, Apr 27 2021, Luke Shumaker wrote:\n> \n> > From: Luke Shumaker <lukeshu@datawire.io>\n> >\n> > It's a dumb test, but it's surprisingly easy to break.\n> >\n> > Signed-off-by: Luke Shumaker <lukeshu@datawire.io>\n> > ---\n> >  contrib/subtree/t/t7900-subtree.sh | 7 +++++++\n> >  1 file changed, 7 insertions(+)\n> >\n> > diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh\n> > index 5c2510f1f5..9afba2f282 100755\n> > --- a/contrib/subtree/t/t7900-subtree.sh\n> > +++ b/contrib/subtree/t/t7900-subtree.sh\n> > @@ -37,6 +37,13 @@ last_commit_subject () {\n> >  \tgit log --pretty=format:%s -1\n> >  }\n> >  \n> > +test_expect_success 'shows short help text for -h' '\n> > +\ttest_expect_code 129 git subtree -h >out 2>err &&\n> > +\ttest_must_be_empty err &&\n> > +\tgrep -e \"^ *or: git subtree pull\" out &&\n> > +\tgrep -e --annotate out\n> \n> I wonder if \"grep -e --could-be-an-option-if-not-for-e\" is portable,\n> probably....\n\nIt's POSIX, and at least works on GNU, busybox, and macOS\n(based-on-FreeBSD) grep.  If it turns out there's somewhere it doesn't\nwork, I'd be happy to change it, but my baseline assumption is that\nit's portable.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"},{"id":"423358","messageId":"87fsz7pvk5.wl-lukeshu@lukeshu.com","threadId":"55548","inReplyTo":"565bbf80-9bdb-699c-ed27-107923e4b94a@gmail.com","subject":"Re: [PATCH v3 10/30] subtree: t7900: add a test for the -h flag","fromName":"Luke Shumaker","fromEmail":"lukeshu@lukeshu.com","sentAt":"2021-04-30T16:48:58Z","receivedAt":"2021-04-30T16:49:03Z","isPatch":true,"sender":{"key":"lukeshu@lukeshu.com","avatar":"https://gravatar.com/avatar/b040e950069ff2e81f026755b364d668aab9d278527aaa2415d0a8845f640bc5?d=mp&s=160"},"body":"On Fri, 30 Apr 2021 06:22:50 -0600,\nBagas Sanjaya wrote:\n> \n> On 28/04/21 04.17, Luke Shumaker wrote:\n> > It's a dumb test, but it's surprisingly easy to break.\n> \n> Why did you say that? Very sensitive?\n\nBecause I very nearly sent v1 of this patchset with a broken '-h' flag\n:)\n\nI don't recall for certain, but I think the mistake I made was\nallowing the ordering of `eval \"$(echo \"$OPTS_SPEC\" | git rev-parse\n--parseopt -- \"$@\")\"` and `. git-sh-setup` to get flipped.  That\ncertainly will break '-h', anyway.\n\n-- \nHappy hacking,\n~ Luke Shumaker\n"}]}