-
Notifications
You must be signed in to change notification settings - Fork 143
Add configuration option to set the default branch name for new repos #653
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add configuration option to set the default branch name for new repos #653
Conversation
Welcome to GitGitGadgetHi @DEGoodmanWilson, and welcome to GitGitGadget, the GitHub App to send patch series to the Git mailing list from GitHub Pull Requests. Please make sure that your Pull Request has a good description, as it will be used as cover letter. Also, it is a good idea to review the commit messages one last time, as the Git project expects them in a quite specific form:
It is in general a good idea to await the automated test ("Checks") in this Pull Request before contributing the patches, e.g. to avoid trivial issues such as unportable code. Contributing the patchesBefore you can contribute the patches, your GitHub username needs to be added to the list of permitted users. Any already-permitted user can do that, by adding a comment to your PR of the form Both the person who commented An alternative is the channel
Once on the list of permitted usernames, you can contribute the patches to the Git mailing list by adding a PR comment If you want to see what email(s) would be sent for a After you submit, GitGitGadget will respond with another comment that contains the link to the cover letter mail in the Git mailing list archive. Please make sure to monitor the discussion in that thread and to address comments and suggestions (while the comments and suggestions will be mirrored into the PR by GitGitGadget, you will still want to reply via mail). If you do not want to subscribe to the Git mailing list just to be able to respond to a mail, you can download the mbox from the Git mailing list archive (click the curl -g --user "<EMailAddress>:<Password>" \
--url "imaps://imap.gmail.com/INBOX" -T /path/to/raw.txt To iterate on your change, i.e. send a revised patch or patch series, you will first want to (force-)push to the same branch. You probably also want to modify your Pull Request description (or title). It is a good idea to summarize the revision by adding something like this to the cover letter (read: by editing the first comment on the PR, i.e. the PR description):
To send a new iteration, just add another PR comment with the contents: Need help?New contributors who want advice are encouraged to join git-mentoring@googlegroups.com, where volunteers who regularly contribute to Git are willing to answer newbie questions, give advice, or otherwise provide mentoring to interested contributors. You must join in order to post or view messages, but anyone can join. You may also be able to find help in real time in the developer IRC channel, |
There are issues in commit d2a68b0c1752fc0ff01cbca044f50679438d1330: |
/allow |
User DEGoodmanWilson is now allowed to use GitGitGadget. WARNING: DEGoodmanWilson has no public email address set on GitHub |
I thought that would be the case. I couldn’t quite get the syntax for it right. I’ll try with the parens. |
You will want to do these things before submitting upstream, or at minimum update your title with "[RFC]" and fill your PR description with questions you'd like to see from the community. |
(This is…well, it shouldn’t be true. Just checked my settings to verify. A bug in the bot?) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice!
I left a couple of suggestions how to improve the patch. The commit message will also need a bit of work, maybe this?
init: allow overriding the default branch name for new repositories
There is a growing number of projects trying to avoid the non-inclusive
name `master` in their repositories. Currently, the only way to do that
automatically is by copying all of Git's template directory, then
hard-coding the desired default branch name in the `HEAD` file, and then
configuring `init.templateDir`.
To make this process much less cumbersome, let's introduce support for
`init.defaultBranchName`. That way, users won't need to keep their
copied template files up to date, and won't interfere with default hooks
installed by their administrators.
While at it, also look at the environment variable
`GIT_TEST_DEFAULT_BRANCH_NAME`, in preparation for adjusting Git's test
suite to a more inclusive default branch name.
Also, feel free to add the footer:
Reviewed-by: Johannes Schindelin <johannes.schindelin@gmx.de>
followed by your Signed-off-by: line.
Further, Documentation/config/init.txt
will need to describe the new config setting.
Lastly, this will need new regression tests. The best place for it is likely t/t0001-init.sh
. Ideally, I would like to see a new test_expect_success
that verifies via test_config
and test_must_fail
that an invalid branch name is rejected and then verifies that a correct branch name is respected (by git -C <directory> symbolic-ref HEAD >actual
and then using test_cmp
with a pre-generated expect
file), followed by another new test_expect_success
that verifies that the environment variable can override the config setting.
Oh, and we will probably want to get clarity what happens when running git clone
on a repository that has no commits yet. If it respects that init.defaultBranchName
setting automatically, we will want to mention that in the commit message. Otherwise, we will want to make Git respect it ;-)
* Create the default symlink from ".git/HEAD" to the "master" | ||
* branch, if it does not exist yet. | ||
* Create the default symlink from ".git/HEAD" to the default | ||
* branch name, if it does not exist yet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good!
builtin/init-db.c
Outdated
*/ | ||
path = git_path_buf(&buf, "HEAD"); | ||
reinit = (!access(path, R_OK) | ||
|| readlink(path, junk, sizeof(junk)-1) != -1); | ||
if (!reinit) { | ||
if (create_symref("HEAD", "refs/heads/master", NULL) < 0) | ||
char *default_branch_name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest an empty line after the declaration, for readability.
builtin/init-db.c
Outdated
*/ | ||
path = git_path_buf(&buf, "HEAD"); | ||
reinit = (!access(path, R_OK) | ||
|| readlink(path, junk, sizeof(junk)-1) != -1); | ||
if (!reinit) { | ||
if (create_symref("HEAD", "refs/heads/master", NULL) < 0) | ||
char *default_branch_name; | ||
git_config_get_default_branch_name(&default_branch_name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can just call git_config_get_string("init.defaultbranchname", &default_branch_name)
directly?
Also, for testing, it would be good to let the environment variable GIT_TEST_DEFAULT_BRANCH_NAME
override this, i.e. something like this:
const char *branch_name = getenv("GIT_TEST_DEFAULT_BRANCH_NAME");
if (!branch_name &&
git_config_get_string_const("init.defaultbranchname", &branch_name) < 0)
return error("could not get `init.defaultBranchName`");
if (!branch_name)
branch_name = "master";
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't quite follow what you're suggesting here (the return statement is confusing me…). Are you suggesting replacing the method git_config_get_default_branch_name()
with the sample code? In git_config_get_default_branch_name()
, I am checking the env, but only after checking the config, which seems to be the pattern for config vars. It appears you are also suggesting reversing the priority here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally, I like the helper method to avoid extra complexity here.
The fact that git_config_get_string_const()
returns a negative value means something went horribly wrong while parsing config, so we should probably halt here. However, it would be better to signal an error higher up.
In this case, I don't think the extra care here is merited. Perhaps we should just do the following?
const char *branch_name;
if ((branch_name = getenv("GIT_TEST_DEFAULT_BRANCH_NAME") &&
*branch_name)
return branch_name;
if (git_config_get_string_const("init.defaultbranchname", &branch_name))
return branch_name;
return "master";
(nit: replace my spaces with tabs)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a really good suggestion.
builtin/init-db.c
Outdated
char *default_branch_name; | ||
git_config_get_default_branch_name(&default_branch_name); | ||
/* prepend "refs/heads/" to the branch name */ | ||
struct strbuf sb = STRBUF_INIT, sb_sanitized = STRBUF_INIT; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please note that Git is pretty strict about the "no declaration after a statement" rule, i.e. you would have to declare this variable at the beginning of the scope.
builtin/init-db.c
Outdated
/* prepend "refs/heads/" to the branch name */ | ||
struct strbuf sb = STRBUF_INIT, sb_sanitized = STRBUF_INIT; | ||
strbuf_addstr(&sb, "refs/heads/"); | ||
strbuf_addstr(&sb, default_branch_name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A quicker way to do this would be char *prefixed = xstrfmt("refs/heads/%s", branch_name);
(but you'll need to declare the variable separately, at the beginning of the scope).
Later on, this needs to be free()
d. You can do it like this:
char *prefixed = NULL;
if (!branch_name)
branch_name = "refs/heads/master";
else
branch_name = prefixed = xstrfmt("refs/heads/%s", branch_name);
[... use `branch_name`...]
free(prefixed);
This works because free(NULL);
is a no-op.
builtin/init-db.c
Outdated
struct strbuf sb = STRBUF_INIT, sb_sanitized = STRBUF_INIT; | ||
strbuf_addstr(&sb, "refs/heads/"); | ||
strbuf_addstr(&sb, default_branch_name); | ||
sanitize_refname_component(sb.buf, &sb_sanitized); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest to be stricter and to validate the name instead, i.e. call check_refname_format(branch_name, 0)
. If it is misconfigured, do not try to fix it, but tell the user about it and error out instead.
config.h
Outdated
@@ -598,6 +598,8 @@ struct key_value_info { | |||
enum config_scope scope; | |||
}; | |||
|
|||
int git_config_get_default_branch_name(char **output); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, we do not introduce such helpers. Maybe it would be a better practice, but we will want this patch to be as unproblematic as possible. To that end, I would like it to be as conforming with current coding style in Git as possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making it static
inside builtin/init.c
should be sufficient.
FWIW the build failure is due to the declaration of those two |
There are issues in commit d2a68b0c1752fc0ff01cbca044f50679438d1330: |
There is an issue in commit a5d486346cca3ba5665dc1da9b93290f3f7ce0a6: |
This is great stuff @dscho thank you! I'll look at your comments soon, in the next day or two. |
@DEGoodmanWilson I don't see any public email on the left side of your profile. That's essentially what GitGitGadget is looking for. |
There are issues in commit 6e94bc62eb911d5b5c0db67dcb77241929145be4: |
There are issues in commit 61d9f9ecb16f17c07e33859f3b7a3ac08b55eda4: |
@dscho I've made most of the suggested changes, however, please see the discussion here: #653 (comment) Next up is tests. |
There are issues in commit 3451b264b9ee1eb7b36c3af03d8f5e873b15c497: |
…itories. No documentation has been added, nor tests written, no any other checks done to see what this could break.
There are issues in commit c23823f: |
I've got some testing in place; unsure if they're written robustly or not, would love some 👀 on them! Next up: Docs, and cleaning up the commit message. |
const char *branch_name; | ||
char *prefixed; | ||
|
||
/* get the default branch name from config, or failing that, env */ | ||
if (git_config_get_string_const("init.defaultbranchname", &branch_name)) | ||
branch_name = getenv("GIT_DEFAULT_BRANCH_NAME"); | ||
|
||
if (!branch_name) { | ||
branch_name = "master"; | ||
} | ||
|
||
/* prepend "refs/heads/" to the branch name */ | ||
prefixed = xstrfmt("refs/heads/%s", branch_name); | ||
if(check_refname_format(prefixed, 0)) { | ||
die(_("Invalid value for default branch name %s"), branch_name); | ||
} | ||
|
||
if (create_symref("HEAD", prefixed, NULL) < 0) | ||
exit(1); | ||
|
||
free(prefixed); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you took @dscho's plan to consume the config directly here. Good.
I do think this method is complicated enough, so extracting your implementation might be good. There are also a few style issues with extra curly braces.
I made a fixup!
commit for you at derrickstolee@a890fcb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this. It is an abstraction at a different level: not just retrieving the config setting, but handling the default, the environment and the prefixing, too. I like it!
@@ -464,4 +464,20 @@ test_expect_success MINGW 'redirect std handles' ' | |||
grep "Needed a single revision" output.txt | |||
' | |||
|
|||
test_expect_success 'custom default branch name from config' ' | |||
git config --global init.defaultbranchname nmb && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: tab here.
test_expect_success 'custom default branch name from env' ' | ||
GIT_DEFAULT_BRANCH_NAME=nmb git init custom-env && | ||
grep nmb custom-env/.git/HEAD | ||
' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that your logic currently has the config option overriding the environment variable. I believe that is the wrong direction, but you should make the behavior explicit in a test. (I make this suggestion because I have hit that exact problem before.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the common pattern in Git is that if there are environment variables and config settings for the same feature, the environment variable overrides the config setting.
|
||
/* get the default branch name from config, or failing that, env */ | ||
if (git_config_get_string_const("init.defaultbranchname", &branch_name)) | ||
branch_name = getenv("GIT_DEFAULT_BRANCH_NAME"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to use the GIT_TEST_
prefix here, otherwise the value will simply be unset by our test suite (meaning: we could not adjust the test suite incrementally).
Please use GIT_TEST_DEFAULT_BRANCH_NAME
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Very easy to miss.
A good point was raised on the Git mailing list: we also need to handle Lines 454 to 457 in b3d7a52
|
Right, and here is the location in the code that will need this to be adjusted: Lines 1267 to 1268 in b3d7a52
Loosely related, I found these location that also need to be adjusted: git/builtin/submodule--helper.c Line 1984 in b3d7a52
Line 16 in b3d7a52
Line 309 in b3d7a52
Line 13 in b3d7a52
Lines 277 to 287 in b3d7a52
Lines 2100 to 2105 in b3d7a52
Line 409 in b3d7a52
Line 1049 in b3d7a52
In light of this, I fear that my initial preference to inline the logic in @DEGoodmanWilson I feel a bit sorry for dumping so much work on you, but you know where to find me (Gitter): I will be more than eager to assist in any way I can. |
Yes, I felt that this functionality might be needed in multiple places, which was why I had originally chosen
Hardly; no need to apologize. The feedback has been very helpful in understanding the git codebase, which I'd never looked at before this week! We'll get this figured out and move on to bigger picture things soon. It might be a few days until I can get around to handling the latest round of comments, just FYI, but I won't let this effort lose momentum. |
Oh, please do look no further as git/git@master...fd17a67 (I already did that for you...) |
And I'll allow myself to move a bit further, in the interest of pushing this PR forward (I really want to see this on the Git mailing list very soon....). |
Phew. That was a chunk of work. I opened a PR: #655 Now, my PR is not intended to override this here PR, but to augment it. I essentially wanted to make sure that we know that the path forward is clear because the test suite will pass with this. And so it does, at least locally. What this means is that in git/git@master...f442831, we have all the code changes necessary to make the new config option work! 🎉 What is missing, still, is the documentation changes ( We also have to decide whether this is an @derrickstolee what do you think? (For the record, I will now be offline for a few hours, so if you want to tackle the |
I think this is a great start! I'm excited for @dscho to submit his RFC for the full transition plan shortly after this patch is sent to the list. I just want to make sure this commit is as solid as possible. There is enough resistance to the change that I want to make sure there are no serious technical reasons to prevent it from being an acceptable change.
I am available to assist today. @DEGoodmanWilson: Let me know if you want to do any pairing on the documentation or just want to point me any updates so we can green-light the change! |
Okay, I'm back and will now tackle the documentation side. And I think I really prefer |
Now that this affects more than just |
@DEGoodmanWilson thank you so much for all your help! I submitted this patch, together with my modifications and additions, on the Git mailing list: https://lore.kernel.org/git/pull.656.git.1591823971.gitgitgadget@gmail.com. |
@DEGoodmanWilson can we close this? |
No documentation has been added, nor tests written, no any other checks done to see what this could break.
Thanks for taking the time to contribute to Git! Please be advised that the
Git community does not use github.com for their contributions. Instead, we use
a mailing list (git@vger.kernel.org) for code submissions, code reviews, and
bug reports. Nevertheless, you can use GitGitGadget (https://gitgitgadget.github.io/)
to conveniently send your Pull Requests commits to our mailing list.
Please read the "guidelines for contributing" linked above!