Skip to content

Add support for fetching unadvertised SHA-1 (allow-tip-sha1-in-want capability) #11958

Open
@JustAnotherArchivist

Description

@JustAnotherArchivist

I'd like to see the allow-tip-sha1-in-want capability added to Gitea's Git server so that objects that aren't advertised in upload-pack can be fetched by a client. The primary use case that I'm aware of is fetching commits that were on branches that have been force-pushed over. In the context of pull requests, these previous commits can be important to understand the review process, for example. GitHub and GitLab.com (haven't tested GitLab CE) support this.

For those who may not be that familiar with how a git clone works, here's a quick summary: the client connects to the server and executes git upload-pack. This returns the server's capabilities and a list of refs. The client then determines which of these refs they want and sends a series of want <SHA-1> lines to the server of the objects (and their history) it wants. The server then returns a packfile with those objects, and the client creates the desired local directory structure.

However, even if the client fetches everything advertised by the server (e.g. with --mirror), this only returns reachable commits. An example of unreachable commits are branches that were force-pushed over. Most notably, that is common in pull requests when major refactors of the PR code are necessary to keep the history clean after the merge. As long as garbage collection hasn't been run on the server, those commits still exist, and they can be fetched if the server supports the allow-tip-sha1-in-want: git fetch remote sha1 will attempt to fetch the commit with hash sha1 from the remote remote.

Example using GitHub and the recent PR #11032:

  1. git clone --mirror https://github.com/go-gitea/gitea.git
  2. cd gitea.git
  3. git show e4c89ba252341b8222dd72389b7407c3a0e05c99fatal: bad object e4c89ba252341b8222dd72389b7407c3a0e05c99
  4. git fetch origin e4c89ba252341b8222dd72389b7407c3a0e05c99
  5. git show e4c89ba252341b8222dd72389b7407c3a0e05c99commit e4c89ba252341b8222dd72389b7407c3a0e05c99 etc.

As of version 1.11.6 and the version deployed on gitea.com (see below), Gitea does not support step 4 (error: Server does not allow request for unadvertised object <SHA-1>), which amounts to a want e4c89ba252341b8222dd72389b7407c3a0e05c99 request from the client where that commit is not reachable from any ref.

Example using https://gitea.com/gitea/homebrew-gitea/pulls/94:

  1. git clone --mirror https://gitea.com/gitea/homebrew-gitea.git
  2. cd homebrew-gitea.git
  3. git show 238dfca61957cd2b8b7c690a1ccea6481104c5b3 → bad object (as expected)
  4. git fetch origin 238dfca61957cd2b8b7c690a1ccea6481104c5b3error: Server does not allow request for unadvertised object 238dfca61957cd2b8b7c690a1ccea6481104c5b3

Since Gitea essentially just delegates the HTTP requests handling to Git (after auth checks etc.) in routers/repo/http.go, I believe the only change that would be needed to support this would be enabling uploadpack.allowTipSHA1InWant in the repositories.

On a related note, supporting allow-reachable-sha1-in-want aka uploadpack.allowReachableSHA1InWant may also be useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/enhancementAn improvement of existing functionality

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions