How to click "git replace -graft"

I used git replace --graft to record that the version was actually (manually executed) merging between the two versions:

  git replace --graft <merged-version> <predecessor-version> <version-merged-from> 

This made changes to my (local, private) repository.

Now I want to make this change available to other members of my team by "clicking" it on our shared repository (on Github, it happened). How can I do it? A simple git push seems to have no effect.

+10
source share
2 answers

Graphs exist within the hierarchy of refs/replace/ . (Or maybe it’s better to say that such links "owe their existence".) To transfer them from one store to another, you must click or get such links.

For instance:

 git push origin refs/replace/5c714d7798d1dc9c18d194fa6448680515c0ccdb 

when commit 5c714d7798d1dc9c18d194fa6448680515c0ccdb has a replacement (in my case the replacement was a new commit object ceba978ce6dad3b52d12134f4ef2720c5f3a9002 , i.e. Git usually does not see " 5c714d7 , instead of the replacement object ceba978 ).

To complete all replacements:

 git push origin 'refs/replace/*:refs/replace/*' 

(quotes are sometimes needed so that the shell does not distort the stars, exactly when and what quotes to use depends on the shell, although single and double quotes work on all Unix-y shells).

Selection Notes for Download

If some remote R has replacements, and you want to bring them all to your repository, use git fetch R 'refs/replace/*:refs/replace/*' (or the same with the + prefix, if you want, so that their replacements redefine everything that you already have). You can automate this for any repository and remote. For example, if you run git config --edit , you will find that the existing origin remote has several options that look like this:

 [remote "origin"] url = ... fetch = +refs/heads/*:refs/remotes/origin/* 

Just add the line:

  fetch = refs/replace/*:refs/replace/* 

or

  fetch = +refs/replace/*:refs/replace/* 

so that your Git delivers them to Git refs/replace/* . (Note: there are no quotes here, because the shell is not going to process this line.) The leading plus sign has the same meaning as usual: 1 without it, if you already have a link, you hold on and ignore them. With the leading plus sign, you drop yours and use them instead. As with tags, if your link and their link already match, it doesn’t matter whether you keep yours or replace yours; it matters only when you have different ideas about which object some link should point to.


1 In fact, the “usual value” for the leading plus sign depends on whether the link should move, such branch names or should not move, such as the tag name. The plus sign sets the force flag, i.e. “Always accept the proposed new settings,” but for branch names that are expected to “move forward”, updating is allowed without force if and only if it is “forward” (or “fast forward”). Git initially applied this rule to other links, such as tags, but Git people fixed it in Git 1.8.2. It’s not clear to me what Git rules apply to refs/replace/ links that should not be moved, but are not handled additionally specifically, like tags.

+9
source

Be careful when using git replace --graft : Git 2.22 (Q2 2019) fixes an error when git replace --graft failed to clear the tag before writing a ref replacement, which made no sense , because the old vaccination mechanism that the function wants to simulate allowed replacing only one fixation object with another.

See commit ee521ec , commit f8e44a8 , commit 5876170 , commit 502d87b (March 31, 2019) from Christian Couder ( chriscool ) .
(Combined Junio ​​C Hamano - gitster - in commit ce2a18f , May 8, 2019)

replace : clear tag when first passing the --graft tag

When passing a tag as the first argument to git replace --graft may be useful to accept it and use the base commit as the commit to be replaced.

This already works for lightweight tags, but unfortunately for annotated tags, we used the hash of the tag object instead of the hash of the base commit.

We would especially pass the hash of the tag object to replace_object_oid() where we could fail with this error:

 "error: Objects must be of the same type. 'annotated_replaced_object' points to a replaced object of type 'tag' while 'replacement' points to a replacement object of type 'commit'." 

This patch fixes this using the hash of the base commit when an annotated tag is passed.

0
source

Source: https://habr.com/ru/post/1015314/


All Articles