{"thread":{"id":"17763","subject":"[RFC] What's the best UI for 'git submodule split'?","startedAt":"2009-02-12T21:50:28Z","lastAt":"2009-02-19T23:04:36Z","messageCount":13,"participants":["Eric Kidd","Junio C Hamano","Lars Hjemli","Johannes Schindelin","Sverre Rabbelier","Nanako Shiraishi","Kyle Moffett"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"104435","messageId":"431341160902121350x45076c8cj26afab0b7a51cac5@mail.gmail.com","threadId":"17763","inReplyTo":null,"subject":"[RFC] What's the best UI for 'git submodule split'?","fromName":"Eric Kidd","fromEmail":"eric.kidd@gmail.com","sentAt":"2009-02-12T21:50:28Z","receivedAt":"2009-02-12T21:50:28Z","isPatch":false,"sender":{"key":"eric.kidd@gmail.com","avatar":null},"body":"The problem: At work, we're converting a large git repository to\nSubversion. This repository contains an optional \"streaming/media\"\ndirectory which we want to split into a submodule. Some constraints:\n\n  1) We want 'git bisect' to work with the converted repository, so\nthe submodule should exist all throughout the repository's history,\nand not just in the HEAD revision.\n  2) The submodule has moved around the tree in the past, and it has\noccasionally disappeared for a commit or two. For example, it used to\nlive in \"Media\", not \"streaming/media\". We want to hook up these\ndifferent historical locations into a single submodule.\n\nThe proposed solution: I'm working on a 'git submodule split' script\nwhich works as follows:\n\n  git submodule split streaming/media Media\n  rm .git/refs/original # or just use --force below\n  git submodule split other-binaries\n\nThis will create two submodules, one at streaming/media and one at\nother-binaries. It will rewrite the parent repository's history to\ncreate correct submodule links, and update .gitmodules as necessary at\neach point in the history. The new modules will be placed at their\nmost recent locations in the tree.\n\nSome Q&A:\n\nQ. Why not merge 'submodule split' into the existing 'filter-branch' loop?\n\nA. Internally, 'submodule split' needs to make two separate passes\nwith 'filter-branch': One to create the new submodule, and one to\nupdate the parent. If I were to merge 'submodule split' into the\nexisting filter-branch loop, filter-branch would need to keep track of\ntwo repositories. Writing 'submodule split' as a wrapper around\nfilter-branch helps keep filter-branch simple.\n\nQ. Why only process one submodule at time?\n\nA. If there were multiple submodules, each with several different\nhistorical locations, the data structures in sh would get too tricky\nfor me to implement well. But I'm happy to take patches and UI\nsuggestions.\n\nQ. Why operate on the current directory, and why output the new\nsubmodule in place?\n\nA. An earlier version of 'submodule split' took the arguments\n'src-repo dst-repo sub-repo sub-repo-dir...'. This required the user\nto do more typing, and it didn't feel very \"git like\". Johannes\nSchindelin suggested the current interface. The new interface feels\nmore natural to me, and it's certainly easier to use in the common\ncases.\n\nQ. What's the status of the code?\n\nA. I'll have a very basic implementation of this interface shortly--I\ncan already handle simple splits, but I want to add more test cases\nand add support for directories which move around the tree.\n\nThank you very much for your feedback! I appreciate the time that the\nreviewers spent helping to improve my filter-branch patch, and I'd\nlike to make this patch as good as possible.\n\nCheers,\nEric\n"},{"id":"104573","messageId":"1234578258-48870-1-git-send-email-git@randomhacks.net","threadId":"17763","inReplyTo":"431341160902121350x45076c8cj26afab0b7a51cac5@mail.gmail.com","subject":"[RFC/PATCHv2] git submodule split","fromName":"Eric Kidd","fromEmail":"git@randomhacks.net","sentAt":"2009-02-14T02:24:18Z","receivedAt":"2009-02-14T02:24:18Z","isPatch":false,"sender":{"key":"git@randomhacks.net","avatar":null},"body":"Proposed usage:\n    git submodule split [--url submodule_repo_url] submodule_dir \\\n        [alternate_dir...]\n\nReplace submodule_dir with a newly-created submodule, keeping all the\nhistory of submodule_dir.  This command also rewrites each commit in the\ncurrent repository's history to include the correct revision of\nsumodule_dir and the appropriate .gitmodules entries.\n\nIf the submodule has moved around the source tree, specify one or more\nvalues for alternate_dir.  To specify the URL of the newly created\nrepository (for use in .gitmodules), use the --url parameter.\n\nJohannes Schindelin provided extensive help with the UI and\nimplementation of this command (but has not yet reviewed the code).\n\nCc: Junio C Hamano <gitster@pobox.com>\nCc: Johannes Schindelin <johannes.schindelin@gmx.de>\n\n---\nOpen questions:\n\n  1) Right now, this command is actually git-submodule-split.sh.  Should\n     I include this code directly into git-submodule.sh, or move it\n     to git-submodule--split.sh and hook it into git-submodule.sh?\n\n  2) Should I implement a --force flag based on filter-branch?  Johannes\n     Schindelin has suggested that it might be better to remove the\n     --force flag from filter-branch and just rely on the reflog to keep\n     backups.\n\n  3) It would be useful to have a version of this command which didn't\n     rewrite the super-project's history.  In fact, the non-rewriting\n     version should probably be the default, and the current behavior\n     should probably be selected using --rewrite.  Thoughts?\n\n  4) We're obviously going to need to support revision arguments other\n     than --all (which is what we currently pass to filter-branch).  Should\n     we default to the current branch only, or to --all?\n\nDesign Q&A (this appeared in an earlier e-mail)\n\n  Q. Why not merge 'submodule split' into the existing 'filter-branch'\n  loop?\n\n  A. Internally, 'submodule split' needs to make two separate passes\n  with 'filter-branch': One to create the new submodule, and one to\n  update the parent. If I were to merge 'submodule split' into the\n  existing filter-branch loop, filter-branch would need to keep track of\n  two repositories. Writing 'submodule split' as a wrapper around\n  filter-branch helps keep filter-branch simple.\n\n  Q. Why only process one submodule at time?\n\n  A. If there were multiple submodules, each with several different\n  historical locations, the data structures in sh would get too tricky\n  for me to implement well. But I'm happy to take patches and UI\n  suggestions.\n\n  Q. Why operate on the current directory, and why output the new\n  submodule in place?\n\n  A. An earlier version of 'submodule split' took the arguments\n  'src-repo dst-repo sub-repo sub-repo-dir...'. This required the user\n  to do more typing, and it didn't feel very \"git like\". Johannes\n  Schindelin suggested the current interface. The new interface feels\n  more natural to me, and it's certainly easier to use in the common\n  cases.\n\n .gitignore                 |    1 +\n Makefile                   |    1 +\n git-submodule-split.sh     |  190 ++++++++++++++++++++++++++++++++++++++++++++\n t/t7404-submodule-split.sh |  135 +++++++++++++++++++++++++++++++\n 4 files changed, 327 insertions(+), 0 deletions(-)\n create mode 100644 git-submodule-split.sh\n create mode 100755 t/t7404-submodule-split.sh\n\ndiff --git a/.gitignore b/.gitignore\nindex 1c57d4c..603ad7a 100644\n--- a/.gitignore\n+++ b/.gitignore\n@@ -118,6 +118,7 @@ git-show\n git-show-branch\n git-show-index\n git-show-ref\n+git-submodule-split\n git-stage\n git-stash\n git-status\ndiff --git a/Makefile b/Makefile\nindex b040a96..96274f1 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -276,6 +276,7 @@ SCRIPT_SH += git-sh-setup.sh\n SCRIPT_SH += git-stash.sh\n SCRIPT_SH += git-submodule.sh\n SCRIPT_SH += git-web--browse.sh\n+SCRIPT_SH += git-submodule-split.sh\n \n SCRIPT_PERL += git-add--interactive.perl\n SCRIPT_PERL += git-archimport.perl\ndiff --git a/git-submodule-split.sh b/git-submodule-split.sh\nnew file mode 100644\nindex 0000000..4582d2a\n--- /dev/null\n+++ b/git-submodule-split.sh\n@@ -0,0 +1,190 @@\n+#!/bin/sh\n+# \n+# Split a repository into a submodule and main module, with history\n+#\n+# Copyright 2009 Trustees of Dartmouth College\n+# License: GNU General Public License, version 2 or later\n+\n+USAGE=\"[--url submodule_repo_url] submodule_dir [alternate_dir...]\"\n+\n+OPTIONS_SPEC=\n+. git-sh-setup\n+require_work_tree\n+\n+# Set up our temporary directory.  We export these variables because we\n+# want to use them from scripts passed to 'git filter-branch'.  We can't\n+# simply substitute these variable values into the text of the scripts we\n+# pass to 'git filter-branch', because the filenames may contain spaces,\n+# which would get mangled.  Thanks to Johannes Schindelin for this idea.\n+export GIT_SPLIT_TEMP_DIR=\"$GIT_DIR/.git_split\"\n+export GIT_SPLIT_MAP_DIR=\"$GIT_SPLIT_TEMP_DIR/map\"\n+rm -rf \"$GIT_SPLIT_TEMP_DIR\" &&\n+mkdir -p \"$GIT_SPLIT_MAP_DIR\" || exit\n+\n+# Parse our command-line arguments.\n+mkdir \"$GIT_SPLIT_TEMP_DIR/dirs\" || exit\n+dir_count=0\n+while test $# -ne 0; do\n+\tcase \"$1\" in\n+\t--)\n+\t\tshift\n+\t\tbreak\n+\t\t;;\n+\t--url)\n+                shift\n+                test $# -ne 0 || die \"Must supply argument to --url\"\n+\t\tsub_url=\"$1\"\n+\t\tshift\n+\t\t;;\n+        -*)\n+\t\tdie \"Unknown option: $1\"\n+\t\t;;\n+\t*)\n+\t\t# Use the first specified directory as the subrepository\n+\t\t# name.\n+\t\tif test \"$dir_count\" -eq 0; then\n+\t\t\tsub_path=\"$1\"\n+\t\tfi\n+\n+\t\t# There's no good way to pass an array of filenames\n+\t\t# containing spaces to our subprocesses, so let's cheat\n+\t\t# shamelessly and create an \"array\" of files on disk.\n+\t\tprintf '%s' \"$1\" > \"$GIT_SPLIT_TEMP_DIR/dirs/$dir_count\"\n+\t\tdir_count=$(($dir_count + 1))\n+                shift\n+\t\t;;\n+\tesac\n+done\n+\n+# We should have at least one directory listed on the command line.\n+test \"$dir_count\" -ge 1 || usage\n+\n+# Default the repository URL to something based on the repository path.\n+if test -z \"$sub_url\"; then\n+\tsub_url=\"../$sub_path\"\n+fi\n+\n+# TODO: Pass remaining arguments to rev-parse, defaulting to --all.\n+revs=\"--all\"\n+\n+# More variables for our subprocesses.\n+export GIT_SPLIT_DIR_COUNT=\"$dir_count\"\n+export GIT_SPLIT_SUB_PATH=\"$sub_path\"\n+export GIT_SPLIT_SUB_URL=\"$sub_url\"\n+\n+# Make sure our environment is sane.\n+test \"$(is_bare_repository)\" = false ||\n+\tdie \"Cannot run submodule split in a bare repository\"\n+git diff-files --ignore-submodules --quiet &&\n+\tgit diff-index --cached --quiet HEAD -- ||\n+\tdie \"Cannot split out a submodule with a dirty working directory.\"\n+(cd \"$sub_path\" &&\n+\ttest \"$GIT_DIR\" = \"$(git rev-parse --git-dir)\" ||\n+\tdie \"$sub_path is already in a submodule\")\n+\n+\n+\n+#--------------------------------------------------------------------------\n+# Create the new submodule\n+\n+# Create a new repository at the last known address of our submodule.  We\n+# initially share our objects with our parent repository.\n+src_repo=\"$(pwd)\"\n+sub_repo_temp=\"$GIT_SPLIT_TEMP_DIR/s\" && mkdir \"$sub_repo_temp\" &&\n+(cd \"$sub_repo_temp\" &&\n+\tgit init &&\n+\tgit remote add origin --mirror \"$src_repo\" &&\n+\techo \"$src_repo/.git/objects\" > .git/objects/info/alternates &&\n+\tgit fetch --update-head-ok &&\n+\tgit remote rm origin &&\n+\tgit read-tree -u -m HEAD) || exit\n+\n+index_filter=$(cat << \\EOF\n+map_info=\"$GIT_SPLIT_MAP_DIR/$GIT_COMMIT\"\n+\n+# Check for the submodule in all possible locations.\n+i=0\n+while test \"$i\" -lt \"$GIT_SPLIT_DIR_COUNT\"; do\n+\tcandidate=\"$(cat \"$GIT_SPLIT_TEMP_DIR/dirs/$i\")\" || exit\n+\tif git rev-parse -q --verify \"$GIT_COMMIT:$candidate\"; then\n+\t\t# Borrowed from git filter-branch.\n+\t\terr=\"$(git read-tree -i -m \"$GIT_COMMIT:$candidate\" 2>&1)\" ||\n+\t\t\tdie \"$err\"\n+\t        printf '%s' \"$candidate\" > \"$map_info-dir\"\n+\t\tbreak\n+\tfi\n+\ti=$(($i + 1))\n+done\n+EOF\n+)\n+\n+commit_filter=$(cat << \\EOF\n+map_info=\"$GIT_SPLIT_MAP_DIR/$GIT_COMMIT\"\n+if test -f \"$map_info-dir\"; then\n+\tnew_commit=\"$(git_commit_non_empty_tree \"$@\")\" || exit\n+\techo \"$new_commit\"\n+\techo \"$new_commit\" > \"$map_info-submodule-commit\" ||\n+\t\tdie \"Can't record the commit ID of the new commit\"\n+else\n+\tskip_commit \"$@\"\n+fi\n+EOF\n+)\n+\n+# Run our filters, repack the results as a standalone repository with no\n+# extra history, and check out HEAD.\n+(cd \"$sub_repo_temp\" &&\n+\tgit filter-branch --index-filter \"$index_filter\" \\\n+\t\t--commit-filter \"$commit_filter\" -- \"$revs\" &&\n+\trm -rf .git/refs/original &&\n+\tgit reflog expire --expire=\"now\" --all &&\n+\tgit repack -a -d &&\n+\trm .git/objects/info/alternates) || exit\n+\n+#--------------------------------------------------------------------------\n+# Create the new superproject\n+\n+index_filter=$(cat << \\EOF\n+map_info=\"$GIT_SPLIT_MAP_DIR/$GIT_COMMIT\"\n+\n+# Only update the index if the submodule is present in this revision.\n+if test -f \"$map_info-dir\"; then\n+\tdir=\"$(cat \"$map_info-dir\")\" || exit\n+\n+\t# Splice the repo into the tree.\n+\ttest -f \"$map_info-submodule-commit\" ||\n+\t\tdie \"Can't find map for $GIT_COMMIT\"\n+\tgit rm -q --cached -r \"$dir\" || exit\n+\tsubcommit=\"$(cat \"$map_info-submodule-commit\")\" || exit\n+\techo \"160000 $subcommit\t$dir\" |\n+\t\tgit update-index --index-info || exit\n+\n+\t# Either update the old .gitmodules file, or make a new one.\n+\tgitmodules=\"$GIT_SPLIT_TEMP_DIR/gitmodules\"\n+\tif git rev-parse -q --verify \"$GIT_COMMIT:.gitmodules\"; then\n+\t\tgit cat-file blob \"$GIT_COMMIT:.gitmodules\" > \"$gitmodules\" ||\n+\t\t\texit\n+\tfi\n+\tsubsection=submodule.\"$GIT_SPLIT_SUB_PATH\"\n+\tgit config -f \"$gitmodules\" \"$subsection\".path \"$dir\"\n+\tgit config -f \"$gitmodules\" \"$subsection\".url \"$GIT_SPLIT_SUB_URL\"\n+\n+\t# Write the new .gitmodules file into the tree.\n+\tnew_obj=\"$(git hash-object -t blob -w \"$gitmodules\")\" ||\n+\t\tdie \"Error adding new .gitmodules file to tree\"\n+\tgit update-index --add --cacheinfo 100644 \"$new_obj\" .gitmodules || exit\n+fi\n+EOF\n+)\n+\n+# Run our filter.\n+git filter-branch --index-filter \"$index_filter\" -- \"$revs\" || exit\n+\n+# Move our submodule into place.  This has to wait until last, because\n+# we want to keep the tree clean until after the final git filter, and we\n+# need to have a place to put the new submodule.\n+rmdir \"$sub_path\"\n+test -d \"$sub_path\" && die \"submodule $sub_path was not actually deleted\"\n+mv \"$sub_repo_temp\" \"$sub_path\" || exit\n+\n+exit 0\ndiff --git a/t/t7404-submodule-split.sh b/t/t7404-submodule-split.sh\nnew file mode 100755\nindex 0000000..ecc167e\n--- /dev/null\n+++ b/t/t7404-submodule-split.sh\n@@ -0,0 +1,135 @@\n+#!/bin/sh\n+#\n+# Copyright 2009 Trustees of Dartmouth College\n+\n+test_description='git submodule split tests'\n+. ./test-lib.sh\n+\n+# We use two main repositories: An \"original\" repository, which remains\n+# unmodified, and a \"working\" repository, which we transform repeatedly.\n+rm -rf .git\n+test_create_repo original\n+\n+test_expect_success 'create original repository' '\n+\t(cd original &&\n+\t\techo \"In main project\" > main-file &&\n+\t\tmkdir sub1 &&\n+\t\techo \"In sub1\" > sub1/sub1-file &&\n+\t\tgit add . &&\n+\t\tgit commit -m \"Original project and sub1\" &&\n+\t\tgit tag c1 &&\n+        \tmkdir -p nested/sub2 &&\n+\t  \techo \"In sub2\" > nested/sub2/sub2-file &&\n+\t\tgit add . &&\n+\t\tgit commit -m \"Add sub2\" &&\n+\t\tgit tag c2 &&\n+\t\tgit rm -r nested &&\n+\t\tgit commit -m \"Removing nested temporarily\" &&\n+\t\tgit tag c3 &&\n+\t\tgit checkout c2 -- nested &&\n+\t\tgit add . &&\n+\t\tgit commit -m \"Putting nested back\" &&\n+\t\tgit tag c4 &&\n+\t\tgit mv nested/sub2 other-sub2 &&\n+\t\techo \"Changed file\" >> other-sub2/sub2-file &&\n+\t\tgit add . &&\n+\t\tgit commit -m \"Moving sub2 and changing a file\" &&\n+\t\tgit tag c5 &&\n+\t\tgit mv other-sub2 nested/sub2 &&\n+\t\tgit commit -m \"Moving sub2 back\" &&\n+\t\tgit tag c6\n+\t)\n+'\n+\n+test_expect_success 'make a working repository' '\n+\tabs_src_path=\"$(pwd)/original\" && mkdir working &&\n+\t(cd working &&\n+\t\tgit init &&\n+\t\tgit remote add origin --mirror \"$abs_src_path\" &&\n+\t\tgit fetch --update-head-ok &&\n+\t\tgit remote rm origin &&\n+\t\tgit read-tree -u -m HEAD)\n+'\n+\n+test_expect_success 'split out sub1' '\n+\t(cd working &&\n+\t\tgit submodule-split --url ../sub1-repo sub1 &&\n+\t\ttest -f main-file &&\n+\t\ttest -d sub1/.git &&\n+\t\ttest_must_fail git rev-parse -q --verify HEAD:sub1/sub1-file &&\n+\t\t(cd sub1 && git rev-parse -q --verify HEAD:sub1-file)\n+\t)\n+'\n+\n+test_expect_success 'split out sub2' '\n+\t(cd working &&\n+\t\trm -rf .git/refs/original &&\n+\t\tgit submodule-split nested/sub2 other-sub2 &&\n+\t\ttest -d nested/sub2/.git &&\n+\t\ttest_must_fail git rev-parse -q --verify \\\n+\t\t\tHEAD:nested/sub2/sub2-file &&\n+\t\ttest_must_fail git rev-parse -q --verify \\\n+\t\t\tc5:other-sub2/sub2-file &&\n+\t\t(cd nested/sub2 &&\n+\t\t\tgit rev-parse -q --verify HEAD:sub2-file &&\n+\t\t\tgit rev-parse -q --verify c5:sub2-file)\n+\t)\n+'\n+\n+submodule_path() {\n+\tgit config -f .gitmodules submodule.\"$1\".path\n+}\n+\n+submodule_url() {\n+\tgit config -f .gitmodules submodule.\"$1\".url\n+}\n+\n+test_expect_success 'make sure .gitmodules knows about both submodules' '\n+\t(cd working &&\n+\t\ttest \"$(submodule_path sub1)\" = sub1 &&\n+\t\ttest \"$(submodule_url  sub1)\" = ../sub1-repo &&\n+\t\ttest \"$(submodule_path nested/sub2)\" = nested/sub2 &&\n+\t\ttest \"$(submodule_url  nested/sub2)\" = ../nested/sub2\n+\t)\n+'\n+\n+test_expect_success 'compare each commit in split repository with original' '\n+\trm -rf working/.git/refs/original &&\n+\tmodule_base=\"$(pwd)/original\" &&\n+\t(cd working && git config remote.origin.url \"$module_base\") &&\n+\tmv working/sub1 sub1-repo &&\n+\tmkdir nested && mv working/nested/sub2 nested &&\n+\toriginal_revs=\"$(cd original && git rev-parse --all)\" &&\n+\tworking_revs=\"$(cd working && git rev-parse --all)\" &&\n+\twhile test -n \"$original_revs\"; do\n+\t\toriginal_commit=\"$(echo \"$original_revs\" | head -n 1)\" &&\n+\t\tworking_commit=\"$(echo \"$working_revs\" | head -n 1)\" &&\n+\t\toriginal_revs=\"$(echo \"$original_revs\" | tail -n +2)\" &&\n+\t\tworking_revs=\"$(echo \"$working_revs\" | tail -n +2)\" &&\n+\t\t(cd original && git checkout -f \"$original_commit\") &&\n+\t\t(cd working && git checkout -f \"$working_commit\" &&\n+\t\t\tgit clean -fd &&\n+\t\t\tgit submodule update --init) &&\n+\t\tdiff -Nr -x .git -x .gitmodules original working ||\n+\t\t\texit\n+\tdone\n+'\n+\n+test_expect_success 'verify that empty commits are skipped' '\n+\t(cd working/sub1 &&\n+\t\ttest \"$(git rev-parse c1)\" = \"$(git rev-parse c2)\"\n+\t)\n+'\n+\n+# Note that we should probably also drop the c3 tag here, because sub2\n+# temporarily disappeared from the tree during that commit, but doing so\n+# will require more work.  For now, we map c3 back to the last known state\n+# of the directory when it was actually in-tree.\n+test_expect_success 'verify that directories missing from rev are skipped' '\n+\t(cd working/nested/sub2 &&\n+\t\ttest_must_fail git rev-parse -q --verify c1 &&\n+\t\ttest \"$(git rev-parse c2)\" = \"$(git rev-parse c4)\"\n+\t)\n+'\n+\n+test_done\n-- \n1.6.2.rc0.59.g5c88.dirty\n"},{"id":"104587","messageId":"7v3aeh3a84.fsf@gitster.siamese.dyndns.org","threadId":"17763","inReplyTo":"1234578258-48870-1-git-send-email-git@randomhacks.net","subject":"Re: [RFC/PATCHv2] git submodule split","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-02-14T04:37:15Z","receivedAt":"2009-02-14T04:37:15Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Eric Kidd <git@randomhacks.net> writes:\n\n> Proposed usage:\n>     git submodule split [--url submodule_repo_url] submodule_dir \\\n>         [alternate_dir...]\n>\n> Replace submodule_dir with a newly-created submodule, keeping all the\n> history of submodule_dir.  This command also rewrites each commit in the\n> current repository's history to include the correct revision of\n> sumodule_dir and the appropriate .gitmodules entries.\n>\n> If the submodule has moved around the source tree, specify one or more\n> values for alternate_dir.  To specify the URL of the newly created\n> repository (for use in .gitmodules), use the --url parameter.\n\nUnfortunately, I do not think we have designed fully (nor implemented at\nall) behaviour to check out different points of history that has the same\nsubmodule moved around in the superproject tree.\n\nThere were several unconcluded discussions done in the past (and I admit I\nparticipated in a few of them), but it may be hard to use the resulting\nrepository out of this tool.\n\nI am not saying the split-submodule-history tool is bad in any way, of\ncourse.  I'm just saying that the \"git submodule\" side needs to be updated\nto support such a history better; otherwise the tool's output won't be\nusable effectively.  You may want to Cc \"submodule\" people in the\ndiscussion.\n\n> Johannes Schindelin provided extensive help with the UI and\n> implementation of this command (but has not yet reviewed the code).\n>\n> Cc: Junio C Hamano <gitster@pobox.com>\n> Cc: Johannes Schindelin <johannes.schindelin@gmx.de>\n\nPlease drop these two lines.  They belong to e-mail headers.\n\n> Open questions:\n>\n>   1) Right now, this command is actually git-submodule-split.sh.  Should\n>      I include this code directly into git-submodule.sh, or move it\n>      to git-submodule--split.sh and hook it into git-submodule.sh?\n\nHow about in contrib/ somewhere?\n\n>   2) Should I implement a --force flag based on filter-branch?  Johannes\n>      Schindelin has suggested that it might be better to remove the\n>      --force flag from filter-branch and just rely on the reflog to keep\n>      backups.\n\nSounds sensible to me, but I do not have strong feeling about this either way.\n\n>   4) We're obviously going to need to support revision arguments other\n>      than --all (which is what we currently pass to filter-branch).  Should\n>      we default to the current branch only, or to --all?\n\nMatching what filter-branch defaults to would be the most natural,\nwouldn't it?\n\nI didn't look at the patch, though.\n"},{"id":"104588","messageId":"431341160902132117s1696c975mbf20dfbdc65a7df3@mail.gmail.com","threadId":"17763","inReplyTo":"7v3aeh3a84.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC/PATCHv2] git submodule split","fromName":"Eric Kidd","fromEmail":"git@randomhacks.net","sentAt":"2009-02-14T05:17:25Z","receivedAt":"2009-02-14T05:17:25Z","isPatch":false,"sender":{"key":"git@randomhacks.net","avatar":null},"body":"On Fri, Feb 13, 2009 at 11:37 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Eric Kidd <git@randomhacks.net> writes:\n>> ...\n>> If the submodule has moved around the source tree, specify one or more\n>> values for alternate_dir.  To specify the URL of the newly created\n>> repository (for use in .gitmodules), use the --url parameter.\n>\n> Unfortunately, I do not think we have designed fully (nor implemented at\n> all) behaviour to check out different points of history that has the same\n> submodule moved around in the superproject tree.\n>\n> There were several unconcluded discussions done in the past (and I admit I\n> participated in a few of them), but it may be hard to use the resulting\n> repository out of this tool.\n\nThank you for looking at this proposal!\n\nI think that the resulting repository is usable (though it could\ncertainly be better). In particular, the following commands will\nalways give you a working checkout:\n\n  git checkout any-version\n  git submodule update --init\n\nThe unit tests for git-submodule-split.sh actually walk through the\nentire history and run 'git submodule update --init' at each revision.\nThis works correctly because git-submodule-split creates the necessary\n.gitmodules entries for each revision, and includes the\nsubmodule.*.url value that you specify.\n\nUnfortunately, this means that whenever the submodule moves to a new\nlocation in the tree, 'git submodule --init' will actually have to\nclone it again. That's not a perfect situation, but it will work for\nreasonably small submodules.\n\n>>   1) Right now, this command is actually git-submodule-split.sh.  Should\n>>      I include this code directly into git-submodule.sh, or move it\n>>      to git-submodule--split.sh and hook it into git-submodule.sh?\n>\n> How about in contrib/ somewhere?\n\nSounds good to me! I'd like to include the unit tests and some\ndocumentation, if that's OK.\n\nI'll let you know when the patch has been reviewed, and submit it for\ninclusion in contrib.\n\n>>   2) Should I implement a --force flag based on filter-branch?  Johannes\n>>      Schindelin has suggested that it might be better to remove the\n>>      --force flag from filter-branch and just rely on the reflog to keep\n>>      backups.\n>\n> Sounds sensible to me, but I do not have strong feeling about this either way.\n\nI realized that there's a problem with removing  --force from\nfilter-branch: The reflog doesn't contain backups of the rewritten\ntags. So I'm afraid --force and the refs/original/ directory will need\nto remain for now. (Any thoughts, Johannes?)\n\n>>   4) We're obviously going to need to support revision arguments other\n>>      than --all (which is what we currently pass to filter-branch).  Should\n>>      we default to the current branch only, or to --all?\n>\n> Matching what filter-branch defaults to would be the most natural,\n> wouldn't it?\n\nI think so, although many (or most?) users will probably want to use '-- --all'.\n\nThank you very much for your suggestions!\n\nCheers,\nEric\n"},{"id":"104614","messageId":"8c5c35580902140103o3e5dd091qe2a18ca52b6fe44a@mail.gmail.com","threadId":"17763","inReplyTo":"431341160902132117s1696c975mbf20dfbdc65a7df3@mail.gmail.com","subject":"Re: [RFC/PATCHv2] git submodule split","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2009-02-14T09:03:31Z","receivedAt":"2009-02-14T09:03:31Z","isPatch":false,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"On Sat, Feb 14, 2009 at 06:17, Eric Kidd <git@randomhacks.net> wrote:\n> On Fri, Feb 13, 2009 at 11:37 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Eric Kidd <git@randomhacks.net> writes:\n>>> ...\n>>> If the submodule has moved around the source tree, specify one or more\n>>> values for alternate_dir.  To specify the URL of the newly created\n>>> repository (for use in .gitmodules), use the --url parameter.\n>>\n>> Unfortunately, I do not think we have designed fully (nor implemented at\n>> all) behaviour to check out different points of history that has the same\n>> submodule moved around in the superproject tree.\n>>\n>> There were several unconcluded discussions done in the past (and I admit I\n>> participated in a few of them), but it may be hard to use the resulting\n>> repository out of this tool.\n>\n> Thank you for looking at this proposal!\n>\n> I think that the resulting repository is usable (though it could\n> certainly be better). In particular, the following commands will\n> always give you a working checkout:\n>\n>  git checkout any-version\n>  git submodule update --init\n>\n> The unit tests for git-submodule-split.sh actually walk through the\n> entire history and run 'git submodule update --init' at each revision.\n> This works correctly because git-submodule-split creates the necessary\n> .gitmodules entries for each revision, and includes the\n> submodule.*.url value that you specify.\n>\n> Unfortunately, this means that whenever the submodule moves to a new\n> location in the tree, 'git submodule --init' will actually have to\n> clone it again. That's not a perfect situation, but it will work for\n> reasonably small submodules.\n\n<hand-waving>\nI didn't look at the patch, but if the submodule uses a single\nmodule-name while moving around, the re-cloning problem would by\nsolved if the submodule git-dir was stored inside the git-dir of the\ncontaining repository  (by using the git-file mechanism). Maybe I\nshould try to finally implement this...\n</hand-waving>\n\n--\nlarsh\n"},{"id":"104628","messageId":"alpine.DEB.1.00.0902141241270.10279@pacific.mpi-cbg.de","threadId":"17763","inReplyTo":"8c5c35580902140103o3e5dd091qe2a18ca52b6fe44a@mail.gmail.com","subject":"Re: [RFC/PATCHv2] git submodule split","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-14T11:44:53Z","receivedAt":"2009-02-14T11:44:53Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 14 Feb 2009, Lars Hjemli wrote:\n\n> On Sat, Feb 14, 2009 at 06:17, Eric Kidd <git@randomhacks.net> wrote:\n> > On Fri, Feb 13, 2009 at 11:37 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> >> Eric Kidd <git@randomhacks.net> writes:\n> >>> ...\n> >>> If the submodule has moved around the source tree, specify one or more\n> >>> values for alternate_dir.  To specify the URL of the newly created\n> >>> repository (for use in .gitmodules), use the --url parameter.\n> >>\n> >> Unfortunately, I do not think we have designed fully (nor implemented at\n> >> all) behaviour to check out different points of history that has the same\n> >> submodule moved around in the superproject tree.\n> >>\n> >> There were several unconcluded discussions done in the past (and I admit I\n> >> participated in a few of them), but it may be hard to use the resulting\n> >> repository out of this tool.\n> >\n> > Thank you for looking at this proposal!\n> >\n> > I think that the resulting repository is usable (though it could\n> > certainly be better). In particular, the following commands will\n> > always give you a working checkout:\n> >\n> >  git checkout any-version\n> >  git submodule update --init\n> >\n> > The unit tests for git-submodule-split.sh actually walk through the\n> > entire history and run 'git submodule update --init' at each revision.\n> > This works correctly because git-submodule-split creates the necessary\n> > .gitmodules entries for each revision, and includes the\n> > submodule.*.url value that you specify.\n> >\n> > Unfortunately, this means that whenever the submodule moves to a new\n> > location in the tree, 'git submodule --init' will actually have to\n> > clone it again. That's not a perfect situation, but it will work for\n> > reasonably small submodules.\n> \n> <hand-waving>\n> I didn't look at the patch, but if the submodule uses a single\n> module-name while moving around, the re-cloning problem would by\n> solved if the submodule git-dir was stored inside the git-dir of the\n> containing repository  (by using the git-file mechanism). Maybe I\n> should try to finally implement this...\n> </hand-waving>\n\nHow should that help with the _working directory_ of the submodule?  After \nall, _that_ is the part we are having with, as the untracked files in that \ndirectory _are_ part of the submodule.\n\nThe real kicker is that when we want to \"git submodule checkout\" the \n(moved) submodule, we no longer know where it was found last time (and \nwhere it still is).  We need a sane semantic for that (and I think it \ninvolves the addition of submodule.<name>.path to the superproject's \nconfig, something we do not do yet).\n\nCiao,\nDscho\n"},{"id":"104629","messageId":"alpine.DEB.1.00.0902141245080.10279@pacific.mpi-cbg.de","threadId":"17763","inReplyTo":"7v3aeh3a84.fsf@gitster.siamese.dyndns.org","subject":"Re: [RFC/PATCHv2] git submodule split","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-14T11:46:09Z","receivedAt":"2009-02-14T11:46:09Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 13 Feb 2009, Junio C Hamano wrote:\n\n> Eric Kidd <git@randomhacks.net> writes:\n> \n> >   1) Right now, this command is actually git-submodule-split.sh.  \n> >      Should I include this code directly into git-submodule.sh, or \n> >      move it to git-submodule--split.sh and hook it into \n> >      git-submodule.sh?\n> \n> How about in contrib/ somewhere?\n\nAs I said to Eric already, I would like this to be part of git-submodule \nproper, as I expect a lot of people needing it.\n\nCiao,\nDscho\n"},{"id":"104636","messageId":"431341160902140611x69a915e6lc3ee482f1ca66dc8@mail.gmail.com","threadId":"17763","inReplyTo":"alpine.DEB.1.00.0902141245080.10279@pacific.mpi-cbg.de","subject":"Re: [RFC/PATCHv2] git submodule split","fromName":"Eric Kidd","fromEmail":"git@randomhacks.net","sentAt":"2009-02-14T14:11:16Z","receivedAt":"2009-02-14T14:11:16Z","isPatch":false,"sender":{"key":"git@randomhacks.net","avatar":null},"body":"On Sat, Feb 14, 2009 at 6:46 AM, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n> As I said to Eric already, I would like this to be part of git-submodule\n> proper, as I expect a lot of people needing it.\n\nI'm happy to do whatever people want. :-) Even if this goes into\ncontrib/, I want to include everything a regular git command would\nhave: unit tests, a man page, portable sh code, etc. And I want to\nmake 'git-submodule-split' useful to as many people as possible.\n\nWhich brings me to a design question: Would 'git-submodule-split' be\nuseful to more people if it were actually two commands?\n\n1) git submodule split: Create the new submodule, update the working\ncopy, but do not change any history in the super-project. This would\nbe useful for existing projects that don't want to rewrite existing\ncommits, but which want to spin off a submodule.\n\n2) git submodule split --rewrite-history: Update the history of the\nproject to use the rewritten submodule. This would be most useful when\nmigrating repositories to git.\n\nI've already implemented (2), but frankly, it feels like a special\ncase of a larger command. It would be very easy to implement (1) and\nmake it the default.\n\nCheers,\nEric\n"},{"id":"104717","messageId":"alpine.DEB.1.00.0902150000140.10279@pacific.mpi-cbg.de","threadId":"17763","inReplyTo":"431341160902140611x69a915e6lc3ee482f1ca66dc8@mail.gmail.com","subject":"Re: [RFC/PATCHv2] git submodule split","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-14T23:01:28Z","receivedAt":"2009-02-14T23:01:28Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sat, 14 Feb 2009, Eric Kidd wrote:\n\n> On Sat, Feb 14, 2009 at 6:46 AM, Johannes Schindelin\n> <Johannes.Schindelin@gmx.de> wrote:\n> > As I said to Eric already, I would like this to be part of git-submodule\n> > proper, as I expect a lot of people needing it.\n> \n> I'm happy to do whatever people want. :-) Even if this goes into\n> contrib/, I want to include everything a regular git command would\n> have: unit tests, a man page, portable sh code, etc.\n\nThat is the problem.  IIRC we do not have a testing framework in contrib/.  \nIndeed, we would not catch breakages in contrib/ at all.\n\nCiao,\nDscho\n"},{"id":"104718","messageId":"bd6139dc0902141513k4316f43h90b652b71e28397a@mail.gmail.com","threadId":"17763","inReplyTo":"alpine.DEB.1.00.0902150000140.10279@pacific.mpi-cbg.de","subject":"Re: [RFC/PATCHv2] git submodule split","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-02-14T23:13:51Z","receivedAt":"2009-02-14T23:13:51Z","isPatch":false,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"On Sun, Feb 15, 2009 at 00:01, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n> That is the problem.  IIRC we do not have a testing framework in contrib/.\n> Indeed, we would not catch breakages in contrib/ at all.\n\nI recall a patch about getting 'make test' to work in /contrib?\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"105116","messageId":"20090217191748.6117@nanako3.lavabit.com","threadId":"17763","inReplyTo":"8c5c35580902140103o3e5dd091qe2a18ca52b6fe44a@mail.gmail.com","subject":"Re: [RFC/PATCHv2] git submodule split","fromName":"Nanako Shiraishi","fromEmail":"nanako3@lavabit.com","sentAt":"2009-02-17T10:17:48Z","receivedAt":"2009-02-17T10:17:48Z","isPatch":false,"sender":{"key":"nanako3@lavabit.com","avatar":"https://gravatar.com/avatar/3777b9e201c5883a62b1a6fdf7c53f2d712d1d80989146063ea861e33aad72a8?d=mp&s=160"},"body":"Quoting Lars Hjemli <hjemli@gmail.com>:\n\n> I didn't look at the patch, but if the submodule uses a single\n> module-name while moving around, the re-cloning problem would by\n> solved if the submodule git-dir was stored inside the git-dir of the\n> containing repository  (by using the git-file mechanism). Maybe I\n> should try to finally implement this...\n\nIs it similar to what was discussed earlier in the thread http://thread.gmane.org/gmane.comp.version-control.git/47466/focus=47621 (I asked gmane for \"submodule relocate\")?\n\nI think it is a good idea to resume your relocatable submodule directory design. Junio said he will keep 'next' open during the stabilization period before the release. I think he means that there is no need for you to be waiting.\n\nI noticed that Junio hasn't taken very big changes to git-submodule and I think it is firstly because he doesn't use submodules himself heavily as he said in the past. It is understandable if he feels uneasy to take large changes that can potentially affect its existing users if he hasn't developed enough first-hand experience with the part of the system himself.\n\nJunio doesn't get involved in git-gui discussion very much either, and I think the reason is the same (see http://gitster.livejournal.com/24080.html for example where he says he doesn't usually use GUI tools) but git-gui has Shawn who takes both initiative and responsibility in the area. git-submodule support would benefit from someobody like Shawn who takes an active role in improving it.\n\n-- \nNanako Shiraishi\nhttp://ivory.ap.teacup.com/nanako3/\n"},{"id":"105498","messageId":"8c5c35580902191123h4f1e56c7m3192bc1ffdf9fee6@mail.gmail.com","threadId":"17763","inReplyTo":"20090217191748.6117@nanako3.lavabit.com","subject":"Re: [RFC/PATCHv2] git submodule split","fromName":"Lars Hjemli","fromEmail":"hjemli@gmail.com","sentAt":"2009-02-19T19:23:08Z","receivedAt":"2009-02-19T19:23:08Z","isPatch":false,"sender":{"key":"hjemli@gmail.com","avatar":null},"body":"[* sorry for the late reply *]\n\nOn Tue, Feb 17, 2009 at 11:17, Nanako Shiraishi <nanako3@lavabit.com> wrote:\n> Quoting Lars Hjemli <hjemli@gmail.com>:\n>\n>> I didn't look at the patch, but if the submodule uses a single\n>> module-name while moving around, the re-cloning problem would by\n>> solved if the submodule git-dir was stored inside the git-dir of the\n>> containing repository  (by using the git-file mechanism). Maybe I\n>> should try to finally implement this...\n>\n> Is it similar to what was discussed earlier in the thread\n> http://thread.gmane.org/gmane.comp.version-control.git/47466/focus=47621\n> (I asked gmane for \"submodule relocate\")?\n\nWell, kind of. We ended up with a scheme similar to what Junio\ndescribed in the linked mail: every submodule in a repository is given\na canonical name by the .gitmodules file and this name is then linked\nwith a url in .git/config. The .gitmodules file also states at which\npath(s) this submodule is located. So we can keep track of which\nsubmodules we're interested in (and what urls to use for fetching\nobjects to those submodules) irrespective of the path used to check\nout the submodules.\n\nBut when we're switching between branches in which a submodule is\nchecked out at different paths, we currently loose track of both the\nold worktree and its gitdir. My gitfile proposal would salvage the\ngitdir but, as Dscho mentioned, uncommited+untracked data in the\nworktree would not be handled.\n\nSo I currently think it's better to make `git submodule init` update\n.git/config with information about the current submodule path (again,\nas Dscho mentioned). Then, after switching branches, `git submodule\n<some-verb>` could notice that the current path is different from the\none in .git/config and simply `mv oldpath newpath` before updating\n.git/config with the new path.\n\nBtw. this wouldn't work smoothly if a single submodule was checked out\nat multiple paths in the same revision, but I don't see why anyone\nwould want to do something like that...\n\n--\nlarsh\n"},{"id":"105528","messageId":"f73f7ab80902191504p2745d2c0m20a9762013fb4501@mail.gmail.com","threadId":"17763","inReplyTo":"8c5c35580902140103o3e5dd091qe2a18ca52b6fe44a@mail.gmail.com","subject":"Re: [RFC/PATCHv2] git submodule split","fromName":"Kyle Moffett","fromEmail":"kyle@moffetthome.net","sentAt":"2009-02-19T23:04:36Z","receivedAt":"2009-02-19T23:04:36Z","isPatch":false,"sender":{"key":"kyle@moffetthome.net","avatar":null},"body":"On Sat, Feb 14, 2009 at 4:03 AM, Lars Hjemli <hjemli@gmail.com> wrote:\n> On Sat, Feb 14, 2009 at 06:17, Eric Kidd <git@randomhacks.net> wrote:\n>> On Fri, Feb 13, 2009 at 11:37 PM, Junio C Hamano <gitster@pobox.com> wrote:\n>>> Eric Kidd <git@randomhacks.net> writes:\n>>>> ...\n>>>> If the submodule has moved around the source tree, specify one or more\n>>>> values for alternate_dir.  To specify the URL of the newly created\n>>>> repository (for use in .gitmodules), use the --url parameter.\n>>>\n>>> Unfortunately, I do not think we have designed fully (nor implemented at\n>>> all) behaviour to check out different points of history that has the same\n>>> submodule moved around in the superproject tree.\n>>>\n>>> There were several unconcluded discussions done in the past (and I admit I\n>>> participated in a few of them), but it may be hard to use the resulting\n>>> repository out of this tool.\n>>\n>> Thank you for looking at this proposal!\n>>\n>> I think that the resulting repository is usable (though it could\n>> certainly be better). In particular, the following commands will\n>> always give you a working checkout:\n>>\n>>  git checkout any-version\n>>  git submodule update --init\n>>\n>> The unit tests for git-submodule-split.sh actually walk through the\n>> entire history and run 'git submodule update --init' at each revision.\n>> This works correctly because git-submodule-split creates the necessary\n>> .gitmodules entries for each revision, and includes the\n>> submodule.*.url value that you specify.\n>>\n>> Unfortunately, this means that whenever the submodule moves to a new\n>> location in the tree, 'git submodule --init' will actually have to\n>> clone it again. That's not a perfect situation, but it will work for\n>> reasonably small submodules.\n>\n> <hand-waving>\n> I didn't look at the patch, but if the submodule uses a single\n> module-name while moving around, the re-cloning problem would by\n> solved if the submodule git-dir was stored inside the git-dir of the\n> containing repository  (by using the git-file mechanism). Maybe I\n> should try to finally implement this...\n> </hand-waving>\n\nWe use submodules at my workplace to keep track of a variety of\nclosely-related projects (branched from each other).  On account of\nsome deficiencies in the interface of the GIT we're using (including a\nfew that are still present), we have a bunch of custom scripts to\nclone and check out the whole mess, but it goes something like this:\n\nIn super/.git/config in a checkout:\n\n    [remote \"origin\"]\n        fetch = +refs/heads/*:refs/remotes/origin/*\n        push = +refs/heads/*:refs/heads/kmoffett-branches/*\n        fetch = +refs/projects/heads/*:refs/projects/remotes/origin/*\n        push = +refs/projects/heads/*:refs/projects/heads/kmoffett-branches/*\n\n    [submodule \"projects/FOO\"]\n        url = ./projects/FOO/.git\n\n\nIn super/.gitmodules:\n\n    [submodule \"projects/FOO\"]\n        path = projects/FOO\n        url = ./projects/FOO/.git\n\n\nIn sub/.git/config (IE: super/projects/FOO/.git/config)\n\n    [remote \"origin\"]\n        url = ../..\n        push = +refs/heads/*:refs/projects/heads/FOO/*\n        fetch = +refs/projects/heads/*:refs/remotes/parent/*\n        fetch = +refs/projects/remotes/*:refs/remotes/*\n\n    [remote \"parent\"]\n        ${same as remote.origin}\n\n\nIn sub/.git/objects/info/alternates (IE:\nsuper/projects/FOO/.git/objects/info/alternates)\n\n    ../../../../.git/objects\n\n\nIn this environment, basically *all* objects are kept in the\n\"superproject\".  When doing a local commit into a subproject, the new\nobjects are first stored there (is there any way to change that?), but\non the first \"git push\" in the subproject they will be pushed up to\nthe parent's objects directory and the next GC of the child project\nwill clean them up.  All of the child branches are stored in\n\"refs/projects\", so they don't show up by default in various \"git\nbranch\", etc, commands, but it's trivial to ensure they get pushed and\npulled appropriately.\n\nEssentially the \"superproject\" consists of our project-management\nenvironment, with the subprojects being each individual project, which\nmay be entirely independent.  There is a relatively tight feature\ncoupling between the per-project scripts and the version of the\nmanagement environment, so this works out relatively nicely for our\nuses.\n\nA clone by default will only get the superproject, if you want\nsubprojects you have to add the appropriate branch refs to the\n.git/config file (as seen in the above example).  This is handy if\nyou're only working on one of the particular projects.  Having them\nall as separate branches cloned from each other does make it very easy\nto diff/merge/cherry-pick between them, even though they are\neffectively independent.\n\nCheers,\nKyle Moffett\n"}]}