有人可以告訴我我的行為有什么問題嗎?我正在嘗試從遠程分支創建一個新分支,并將新分支推送到我的存盤庫。
Description:
-Currently on branch "test"
-git pull
-git checkout -b <new_branch_name> origin/test
我確認我的分支已切換到新分支。但是,當我通過 Visual Studio 提交/推送我的更改時,沒有創建新分支,并且更改被推送到遠程“原點/測驗”。
相反,如果我在沒有第二個引數“origin/test”的情況下運行 checkout 命令(雖然當前仍在 origin/test 分支上)然后我執行 git push,我的新分支就會創建
為什么會出現這種情況?
uj5u.com熱心網友回復:
TL;博士
這是因為您的新分支的上游設定為origin/test. Visual Studio 顯然(錯誤)使用它來決定要求遠程更新其test分支。
重要背景
分支不是從分支創建的。分支是從提交創建的。了解和理解這一點很重要;如果你認為分支在 Git 中意味著什么,你最終會傷害自己。這就像假設一輛 1980 年代的汽車具有自動駕駛能力。
上游
也就是說,Git 中的每個分支都可以有一個上游集。一個分支要么有上游集,要么沒有上游集。要設定特定的上游,請使用git branch --set-upstream-to:
git branch --set-upstream-to=origin/somebranch
例如。當前分支現在已origin/somebranch設定為其上游(除非命令失敗,在這種情況下沒有任何改變)。如果它之前已origin/otherbranch設定為其上游,則該上游現在被洗掉,因為只能設定一個上游:origin/somebranch現在是上游。
要取消設定上游,請使用git branch --unset-upstream:
git branch --unset-upstream
當前分支現在沒有上游。如果之前沒有上游,這個操作什么也不做;否則,它會洗掉上游設定。
一個分支的上游是:
- 另一個(本地)分支名稱,或
- 一個遠程跟蹤名稱,例如
origin/somebranch.
在命令列 Git 中,git push沒有附加引數的行為由push.default設定控制。如果將其設定為simple- 就像今天一樣 - 這種型別git push只會推送到當前分支的上游,并且只有當上游設定為遠程跟蹤名稱時 - 一旦遠程部分被洗掉 - 匹配當前分支。
例如,假定當前分支命名br1,都origin/br1和origin/br2存在。如果我們運行:
git branch --set-upstream-to=origin/br2
git push
我們會得到一個錯誤,git push因為 namebr2中origin/br2的 name 與 name 不匹配br1。但是,如果我們然后運行:
git branch --set-upstream-to=origin/br1
git push
這次git push將呼叫origin并嘗試讓 Git 存盤庫origin更新其他 Git 存盤庫的分支br1(我們在本地記得的另一個 Git 上的分支,如origin/br1)。
分支創建和上游設定
當我們選擇創建一個新的分支,與git branch,git checkout -b或git switch -c-我們必須給Git的兩件事情:
- Git 需要它應該創建的新分支的名稱。
- Git 需要一些現有提交的哈希 ID。新創建的分支將指向這個現有的提交。
在默認的哈希ID,如果我們不給Git的一個,是的哈希ID當前提交(如發現在當前分支的名字在大多數情況下)。也就是說,如果我們已經運行git checkout test以便當前分支名稱為test,那么我們運行:
git rev-parse test
和
git rev-parse HEAD
我們將從兩個操作中獲得相同的哈希 ID。這是因為特殊的名字HEAD被連接到分支名稱test,分支名稱test指向提交其哈希ID兩個git rev-parse命令列印。
我們可以像這樣繪制這個設定:
... <-F <-G <-H <-- test (HEAD)
That is, the name test points to some commit with some hash ID, drawn here as H, which stands for "hash". Every commit in Git has both a snapshot and metadata, and the metadata in a commit contain a list of previous commit hash IDs, usually just one entry long. In this case commit H contains the hash ID of—i.e., "points to"—some earlier commit, whose hash ID we're just calling G. (The real hash ID, in each case, is some big ugly random-looking string of letters and digits.) Commit G has a snapshot and metadata, and thereby points to still-earlier commit F, which has a snapshot and metadata, and so on.
When we ask Git to create a new branch name, with git checkout -b newbr in this case, Git will:
- create the new name, pointing to the selected commit—in this case commit
H—and then - attach
HEADto the new name.
We can draw the result like this:
... <-F <-G <-H <-- newbr (HEAD), test
That is, both branch names point to the same commit (whose hash ID is H).
When we use this form of branch creation, the new branch has no upstream set. So newbr has no upstream. A command-line git push will, with the defaults in modern Git, give us an error; we will have to run git push -u origin newbr or git push -u origin HEAD to create a name newbr over on origin so that our Git will create origin/newbr locally, so that we have an origin/newbr to have as an upstream. The -u option to git push will then immediately set that as the upstream.
Visual Studio apparently behaves differently. If no upstream is set, VS apparently just runs git push origin newbr:newbr, rather than giving us an error.
You can, however, tell Git, at the time you create a branch, to set its upstream right then. To do so, you must use the form in which you give Git a specific commit by name rather than by raw hash ID:
git checkout -b newbr origin/test
for instance. This is what you are doing. When you use this form of git checkout -b or git switch -c or git branch, Git will, by default:
- use the name
origin/testto find a commit hash ID; - create the new branch name
newbrpointing to this commit; and - set the upstream of
newbrtoorigin/test.
Note this extra step 3, that does not occur when using git checkout -b newbr without that additional argument.
In command-line Git, this choice—to create a new branch with an upstream set—is actually controllable via multiple options:
- The
-tor--trackoption says do do this. - The
--no-trackoptions says do not do this. - The configuration setting
branch.autoSetupMergesays whether to do this, in which cases, when-tor--no-trackis not specified.
說明我上面蓋給出的正常行為時branch.autoSetupMerge是沒有設定,或者設定為true。您可以將其設定為false,在這種情況下,分支創建選項始終如同--no-track已指定一樣,您可以將其設定為always,當您提供本地分支名稱作為開始時,這會使 Git 將本地分支設定為新分支的上游觀點。
您可能不應該設定此選項,而只是避免給出git branch起始名稱,或使用以下--no-track選項:
git checkout -b newbr $(git rev-parse origin/test)
或者:
git checkout -b newbr --no-track origin/test
這兩種方法都將避免為新分支設定任何上游。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/405416.html
標籤:
上一篇:按鈕中的JavaFX算術運算式
