* Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible? @ 2011-01-11 10:41 Алексей Шумкин 2011-01-11 11:49 ` "Martin Krüger" 2011-01-11 13:21 ` Jakub Narebski 0 siblings, 2 replies; 18+ messages in thread From: Алексей Шумкин @ 2011-01-11 10:41 UTC (permalink / raw) To: git Hi all! 1.5 years ago I had sources of a project in a SVN repository (actually it does not matter what SCM was used before). And I had two branches: v2.4 and v2.5. They differed enough at that moment and (as usual for SVN branches) laid in two different folders. Then I had known of Git and I decided to try to use this powerful DVCS. But as I was a newbie I created two git-repositories: one per each branch. So v2.4 has its own git-repo. v2.5 (and above) has another one. Now I'd like to merge them as v2.5 was a continuos branch from v2.4, but without a rebasing (i.e. without a global changing of v2.5 repository, which already has another branches) It must look like LAST commit of v2.4 should be a PARENT of FIRST commit of v2.5 Now there's a question: Is it possible to do so (no rebasing!), and If "yes" then how to? ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible? 2011-01-11 10:41 Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible? Алексей Шумкин @ 2011-01-11 11:49 ` "Martin Krüger" 2011-01-11 12:33 ` Re[2]: " Алексей Шумкин 2011-01-11 13:21 ` Jakub Narebski 1 sibling, 1 reply; 18+ messages in thread From: "Martin Krüger" @ 2011-01-11 11:49 UTC (permalink / raw) To: "ÐлекÑей ШÑмкин", git > > Now I'd like to merge them as v2.5 was a continuos branch from v2.4, > but without a rebasing (i.e. without a global changing of v2.5 > repository, which already has another branches) > It must look like LAST commit of v2.4 should be a PARENT of FIRST commit > of v2.5 > > Now there's a question: Is it possible to do so (no rebasing!), and If > "yes" then how to? > > It's possible with a little arts an crafts. You have 2 friends: git format-patch & git am . With "git format-patch" you will see what a branch really is: a serie of patches. With "git am" you can apply these patches to a branch created on the correct point of the commit-history . E voila the branch is recreated in the repository. In your case: On the 2.5 repository master branch: git format-patch INITIAL_COMMITID On the 2.4 repository master branch: git branch 2.5 git checkout 2.4 git reset --hard INITIAL_COMMITID cat *.patch | git am E voila you habe both branches in a single repository. Nearly same procedure for every branch of the 2.5 repository git checkout branchname git format-patch master In the 2.4(Contains now both branches.) respository: git checkout 2.5 git branch branchname git reset --hard CORRECT_BRANCHBASE cat *.patch | git am Best regards martin ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re[2]: Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible? 2011-01-11 11:49 ` "Martin Krüger" @ 2011-01-11 12:33 ` Алексей Шумкин 2011-01-11 12:41 ` Andreas Ericsson 2011-01-11 12:47 ` "Martin Krüger" 0 siblings, 2 replies; 18+ messages in thread From: Алексей Шумкин @ 2011-01-11 12:33 UTC (permalink / raw) To: "Martin Krüger"; +Cc: git Thank you for the answer, but it's not what I want )) Applying patches is the same as rebasing, I guess. But I do not want to change v2.5-repo (let's call it so) that much. I'd like to know is there any method (low-level I suppose, as far as Git manages tree-objects as files) to make v2.4 LAST commit to be the parent of v2.5 FIRST commit? MK> It's possible with a little arts an crafts. MK> You have 2 friends: git format-patch & git am . MK> With "git format-patch" you will see what a branch really is: MK> a serie of patches. With "git am" you can apply these patches MK> to a branch created on the correct point of the commit-history . E MK> voila the branch is recreated in the repository. MK> In your case: MK> On the 2.5 repository master branch: MK> git format-patch INITIAL_COMMITID MK> On the 2.4 repository master branch: MK> git branch 2.5 MK> git checkout 2.4 MK> git reset --hard INITIAL_COMMITID MK> cat *.patch | git am MK> E voila you habe both branches in a single repository. MK> Nearly same procedure for every branch of the 2.5 repository MK> git checkout branchname MK> git format-patch master MK> In the 2.4(Contains now both branches.) respository: MK> git checkout 2.5 MK> git branch branchname MK> git reset --hard CORRECT_BRANCHBASE MK> cat *.patch | git am ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible? 2011-01-11 12:33 ` Re[2]: " Алексей Шумкин @ 2011-01-11 12:41 ` Andreas Ericsson 2011-01-11 14:58 ` Re[2]: " Алексей Шумкин 2011-01-11 12:47 ` "Martin Krüger" 1 sibling, 1 reply; 18+ messages in thread From: Andreas Ericsson @ 2011-01-11 12:41 UTC (permalink / raw) To: Алексей Шумкин Cc: Martin Krüger, git On 01/11/2011 01:33 PM, Алексей Шумкин wrote: > Thank you for the answer, but it's not what I want )) > Applying patches is the same as rebasing, I guess. > But I do not want to change v2.5-repo (let's call it so) that much. > I'd like to know is there any method (low-level I suppose, as far as Git > manages tree-objects as files) to make v2.4 LAST commit to be the > parent of v2.5 FIRST commit? > You want grafts. Check them up in the docs. Googling for "git graft" should get you a good starting point. -- Andreas Ericsson andreas.ericsson@op5.se OP5 AB www.op5.se Tel: +46 8-230225 Fax: +46 8-230231 Considering the successes of the wars on alcohol, poverty, drugs and terror, I think we should give some serious thought to declaring war on peace. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re[2]: Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible? 2011-01-11 12:41 ` Andreas Ericsson @ 2011-01-11 14:58 ` Алексей Шумкин 0 siblings, 0 replies; 18+ messages in thread From: Алексей Шумкин @ 2011-01-11 14:58 UTC (permalink / raw) To: Andreas Ericsson; +Cc: Martin Krüger, git AE> On 01/11/2011 01:33 PM, Алексей Шумкин wrote: >> Thank you for the answer, but it's not what I want )) >> Applying patches is the same as rebasing, I guess. >> But I do not want to change v2.5-repo (let's call it so) that much. >> I'd like to know is there any method (low-level I suppose, as far as Git >> manages tree-objects as files) to make v2.4 LAST commit to be the >> parent of v2.5 FIRST commit? >> AE> You want grafts. Check them up in the docs. Googling for "git graft" AE> should get you a good starting point. Yes, you`re right, but unfortunately grafts ('info/grafts' file) cannot be cloned unless 'git filter-branch' is executed, but this command changes all the "v2.5-repo" which is "equivalent" to 'git rebase' and what I aspire to avoid. But Jakub Narebski <jnareb@gmail.com> gave a solution which suits for me great. Thank you for your reply ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Re[2]: Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible? 2011-01-11 12:33 ` Re[2]: " Алексей Шумкин 2011-01-11 12:41 ` Andreas Ericsson @ 2011-01-11 12:47 ` "Martin Krüger" 1 sibling, 0 replies; 18+ messages in thread From: "Martin Krüger" @ 2011-01-11 12:47 UTC (permalink / raw) To: "ÐлекÑей ШÑмкин" Cc: git > Thank you for the answer, but it's not what I want )) > Applying patches is the same as rebasing, I guess. > But I do not want to change v2.5-repo (let's call it so) that much. > I'd like to know is there any method (low-level I suppose, as far as Git > manages tree-objects as files) to make v2.4 LAST commit to be the > parent of v2.5 FIRST commit? > This is impossible. The commit-id is calculated from the history of the whole repository. So you must rebase in the sense of dependency on another history. My method enables to rebase on the same content of the repository. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible? 2011-01-11 10:41 Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible? Алексей Шумкин 2011-01-11 11:49 ` "Martin Krüger" @ 2011-01-11 13:21 ` Jakub Narebski 2011-01-11 14:49 ` Re[2]: " Алексей Шумкин ` (2 more replies) 1 sibling, 3 replies; 18+ messages in thread From: Jakub Narebski @ 2011-01-11 13:21 UTC (permalink / raw) To: Алексей Шумкин Cc: git =?windows-1251?B?wOvl6vHl6SDY8+zq6O0=?= <zapped@mail.ru> writes: > 1.5 years ago I had sources of a project in a SVN repository (actually it does not > matter what SCM was used before). And I had two branches: v2.4 and v2.5. > They differed enough at that moment and (as usual for SVN branches) > laid in two different folders. > Then I had known of Git and I decided to try to use this powerful DVCS. > But as I was a newbie I created two git-repositories: one per each > branch. So v2.4 has its own git-repo. v2.5 (and above) has another one. > > Now I'd like to merge them as v2.5 was a continuos branch from v2.4, > but without a rebasing (i.e. without a global changing of v2.5 > repository, which already has another branches) > It must look like LAST commit of v2.4 should be a PARENT of FIRST commit of v2.5 > > Now there's a question: Is it possible to do so (no rebasing!), and If > "yes" then how to? As Andreas Ericsson wrote, you can do this using grafts (and you can make history with grafts permanent using "git filter-branch"). Better solution might be to use more modern replace mechanism, see e.g. "git replace" manpage. Below there is untested step-by-step instruction. First, you have put history of v2.4 and of v2.5 in a single repository (e.g. using "git remote add"). Then you need to find FIRST commit of v2.5 among $ git rev-list master --parents | grep -v ' ' The above finds all parent-less commits in 'master' branch; replace it with branch holding v2.5 history. Then you need to find LAST commit of v2.4 and its SHA-1, e.g. via $ git rev-parse v2.4 Save current state of FIRST commit of v2.5 to a file $ git cat-file -p FIRST > tmp 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 (trailing space added for better readibility). Then you need to add newly created object to repository: $ git hash-object -t commit -w tmp and then use it as replacement $ git replace <SHA-1 of FIRST> <SHA-1 returned by hash-object> Finally check that replacement works, e.g.: $ git show FIRST $ git log --graph --oneline -3 FIRST The anyone who would fetch refs/replace/ would get joined history, and who doesn't would see it not connected. P.S. This probably should made it into Documentation/howto -- Jakub Narebski Poland ShadeHawk on #git ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re[2]: Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible? 2011-01-11 13:21 ` Jakub Narebski @ 2011-01-11 14:49 ` Алексей Шумкин 2011-01-11 15:16 ` Алексей Шумкин 2011-01-12 0:08 ` [RFC/PATCH] Documentation: start to explain what git replace is for Jonathan Nieder 2 siblings, 0 replies; 18+ messages in thread From: Алексей Шумкин @ 2011-01-11 14:49 UTC (permalink / raw) To: Jakub Narebski; +Cc: git Hello, Jakub. Thank you very much. Your method works great and it suits for me well >> 1.5 years ago I had sources of a project in a SVN repository (actually it does not >> matter what SCM was used before). And I had two branches: v2.4 and v2.5. >> They differed enough at that moment and (as usual for SVN branches) >> laid in two different folders. >> Then I had known of Git and I decided to try to use this powerful DVCS. >> But as I was a newbie I created two git-repositories: one per each >> branch. So v2.4 has its own git-repo. v2.5 (and above) has another one. >> >> Now I'd like to merge them as v2.5 was a continuos branch from v2.4, >> but without a rebasing (i.e. without a global changing of v2.5 >> repository, which already has another branches) >> It must look like LAST commit of v2.4 should be a PARENT of FIRST commit of v2.5 >> >> Now there's a question: Is it possible to do so (no rebasing!), and If >> "yes" then how to? JN> As Andreas Ericsson wrote, you can do this using grafts (and you can JN> make history with grafts permanent using "git filter-branch"). JN> Better solution might be to use more modern replace mechanism, see JN> e.g. "git replace" manpage. Below there is untested step-by-step JN> instruction. JN> First, you have put history of v2.4 and of v2.5 in a single repository JN> (e.g. using "git remote add"). Then you need to find FIRST commit of JN> v2.5 among JN> $ git rev-list master --parents | grep -v ' ' JN> The above finds all parent-less commits in 'master' branch; replace it JN> with branch holding v2.5 history. Then you need to find LAST commit JN> of v2.4 and its SHA-1, e.g. via JN> $ git rev-parse v2.4 JN> Save current state of FIRST commit of v2.5 to a file JN> $ git cat-file -p FIRST > tmp JN> Edit this file, adding 'parent' line between 'tree' and 'author' JN> headers, so the header of this file looks like the following: JN> tree 13d050266e05f7c66000240814199fcf3b559d43 JN> parent ada9983c4256f5a7bac1f7f0e29d52011741d6aa JN> author Jakub Narebski <jnareb@gmail.com> 1294231771 +0100 JN> (trailing space added for better readibility). JN> Then you need to add newly created object to repository: JN> $ git hash-object -t commit -w tmp JN> and then use it as replacement JN> $ git replace <SHA-1 of FIRST> <SHA-1 returned by hash-object> JN> Finally check that replacement works, e.g.: JN> $ git show FIRST JN> $ git log --graph --oneline -3 FIRST JN> The anyone who would fetch refs/replace/ would get joined history, and JN> who doesn't would see it not connected. JN> P.S. This probably should made it into Documentation/howto ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re[2]: Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible? 2011-01-11 13:21 ` Jakub Narebski 2011-01-11 14:49 ` Re[2]: " Алексей Шумкин @ 2011-01-11 15:16 ` Алексей Шумкин 2011-01-12 0:08 ` [RFC/PATCH] Documentation: start to explain what git replace is for Jonathan Nieder 2 siblings, 0 replies; 18+ messages in thread From: Алексей Шумкин @ 2011-01-11 15:16 UTC (permalink / raw) To: Jakub Narebski; +Cc: git There is one more method using grafts and fast-export/import http://ben.straubnet.net/post/939181602/git-grafting-repositories Let it be here too ^ permalink raw reply [flat|nested] 18+ messages in thread
* [RFC/PATCH] Documentation: start to explain what git replace is for 2011-01-11 13:21 ` Jakub Narebski 2011-01-11 14:49 ` Re[2]: " Алексей Шумкин 2011-01-11 15:16 ` Алексей Шумкин @ 2011-01-12 0:08 ` Jonathan Nieder 2011-01-12 22:47 ` Maaartin 2 siblings, 1 reply; 18+ messages in thread From: Jonathan Nieder @ 2011-01-12 0:08 UTC (permalink / raw) To: Jakub Narebski Cc: Алексей Шумкин, git 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 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [RFC/PATCH] Documentation: start to explain what git replace is for 2011-01-12 0:08 ` [RFC/PATCH] Documentation: start to explain what git replace is for Jonathan Nieder @ 2011-01-12 22:47 ` Maaartin 2011-01-13 7:52 ` Alexey Shumkin 2011-01-14 8:49 ` [RFC/PATCH 2/1] fixup! " Jonathan Nieder 0 siblings, 2 replies; 18+ messages in thread From: Maaartin @ 2011-01-12 22:47 UTC (permalink / raw) To: git Jonathan Nieder <jrnieder <at> gmail.com> writes: > +. The following example comes from ??????? ??????: I know unicode exists already for many years, but in cygwin I get just a bunch of question marks instead of the name. So I'd suggest to replace "Алексей Шумкин" by "Alexej Shumkin" or whatever his preferred transcription is. > +<1> Find all parentless commits in the 'master' branch; > +for 'master' read the branch holding v2.5 history. Aren't you later calling it "FIRST" and assuming there's only one? > +$ sed -i "/^tree / a \\ > +parent $(git rev-parse v2.4)" <tmp >new <4> Isn't the combination of "-i" (=in-place edit) with redirection wrong? I hardly know anything about sed (abandoned it in favor of perl many years ago). > +$ git hash-object -t commit -w new <5> > +$ git replace FIRST <object id from hash-object> <6> I'd prefer something like +$ objectId=$(git hash-object -t commit -w new) +$ git replace FIRST $objectId This is easier for people just willing to use it without much thinking, and also for those having no idea that git-hash-object creates a new object. That said, it's a nice example and I've learned quite a few things. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC/PATCH] Documentation: start to explain what git replace is for 2011-01-12 22:47 ` Maaartin @ 2011-01-13 7:52 ` Alexey Shumkin 2011-01-14 8:49 ` [RFC/PATCH 2/1] fixup! " Jonathan Nieder 1 sibling, 0 replies; 18+ messages in thread From: Alexey Shumkin @ 2011-01-13 7:52 UTC (permalink / raw) To: git Maaartin <grajcar1 <at> seznam.cz> writes: > I know unicode exists already for many years, but in cygwin I get just a bunch > of question marks instead of the name. So I'd suggest to replace "Алексей > Шумкин" by "Alexej Shumkin" or whatever his preferred transcription is. "Alexey Shumkin" I'd prefer ) (it can be noticed in the patche) I use email-client for this account primarily for Russian correspondents so the signature is in Russian * "Maybe that's the reason to know how "The Bat!" can change letter templates for particular recipients" he thought * ^ permalink raw reply [flat|nested] 18+ messages in thread
* [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for 2011-01-12 22:47 ` Maaartin 2011-01-13 7:52 ` Alexey Shumkin @ 2011-01-14 8:49 ` Jonathan Nieder 2011-01-14 17:44 ` Maaartin-1 1 sibling, 1 reply; 18+ messages in thread From: Jonathan Nieder @ 2011-01-14 8:49 UTC (permalink / raw) To: Maaartin; +Cc: git, Jakub Narebski, Aleksey Shumkin Some tweaks suggested by Maaartin: - use a transliteration for Aleksey's name. - clarify that there will only be one parentless commit in a typical branch - use variables so the recipe is easier to test by copy and paste - remove unintended "-i" argument to sed While at it, make a few miscellaneous grammar tweaks and make sure each line of the example raw commit appears on a separate line. The formatting is still not great for that --- there is too much space between lines. Still to do: check whether this actually works and add a test script to make sure it keeps working. Improved-by: Maaartin <grajcar1@seznam.cz> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> --- Can be tested with make -C Documentation git-replace.1 man Documentation/git-replace.1 . Maaartin wrote: > Jonathan Nieder writes: [side note: please do not prune the cc list; I only stumbled on this message in the online archive by luck] >> +. The following example comes from ??????? ??????: > > I know unicode exists already for many years, but in cygwin I get just a bunch > of question marks instead of the name. So I'd suggest to replace "Алексей > Шумкин" by "Alexej Shumkin" or whatever his preferred transcription is. Makes sense. >> +<1> Find all parentless commits in the 'master' branch; >> +for 'master' read the branch holding v2.5 history. > > Aren't you later calling it "FIRST" and assuming there's only one? Hmm. I want to say that there _could_ be multiple parentless commits in the v2.5 history and we are treating one of them as its root (just like git master has multiple parentless ancestors but e83c5163 is conventionally considered its beginning). Not sure how to write that clearly. > Isn't the combination of "-i" (=in-place edit) with redirection wrong? Good catch (the "-i" is a typo). > +$ objectId=$(git hash-object -t commit -w new) > +$ git replace FIRST $objectId > > This is easier for people just willing to use it without much thinking, and > also for those having no idea that git-hash-object creates a new object. Right, thanks. Documentation/git-replace.txt | 40 ++++++++++++++++++++++------------------ 1 files changed, 22 insertions(+), 18 deletions(-) diff --git a/Documentation/git-replace.txt b/Documentation/git-replace.txt index 02e5de8..5829901 100644 --- a/Documentation/git-replace.txt +++ b/Documentation/git-replace.txt @@ -68,16 +68,17 @@ $ git cat-file commit foo <3> <2> show information about the true commit 'foo' <3> show information about the replacement commit 'bar' -. The following example comes from Алексей Шумкин: +. The following example comes from Aleksey Shumkin: + 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. +They differed enough at that moment and lay 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. +So v2.4 has one 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, +Now I'd like to merge them as if v2.5 were a continuous development +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 @@ -89,25 +90,28 @@ 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> +$ git rev-list master --parents | grep -v ' ' +$ first=$(git rev-list master --parents | grep -v ' ') <1> +$ git rev-parse v2.4 <2> +$ git cat-file commit $first >tmp <3> +$ sed "/^tree / a \\ +parent $(git rev-parse v2.4)" <tmp >new <4> +$ new_commit=$(git hash-object -t commit -w new) <5> +$ git replace $first $new_commit <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. +<1> List all parentless commits in the 'master' branch and +call the appropriate one (in this case the only one) $first. +Instead of 'master' one would use 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 +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. -- 1.7.4.rc2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for 2011-01-14 8:49 ` [RFC/PATCH 2/1] fixup! " Jonathan Nieder @ 2011-01-14 17:44 ` Maaartin-1 2011-01-14 19:30 ` Jonathan Nieder 2011-01-14 22:48 ` [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for Jakub Narebski 0 siblings, 2 replies; 18+ messages in thread From: Maaartin-1 @ 2011-01-14 17:44 UTC (permalink / raw) To: Jonathan Nieder; +Cc: git, Jakub Narebski, Aleksey Shumkin On 11-01-14 09:49, Jonathan Nieder wrote: > Some tweaks suggested by Maaartin: [snip] > [side note: please do not prune the cc list; I only stumbled on this > message in the online archive by luck] What could I have done about it? I didn't received it by email and answered using post.gmane.org. There's no way to add CC there. If I'd wrote an email instead, it wouldn't be placed in the thread. [snip] >>> +<1> Find all parentless commits in the 'master' branch; >>> +for 'master' read the branch holding v2.5 history. >> >> Aren't you later calling it "FIRST" and assuming there's only one? > > Hmm. I want to say that there _could_ be multiple parentless commits > in the v2.5 history and we are treating one of them as its root (just > like git master has multiple parentless ancestors but e83c5163 is > conventionally considered its beginning). Not sure how to write that > clearly. Maybe just something like "Let's assume there's only one and let's call it FIRST". For the example, this is enough. >> Isn't the combination of "-i" (=in-place edit) with redirection wrong? > > Good catch (the "-i" is a typo). I'd go the other way round and use "-i" so I'd need only one file. Using a shell variable instead would be even better, s. below. [snip] I tried to use the vars instead of files below, but never tested it. I used "first_commit" instead of both "tmp" and "new", which is not really nice. > +$ git rev-list master --parents | grep -v ' ' > +$ first=$(git rev-list master --parents | grep -v ' ') <1> > +$ git rev-parse v2.4 <2> > +$ git cat-file commit $first >tmp <3> $ first_commit = $(git cat-file commit FIRST) <3> > +$ sed "/^tree / a \\ > +parent $(git rev-parse v2.4)" <tmp >new <4> $ first_commit = $($ echo $first_commit | sed "/^tree / a \\ parent $(git rev-parse v2.4)") <4> Unfortunately, the line got too long. For sed unaware people like me it may not be obvious that a line break is required. I'd use perl, anyway. $ first_commit = $($ echo $first_commit | perl -p "s/^tree .*/$&\nparent $(git rev-parse v2.4)/") <4> > +$ new_commit=$(git hash-object -t commit -w new) <5> $ new_commit=$(echo $first_commit | git hash-object -t commit -w --stdin) <5> [snip] ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for 2011-01-14 17:44 ` Maaartin-1 @ 2011-01-14 19:30 ` Jonathan Nieder 2011-01-14 21:09 ` how multiple roots happen (Re: [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for) Jonathan Nieder 2011-01-14 22:48 ` [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for Jakub Narebski 1 sibling, 1 reply; 18+ messages in thread From: Jonathan Nieder @ 2011-01-14 19:30 UTC (permalink / raw) To: Maaartin-1; +Cc: git, Jakub Narebski, Aleksey Shumkin Maaartin wrote: > On 11-01-14 09:49, Jonathan Nieder wrote: >> [side note: please do not prune the cc list; I only stumbled on this >> message in the online archive by luck] > > What could I have done about it? See [1]. > Maybe just something like "Let's assume there's only one and let's call > it FIRST". For the example, this is enough. True enough. Even better would be to give a reference to the "coolest merge ever" (is that documented anywhere?) so the interested reader can discover how there could be more than one. > I'd go the other way round and use "-i" so I'd need only one file. "sed -i" is not portable (not sure how important that is for documentation). But perl -i is. :) > $ first_commit = $($ echo $first_commit | > perl -p > "s/^tree .*/$&\nparent $(git rev-parse v2.4)/") <4> So: perl -pi -e "s/^tree .*$/\$&\nparent $(git rev-parse v2.4)/" new Unfortunately "echo" and process substitution destroy some formatting in the commit message --- in particular, trailing whitespace. Thanks for the suggestions. Please feel free to pick up the patch and run with it (I trust you for this more than I would trust myself). Regards, Jonathan [1] My current method: [2] Yes, I agree that this is cumbersome. I'm also told that Thunderbird when used as a newsreader can reply-to-all easily, though I haven't tried it. [2] http://thread.gmane.org/gmane.comp.version-control.git/154490 ^ permalink raw reply [flat|nested] 18+ messages in thread
* how multiple roots happen (Re: [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for) 2011-01-14 19:30 ` Jonathan Nieder @ 2011-01-14 21:09 ` Jonathan Nieder 0 siblings, 0 replies; 18+ messages in thread From: Jonathan Nieder @ 2011-01-14 21:09 UTC (permalink / raw) To: Maaartin-1; +Cc: git, Jakub Narebski, Aleksey Shumkin Jonathan Nieder wrote: > Maaartin wrote: >> Maybe just something like "Let's assume there's only one and let's call >> it FIRST". For the example, this is enough. > > True enough. Even better would be to give a reference to the "coolest merge > ever" (is that documented anywhere?) so the interested reader can discover > how there could be more than one. Apparently it was not clear what I was talking about (who knew?). So here you go: http://thread.gmane.org/gmane.comp.version-control.git/5126 For a more modern take on it: http://thread.gmane.org/gmane.comp.version-control.git/144302/focus=144323 ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for 2011-01-14 17:44 ` Maaartin-1 2011-01-14 19:30 ` Jonathan Nieder @ 2011-01-14 22:48 ` Jakub Narebski 2011-01-15 0:04 ` Maaartin-1 1 sibling, 1 reply; 18+ messages in thread From: Jakub Narebski @ 2011-01-14 22:48 UTC (permalink / raw) To: Maaartin-1; +Cc: Jonathan Nieder, git, Aleksey Shumkin On Fri, 14 Jan 2011, Maaartin-1 wrote: > On 11-01-14 09:49, Jonathan Nieder wrote: > > Some tweaks suggested by Maaartin: > > [snip] > >> [side note: please do not prune the cc list; I only stumbled on this >> message in the online archive by luck] > > What could I have done about it? I didn't received it by email and > answered using post.gmane.org. There's no way to add CC there. If I'd > wrote an email instead, it wouldn't be placed in the thread. In a good newsreader, like e.g. Gnus from GNU Emacs, you have option to do 'reply all via email', which includes also git@vger.kernel.org, i.e. mailing list from which gmane newsgroup is created. That's what I do nowadays (usually). > [snip] > >>>> +<1> Find all parentless commits in the 'master' branch; >>>> +for 'master' read the branch holding v2.5 history. >>> >>> Aren't you later calling it "FIRST" and assuming there's only one? >> >> Hmm. I want to say that there _could_ be multiple parentless commits >> in the v2.5 history and we are treating one of them as its root (just >> like git master has multiple parentless ancestors but e83c5163 is >> conventionally considered its beginning). Not sure how to write that >> clearly. > > Maybe just something like "Let's assume there's only one and let's call > it FIRST". For the example, this is enough. That might be good enough, as I don't think that at beginning (where you are creating current and archive repository) one would have multiple roots from joining separate projects. >>> Isn't the combination of "-i" (=in-place edit) with redirection wrong? >> >> Good catch (the "-i" is a typo). > > I'd go the other way round and use "-i" so I'd need only one file. Using > a shell variable instead would be even better, s. below. No, using shell variable for storing commit object is *not* a good idea. Either save it to temporary file, where you can edit it using editor of your choice, or use pipeline. > [snip] > > I tried to use the vars instead of files below, but never tested it. I > used "first_commit" instead of both "tmp" and "new", which is not really > nice. > >> +$ git rev-list master --parents | grep -v ' ' >> +$ first=$(git rev-list master --parents | grep -v ' ') <1> Or using always the oldest commit: +$ first=$(git rev-list master --date-order --parents | grep -v ' ' | tail -1) <1> >> +$ git rev-parse v2.4 <2> Let's save it to a variable too +$ join=$(git rev-parse v2.4) <2> >> +$ git cat-file commit $first >tmp <3> We can use COMMIT, or even FIRST as a file name here. > $ first_commit = $(git cat-file commit FIRST) <3> No. Just... no. > > +$ sed "/^tree / a \\ > > +parent $(git rev-parse v2.4)" <tmp >new <4> > > $ first_commit = $($ echo $first_commit | > sed "/^tree / a \\ > parent $(git rev-parse v2.4)") <4> > > Unfortunately, the line got too long. For sed unaware people like me it > may not be obvious that a line break is required. No, it is not required, I think. > I'd use perl, anyway. > > $ first_commit = $($ echo $first_commit | > perl -p > "s/^tree .*/$&\nparent $(git rev-parse v2.4)/") <4> > > > +$ new_commit=$(git hash-object -t commit -w new) <5> > > $ new_commit=$(echo $first_commit | > git hash-object -t commit -w --stdin) <5> If you don't use temporary file, which you can edit, you can use pipeline instead: $ new_commit=$(git cat-file commit $first_commit | sed -e "/^tree / a\\parent $(git rev-parse v2.4)" | git hash-object -t commit -w --stdin $ git replace $first_commit $new_commit -- Jakub Narebski Poland ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for 2011-01-14 22:48 ` [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for Jakub Narebski @ 2011-01-15 0:04 ` Maaartin-1 0 siblings, 0 replies; 18+ messages in thread From: Maaartin-1 @ 2011-01-15 0:04 UTC (permalink / raw) To: Jakub Narebski; +Cc: Jonathan Nieder, git, Aleksey Shumkin On 11-01-14 23:48, Jakub Narebski wrote: > On Fri, 14 Jan 2011, Maaartin-1 wrote: >> On 11-01-14 09:49, Jonathan Nieder wrote: >>> Some tweaks suggested by Maaartin: >>> [side note: please do not prune the cc list; I only stumbled on this >>> message in the online archive by luck] >> >> What could I have done about it? I didn't received it by email and >> answered using post.gmane.org. There's no way to add CC there. If I'd >> wrote an email instead, it wouldn't be placed in the thread. > > In a good newsreader, like e.g. Gnus from GNU Emacs, you have option > to do 'reply all via email', which includes also git@vger.kernel.org, > i.e. mailing list from which gmane newsgroup is created. That's what > I do nowadays (usually). I hate using Emacs for too many things. However, I'm starting to use Thunderbird as newsreader, and it's quite OK. >> I'd go the other way round and use "-i" so I'd need only one file. Using >> a shell variable instead would be even better, s. below. > > No, using shell variable for storing commit object is *not* a good idea. > Either save it to temporary file, where you can edit it using editor of > your choice, or use pipeline. I see that the line-breaks get (for whatever reason) replaced by blanks, sorry for the noise. >>> +$ sed "/^tree / a \\ >>> +parent $(git rev-parse v2.4)" <tmp >new <4> >> >> $ first_commit = $($ echo $first_commit | >> sed "/^tree / a \\ >> parent $(git rev-parse v2.4)") <4> >> >> Unfortunately, the line got too long. For sed unaware people like me it >> may not be obvious that a line break is required. > > No, it is not required, I think. You're right, sorry again. > If you don't use temporary file, which you can edit, you can use pipeline > instead: > > $ new_commit=$(git cat-file commit $first_commit | > sed -e "/^tree / a\\parent $(git rev-parse v2.4)" | > git hash-object -t commit -w --stdin > > $ git replace $first_commit $new_commit I know, I just thought, using such a pipe is not very enlightening, but it's actually quite easy to follow. ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2011-01-15 0:04 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-01-11 10:41 Merge two different repositories (v2.4 + v2.5) into the one (v2.4 -> v2.5). Possible? Алексей Шумкин 2011-01-11 11:49 ` "Martin Krüger" 2011-01-11 12:33 ` Re[2]: " Алексей Шумкин 2011-01-11 12:41 ` Andreas Ericsson 2011-01-11 14:58 ` Re[2]: " Алексей Шумкин 2011-01-11 12:47 ` "Martin Krüger" 2011-01-11 13:21 ` Jakub Narebski 2011-01-11 14:49 ` Re[2]: " Алексей Шумкин 2011-01-11 15:16 ` Алексей Шумкин 2011-01-12 0:08 ` [RFC/PATCH] Documentation: start to explain what git replace is for Jonathan Nieder 2011-01-12 22:47 ` Maaartin 2011-01-13 7:52 ` Alexey Shumkin 2011-01-14 8:49 ` [RFC/PATCH 2/1] fixup! " Jonathan Nieder 2011-01-14 17:44 ` Maaartin-1 2011-01-14 19:30 ` Jonathan Nieder 2011-01-14 21:09 ` how multiple roots happen (Re: [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for) Jonathan Nieder 2011-01-14 22:48 ` [RFC/PATCH 2/1] fixup! Documentation: start to explain what git replace is for Jakub Narebski 2011-01-15 0:04 ` Maaartin-1
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).