Hi, On Fri, May 22, 2015 at 4:38 PM, Stephen Kelly <steveire@xxxxxxxxx> wrote: > Hello, > > I have an 'integration repo' which contains other git repos as submodules. > > One of the submodules is to be split in two to extract a library. > > A common way of doing that is to use git-filter-branch. A disadvantage > of that is that it results in duplicated partial-history in the > extracted repo. So, git log shows the entire history, but there is not > one canonical sha which represents the history at that point. The > split repo will contain 'false history', and checking it out will not > be useful. > > So, I want to avoid git-filter-branch. > > I have tried out using `git replace --graft` and > .git/objects/info/alternates to 'refer to' the history in the origin > repo instead of 'duplicating' it. This is similar to how Qt5 repos > refer to Qt 4 history in a different repo. > > Question 1) Is this a reasonable thing to do for this scenario? I think it should work without too much work, but see the answer to the next question. > Question 2) Is there a way to push the `git replace` result and the > `info/alternates` content so that clients cloning the 'integration > repo' do not have to do that 'manually' or with a 'setup-repo.sh' > script? In short no. "git replace" creates replace refs in "refs/replace/". To fetch these refs, people need to use either "git fetch 'refs/replace/*:refs/replace/*'" or add a "fetch = refs/replace/*:refs/replace/*" line in their config. For simplicity and security reasons fetching replace refs is not on by default. Also changing the objects/info/alternates to make it point to another repo cannot be done automatically when cloning. > The sequence of commands below can be pasted into a tmp directory to > see the scenario in action. > > Thanks! > > > mkdir calculator > cd calculator > mkdir mainui libcalc > echo "print \"hello\"" > mainui/app.py > echo "print \"hello\"" > libcalc/adder.py > echo "print \"hello\"" > libcalc/subtracter.py > git init > git add . > git commit -am "Initial commit" > git checkout `git rev-parse HEAD` > > cd .. > mkdir appsuite > cd appsuite > git init > git submodule add ../calculator > git commit -m "Add calculator submodule" > > # Add other submodules in the suite... > > cd calculator > > echo "print \"goodbye\"" > libcalc/subtracter.py > git add libcalc/subtracter.py > git commit -am "Fix bug in subtracter" > > echo "print \"Hi\"" > libcalc/adder.py > git add libcalc/adder.py > git commit -am "Make adder more efficient" > > echo "print \"Hello, world!\"" > mainui/app.py > git add mainui/app.py > git commit -am "Improve app" > > echo "print \"hello, hello\"" > libcalc/multiplier.py > git add libcalc/multiplier.py > git commit -am "Add multiplier" > > cd .. > git add calculator > git commit -m "Update calculator submodule" > > mkdir compute > cd calculator > mv libcalc ../compute > > extraction_sha=`git rev-parse HEAD` > git commit -am "Remove libcalc from calculator repo" -m "It is moved > to a new compute repo" > removal_sha=`git rev-parse HEAD` > git push > > cd ../compute > git init > git add . > git commit -m "Create the compute repo." -m "This commit will not be > normally visible after the replace --graft below." > > echo "This is the compute framework. It contains the libcalc library." > README > git add README > git commit -m "Initialize the compute repo." -m "This has been > extracted from calculator.git at $removal_sha" > git checkout `git rev-parse HEAD` > > cd .. > mv compute .. > git submodule add ../compute > > git add calculator compute > git commit -m "Split compute framework out of calculator repo." > > cd compute > git log --oneline > # We don't see older history from the calculator repo > > # Let's add alternates > echo "../../calculator/objects" > > ../.git/modules/compute/objects/info/alternates > > # ... and graft onto the extraction commit > git replace --graft HEAD $extraction_sha > > git log --oneline > # Great, now we see history from the calculator repo. > > cd ../.. > git clone appsuite appsuite-clone > cd appsuite-clone > git submodule update --init > cd compute > ls ../.git/modules/compute/objects/info > git log --oneline > # The replacement and alternatives did not get cloned ... :( > > echo "../../calculator/objects" > > ../.git/modules/compute/objects/info/alternates > git replace --graft HEAD $extraction_sha Maybe use the following instead of the above line: git fetch 'refs/replace/*:refs/replace/*' > # And now we see the history from the calculator repo. Great. But, it > required user action after the clone. Yeah, but if the 2 above commands are in a script maybe it's reasonable to ask the user to launch the script once after cloning. Best, Christian. -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html