Jakub Narebski wrote: > P.S. This probably should made it into Documentation/howto Or even better, the git-replace manpage. How about something like this? Still very rough. I'd be happy if someone else can pick this up and make it into something better (for example, with an addition to the test suite to make sure we are not telling lies). -- 8< -- Subject: Documentation: start to explain what git replace is for With an example from ÐÐÐÐÑÐÐ ÐÑÐÐÐÐ <zapped@xxxxxxx>. Based-on-message-by: Jakub Narebski <jnareb@xxxxxxxxx> Signed-off-by: Jonathan Nieder <jrnieder@xxxxxxxxx> --- Documentation/git-replace.txt | 106 +++++++++++++++++++++++++++++++---------- 1 files changed, 80 insertions(+), 26 deletions(-) diff --git a/Documentation/git-replace.txt b/Documentation/git-replace.txt index fde2092..02e5de8 100644 --- a/Documentation/git-replace.txt +++ b/Documentation/git-replace.txt @@ -14,38 +14,29 @@ SYNOPSIS DESCRIPTION ----------- -Adds a 'replace' reference in `.git/refs/replace/` -The name of the 'replace' reference is the SHA1 of the object that is -replaced. The content of the 'replace' reference is the SHA1 of the -replacement object. +The `git replace <object> <replacement>` command adds a ref in the +`refs/replace/` hierarchy requesting that requests for <object> be +handled by retrieving <replacement> instead. This is most commonly +used to replace one commit by another. -Unless `-f` is given, the 'replace' reference must not yet exist in -`.git/refs/replace/` directory. +The name of this 'replace' reference is the object id for the object +that is replaced. Unless `-f` is given, the 'replace' reference must +not already exist in the `refs/replace/` hierarchy. -Replacement references will be used by default by all git commands -except those doing reachability traversal (prune, pack transfer and -fsck). +Replacement references will be used by default by most git commands, +with the notable exception of reachability calculations. This +exception means that replacements do not affect the result of 'git gc' +or 'git clone', ensuring that (1) it is always safe to remove a +replacement reference without harming repository integrity and +(2) replacements do not change the meaning of 'have' lines during +pack transfer, so the client and server do not need to have the same +replacements during object transfer for it to succeed. It is possible to disable use of replacement references for any command using the `--no-replace-objects` option just after 'git'. - -For example if commit 'foo' has been replaced by commit 'bar': - ------------------------------------------------- -$ git --no-replace-objects cat-file commit foo ------------------------------------------------- - -shows information about commit 'foo', while: - ------------------------------------------------- -$ git cat-file commit foo ------------------------------------------------- - -shows information about commit 'bar'. - -The 'GIT_NO_REPLACE_OBJECTS' environment variable can be set to -achieve the same effect as the `--no-replace-objects` option. +Additionally, the 'GIT_NO_REPLACE_OBJECTS' environment variable can +be set to achieve the same effect. OPTIONS ------- @@ -62,6 +53,69 @@ OPTIONS Typing "git replace" without arguments, also lists all replace refs. +EXAMPLES +-------- +. The following sequence replaces commit 'foo' with commit 'bar' +and then views the replaced and unreplaced versions of 'foo'. ++ +------------------------------------------------ +$ git replace foo^{commit} bar^{commit} <1> +$ git --no-replace-objects cat-file commit foo <2> +$ git cat-file commit foo <3> +------------------------------------------------ ++ +<1> request replacement +<2> show information about the true commit 'foo' +<3> show information about the replacement commit 'bar' + +. The following example comes from ÐÐÐÐÑÐÐ ÐÑÐÐÐÐ: ++ +1.5 years ago I had sources of a project in another version control +system. And I had two branches: v2.4 and v2.5. +They differed enough at that moment and laid in two different folders. +Then I learned about Git and I decided to try to use this DVCS. +I created two git repositories: one for each branch. +So v2.4 has its own git repo and v2.5 (and above) has another one. ++ +Now I'd like to merge them as v2.5 was a continuous branch from v2.4, +but without rebasing (i.e. without a global change to the v2.5 +repository, which already has other branches). It should look like +the last commit of from the v2.4 branch is a parent of the first +commit of v2.5. ++ +You can do this using grafts (and you can make history with grafts +permanent using 'git filter-branch'). A better solution might be to +use the more modern replace mechanism. Below are untested step-by-step +instructions. ++ +-------------------------------------------------- +$ git rev-list master --parents | grep -v ' ' <1> +$ git rev-parse v2.4 <2> +$ git cat-file commit FIRST >tmp <3> +$ sed -i "/^tree / a \\ +parent $(git rev-parse v2.4)" <tmp >new <4> +$ git hash-object -t commit -w new <5> +$ git replace FIRST <object id from hash-object> <6> +$ git show FIRST +$ git log --graph --oneline -3 FIRST <7> +-------------------------------------------------- ++ +<1> Find all parentless commits in the 'master' branch; +for 'master' read the branch holding v2.5 history. +<2> Find the last commit of v2.4. +<3> Save the current state of the first commit of v2.5 to a file. +<4> Edit this file, adding 'parent' line between 'tree' and 'author' +headers, so the header of this file looks like the following: + tree 13d050266e05f7c66000240814199fcf3b559d43 + parent ada9983c4256f5a7bac1f7f0e29d52011741d6aa + author Jakub Narebski <jnareb@xxxxxxxxx> 1294231771 +0100 +<5> Add the newly created object to the repository. +<6> Use it as a replacement. +<7> Check that replacement works. ++ +Then anyone who fetches `refs/replace/*` will get the joined history, +and those who doesn't will see it not connected. + BUGS ---- Comparing blobs or trees that have been replaced with those that -- 1.7.4.rc1 -- 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