James Hawkins 4fe87617ff project: read HEAD directly in-memory to avoid subprocesses
Benchmark:
* repo upload frameworks/base: 2.84s -> 0.50s (-82.3%, 5.6x faster)
* repo upload (3,045 projects): 7.66s -> 5.24s (-31.6%, 2.42s saved)

From repo's inception through v2.56, GetHead() directly read the
`.git/HEAD` file in Python. In commit 52bab0ba ("project: Use git
rev-parse to read HEAD"), this was replaced with git subprocess calls
on the premise that git provides a dedicated command. However, in
large multi-project workspaces (such as Android with 3,000+ projects),
spawning thousands of git processes introduced severe latency
regressions during `repo upload` and `repo status`.

Furthermore, switching to subprocesses broke detached HEADs and
unborn branches (fixed in commits 7f7d70ef and 8c3585f3 by re-adding
the v2.56 file-reading logic as an error recovery fallback).

This patch restores fast in-memory reading as the primary path, while
adding modern defensive safeguards:
* Symbolic refs (`ref: refs/heads/...`): Strips whitespace and tabs
  and returns the ref directly in memory.
* Detached HEAD: Validates 40-char SHA-1 and 64-char SHA-256 commit
  hashes via git_config.IsId(), normalizing to lowercase.
* Symlinks: Detects filesystem symlinks via os.path.islink() and
  safely falls back to git symbolic-ref.
* Fallback: Catches (OSError, AssertionError) and transparently falls
  back to native git commands for reftables, unexpected layouts, or
  filesystem errors. Unifies recovery fallback parsing with the fast
  path (CRLF/tabs, lowercase hashes, and consistent RelPath errors).

In addition, this change substantially expands test coverage in
tests/test_project.py, adding comprehensive unit tests for symbolic
refs, whitespace/tabs, CRLF line endings, SHA-1, SHA-256, uppercase
hash normalization, symlinks, corrupted worktrees, and fallback
robustness.

Test: ./run_tests tests/test_project.py
Change-Id: Ib5c2530117c6939e4b9293feda81aa745c003c6a
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/623001
Commit-Queue: James Hawkins <jhawkins@google.com>
Reviewed-by: Brian Gan <brgan@google.com>
Tested-by: James Hawkins <jhawkins@google.com>
2026-08-28 16:03:06 -07:00
2026-01-06 11:32:42 -08:00
2026-07-01 15:45:23 -07:00
2026-06-25 16:07:53 -07:00
2025-04-23 08:33:37 -07:00
2026-06-22 16:19:30 -07:00
2021-11-15 01:39:36 +00:00
2020-02-13 04:49:55 +00:00
2026-03-18 12:01:37 -07:00
2026-05-14 09:03:56 -07:00
2024-12-03 22:27:56 +00:00
2025-08-21 11:04:41 -07:00
2019-12-02 04:23:31 +00:00
2025-04-01 20:59:10 -07:00
2025-08-21 11:04:41 -07:00

repo

Repo is a tool built on top of Git. Repo helps manage many Git repositories, does the uploads to revision control systems, and automates parts of the development workflow. Repo is not meant to replace Git, only to make it easier to work with Git. The repo command is an executable Python script that you can put anywhere in your path.

Contact

Please use the repo-discuss mailing list or issue tracker for questions.

You can file a new bug report under the "repo" component.

Please do not e-mail individual developers for support. They do not have the bandwidth for it, and often times questions have already been asked on repo-discuss or bugs posted to the issue tracker. So please search those sites first.

Install

Many distros include repo, so you might be able to install from there.

# Debian/Ubuntu.
$ sudo apt-get install repo

# Gentoo.
$ sudo emerge dev-vcs/repo

You can install it manually as well as it's a single script.

$ mkdir -p ~/.bin
$ PATH="${HOME}/.bin:${PATH}"
$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo
$ chmod a+rx ~/.bin/repo

Shell Completion

Repo includes completion scripts for Bash and Zsh.

Bash

To enable completion in Bash, source completion.bash in your ~/.bashrc:

source /path/to/git-repo/completion.bash

Zsh

To enable completion in Zsh, you can either:

  1. Copy or symlink completion.zsh to a file named _repo in a directory in your $fpath:

    mkdir -p ~/.zsh/completion
    # You can copy the file:
    cp /path/to/git-repo/completion.zsh ~/.zsh/completion/_repo
    # Or symlink it:
    ln -s /path/to/git-repo/completion.zsh ~/.zsh/completion/_repo
    

    Then add that directory to your fpath in ~/.zshrc before compinit:

    fpath=(~/.zsh/completion $fpath)
    autoload -Uz compinit
    compinit
    
  2. Or source the file directly and call compdef in your ~/.zshrc:

    source /path/to/git-repo/completion.zsh
    compdef _repo repo
    
S
Description
No description provided
Readme Apache-2.0
32 MiB
Languages
Python 98.1%
Shell 1.9%