Procházet zdrojové kódy

Add a --keep-going flag for people who run rebase-update infrequently.

Review URL: https://codereview.chromium.org/1331263002

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@296639 0039d316-1c4b-4281-b951-d872f2087c98
stip@chromium.org před 10 roky
rodič
revize
74374f985f

+ 20 - 1
git_rebase_update.py

@@ -196,6 +196,8 @@ def rebase_branch(branch, parent, start_hash):
 def main(args=None):
 def main(args=None):
   parser = argparse.ArgumentParser()
   parser = argparse.ArgumentParser()
   parser.add_argument('--verbose', '-v', action='store_true')
   parser.add_argument('--verbose', '-v', action='store_true')
+  parser.add_argument('--keep-going', '-k', action='store_true',
+                      help='Keep processing past failed rebases.')
   parser.add_argument('--no_fetch', '--no-fetch', '-n',
   parser.add_argument('--no_fetch', '--no-fetch', '-n',
                       action='store_true',
                       action='store_true',
                       help='Skip fetching remotes.')
                       help='Skip fetching remotes.')
@@ -245,6 +247,7 @@ def main(args=None):
   logging.debug('merge_base: %s' % pformat(merge_base))
   logging.debug('merge_base: %s' % pformat(merge_base))
 
 
   retcode = 0
   retcode = 0
+  unrebased_branches = []
   # Rebase each branch starting with the root-most branches and working
   # Rebase each branch starting with the root-most branches and working
   # towards the leaves.
   # towards the leaves.
   for branch, parent in git.topo_iter(branch_tree):
   for branch, parent in git.topo_iter(branch_tree):
@@ -254,7 +257,23 @@ def main(args=None):
       ret = rebase_branch(branch, parent, merge_base[branch])
       ret = rebase_branch(branch, parent, merge_base[branch])
       if not ret:
       if not ret:
         retcode = 1
         retcode = 1
-        break
+
+        if opts.keep_going:
+          print '--keep-going set, continuing with next branch.'
+          unrebased_branches.append(branch)
+          if git.in_rebase():
+            git.run_with_retcode('rebase', '--abort')
+          if git.in_rebase():  # pragma: no cover
+            print 'Failed to abort rebase. Something is really wrong.'
+            break
+        else:
+          break
+
+  if unrebased_branches:
+    print
+    print 'The following branches could not be cleanly rebased:'
+    for branch in unrebased_branches:
+      print '  %s' % branch
 
 
   if not retcode:
   if not retcode:
     remove_empty_branches(branch_tree)
     remove_empty_branches(branch_tree)

+ 9 - 4
man/html/git-rebase-update.html

@@ -755,7 +755,7 @@ git-rebase-update(1) Manual Page
 <h2 id="_synopsis">SYNOPSIS</h2>
 <h2 id="_synopsis">SYNOPSIS</h2>
 <div class="sectionbody">
 <div class="sectionbody">
 <div class="verseblock">
 <div class="verseblock">
-<pre class="content"><em>git rebase-update</em> [-v | --verbose] [-n | --no_fetch]</pre>
+<pre class="content"><em>git rebase-update</em> [-v | --verbose] [-n | --no-fetch] [-k | --keep-going]</pre>
 <div class="attribution">
 <div class="attribution">
 </div></div>
 </div></div>
 </div>
 </div>
@@ -786,7 +786,7 @@ Fetching
   of git remotes is determined, and fetched accordingly. Note that if any
   of git remotes is determined, and fetched accordingly. Note that if any
   branches have a tag as their upstream, we are forced to pull all remotes.
   branches have a tag as their upstream, we are forced to pull all remotes.
 </p>
 </p>
-<div class="paragraph"><p>Pass <code>--no_fetch</code> to skip this phase.</p></div>
+<div class="paragraph"><p>Pass <code>--no-fetch</code> to skip this phase.</p></div>
 </dd>
 </dd>
 <dt class="hdlist1">
 <dt class="hdlist1">
 Rebasing
 Rebasing
