From 83428a9b260a660c6848905d17f6b3028fad9009 Mon Sep 17 00:00:00 2001 From: Gavin Mak Date: Tue, 25 Aug 2026 08:53:53 -0700 Subject: [PATCH] rebase: delegate automatic stashing to Git Git --autostash predates repo's minimum supported client. Pass it directly to rebase instead of probing the index and separately running stash and stash pop, reducing the dirty path from four Git processes to one and correctly covering staged-only changes. Bug: 553599402 Change-Id: I0d6d59b17996576310498e9378e49380d355236e Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/623902 Tested-by: Gavin Mak Reviewed-by: Brian Gan Commit-Queue: Gavin Mak --- subcmds/rebase.py | 21 ++---------------- tests/test_subcmds_rebase.py | 41 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/subcmds/rebase.py b/subcmds/rebase.py index af8be4ea2..db397e891 100644 --- a/subcmds/rebase.py +++ b/subcmds/rebase.py @@ -139,6 +139,8 @@ branch but need to incorporate new upstream changes "underneath" them. common_args.append("--autosquash") if opt.interactive: common_args.append("-i") + if opt.auto_stash: + common_args.append("--autostash") config = self.manifest.manifestProject.config out = RebaseColoring(config) @@ -188,29 +190,10 @@ branch but need to incorporate new upstream changes "underneath" them. out.nl() out.flush() - needs_stash = False - if opt.auto_stash: - stash_args = ["update-index", "--refresh", "-q"] - - if GitCommand(project, stash_args).Wait() != 0: - needs_stash = True - # Dirty index, requires stash... - stash_args = ["stash"] - - if GitCommand(project, stash_args).Wait() != 0: - ret += 1 - continue - if GitCommand(project, args).Wait() != 0: ret += 1 continue - if needs_stash: - stash_args.append("pop") - stash_args.append("--quiet") - if GitCommand(project, stash_args).Wait() != 0: - ret += 1 - if ret: msg_fmt = "%d projects had errors" self.git_event_log.ErrorEvent(msg_fmt % (ret), msg_fmt) diff --git a/tests/test_subcmds_rebase.py b/tests/test_subcmds_rebase.py index d7e917316..a74aecbc7 100644 --- a/tests/test_subcmds_rebase.py +++ b/tests/test_subcmds_rebase.py @@ -14,6 +14,9 @@ """Unittests for the subcmds/rebase.py module.""" +import contextlib +import io +from types import SimpleNamespace from unittest import mock from error import GitError @@ -48,3 +51,41 @@ def test_resolve_onto_manifest_fallback() -> None: assert res == "main" project.GetRemote.assert_called_once() remote.ToLocal.assert_called_once_with("main") + + +def test_execute_delegates_autostash_to_rebase() -> None: + """--auto-stash is one rebase process, including staged-only changes.""" + cmd = rebase.Rebase() + cmd.manifest = mock.MagicMock() + cmd.git_event_log = mock.MagicMock() + project = mock.MagicMock() + project.CurrentBranch = "topic" + project.RelPath.return_value = "project" + branch = mock.MagicMock() + branch.LocalMerge = "refs/remotes/origin/main" + project.GetBranch.return_value = branch + cmd.GetProjects = mock.MagicMock(return_value=[project]) + opt = SimpleNamespace( + interactive=False, + fail_fast=False, + whitespace=None, + quiet=False, + force_rebase=False, + ff=True, + autosquash=False, + auto_stash=True, + onto_manifest=False, + this_manifest_only=False, + ) + git_command = mock.MagicMock() + git_command.Wait.return_value = 0 + + with mock.patch.object( + rebase, "GitCommand", return_value=git_command + ) as run_git, contextlib.redirect_stdout(io.StringIO()): + assert cmd.Execute(opt, []) == 0 + + run_git.assert_called_once_with( + project, + ["rebase", "--autostash", "refs/remotes/origin/main"], + )