]>
git.wh0rd.org - home.git/blob - .bin/git-rb-catchup
bb6b910ef7f84f24678b30903b9e3fd72399cd7a
3 """Helper to automatically rebase onto latest commit possible."""
10 def git(args
, **kwargs
):
12 kwargs
.setdefault('check', True)
13 kwargs
.setdefault('capture_output', True)
14 kwargs
.setdefault('encoding', 'utf-8')
15 return subprocess
.run(['git'] + args
, **kwargs
)
19 """Try to rebase onto |target|."""
21 git(['rebase', target
])
23 except KeyboardInterrupt:
24 git(['rebase', '--abort'])
28 git(['rebase', '--abort'])
32 def rebase_bisect(lbranch
, rbranch
, behind
):
33 """Try to rebase branch as close to |rbranch| as possible."""
35 target
= f
'{rbranch}~{pos}'
36 print(f
'Rebasing onto {target} ', end
='', flush
=True)
37 print('.', end
='', flush
=True)
38 # git(['checkout', '-f', target])
39 print('.', end
='', flush
=True)
40 # git(['checkout', '-f', lbranch])
41 print('. ', end
='', flush
=True)
43 print('OK' if ret
else 'failed')
46 #"min" is the latest branch commit while "max" is where we're now.
51 mid
= min + (max - min) // 2
52 if mid
== old_mid
or mid
< min or mid
>= max:
62 def get_ahead_behind(lbranch
, rbranch
):
63 """Return number of commits |lbranch| is ahead & behind relative to |rbranch|."""
64 output
= git(['rev-list', '--left-right', '--count', f
'{lbranch}...{rbranch}']).stdout
65 return [int(x
) for x
in output
.split()]
68 def get_tracking_branch(branch
):
69 """Return remote branch that |branch| is tracking."""
70 merge
= git(['config', '--local', f
'branch.{branch}.merge']).stdout
.strip()
74 remote
= git(['config', '--local', f
'branch.{branch}.remote']).stdout
.strip()
76 if merge
.startswith('refs/heads/'):
78 return f
'{remote}/{merge}'
83 def get_local_branch():
84 """Return the name of the local checked out branch."""
85 return git(['branch', '--show-current']).stdout
.strip()
90 parser
= argparse
.ArgumentParser(description
=__doc__
)
92 '--skip-initial-rebase-latest', dest
='initial_rebase',
93 action
='store_false', default
=True,
94 help='skip initial rebase attempt onto the latest branch')
97 help='branch to rebase onto')
102 """The main entry point for scripts."""
103 parser
= get_parser()
104 opts
= parser
.parse_args(argv
)
106 lbranch
= get_local_branch()
107 print(f
'Local branch resolved to "{lbranch}"')
109 print('Unable to resolve local branch', file=sys
.stderr
)
113 rbranch
= opts
.branch
115 rbranch
= get_tracking_branch(lbranch
)
116 print(f
'Remote branch resolved to "{rbranch}"')
118 ahead
, behind
= get_ahead_behind(lbranch
, rbranch
)
119 print(f
'Branch is {ahead} commits ahead and {behind} commits behind')
124 print('Fast forwarding ...')
127 if opts
.initial_rebase
:
128 print(f
'Trying to rebase onto latest {rbranch} ... ', end
='', flush
=True)
132 print('failed; falling back to bisect')
133 rebase_bisect(lbranch
, rbranch
, behind
)
136 if __name__
== '__main__':
137 sys
.exit(main(sys
.argv
[1:]))