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

[RFC/PATCH] Documentation: start to explain what git replace is for

From
Jonathan Nieder <jrnieder@gmail.com>
Date
Jan 12, 2011, 00:08 UTC
Message-ID
<20110112000812.GA31950@burratino>
In-Reply-To
<m3lj2rbmq5.fsf@localhost.localdomain>
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@mail.ru>.
Based-on-message-by: Jakub Narebski <jnareb@gmail.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
 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@gmail.com> 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
Previous: Алексей ШумкинNext: Maaartin
Message 10 of 18 in “Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible?”
  1. Алексей ШумкинJan 11, 2011
  2. Martin KrügerJan 11, 2011
  3. Re[2]: Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible?Алексей Шумкин, Jan 11, 2011
  4. Andreas EricssonJan 11, 2011
  5. Re[2]: Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible?Алексей Шумкин, Jan 11, 2011
  6. Martin KrügerJan 11, 2011
  7. Jakub NarebskiJan 11, 2011
  8. Re[2]: Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible?Алексей Шумкин, Jan 11, 2011
  9. Re[2]: Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible?Алексей Шумкин, Jan 11, 2011
  10. Documentation: start to explain what git replace is forJonathan Nieder, Jan 12, 2011
  11. MaaartinJan 12, 2011
  12. Alexey ShumkinJan 13, 2011
  13. 2/1 fixup! Documentation: start to explain what git replace is forJonathan Nieder, Jan 14, 2011
  14. Maaartin-1Jan 14, 2011
  15. Jonathan NiederJan 14, 2011
  16. how multiple roots happen (Re: [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for)Jonathan Nieder, Jan 14, 2011
  17. Jakub NarebskiJan 14, 2011
  18. Maaartin-1Jan 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.