@@ -810,6 +810,11 @@ left in mid-rebase and <code>git rebase-update</code> will exit. You can deal wi
 like any other conflicted rebase. When you&#8217;re done, just <code>git rebase-update</code>
 like any other conflicted rebase. When you&#8217;re done, just <code>git rebase-update</code>
 again to pick up where you left off.</p></div>
 again to pick up where you left off.</p></div>
 </dd>
 </dd>
+</dl></div>
+<div class="paragraph"><p>If you&#8217;d like to rebase all rebaseable branches in one pass and manually process
+the unrebaseable ones later, use -k or --keep-going. Cleanup will not happen
+until all branches apply cleanly.</p></div>
+<div class="dlist"><dl>
 <dt class="hdlist1">
 <dt class="hdlist1">
 Cleanup
 Cleanup
 </dt>
 </dt>
@@ -844,7 +849,7 @@ Restoration
 -n
 -n
 </dt>
 </dt>
 <dt class="hdlist1">
 <dt class="hdlist1">
---no_fetch
+--no-fetch
 </dt>
 </dt>
 <dd>
 <dd>
 <p>
 <p>
@@ -930,7 +935,7 @@ from <a href="https://chromium.googlesource.com/chromium/tools/depot_tools.git">
 <div id="footnotes"><hr /></div>
 <div id="footnotes"><hr /></div>
 <div id="footer">
 <div id="footer">
 <div id="footer-text">
 <div id="footer-text">
-Last updated 2014-04-10 14:23:11 PDT
+Last updated 2015-09-10 16:42:50 PDT
 </div>
 </div>
 </div>
 </div>
 </body>
 </body>

+ 8 - 6
man/man1/git-rebase-update.1

@@ -2,12 +2,12 @@
 .\"     Title: git-rebase-update
 .\"     Title: git-rebase-update
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
 .\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\"      Date: 04/10/2014
+.\"      Date: 09/10/2015
 .\"    Manual: Chromium depot_tools Manual
 .\"    Manual: Chromium depot_tools Manual
-.\"    Source: depot_tools 68b1017
+.\"    Source: depot_tools 805792e
 .\"  Language: English
 .\"  Language: English
 .\"
 .\"
-.TH "GIT\-REBASE\-UPDATE" "1" "04/10/2014" "depot_tools 68b1017" "Chromium depot_tools Manual"
+.TH "GIT\-REBASE\-UPDATE" "1" "09/10/2015" "depot_tools 805792e" "Chromium depot_tools Manual"
 .\" -----------------------------------------------------------------
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
 .\" -----------------------------------------------------------------
@@ -32,7 +32,7 @@ git-rebase-update \- Updates all branches to have the latest changes from their
 .SH "SYNOPSIS"
 .SH "SYNOPSIS"
 .sp
 .sp
 .nf
 .nf
-\fIgit rebase\-update\fR [\-v | \-\-verbose] [\-n | \-\-no_fetch]
+\fIgit rebase\-update\fR [\-v | \-\-verbose] [\-n | \-\-no\-fetch] [\-k | \-\-keep\-going]
 .fi
 .fi
 .sp
 .sp
 .SH "DESCRIPTION"
 .SH "DESCRIPTION"
@@ -58,7 +58,7 @@ Fetching
 All branches are examined to find their upstream references\&. The correct set of git remotes is determined, and fetched accordingly\&. Note that if any branches have a tag as their upstream, we are forced to pull all remotes\&.
 All branches are examined to find their upstream references\&. The correct set of git remotes is determined, and fetched accordingly\&. Note that if any branches have a tag as their upstream, we are forced to pull all remotes\&.
 .sp
 .sp
 Pass
 Pass
-\-\-no_fetch
+\-\-no\-fetch
 to skip this phase\&.
 to skip this phase\&.
 .RE
 .RE
 .PP
 .PP
@@ -87,6 +87,8 @@ will exit\&. You can deal with this like any other conflicted rebase\&. When you
 git rebase\-update
 git rebase\-update
 again to pick up where you left off\&.
 again to pick up where you left off\&.
 .RE
 .RE
