Change in osmo-dev[master]: gits: use @{u} to get upstream branch, not origin/%s

Neels Hofmeyr gerrit-no-reply at
Mon Nov 12 22:35:52 UTC 2018

Neels Hofmeyr has uploaded this change for review. (

Change subject: gits: use @{u} to get upstream branch, not origin/%s

gits: use @{u} to get upstream branch, not origin/%s

git has an internal concept of a branch's upstream branch, and the remote need
not be 'origin', and also, the upstream branch name may differ completely. So,
use git's {u} keyword to obtain the upstream branch name.

This removes all 'origin' strings from gits. Also, git_branch_exists() is no
longer needed, drop it.

Also remove a couple of default arguments which aren't ever used because we
always pass arguments anyway.

In the case of git_ahead_behind(), we would have use for a default
branch_upstream=None to imply calling git_branch_upstream(), but then during
rebase, if no upstream exists, we would invoke it twice to get None a second
time. So just call the function explicitly. I thought about returning an empty
string instead of None, but it's too convoluted.

Change-Id: Ife146903ae1323a4e568587ccfd4018725e9d719
M src/gits
1 file changed, 30 insertions(+), 22 deletions(-)

  git pull ssh:// refs/changes/56/11756/1

diff --git a/src/gits b/src/gits
index 490a6af..681082d 100755
--- a/src/gits
+++ b/src/gits
@@ -58,7 +58,7 @@
 def git_output(git_dir, *args):
-    return subprocess.check_output(['git', '-C', git_dir, ] + list(args)).decode('utf-8')
+    return subprocess.check_output(['git', '-C', git_dir, ] + list(args), stderr=subprocess.STDOUT).decode('utf-8')
 def git_bool(git_dir, *args):
@@ -69,20 +69,16 @@
         return False
-def git_branch_exists(git_dir, branch='origin/master'):
-    return git_bool(git_dir, 'rev-parse', '--quiet', '--verify', branch)
-def git_ahead_behind(git_dir, branch='master', remote='origin'):
+def git_ahead_behind(git_dir, branch, branch_upstream):
     ''' Count revisions ahead/behind of the remote branch.
         returns: (ahead, behind) (e.g. (0, 5)) '''
     # Missing remote branch
-    if not git_branch_exists(git_dir, remote + '/' + branch):
+    if not branch_upstream:
         return (0, 0)
-    behind = git_output(git_dir, 'rev-list', '--count', '%s..%s/%s' % (branch, remote, branch))
-    ahead = git_output(git_dir, 'rev-list', '--count', '%s/%s..%s' % (remote, branch, branch))
+    behind = git_output(git_dir, 'rev-list', '--count', '%s..%s' % (branch, branch_upstream))
+    ahead = git_output(git_dir, 'rev-list', '--count', '%s..%s' % (branch_upstream, branch))
     return (int(ahead.rstrip()), int(behind.rstrip()))
@@ -98,12 +94,20 @@
     return ret
+def git_branch_upstream(git_dir, branch_name='HEAD'):
+    '''Return an upstream branch name, or an None if there is none.'''
+    try:
+        return git_output(git_dir, 'rev-parse', '--abbrev-ref', '%s@{u}' % branch_name).rstrip()
+    except subprocess.CalledProcessError:
+        return None
 def git_has_modifications(git_dir):
     return not git_bool(git_dir, 'diff-index', '--quiet', 'HEAD')
-def git_can_fast_forward(git_dir, branch='master', remote='origin'):
-    return git_bool(git_dir, 'merge-base', '--is-ancestor', branch, remote + '/' + branch)
+def git_can_fast_forward(git_dir, branch, branch_upstream):
+    return git_bool(git_dir, 'merge-base', '--is-ancestor', branch, branch_upstream)
 def format_branch_ahead_behind(branch, ahead, behind):
@@ -142,12 +146,14 @@
         if not is_current and branch not in interesting_branch_names:
-        ahead, behind = git_ahead_behind(git_dir, branch)
+        ahead, behind = git_ahead_behind(git_dir, branch,
+                                         git_branch_upstream(git_dir, branch))
         if not ahead and not behind and not is_current:
             # skip branches that are "not interesting"
-        # Branch with ahead/behind origin info ("master[+1|-5]")
+        # Branch with ahead/behind upstream info ("master[+1|-5]")
         strs.append(format_branch_ahead_behind(branch, ahead, behind))
     return strs
@@ -238,8 +244,10 @@
         print('Not on a branch: %s' % git_dir)
         raise SkipThisRepo()
-    print('Rebasing branch: ' + orig_branch)
-    ahead, behind = git_ahead_behind(git_dir, orig_branch)
+    upstream_branch = git_branch_upstream(git_dir, orig_branch)
+    print('Rebasing %r onto %r' % (orig_branch, upstream_branch))
+    ahead, behind = git_ahead_behind(git_dir, orig_branch, upstream_branch)
     if git_has_modifications(git_dir):
         do_commit = ask(git_dir, 'Local mods.',
@@ -262,24 +270,24 @@
             raise SkipThisRepo()
     # Missing upstream branch
-    if not git_branch_exists(git_dir, 'origin/' + orig_branch):
+    if not upstream_branch:
         print('there is no upstream branch for %r' % orig_branch)
     # Diverged
     elif ahead and behind:
         do_reset = ask(git_dir, 'Diverged.',
-                       '%s: git reset --hard origin/%s?' % (
-                           orig_branch, orig_branch),
+                       '%s: git reset --hard %s?' % (
+                           orig_branch, upstream_branch),
                        '<empty>  no',
                        'OK  yes (write OK in caps!)',
                        valid_answers=('', 'OK'))
         if do_reset == 'OK':
-            git(git_dir, 'reset', '--hard', 'origin/%s' % orig_branch)
+            git(git_dir, 'reset', '--hard', upstream_branch)
     # Behind
     elif behind:
-        if git_can_fast_forward(git_dir, orig_branch):
+        if git_can_fast_forward(git_dir, orig_branch, upstream_branch):
             git(git_dir, 'merge')
@@ -303,13 +311,13 @@
             git(git_dir, 'commit', '-am', 'wip', may_fail=True)
             git(git_dir, 'checkout', orig_branch)
-        do_reset = ask(git_dir, '%s: git reset --hard origin/%s?' % (orig_branch, orig_branch),
+        do_reset = ask(git_dir, '%s: git reset --hard %s?' % (orig_branch, upstream_branch),
                        '<empty>  no',
                        'OK  yes (write OK in caps!)',
                        valid_answers=('', 'OK'))
         if do_reset == 'OK':
-            git(git_dir, 'reset', '--hard', 'origin/%s' % orig_branch)
+            git(git_dir, 'reset', '--hard', upstream_branch)
     return orig_branch

To view, visit
To unsubscribe, or for help writing mail filters, visit

Gerrit-Project: osmo-dev
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ife146903ae1323a4e568587ccfd4018725e9d719
Gerrit-Change-Number: 11756
Gerrit-PatchSet: 1
Gerrit-Owner: Neels Hofmeyr <nhofmeyr at>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the gerrit-log mailing list