subtree: move out of contrib
Subsystems (2)
cover subtree: move out of contrib
I think at this point git-subtree is widely used enough to move out of contrib/, maybe others disagree, but patches are always better for discussion that patch-less ML posts.
Ævar Arnfjörð Bjarmason (4):
git-subtree: move from contrib/subtree/
subtree: remove support for git version <1.7
subtree: fix a test failure under GETTEXT_POISON
i18n: translate the git-subtree command
.gitignore | 1 +
Documentation/git-submodule.txt | 2 +-
.../subtree => Documentation}/git-subtree.txt | 3 +
Makefile | 1 +
contrib/subtree/.gitignore | 7 -
contrib/subtree/COPYING | 339 ------------------
contrib/subtree/INSTALL | 28 --
contrib/subtree/Makefile | 97 -----
contrib/subtree/README | 8 -
contrib/subtree/t/Makefile | 86 -----
contrib/subtree/todo | 48 ---
.../subtree/git-subtree.sh => git-subtree.sh | 109 +++---
{contrib/subtree/t => t}/t7900-subtree.sh | 21 +-
13 files changed, 78 insertions(+), 672 deletions(-)
rename {contrib/subtree => Documentation}/git-subtree.txt (99%)
delete mode 100644 contrib/subtree/.gitignore
delete mode 100644 contrib/subtree/COPYING
delete mode 100644 contrib/subtree/INSTALL
delete mode 100644 contrib/subtree/Makefile
delete mode 100644 contrib/subtree/README
delete mode 100644 contrib/subtree/t/Makefile
delete mode 100644 contrib/subtree/todo
rename contrib/subtree/git-subtree.sh => git-subtree.sh (84%)
rename {contrib/subtree/t => t}/t7900-subtree.sh (99%)Signature · 1 line
2.17.0.290.gded63e768a
PATCH 1/4 git-subtree: move from contrib/subtree/
Change the git-subtree command from living in contrib to being a "real" git command.
I think it's useful enough that it should be shipped by default, and unlike git-submodule doesn't need any changes to git's object format. It's just a helper to do things you can do manually already with plumbing tools (but that would be much more tedious).
It'll also help to avoid the confusion noted in
https://public-inbox.org/git/alpine.LFD.2.21.1802070547040.5530@android-a172fe96dd584b41/
where users know git-subtree exists, but can't find its documentation (or it isn't installed).
This change removes config/subtree's copy of COPYING because it's redundant to the one in the root of the tree. The contrib/subtree/todo file is being removed because we don't usually store TODOs in-tree (and this'll be available in the history), the rest like the .gitignore, Makefile etc. are all redundant to things we have in-tree.
---
.gitignore | 1 +
Documentation/git-submodule.txt | 2 +-
.../subtree => Documentation}/git-subtree.txt | 3 +
Makefile | 1 +
contrib/subtree/.gitignore | 7 -
contrib/subtree/COPYING | 339 ------------------
contrib/subtree/INSTALL | 28 --
contrib/subtree/Makefile | 97 -----
contrib/subtree/README | 8 -
contrib/subtree/t/Makefile | 86 -----
contrib/subtree/todo | 48 ---
.../subtree/git-subtree.sh => git-subtree.sh | 0
{contrib/subtree/t => t}/t7900-subtree.sh | 5 +-
13 files changed, 7 insertions(+), 618 deletions(-)
rename {contrib/subtree => Documentation}/git-subtree.txt (99%)
delete mode 100644 contrib/subtree/.gitignore
delete mode 100644 contrib/subtree/COPYING
delete mode 100644 contrib/subtree/INSTALL
delete mode 100644 contrib/subtree/Makefile
delete mode 100644 contrib/subtree/README
delete mode 100644 contrib/subtree/t/Makefile
delete mode 100644 contrib/subtree/todo
rename contrib/subtree/git-subtree.sh => git-subtree.sh (100%)
rename {contrib/subtree/t => t}/t7900-subtree.sh (99%).gitignore +1 -0
@@ -155,6 +155,7 @@ /git-status /git-stripspace /git-submodule +/git-subtree /git-submodule--helper /git-svn /git-symbolic-ref
Documentation/git-submodule.txt +1 -1
@@ -402,7 +402,7 @@ for details. SEE ALSO -------- -linkgit:gitsubmodules[7], linkgit:gitmodules[5]. +linkgit:gitsubmodules[7], linkgit:gitmodules[5], linkgit:git-subtree[1]. GIT ---
Documentation/git-subtree.txt renamed from contrib/subtree/git-subtree.txt +3 -0
@@ -345,6 +345,9 @@ AUTHOR ------ Written by Avery Pennarun <[email protected]> +SEE ALSO +-------- +linkgit:git-submodule[1]. GIT ---
Makefile +1 -0
@@ -576,6 +576,7 @@ SCRIPT_SH += git-remote-testgit.sh SCRIPT_SH += git-request-pull.sh SCRIPT_SH += git-stash.sh SCRIPT_SH += git-submodule.sh +SCRIPT_SH += git-subtree.sh SCRIPT_SH += git-web--browse.sh SCRIPT_LIB += git-mergetool--lib
contrib/subtree/.gitignore deleted +0 -7
@@ -1,7 +0,0 @@ -*~ -git-subtree -git-subtree.1 -git-subtree.html -git-subtree.xml -mainline -subproj
contrib/subtree/COPYING deleted +0 -339
339 lines not on this page · raw message
contrib/subtree/INSTALL deleted +0 -28
@@ -1,28 +0,0 @@ -HOW TO INSTALL git-subtree -========================== - -First, build from the top source directory. - -Then, in contrib/subtree, run: - - make - make install - make install-doc - -If you used configure to do the main build the git-subtree build will -pick up those settings. If not, you will likely have to provide a -value for prefix: - - make prefix=<some dir> - make prefix=<some dir> install - make prefix=<some dir> install-doc - -To run tests first copy git-subtree to the main build area so the -newly-built git can find it: - - cp git-subtree ../.. - -Then: - - make test -
contrib/subtree/Makefile deleted +0 -97
97 lines not on this page · raw message
contrib/subtree/README deleted +0 -8
@@ -1,8 +0,0 @@ - -Please read git-subtree.txt for documentation. - -Please don't contact me using github mail; it's slow, ugly, and worst of -all, redundant. Email me instead at [email protected] and I'll be happy to -help. - -Avery
contrib/subtree/t/Makefile deleted +0 -86
86 lines not on this page · raw message
contrib/subtree/todo deleted +0 -48
48 lines not on this page · raw message
git-subtree.sh renamed from contrib/subtree/git-subtree.sh +0 -0
t/t7900-subtree.sh renamed from contrib/subtree/t/t7900-subtree.sh +1 -4
@@ -9,10 +9,7 @@ This test verifies the basic operation of the add, pull, merge and split subcommands of git subtree. ' -TEST_DIRECTORY=$(pwd)/../../../t -export TEST_DIRECTORY - -. ../../../t/test-lib.sh +. ./test-lib.sh subtree_test_create_repo() {
Signature · 1 line
2.17.0.290.gded63e768a
PATCH 2/4 subtree: remove support for git version <1.7
In reply to Ævar Arnfjörð BjarmasonNow that git-subtree is in-tree there's no reason to be supporting older git Versions. This reverts & amends 448e71e263 ("Use 'git merge -Xsubtree' when git version >= 1.7.0.", 2010-05-07).
--- git-subtree.sh | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-)
git-subtree.sh +4 -15
@@ -810,23 +810,12 @@ cmd_merge () { rev="$new" fi - version=$(git version) - if test "$version" \< "git version 1.7" + if test -n "$message" then - if test -n "$message" - then - git merge -s subtree --message="$message" "$rev" - else - git merge -s subtree "$rev" - fi + git merge -Xsubtree="$prefix" \ + --message="$message" "$rev" else - if test -n "$message" - then - git merge -Xsubtree="$prefix" \ - --message="$message" "$rev" - else - git merge -Xsubtree="$prefix" $rev - fi + git merge -Xsubtree="$prefix" $rev fi }
Signature · 1 line
2.17.0.290.gded63e768a
PATCH 3/4 subtree: fix a test failure under GETTEXT_POISON
In reply to Ævar Arnfjörð Bjarmason--- t/t7900-subtree.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
t/t7900-subtree.sh +11 -1
@@ -38,6 +38,16 @@ check_equal() fi } +check_equal_i18n() +{ + if test_have_prereq C_LOCALE_OUTPUT + then + check_equal "$@" + else + return 0 + fi +} + undo() { git reset --hard HEAD~
@@ -250,7 +260,7 @@ test_expect_success 'merge the added subproj again, should do nothing' ' # this shouldn not actually do anything, since FETCH_HEAD # is already a parent result=$(git merge -s ours -m "merge -s -ours" FETCH_HEAD) && - check_equal "${result}" "Already up to date." + check_equal_i18n "${result}" "Already up to date." ) '
Signature · 1 line
2.17.0.290.gded63e768a
PATCH 4/4 i18n: translate the git-subtree command
In reply to Ævar Arnfjörð BjarmasonOne of the advantages of having git-subtree out of contrib/ is being able to treat it as a first-class citizen when it comes to translations.
Mark those messages that make sense to translate for translation, and add a comment to the ones that shouldn't be translated. This has been tested under GIT_GETTEXT_POISON=1.
--- git-subtree.sh | 90 +++++++++++++++++++++++++++------------------- t/t7900-subtree.sh | 4 +-- 2 files changed, 56 insertions(+), 38 deletions(-)
git-subtree.sh +54 -36
@@ -141,7 +141,7 @@ do break ;; *) - die "Unexpected option: $opt" + die "$(eval_gettext "Unexpected option: \$opt")" ;; esac done
@@ -157,23 +157,23 @@ split|push) default="--default HEAD" ;; *) - die "Unknown command '$command'" + die "$(eval_gettext "Unknown command '\$command'")" ;; esac if test -z "$prefix" then - die "You must provide the --prefix option." + die "$(gettext "You must provide the --prefix option.")" fi case "$command" in add) test -e "$prefix" && - die "prefix '$prefix' already exists." + die "$(eval_gettext "prefix '\$prefix' already exists.")" ;; *) test -e "$prefix" || - die "'$prefix' does not exist; use 'git subtree add'" + die "$(eval_gettext "'\$prefix' does not exist; use 'git subtree add'")" ;; esac
@@ -187,7 +187,7 @@ then dirs=$(git rev-parse --no-revs --no-flags "$@") || exit $? if test -n "$dirs" then - die "Error: Use --prefix instead of bare filenames." + die "$(gettext "Error: Use --prefix instead of bare filenames.")" fi fi
@@ -201,12 +201,12 @@ debug cache_setup () { cachedir="$GIT_DIR/subtree-cache/$$" rm -rf "$cachedir" || - die "Can't delete old cachedir: $cachedir" + die "$(eval_gettext "Can't delete old cachedir: \$cachedir")" mkdir -p "$cachedir" || - die "Can't create new cachedir: $cachedir" + die "$(eval_gettext "Can't create new cachedir: \$cachedir")" mkdir -p "$cachedir/notree" || - die "Can't create new cachedir: $cachedir/notree" - debug "Using cachedir: $cachedir" >&2 + die "$(eval_gettext "Can't create new cachedir: \$cachedir/notree")" + debug "$(eval_gettext "Using cachedir: \$cachedir")" >&2 } cache_get () {
@@ -252,7 +252,7 @@ cache_set () { test "$oldrev" != "latest_new" && test -e "$cachedir/$oldrev" then - die "cache for $oldrev already exists!" + die "$(eval_gettext "cache for \$oldrev already exists!")" fi echo "$newrev" >"$cachedir/$oldrev" }
@@ -311,7 +311,7 @@ find_latest_squash () { ;; git-subtree-split:) sub="$(git rev-parse "$b^0")" || - die "could not rev-parse split hash $b from commit $sq" + die "$(eval_gettext "could not rev-parse split hash \$b from commit \$sq")" ;; END) if test -n "$sub"
@@ -353,7 +353,7 @@ find_existing_splits () { ;; git-subtree-split:) sub="$(git rev-parse "$b^0")" || - die "could not rev-parse split hash $b from commit $sq" + die "$(eval_gettext "could not rev-parse split hash \$b from commit \$sq")" ;; END) debug " Main is: '$main'"
@@ -401,7 +401,10 @@ copy_commit () { cat ) | git commit-tree "$2" $3 # reads the rest of stdin - ) || die "Can't copy commit $1" + ) || { + commit="$1" + die "$(eval_gettext "Can't copy commit \$commit")" + } } add_msg () {
@@ -412,6 +415,7 @@ add_msg () { then commit_message="$message" else + # i18n: This message must not be translated! commit_message="Add '$dir/' from commit '$latest_new'" fi cat <<-EOF
@@ -428,6 +432,7 @@ add_squashed_msg () { then echo "$message" else + # i18n: This message must not be translated! echo "Merge commit '$1' as '$2'" fi }
@@ -440,6 +445,7 @@ rejoin_msg () { then commit_message="$message" else + # i18n: This message must not be translated! commit_message="Split '$dir/' into commit '$latest_new'" fi cat <<-EOF
@@ -460,12 +466,12 @@ squash_msg () { if test -n "$oldsub" then oldsub_short=$(git rev-parse --short "$oldsub") - echo "Squashed '$dir/' changes from $oldsub_short..$newsub_short" + echo "$(eval_gettext "Squashed '\$dir/' changes from \$oldsub_short..\$newsub_short")" echo git log --no-show-signature --pretty=tformat:'%h %s' "$oldsub..$newsub" git log --no-show-signature --pretty=tformat:'REVERT: %h %s' "$newsub..$oldsub" else - echo "Squashed '$dir/' content from commit $newsub_short" + echo "$(eval_gettext "Squashed '\$dir/' content from commit \$newsub_short")" fi echo
@@ -585,31 +591,35 @@ copy_or_skip () { ensure_clean () { if ! git diff-index HEAD --exit-code --quiet 2>&1 then - die "Working tree has modifications. Cannot add." + die "$(gettext "Working tree has modifications. Cannot add.")" fi if ! git diff-index --cached HEAD --exit-code --quiet 2>&1 then - die "Index has modifications. Cannot add." + die "$(gettext "Index has modifications. Cannot add.")" fi } ensure_valid_ref_format () { - git check-ref-format "refs/heads/$1" || - die "'$1' does not look like a ref" + git check-ref-format "refs/heads/$1" || { + reference="$1" + die "$(eval_gettext "'\$reference' does not look like a ref")" + } } cmd_add () { if test -e "$dir" then - die "'$dir' already exists. Cannot add." + die "$(eval_gettext "'\$dir' already exists. Cannot add.")" fi ensure_clean if test $# -eq 1 then - git rev-parse -q --verify "$1^{commit}" >/dev/null || - die "'$1' does not refer to a commit" + git rev-parse -q --verify "$1^{commit}" >/dev/null || { + reference="$1" + die "$(eval_gettext "'\$reference' does not refer to a commit")" + } cmd_add_commit "$@"
@@ -625,7 +635,7 @@ cmd_add () { cmd_add_repository "$@" else say "error: parameters were '$@'" - die "Provide either a commit or a repository and commit." + die "$(gettext "Provide either a commit or a repository and commit.")" fi }
@@ -669,7 +679,7 @@ cmd_add_commit () { fi git reset "$commit" || exit $? - say "Added dir '$dir'" + say "$(eval_gettext "Added dir '\$dir'")" } cmd_split () {
@@ -747,7 +757,7 @@ cmd_split () { latest_new=$(cache_get latest_new) if test -z "$latest_new" then - die "No new revisions were found" + die "$(gettext "No new revisions were found")" fi if test -n "$rejoin"
@@ -765,15 +775,23 @@ cmd_split () { then if ! rev_is_descendant_of_branch "$latest_new" "$branch" then - die "Branch '$branch' is not an ancestor of commit '$latest_new'." + die "$(eval_gettext "Branch '\$branch' is not an ancestor of commit '\$latest_new'.")" fi - action='Updated' + action='updated' else - action='Created' + action='created' fi git update-ref -m 'subtree split' \ "refs/heads/$branch" "$latest_new" || exit $? - say "$action branch '$branch'" + if test $action = 'created' + then + say "$(eval_gettext "Created branch '\$branch'")" + elif test $action = 'updated' + then + say "$(eval_gettext "Updated branch '\$branch'")" + else + die "BUG: Should have updated the created/updated if/else!" + fi fi echo "$latest_new" exit 0
@@ -786,7 +804,7 @@ cmd_merge () { set -- $revs if test $# -ne 1 then - die "You must provide exactly one revision. Got: '$revs'" + die "$(eval_gettext "You must provide exactly one revision. Got: '\$revs'")" fi rev="$1"
@@ -795,14 +813,14 @@ cmd_merge () { first_split="$(find_latest_squash "$dir")" if test -z "$first_split" then - die "Can't squash-merge: '$dir' was never added." + die "$(eval_gettext "Can't squash-merge: '\$dir' was never added.")" fi set $first_split old=$1 sub=$2 if test "$sub" = "$rev" then - say "Subtree is already at commit $rev." + say "$(eval_gettext "Subtree is already at commit \$rev.")" exit 0 fi new=$(new_squash_commit "$old" "$sub" "$rev") || exit $?
@@ -822,7 +840,7 @@ cmd_merge () { cmd_pull () { if test $# -ne 2 then - die "You must provide <repository> <ref>" + die "$(gettext "You must provide <repository> <ref>")" fi ensure_clean ensure_valid_ref_format "$2"
@@ -835,7 +853,7 @@ cmd_pull () { cmd_push () { if test $# -ne 2 then - die "You must provide <repository> <ref>" + die "$(gettext "You must provide <repository> <ref>")" fi ensure_valid_ref_format "$2" if test -e "$dir"
@@ -846,7 +864,7 @@ cmd_push () { localrev=$(git subtree split --prefix="$prefix") || die git push "$repository" "$localrev":"refs/heads/$refspec" else - die "'$dir' must already exist. Try 'git subtree add'." + die "$(eval_gettext "'\$dir' must already exist. Try 'git subtree add'.")" fi }
t/t7900-subtree.sh +2 -2
@@ -304,7 +304,7 @@ test_expect_success 'split requires option --prefix' ' test_debug "cat expected" && test_debug "printf '"actual: "'" && test_debug "cat actual" && - test_cmp expected actual + test_i18ncmp expected actual ) '
@@ -324,7 +324,7 @@ test_expect_success 'split requires path given by option --prefix must exist' ' test_debug "cat expected" && test_debug "printf '"actual: "'" && test_debug "cat actual" && - test_cmp expected actual + test_i18ncmp expected actual ) '
Signature · 1 line
2.17.0.290.gded63e768a
From: "Ævar Arnfjörð Bjarmason" <[email protected]>
Quoted 4 lines
I think at this point git-subtree is widely used enough to move out of contrib/, maybe others disagree, but patches are always better for discussion that patch-less ML posts.
Assuming this lands in Git, then there will also need to be a simple follow on into Duy's series that is updating the command-list.txt (Message-Id: <[email protected]>). Duy's series also does the completions thing IIUC;-). --
Philip
Quoted 35 lines
Ævar Arnfjörð Bjarmason (4):
git-subtree: move from contrib/subtree/
subtree: remove support for git version <1.7
subtree: fix a test failure underGETTEXT_POISON
i18n: translate the git-subtree command.gitignore | 1 + Documentation/git-submodule.txt | 2 +- .../subtree => Documentation}/git-subtree.txt | 3 + Makefile | 1 + contrib/subtree/.gitignore | 7 - contrib/subtree/COPYING | 339 ------------------ contrib/subtree/INSTALL | 28 -- contrib/subtree/Makefile | 97 ----- contrib/subtree/README | 8 - contrib/subtree/t/Makefile | 86 ----- contrib/subtree/todo | 48 --- .../subtree/git-subtree.sh => git-subtree.sh | 109 +++--- {contrib/subtree/t => t}/t7900-subtree.sh | 21 +- 13 files changed, 78 insertions(+), 672 deletions(-)rename {contrib/subtree =>
Documentation}/git-subtree.txt(99%) delete mode 100644 contrib/subtree/.gitignore
delete mode 100644 contrib/subtree/COPYING
delete mode 100644 contrib/subtree/INSTALL
delete mode 100644 contrib/subtree/Makefile
delete mode 100644 contrib/subtree/README
delete mode 100644 contrib/subtree/t/Makefile
delete mode 100644 contrib/subtree/todo
renamecontrib/subtree/git-subtree.sh=>git-subtree.sh(84%) rename {contrib/subtree/t =>t}/t7900-subtree.sh(99%)Signature · 1 line
2.17.0.290.gded63e768a
Quoted 3 lines · Ævar Arnfjörð Bjarmason
I think at this point git-subtree is widely used enough to move out of contrib/, maybe others disagree, but patches are always better for discussion that patch-less ML posts.
I really was hoping git-subtree would be completely obsoleted by git-submodule by now, but... it hasn't been, so... no objections on this end.
The gerrit team (eg. Stefan Beller) has been doing some really great stuff to make submodules more usable by helping with relative submodule links and by auto-updating links in supermodules at the right times. Unfortunately doing that requires help from the server side, which kind of messes up decentralization and so doesn't solve the problem in the general case.
I really wish there were a good answer, but I don't know what it is. I do know that lots of people seem to at least be happy using git-subtree, and would be even happier if it were installed automatically with git.
Have fun,
Avery
Quoted 9 lines · Avery Pennarun
Quoted 3 lines · Ævar Arnfjörð Bjarmason
I think at this point git-subtree is widely used enough to move out of contrib/, maybe others disagree, but patches are always better for discussion that patch-less ML posts.
I really was hoping git-subtree would be completely obsoleted by git-submodule by now, but... it hasn't been, so... no objections on this end.
No objections from me either.
Submodules seem to serve a slightly different purpose, though?
With Subtrees the superproject always contains all the code, even when you squash the subtree histroy when merging it in. In the submodule world, you may not have access to one of the submodules.
Submodules do not need to produce a synthetic project history when splitting off again, as the history is genuine. This allows for easier work with upstream.
Subtrees present you the whole history by default and the user needs to be explicit about not wanting to see history from the subtree, which is the opposite of submodules (though this may be planned in the future to switch).
Quoted 6 lines
The gerrit team (eg. Stefan Beller) has been doing some really great stuff to make submodules more usable by helping with relative submodule links and by auto-updating links in supermodules at the right times. Unfortunately doing that requires help from the server side, which kind of messes up decentralization and so doesn't solve the problem in the general case.
Conceptually Gerrit is doing
while true:
git submodule update --remote
if worktree is dirty:
git commit "update the submodules"
just that Gerrit doesn't poll but does it event based.
Quoted 4 lines
I really wish there were a good answer, but I don't know what it is. I do know that lots of people seem to at least be happy using git-subtree, and would be even happier if it were installed automatically with git.
https://trends.google.com/trends/explore?date=all&q=git%20subtree,git%20submodule
Not sure what to make of this data.
Quoted 4 lines · Stefan Beller
On Mon, Apr 30, 2018 at 1:45 PM, Avery Pennarun <[email protected]> wrote:
No objections from me either.Submodules seem to serve a slightly different purpose, though?
I think the purpose is actually the same - it's just the tradeoffs that are difference. Both sets of tradeoffs kind of suck.
Quoted 4 lines
With Subtrees the superproject always contains all the code, even when you squash the subtree histroy when merging it in. In the submodule world, you may not have access to one of the submodules.
Right. Personally I think it's a disadvantage of subtree that it always contains all the code (what if some people don't want the code for a particular build variant?). However, it's a huge pain that submodules *don't* contain all the code (what if I'm not online right now, or the site supposedly containing the code goes offline, or I want to make my own fork?).
For the best of both worlds, I've often thought that a good balance would be to use the same data structure that submodule uses, but to store all the code in a single git repo under different refs, which we might or might not download (or might or might not have different ACLs) under different circumstances. However, when some projects get really huge (lots of very big submodule dependencies), then repacking one-big-repo starts becoming unwieldy; in that situation git-subtree also fails completely.
Quoted 3 lines
Submodules do not need to produce a synthetic project history when splitting off again, as the history is genuine. This allows for easier work with upstream.
Splitting for easier work upstream is great, and there really ought to be an official version of 'git subtree split', which is good for all sorts of purposes.
However, I suspect almost all uses of the split feature are a) splitting a subtree that you previously merged in, or b) splitting a subtree into a separate project that you want to maintain separately from now on. Repeated splits in case (a) are only necessary because you're not using submodules, or in case (b) are only necessary because you didn't *switch* to submodules when it finally came time to split the projects. (In both cases you probably didn't switch to submodules because you didn't like one of its tradeoffs, especially the need to track multiple repos when you fork.)
Quoted 4 lines
Subtrees present you the whole history by default and the user needs to be explicit about not wanting to see history from the subtree, which is the opposite of submodules (though this may be planned in the future to switch).
It turns out that AFAIK, almost everyone prefers 'git subtree --squash', which squashes into a single commit each time you merge, much like git submodule does. I doubt people would cry too much if the full-history feature went away.
There's one exception, which is doing a one-time permanent merge of two projects into one. That's a nice feature, but is probably used extremely rarely. More often people get into a merge-split-merge-split cycle that would be better served by a slightly improved git-submodule.
Quoted 7 lines
Quoted 6 lines
The gerrit team (eg. Stefan Beller) has been doing some really great stuff to make submodules more usable by helping with relative submodule links and by auto-updating links in supermodules at the right times. Unfortunately doing that requires help from the server side, which kind of messes up decentralization and so doesn't solve the problem in the general case.
Quoted 8 lines
Conceptually Gerrit is doing
while true:
git submodule update --remote
if worktree is dirty:
git commit "update the submodules"just that Gerrit doesn't poll but does it event based.
...and it's super handy :) The problem is it's fundamentally
centralized: because gerrit can serialize merges into the submodule, it also knows exactly how to update the link in the supermodule. If there was wild branching and merging (as there often is in git) and you had to resolve conflicts between two submodules, I don't think it would be obvious at all how to do it automatically when pushing a submodule. (This also works quite badly with git subtree --squash.)
Quoted 8 lines
Quoted 4 lines
I really wish there were a good answer, but I don't know what it is. I do know that lots of people seem to at least be happy using git-subtree, and would be even happier if it were installed automatically with git.
https://trends.google.com/trends/explore?date=all&q=git%20subtree,git%20submodule
Not sure what to make of this data.
Clearly people need a lot more help when using submodules than when using subtree :)
Have fun,
Avery
Quoted 5 lines · Avery Pennarun
For the best of both worlds, I've often thought that a good balance would be to use the same data structure that submodule uses, but to store all the code in a single git repo under different refs, which we might or might not download (or might or might not have different ACLs) under different circumstances.
There has been some experimentation with having a simpler ref surface on the submodule side,
https://public-inbox.org/git/[email protected]/
The way you describe the future of submodules, all we'd have to do is to teach git-clone how to select the the "interesting" refs for your use case. Any other command would assume all submodule data to be in the main repository.
The difference to Jonathans proposal linked above, would be the object store to be in the main repo and the refs to be prefixed per submodule instead of "shadowed".
Quoted 4 lines
However, when some projects get
really huge (lots of very big submodule dependencies), then repacking one-big-repo starts becoming unwieldy; in that situation git-subtree also fails completely.
Yes, but that is a general scaling problem of Git that could be tackled, e.g. repack into multiple packs serially instead of putting everything into one pack.
Quoted 8 lines
Quoted 3 lines
Submodules do not need to produce a synthetic project history when splitting off again, as the history is genuine. This allows for easier work with upstream.
Splitting for easier work upstream is great, and there really ought to be an official version of 'git subtree split', which is good for all sorts of purposes.
Quoted 9 lines
However, I suspect almost all uses of the split feature are a) splitting a subtree that you previously merged in, or b) splitting a subtree into a separate project that you want to maintain separately from now on. Repeated splits in case (a) are only necessary because you're not using submodules, or in case (b) are only necessary because you didn't *switch* to submodules when it finally came time to split the projects. (In both cases you probably didn't switch to submodules because you didn't like one of its tradeoffs, especially the need to track multiple repos when you fork.)
That makes sense.
Quoted 6 lines
There's one exception, which is doing a one-time permanent merge of two projects into one. That's a nice feature, but is probably used extremely rarely. More often people get into a merge-split-merge-split cycle that would be better served by a slightly improved git-submodule.
This rare use case is how git-subtree came into existence in gits contrib directory AFAICT,
https://kernel.googlesource.com/pub/scm/git/git/+/634392b26275fe5436c0ea131bc89b46476aa4ae
which is interesting to view in git-show, but I think defaults could be tweaked there, as it currently shows me mostly a license file.
Quoted 9 lines
Quoted 8 lines
Conceptually Gerrit is doing
while true:
git submodule update --remote
if worktree is dirty:
git commit "update the submodules"just that Gerrit doesn't poll but does it event based.
Quoted 7 lines
...and it's super handy :) The problem is it's fundamentally
centralized: because gerrit can serialize merges into the submodule, it also knows exactly how to update the link in the supermodule. If there was wild branching and merging (as there often is in git) and you had to resolve conflicts between two submodules, I don't think it would be obvious at all how to do it automatically when pushing a submodule. (This also works quite badly with git subtree --squash.)
With the poll based solution I don't think you'd run into many more problems than you would with Gerrits solution.
In a nearby thread, we were just discussing the submodule merging strategies,
https://public-inbox.org/git/[email protected]/
which might seem confusing, but the implementation is actually easy as we just fastforward-only in submodules.
Quoted 7 lines
Quoted 4 lines
https://trends.google.com/trends/explore?date=all&q=git%20subtree,git%20submodule
Not sure what to make of this data.
Clearly people need a lot more help when using submodules than when using subtree :)
That could be true. :)
Thanks,
Stefan
Quoted 4 lines · Avery Pennarun
On Mon, Apr 30, 2018 at 5:38 PM, Stefan Beller <[email protected]> wrote:
There's one exception, which is doing a one-time permanent merge of two projects into one. That's a nice feature, but is probably used extremely rarely.
FWIW this is the only thing I've used it for. I do this occasionally and used to do this manually with format-patch + "perl -pe" before or similar when I needed to merge some repositories together, and then some other times I was less stupid and manually started doing something similar to what subtree is doing with a "move everything" commit just before the merge of the two histories.
Quoted 6 lines
Quoted 3 lines
https://trends.google.com/trends/explore?date=all&q=git%20subtree,git%20submodule
Not sure what to make of this data.
Clearly people need a lot more help when using submodules than when using subtree :)
Pretty clear it's garbage data, unless we're to believe that the relative interest of submodules in the US, Germany and Sweden is 51, 64 & 84, but 75, 100 and 0 for subtree.
Quoted 3 lines · Ævar Arnfjörð Bjarmason
Pretty clear it's garbage data, unless we're to believe that the relative interest of submodules in the US, Germany and Sweden is 51, 64 & 84, but 75, 100 and 0 for subtree.
Oh yeah, Swedish people hate git-subtree. Nobody knows why.
Avery
Quoted 3 lines · Ævar Arnfjörð Bjarmason
I think at this point git-subtree is widely used enough to move out of contrib/, maybe others disagree, but patches are always better for discussion that patch-less ML posts.
After narrow/partial clone becomes real, it should be "easy" to implement some sort of narrow checkout that would achieve the same thing. But it took me forever with all other stuff to get back to this.
If we remove it from contrib and there are people willing to update/maintain it, should it be a separate repository then? The willing people will have much more freedom to update it. And I don't have to answer the questions about who will maintain this thing in git.git. I don't like the idea of adding new (official) shell-based commands either to be honest.
Signature · 1 line
Duy
Hi Ævar,
Quoted 3 lines · Ævar Arnfjörð Bjarmason
I think at this point git-subtree is widely used enough to move out of contrib/, maybe others disagree, but patches are always better for discussion that patch-less ML posts.
Sure, it is used widely enough.
However, it flies in the face of so many GSoC efforts to introduce yet another one of those poorly portable Unix shell scripts, as central part of Git's code base.
The script itself does look quite straight-forward to port to a builtin, so why not give it a try?
If you are completely opposed to porting it to C, I will be completely opposed to moving it out of contrib/.
If you need help with porting it, please come up with a task plan and I can jump in, to help (but please do collaborate with me on this one, don't leave all of the hard work to me).
Ciao,
Dscho
Quoted 8 lines · Johannes Schindelin
Hi Ævar,
Quoted 3 lines · Ævar Arnfjörð Bjarmason
I think at this point git-subtree is widely used enough to move out of contrib/, maybe others disagree, but patches are always better for discussion that patch-less ML posts.
Quoted 8 lines
Sure, it is used widely enough.
However, it flies in the face of so many GSoC efforts to introduce yet another one of those poorly portable Unix shell scripts, as central part of Git's code base.
The script itself does look quite straight-forward to port to a builtin, so why not give it a try?
That's a valid point. I think it makes sense to leave that aside for now, maybe the consensus is that subtree is fine in every way except we'd like to have a policy not to introduce new shellscript built-ins.
Let's first just assume it's in C already and look at it in terms of its functionality, to figure out if it's worth even getting to that point.
Quoted 2 lines
If you are completely opposed to porting it to C, I will be completely opposed to moving it out of contrib/.
This series shows that we should split the concern about whether something lives in contrib/ from whether it's built/installed by default.
No matter if we decide that subtree should be a blessed default command it makes sense to move it out of contrib, purely because as can be seen from this series it'll replace >100 lines of hacks with 1 line in our main Makefile.
We can then just e.g. add a flag to guard for it,
e.g. CONTRIB_SUBTREE=YesPlease.
But that's just an internal implementation detail of how we manage code sitting in git.git.