git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Pushing and pulling the result of `git replace` and objects/info/alternates

From
Christian Couder <christian.couder@gmail.com>
Date
May 24, 2015, 05:28 UTC
Message-ID
<CAP8UFD3G8_ChRX6HHtieFTksUJBiXu9FLNbewFQVj7qPyGh8EQ@mail.gmail.com>
In-Reply-To
<CACHsx4Kz3_bMbKqd1O7-ZXLBUqJBs6hTsiRNAALNJhDV44v6Rw@mail.gmail.com>
Hi,
On Fri, May 22, 2015 at 4:38 PM, Stephen Kelly <steveire@gmail.com> wrote:
Show 21 quoted lines
> 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.

Show 103 quoted lines
> 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.

Previous: Stephen KellyNext: Stephen Kelly
Message 2 of 6 in “Pushing and pulling the result of `git replace` and objects/info/alternates”
  1. Stephen KellyMay 22, 2015
  2. Christian CouderMay 24, 2015
  3. Stephen KellyMay 25, 2015
  4. Christian CouderMay 25, 2015
  5. Stephen KellyMay 26, 2015
  6. Christian CouderMay 26, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.