{"thread":{"id":"29130","subject":"best way to fastforward all tracking branches after a fetch","startedAt":"2011-12-10T12:26:32Z","lastAt":"2012-01-18T01:50:45Z","messageCount":27,"participants":["Gelonida N","Sitaram Chamarty","Martin Langhoff","Jakub Narebski","Andreas Schwab","Stefan Haller","Hallvard B Furuseth","Jeff King","Junio C Hamano","Hallvard Breien Furuseth","Nazri Ramliy"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"180784","messageId":"jbvj5o$skt$1@dough.gmane.org","threadId":"29130","inReplyTo":null,"subject":"best way to fastforward all tracking branches after a fetch","fromName":"Gelonida N","fromEmail":"gelonida@gmail.com","sentAt":"2011-12-10T12:26:32Z","receivedAt":"2011-12-10T12:26:32Z","isPatch":false,"sender":{"key":"gelonida@gmail.com","avatar":null},"body":"Hi,\n\nWhat is the best way to fastforward all fastforwardable tracking\nbranches after a git fetch?\n"},{"id":"180815","messageId":"20111211022218.GA22749@sita-lt.atc.tcs.com","threadId":"29130","inReplyTo":"jbvj5o$skt$1@dough.gmane.org","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Sitaram Chamarty","fromEmail":"sitaramc@gmail.com","sentAt":"2011-12-11T02:22:18Z","receivedAt":"2011-12-11T02:22:18Z","isPatch":false,"sender":{"key":"sitaramc@gmail.com","avatar":"https://avatars.githubusercontent.com/u/43316?v=4"},"body":"On Sat, Dec 10, 2011 at 01:26:32PM +0100, Gelonida N wrote:\n> Hi,\n> \n> What is the best way to fastforward all fastforwardable tracking\n> branches after a git fetch?\n\nI dont think there is a single command to do it for *all*\nbranches, but for any particular branch, this should work:\n\n    git merge --ff-only @{u}\n\nSo what you want would boil down to this script (untested):\n\n    #!/bin/bash\n    git status --porcelain -uno | grep . && {echo dirty tree, exiting...; exit 1; }\n\n    for b in `git for-each-ref '--format=%(refname:short)' refs/heads`\n    do\n        git checkout $b\n        git merge --ff-only @{u}\n    done\n"},{"id":"180822","messageId":"jc2l2a$som$1@dough.gmane.org","threadId":"29130","inReplyTo":"20111211022218.GA22749@sita-lt.atc.tcs.com","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Gelonida N","fromEmail":"gelonida@gmail.com","sentAt":"2011-12-11T16:17:14Z","receivedAt":"2011-12-11T16:17:14Z","isPatch":false,"sender":{"key":"gelonida@gmail.com","avatar":null},"body":"On 12/11/2011 03:22 AM, Sitaram Chamarty wrote:\n> On Sat, Dec 10, 2011 at 01:26:32PM +0100, Gelonida N wrote:\n>> Hi,\n>>\n>> What is the best way to fastforward all fastforwardable tracking\n>> branches after a git fetch?\n> \n> I dont think there is a single command to do it for *all*\n> branches, but for any particular branch, this should work:\n\nA tiny script is fine. I didn't really expect the magic command.\n\nCurrently I'm using one script per repository, which hard coded the\nbranches,\nthat I want to fast-forward (checking them out and doing a git-pull)\n\n> \n>     git merge --ff-only @{u}\n> \nThanks, '--ff=only @{u}'  is already the first improvement for my script.\n\n\n> So what you want would boil down to this script (untested):\n> \n>     #!/bin/bash\n>     git status --porcelain -uno | grep . && {echo dirty tree, exiting...; exit 1; }\n> \n>     for b in `git for-each-ref '--format=%(refname:short)' refs/heads`\n>     do\n>         git checkout $b\n>         git merge --ff-only @{u}\n>     done\n\n\n\nIs there no way to distinguish tracking branches from other branches?\nwithout checking them out?\n\nIn order to save time I'd like to avoid checking out local branches.\n\nIdeally I would even like to avoid checking out branches, which don't\nneed to be forwarded.\n\n\nI also had to remember on which branch I was in order to avoid, that I\nam at a random branch after running the script.\n\nI could imagine something like my snippet below , though I guess,\nthere's something more elegant.\n\ngit stash\nmybranch=`git branch | sed -n 's/\\* *//p'`\n# do_script . . .\ngit checkout $mybranch\ngit stash apply\n"},{"id":"180823","messageId":"CACPiFCKNxCHRvom8Qy2PErE92tCmYJhqB+FSawCsFSsdGUFH6Q@mail.gmail.com","threadId":"29130","inReplyTo":"jbvj5o$skt$1@dough.gmane.org","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2011-12-11T16:27:58Z","receivedAt":"2011-12-11T16:27:58Z","isPatch":false,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On Sat, Dec 10, 2011 at 7:26 AM, Gelonida N <gelonida@gmail.com> wrote:\n> What is the best way to fastforward all fastforwardable tracking\n> branches after a git fetch?\n\nIt'd be a great addition to git fetch ;-)\n\n\nm\n-- \n martin.langhoff@gmail.com\n martin@laptop.org -- Software Architect - OLPC\n - ask interesting questions\n - don't get distracted with shiny stuff  - working code first\n - http://wiki.laptop.org/go/User:Martinlanghoff\n"},{"id":"180824","messageId":"m3ehwbge8f.fsf@localhost.localdomain","threadId":"29130","inReplyTo":"jc2l2a$som$1@dough.gmane.org","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2011-12-11T18:22:42Z","receivedAt":"2011-12-11T18:22:42Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Don't remove people from Cc, please.\n\nGelonida N <gelonida@gmail.com> writes:\n> On 12/11/2011 03:22 AM, Sitaram Chamarty wrote:\n> > On Sat, Dec 10, 2011 at 01:26:32PM +0100, Gelonida N wrote:\n\n> > So what you want would boil down to this script (untested):\n> > \n> >     #!/bin/bash\n> >     git status --porcelain -uno | grep . && {echo dirty tree, exiting...; exit 1; }\n> > \n> >     for b in `git for-each-ref '--format=%(refname:short)' refs/heads`\n> >     do\n> >         git checkout $b\n> >         git merge --ff-only @{u}\n> >     done\n> \n> Is there no way to distinguish tracking branches from other branches?\n> without checking them out?\n> \n> In order to save time I'd like to avoid checking out local branches.\n\nYou can use 'upstream' field name in git-for-each-ref invocation,\nfor example\n\n  git for-each-ref '--format=%(refname:short) %(upstream:short)' refs/heads |\n  \tgrep -e ' [^ ]' |\n  \tsed  -e 's/ .*$//\n \nThis could probably be done using only sed -- grep is not necessary.\n\n> Ideally I would even like to avoid checking out branches, which don't\n> need to be forwarded.\n \nYou can use git-update-ref plumbing, but you would have to do the\ncheck if it does fast-forward yourself, and provide reflog message\nyourself too.\n \nSomething like\n\n  git for-each-ref '--format=%(refname) %(upstream)' |\n  while read refname upstream\n  do\n  \t# there is upstream\n  \ttest -n \"$upstream\" || break\n  \t# and if fast-forwards\n  \ttest $(git merge-base $refname $upstream) = $(git rev-parse $refname) || break\n  \tgit update-ref -m \"$message\" $refname $upstream\n  done\n\n> I also had to remember on which branch I was in order to avoid, that I\n> am at a random branch after running the script.\n> \n> I could imagine something like my snippet below , though I guess,\n> there's something more elegant.\n> \n> git stash\n> mybranch=`git branch | sed -n 's/\\* *//p'`\n> # do_script . . .\n> git checkout $mybranch\n> git stash apply\n\nDon't use git-branch in scripting.  See __git_ps1 function in\ncontrib/completion/git-completion.bash how it can be done:\n\n  b=\"$(git symbolic-ref HEAD 2>/dev/null)\" ||\n  b=\"$(git rev-parse --verify HEAD)\"\n\nNb. the second part is here only if there is possibility that you are\non detached HEAD (unnamed branch).\n\nHTH (hope that helps)\n-- \nJakub Narębski\n"},{"id":"180826","messageId":"CAMK1S_gjZSBv5ASz4GhV25TsRKuzBvZ9D7_X+bniP9K0BQQCmA@mail.gmail.com","threadId":"29130","inReplyTo":"m3ehwbge8f.fsf@localhost.localdomain","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Sitaram Chamarty","fromEmail":"sitaramc@gmail.com","sentAt":"2011-12-11T18:56:13Z","receivedAt":"2011-12-11T18:56:13Z","isPatch":false,"sender":{"key":"sitaramc@gmail.com","avatar":"https://avatars.githubusercontent.com/u/43316?v=4"},"body":"2011/12/11 Jakub Narebski <jnareb@gmail.com>:\n> Don't remove people from Cc, please.\n>\n> Gelonida N <gelonida@gmail.com> writes:\n>> On 12/11/2011 03:22 AM, Sitaram Chamarty wrote:\n>> > On Sat, Dec 10, 2011 at 01:26:32PM +0100, Gelonida N wrote:\n>\n>> > So what you want would boil down to this script (untested):\n>> >\n>> >     #!/bin/bash\n>> >     git status --porcelain -uno | grep . && {echo dirty tree, exiting...; exit 1; }\n>> >\n>> >     for b in `git for-each-ref '--format=%(refname:short)' refs/heads`\n>> >     do\n>> >         git checkout $b\n>> >         git merge --ff-only @{u}\n>> >     done\n>>\n>> Is there no way to distinguish tracking branches from other branches?\n>> without checking them out?\n>>\n>> In order to save time I'd like to avoid checking out local branches.\n>\n> You can use 'upstream' field name in git-for-each-ref invocation,\n> for example\n>\n>  git for-each-ref '--format=%(refname:short) %(upstream:short)' refs/heads |\n>        grep -e ' [^ ]' |\n>        sed  -e 's/ .*$//\n>\n> This could probably be done using only sed -- grep is not necessary.\n>\n>> Ideally I would even like to avoid checking out branches, which don't\n>> need to be forwarded.\n>\n> You can use git-update-ref plumbing, but you would have to do the\n> check if it does fast-forward yourself, and provide reflog message\n> yourself too.\n\nif it's not the currently checked-out branch, 'git branch -f foo\norigin/foo' seems to work fine.  However, it only updates the branch\nreflog, not the HEAD reflog also, naturally.\n\nFWIW...\n\n> Something like\n>\n>  git for-each-ref '--format=%(refname) %(upstream)' |\n>  while read refname upstream\n>  do\n>        # there is upstream\n>        test -n \"$upstream\" || break\n>        # and if fast-forwards\n>        test $(git merge-base $refname $upstream) = $(git rev-parse $refname) || break\n>        git update-ref -m \"$message\" $refname $upstream\n>  done\n>\n>> I also had to remember on which branch I was in order to avoid, that I\n>> am at a random branch after running the script.\n>>\n>> I could imagine something like my snippet below , though I guess,\n>> there's something more elegant.\n>>\n>> git stash\n>> mybranch=`git branch | sed -n 's/\\* *//p'`\n>> # do_script . . .\n>> git checkout $mybranch\n>> git stash apply\n>\n> Don't use git-branch in scripting.  See __git_ps1 function in\n> contrib/completion/git-completion.bash how it can be done:\n>\n>  b=\"$(git symbolic-ref HEAD 2>/dev/null)\" ||\n>  b=\"$(git rev-parse --verify HEAD)\"\n>\n> Nb. the second part is here only if there is possibility that you are\n> on detached HEAD (unnamed branch).\n>\n> HTH (hope that helps)\n> --\n> Jakub Narębski\n\n\n\n-- \nSitaram\n"},{"id":"180827","messageId":"m2hb176iiy.fsf@igel.home","threadId":"29130","inReplyTo":"m3ehwbge8f.fsf@localhost.localdomain","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Andreas Schwab","fromEmail":"schwab@linux-m68k.org","sentAt":"2011-12-11T19:00:05Z","receivedAt":"2011-12-11T19:00:05Z","isPatch":false,"sender":{"key":"schwab@linux-m68k.org","avatar":"https://avatars.githubusercontent.com/u/2175493?v=4"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Something like\n>\n>   git for-each-ref '--format=%(refname) %(upstream)' |\n>   while read refname upstream\n>   do\n>   \t# there is upstream\n>   \ttest -n \"$upstream\" || break\n>   \t# and if fast-forwards\n>   \ttest $(git merge-base $refname $upstream) = $(git rev-parse $refname) || break\n>   \tgit update-ref -m \"$message\" $refname $upstream\n>   done\n\nYou probably meant s/break/continue/.\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":"180828","messageId":"201112112053.07548.jnareb@gmail.com","threadId":"29130","inReplyTo":"m2hb176iiy.fsf@igel.home","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2011-12-11T19:53:05Z","receivedAt":"2011-12-11T19:53:05Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Andreas Schwab wrote:\n> Jakub Narebski <jnareb@gmail.com> writes:\n> \n> > Something like\n> >\n> >   git for-each-ref '--format=%(refname) %(upstream)' |\n> >   while read refname upstream\n> >   do\n> >   \t# there is upstream\n> >   \ttest -n \"$upstream\" || break\n\nHere you should probably also check if we are already up-to-date:\n\n    \ttest $(git rev-parse $upstream) = $(git rev-parse $refname) || continue\n\n> >   \t# and if fast-forwards\n> >   \ttest $(git merge-base $refname $upstream) = $(git rev-parse $refname) || break\n> >   \tgit update-ref -m \"$message\" $refname $upstream\n> >   done\n> \n> You probably meant s/break/continue/.\n\nYes, sorry about that.\n\nBTW. git-update-ref invocation can be replaced by Sitaram's suggestion:\n\n    \tgit branch -f $refname $upstream\n\n-- \nJakub Narebski\nPoland\n"},{"id":"180829","messageId":"4EE50B5A.3000706@gmail.com","threadId":"29130","inReplyTo":"m3ehwbge8f.fsf@localhost.localdomain","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Gelonida N","fromEmail":"gelonida@gmail.com","sentAt":"2011-12-11T19:58:18Z","receivedAt":"2011-12-11T19:58:18Z","isPatch":false,"sender":{"key":"gelonida@gmail.com","avatar":null},"body":"On 12/11/2011 07:22 PM, Jakub Narebski wrote:\n> Don't remove people from Cc, please.\n\nOK,\n\n> \n> Gelonida N <gelonida@gmail.com> writes:\n>> On 12/11/2011 03:22 AM, Sitaram Chamarty wrote:\n\n>>\n>> In order to save time I'd like to avoid checking out local branches.\n> \n> You can use 'upstream' field name in git-for-each-ref invocation,\n> for example\n> \n>   git for-each-ref '--format=%(refname:short) %(upstream:short)' refs/heads |\n>   \tgrep -e ' [^ ]' |\n>   \tsed  -e 's/ .*$//\n>  \nThanks\n\n\n\n> This could probably be done using only sed -- grep is not necessary.\nI think the equivalent would be:\nsed '/ [^ ]/ s/ .*$//'\n\n\n> \n>> Ideally I would even like to avoid checking out branches, which don't\n>> need to be forwarded.\n>  \n> You can use git-update-ref plumbing, but you would have to do the\n> check if it does fast-forward yourself, and provide reflog message\n> yourself too.\n>  \n\nTrue this would probably be fastest. Will read the docs a little to\nunderstand exactly what you're doing. I'm not that much used to all the\ncommands used in the script.\n\n> Something like\n> \n>   git for-each-ref '--format=%(refname) %(upstream)' |\n>   while read refname upstream\n>   do\n>   \t# there is upstream\n>   \ttest -n \"$upstream\" || break\n>   \t# and if fast-forwards\n>   \ttest $(git merge-base $refname $upstream) = $(git rev-parse $refname) || break\n>   \tgit update-ref -m \"$message\" $refname $upstream\n>   done\n> \n>> I also had to remember on which branch I was in order to avoid, that I\n>> am at a random branch after running the script.\n>>\n\n> \n> Don't use git-branch in scripting.  See __git_ps1 function in\n> contrib/completion/git-completion.bash how it can be done:\n> \n>   b=\"$(git symbolic-ref HEAD 2>/dev/null)\" ||\n>   b=\"$(git rev-parse --verify HEAD)\"\n> \n> Nb. the second part is here only if there is possibility that you are\n> on detached HEAD (unnamed branch).\n> \n> HTH (hope that helps)\n\nIt definitely helps. Thanks a lot.\nIt's always good to see how one can do better after some attempts o some\nself made clumsy scripts not suing all the features of git.\n"},{"id":"180831","messageId":"1kc4qnw.1xgi3yf14oaw7gM%lists@haller-berlin.de","threadId":"29130","inReplyTo":"jbvj5o$skt$1@dough.gmane.org","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Stefan Haller","fromEmail":"lists@haller-berlin.de","sentAt":"2011-12-11T20:14:37Z","receivedAt":"2011-12-11T20:14:37Z","isPatch":false,"sender":{"key":"lists@haller-berlin.de","avatar":null},"body":"Gelonida N <gelonida@gmail.com> wrote:\n\n> What is the best way to fastforward all fastforwardable tracking\n> branches after a git fetch?\n\nHere's a script that does this.  It isn't very well tested, I hope I\ndidn't miss any edge cases. Use at your own risk.\n\n(It doesn't fastforward the branch you're on, on the assumtion that if\nyou said git fetch instead of git pull, you probably had a reason.)\n\n========= 8< =========\n#!/bin/sh\n\ncurrentbranch=\"`git symbolic-ref HEAD 2>/dev/null`\"\n\ngit for-each-ref --shell --format='ref=%(refname);upstream=%(upstream)' \\\n    refs/heads | \\\nwhile read entry\ndo\n    eval \"$entry\"\n\n    # skip the current branch\n    test \"$ref\" = \"$currentbranch\" && continue\n\n    # skip branches that have no upstream\n    test -z \"$upstream\" && continue\n\n    # skip if upstream doesn't have any new commits\n    if [ -z \"`git rev-list \"$ref..$upstream\"`\" ]; then\n        echo \"${ref#refs/heads/} is up to date\"\n        continue\n    fi\n\n    # error if there are local commits\n    if [ -n \"`git rev-list \"$upstream..$ref\"`\" ]; then\n        echo \"${ref#refs/heads/} has local commits; can't fast-forward\"\n        continue\n    fi\n\n    echo \"${ref#refs/heads/} -> ${upstream#refs/remotes/}\"\n    git update-ref -m ff-all-branches \"$ref\" \"$upstream\"\ndone\n========= >8 =========\n\n\n-- \nStefan Haller\nBerlin, Germany\nhttp://www.haller-berlin.de/\n"},{"id":"180832","messageId":"4EE5121D.2050002@gmail.com","threadId":"29130","inReplyTo":"1kc4qnw.1xgi3yf14oaw7gM%lists@haller-berlin.de","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Gelonida N","fromEmail":"gelonida@gmail.com","sentAt":"2011-12-11T20:27:09Z","receivedAt":"2011-12-11T20:27:09Z","isPatch":false,"sender":{"key":"gelonida@gmail.com","avatar":null},"body":"On 12/11/2011 09:14 PM, Stefan Haller wrote:\n> Gelonida N <gelonida@gmail.com> wrote:\n> \n>> What is the best way to fastforward all fastforwardable tracking\n>> branches after a git fetch?\n> \n> Here's a script that does this.  It isn't very well tested, I hope I\n> didn't miss any edge cases. Use at your own risk.\n> \n> (It doesn't fastforward the branch you're on, on the assumtion that if\n> you said git fetch instead of git pull, you probably had a reason.)\n\nAgreed. it might be reasonable to ignore the current branch if it wasn't\npulled.\n\n\nThanks a lot for the script. I will play with it.\n\n> \n"},{"id":"180833","messageId":"m2d3bu7swz.fsf@igel.home","threadId":"29130","inReplyTo":"4EE50B5A.3000706@gmail.com","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Andreas Schwab","fromEmail":"schwab@linux-m68k.org","sentAt":"2011-12-11T20:30:20Z","receivedAt":"2011-12-11T20:30:20Z","isPatch":false,"sender":{"key":"schwab@linux-m68k.org","avatar":"https://avatars.githubusercontent.com/u/2175493?v=4"},"body":"Gelonida N <gelonida@gmail.com> writes:\n\n> On 12/11/2011 07:22 PM, Jakub Narebski wrote:\n>> You can use 'upstream' field name in git-for-each-ref invocation,\n>> for example\n>> \n>>   git for-each-ref '--format=%(refname:short) %(upstream:short)' refs/heads |\n>>   \tgrep -e ' [^ ]' |\n>>   \tsed  -e 's/ .*$//\n>>  \n> Thanks\n>\n>\n>\n>> This could probably be done using only sed -- grep is not necessary.\n> I think the equivalent would be:\n> sed '/ [^ ]/ s/ .*$//'\n\nYou need to suppress printing the non-matching lines.\n\n  sed -n '/ [^ ]/ s/ .*$//p'\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":"180834","messageId":"CACPiFCLoaELx1=thKNnFD2bavjT-mokSmLOVq-uUC7xbU1U5=w@mail.gmail.com","threadId":"29130","inReplyTo":"4EE5121D.2050002@gmail.com","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Martin Langhoff","fromEmail":"martin.langhoff@gmail.com","sentAt":"2011-12-11T20:43:04Z","receivedAt":"2011-12-11T20:43:04Z","isPatch":false,"sender":{"key":"martin.langhoff@gmail.com","avatar":"https://gravatar.com/avatar/1e3f311b6c4c15836501901ca58f8c0b0667246488084ba524d8bc9867e22fd9?d=mp&s=160"},"body":"On Sun, Dec 11, 2011 at 3:27 PM, Gelonida N <gelonida@gmail.com> wrote:\n> Agreed. it might be reasonable to ignore the current branch if it wasn't\n> pulled.\n\nActually, what this means is that this should be an enhancement to git\npull (\"git pull --all\") because pull means fetch + merge.\n\ncheers,\n\n\n\nm\n-- \n martin.langhoff@gmail.com\n martin@laptop.org -- Software Architect - OLPC\n - ask interesting questions\n - don't get distracted with shiny stuff  - working code first\n - http://wiki.laptop.org/go/User:Martinlanghoff\n"},{"id":"180838","messageId":"hbf.20111211x512@bombur.uio.no","threadId":"29130","inReplyTo":"1kc4qnw.1xgi3yf14oaw7gM%lists@haller-berlin.de","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Hallvard B Furuseth","fromEmail":"h.b.furuseth@usit.uio.no","sentAt":"2011-12-11T22:22:50Z","receivedAt":"2011-12-11T22:22:50Z","isPatch":false,"sender":{"key":"h.b.furuseth@usit.uio.no","avatar":null},"body":"Stefan Haller writes:\n>Gelonida N <gelonida@gmail.com> wrote:\n> \n>> What is the best way to fastforward all fastforwardable tracking\n>> branches after a git fetch?\n> \n> Here's a script that does this.  It isn't very well tested, I hope I\n> didn't miss any edge cases. Use at your own risk.\n\nLocal branches can track each other.  So the script needs to toposort\nthe branches, or to loop until either nothing was done or an error\nhappened.  (The latter to prevent an eternal loop on error.)\n\nI've wished for a more limited 'git ff' command than this:\n- git update-ref --ff-only, and branch/fetch options based on this.\n- Fast-forward only the branches tracking one particular remote/branch,\n  and maybe branches tracking the fast-forwarded branches.\n- Fast-forward to another remote or branch than the tracked one.\nI have a few aliases for it, but never thought much of a good common\ndesign.\n\n-- \nHallvard\n"},{"id":"180895","messageId":"1kc5m38.m71ik21ytxkhbM%lists@haller-berlin.de","threadId":"29130","inReplyTo":"hbf.20111211x512@bombur.uio.no","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Stefan Haller","fromEmail":"lists@haller-berlin.de","sentAt":"2011-12-12T07:33:15Z","receivedAt":"2011-12-12T07:33:15Z","isPatch":false,"sender":{"key":"lists@haller-berlin.de","avatar":null},"body":"Hallvard B Furuseth <h.b.furuseth@usit.uio.no> wrote:\n\n> Stefan Haller writes:\n> >Gelonida N <gelonida@gmail.com> wrote:\n> > \n> >> What is the best way to fastforward all fastforwardable tracking\n> >> branches after a git fetch?\n> > \n> > Here's a script that does this.  It isn't very well tested, I hope I\n> > didn't miss any edge cases. Use at your own risk.\n> \n> Local branches can track each other.  So the script needs to toposort\n> the branches, or to loop until either nothing was done or an error\n> happened.  (The latter to prevent an eternal loop on error.)\n\nIs this just theoretical, or are there real use cases for this? What\nwould be a workflow with such a local tracking branch?\n\nFor me personally, the script is good enough, because I only ever have\nbranches that track an 'origin' branch with the same name.\n\n\n-- \nStefan Haller\nBerlin, Germany\nhttp://www.haller-berlin.de/\n"},{"id":"180913","messageId":"7vmxay5h0g.fsf@alter.siamese.dyndns.org","threadId":"29130","inReplyTo":"jbvj5o$skt$1@dough.gmane.org","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-12-12T08:09:30Z","receivedAt":"2011-12-12T08:09:30Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Gelonida N <gelonida@gmail.com> writes:\n\n> What is the best way to fastforward all fastforwardable tracking\n> branches after a git fetch?\n\nThis lacks context and invites too many tangents, so I'll only touch a few\nof them.\n\nFirst of all, why do you want to do this?\n\nYou have many local branches that are forked from remote tracking branches\nand can be fast-forwarded to their counterparts, iow, these local branches\nare often behind their upstream and you do not have your own development\nin this repository. Because you can by definition have only one branch\nchecked out in your working tree, after a fetch from your origin, they\nwill further fall behind their counterparts.\n\nComing from that background, I can see you may want these branches that\nare not checked out fast-forwarded to their remote counterparts to keep\nthem stay current, but I first question that background. Why have these\nlocal branches to begin with, if they always are supposed to match their\nremote counterpart?\n\nOne possible reason (this is one tangent) is that you want to build and\ninstall tips of many branches fetched from the upstream without doing any\nlocal development in this repository (the \"upstream\" could be your primary\nrepository and the changes fed to this repository may be your own\ndevelopment, so this is different from saying that you as a person is only\nfollowing other people's work. It is just that nothing is done to the\nhistory in THIS repository). It could be solved by directly checking out\nthe remote tracking branches into detached head state, e.g.\n\n    $ for branch in maint master next\n      do\n        git checkout origin/$branch &&\n        make prefix=$HOME/git-$branch all test install || break\n      done\n\nand the reason why you want local branches instead may be because your\nbuild infrastructure (i.e. instead of \"make\" you have a custom script,\njust like I use 'Make' script in my 'todo' branch) the does customization\ndepending on the name of the current branch, and might be more cumbersome\nto get the same information for a detached head state (i.e. \"the tip of\nwhich remote tracking branch is the current commit?\") than asking \"git\nsymbolic-ref\" the name of the current branch. But then it is easy to find\nout which remote branch was checked out from the reflog for the HEAD (and\nit is easier for your script that builds the origin/$branch to use that\ninformation internally when the script calls your 'Make' equivalent). In\nany case, it is largely your build customization's problem if this is the\ncase.\n\nAnother tangent. Perhaps the reason why you want these local branches but\nthey can often be fast-forwarded is because your workflow looks like this:\n\n (1) you fork a topic from origin/master;\n (2) you develop a bit;\n (3) you push the topic back to origin/master;\n (4) time passes, others push to origin/master, while you work on other\n     branches of yours;\n (5) from time to time, you fetch from origin;\n (6) you decide to continue working on the topic, so you check it out,\n     and before continuing, you wish it is already up-to-date.\n\nBut then after fast-forwarding the topic in (6), your topic's history\ncontains commits other than those you made to work toward the goal of your\ntopic, namely, other commits made by others during (4) for random purposes\nthat do not have anything to do with achieving the goal of the topic of\nyours. Your branch is no longer about what you wanted to accomplish on\nyour topic. This invites two tangents.\n\nOne is a question. If you knew that the topic is not cooked fully and\nneeds further work after step (6), why did you push it back to the\norigin/master in the first place at step (3), contaminating the history\neverybody else bases their further work on with the contents of your\n\"half-done\" topic?\n\nAnother tangent. Perhaps the fork is not made from origin/master but you\nare collaboratively working on the same topic with others, and you handed\noff the work up to what you have done at step (3), and others continued to\nfurther the goal of the shared topic during (4). If that is the case,\nwouldn't it make more sense to delete the topic after you push it back,\nand forking at the point when you actually decide to get back into action?\n\nYet another. Even if you keep the (stale) topic branch that you already\nhave pushed out to the remote, because you can work on one topic at a time\nin a single working tree anyway, perhaps it makes more sense to delay this\nfast-forwarding until you actually check out the topic branch? After all,\nyour wishing to fast-forward \"all branches\" imply you have many of them,\nand it wouldn't be far-fetched for me to imagine that you will check one\nof them out a lot less often than you run \"git fetch\".\n\nIn other words, wouldn't a post-checkout hook be a better place to do\nthis kind of thing, perhaps like this (completely untested)? \n\n    #!/bin/sh\n    old=$1 new=$2 kind=$3\n\n    # did we checkout a branch?\n    test \"$kind\" = 1 || exit 0\n\n    # what did we check out?\n    branch=$(git symbolic-ref HEAD 2>/dev/null) || exit 0\n\n    # does it track anything? otherwise nothing needs to be done\n    upstream=$(git for-each-ref --format='%(upstream)' \"$branch\")\n    test -z \"$upstream\" || exit 0\n\n    # are we up-to-date? if so no need to do anything\n    test 0 = $(git rev-list \"..$upstream\" | wc -l) && exit 0\n\n    # do we have something we made? if so no point trying to fast-forward\n    test 0 = $(git rev-list \"$upstream..\" | wc -l) || exit 0\n\n    # attempt a fast-forward merge with it\n    git merge --ff-only @{upstream}\n\nThat is, of course, assuming that it makes sense to keep these local\nbranches in the first place.\n"},{"id":"180908","messageId":"20111212082526.GC16511@sigill.intra.peff.net","threadId":"29130","inReplyTo":"1kc5m38.m71ik21ytxkhbM%lists@haller-berlin.de","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-12-12T08:25:26Z","receivedAt":"2011-12-12T08:25:26Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Dec 12, 2011 at 08:33:15AM +0100, Stefan Haller wrote:\n\n> > Local branches can track each other.  So the script needs to toposort\n> > the branches, or to loop until either nothing was done or an error\n> > happened.  (The latter to prevent an eternal loop on error.)\n> \n> Is this just theoretical, or are there real use cases for this? What\n> would be a workflow with such a local tracking branch?\n\nI use this all the time.\n\nIn git.git, we use a topic branch workflow (i.e., every feature gets its\nown topic branch, and topics graduate independently to master as they\nare deemed stable). And we use a patch-submission workflow, which means\nit's OK for me to rebase my topics locally, because the end-product is a\nseries of patches sent to the list.\n\nTypically I branch off of \"origin/master\", so the topic is independent\nof anything else. For example, the \"jk/credentials\" branch in my git\nrepo is branched from \"origin/master\" (Junio's master).  But sometimes\nthere is a topic that depends on another topic, but should not be part\nof the same series (because the the first topic can graduate to master,\nbut the second one may still need more time for discussion and cooking).\nIn that case, I'll set the upstream to the other local topic branch. An\nexample of this is the \"jk/prompt\" series, which depends on\n\"jk/credentials\" for infrastructure, but is really a separate issue.\n\nHaving the upstream set is convenient, because I can get _just_ the\ncommits in jk/prompt with \"git log @{u}..\". Or I can rebase _just_ the\ncommits in that topic with \"git rebase -i\". If my upstream were set to\norigin, I would accidentally also rebase all of the commits pulled in\nfrom jk/credentials, too.\n\nWhile my topics are still in development (i.e., before they have even\nhit \"next\"), I tend to rebase them aggressively (so that I keep them up\nto date with git development), using a script that is something like[1]:\n\n  for i in `topics`; do\n    git rebase $i@{u} $i\n  done\n\nAnd I do topo-sort my topics for exactly the reason mentioned.\n\n-Peff\n\n[1] https://github.com/peff/git/blob/meta/rebase\n"},{"id":"180914","messageId":"7vhb165h0d.fsf@alter.siamese.dyndns.org","threadId":"29130","inReplyTo":"hbf.20111211x512@bombur.uio.no","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-12-12T08:28:57Z","receivedAt":"2011-12-12T08:28:57Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Hallvard B Furuseth <h.b.furuseth@usit.uio.no> writes:\n\n> Local branches can track each other.  So the script needs to toposort\n> the branches, or to loop until either nothing was done or an error\n> happened.  (The latter to prevent an eternal loop on error.)\n\nIf you have branches A that forked from B that in turn forked from C, and\nif after updating C you want to and can successfully update both B and A\nby fast-forwarding, that would only mean that neither A nor B had their\nown change since they were forked from their upstream, regardless of local\nor remote.\n\nWhat use do these empty branches have in the first place?\n"},{"id":"180917","messageId":"1kc5qsi.v9kcpd1vui7adM%lists@haller-berlin.de","threadId":"29130","inReplyTo":"20111212082526.GC16511@sigill.intra.peff.net","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Stefan Haller","fromEmail":"lists@haller-berlin.de","sentAt":"2011-12-12T09:19:37Z","receivedAt":"2011-12-12T09:19:37Z","isPatch":false,"sender":{"key":"lists@haller-berlin.de","avatar":null},"body":"Jeff King <peff@peff.net> wrote:\n\n> On Mon, Dec 12, 2011 at 08:33:15AM +0100, Stefan Haller wrote:\n> \n> > > Local branches can track each other.  So the script needs to toposort\n> > > the branches, or to loop until either nothing was done or an error\n> > > happened.  (The latter to prevent an eternal loop on error.)\n> > \n> > Is this just theoretical, or are there real use cases for this? What\n> > would be a workflow with such a local tracking branch?\n> \n> I use this all the time.\n> \n> In git.git, we use a topic branch workflow (i.e., every feature gets its\n> own topic branch, and topics graduate independently to master as they\n> are deemed stable). And we use a patch-submission workflow, which means\n> it's OK for me to rebase my topics locally, because the end-product is a\n> series of patches sent to the list.\n> \n> Typically I branch off of \"origin/master\", so the topic is independent\n> of anything else. For example, the \"jk/credentials\" branch in my git\n> repo is branched from \"origin/master\" (Junio's master).  But sometimes\n> there is a topic that depends on another topic, but should not be part\n> of the same series (because the the first topic can graduate to master,\n> but the second one may still need more time for discussion and cooking).\n> In that case, I'll set the upstream to the other local topic branch. An\n> example of this is the \"jk/prompt\" series, which depends on\n> \"jk/credentials\" for infrastructure, but is really a separate issue.\n> \n> Having the upstream set is convenient, because I can get _just_ the\n> commits in jk/prompt with \"git log @{u}..\". Or I can rebase _just_ the\n> commits in that topic with \"git rebase -i\". If my upstream were set to\n> origin, I would accidentally also rebase all of the commits pulled in\n> from jk/credentials, too.\n\nI see, thanks.  For my script, I'm wondering then if the most sensible\nthing to do is to just skip any branch whose upstream doesn't start with\nrefs/remotes/.\n\nFor a future \"git pull --all\" feature, it would probably only work on\nthose branches whose upstream is on the remote being pulled from,\nanyway.\n\n\n-- \nStefan Haller\nBerlin, Germany\nhttp://www.haller-berlin.de/\n"},{"id":"180920","messageId":"4EE5D3CD.6020604@gmail.com","threadId":"29130","inReplyTo":"7vmxay5h0g.fsf@alter.siamese.dyndns.org","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Gelonida N","fromEmail":"gelonida@gmail.com","sentAt":"2011-12-12T10:13:33Z","receivedAt":"2011-12-12T10:13:33Z","isPatch":false,"sender":{"key":"gelonida@gmail.com","avatar":null},"body":"Thanks for this rather long answer,\n\nOn 12/12/2011 09:09 AM, Junio C Hamano wrote:\n> Gelonida N <gelonida@gmail.com> writes:\n> \n>> What is the best way to fastforward all fastforwardable tracking\n>> branches after a git fetch?\n> \n> This lacks context and invites too many tangents, so I'll only touch a few\n> of them.\n> \n> First of all, why do you want to do this?\n> \n\nTo explain the scenario:\n- small project\n- every person works on master and multiple topic branches\n   and might alternate rather often\n- sometimes several persons work on the same topic branch\n  but most of the time not in parallel.\n- one person is working from several machines (starting work on\n  one and continuing on another)\n- additionally we do many pushed in order to be sure,\n  that our data is backed up in case of disk failures.\n- sometimes I just want to 'build' from a branch, that I am not\n   working on. but there I create mostly not even a tracking branch\n\nbefore changing a machine I want to be sure to have pushed everything. I\nwanted to get rid of the warning, that some branches cannot be pushed,\nbecause they aren't fastforwarded\n\nwhen checking out a branch I want to avoid, that I have to pull manually.\n\n\n\n> In other words, wouldn't a post-checkout hook be a better place to do\n> this kind of thing, perhaps like this (completely untested)? \n> \n>     #!/bin/sh\n>     old=$1 new=$2 kind=$3\n> \n>     # did we checkout a branch?\n>     test \"$kind\" = 1 || exit 0\n> \n>     # what did we check out?\n>     branch=$(git symbolic-ref HEAD 2>/dev/null) || exit 0\n> \n>     # does it track anything? otherwise nothing needs to be done\n>     upstream=$(git for-each-ref --format='%(upstream)' \"$branch\")\n>     test -z \"$upstream\" || exit 0\n> \n>     # are we up-to-date? if so no need to do anything\n>     test 0 = $(git rev-list \"..$upstream\" | wc -l) && exit 0\n> \n>     # do we have something we made? if so no point trying to fast-forward\n>     test 0 = $(git rev-list \"$upstream..\" | wc -l) || exit 0\n> \n>     # attempt a fast-forward merge with it\n>     git merge --ff-only @{upstream}\n> \n\nThis is a solution, I wouldn't get rid of the warnings though when\nrunning git push.\n"},{"id":"180921","messageId":"4EE5D656.20400@gmail.com","threadId":"29130","inReplyTo":"4EE5D3CD.6020604@gmail.com","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Gelonida N","fromEmail":"gelonida@gmail.com","sentAt":"2011-12-12T10:24:22Z","receivedAt":"2011-12-12T10:24:22Z","isPatch":false,"sender":{"key":"gelonida@gmail.com","avatar":null},"body":"I forgot one other use case:\n\n- wanting to pull from tracking branches without fastforwarding is not\nsuch a smart idea.\n\nof course I can do\ngit merge from  remotes/origin/branch\nbut this is more to type and would vary depending on whether 'd like to\npull from an unpushed tracking branch or from a freshly fetched tracking\nbranch.\n\n\nOn 12/12/2011 11:13 AM, Gelonida N wrote:\n> Thanks for this rather long answer,\n> \n> On 12/12/2011 09:09 AM, Junio C Hamano wrote:\n>> Gelonida N <gelonida@gmail.com> writes:\n>>\n>>> What is the best way to fastforward all fastforwardable tracking\n>>> branches after a git fetch?\n>>\n>> This lacks context and invites too many tangents, so I'll only touch a few\n>> of them.\n>>\n>> First of all, why do you want to do this?\n>>\n> \n> To explain the scenario:\n> - small project\n> - every person works on master and multiple topic branches\n>    and might alternate rather often\n> - sometimes several persons work on the same topic branch\n>   but most of the time not in parallel.\n> - one person is working from several machines (starting work on\n>   one and continuing on another)\n> - additionally we do many pushed in order to be sure,\n>   that our data is backed up in case of disk failures.\n> - sometimes I just want to 'build' from a branch, that I am not\n>    working on. but there I create mostly not even a tracking branch\n> \n> before changing a machine I want to be sure to have pushed everything. I\n> wanted to get rid of the warning, that some branches cannot be pushed,\n> because they aren't fastforwarded\n> \n> when checking out a branch I want to avoid, that I have to pull manually.\n> \n> \n> \n>> In other words, wouldn't a post-checkout hook be a better place to do\n>> this kind of thing, perhaps like this (completely untested)? \n>>\n>>     #!/bin/sh\n>>     old=$1 new=$2 kind=$3\n>>\n>>     # did we checkout a branch?\n>>     test \"$kind\" = 1 || exit 0\n>>\n>>     # what did we check out?\n>>     branch=$(git symbolic-ref HEAD 2>/dev/null) || exit 0\n>>\n>>     # does it track anything? otherwise nothing needs to be done\n>>     upstream=$(git for-each-ref --format='%(upstream)' \"$branch\")\n>>     test -z \"$upstream\" || exit 0\n>>\n>>     # are we up-to-date? if so no need to do anything\n>>     test 0 = $(git rev-list \"..$upstream\" | wc -l) && exit 0\n>>\n>>     # do we have something we made? if so no point trying to fast-forward\n>>     test 0 = $(git rev-list \"$upstream..\" | wc -l) || exit 0\n>>\n>>     # attempt a fast-forward merge with it\n>>     git merge --ff-only @{upstream}\n>>\n> \n> This is a solution, I wouldn't get rid of the warnings though when\n> running git push.\n> \n"},{"id":"181064","messageId":"hbf.20111213g43t@bombur.uio.no","threadId":"29130","inReplyTo":"1kc5m38.m71ik21ytxkhbM%lists@haller-berlin.de","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Hallvard Breien Furuseth","fromEmail":"h.b.furuseth@usit.uio.no","sentAt":"2011-12-13T19:05:50Z","receivedAt":"2011-12-13T19:05:50Z","isPatch":false,"sender":{"key":"h.b.furuseth@usit.uio.no","avatar":null},"body":"Stefan Haller writes:\n>Hallvard B Furuseth <h.b.furuseth@usit.uio.no> wrote:\n>> Local branches can track each other.  So the script needs to toposort\n>> the branches, or to loop until either nothing was done or an error\n>> happened.  (The latter to prevent an eternal loop on error.)\n> \n> Is this just theoretical, or are there real use cases for this? What\n> would be a workflow with such a local tracking branch?\n\nPersonally I don't care much, I just noted that the script did not\nmatch the question in the subject line.\n\n-- \nHallvard\n"},{"id":"181382","messageId":"20111217101009.GA19248@sita-lt.atc.tcs.com","threadId":"29130","inReplyTo":"jbvj5o$skt$1@dough.gmane.org","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Sitaram Chamarty","fromEmail":"sitaramc@gmail.com","sentAt":"2011-12-17T10:10:09Z","receivedAt":"2011-12-17T10:10:09Z","isPatch":false,"sender":{"key":"sitaramc@gmail.com","avatar":"https://avatars.githubusercontent.com/u/43316?v=4"},"body":"On Sat, Dec 10, 2011 at 01:26:32PM +0100, Gelonida N wrote:\n> Hi,\n> \n> What is the best way to fastforward all fastforwardable tracking\n> branches after a git fetch?\n\nI know this is a somewhat closed topic, but I took some time to\nclean up a program I have been using for a while, including some\nchanges based upon ideas elsewhere in this thread.  The program\n\"git-branch-check\" is attached, and requires perl > 5.10.0.\n\nNote that this does a lot more than just fast-forward all\nbranches, although it can do that as well.\n\nI alias it (in ~/.gitconfig) to 'bc', so I just run \"git bc\".\nRunning with \"-h\" shows usage:\n\n    Usage: /home/sitaram/bin/git-branch-check [options] [branches]\n\n    Check or fast forward branches.  Default: act upon all local branches if no\n    arguments supplied, or just the current branch if '-c' is passed.\n            -c      act upon current branch only\n            -ff     don't just check, try to fast forward also\n            -md     max diff (default 100; see below for details)\n            -h      help\n    'max diff':\n        hide output for two branches different by more than so many commits\n\nMy usual usage is just \"git bc -c\", which may give me:\n\n       1        pu...origin/pu\n       1        pu...github/pu\n      13        pu...master\n           5    pu...q\n           7    pu...vrs\n\nThis quickly tells me my 'pu' is one ahead of both my own\ngitolite server as well as github's copy, and that it is 13\ncommits ahead of master.  The (unreleased and frequently\nrebased) feature branches 'q' and 'vrs' are ahead of pu, which\nmeans a rebase is not pending.  Without the \"-c\" I may see the\nstatus of master versus its own upstream and other remotes,\netc., also.\n\nThe purpose of the max diff limit (default 100) is to hide, for\nexample, the pair 'master' and 'man' from the git.git repo.\nOtherwise you'd see something like:\n\n    27249 973    master...man\n\nwhich is pretty meaningless.  The sum of those two numbers\nshould be less than the max.\n\n\"git bc -ff\" will attempt to fast forward all selected branches\nthat are ancestors of their respective upstreams.  The current\nbranch will not be ff-ed if the tree is dirty, since you can't\ndo this by 'git branch -f'; it has to be an actual merge\ncommand.\n\nThe output is not (currently) pipable to other programs because\nI use colors (obtained from 'git config --get-color') and\ncurrently it is not conditional on STDOUT being a tty.\n"},{"id":"181383","messageId":"20111217101106.GB19248@sita-lt.atc.tcs.com","threadId":"29130","inReplyTo":"20111217101009.GA19248@sita-lt.atc.tcs.com","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Sitaram Chamarty","fromEmail":"sitaramc@gmail.com","sentAt":"2011-12-17T10:11:06Z","receivedAt":"2011-12-17T10:11:06Z","isPatch":false,"sender":{"key":"sitaramc@gmail.com","avatar":"https://avatars.githubusercontent.com/u/43316?v=4"},"body":"oops; forgot the program...\n\nOn Sat, Dec 17, 2011 at 03:40:09PM +0530, Sitaram Chamarty wrote:\n> On Sat, Dec 10, 2011 at 01:26:32PM +0100, Gelonida N wrote:\n> > Hi,\n> > \n> > What is the best way to fastforward all fastforwardable tracking\n> > branches after a git fetch?\n> \n> I know this is a somewhat closed topic, but I took some time to\n> clean up a program I have been using for a while, including some\n> changes based upon ideas elsewhere in this thread.  The program\n> \"git-branch-check\" is attached, and requires perl > 5.10.0.\n> \n> Note that this does a lot more than just fast-forward all\n> branches, although it can do that as well.\n> \n> I alias it (in ~/.gitconfig) to 'bc', so I just run \"git bc\".\n> Running with \"-h\" shows usage:\n> \n>     Usage: /home/sitaram/bin/git-branch-check [options] [branches]\n> \n>     Check or fast forward branches.  Default: act upon all local branches if no\n>     arguments supplied, or just the current branch if '-c' is passed.\n>             -c      act upon current branch only\n>             -ff     don't just check, try to fast forward also\n>             -md     max diff (default 100; see below for details)\n>             -h      help\n>     'max diff':\n>         hide output for two branches different by more than so many commits\n> \n> My usual usage is just \"git bc -c\", which may give me:\n> \n>        1        pu...origin/pu\n>        1        pu...github/pu\n>       13        pu...master\n>            5    pu...q\n>            7    pu...vrs\n> \n> This quickly tells me my 'pu' is one ahead of both my own\n> gitolite server as well as github's copy, and that it is 13\n> commits ahead of master.  The (unreleased and frequently\n> rebased) feature branches 'q' and 'vrs' are ahead of pu, which\n> means a rebase is not pending.  Without the \"-c\" I may see the\n> status of master versus its own upstream and other remotes,\n> etc., also.\n> \n> The purpose of the max diff limit (default 100) is to hide, for\n> example, the pair 'master' and 'man' from the git.git repo.\n> Otherwise you'd see something like:\n> \n>     27249 973    master...man\n> \n> which is pretty meaningless.  The sum of those two numbers\n> should be less than the max.\n> \n> \"git bc -ff\" will attempt to fast forward all selected branches\n> that are ancestors of their respective upstreams.  The current\n> branch will not be ff-ed if the tree is dirty, since you can't\n> do this by 'git branch -f'; it has to be an actual merge\n> command.\n> \n> The output is not (currently) pipable to other programs because\n> I use colors (obtained from 'git config --get-color') and\n> currently it is not conditional on STDOUT being a tty.\n\n\n\n\n#!/usr/bin/perl -s\nuse 5.10.0;\nuse strict;\nuse warnings;\n\n# ----------------------------------------------------------------------\n\n# bare-minimum subset of 'Tsh' (see github.com/sitaramc/tsh)\n{\n    my($rc, $text);\n    sub rc { return $rc || 0; }\n    sub text { return $text || ''; }\n    sub lines { return split /\\n/, $text; }\n    sub try {\n        my $cmd = shift; die \"try: expects only one argument\" if @_;\n        $text = `( $cmd ) 2>&1; echo -n RC=\\$?`;\n        if ($text =~ s/RC=(\\d+)$//) {\n            $rc = $1;\n            return (not $rc);\n        }\n        die \"couldnt find RC= in result; this should not happen:\\n$text\\n\\n...\\n\";\n    }\n}\n\n# ----------------------------------------------------------------------\n\n# options; the \"-s\" above sets one or more of these\n# (the format of the lines below is special; it is used by usage() to generate\n# help text for the options)\n# BEGIN OPTIONS\n    our $c;     # act upon current branch only\n    our $ff;    # don't just check, try to fast forward also\n    our $md;    # max diff (default 100; see below for details)\n    our $h;     # help\n# END OPTIONS\n    $md ||= 100;\n\n# get this over with; usage() exits so don't worry\n    usage() if $h;\n\n# get current branch\n    my $current = '';\n    try \"git symbolic-ref HEAD\" or die \"DETACHED HEAD or no repo\";\n    ($current = (lines)[0]) =~ s(refs/heads/)();\n\n# get branch names\n    # first, all local branches as keys of a hash with upstream name if any, as the value\n    my %upstream;\n    try \"git for-each-ref --perl '--format=\\$upstream{%(refname:short)} = %(upstream:short);' refs/heads\"\n        or die \"for-each-ref 1 failed\";\n    eval text;\n\n    # local branches as a list; keep $current at the top, and the rest sorted\n    my @local = ($current, grep { $_ ne $current } sort keys %upstream);\n\n    # remote branches as a list\n    try \"git for-each-ref '--format=%(refname:short)' refs/remotes\"\n        or die \"for-each-ref 2 failed\";\n    my @remote = lines;\n\n# decide what branches to act upon.  Default: all local branches.  If any\n# arguments are given, then those.  If '-c' is passed, only current branch.\n    my @branches = @local;\n    @branches = @ARGV if @ARGV;\n    @branches = ($current) if $c;\n\n# ----------------------------------------------------------------------\n\n# show the tree state if it's dirty\n    print \"dirty:\\n\", text if dirty();\n\n# process selected branches\n    for my $b (@branches) {\n        # attempt a fast-forward if -ff is passed\n        ff($b, $upstream{$b}, $current) if ($ff);\n        # check against its own upstream\n        check($b, $upstream{$b});\n        # then against all remote branches of the same name (I typically have\n        # my own gitolite server as 'upstream' but also have github and google\n        # code as additional remotes that I push my branches to)\n        check($b, grep(m(^[^/]+/$b$), @remote));\n    }\n    # ...then against all local branches.  We do this in a separate loop\n    # so their output is kept separate from the remote compares above.\n    for my $b (@branches) {\n        check($b, @local);\n    }\n\n# DONE...\n\n# ----------------------------------------------------------------------\n# subroutines\n# ----------------------------------------------------------------------\n\nsub ff {\n    # b=branch, u=upstream, c=current\n    my ($b, $u, $c) = @_;\n\n    unless ($u) {\n        say \"$b does not have an upstream\";\n        return;\n    }\n\n    if ($b eq $c and dirty()) {\n        say \"working tree is dirty; skipping ff for (current branch) $b\";\n        return;\n    }\n\n    # $l = number of commits \"l\"eft side has over the \"r\"ight (similarly $r...)\n    my($l, $r) = compare($b, $u);\n    if ($r and not $l) {\n        # there is something to update, and ff is possible\n        if ($b eq $c) {\n            # current branch; needs an actual merge\n            try(\"git merge --ff-only $u\") or die \"$b: 'git merge --ff-only $u' failed:\\n\" .  text;\n        } else {\n            # other branches can be forced\n            try(\"git branch -f $b $u\") or die \"$b: 'git branch -f $b $u' failed:\\n\" .  text;\n        }\n    }\n}\n\nsub check {\n    my ($b, @list) = @_;\n    state %seen;\n\n    for my $u (@list) {\n        next unless $u;\n        next if $b eq $u or $seen{$b}{$u};\n        # seeing a...b is as good as seeing b...a also\n        $seen{$b}{$u} = 1;\n        $seen{$u}{$b} = 1;\n\n        my ($l, $r) = compare($b, $u);\n\n        my $abs = $l + $r; next unless $abs;    # if they're equal, don't show it\n        next if $abs >= $md;                    # if they're too far apart, don't show it\n\n        print spacepad(4, $l) . color('green') . ($l || ' ');\n        print spacepad(4, $r) . color('red')   . ($r || ' ');\n        say color('reset') . \"    $b...$u\";\n    }\n}\n\nsub compare {\n    my ($b, $u) = @_;\n\n    try(\"git rev-list $u..$b\") or die \"'git rev-list $u..$b' failed:\\n\" .  text;\n    my $l = lines;\n\n    try(\"git rev-list $b..$u\") or die \"'git rev-list $b..$u' failed:\\n\" .  text;\n    my $r = lines;\n\n    return($l, $r);\n}\n\nsub dirty {\n    try \"git status -s -uno | cut -c1-2 | sort | uniq -c; /./\";\n}\n\nsub color {\n    my $color = shift;\n    return `git config --get-color \"\" $color`;\n}\n\nsub spacepad {\n    return \" \" x ($_[0] - length($_[1]));\n}\n\nsub usage {\n    print \"\nUsage: $0 [options] [branches]\n\nCheck or fast forward branches.  Default: act upon all local branches if no\narguments supplied, or just the current branch if '-c' is passed.\n\";\n    @ARGV=($0);\n    for ( grep { /BEGIN OPTIONS/../END OPTIONS/ and not /OPTION/ } <> ) {\n        s/our \\$/\\t-/;\n        s/; *#/\\t/;\n        print;\n    }\n    say \"\\'max diff':\\n    hide output for two branches different by more than so many commits\";\n    exit 1;\n}\n"},{"id":"181455","messageId":"CAEY4ZpPKLrWQpEUYkwST8Fh40JwrjxvD+6yML6A+=XpsYmPevg@mail.gmail.com","threadId":"29130","inReplyTo":"20111217101106.GB19248@sita-lt.atc.tcs.com","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Nazri Ramliy","fromEmail":"ayiehere@gmail.com","sentAt":"2011-12-19T06:31:04Z","receivedAt":"2011-12-19T06:31:04Z","isPatch":false,"sender":{"key":"ayiehere@gmail.com","avatar":"https://avatars.githubusercontent.com/u/164756?v=4"},"body":"On Sat, Dec 17, 2011 at 6:11 PM, Sitaram Chamarty <sitaramc@gmail.com> wrote:\n> oops; forgot the program...\n\nThis is nice!\n\nStick it on github, or somewhere, please, so that I can always get the\nlatest and greatest?\n\nThanks.\n\nnazri\n"},{"id":"182714","messageId":"CAMK1S_j8zJ3Lrz7R2gNV500Ata2rG6R=E0p8ptaB675XqGDi0g@mail.gmail.com","threadId":"29130","inReplyTo":"20111217101009.GA19248@sita-lt.atc.tcs.com","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Sitaram Chamarty","fromEmail":"sitaramc@gmail.com","sentAt":"2012-01-18T01:48:51Z","receivedAt":"2012-01-18T01:48:51Z","isPatch":false,"sender":{"key":"sitaramc@gmail.com","avatar":"https://avatars.githubusercontent.com/u/43316?v=4"},"body":"On Sat, Dec 17, 2011 at 3:40 PM, Sitaram Chamarty <sitaramc@gmail.com> wrote:\n> On Sat, Dec 10, 2011 at 01:26:32PM +0100, Gelonida N wrote:\n>> Hi,\n>>\n>> What is the best way to fastforward all fastforwardable tracking\n>> branches after a git fetch?\n>\n> I know this is a somewhat closed topic, but I took some time to\n> clean up a program I have been using for a while, including some\n\nA month later and I find I have modified this program\n"},{"id":"182715","messageId":"CAMK1S_hK_shh5g8BOxhKz3tw2m=kp6qZM1ZTQOOnY2eMNzL3hA@mail.gmail.com","threadId":"29130","inReplyTo":"CAEY4ZpPKLrWQpEUYkwST8Fh40JwrjxvD+6yML6A+=XpsYmPevg@mail.gmail.com","subject":"Re: best way to fastforward all tracking branches after a fetch","fromName":"Sitaram Chamarty","fromEmail":"sitaramc@gmail.com","sentAt":"2012-01-18T01:50:45Z","receivedAt":"2012-01-18T01:50:45Z","isPatch":false,"sender":{"key":"sitaramc@gmail.com","avatar":"https://avatars.githubusercontent.com/u/43316?v=4"},"body":"(sorry about that previous email; hit send in error.  Here's the complete one)\n\nOn Mon, Dec 19, 2011 at 12:01 PM, Nazri Ramliy <ayiehere@gmail.com> wrote:\n> On Sat, Dec 17, 2011 at 6:11 PM, Sitaram Chamarty <sitaramc@gmail.com> wrote:\n>> oops; forgot the program...\n>\n> This is nice!\n>\n> Stick it on github, or somewhere, please, so that I can always get the\n> latest and greatest?\n>\n> Thanks.\n>\n> nazri\n\nok; it's on github: http://github.com/sitaramc/git-tools (they're all\nstandalone tools; you don't have to use the others)\n\nThe output is now colorised, and it will now also tell you, for each\nremote you have, what branches you are hiding from them and what they\nhave which you have not started tracking locally.\n\na \"screenshot\" is at\nhttp://sitaramc.github.com/git-tools/index.html#index_git_branch_check_\n\nI notice I'm using it more and more, often even as a replacement for\n'git status'... at least for repos where I'm juggling multiple\nremotes.\n"}]}