From 0e2b0ed08cfc2c45ce1f5abae6cfc2f20bb4c4b0 Mon Sep 17 00:00:00 2001 From: Alexey Shamrin Date: Tue, 16 Feb 2021 18:58:02 +0200 Subject: [PATCH 1/4] add git-fix-modules.sh --- scripts/git-fix-modules.sh | 93 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100755 scripts/git-fix-modules.sh diff --git a/scripts/git-fix-modules.sh b/scripts/git-fix-modules.sh new file mode 100755 index 0000000..41f41f8 --- /dev/null +++ b/scripts/git-fix-modules.sh @@ -0,0 +1,93 @@ +#!/bin/sh +# A more helpful replacement for 'git submodule update --init'. +# +# It leaves the remote 'origin' pointing at the upstream projects, but can +# use local git-subtrac branches as a data source so that most of the time +# it doesn't actually need to fetch from the upstream. +# +# Use this whenever you want to get your submodules back in sync. +# +set -e +cd "$(dirname "$0")" # move to git worktree root +topdir="$PWD" # absolute path of git worktree root + +# For initial 'git submodule update', the --no-fetch option is ignored, +# and it tries to talk to the origin repo for no good reason. Let's override +# the origin repo URL to fool git into not doing that. +git submodule status | while read -r commit path junk; do + git submodule init -- "$path" +done +git config --local --get-regexp '^submodule\..*\.url$' | while read k v; do + git config "$k" . +done + +# In each submodule, make sure info/alternates is set up to retrieve +# objects directly from the parent repo (git-subtrac objects), bypassing +# the need to fetch anything. If someone has previously checked out a +# submodule without setting these values, this will fix them up. +for config in .git/modules/*/config; do + [ -f "$config" ] || continue + + dir=$(dirname "$config") + echo "$topdir/.git/objects" >"$dir/objects/info/alternates" +done + +# Make sure any remaining submodules have been checked out at least once, +# referring to the toplevel repo for all objects. +# +# TODO(apenwarr): --merge is not always the right option. +# eg. when checking out old revisions, we'd rather just roll the submodule +# backwards too. But git submodule doesn't have a good way to do that +# safely, so after a checkout, you can run git-stash-all.sh by hand to +# rewind the submodules. +git submodule update --init --no-fetch --reference="$PWD" --recursive --merge + +# Make sure all submodules are *now* (after initial checkout) using the +# latest URL from .gitmodules for their 'origin' URL. +git submodule --quiet sync --recursive + +git submodule status --cached | while read -r commit path junk; do + # fix superproject conflicts caused by trying to merge submodules, + # if any. These happen when two different commits try to change the + # same submodule in incompatible ways. To resolve it, we'll check out + # the first one and try to git merge the second. (Why git can't just + # do this by itself is... one of the many problems with submodules.) + cid2= + cid3= + git ls-files --unmerged -- "$path" | while read -r mode hash rev junk; do + if [ "$rev" = "2" ]; then + (cd "$path" && git checkout "$hash" -- || true) + cid2=$hash + fi + if [ "$rev" = "3" ]; then + cid3=$hash + (cd "$path" && git merge "$hash" -- || true) + git add -- "$path" + fi + done + + commit=${commit#-} + commit=${commit#+} + ( + cd "$path" + + main=$(git rev-parse --verify --quiet main || true) + head=$(git rev-parse --verify HEAD) + + if [ -n "$main" ] && + ! git merge-base main "$commit" >/dev/null; then + # main and $commit have no common history. + # It's probably dangerous. Move it aside. + git branch -f -m main main.probably-broken + fi + + # update --merge can't rewind the branch, only move it + # forward. Give a warning if we notice this problem. + if [ "$head" != "$commit" ]; then + echo "$path:" >&2 + echo " Couldn't checkout non-destructively." >&2 + echo " You can try to fix it by hand, or" >&2 + echo " use git-stash-all.sh if you want to force it." >&2 + fi + ) +done From 0e7d7151b41e8dc43f61816ab2b4a43db1ded941 Mon Sep 17 00:00:00 2001 From: Alexey Shamrin Date: Wed, 17 Feb 2021 00:28:18 +0200 Subject: [PATCH 2/4] test.sh draft --- t/test.sh | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 t/test.sh diff --git a/t/test.sh b/t/test.sh new file mode 100644 index 0000000..6086ca3 --- /dev/null +++ b/t/test.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +mkdir playground +cd playground + +# make (bare) parent.git repo +mkdir parent +cd parent +git init +echo parent > README +cp ~/src/swanbase/git-fix-modules.sh . +git add README git-fix-modules.sh +git commit -m 'initial parent commit' +mv .git ../parent.git +cd .. +rm -fr parent +cd parent.git +git config --bool core.bare true +cd .. + +# make (bare) dep.git repo +mkdir dep +cd dep +git init +echo dep > README +git add README +git commit -m 'initial dep commit' +mv .git ../dep.git +cd .. +rm -fr dep +cd dep.git +git config --bool core.bare true +cd .. + +# repo owner: add dep as a subtrac-enhanced submodule +git clone parent.git parent +cd parent/ +git submodule add ../dep +git add .gitmodules dep +git commit -m 'add submodule' +./git-fix-modules.sh +git subtrac --auto-exclude update +git push origin master master.trac +cd .. + +# repo contributor: clone +git clone --recurse-submodules parent.git another-parent +cd another-parent +./git-fix-modules.sh +cd dep +git checkout master + +# repo contributor: make local change +echo 'local change' >> README +git commit -m 'locally patch dep' README +cd .. +git commit -m 'record change in parent' dep +git subtrac --auto-exclude update +git push origin master master.trac +cd .. + +# upstream change +git clone dep.git dep +cd dep +echo 'upstream change' >> README +git commit -m 'upstream change' README +git push origin master +cd .. + +# rebase parent/dep after upstream change +cd parent/dep +git fetch +git rebase origin/master +git commit -m 'rebase dep on upstream changes' dep +git push origin master + +# push parent/dep changes to upstream +cd parent/dep +git push origin master From 5f933e3708aa2eb013ba771ab19823d354f3a186 Mon Sep 17 00:00:00 2001 From: Alexey Shamrin Date: Wed, 17 Feb 2021 00:44:39 +0200 Subject: [PATCH 3/4] tutorial --- TUTORIAL.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 TUTORIAL.md diff --git a/TUTORIAL.md b/TUTORIAL.md new file mode 100644 index 0000000..be37480 --- /dev/null +++ b/TUTORIAL.md @@ -0,0 +1,51 @@ +Add subtrac-enhanced submodule to a parent project: + +```sh +git clone git@example.com:example/parent.git +cd parent/ +git submodule git@example.com:example/dep.git ../dep +git add .gitmodules dep +git commit -m 'add submodule' +cp /path/to/git-subtrac/git-fix-modules.sh . +./git-fix-modules.sh +git subtrac --auto-exclude update +git push origin master master.trac +cd .. +``` + +Another contribor clones parent repo and makes local change in a submodule: + +```sh +git clone --recurse-submodules git@example.com:example/parent.git another-parent +cd another-parent +./git-fix-modules.sh +cd dep +git checkout master + +echo 'local change' >> README +git commit -m 'locally patch dep' README +cd .. +git commit -m 'record change in parent' dep +git subtrac --auto-exclude update +git push origin master master.trac +cd .. +``` + +Bring in changes from upstream and rebase: + +```sh +cd parent/dep +git fetch +git rebase origin/master +git commit -m 'rebase dep on upstream changes' dep +git push origin master +cd ../.. +``` + +Share changes with upstream: + +```sh +cd parent/dep +git push origin master +cd ../.. +``` From 769674f7a91a0f0b887fcd2544f4d553ddf1b2b2 Mon Sep 17 00:00:00 2001 From: Alexey Shamrin Date: Wed, 17 Feb 2021 00:55:17 +0200 Subject: [PATCH 4/4] Update TUTORIAL.md --- TUTORIAL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TUTORIAL.md b/TUTORIAL.md index be37480..0e6de7e 100644 --- a/TUTORIAL.md +++ b/TUTORIAL.md @@ -13,7 +13,7 @@ git push origin master master.trac cd .. ``` -Another contribor clones parent repo and makes local change in a submodule: +Another contributor clones parent repo and makes local change in a submodule: ```sh git clone --recurse-submodules git@example.com:example/parent.git another-parent