Skip to content

Commit

Permalink
BREAKING CHANGE: Change the behaviour of git_repository_is_empty to…
Browse files Browse the repository at this point in the history
… better align with expectations in a world where

`master` isn't always the "initial branch"

This pull request proposes a change to the definition of
an "empty" repository used in `git_repository_is_empty`.

At present, an empty is repository is one which:

1. has just been initialised
2. has no references apart from `HEAD`
3. has a `HEAD` pointing to the unborn `master` branch or,
  if specified, the unborn branch specified in the
  `init.defaultBranch` configuration value

This changes the definition of empty, removing requirement 3.

Why? Since `git_repository_is_empty` was first implemented,
there has been significant cultural change in the Git community
towards using an "initial branch" other than `master`.

Because of this change, the current implementation of
`git_repository_is_empty` considers repos to be *not empty* which
an ordinary observer would consider to be empty.

Specifically, this happens where a repo is initialized with
`git init --initial-branch`. An ordinary observer would consider
such a repo to be empty, but currently, libgit2 considers it to be
non-empty if the `initial-branch` is not `master`. This is because,
whilst `git_repository_is_empty` checks the `init.defaultBranch` to
try to figure out the initial branch, `git init --initial-branch`
doesn't set this value, as you can prove like this:

```bash
git config init.defaultBranch
mkdir test-repo
git init --initial-branch main
git config init.defaultBranch
```

I'm not necessarily expecting this PR to be merged as is or ever -
but I want to start a conversation about this, given that the
current implementation is surprising and likely confusing.

See #6049.
  • Loading branch information
timrogers committed Feb 26, 2023
1 parent 8a871d1 commit ad370b1
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 10 deletions.
4 changes: 1 addition & 3 deletions include/git2/repository.h
Original file line number Diff line number Diff line change
Expand Up @@ -465,9 +465,7 @@ GIT_EXTERN(int) git_repository_head_unborn(git_repository *repo);
* Check if a repository is empty
*
* An empty repository has just been initialized and contains no references
* apart from HEAD, which must be pointing to the unborn master branch,
* or the branch specified for the repository in the `init.defaultBranch`
* configuration variable.
* apart from HEAD.
*
* @param repo Repo to test
* @return 1 if the repository is empty, 0 if it isn't, error code
Expand Down
9 changes: 2 additions & 7 deletions src/libgit2/repository.c
Original file line number Diff line number Diff line change
Expand Up @@ -2867,21 +2867,16 @@ int git_repository_initialbranch(git_str *out, git_repository *repo)
int git_repository_is_empty(git_repository *repo)
{
git_reference *head = NULL;
git_str initialbranch = GIT_STR_INIT;
int result = 0;

if ((result = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0 ||
(result = git_repository_initialbranch(&initialbranch, repo)) < 0)
if (result = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0
goto done;

result = (git_reference_type(head) == GIT_REFERENCE_SYMBOLIC &&
strcmp(git_reference_symbolic_target(head), initialbranch.ptr) == 0 &&
result = (git_reference_type(head) == GIT_REFERENCE_SYMBOLIC &&&&
repo_contains_no_reference(repo));

done:
git_reference_free(head);
git_str_dispose(&initialbranch);

return result;
}

Expand Down

0 comments on commit ad370b1

Please sign in to comment.