1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 14:52:41 +01:00

In Git repositories, use "git symbolic-ref HEAD ..." to select the default branch

Summary:
Depends on D20434. Fixes T5963. Broadly, the issue here is that when:

  - You create a new, empty repository.
  - Then, you work on some branch other than `master`, without ever creating `master`.

...you get a warning on `git clone`:

> warning: remote HEAD refers to nonexistent ref, unable to checkout

To fix this, point the symbolic-ref HEAD at `refs/heads/<default-branch>` after installing commit hooks.

This fixes the warning, and also means that `git clone` will check out the repository default branch by default, which is nice.

There are a few caveats about this behavior (see T5963 for discussion) but nothing too substantial.

The only real issue is that Git prevents deletion of the default branch without a config setting. Just set that settting.

Test Plan:
See T5963.

In a repository, set `HEAD` to point somewhere invalid. Ran `bin/repository update ...`. Saw HEAD pointed back at the repository default branch.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T5963

Differential Revision: https://secure.phabricator.com/D20435
This commit is contained in:
epriestley 2019-04-16 06:27:53 -07:00
parent 7be671fb07
commit faf0a311ec

View file

@ -142,6 +142,10 @@ final class PhabricatorRepositoryPullEngine
}
}
if ($is_git) {
$this->updateGitWorkingCopyConfiguration();
}
} catch (Exception $ex) {
$this->abortPull(
pht(
@ -420,6 +424,43 @@ final class PhabricatorRepositoryPullEngine
$this->installHook($root.$path);
}
private function updateGitWorkingCopyConfiguration() {
$repository = $this->getRepository();
// See T5963. When you "git clone" from a remote with no "master", the
// client warns you that it isn't sure what it should check out as an
// initial state:
// warning: remote HEAD refers to nonexistent ref, unable to checkout
// We can tell the client what it should check out by making "HEAD"
// point somewhere. However:
//
// (1) If we don't set "receive.denyDelteCurrent" to "ignore" and a user
// tries to delete the default branch, Git raises an error and refuses.
// We want to allow this; we already have sufficient protections around
// dangerous changes and do not need to special case the default branch.
//
// (2) A repository may have a nonexistent default branch configured.
// For now, we just respect configuration. This will raise a warning when
// users clone the repository.
//
// In any case, these changes are both advisory, so ignore any errors we
// may encounter.
// We do this for both hosted and observed repositories. Although it is
// not terribly common to clone from Phabricator's copy of an observed
// repository, it works fine and makes sense occasionally.
if ($repository->isWorkingCopyBare()) {
$repository->execLocalCommand(
'config -- receive.denyDeleteCurrent ignore');
$repository->execLocalCommand(
'symbolic-ref HEAD %s',
'refs/heads/'.$repository->getDefaultBranch());
}
}
private function loadGitRemoteRefs(
PhabricatorRepository $repository,
PhutilOpaqueEnvelope $remote_envelope) {