{"thread":{"id":"50982","subject":"Bug: git branch returns EXIT_SUCCESS when no branches found","startedAt":"2019-04-24T10:20:19Z","lastAt":"2019-04-24T11:11:29Z","messageCount":6,"participants":["Christoffer Stjernlöf","Junio C Hamano","SZEDER Gábor"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"374382","messageId":"875zr3iucd.fsf@xkqr.org","threadId":"50982","inReplyTo":null,"subject":"Bug: git branch returns EXIT_SUCCESS when no branches found","fromName":"Christoffer Stjernlöf","fromEmail":"a@xkqr.org","sentAt":"2019-04-24T10:13:54Z","receivedAt":"2019-04-24T10:20:19Z","isPatch":false,"sender":{"key":"a@xkqr.org","avatar":null},"body":"Dear Sirs/Madams,\n\nA common use case of git branch – for me – is to use it to test whether\na particular branch satisfies some conditions. A recent example is this:\n\n    if ! git branch \"$DEV_BRANCH\" --contains master; then\n        echo \"The development branch ($DEV_BRANCH) is not up to date\"\n        echo \"with the latest master.\"\n        exit 1\n    fi\n\nExcept this doesn't work, because git branch returns success even though\nit failed to list any branches satisfying the condition. My workaround\nhas been to rewrite the condition as\n\n    git branch \"$DEV_BRANCH\" --contains master \\\n        | grep -xE '\\* *'\"$DEV_BRANCH\"\n\nbut this is obviously not desirable in comparison.\n\nThe syntax of e.g. --contains makes it seem almost like this use case of\nmine was intended, but the exit code makes me doubt it. Is there any\nconsideration I'm missing that's a reason for not returning a failure\ncode when not matching any branches?\n\nYours faithfully,\nChris\n"},{"id":"374384","messageId":"xmqqmukf1yh9.fsf@gitster-ct.c.googlers.com","threadId":"50982","inReplyTo":"875zr3iucd.fsf@xkqr.org","subject":"Re: Bug: git branch returns EXIT_SUCCESS when no branches found","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-04-24T10:36:34Z","receivedAt":"2019-04-24T10:36:45Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"a@xkqr.org (Christoffer Stjernlöf) writes:\n\n> A common use case of git branch – for me – is to use it to test whether\n> a particular branch satisfies some conditions. A recent example is this:\n>\n>     if ! git branch \"$DEV_BRANCH\" --contains master; then\n\nThis invocation is not in line with how \"git branch\" subcommand is\ndesigned to work.\n\nThe subcommand operates in various modes (like creating a new one,\nrenaming an existing one, deleting existing one(s)), among which\nthere is a mode to \"list existing ones\".  Without an explicit option\non the command line to tell what mode the user wants (e.g. \"-d\" for\ndeleting), it defaults to the listing mode, \"git branch --list\".\n\nThe list mode can limit what is listed via different criteria, one\nof which is with a pattern that the shown branches must match, e.g.\n\n\t$ git branch --list \"cs/*\"\n\nwhich shows only the branches whose names begin with \"cs/\".  It can\nalso limit the branches whose tip commits can reach a named commit\nwith the \"--contains\".\n\n\t$ DEV_BRANCH=cs/topic\n\t$ git branch --contains master \"$DEV_BRANCH\"\n\nasks the subcommand to show only the branches that can reach the\ncommit at the tip of 'master', *AND* whose name match cs/topic.  So\nit may show the cs/topic branch (and nothing else, even there are\ncs/topic1 or cs/topic/2 branches) if and only if that branch\ncan reach the tip of 'master'.\n\nIf you want to ask \"does the tip of $DEV_BRANCH reach commit\n'master'?\", the right way would probably be to ask\n\n\tif git merge-base --is-ancestor master \"$DEV_BRANCH\"\n\tthen\n\t\techo \"master is an ancestor of $DEV_BRANCH\"\n\telse\n\t\techo \"master has commits not in $DEV_BRANCH\"\n\t\tgit --no-pager log \"master..$DEV_BRANCH\" --\n\tfi\n\n\n"},{"id":"374385","messageId":"xmqqimv31y3n.fsf@gitster-ct.c.googlers.com","threadId":"50982","inReplyTo":"xmqqmukf1yh9.fsf@gitster-ct.c.googlers.com","subject":"Re: Bug: git branch returns EXIT_SUCCESS when no branches found","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-04-24T10:44:44Z","receivedAt":"2019-04-24T10:44:50Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> The list mode ...\n> ... can\n> also limit the branches whose tip commits can reach a named commit\n> with the \"--contains\".\n>\n> \t$ DEV_BRANCH=cs/topic\n> \t$ git branch --contains master \"$DEV_BRANCH\"\n>\n> asks the subcommand to show only the branches that can reach the\n> commit at the tip of 'master', *AND* whose name match cs/topic.  So\n> it may show the cs/topic branch (and nothing else, even there are\n> cs/topic1 or cs/topic/2 branches) if and only if that branch\n> can reach the tip of 'master'.\n\nOne crucial bit is missing from my response.  In general, a git\nsubcommand that shows zero or more things in response to a request\nto list things that match criteria does *NOT* consider it an error\nto make a request that happens to produce a zero result.  The above\ncommand will exit with non-zero status if 'master' does not name a\ncommit.  But if cs/topic branch does not exist, of if the branch\ndoes not contain 'master', the command will show \"here are the\nbranches that match the criteria you gave me\" by giving no lines in\nits standard output, and exits with 0 to signal that what you see on\nthe screen indeed was computed correctly (as opposed to the command\ninternally crashing and failing to produce a result, in which case\nyou would want to be told with non-zero exit status).\n\n\n"},{"id":"374386","messageId":"871s1rissy.fsf@xkqr.org","threadId":"50982","inReplyTo":"xmqqmukf1yh9.fsf@gitster-ct.c.googlers.com","subject":"Re: Bug: git branch returns EXIT_SUCCESS when no branches found","fromName":"Christoffer Stjernlöf","fromEmail":"a@xkqr.org","sentAt":"2019-04-24T10:47:09Z","receivedAt":"2019-04-24T10:47:14Z","isPatch":false,"sender":{"key":"a@xkqr.org","avatar":null},"body":"Dear Junio,\n\nJunio C Hamano (gitster@pobox.com) 2019-04-24:\n> This invocation is not in line with how \"git branch\" subcommand is\n> designed to work.\n\nThis is fair. I completely accept a \"you're wielding it wrong\" answer!\nHowever, your explanation sounds to me like that invocation is exactly\nin line with how git branch is designed to work! What might I be\nmissing?\n\n\nJunio C Hamano (gitster@pobox.com) 2019-04-24:\n> If you want to ask \"does the tip of $DEV_BRANCH reach commit\n> 'master'?\", the right way would probably be to ask\n>\n> \tif git merge-base --is-ancestor master \"$DEV_BRANCH\"\n> \tthen\n> \t\techo \"master is an ancestor of $DEV_BRANCH\"\n> \telse\n> \t\techo \"master has commits not in $DEV_BRANCH\"B\n> \t\tgit --no-pager log \"master..$DEV_BRANCH\" --\n> \tfi\n\nThis seems like a more convenient command for my current purpose,\nalthough it's not a complete replacement for git branch. Thank you!\n\nSincerely yours,\nChristoffer\n"},{"id":"374387","messageId":"87wojjhdx7.fsf@xkqr.org","threadId":"50982","inReplyTo":"xmqqimv31y3n.fsf@gitster-ct.c.googlers.com","subject":"Re: Bug: git branch returns EXIT_SUCCESS when no branches found","fromName":"Christoffer Stjernlöf","fromEmail":"a@xkqr.org","sentAt":"2019-04-24T10:53:56Z","receivedAt":"2019-04-24T10:54:02Z","isPatch":false,"sender":{"key":"a@xkqr.org","avatar":null},"body":"Dear Junio,\n\nJunio C Hamano (gitster@pobox.com) 2019-04-24:\n> if cs/topic branch does not exist, of if the branch\n> does not contain 'master', the command will show \"here are the\n> branches that match the criteria you gave me\" by giving no lines in\n> its standard output, and exits with 0 to signal that what you see on\n> the screen indeed was computed correctly (as opposed to the command\n> internally crashing and failing to produce a result, in which case\n> you would want to be told with non-zero exit status).\n\nThank you for taking the time to elaborate on your already detailed\nanswer. I can see the concern about separating internal command errors\nfrom correctly computed results, even if those results seem to indicate\nsomething being amiss. Is this not a place where different error codes\ncan be useful?\n\nSincerely yours,\nChristoffer\n"},{"id":"374388","messageId":"20190424111123.GB8695@szeder.dev","threadId":"50982","inReplyTo":"xmqqmukf1yh9.fsf@gitster-ct.c.googlers.com","subject":"Re: Bug: git branch returns EXIT_SUCCESS when no branches found","fromName":"SZEDER Gábor","fromEmail":"szeder.dev@gmail.com","sentAt":"2019-04-24T11:11:23Z","receivedAt":"2019-04-24T11:11:29Z","isPatch":false,"sender":{"key":"szeder.dev@gmail.com","avatar":"https://avatars.githubusercontent.com/u/116324?v=4"},"body":"On Wed, Apr 24, 2019 at 07:36:34PM +0900, Junio C Hamano wrote:\n> \tif git merge-base --is-ancestor master \"$DEV_BRANCH\"\n> \tthen\n> \t\techo \"master is an ancestor of $DEV_BRANCH\"\n> \telse\n> \t\techo \"master has commits not in $DEV_BRANCH\"\n> \t\tgit --no-pager log \"master..$DEV_BRANCH\" --\n> \tfi\n\nA non-zero exit code might indicate an error in 'git merge-base'\nitself; I had basically the same if-else condition in a script of my\nown that had to check the same thing...  until once I mistyped the\nbranchname, and, well, undesired behavior ensued.  After that I\nadded one more branch to the condition like this:\n\n  git merge-base --is-ancestor master \"$DEV_BRANCH\"\n  ret=$?\n  if test $ret -gt 1\n  then\n        die \"uh-oh, git merge-base errored out\"\n  elif test $ret -eq 0\n  then\n        echo \"master is an ancestor of $DEV_BRANCH\"\n  else\n        echo \"master has commits not in $DEV_BRANCH\"\n  fi\n\n"}]}