From d3acb16c9ca92bbce72d0d0de2e84297ed8ea776 Mon Sep 17 00:00:00 2001 From: Robert Iannucci Date: Tue, 4 May 2021 21:37:40 +0000 Subject: [PATCH] [git-rebase-update] Disallow `git gc` during git-rebase-update. In theory this should prevent `git rebase-update` from invoking potentially expensive `git gc` operations after every `git rebase` (ideally once per branch, but sometimes as many as three per branch (!)). This has outsized effects as the size of the repo or number of branches increases, and additionally has penalties on Windows due to git's POSIXey assumptions around how disk I/O works. After doing all rebase stuff, we run `git gc --auto` from rebase-update once (assuming we were successful; if the command failed then we don't run gc at all). R=apolito@google.com Bug: 617218 Change-Id: I37a8f7953779f15b320e4ed7bb85119cb4bb665a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2868766 Auto-Submit: Robbie Iannucci Reviewed-by: Anthony Polito Commit-Queue: Robbie Iannucci --- git_common.py | 23 ++++++++++++++++++----- git_rebase_update.py | 4 ++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/git_common.py b/git_common.py index 523f62894..d70bdfbb7 100644 --- a/git_common.py +++ b/git_common.py @@ -641,15 +641,22 @@ def parse_commitrefs(*commitrefs): RebaseRet = collections.namedtuple('RebaseRet', 'success stdout stderr') -def rebase(parent, start, branch, abort=False): +def rebase(parent, start, branch, abort=False, allow_gc=False): """Rebases |start|..|branch| onto the branch |parent|. + Sets 'gc.auto=0' for the duration of this call to prevent the rebase from + running a potentially slow garbage collection cycle. + Args: parent - The new parent ref for the rebased commits. start - The commit to start from branch - The branch to rebase abort - If True, will call git-rebase --abort in the event that the rebase doesn't complete successfully. + allow_gc - If True, sets "-c gc.auto=1" on the rebase call, rather than + "-c gc.auto=0". Usually if you're doing a series of rebases, + you'll only want to run a single gc pass at the end of all the + rebase activity. Returns a namedtuple with fields: success - a boolean indicating that the rebase command completed @@ -658,10 +665,16 @@ def rebase(parent, start, branch, abort=False): rebase. """ try: - args = ['--onto', parent, start, branch] + args = [ + '-c', 'gc.auto={}'.format('1' if allow_gc else '0'), + 'rebase', + ] if TEST_MODE: - args.insert(0, '--committer-date-is-author-date') - run('rebase', *args) + args.append('--committer-date-is-author-date') + args += [ + '--onto', parent, start, branch, + ] + run(*args) return RebaseRet(True, '', '') except subprocess2.CalledProcessError as cpe: if abort: @@ -1064,7 +1077,7 @@ def get_branches_info(include_tracking_status): behind = int(behind_match.group(1)) if behind_match else None info_map[branch] = BranchesInfo( - hash=branch_hash, upstream=upstream_branch, commits=commits, + hash=branch_hash, upstream=upstream_branch, commits=commits, behind=behind) # Set None for upstreams which are not branches (e.g empty upstream, remotes diff --git a/git_rebase_update.py b/git_rebase_update.py index 5840f83c3..716111e20 100755 --- a/git_rebase_update.py +++ b/git_rebase_update.py @@ -340,6 +340,10 @@ def main(args=None): git.set_config(STARTING_BRANCH_KEY, '') git.set_config(STARTING_WORKDIR_KEY, '') + print() + print("Running `git gc --auto` - Ctrl-C to abort is OK.") + git.run('gc', '--auto') + return retcode