git: pushing a new, empty branch for an empty project?

If you repo is still empty, you might try and create an empty commit, to have something to push:

git commit --allow-empty -m "initial commit"
git push -u origin testdev

See also “Why do I need to explicitly push a new branch?”.


Git 2.35 (Q1 2022) allows information on remotes defined for an arbitrary repository to be read.

See commit 4a2dcb1, commit 56eed34, commit 085b98f, commit fd3cb05, commit e083ef5 (17 Nov 2021) by Glen Choo (chooglen).
(Merged by Junio C Hamano — gitster in commit 6d1e149, 10 Dec 2021)

remote: die if branch is not found in repository

Signed-off-by: Glen Choo
Reviewed-by: Jonathan Tan

In a subsequent commit, we would like external-facing functions to be able to accept “struct repository” and “struct branch” as a pair.
This is useful for functions like pushremote_for_branch(), which need to take values from the remote_state and branch, even if branch == NULL.
However, a caller may supply an unrelated repository and branch, which is not supported behavior.

To prevent misuse, add a die_on_missing_branch() helper function that dies if a given branch is not from a given repository.
Speed up the existence check by replacing the branches list with a branches_hash hashmap.

Like read_config(), die_on_missing_branch() is only called from non-static functions; static functions are less prone to misuse because they have strong conventions for keeping remote_state and branch in sync.


With Git 2.37 (Q3 2022), a misconfigured ‘branch..remote‘ led to a bug in configuration parsing.

It avoids branch was not found in the repository.

See commit f1dfbd9, commit 91e2e8f (31 May 2022) by Glen Choo (chooglen).
(Merged by Junio C Hamano — gitster in commit 0b91d56, 10 Jun 2022)

remote.c: don’t BUG() on 0-length branch names

Reported-by: “Ing. Martin Prantl Ph.D.”
Helped-by: Jeff King
Signed-off-by: Glen Choo

4a2dcb1 (“remote: die if branch is not found in repository”, 2021-11-17, Git v2.35.0-rc0 — merge listed in batch #2) introduced a regression where multiple config entries with an empty branch name, e.g.

[branch ""]
    remote = foo
    merge = bar

could cause Git to fail when it tries to look up branch tracking information.

We parse the config key to get (branch name, branch name length), but when the branch name subsection is empty, we get a bogus branch name, e.g. “branch..remote” gives (".remote", 0).
We continue to use the bogus branch name as if it were valid, and prior to 4a2dcb1, this wasn’t an issue because length = 0 caused the branch name to effectively be "" everywhere.

However, that commit handles length = 0 inconsistently when we create the branch:

  • When find_branch() is called to check if the branch exists in the branch hash map, it interprets a length of 0 to mean that it should call strlen on the char pointer.
  • But the code path that inserts into the branch hash map interprets a length of 0 to mean that the string is 0-length.

This results in the bug described above:

  • branch..remote” looks for “.remote” in the branch hash map.
    Since we do not find it, we insert the "" entry into the hash map.
  • branch..merge” looks for “.merge” in the branch hash map.
    Since we do not find it, we again try to insert the "" entry into the hash map.
    However, the entries in the branch hash map are supposed to be appended to, not overwritten.
  • Since overwriting an entry is a BUG(), Git fails instead of silently ignoring the empty branch name.

Fix the bug by removing the convenience strlen functionality, so that 0 means that the string is 0-length.


With Git 2.37 (Q3 2022), fix git remote use-after-free (with another forget-to-free) fix.

See commit 323822c, commit 338959d (07 Jun 2022) by Ævar Arnfjörð Bjarmason (avar).
(Merged by Junio C Hamano — gitster in commit fe66167, 13 Jun 2022)

remote.c: don’t dereference NULL in freeing loop

Signed-off-by: Ævar Arnfjörð Bjarmason

Fix a bug in fd3cb05 (“remote: move static variables into per-repository struct”, 2021-11-17, Git v2.35.0-rc0 — merge listed in batch #2) where we’d free(remote->pushurl[i]) after having NULL‘d out remote->pushurl.
itself.
We free “remote->pushurl” in the next “for“-loop, so doing this appears to have been a copy/paste error.

Before this change GCC 12’s -fanalyzer would correctly note that we’d dereference NULL in this case, this change fixes that:

remote.c: In function ‘remote_clear’:
remote.c:153:17: error: dereference of NULL ‘*remote.pushurl’ [CWE-476] [-Werror=analyzer-null-dereference]
  153 |                 free((char *)remote->pushurl[i]);
      |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      [...]

Leave a Comment