Don't keep incomplete rebase state by default
Dumping the user into a dirtied working tree after a failed rebase attempt can be confusing, no matter how much contextual explanation we provide when doing so. By default, run `git rebase --abort` automatically so as to clean up from a failed test rebase, and then let the user rebase again on their own if that's the state they want to be in. Add a -K/--keep-rebase option to get the old behavior, and mention it when we automatically abort in case the user wants to just have git-review redo the rebase for them and leave things in that incomplete state. Change-Id: I7d7bfca1623a71a9b4fe445360d94fd6b039f040
This commit is contained in:
parent
7009d7d03d
commit
29f598d554
|
@ -131,7 +131,9 @@ If the master branch is different enough, the rebase can produce merge conflicts
|
||||||
If that happens rebasing will be aborted and diff displayed for not\-rebased branches.
|
If that happens rebasing will be aborted and diff displayed for not\-rebased branches.
|
||||||
You can also use
|
You can also use
|
||||||
.Ar \-\-no\-rebase ( Ar \-R )
|
.Ar \-\-no\-rebase ( Ar \-R )
|
||||||
to always skip the test rebase.
|
to always skip the test rebase or
|
||||||
|
.Ar \-\-keep\-rebase ( Ar \-K )
|
||||||
|
to keep the incomplete state rather than having it automatically aborted.
|
||||||
.It Fl f , Fl \-finish
|
.It Fl f , Fl \-finish
|
||||||
Close down the local branch and switch back to the target branch on
|
Close down the local branch and switch back to the target branch on
|
||||||
successful submission.
|
successful submission.
|
||||||
|
@ -188,6 +190,9 @@ Use the this option to skip the merge conflict test, allowing you to push merge
|
||||||
Also can be used for
|
Also can be used for
|
||||||
.Fl \-compare
|
.Fl \-compare
|
||||||
to skip automatic rebase of fetched reviews.
|
to skip automatic rebase of fetched reviews.
|
||||||
|
.It Fl K , Fl \-keep\-rebase
|
||||||
|
If the test rebase before pushing fails, keep the incomplete rebase state in
|
||||||
|
the worktree rather than automatically aborting it to clean up.
|
||||||
.It Fl \-no-thin
|
.It Fl \-no-thin
|
||||||
Disable thin pushes when pushing to Gerrit. This should only be used if you
|
Disable thin pushes when pushing to Gerrit. This should only be used if you
|
||||||
are currently experiencing unpack failures due to missing trees. It should
|
are currently experiencing unpack failures due to missing trees. It should
|
||||||
|
|
|
@ -900,7 +900,7 @@ def check_remote(branch, remote, scheme, hostname, port, project,
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def rebase_changes(branch, remote, interactive=True):
|
def rebase_changes(branch, remote, interactive=True, keep=False):
|
||||||
|
|
||||||
global _orig_head
|
global _orig_head
|
||||||
|
|
||||||
|
@ -959,17 +959,35 @@ def rebase_changes(branch, remote, interactive=True):
|
||||||
print("Errors running %s" % cmd)
|
print("Errors running %s" % cmd)
|
||||||
if interactive:
|
if interactive:
|
||||||
print(output)
|
print(output)
|
||||||
printwrap("It is likely that your change has a merge conflict. "
|
if keep:
|
||||||
"You may resolve it in the working tree now as "
|
printwrap("It is likely that your change has a merge "
|
||||||
"described above and then run 'git review' again, or "
|
"conflict. You may resolve it in the working tree "
|
||||||
"if you do not want to resolve it yet (note that the "
|
"now as described above and then run 'git review' "
|
||||||
"change can not merge until the conflict is resolved) "
|
"again, or if you do not want to resolve it yet "
|
||||||
"you may run 'git rebase --abort' then 'git review -R' "
|
"(note that the change can not merge until the "
|
||||||
"to upload the change without rebasing.")
|
"conflict is resolved) you may run 'git rebase "
|
||||||
|
"--abort' then 'git review -R' to upload the change "
|
||||||
|
"without rebasing.")
|
||||||
|
else:
|
||||||
|
printwrap("It is likely that your change has a merge "
|
||||||
|
"conflict, but the result of the test rebase has "
|
||||||
|
"been discarded. You may rebase it yourself and "
|
||||||
|
"review again, or use 'git review -R' to upload the "
|
||||||
|
"change without resolving the conflict, or use the "
|
||||||
|
"--keep-rebase option to leave the incomplete "
|
||||||
|
"rebase result in your working tree.")
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def abort_rebase():
|
||||||
|
cmd = "git rebase --abort"
|
||||||
|
(status, output) = run_command_status(cmd)
|
||||||
|
if status != 0:
|
||||||
|
print("Errors running %s" % cmd)
|
||||||
|
print(output)
|
||||||
|
|
||||||
|
|
||||||
def undo_rebase():
|
def undo_rebase():
|
||||||
global _orig_head
|
global _orig_head
|
||||||
if not _orig_head:
|
if not _orig_head:
|
||||||
|
@ -1546,6 +1564,10 @@ additional information:
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Force and push a rebase even when not"
|
help="Force and push a rebase even when not"
|
||||||
" needed.")
|
" needed.")
|
||||||
|
rebase_group.add_argument("-K", "--keep-rebase", dest="keep_rebase",
|
||||||
|
action="store_true",
|
||||||
|
help="Keep the unfinished test rebase if a "
|
||||||
|
" merge conflict is detected.")
|
||||||
|
|
||||||
track_group = parser.add_mutually_exclusive_group()
|
track_group = parser.add_mutually_exclusive_group()
|
||||||
track_group.add_argument("--track", dest="track",
|
track_group.add_argument("--track", dest="track",
|
||||||
|
@ -1768,7 +1790,9 @@ additional information:
|
||||||
return
|
return
|
||||||
|
|
||||||
if options.rebase or options.force_rebase:
|
if options.rebase or options.force_rebase:
|
||||||
if not rebase_changes(branch, remote):
|
if not rebase_changes(branch, remote, keep=options.keep_rebase):
|
||||||
|
if not options.keep_rebase:
|
||||||
|
abort_rebase()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if not options.force_rebase and not undo_rebase():
|
if not options.force_rebase and not undo_rebase():
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
|
@ -330,6 +330,23 @@ class GitReviewTestCase(tests.BaseGitReviewTestCase):
|
||||||
self.assertTrue(rebased)
|
self.assertTrue(rebased)
|
||||||
self.assertIn("It is likely that your change has a merge conflict.",
|
self.assertIn("It is likely that your change has a merge conflict.",
|
||||||
exc.args[0])
|
exc.args[0])
|
||||||
|
exc = self.assertRaises(Exception, self._run_git, 'rebase', '--abort')
|
||||||
|
self.assertIn("fatal: No rebase in progress?", exc.args[0])
|
||||||
|
|
||||||
|
def test_keep_aborted_rebase_state(self):
|
||||||
|
"""Test git-review -K behavior when rebase is needed."""
|
||||||
|
self._run_git_review('-s')
|
||||||
|
head_1 = self._run_git('rev-parse', 'HEAD^1')
|
||||||
|
|
||||||
|
self._run_git('checkout', '-b', 'test_branch', head_1)
|
||||||
|
|
||||||
|
self._simple_change('some other message',
|
||||||
|
'create conflict with master')
|
||||||
|
|
||||||
|
self.assertRaises(Exception, self._run_git_review, '-K')
|
||||||
|
output = self._run_git('status')
|
||||||
|
self.assertIn(
|
||||||
|
"You are currently editing a commit while rebasing", output)
|
||||||
|
|
||||||
def test_upload_without_rebase(self):
|
def test_upload_without_rebase(self):
|
||||||
"""Test change not needing a rebase can upload without rebasing."""
|
"""Test change not needing a rebase can upload without rebasing."""
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
By default, `git rebase --abort` is run automatically following a failed
|
||||||
|
test rebase, letting the user rebase again on their own if that's the state
|
||||||
|
they want to be in. A -K/--keep-rebase option is added to get the old
|
||||||
|
behavior.
|
Loading…
Reference in New Issue