There are very few Q&A's on git grafts
versus replace
. The search [git] +grafts +replace only found two that felt relevant of the 5. what-are-git-info-grafts-for and git-what-is-a-graftcommit-or-a-graft-id. There is also a note on git.wiki.kernel.org:GraftPoint
Are grafts now completely overtaken by the replace
and filter-branch
, or do they still needed for some special corner cases (and backward compatibility) ?
In general, how do they differ (e.g. which are transported between repos), and how are they generically the same? I've seen that Linus doesn't appear to care about grafts at present in the discussion on commit generation numbers (of the max parents back to any root variety) "Grafts are already unreliable."
EDIT: more info found.
A search of www.kernel.org/pub/software/scm/git/docs for graft
only found 3 results:
A slightly broader search found RelNotes/1.6.5.txt which contains:
- refs/replace/ hierarchy is designed to be usable as a replacement of the "grafts" mechanism, with the added advantage that it can be transferred across repositories.
Unfortunately, the gitrepository-layout(5) isn't yet up to date with the refs/replace/ repository layout info (and notes), nor any deprecation note of info/grafts.
This gets closer to supporting what I was thinking but I'd welcome any confirmation or clarification.
The replace command lets you specify an object in Git and say "every time you refer to this object, pretend it's a different object". This is most commonly useful for replacing one commit in your history with another one without having to rebuild the entire history with, say, git filter-branch .
Git has a local – per-repository – mechanism to change and specify explicitly the parent of existing commits: These are called Grafts.
Graft points or grafts enable two otherwise different lines of development to be joined together. It works by letting users record fake ancestry information for commits. This way you can make git pretend the set of parents a commit has is different from what was recorded when the commit was created. As of Git 1.6.
In the same discussion about Commit Generation Number that you mention, Jakub Narębski does confirm that grafts are more aproblem than a solution:
grafts are so horrible hack that I would be not against turning off generation numbers if they are used.
In the case of replace objects you need both non-replaced and replaced DAG generation numbers.
[...] Grafts are non-transferable, and if you use them to cull rather than add history they are unsafe against garbage collection... I think.
(publishing has always been taken care of with git filter-branch
, as illustrated by this 2008 thread on grafts workflow.)
The difference between grafts and git replace is best illustrated by this SO question "Setting git parent pointer to a different parent", and the comments of (Jakub's again) answer.
It does include the reference to Git1.6.5
From what I understand (from GraftPoints),
git replace
has supersededgit grafts
(assuming you have git 1.6.5 or later)(Jakub:)
- if you want to rewrite history then
grafts
+git-filter-branch
(or interactive rebase, or fast-export + e.g. reposurgeon) is the way to do it.- If you want/need to preserve history, then
git-replace
is far superior to graft
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With