{"thread":{"id":"11488","subject":"how to use git merge -s subtree?","startedAt":"2008-01-05T23:00:04Z","lastAt":"2008-01-08T06:57:53Z","messageCount":12,"participants":["Miklos Vajna","Sean","David Soria Parra","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"64552","messageId":"20080105230004.GY29972@genesis.frugalware.org","threadId":"11488","inReplyTo":null,"subject":"how to use git merge -s subtree?","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2008-01-05T23:00:04Z","receivedAt":"2008-01-05T23:00:04Z","isPatch":false,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"hi,\n\ni recently noticed that the subtree merge strategy is missing from\nmerge-strategies.txt an i tried to first figure out how it works. i got\nit to work, but i'm not 100% sure about i'm using it the way i'm\nsupposed to.\n\nhere is what i do:\n\n1) git remote add B /path/to/B.git\n2) git fetch\n3) mkdir B\n4) touch B/.gitignore\n5) git add B/.gitignore\n6) git commit -m \"add empty B directory\"\n7) git merge -s subtree B/master\n\nand yes, it works pretty well, but is this the right way? or is it\npossible to somehow avoid steps 3..6?\n\nthanks,\n- VMiklos\n"},{"id":"64556","messageId":"BAYC1-PASMTP12374B54BA370A1E1C6E78AE4E0@CEZ.ICE","threadId":"11488","inReplyTo":"20080105230004.GY29972@genesis.frugalware.org","subject":"Re: how to use git merge -s subtree?","fromName":"Sean","fromEmail":"seanlkml@sympatico.ca","sentAt":"2008-01-06T01:17:40Z","receivedAt":"2008-01-06T01:17:40Z","isPatch":false,"sender":{"key":"seanlkml@sympatico.ca","avatar":"https://gravatar.com/avatar/f92923f54fc08c401fc59b71829d4b89e9b8087fbba45ff87c82e6a83aee02ae?d=mp&s=160"},"body":"On Sun, 6 Jan 2008 00:00:04 +0100\nMiklos Vajna <vmiklos@frugalware.org> wrote:\n\n> i recently noticed that the subtree merge strategy is missing from\n> merge-strategies.txt an i tried to first figure out how it works. i got\n> it to work, but i'm not 100% sure about i'm using it the way i'm\n> supposed to.\n> \n> here is what i do:\n> \n> 1) git remote add B /path/to/B.git\n> 2) git fetch\n> 3) mkdir B\n> 4) touch B/.gitignore\n> 5) git add B/.gitignore\n> 6) git commit -m \"add empty B directory\"\n> 7) git merge -s subtree B/master\n> \n> and yes, it works pretty well, but is this the right way? or is it\n> possible to somehow avoid steps 3..6?\n> \n\nHi Miklos,\n\nHere's another way that is perhaps a little cleaner:\n\n$ git remote add -f B /path/to/B\n$ git merge -s ours --no-commit B/master\n$ git read-tree --prefix=sub/ -u B/master \n$ git commit -m \"subtree merged B\"\n\nThe first line creates and fetches the remote.  The second line initiates a merge, but\nstops before committing it.  The third line reads B/master into the subdirectory \"sub\",\nat which point all that remains is committing the completed merge.\n\nHTH,\nSean\n \n"},{"id":"64557","messageId":"flpac6$beg$1@ger.gmane.org","threadId":"11488","inReplyTo":"20080105230004.GY29972@genesis.frugalware.org","subject":"Re: how to use git merge -s subtree?","fromName":"David Soria Parra","fromEmail":"sn_@gmx.net","sentAt":"2008-01-06T01:20:05Z","receivedAt":"2008-01-06T01:20:05Z","isPatch":false,"sender":{"key":"sn_@gmx.net","avatar":"https://gravatar.com/avatar/b1075ecdd33ea094cbc23798fe8b95c73ec1ccf7bb213ac8260c719e2dd97b55?d=mp&s=160"},"body":"As said in IRC, subtree is not made for that as far is a understand.\n\nQuite frankly the given workflow doesnot work for me as subtree imports\nthe things into some directory that it was not supposed to merge it into\n(x/z/ instead of B).\n\n                              dsp\n"},{"id":"64558","messageId":"flpah7$beg$2@ger.gmane.org","threadId":"11488","inReplyTo":"BAYC1-PASMTP12374B54BA370A1E1C6E78AE4E0@CEZ.ICE","subject":"Re: how to use git merge -s subtree?","fromName":"David Soria Parra","fromEmail":"sn_@gmx.net","sentAt":"2008-01-06T01:22:47Z","receivedAt":"2008-01-06T01:22:47Z","isPatch":false,"sender":{"key":"sn_@gmx.net","avatar":"https://gravatar.com/avatar/b1075ecdd33ea094cbc23798fe8b95c73ec1ccf7bb213ac8260c719e2dd97b55?d=mp&s=160"},"body":"\n> Hi Miklos,\n> \n> Here's another way that is perhaps a little cleaner:\n> \n> $ git remote add -f B /path/to/B\n> $ git merge -s ours --no-commit B/master\n> $ git read-tree --prefix=sub/ -u B/master \n> $ git commit -m \"subtree merged B\"\n> \n\nhi sean,\n\nthat works perfectly but it doesn't preserve the history, does it?\n\n                    dsp\n"},{"id":"64561","messageId":"BAYC1-PASMTP01FC193EA959D148F19374AE4E0@CEZ.ICE","threadId":"11488","inReplyTo":"flpah7$beg$2@ger.gmane.org","subject":"Re: how to use git merge -s subtree?","fromName":"Sean","fromEmail":"seanlkml@sympatico.ca","sentAt":"2008-01-06T02:13:56Z","receivedAt":"2008-01-06T02:13:56Z","isPatch":false,"sender":{"key":"seanlkml@sympatico.ca","avatar":"https://gravatar.com/avatar/f92923f54fc08c401fc59b71829d4b89e9b8087fbba45ff87c82e6a83aee02ae?d=mp&s=160"},"body":"On Sun, 06 Jan 2008 02:22:47 +0100\nDavid Soria Parra <sn_@gmx.net> wrote:\n\n> > Here's another way that is perhaps a little cleaner:\n> > \n> > $ git remote add -f B /path/to/B\n> > $ git merge -s ours --no-commit B/master\n> > $ git read-tree --prefix=sub/ -u B/master \n> > $ git commit -m \"subtree merged B\"\n> \n> that works perfectly but it doesn't preserve the history, does it?\n\nDavid,\n\nYes, the reason to start with the \"--no-commit\" merge is so that the history\nis properly connected once you do the final commit step.  However, I should\nhave noted in my original message that none of the steps actually use the\nsubtree merge.  Instead they simply prepare a repository such that\nfuture merging can be done with:\n\n   $ git merge -s subtree B/master.\n\nCheers,\nSean\n"},{"id":"64563","messageId":"47803CB6.4050102@gmx.net","threadId":"11488","inReplyTo":"BAYC1-PASMTP01FC193EA959D148F19374AE4E0@CEZ.ICE","subject":"Re: how to use git merge -s subtree?","fromName":"David Soria Parra","fromEmail":"sn_@gmx.net","sentAt":"2008-01-06T02:28:06Z","receivedAt":"2008-01-06T02:28:06Z","isPatch":false,"sender":{"key":"sn_@gmx.net","avatar":"https://gravatar.com/avatar/b1075ecdd33ea094cbc23798fe8b95c73ec1ccf7bb213ac8260c719e2dd97b55?d=mp&s=160"},"body":"Sean wrote:\n>\n> David,\n>\n> Yes, the reason to start with the \"--no-commit\" merge is so that the history\n> is properly connected once you do the final commit step.  However, I should\n> have noted in my original message that none of the steps actually use the\n> subtree merge.  Instead they simply prepare a repository such that\n> future merging can be done with:\n>\n>    $ git merge -s subtree B/master.\n>\n> Cheers,\n> Sean\n\nWell yes the history is preserved, but it's not connected to the\nsubdirectory. So you cannot do git-log B/foo.c as git doesnot know where\nto search it as it thinks\nit is in /foo.c not in B/foo.c\n\nCheers\n"},{"id":"64564","messageId":"7vir277jz6.fsf@gitster.siamese.dyndns.org","threadId":"11488","inReplyTo":"47803CB6.4050102@gmx.net","subject":"Re: how to use git merge -s subtree?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-01-06T02:42:37Z","receivedAt":"2008-01-06T02:42:37Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"David Soria Parra <sn_@gmx.net> writes:\n\n> Well yes the history is preserved, but it's not connected to the\n> subdirectory. So you cannot do git-log B/foo.c as git doesnot know where\n> to search it as it thinks\n> it is in /foo.c not in B/foo.c\n\nThe thing is, what you are talking is not about the subtree\nmerge strategy, but the fundamental philosophy of git.  Asking\nfor \"the history of file B/foo.c\" does not make any sense, as\ngit never tracks history of individual files.\n\nI'll point you to one of the most important messages in the\nwhole archive of the git mailing list.\n\n http://thread.gmane.org/gmane.comp.version-control.git/27/focus=217\n"},{"id":"64569","messageId":"20080106034533.GE29972@genesis.frugalware.org","threadId":"11488","inReplyTo":"BAYC1-PASMTP12374B54BA370A1E1C6E78AE4E0@CEZ.ICE","subject":"Re: how to use git merge -s subtree?","fromName":"Miklos Vajna","fromEmail":"vmiklos@frugalware.org","sentAt":"2008-01-06T03:45:34Z","receivedAt":"2008-01-06T03:45:34Z","isPatch":false,"sender":{"key":"vmiklos@frugalware.org","avatar":"https://gravatar.com/avatar/401c1cbbb3a5d13e650c691a2c71d6fd0b80df1a01bc74d9f1972675dd58f2bd?d=mp&s=160"},"body":"On Sat, Jan 05, 2008 at 08:17:40PM -0500, Sean <seanlkml@sympatico.ca> wrote:\n> Here's another way that is perhaps a little cleaner:\n> \n> $ git remote add -f B /path/to/B\n> $ git merge -s ours --no-commit B/master\n> $ git read-tree --prefix=sub/ -u B/master \n> $ git commit -m \"subtree merged B\"\n> \n> The first line creates and fetches the remote.  The second line initiates a merge, but\n> stops before committing it.  The third line reads B/master into the subdirectory \"sub\",\n> at which point all that remains is committing the completed merge.\n\ngreat, thanks. that's more simple than mine, and this is necessary for\nthe first commit only. the rest (i hope i'm right) can be done using\njust by\n\n$ git fetch\n$ git merge -s subtree B/master\n\ndo you mind if i send a patch to add this to Documentation/howto? i\ndon't think it's trivial :)\n\nthanks,\n- VMiklos\n"},{"id":"64575","messageId":"BAYC1-PASMTP1079A31936B4563801537DAE4E0@CEZ.ICE","threadId":"11488","inReplyTo":"7vir277jz6.fsf@gitster.siamese.dyndns.org","subject":"Re: how to use git merge -s subtree?","fromName":"Sean","fromEmail":"seanlkml@sympatico.ca","sentAt":"2008-01-06T08:06:25Z","receivedAt":"2008-01-06T08:06:25Z","isPatch":false,"sender":{"key":"seanlkml@sympatico.ca","avatar":"https://gravatar.com/avatar/f92923f54fc08c401fc59b71829d4b89e9b8087fbba45ff87c82e6a83aee02ae?d=mp&s=160"},"body":"On Sat, 05 Jan 2008 18:42:37 -0800\nJunio C Hamano <gitster@pobox.com> wrote:\n\n> David Soria Parra <sn_@gmx.net> writes:\n> \n> > Well yes the history is preserved, but it's not connected to the\n> > subdirectory. So you cannot do git-log B/foo.c as git doesnot know where\n> > to search it as it thinks\n> > it is in /foo.c not in B/foo.c\n> \n> The thing is, what you are talking is not about the subtree\n> merge strategy, but the fundamental philosophy of git.  Asking\n> for \"the history of file B/foo.c\" does not make any sense, as\n> git never tracks history of individual files.\n\nHi Junio,\n\nObviously you are making an important point here about the way Git is designed,\nbut I think you misspoke slightly.  Asking for the history of a file does make\nsense.  Through path limiting you can ask to see just the subset of history that\ntouched a certain file or directory etc..\n\nIn a simple repo where you don't have any subtree merge, with a file /B/foo.c\nthat at some point earlier in the history was renamed from /foo.c, the command\n\"git log --follow B/foo.c\" will show changes extending back before the rename.\nHowever, that doesn't seem to work across a subtree merge.  Obviously there's\nsome technical reason for this that i'm overlooking, but on the surface the two\ncases seem similar.\n\nIt would be nice to be able to do \"gitk --follow git-gui.sh\" in git.git and\nactually see the history of that file.  As it stands now, you have to type\n\"gitk -- git-gui.sh ../git-gui.sh\".  Is there a fundamental reason Git can't\nbe taught to notice this particular type of subtree merge \"rename\" and\nsupport --follow type semantics?\n \nAt least the message you referenced from Linus leaves hope that this may be\npossible as it makes the case that this is the type of thing that you can do if\nyou avoid locking yourself into inadequate rename-tracking data structures.\n\nSean\n"},{"id":"64668","messageId":"7vlk71z6sd.fsf@gitster.siamese.dyndns.org","threadId":"11488","inReplyTo":"BAYC1-PASMTP1079A31936B4563801537DAE4E0@CEZ.ICE","subject":"Re: how to use git merge -s subtree?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-01-07T21:04:34Z","receivedAt":"2008-01-07T21:04:34Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sean <seanlkml@sympatico.ca> writes:\n\n> ...  Asking for the history of a file does make\n> sense.  Through path limiting you can ask to see just the subset of history that\n> touched a certain file or directory etc..\n\nThat's asking for the history of a _path_ (or subset defined by\npaths, as in \"what changes were made to paths under 'arch/'\"),\nwhich is very different from asking \"I have B/foo.c -- show me\nthe history of that _file_\".\n\nRemember, David stated:\n\n>> ... So you cannot do git-log B/foo.c as git doesnot know where\n>> to search it as it thinks it is in /foo.c not in B/foo.c ...\n\nNotice \"as git does not know where to search it\" part?\n\nThink --- what does that \"it\" refer to in that sentence?\n\nThe statement is not about paths.  If it were about paths, then\nthe output of \"git log B/foo.c\" does show what he wants.  The\nquestion \"git log B/foo.c\" asks is \"what change were made to the\npath at B/foo.c\".  The changes made to B/foo.c (i.e. what's\nshown with the diff headers that begin with \"--- a/B/foo.c\") are\nshown.  The changes made to foo.c are not shown.\n\nBut that is different from what David is asking.  He wants to\nknow what changes were made to B/foo.c or to foo.c, and wants to\nmake the choice between the two depend on commit.  The reason\nyou think you can pick between foo.c and B/foo.c is because\nthere is an illusion that somehow there is an i-node like file\nidentity that is kept track of, and it is preserved across\nrenames and merges.\n\nThat's keeping track of the history of a _file_.\n\nAnd as you know, git doesn't do that.\n\nWhat git does is to keep track of the history of the whole tree,\nbut prune the parts that are not interesting away when you view\nthe history.  And the pruning can be specified by _PATH_.\n\nSee the difference?\n"},{"id":"64699","messageId":"BAYC1-PASMTP152065390CFAF8C09F0B60AE480@CEZ.ICE","threadId":"11488","inReplyTo":"7vlk71z6sd.fsf@gitster.siamese.dyndns.org","subject":"Re: how to use git merge -s subtree?","fromName":"Sean","fromEmail":"seanlkml@sympatico.ca","sentAt":"2008-01-08T05:34:55Z","receivedAt":"2008-01-08T05:34:55Z","isPatch":false,"sender":{"key":"seanlkml@sympatico.ca","avatar":"https://gravatar.com/avatar/f92923f54fc08c401fc59b71829d4b89e9b8087fbba45ff87c82e6a83aee02ae?d=mp&s=160"},"body":"On Mon, 07 Jan 2008 13:04:34 -0800\nJunio C Hamano <gitster@pobox.com> wrote:\n\n> That's asking for the history of a _path_ (or subset defined by\n> paths, as in \"what changes were made to paths under 'arch/'\"),\n> which is very different from asking \"I have B/foo.c -- show me\n> the history of that _file_\".\n> \n> Remember, David stated:\n> \n> >> ... So you cannot do git-log B/foo.c as git doesnot know where\n> >> to search it as it thinks it is in /foo.c not in B/foo.c ...\n> \n> Notice \"as git does not know where to search it\" part?\n> \n> Think --- what does that \"it\" refer to in that sentence?\n> \n> The statement is not about paths.  If it were about paths, then\n> the output of \"git log B/foo.c\" does show what he wants.  The\n> question \"git log B/foo.c\" asks is \"what change were made to the\n> path at B/foo.c\".  The changes made to B/foo.c (i.e. what's\n> shown with the diff headers that begin with \"--- a/B/foo.c\") are\n> shown.  The changes made to foo.c are not shown.\n> \n> But that is different from what David is asking.  He wants to\n> know what changes were made to B/foo.c or to foo.c, and wants to\n> make the choice between the two depend on commit.  The reason\n> you think you can pick between foo.c and B/foo.c is because\n> there is an illusion that somehow there is an i-node like file\n> identity that is kept track of, and it is preserved across\n> renames and merges.\n> \n> That's keeping track of the history of a _file_.\n> \n> And as you know, git doesn't do that.\n> \n> What git does is to keep track of the history of the whole tree,\n> but prune the parts that are not interesting away when you view\n> the history.  And the pruning can be specified by _PATH_.\n> \n> See the difference?\n> \n\nJunio,\n\nThanks for taking the time to answer, I know you're busy with much more\npressing issues getting 1.5.4 out the door.  You make the distinction\nbetween paths and files quite clear, and why it's important to keep in\nmind.\n\nIn the case of the \"--follow\" option though, the user might be forgiven\nfor thinking in terms of files rather than paths.  Even the git-log\ndocumentation says for \"--follow\", \"Continue listing the history of a\nfile beyond renames\".   Which at least implies that Git knows about\nfile history, rather than just paths.\n\nIt's reasonable for a user to expect \"git log --follow B/foo.c\" to do\nThe-Right-Thing in the subtree merge case.  But I recognize that it would\nactually be rather difficult to implement, perhaps making it impractical.\n\nCheers,\nSean\n"},{"id":"64704","messageId":"7vir24x0r2.fsf@gitster.siamese.dyndns.org","threadId":"11488","inReplyTo":"BAYC1-PASMTP152065390CFAF8C09F0B60AE480@CEZ.ICE","subject":"Re: how to use git merge -s subtree?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-01-08T06:57:53Z","receivedAt":"2008-01-08T06:57:53Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sean <seanlkml@sympatico.ca> writes:\n\n> In the case of the \"--follow\" option though, the user might be forgiven\n> for thinking in terms of files rather than paths.  Even the git-log\n> documentation says for \"--follow\", \"Continue listing the history of a\n> file beyond renames\".   Which at least implies that Git knows about\n> file history, rather than just paths.\n\nBut you know git does not know nor care about \"file\" history.\n\nAnd the thing is, I just tried this:\n\n  $ git log --follow --pretty=short --stat gitk-git/gitk | head -n 20\n  commit 62ba5143ec2ab9d4083669b1b1679355e7639cd5\n  Author: Junio C Hamano <gitster@pobox.com>\n\n      Move gitk to its own subdirectory\n\n   gitk => gitk-git/gitk |    0 \n   1 files changed, 0 insertions(+), 0 deletions(-)\n\n  commit 7388bcbc5431552718dde5c3259d861d2fa75a12\n  Author: Paul Mackerras <paulus@samba.org>\n\n      gitk: Use the UI font for the diff/old version/new version radio buttons\n\n   gitk |    6 +++---\n   1 files changed, 3 insertions(+), 3 deletions(-)\n\n  commit cca5d946d692fde7ea5408a694cb4b1c97a5a838\n  Author: Paul Mackerras <paulus@samba.org>\n\n      gitk: Simplify the code for finding commits\n\nSo there is something else going on, if David actually tried to\nfollow \"B/foo\" that was subtree-merged from a parent that had it\nat toplevel \"foo\" and \"log --follow\" did not work for him.\n\nTwo things that come to mind offhand are that (1) --follow looks\nfor a path that has similar contents elsewhere only when the\npath it is following in the child disappears in the parent.  So\nif you start from B/foo that was subtree-merged (i.e. the other\nparent has foo at the top) into a parent that already had B/foo,\nit will not follow the other parent that does not have B/foo;\n(2) I do not know if the original example by David tried to use\n\"-n $count\" offhand, but it seems that currently --follow does\nnot play well with -n (try the above gitk-git/gitk without\npiping the result into \"head -n 20\" but instead by limiting with\n\"git log -3 --follow ...\"); if that is the case that definitely\nis a bug.\n"}]}