我想跑
git push origin --force CURRENT_BRANCH_NAME:sandbox
在預推鉤中。
如何得到
CURRENT_BRANCH_NAME
作為上述命令的一部分?
我知道我必須git branch --show-current回傳當前的分支名稱。只是不確定如何將其輸出與上述 git 命令一起使用。
uj5u.com熱心網友回復:
首先,我將回答您實際提出的問題:
要獲取當前分支名稱,請使用
git branch --show-currentorgit symbolic-ref --short HEAD或git rev-parse --abbrev-ref HEAD。 請注意,這三個命令的作用略有不同! 請參閱下面的詳細資訊。在 POSIX 兼容的 shell 中,要將命令的輸出替換為另一個命令內部的適當位置作為引數,請使用反引號或
$(and)。我更喜歡這個$(...)序列,因為它嵌套得很好:也就是說,你可以$(...)在里面放另一個$(...),因為括號嵌套它可以正常作業。反引號并非如此(它們可以起作用,但更棘手)。
接下來,我會注意到你不應該費心這樣做。原因很簡單:你必須選擇的一個以上的三個專案,其中兩個都可能是錯誤的,而這是所有不必要的。只需使用:
git push --force origin HEAD:sandbox
或者,在其中兩項可能錯誤的情況下,為了嚴格正確:
git push --force origin HEAD:refs/heads/sandbox
此變體使用完全限定的參考 ,refs/heads/sandbox來參考遠程 Git 中的分支名稱 sandbox,而不管嘗試HEAD轉換為 Git 提交哈希 ID 的結果如何。
為什么這有效
該git push命令將提交(不是檔案,不是分支,只是提交和其他支持 Git 物件)推送到另一個 Git。一旦提交(和/或其他支持Git物件)都在努力讓到其他Git和準備在那里使用,然后 git push 結束通過要求(非強制推送)或指令(強制推送)其他Git的創建,洗掉,或更新其存盤庫中的某些名稱。
為了實作這一系列事件,git push需要:
- 如果/根據需要,它應該發送的某些提交和/或其他支持 Git 物件的原始哈希 ID;
- 該名稱應該問/與操作指令的其他的Git來設定或洗掉,一起做(集VS洗掉); 和
- force 標志(可以是簡單的關閉/打開,或者更復雜的“帶租賃”樣式選項之一)。
你的 Git——你的軟體,從你的存盤庫發送到另一個 Git,它的軟體接收到目標存盤庫——從以下位置獲取這三個專案:
- 像
--force或inHEAD:refs/heads/sandbox或--deletein 之類的標志git push --delete,它們位于明顯的位置; - 為應的原始散列ID(一個或多個)發送,從左側的的一對;
src:dst - 對于要更新的名稱,從同一對的右側開始。
Git 呼叫對本身,有或沒有可選的 force 標志,一個refspec。feature:sandboxrefspecHEAD:sandbox也是如此,也是 refspec。事實上,即使是退化形式:
git push origin main
例如,使用 refspec:它只是缺少冒??號的一個,因此您只提供src一部分。這是一個部分refspec,在這種情況下,Git為目標使用與您為源提供的名稱相同的名稱(因為git push- 雖然git fetch也適用于 refspec,但它對部分 refspec 的處理是不同的)。
由于您已經計劃使用包含冒號的完整refspec,因此左側的專案不需要是name。該名稱,你的Git會發送到其他的Git來自的Refspec的右手邊。
Now, there's a small hitch here: how does the sending Git (i.e., yours) know whether to ask the receiving Git to set a branch name (refs/heads/moo), or a tag name (refs/tags/moo), or perhaps some other kind of name (refs/for/moo for Gerrit for instance) if you give your Git an unqualified name like moo? The answer is that your Git and/or their Git will do their best to guess which kind of name you mean, but in general, when you are doing this—providing a full refspec, that is—it's wise to provide a full ref on the right, so that you know for sure what you intend to ask the other Git to set (or delete). This is especially true from scripts, which may operate without a human overseer.
Hence there is a general rule here
When you, as a human, are running:
git push origin feature3 v1.2
you know that feature3 is your own local branch name, and v1.2 is your own local tag name, so you know that this is really refs/heads/feature3:refs/heads/feature3 and refs/tags/v1.2:refs/tags/v1.2. But in scripts, which are generally write-once run-many-times, it's wiser to be explicit.
Coda: the three different commands
Git has two "modes" for HEAD: attached and detached. (Note: Git calls the latter detached HEAD mode; I made up the name attached HEAD mode as the obvious counterpart, but it's not officially a Git name.) In the attached-HEAD mode, the name HEAD is a symbolic reference to a branch name.1 In the detached mode, however, HEAD holds a raw commit hash ID.
The command git branch --show-current will show the name to which HEAD is attached when you are in attached-HEAD mode, but will silently print nothing and exit with a successful status when you are in detached-HEAD mode.
The command git symbolic-ref HEAD prints the full name of the branch to which HEAD is attached when in attached-HEAD mode, and produces an error message, no standard output, and a nonzero exit code when in detached-HEAD mode. It prints the short version of the branch name with --short but still produces the same no-output-but-error-instead when detached.
The command git rev-parse --abbrev-ref HEAD prints the shortened name of the current branch when in attached-HEAD mode, and prints the word HEAD when in detached-HEAD mode.
There's one more mode worthy of mention here, although it's quite rare: when you are on an "orphan" or "unborn" branch (Git uses both terms to refer to this state), the name HEAD is a symbolic ref to a branch name that does not exist. In this state, git branch --show-current and git symbolic-ref HEAD both succeed (and print the nonexistent branch name), but git rev-parse --abbrev-rev HEAD fails.
To test which mode you're in and get the commit hash ID:
detached=false unborn=false
branch=$(git symbolic-ref --short HEAD 2>/dev/null) || detached=true
if ! $detached; then
git rev-parse -q --verify HEAD >/dev/null || unborn=true
fi
After executing these five lines, $detached holds whether HEAD is detached (as a simple boolean result), $branch holds the branch name if HEAD is not detached, and $unborn contains the result of testing whether there is currently a commit, or making a new commit will create the current branch. (The need for $unborn is rare.)
1在古老的原始 Git 中,這是通過符號鏈接實作的:ln -s refs/heads/master HEAD例如。當它被移植到缺少符號鏈接的 Windows 時,Git 不得不洗掉這個特定的快捷方式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/341823.html
