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

Re: clone breaks replace

From
Jonathan Nieder <jrnieder@gmail.com>
Date
Jan 7, 2011, 20:51 UTC
Message-ID
<20110107205103.GC4629@burratino>
In-Reply-To
<4D276CD2.60607@cfl.rr.com>
Phillip Susi wrote:
> Isn't the whole purpose of using replace to avoid having to use
> filter-branch, which throws out all of the existing commit records, and
> creates an entirely new commit chain that is slightly modified?
No.  What documentation suggested that?  Maybe it can be fixed.

The original purpose of grafts (the ideological ancestor of replacement refs) was to serve a very particular use case. Sit down by the fire, if you will, and...

Git had just came into existence and pack files did not exist yet. A full import of the Linux kernel history was possible but the result was enormous and not something ready to be imposed on all Linux contributors. So what can one do?

 $ git show -s v2.6.12-rc2^0
 commit 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2
 Author: Linus Torvalds <torvalds@ppc970.osdl.org>
 Date:   Sat Apr 16 15:20:36 2005 -0700
     Linux-2.6.12-rc2
     Initial git repository build. I'm not bothering with the full history,
     even though we have it. We can create a separate "historical" git
     archive of that later if we want to, and in the meantime it's about
     3.2GB when imported into git - space that would just make the early
     git days unnecessarily complicated, when we don't have a lot of good
     infrastructure for it.
     Let it rip!

Fast forward three months, and there is discussion[1] about what to do with the historical git archive. A clever idea: teach git to _pretend_ that the historical archive is the parent to v2.6.12-rc2, so "git log --grep", "gitk", and so on work as they ought to.

So grafts were born. One of the nicest advantages of grafts is that they make it easy to do complex history surgery: make some grafts --- cut here, paste there --- and then run "git filter-branch" to make it permanent.

But grafts have a serious problem.

Transport machinery needs to ignore grafts --- otherwise, the two ends of a connection could have different ideas of the history preceding a commit, resulting in confusion and breakage. A fix to that was finally grafted on a few years later (see also [2]).

 $ GIT_NOTES_REF=refs/remotes/charon/notes/full \
   git log --grep=graft --grep=repack --all-match --no-merges
 [...]
     git repack: keep commits hidden by a graft
 [...]
     Archived-At: <http://thread.gmane.org/gmane.comp.version-control.git/123874>

There is also the problem that grafts are too "raw": it is very easy to make a graft pointing to a nonexistent object, say. And meanwhile git has no native support for transfering grafts over the wire.

In that context there emerged the nicer (imho) refs/replace mechanism:
 - reachability checking and transport machinery can treat them like
   all other references --- no need for low-level tools to pay
   attention to the artificial history;
 - easy to script around with "git replace" and "git for-each-ref"
 - can choose to fetch or not fetch with the usual
   "git fetch repo refs/replace/*:refs/replace/*" syntax
Common applications:
 - locally staging history changes that will later be made permanent
   with "git filter-branch";
 - grafting on additional (historical) history;
 - replacing ancient broken commits with fixed ones, for use by "git
   bisect".

Hope that helps, Jonathan

[1] http://thread.gmane.org/gmane.comp.version-control.git/6470/focus=6484 found with "git log --grep=graft --reverse" [2] http://thread.gmane.org/gmane.comp.version-control.git/37744/focus=37908

Previous: Phillip SusiNext: Stephen Bash
Message 5 of 34 in “clone breaks replace”
  1. Phillip SusiJan 6, 2011
  2. Jonathan NiederJan 6, 2011
  3. Junio C HamanoJan 6, 2011
  4. Phillip SusiJan 7, 2011
  5. Jonathan NiederJan 7, 2011
  6. Stephen BashJan 7, 2011
  7. Jonathan NiederJan 7, 2011
  8. Phillip SusiJan 7, 2011
  9. Jonathan NiederJan 7, 2011
  10. Phillip SusiJan 7, 2011
  11. Jeff KingJan 7, 2011
  12. Junio C HamanoJan 7, 2011
  13. Jeff KingJan 11, 2011
  14. Junio C HamanoJan 11, 2011
  15. Jeff KingJan 11, 2011
  16. Jonathan NiederJan 11, 2011
  17. Jeff KingJan 11, 2011
  18. Christian CouderJan 11, 2011
  19. Phillip SusiJan 8, 2011
  20. Jeff KingJan 11, 2011
  21. Jonathan NiederJan 11, 2011
  22. Phillip SusiJan 11, 2011
  23. Jonathan NiederJan 11, 2011
  24. Phillip SusiJan 11, 2011
  25. Phillip SusiJan 11, 2011
  26. Jeff KingJan 11, 2011
  27. Johannes SixtJan 11, 2011
  28. Jeff KingJan 11, 2011
  29. Johannes SixtJan 11, 2011
  30. Phillip SusiJan 11, 2011
  31. Jonathan NiederJan 11, 2011
  32. Phillip SusiJan 12, 2011
  33. small downloads and immutable history (Re: clone breaks replace)Jonathan Nieder, Jan 14, 2011
  34. Phillip SusiJan 15, 2011

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.