问题
Starting with Git version 2.0, the default value for the push.default
config option if not specified in the user's config, is simple
.
According to the documentation, this means:
in centralized workflow, work like upstream with an added safety to refuse to push if the upstream branch's name is different from the local one.
When pushing to a remote that is different from the remote you normally pull from, work as current. This is the safest option and is suited for beginners.
In playing around with "git push" edge cases while writing training materials, I found a surprising ramification of the configuration options:
If you are on a branch that has no upstream configured, and you run git push my-remote
when you have two remotes, in some cases you will get the error:
fatal: The current branch my-branch has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream my-remote my-branch
And in other cases, the push will succeed and will create the new branch on the remote, and the remote-tracking branch to go along with it (but not configure the remote branch as upstream).
After some extreme confusion about the inconsistency and some digging through the documentation, I finally realized that the upstream
config option for push.default
(which simple
sometimes acts like) will only push to the upstream branch, and so will fail if no upstream is configured, whereas the current
config option (which simple
also sometimes acts like) will work regardless of whether an upstream is configured or not.
The crux of the matter, then, is whether Git is working as current
or as upstream
for a particular push when the simple
option is selected (or left blank). The documentation only says that it works as current
"when pushing to a remote that is different from the remote you normally pull from." So, how does it determine that?
I've checked some obvious things like which remotes do I have remote-tracking branches for, but the results still seem inconsistent between my two test repos. I've even tried adding a new empty repo as a remote for my repo that's giving me the error message, and trying to push to that, but I get the same error. Unfortunately, I've been playing with fetching and pushing in these test repos so much today that it's hard to pin down what the difference is.
But this question isn't about my specific repos or why they're behaving inconsistently; that's just an attempt to reverse engineer the answer to this question, which the documentation seems to leave unclear.
Answers that refer to the documentation would be greatly appreciated (I'm not sure the answer can be found there); answers that refer to Git source code are fine also, but I'm not fully fluent reading C so an explanation would be helpful. :)
回答1:
You can see in t5528-push-default.sh all the tested use-cases with git push using a push policy 'simple'
In particular:
test_expect_success 'push to existing branch, with no upstream configured' '
test_config branch.master.remote repo1 &&
git checkout master &&
test_push_failure simple &&
test_push_failure upstream
'
test_expect_success 'push to existing branch, upstream configured with same name' '
test_config branch.master.remote repo1 &&
test_config branch.master.merge refs/heads/master &&
git checkout master &&
test_commit six &&
test_push_success upstream master &&
test_commit seven &&
test_push_success simple master
'
test_expect_success 'push to existing branch, upstream configured with different name' '
test_config branch.master.remote repo1 &&
test_config branch.master.merge refs/heads/other-name &&
git checkout master &&
test_commit eight &&
test_push_success upstream other-name &&
test_commit nine &&
test_push_failure simple &&
git --git-dir=repo1 log -1 --format="%h %s" "other-name" >expect-other-name &&
test_push_success current master &&
git --git-dir=repo1 log -1 --format="%h %s" "other-name" >actual-other-name &&
test_cmp expect-other-name actual-other-name
'
If your upstream branch is specified (git config branch.master.merge refs/heads/master
), a simple or upstream push policy will work.
Provided the branch name matches the upstream one.
upstream
- push the current branch back to the branch whose changes are usually integrated into the current branch (which is called@{upstream}
). This mode only makes sense if you are pushing to the same repository you would normally pull from (i.e. central workflow).
simple
- in centralized workflow, work like upstream with an added safety to refuse to push if the upstream branch’s name is different from the local one.
If you think an edge-case is not covered by those tests, the new git bugreport command (Git 2.27+) can come in handy.
来源:https://stackoverflow.com/questions/62497089/how-does-git-determine-the-remote-i-normally-pull-from-to-decide-the-behavior