{"thread":{"id":"33578","subject":"git fetch refs and tags","startedAt":"2013-04-23T10:53:41Z","lastAt":"2013-04-24T07:45:08Z","messageCount":7,"participants":["Jan Weitzel","Johan Herland","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"215203","messageId":"1366714421.2899.10.camel@lws-weitzel","threadId":"33578","inReplyTo":null,"subject":"git fetch refs and tags","fromName":"Jan Weitzel","fromEmail":"j.weitzel@phytec.de","sentAt":"2013-04-23T10:53:41Z","receivedAt":"2013-04-23T10:53:41Z","isPatch":false,"sender":{"key":"j.weitzel@phytec.de","avatar":null},"body":"Hello,\nI have the following problem: I have 2 bare git repositories one has\nseveral branches and tags.\nIf I try this in the second repository:\ngit fetch -f ../main.git refs/heads/master:refs/heads/master \nI'm getting also tags from other branches, if I have an old object from\none of the other branches.\nI would expect to have only tags pointing to master ref. (Although the\nman pages points to the behaviour regarding dangling objects). Is there\na way to avoid this? I only find --no-tags which results in having no\ntags at all. Or need I git purge to remove the old objects first?\nMy goal is to fetch only specific branches and the related tags.\n\nJan\n"},{"id":"215205","messageId":"CALKQrge2vHqA1HitpdJKYQu0KY5+XkFdrN_Gg254gW_ih57o=Q@mail.gmail.com","threadId":"33578","inReplyTo":"1366714421.2899.10.camel@lws-weitzel","subject":"Re: git fetch refs and tags","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2013-04-23T11:25:29Z","receivedAt":"2013-04-23T11:25:29Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Tue, Apr 23, 2013 at 12:53 PM, Jan Weitzel <J.Weitzel@phytec.de> wrote:\n> Hello,\n> I have the following problem: I have 2 bare git repositories one has\n> several branches and tags.\n> If I try this in the second repository:\n> git fetch -f ../main.git refs/heads/master:refs/heads/master\n> I'm getting also tags from other branches, if I have an old object from\n> one of the other branches.\n> I would expect to have only tags pointing to master ref. (Although the\n> man pages points to the behaviour regarding dangling objects). Is there\n> a way to avoid this? I only find --no-tags which results in having no\n> tags at all. Or need I git purge to remove the old objects first?\n> My goal is to fetch only specific branches and the related tags.\n\nAFAIK, Git should only auto-follow tags that are reachable from the\nbranches you fetch (in this case master). Are you saying that you get\ntags pointing to other history that is NOT reachable from the master\nbranch? (i.e. are you getting tags for which \"git merge-base $tag\nmaster\" is not equal to \"git rev-parse $tag\")?\n\nRe-reading the man page, I do see the following:\n\n\"if the repository has objects that are pointed by remote tags that it\ndoes not yet have, then fetch those missing tags. If the other end has\ntags that point at branches you are not interested in, you will not\nget them.\"\n\nThis can be interpreted as saying that even unreachable objects in\nyour local repo that are pointed to by some remote tag will cause that\ntag to be fetched, and in effect resuscitate the\npreviously-unreachable object. If this is indeed how it works, I would\nbe tempted to label this a bug in the auto-following behavior, as it's\nprobably not what most people would expect. In that case, yes, you\nshould be able to get your desired behavior by first purging all\nunreachable objects. Something like \"git gc --prune=now\" should do the\njob.\n\nHope this helps,\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"215207","messageId":"1366717552.2899.17.camel@lws-weitzel","threadId":"33578","inReplyTo":"CALKQrge2vHqA1HitpdJKYQu0KY5+XkFdrN_Gg254gW_ih57o=Q@mail.gmail.com","subject":"Re: git fetch refs and tags","fromName":"Jan Weitzel","fromEmail":"j.weitzel@phytec.de","sentAt":"2013-04-23T11:45:52Z","receivedAt":"2013-04-23T11:45:52Z","isPatch":false,"sender":{"key":"j.weitzel@phytec.de","avatar":null},"body":"Am Dienstag, den 23.04.2013, 13:25 +0200 schrieb Johan Herland:\n> On Tue, Apr 23, 2013 at 12:53 PM, Jan Weitzel <J.Weitzel@phytec.de> wrote:\n> > Hello,\n> > I have the following problem: I have 2 bare git repositories one has\n> > several branches and tags.\n> > If I try this in the second repository:\n> > git fetch -f ../main.git refs/heads/master:refs/heads/master\n> > I'm getting also tags from other branches, if I have an old object from\n> > one of the other branches.\n> > I would expect to have only tags pointing to master ref. (Although the\n> > man pages points to the behaviour regarding dangling objects). Is there\n> > a way to avoid this? I only find --no-tags which results in having no\n> > tags at all. Or need I git purge to remove the old objects first?\n> > My goal is to fetch only specific branches and the related tags.\n> \n> AFAIK, Git should only auto-follow tags that are reachable from the\n> branches you fetch (in this case master). Are you saying that you get\n> tags pointing to other history that is NOT reachable from the master\n> branch? (i.e. are you getting tags for which \"git merge-base $tag\n> master\" is not equal to \"git rev-parse $tag\")?\n> \nexactly. I reproduced it by coping a object from an other branch to the\nlocale repository. This results in fetching the not reachable tags.\n\n> Re-reading the man page, I do see the following:\n> \n> \"if the repository has objects that are pointed by remote tags that it\n> does not yet have, then fetch those missing tags. If the other end has\n> tags that point at branches you are not interested in, you will not\n> get them.\"\n> \n> This can be interpreted as saying that even unreachable objects in\n> your local repo that are pointed to by some remote tag will cause that\n> tag to be fetched, and in effect resuscitate the\n> previously-unreachable object. If this is indeed how it works, I would\n> be tempted to label this a bug in the auto-following behavior, as it's\n> probably not what most people would expect. In that case, yes, you\nYes my first understanding of auto-following behaviour was wrong ;)\n> should be able to get your desired behavior by first purging all\n> unreachable objects. Something like \"git gc --prune=now\" should do the\n> job.\nBecause I run this by scripts is there a way without porcelain commands?\nI saw even git prune is one.\n> \n> Hope this helps,\nThanks\nJan\n> \n> ...Johan\n> \n"},{"id":"215216","messageId":"CALKQrgf2UxC3h2ApJ-ug=B-Pg_gxf_4=FV1MSmfdt9S2Ut5YFA@mail.gmail.com","threadId":"33578","inReplyTo":"1366717552.2899.17.camel@lws-weitzel","subject":"Re: git fetch refs and tags","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2013-04-23T12:16:18Z","receivedAt":"2013-04-23T12:16:18Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Tue, Apr 23, 2013 at 1:45 PM, Jan Weitzel <J.Weitzel@phytec.de> wrote:\n> Am Dienstag, den 23.04.2013, 13:25 +0200 schrieb Johan Herland:\n>> On Tue, Apr 23, 2013 at 12:53 PM, Jan Weitzel <J.Weitzel@phytec.de> wrote:\n>> > Hello,\n>> > I have the following problem: I have 2 bare git repositories one has\n>> > several branches and tags.\n>> > If I try this in the second repository:\n>> > git fetch -f ../main.git refs/heads/master:refs/heads/master\n>> > I'm getting also tags from other branches, if I have an old object from\n>> > one of the other branches.\n>> > I would expect to have only tags pointing to master ref. (Although the\n>> > man pages points to the behaviour regarding dangling objects). Is there\n>> > a way to avoid this? I only find --no-tags which results in having no\n>> > tags at all. Or need I git purge to remove the old objects first?\n>> > My goal is to fetch only specific branches and the related tags.\n>>\n>> AFAIK, Git should only auto-follow tags that are reachable from the\n>> branches you fetch (in this case master). Are you saying that you get\n>> tags pointing to other history that is NOT reachable from the master\n>> branch? (i.e. are you getting tags for which \"git merge-base $tag\n>> master\" is not equal to \"git rev-parse $tag\")?\n>>\n> exactly. I reproduced it by coping a object from an other branch to the\n> locale repository. This results in fetching the not reachable tags.\n>\n>> Re-reading the man page, I do see the following:\n>>\n>> \"if the repository has objects that are pointed by remote tags that it\n>> does not yet have, then fetch those missing tags. If the other end has\n>> tags that point at branches you are not interested in, you will not\n>> get them.\"\n>>\n>> This can be interpreted as saying that even unreachable objects in\n>> your local repo that are pointed to by some remote tag will cause that\n>> tag to be fetched, and in effect resuscitate the\n>> previously-unreachable object. If this is indeed how it works, I would\n>> be tempted to label this a bug in the auto-following behavior, as it's\n>> probably not what most people would expect. In that case, yes, you\n>\n> Yes my first understanding of auto-following behaviour was wrong ;)\n>\n>> should be able to get your desired behavior by first purging all\n>> unreachable objects. Something like \"git gc --prune=now\" should do the\n>> job.\n>\n> Because I run this by scripts is there a way without porcelain commands?\n> I saw even git prune is one.\n\ngit prune is not sufficient, since it only removes _unpacked_ and\nunreachable objects. You first need to create a new pack that does not\ncontain unreachable objects (git rebase -a -d), but before that you\nalso need to expire reflogs (git reflog expire ...) and you should\nalso prune packed refs (git pack-refs --prune ...).\n\nIn short there are a number of commands you need to run, and in the\nright order and with the right options, but \"git gc --prune=now\" is\nbasically just a wrapper around these that Does The Right Thing(tm). I\nwould just use that instead.\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"215232","messageId":"7vsj2hl2c7.fsf@alter.siamese.dyndns.org","threadId":"33578","inReplyTo":"1366714421.2899.10.camel@lws-weitzel","subject":"Re: git fetch refs and tags","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2013-04-23T14:59:52Z","receivedAt":"2013-04-23T14:59:52Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jan Weitzel <J.Weitzel@phytec.de> writes:\n\n> Hello,\n> I have the following problem: I have 2 bare git repositories one has\n> several branches and tags.\n> If I try this in the second repository:\n> git fetch -f ../main.git refs/heads/master:refs/heads/master \n> I'm getting also tags from other branches, if I have an old object from\n> one of the other branches.\n> I would expect to have only tags pointing to master ref.\n\nA tag that points at a commit that is reachable from 'master' will\nbe followed, not just pointing _at_ 'master'.  For example, when\nyour 'master' is a bit beyond v1.2 release, it is likely you will\nalso get v1.1 and v1.0 tags (if your release structure is such that\nnew release contains everything old releases had).\n"},{"id":"215272","messageId":"CALKQrgdTyD+jX+2WqxArC2HPtWSLrhqL3YQ6M9-oYDvYSqU_-g@mail.gmail.com","threadId":"33578","inReplyTo":"7vsj2hl2c7.fsf@alter.siamese.dyndns.org","subject":"Re: git fetch refs and tags","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2013-04-23T20:50:33Z","receivedAt":"2013-04-23T20:50:33Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Tue, Apr 23, 2013 at 4:59 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Jan Weitzel <J.Weitzel@phytec.de> writes:\n>\n>> Hello,\n>> I have the following problem: I have 2 bare git repositories one has\n>> several branches and tags.\n>> If I try this in the second repository:\n>> git fetch -f ../main.git refs/heads/master:refs/heads/master\n>> I'm getting also tags from other branches, if I have an old object from\n>> one of the other branches.\n>> I would expect to have only tags pointing to master ref.\n>\n> A tag that points at a commit that is reachable from 'master' will\n> be followed, not just pointing _at_ 'master'.  For example, when\n> your 'master' is a bit beyond v1.2 release, it is likely you will\n> also get v1.1 and v1.0 tags (if your release structure is such that\n> new release contains everything old releases had).\n\nThat is all true, and behaves as expected. However, what Jan is observing\nis (I believe) equivalent to the following:\n\nRemote repo:\n\n  o---o---o---o <---- master, tag: spam\n   \\      ^---- tag: eggs\n    \\\n     o---o---o <---- tag: sausage\n\nLocal repo:\n\n  o---o\n   \\  ^---- master\n    \\\n     o---o---o (unreachable)\n\nNow, when Jan fetches master, he gets the new master, plus tags spam and\neggs (as expected), but he ALSO gets tag sausage, which he _shouldn't_\nget, since it is not reachable from master (hence not part of the fetched\nhistory). The following session demonstrates the problem using the above\nexample:\n\n# Prepare history in repo1\n$ git init repo1\nInitialized empty Git repository in /home/johan/git/repo1/.git/\n$ cd repo1/\n$ echo foo>foo\n$ git add foo\n$ git commit -m a\n[master (root-commit) 92f92ec] a\n 1 file changed, 1 insertion(+)\n create mode 100644 foo\n$ echo bar >> foo\n$ git commit -am b\n[master e90d835] b\n 1 file changed, 1 insertion(+)\n$ echo baz >> foo\n$ git commit -am c\n[master 09e4bb2] c\n 1 file changed, 1 insertion(+)\n$ echo xyzzy >> foo\n$ git commit -am d\n[master 13ce4fb] d\n 1 file changed, 1 insertion(+)\n$ git checkout -b side HEAD~3\nSwitched to a new branch 'side'\n$ echo side >> foo\n$ git commit -am side\n[side 7294fc9] side\n 1 file changed, 1 insertion(+)\n\n# Copy history to repo2, and make most of it unreachable\n$ cd ..\n$ git clone repo1 repo2\nCloning into 'repo2'...\ndone.\n$ cd repo2/\n$ git checkout -b master origin/master~2\nSwitched to a new branch 'master'\n$ git remote rm origin\n$ git branch -D side\nDeleted branch side (was 7294fc9).\n$ git show-ref\ne90d8356350e4f2fd5e7bfb3a0327e2fa6115c2a refs/heads/master\n\n# Create tags in repo1\n$ cd ../repo1/\n$ git checkout master\nSwitched to branch 'master'\n$ git tag spam master\n$ git tag eggs master^\n$ git tag sausage side\n$ git branch -D side\nDeleted branch side (was 7294fc9).\n$ git show-ref\n13ce4fbc1761562a36f755b081b0d44b657c25a9 refs/heads/master\n09e4bb21112b0f0acb82ed3b0fd6af9c685c3799 refs/tags/eggs\n7294fc90fc1fbd1dd941c8999518d4a4b57048b4 refs/tags/sausage\n13ce4fbc1761562a36f755b081b0d44b657c25a9 refs/tags/spam\n\n# Fetch master into repo2\n$ cd ../repo2\n$ git checkout -b foo\nSwitched to a new branch 'foo'\n$ git fetch -f ../repo1 refs/heads/master:refs/heads/master\nFrom ../repo1\n   e90d835..13ce4fb  master     -> master\n * [new tag]         eggs       -> eggs\n * [new tag]         sausage    -> sausage\n * [new tag]         spam       -> spam\n\n# See that tag sausage was fetched even though it's not reachable from master\n$ git show-ref\ne90d8356350e4f2fd5e7bfb3a0327e2fa6115c2a refs/heads/foo\n13ce4fbc1761562a36f755b081b0d44b657c25a9 refs/heads/master\n09e4bb21112b0f0acb82ed3b0fd6af9c685c3799 refs/tags/eggs\n7294fc90fc1fbd1dd941c8999518d4a4b57048b4 refs/tags/sausage\n13ce4fbc1761562a36f755b081b0d44b657c25a9 refs/tags/spam\n$ git log --graph --decorate --all --oneline\n* 7294fc9 (tag: sausage) side\n| * 13ce4fb (tag: spam, master) d\n| * 09e4bb2 (tag: eggs) c\n| * e90d835 (HEAD, foo) b\n|/\n* 92f92ec a\n\n\nHave fun! :)\n\n...Johan\n\n--\nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"215294","messageId":"1366789508.3672.0.camel@lws-weitzel","threadId":"33578","inReplyTo":"CALKQrgdTyD+jX+2WqxArC2HPtWSLrhqL3YQ6M9-oYDvYSqU_-g@mail.gmail.com","subject":"Re: git fetch refs and tags","fromName":"Jan Weitzel","fromEmail":"j.weitzel@phytec.de","sentAt":"2013-04-24T07:45:08Z","receivedAt":"2013-04-24T07:45:08Z","isPatch":false,"sender":{"key":"j.weitzel@phytec.de","avatar":null},"body":"Am Dienstag, den 23.04.2013, 22:50 +0200 schrieb Johan Herland:\n> On Tue, Apr 23, 2013 at 4:59 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> > Jan Weitzel <J.Weitzel@phytec.de> writes:\n> >\n> >> Hello,\n> >> I have the following problem: I have 2 bare git repositories one has\n> >> several branches and tags.\n> >> If I try this in the second repository:\n> >> git fetch -f ../main.git refs/heads/master:refs/heads/master\n> >> I'm getting also tags from other branches, if I have an old object from\n> >> one of the other branches.\n> >> I would expect to have only tags pointing to master ref.\n> >\n> > A tag that points at a commit that is reachable from 'master' will\n> > be followed, not just pointing _at_ 'master'.  For example, when\n> > your 'master' is a bit beyond v1.2 release, it is likely you will\n> > also get v1.1 and v1.0 tags (if your release structure is such that\n> > new release contains everything old releases had).\n> \n> That is all true, and behaves as expected. However, what Jan is observing\n> is (I believe) equivalent to the following:\n> \nThank you for the explanation, you show exactly what I mean :)\nJan\n> Remote repo:\n> \n>   o---o---o---o <---- master, tag: spam\n>    \\      ^---- tag: eggs\n>     \\\n>      o---o---o <---- tag: sausage\n> \n> Local repo:\n> \n>   o---o\n>    \\  ^---- master\n>     \\\n>      o---o---o (unreachable)\n> \n> Now, when Jan fetches master, he gets the new master, plus tags spam and\n> eggs (as expected), but he ALSO gets tag sausage, which he _shouldn't_\n> get, since it is not reachable from master (hence not part of the fetched\n> history). The following session demonstrates the problem using the above\n> example:\n> \n> # Prepare history in repo1\n> $ git init repo1\n> Initialized empty Git repository in /home/johan/git/repo1/.git/\n> $ cd repo1/\n> $ echo foo>foo\n> $ git add foo\n> $ git commit -m a\n> [master (root-commit) 92f92ec] a\n>  1 file changed, 1 insertion(+)\n>  create mode 100644 foo\n> $ echo bar >> foo\n> $ git commit -am b\n> [master e90d835] b\n>  1 file changed, 1 insertion(+)\n> $ echo baz >> foo\n> $ git commit -am c\n> [master 09e4bb2] c\n>  1 file changed, 1 insertion(+)\n> $ echo xyzzy >> foo\n> $ git commit -am d\n> [master 13ce4fb] d\n>  1 file changed, 1 insertion(+)\n> $ git checkout -b side HEAD~3\n> Switched to a new branch 'side'\n> $ echo side >> foo\n> $ git commit -am side\n> [side 7294fc9] side\n>  1 file changed, 1 insertion(+)\n> \n> # Copy history to repo2, and make most of it unreachable\n> $ cd ..\n> $ git clone repo1 repo2\n> Cloning into 'repo2'...\n> done.\n> $ cd repo2/\n> $ git checkout -b master origin/master~2\n> Switched to a new branch 'master'\n> $ git remote rm origin\n> $ git branch -D side\n> Deleted branch side (was 7294fc9).\n> $ git show-ref\n> e90d8356350e4f2fd5e7bfb3a0327e2fa6115c2a refs/heads/master\n> \n> # Create tags in repo1\n> $ cd ../repo1/\n> $ git checkout master\n> Switched to branch 'master'\n> $ git tag spam master\n> $ git tag eggs master^\n> $ git tag sausage side\n> $ git branch -D side\n> Deleted branch side (was 7294fc9).\n> $ git show-ref\n> 13ce4fbc1761562a36f755b081b0d44b657c25a9 refs/heads/master\n> 09e4bb21112b0f0acb82ed3b0fd6af9c685c3799 refs/tags/eggs\n> 7294fc90fc1fbd1dd941c8999518d4a4b57048b4 refs/tags/sausage\n> 13ce4fbc1761562a36f755b081b0d44b657c25a9 refs/tags/spam\n> \n> # Fetch master into repo2\n> $ cd ../repo2\n> $ git checkout -b foo\n> Switched to a new branch 'foo'\n> $ git fetch -f ../repo1 refs/heads/master:refs/heads/master\n> From ../repo1\n>    e90d835..13ce4fb  master     -> master\n>  * [new tag]         eggs       -> eggs\n>  * [new tag]         sausage    -> sausage\n>  * [new tag]         spam       -> spam\n> \n> # See that tag sausage was fetched even though it's not reachable from master\n> $ git show-ref\n> e90d8356350e4f2fd5e7bfb3a0327e2fa6115c2a refs/heads/foo\n> 13ce4fbc1761562a36f755b081b0d44b657c25a9 refs/heads/master\n> 09e4bb21112b0f0acb82ed3b0fd6af9c685c3799 refs/tags/eggs\n> 7294fc90fc1fbd1dd941c8999518d4a4b57048b4 refs/tags/sausage\n> 13ce4fbc1761562a36f755b081b0d44b657c25a9 refs/tags/spam\n> $ git log --graph --decorate --all --oneline\n> * 7294fc9 (tag: sausage) side\n> | * 13ce4fb (tag: spam, master) d\n> | * 09e4bb2 (tag: eggs) c\n> | * e90d835 (HEAD, foo) b\n> |/\n> * 92f92ec a\n> \n> \n> Have fun! :)\n> \n> ...Johan\n> \n> --\n> Johan Herland, <johan@herland.net>\n> www.herland.net\n"}]}