"Philip Oakley" <philipoakley@xxxxxxx> writes: > From: "Junio C Hamano" <gitster@xxxxxxxxx> > Sent: Saturday, January 09, 2016 1:04 AM >> Mike Hommey <mh@xxxxxxxxxxxx> writes: >> >>> So while `cat-file commit A` gives you what `cat-file commit Z` would, >>> `notes show A` doesn't give you what `notes show Z` would. And that's >>> this "inconsistency" that bothers me. >> >> In any case, 'notes' being a way to add extra information to an >> existing object means that with your original "replace" that tells >> Git to keep A in the history (and give Z's contents when contents of >> A was asked), >> it is absolutely correct that notes for A is shown. > > This seems very wrong to me. Surely we have asked that _all_ > references to A be replaced by a reference to Z and thence onward to > Z's contents. You didn't ask any such thing. I already said: The true source of your confusion, I think, is that there is a misunderstanding of what "replace A with Z" does. It is NOT "whenever somebody refers to A, pretend as if it is referring to Z". If that _were_ the case, then I'd agree that "whenever somebody else asks notes attached to A, pretend as if notes attached to Z were asked" might make sense, but that does not match the reality. but then didn't say what "the reality" is (because I already said it elsewhere upthread). What you asked is that whenever information in A is asked, a tweaked version of the original information in A is returned. The tweaked version happens to match what is in Z, but after the replacement, the object Z does not directly get into the picture---as you can see in the result of log (or rev-list) from C that shows "C B A Y X" (in tip-to-root order), the end user does not even have to be aware of Z's existence. Let's think about the example of grafting "old" history that starts at X, resurrected from archive since the history of the current project has already started at A and leading to C in real-world terms. A would be like Linus's v2.6.12-rc2 in the Linux kernel project that does not have any parent. Then you rebuild the "old" history from the archive that ends at the same v2.6.12-rc2, so your X Y Z history also ends with v2.6.12-rc2. And you would "graft" it behind the true history. Commits A and Z would both have the same log message, record the same tree, made by the same author and committer with same timestamps. Now, think which one of A and Z do you think people would want to "survive" in the graft operation? Everybody has built (and will continue to build) on the history that started at A whose tip is currently at C. If you have a way to tell Git "Earlier A was recorded as having NO parent, but I wish we had recorded Y as its parent. So create a fake reality where A's parent is Y.", then you can keep the resulting world view consistent with the "recent-only" real history, i.e. B's parent is still A. Some might even have notes on A, or commits made since A may reference the commit object A by name in its log, or another superproject may bind A as its subproject, but because we are not changing the identity/name of A with Z, all of these "external" references survive the grafting/replacing. Perhaps it would help if you stop thinking that you are somehow losing "Z" and "Z" is somehow precious. It is not, at least in the "history grafting" context, at all precious. When you have the true history starting from v2.6.12-rc2 (that is "A B C"), the thing you REALLY want to do is to resurrect history that ends at one commit before v2.6.12-rc2 (that is "Y" in the example), and somehow tweak "A" so that its parent is "Y". And the way you tweak "A" to make that happen is to replace its contents with the contents of a commit that records all the same information as "A" except that it has a parent that is "Y". We could do "cat-file commit A" piped to sed to add a "parent Y" line to it and then "hash-object" to come up with such a replacement commit, and replace A with it, but "Z" happens to be such a commit already, so that is why replacing A with Z would graft Y just behind A. The resulting history would show Y as the parent of A and Z won't even be in the consciousness of the end users. The "old history resurrection" project does not even have to create "Z" in the first place. If the contents of "Z" is different from contents of "A" in some other way, other than their set of parents, or if "Z" has other external references that are precious (e.g. a note may refer to it, or a superproject may bind Z to its tree), then either replacing A with Z or replacing Z with A would not be a good way to connect the two histories. As you would want to keep both, and the "external" references, such as notes and submodule gitlink bindings, want to keep refering to both. In such a case, the best you can do is to tweak A to have Z (instead of Y) as its fake parent, to make the resulting fake history read like "C B A Z Y X" (in tip-to-root order), having two copies of v2.6.12-rc2. That way you would be able to see both notes for A and Z, and can tell which note was attached to the true history and which note was attached to the history resurrected from the archive. -- 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