{"thread":{"id":"21163","subject":"combine git repo historically","startedAt":"2009-10-09T01:22:54Z","lastAt":"2009-10-11T14:29:44Z","messageCount":12,"participants":["bill lam","Johannes Sixt","Christian Couder","Jakub Narebski","Andreas Schwab"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"124414","messageId":"20091009012254.GA3980@debian.b2j","threadId":"21163","inReplyTo":null,"subject":"combine git repo historically","fromName":"bill lam","fromEmail":"cbill.lam@gmail.com","sentAt":"2009-10-09T01:22:54Z","receivedAt":"2009-10-09T01:22:54Z","isPatch":false,"sender":{"key":"cbill.lam@gmail.com","avatar":null},"body":"I have two git repos, no branches.\n\nrepo 1.\n  emptyrootcommit -- A ... M \n\nrepo 2.\n  emptyrootcommit -- N ... Z\n\nN was evolved from M but the time gap is large, how can I combine them\ninto one repo\n\nemptyrootcommit -- A ... M -- N ... Z\n\nso that snapshots N .. Z will not be changed.\n\n-- \nregards,\n====================================================\nGPG key 1024D/4434BAB3 2008-08-24\ngpg --keyserver subkeys.pgp.net --recv-keys 4434BAB3\n"},{"id":"124423","messageId":"4ACED204.3000907@viscovery.net","threadId":"21163","inReplyTo":"20091009012254.GA3980@debian.b2j","subject":"Re: combine git repo historically","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-10-09T06:02:44Z","receivedAt":"2009-10-09T06:02:44Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"bill lam schrieb:\n> I have two git repos, no branches.\n> \n> repo 1.\n>   emptyrootcommit -- A ... M \n> \n> repo 2.\n>   emptyrootcommit -- N ... Z\n> \n> N was evolved from M but the time gap is large, how can I combine them\n> into one repo\n> \n> emptyrootcommit -- A ... M -- N ... Z\n> \n> so that snapshots N .. Z will not be changed.\n\n$ echo $(git rev-parse N) $(git rev-parse M) >> .git/info/grafts\n$ git filter-branch --tag-name-filter cat -- --all --not M\n\ni.e. you graft the older history right before the younger history, then\nyou use git filter-branch to rewrite the parentship of the younger commits.\n\n-- Hannes\n"},{"id":"124436","messageId":"c07716ae0910090040j4868edf4x12eea330416b8ccb@mail.gmail.com","threadId":"21163","inReplyTo":"4ACED204.3000907@viscovery.net","subject":"Re: combine git repo historically","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2009-10-09T07:40:47Z","receivedAt":"2009-10-09T07:40:47Z","isPatch":false,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Fri, Oct 9, 2009 at 8:02 AM, Johannes Sixt <j.sixt@viscovery.net> wrote:\n> bill lam schrieb:\n>> I have two git repos, no branches.\n>>\n>> repo 1.\n>>   emptyrootcommit -- A ... M\n>>\n>> repo 2.\n>>   emptyrootcommit -- N ... Z\n>>\n>> N was evolved from M but the time gap is large, how can I combine them\n>> into one repo\n>>\n>> emptyrootcommit -- A ... M -- N ... Z\n>>\n>> so that snapshots N .. Z will not be changed.\n>\n> $ echo $(git rev-parse N) $(git rev-parse M) >> .git/info/grafts\n> $ git filter-branch --tag-name-filter cat -- --all --not M\n>\n> i.e. you graft the older history right before the younger history, then\n> you use git filter-branch to rewrite the parentship of the younger commits.\n\nIf you cannot create a new history, using \"git replace\" could be\nbetter than using grafts.\n(\"git replace\" is in the \"master\" branch in the git repository. It\nwill be in git 1.6.5 that should be released soon.)\n\nRegards,\nChristian\n"},{"id":"124569","messageId":"20091010140358.GA3924@debian.b2j","threadId":"21163","inReplyTo":"4ACED204.3000907@viscovery.net","subject":"Re: combine git repo historically","fromName":"bill lam","fromEmail":"cbill.lam@gmail.com","sentAt":"2009-10-10T14:03:58Z","receivedAt":"2009-10-10T14:03:58Z","isPatch":false,"sender":{"key":"cbill.lam@gmail.com","avatar":null},"body":"On Fri, 09 Oct 2009, Johannes Sixt wrote:\n> bill lam schrieb:\n> > I have two git repos, no branches.\n> > \n> > repo 1.\n> >   emptyrootcommit -- A ... M \n> > \n> > repo 2.\n> >   emptyrootcommit -- N ... Z\n> > \n> > N was evolved from M but the time gap is large, how can I combine them\n> > into one repo\n> > \n> > emptyrootcommit -- A ... M -- N ... Z\n> > \n> > so that snapshots N .. Z will not be changed.\n> \n> $ echo $(git rev-parse N) $(git rev-parse M) >> .git/info/grafts\n> $ git filter-branch --tag-name-filter cat -- --all --not M\n> \n> i.e. you graft the older history right before the younger history, then\n> you use git filter-branch to rewrite the parentship of the younger commits.\n \n\nThanks,  graft is new to me. I tested it works but it needs first issue\n   git fetch /path/to/repo1\nwithin repo2 to fetch tip M from repo1 into repo2, is it correct?\n\nIf I also want to fetch also all objects from repo1, what will the\ncommand to do it.\n\nChristian Couder also mentioned the git-replace command, how to stitch\nwith it?\n\n-- \nregards,\n====================================================\nGPG key 1024D/4434BAB3 2008-08-24\ngpg --keyserver subkeys.pgp.net --recv-keys 4434BAB3\n"},{"id":"124586","messageId":"200910110436.52653.chriscool@tuxfamily.org","threadId":"21163","inReplyTo":"20091010140358.GA3924@debian.b2j","subject":"Re: combine git repo historically","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-10-11T02:36:52Z","receivedAt":"2009-10-11T02:36:52Z","isPatch":false,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Saturday 10 October 2009, bill lam wrote:\n> On Fri, 09 Oct 2009, Johannes Sixt wrote:\n> > bill lam schrieb:\n> > > I have two git repos, no branches.\n> > >\n> > > repo 1.\n> > >   emptyrootcommit -- A ... M\n> > >\n> > > repo 2.\n> > >   emptyrootcommit -- N ... Z\n> > >\n> > > N was evolved from M but the time gap is large, how can I combine\n> > > them into one repo\n> > >\n> > > emptyrootcommit -- A ... M -- N ... Z\n> > >\n> > > so that snapshots N .. Z will not be changed.\n> >\n> > $ echo $(git rev-parse N) $(git rev-parse M) >> .git/info/grafts\n> > $ git filter-branch --tag-name-filter cat -- --all --not M\n> >\n> > i.e. you graft the older history right before the younger history, then\n> > you use git filter-branch to rewrite the parentship of the younger\n> > commits.\n>\n> Thanks,  graft is new to me. I tested it works but it needs first issue\n>    git fetch /path/to/repo1\n> within repo2 to fetch tip M from repo1 into repo2, is it correct?\n>\n> If I also want to fetch also all objects from repo1, what will the\n> command to do it.\n\nMaybe you should do something like:\n\n$ git remote add repo1 /path/to/repo1\n$ git fetch repo1\n\nThe fetch command should output something like:\n\nremote: Counting objects: 423, done.\nremote: Compressing objects: 100% (149/149), done.\nremote: Total 363 (delta 276), reused 298 (delta 213)\nReceiving objects: 100% (363/363), 136.65 KiB, done.\nResolving deltas: 100% (276/276), completed with 29 local objects.\nFrom /path/to/repo1\n * [new branch]      branch1       -> repo1/branch1\n * [new branch]      branch2       -> repo1/branch2\n\nSo the branches in repo1 will be available in repo2 as remote/repo1/branch1, \nremote/repo1/branch2, ...\n\n> Christian Couder also mentioned the git-replace command, how to stitch\n> with it?\n\nFirst you need to create a commit that will replace commit N, let's call it \nN' and after that you can use \"git replace N N'\". So the complex part is to \ncreate N'.\n\nYou want N' to have the same content as N but to have M as parent. So you \ncould do something like the following:\n\n(We suppose that commits A to M are in branch1 and that you are in the root \ndirectory of your repo2 working directory.)\n\n$ git checkout -b repo1-branch1 remote/repo1/branch1\n$ git checkout N -- .\n$ export GIT_AUTHOR_NAME=<author name of commit N>\n$ export GIT_AUTHOR_EMAIL=<author email of commit N>\n$ export GIT_AUTHOR_DATE=<date of commit N>\n$ git commit -a\n\nAnd then use the commit message from commit N, and maybe also say in the \ncommit message that it is replacement commit made to link repo1 with repo2 \nor something like that.\n\nAt this step you have created N' and you should make sure that it is exactly \nwhat you want. It should point to the same tree as N, it should have M as \nparent, ...\n\nIf everything is ok then you can use:\n\n$ git replace N HEAD\n\nAnd you should be done.\n\nRegards,\nChristian.\n"},{"id":"124588","messageId":"20091011040659.GB9021@debian.b2j","threadId":"21163","inReplyTo":"200910110436.52653.chriscool@tuxfamily.org","subject":"Re: combine git repo historically","fromName":"bill lam","fromEmail":"cbill.lam@gmail.com","sentAt":"2009-10-11T04:06:59Z","receivedAt":"2009-10-11T04:06:59Z","isPatch":false,"sender":{"key":"cbill.lam@gmail.com","avatar":null},"body":"On Sun, 11 Oct 2009, Christian Couder wrote:\n> $ git checkout -b repo1-branch1 remote/repo1/branch1\n> $ git checkout N -- .\n> ...\n> If everything is ok then you can use:\n> \n> $ git replace N HEAD\n\nThanks for detail instruction, I tested it ok except that when trying\nto checkout it reported an error\n\n  $ git checkout -b repo1-branch1 remote/oldjproject/master\n  fatal: git checkout: updating paths is incompatible with switching branches. \n  Did you intend to checkout 'remote/oldjproject/master' which can not\n  be resolved as commit?\n\nbut it ran ok by omitting that 'remote/'\n$ git checkout -b repo1-branch1 oldjproject/master\n\nDoes it need to purge the file system tree before\n  git checkout N -- .\n\nso that there will be no artifact leaved by M?\n\nI found that it is necessary to do a \n   git reset --hard (original HEAD)\n\nto complete the story. Is it correct?\n\ngit version 1.6.5.rc3.35.g3340\n\n-- \nregards,\n====================================================\nGPG key 1024D/4434BAB3 2008-08-24\ngpg --keyserver subkeys.pgp.net --recv-keys 4434BAB3\n"},{"id":"124592","messageId":"m31vlagvtw.fsf@localhost.localdomain","threadId":"21163","inReplyTo":"200910110436.52653.chriscool@tuxfamily.org","subject":"Re: combine git repo historically","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-10-11T08:48:17Z","receivedAt":"2009-10-11T08:48:17Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Christian Couder <chriscool@tuxfamily.org> writes:\n\n> On Saturday 10 October 2009, bill lam wrote:\n\n> > Christian Couder also mentioned the git-replace command, how to stitch\n> > with it?\n> \n> First you need to create a commit that will replace commit N, let's call it \n> N' and after that you can use \"git replace N N'\". So the complex part is to \n> create N'.\n> \n> You want N' to have the same content as N but to have M as parent. So you \n> could do something like the following:\n> \n> (We suppose that commits A to M are in branch1 and that you are in the root \n> directory of your repo2 working directory.)\n> \n> $ git checkout -b repo1-branch1 remote/repo1/branch1\n> $ git checkout N -- .\n> $ export GIT_AUTHOR_NAME=<author name of commit N>\n> $ export GIT_AUTHOR_EMAIL=<author email of commit N>\n> $ export GIT_AUTHOR_DATE=<date of commit N>\n> $ git commit -a\n> \n> And then use the commit message from commit N, and maybe also say in the \n> commit message that it is replacement commit made to link repo1 with repo2 \n> or something like that.\n\nI think simpler solution would be to use plumbing for that.  First\nsave commit to be replaced in a (text) file:\n\n $ git cat-file commit N > COMMIT_N\n\nIf you want to edit only commit message and perhaps parentage (like I\nthink in this case), you need to simply edit COMMIT_N file, and modify\n(or add) 'parent' header(s), which is between 'tree' and 'author'\nheader.\n\nThen put modified commit in repository object database\n\n $ git hash-object -t commit -w COMMIT_N\n \n> At this step you have created N' and you should make sure that it is exactly \n> what you want. It should point to the same tree as N, it should have M as \n> parent, ...\n> \n> If everything is ok then you can use:\n> \n> $ git replace N HEAD\n\nAnd then do\n\n $ git replace N NEW_N\n\nwhere N is _SHA-1_ of original comit (\"git rev-parse --verify N^0\"),\nand NEW_N is SHA-1 of replacement commit, as written by git-hash-object.\n \n> And you should be done.\n\nBut I haven't tested this. YMMV.\n\nSee also my answer here: \nhttp://stackoverflow.com/questions/1220557/how-do-i-prepend-history-to-a-git-repo/1547490#1547490\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"124595","messageId":"m2bpkes287.fsf@igel.home","threadId":"21163","inReplyTo":"200910110436.52653.chriscool@tuxfamily.org","subject":"Re: combine git repo historically","fromName":"Andreas Schwab","fromEmail":"schwab@linux-m68k.org","sentAt":"2009-10-11T09:34:48Z","receivedAt":"2009-10-11T09:34:48Z","isPatch":false,"sender":{"key":"schwab@linux-m68k.org","avatar":"https://avatars.githubusercontent.com/u/2175493?v=4"},"body":"Christian Couder <chriscool@tuxfamily.org> writes:\n\n> You want N' to have the same content as N but to have M as parent. So you \n> could do something like the following:\n>\n> (We suppose that commits A to M are in branch1 and that you are in the root \n> directory of your repo2 working directory.)\n>\n> $ git checkout -b repo1-branch1 remote/repo1/branch1\n> $ git checkout N -- .\n> $ export GIT_AUTHOR_NAME=<author name of commit N>\n> $ export GIT_AUTHOR_EMAIL=<author email of commit N>\n> $ export GIT_AUTHOR_DATE=<date of commit N>\n> $ git commit -a\n\nIsn't that what git cherry-pick does?\n\nAndreas.\n\n-- \nAndreas Schwab, schwab@linux-m68k.org\nGPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5\n\"And now for something completely different.\"\n"},{"id":"124598","messageId":"200910111211.56011.chriscool@tuxfamily.org","threadId":"21163","inReplyTo":"20091011040659.GB9021@debian.b2j","subject":"Re: combine git repo historically","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-10-11T10:11:55Z","receivedAt":"2009-10-11T10:11:55Z","isPatch":false,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Sunday 11 October 2009, bill lam wrote:\n> On Sun, 11 Oct 2009, Christian Couder wrote:\n> > $ git checkout -b repo1-branch1 remote/repo1/branch1\n> > $ git checkout N -- .\n> > ...\n> > If everything is ok then you can use:\n> >\n> > $ git replace N HEAD\n>\n> Thanks for detail instruction, I tested it ok except that when trying\n> to checkout it reported an error\n>\n>   $ git checkout -b repo1-branch1 remote/oldjproject/master\n>   fatal: git checkout: updating paths is incompatible with switching\n> branches. Did you intend to checkout 'remote/oldjproject/master' which\n> can not be resolved as commit?\n>\n> but it ran ok by omitting that 'remote/'\n> $ git checkout -b repo1-branch1 oldjproject/master\n>\n> Does it need to purge the file system tree before\n>   git checkout N -- .\n>\n> so that there will be no artifact leaved by M?\n\nYeah, perhaps, I forgot that there could be some files added and other files \nremoved between M and N.\n\nIf you remove everything (except the .git directory of course), then doing:\n\n$ git checkout N -- .\n$ git add .\n$ export GIT_AUTHOR_NAME=<author name of commit N>\n$ export GIT_AUTHOR_EMAIL=<author email of commit N>\n$ export GIT_AUTHOR_DATE=<date of commit N>\n$ git commit\n\nshould do the trick if I am not missing something which may very well be the \ncase.\n\nSo perhaps it is easier to use Jakub's suggestion instead.\n\n> I found that it is necessary to do a\n>    git reset --hard (original HEAD)\n>\n> to complete the story. Is it correct?\n\nYes, you should go back to your orginal branch at the end.\n\nRegards,\nChristian.\n"},{"id":"124607","messageId":"200910111507.06926.j.sixt@viscovery.net","threadId":"21163","inReplyTo":"m31vlagvtw.fsf@localhost.localdomain","subject":"Re: combine git repo historically","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2009-10-11T13:07:06Z","receivedAt":"2009-10-11T13:07:06Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Sonntag, 11. Oktober 2009, Jakub Narebski wrote:\n> Christian Couder <chriscool@tuxfamily.org> writes:\n> > $ git checkout -b repo1-branch1 remote/repo1/branch1\n> > $ git checkout N -- .\n> > $ export GIT_AUTHOR_NAME=<author name of commit N>\n> > $ export GIT_AUTHOR_EMAIL=<author email of commit N>\n> > $ export GIT_AUTHOR_DATE=<date of commit N>\n> > $ git commit -a\n\nThis would not preserver the committer, but in particular the committer date \nis rather important for history traversal. You really don't want to change \nit. I used a much more elaborate pipleine involving git-commit-tree because I \ndid not think about this simple procedure:\n\n>  $ git cat-file commit N > COMMIT_N\n>[ $ edit COMMIT_N  ]\n>  $ git hash-object -t commit -w COMMIT_N\n\nThanks for this tip, Jakub.\n\nChristian, one thing that worries me is that 'git cat-file commit foo' returns \nthe replacement (bar) instead of the original (foo). Is it intended? There is \nno way to retrieve the original commit using plumbing unless the replacement \nis removed. Am I right?\n\n-- Hannes\n"},{"id":"124610","messageId":"200910111543.39327.chriscool@tuxfamily.org","threadId":"21163","inReplyTo":"200910111507.06926.j.sixt@viscovery.net","subject":"Re: combine git repo historically","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2009-10-11T13:43:39Z","receivedAt":"2009-10-11T13:43:39Z","isPatch":false,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Sunday 11 October 2009, Johannes Sixt wrote:\n> On Sonntag, 11. Oktober 2009, Jakub Narebski wrote:\n> > Christian Couder <chriscool@tuxfamily.org> writes:\n> > > $ git checkout -b repo1-branch1 remote/repo1/branch1\n> > > $ git checkout N -- .\n> > > $ export GIT_AUTHOR_NAME=<author name of commit N>\n> > > $ export GIT_AUTHOR_EMAIL=<author email of commit N>\n> > > $ export GIT_AUTHOR_DATE=<date of commit N>\n> > > $ git commit -a\n>\n> This would not preserver the committer, but in particular the committer\n> date is rather important for history traversal. You really don't want to\n> change it. I used a much more elaborate pipleine involving\n> git-commit-tree because I\n>\n> did not think about this simple procedure:\n> >  $ git cat-file commit N > COMMIT_N\n> >[ $ edit COMMIT_N  ]\n> >  $ git hash-object -t commit -w COMMIT_N\n>\n> Thanks for this tip, Jakub.\n>\n> Christian, one thing that worries me is that 'git cat-file commit foo'\n> returns the replacement (bar) instead of the original (foo). Is it\n> intended? \n\nYes it is intended. \"git replace\" was designed so that the original objects \nare not replaced only when reachability traversal (prune, pack transfer and \nfsck) wants to read the commit. See:\n\nhttp://article.gmane.org/gmane.comp.version-control.git/104776/\n\n> There is no way to retrieve the original commit using plumbing \n> unless the replacement is removed. Am I right?\n\nI think you are right, but a flag could be easily added to some commands to \nretreive original objects. Or you can remove the replacement, retrieve the \nobject and then put back the replacement.\n\nBest regards,\nChristian.\n"},{"id":"124618","messageId":"200910111629.45111.jnareb@gmail.com","threadId":"21163","inReplyTo":"200910111543.39327.chriscool@tuxfamily.org","subject":"Re: combine git repo historically","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2009-10-11T14:29:44Z","receivedAt":"2009-10-11T14:29:44Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Dnia niedziela 11. października 2009 15:43, Christian Couder napisał:\n> On Sunday 11 October 2009, Johannes Sixt wrote:\n\n> > There is no way to retrieve the original commit using plumbing \n> > unless the replacement is removed. Am I right?\n> \n> I think you are right, but a flag could be easily added to some commands to \n> retreive original objects. Or you can remove the replacement, retrieve the \n> object and then put back the replacement.\n\nWouldn't it be better for this option to be option for git wrapper,\ni.e.\n\n $ git --no-replace cat-file -p N\n\nand not\n\n $ git cat-file --no-replace -p N\n\n-- \nJakub Narebski\nPoland\n"}]}