blob: c1f8f2a09d919ca6a89dd3acc3ce470508a27d38 [file] [log] [blame]
Edward Lesmes98eda3f2019-08-12 21:09:53 +00001#!/usr/bin/env python
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +00002# Copyright 2014 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Change the upstream of the current branch."""
7
Raul Tambre80ee78e2019-05-06 22:41:05 +00008from __future__ import print_function
9
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000010import argparse
11import sys
12
13import subprocess2
14
15from git_common import upstream, current_branch, run, tags, set_branch_config
iannucci@chromium.org10fbe872014-05-16 22:31:13 +000016from git_common import get_or_create_merge_base, root, manual_merge_base
Henrique Ferreiro9f273d02019-02-22 10:10:27 +000017from git_common import get_branch_tree, topo_iter
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000018
19import git_rebase_update
Anthony Polito87e73892021-07-09 19:15:11 +000020import metrics
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000021
Anthony Polito87e73892021-07-09 19:15:11 +000022@metrics.collector.collect_metrics('git reparent-branch')
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000023def main(args):
24 root_ref = root()
25
26 parser = argparse.ArgumentParser()
27 g = parser.add_mutually_exclusive_group()
28 g.add_argument('new_parent', nargs='?',
29 help='New parent branch (or tag) to reparent to.')
30 g.add_argument('--root', action='store_true',
31 help='Reparent to the configured root branch (%s).' % root_ref)
32 g.add_argument('--lkgr', action='store_true',
33 help='Reparent to the lkgr tag.')
34 opts = parser.parse_args(args)
35
36 # TODO(iannucci): Allow specification of the branch-to-reparent
37
38 branch = current_branch()
iannucci@chromium.orgf3e37a02015-12-04 19:03:23 +000039
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000040 if opts.root:
41 new_parent = root_ref
42 elif opts.lkgr:
43 new_parent = 'lkgr'
44 else:
tandrii@chromium.org41a9ce42015-08-06 17:57:12 +000045 if not opts.new_parent:
46 parser.error('Must specify new parent somehow')
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000047 new_parent = opts.new_parent
48 cur_parent = upstream(branch)
49
50 if branch == 'HEAD' or not branch:
51 parser.error('Must be on the branch you want to reparent')
52 if new_parent == cur_parent:
53 parser.error('Cannot reparent a branch to its existing parent')
54
iannucci@chromium.orgf3e37a02015-12-04 19:03:23 +000055 if not cur_parent:
56 msg = (
57 "Unable to determine %s@{upstream}.\n\nThis can happen if you didn't use "
58 "`git new-branch` to create the branch and haven't used "
59 "`git branch --set-upstream-to` to assign it one.\n\nPlease assign an "
60 "upstream branch and then run this command again."
61 )
Raul Tambre80ee78e2019-05-06 22:41:05 +000062 print(msg % branch, file=sys.stderr)
iannucci@chromium.orgf3e37a02015-12-04 19:03:23 +000063 return 1
64
iannucci@chromium.org10fbe872014-05-16 22:31:13 +000065 mbase = get_or_create_merge_base(branch, cur_parent)
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000066
67 all_tags = tags()
68 if cur_parent in all_tags:
69 cur_parent += ' [tag]'
70
71 try:
72 run('show-ref', new_parent)
73 except subprocess2.CalledProcessError:
Raul Tambre80ee78e2019-05-06 22:41:05 +000074 print('fatal: invalid reference: %s' % new_parent, file=sys.stderr)
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000075 return 1
76
77 if new_parent in all_tags:
Raul Tambre80ee78e2019-05-06 22:41:05 +000078 print("Reparenting %s to track %s [tag] (was %s)" % (branch, new_parent,
79 cur_parent))
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000080 set_branch_config(branch, 'remote', '.')
81 set_branch_config(branch, 'merge', new_parent)
82 else:
Raul Tambre80ee78e2019-05-06 22:41:05 +000083 print("Reparenting %s to track %s (was %s)" % (branch, new_parent,
84 cur_parent))
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000085 run('branch', '--set-upstream-to', new_parent, branch)
86
iannucci@chromium.org10fbe872014-05-16 22:31:13 +000087 manual_merge_base(branch, mbase, new_parent)
88
Henrique Ferreiro9f273d02019-02-22 10:10:27 +000089 # ONLY rebase-update the branch which moved (and dependants)
90 _, branch_tree = get_branch_tree()
91 branches = [branch]
92 for branch, parent in topo_iter(branch_tree):
93 if parent in branches:
94 branches.append(branch)
95 return git_rebase_update.main(['--no-fetch'] + branches)
iannucci@chromium.orgc050a5b2014-03-26 06:18:50 +000096
97
98if __name__ == '__main__': # pragma: no cover
sbc@chromium.org013731e2015-02-26 18:28:43 +000099 try:
Anthony Polito87e73892021-07-09 19:15:11 +0000100 with metrics.collector.print_notice_and_exit():
101 sys.exit(main(sys.argv[1:]))
sbc@chromium.org013731e2015-02-26 18:28:43 +0000102 except KeyboardInterrupt:
103 sys.stderr.write('interrupted\n')
104 sys.exit(1)