+.sp
+If you\(cqd like to rebase all rebaseable branches in one pass and manually process the unrebaseable ones later, use \-k or \-\-keep\-going\&. Cleanup will not happen until all branches apply cleanly\&.
 .PP
 .PP
 Cleanup
 Cleanup
 .RS 4
 .RS 4
@@ -111,7 +113,7 @@ depot\-tools\&.upstream, see
 .RE
 .RE
 .SH "OPTIONS"
 .SH "OPTIONS"
 .PP
 .PP
-\-n, \-\-no_fetch
+\-n, \-\-no\-fetch
 .RS 4
 .RS 4
 Skip the
 Skip the
 git fetch
 git fetch

+ 5 - 1
man/src/git-rebase-update.txt

@@ -9,7 +9,7 @@ include::_git-rebase-update_desc.helper.txt[]
 SYNOPSIS
 SYNOPSIS
 --------
 --------
 [verse]
 [verse]
-'git rebase-update' [-v | --verbose] [-n | --no-fetch]
+'git rebase-update' [-v | --verbose] [-n | --no-fetch] [-k | --keep-going]
 
 
 DESCRIPTION
 DESCRIPTION
 -----------
 -----------
@@ -49,6 +49,10 @@ left in mid-rebase and `git rebase-update` will exit. You can deal with this
 like any other conflicted rebase. When you're done, just `git rebase-update`
 like any other conflicted rebase. When you're done, just `git rebase-update`
 again to pick up where you left off.
 again to pick up where you left off.
 
 
+If you'd like to rebase all rebaseable branches in one pass and manually process
+the unrebaseable ones later, use -k or --keep-going. Cleanup will not happen
+until all branches apply cleanly.
+
 Cleanup::
 Cleanup::
   Once all the branches have been rebased, any empty branches (i.e. branches
   Once all the branches have been rebased, any empty branches (i.e. branches
   with no commits on them) are removed. If a branch is removed in this fashion,
   with no commits on them) are removed. If a branch is removed in this fashion,

+ 36 - 0
tests/git_rebase_update_test.py

@@ -259,6 +259,42 @@ class GitRebaseUpdateTest(git_test_utils.GitRepoReadWriteTestBase):
     self.assertIn('\'branch_G\' was merged', output)
     self.assertIn('\'branch_G\' was merged', output)
     self.assertIn('checking out \'origin/master\'', output)
     self.assertIn('checking out \'origin/master\'', output)
 
 
+  def testRebaseConflictsKeepGoing(self):
+    # Pretend that branch_L landed
+    self.origin.git('checkout', 'master')
+    with self.origin.open('L', 'w') as f:
+      f.write('L')
+    self.origin.git('add', 'L')
+    self.origin.git_commit('L')
+
+    # Add a commit to branch_K so that things fail
+    self.repo.git('checkout', 'branch_K')
+    with self.repo.open('M', 'w') as f:
+      f.write('NOPE')
+    self.repo.git('add', 'M')
+    self.repo.git_commit('K NOPE')
+
+    # Add a commits to branch_L which will work when squashed
+    self.repo.git('checkout', 'branch_L')
+    self.repo.git('reset', 'branch_L~')
+    with self.repo.open('L', 'w') as f:
+      f.write('NOPE')
+    self.repo.git('add', 'L')
+    self.repo.git_commit('L NOPE')
+    with self.repo.open('L', 'w') as f:
+      f.write('L')
+    self.repo.git('add', 'L')
+    self.repo.git_commit('L YUP')
+
+    # start on a branch which will be deleted
+    self.repo.git('checkout', 'branch_G')
+
+    self.repo.git('config', 'branch.branch_K.dormant', 'false')
+    output, _ = self.repo.capture_stdio(self.reup.main, ['-k'])
+    self.assertIn('--keep-going set, continuing with next branch.', output)
+    self.assertIn('could not be cleanly rebased:', output)
+    self.assertIn('  branch_K', output)
+
 
 
   def testTrackTag(self):
   def testTrackTag(self):
     self.origin.git('tag', 'lkgr', self.origin['M'])
     self.origin.git('tag', 'lkgr', self.origin['M'])