「TL; DR」部分:提防只是盲目做git stash save && git checkout ... && git stash pop
。
實際上有幾件你可以取笑,特別是在使用git的命令行界面時。
特別是,「當前分支」(如果有的話)只是記錄在文件中的項目(該文件包含HEAD
參考,.git/HEAD
)。查看該文件的原始內容,您通常會看到ref: refs/heads/master
等。 (在「分離HEAD」模式下,您將看到一個原始SHA-1。)有一些低級別的git命令會更新HEAD
而不做任何其他操作。
但是,大多數人主要使用git checkout
來切換分支,除了正確的方法:-)來做到這一點 - 內置了一些保護。主要是,如果您有工作樹,它將拒絕切換分支或「索引」(AKA緩存)修改將被這樣的交換機丟失。假設您在分支A
上,並且您要求切換到分支B
。結帳過程必須:
- 得到存在於尖端的所有文件的清單提交分行
A
- 的獲取存在於尖端的所有文件的列表選項
B
- 的承諾在文件第一個不在第二個的列表中,從第二個列表中不在第一個文件的工作目錄
- 中刪除這些文件,將這些文件添加到工作目錄中
- 中的文件如果(且僅當)文件不同,則替換工作目錄內容[R
此外,退房時被做緩存「通過書寫」:如果文件F
爲A
和B
不同,的B
版本的內容將首先被複制到索引/緩存,然後寫入工作目錄。
如果你已經上演(與git add
)一些修改文件F
,或者你有一些未上演修改F
在你的工作目錄,該結賬過程將覆蓋這些階段性或非階段性變化,因此git checkout
停止帶有錯誤信息。如果文件F
將被刪除,那麼也會覆蓋(或者更準確地說,刪除)您的更改,因此checkout
也會停止。
在另一方面,如果文件F
是兩個犯了同一,在checkout
可以繼續:它只是離開未提交的更改上演或不分級。這就是爲什麼你有時可以,但不總是,只需git checkout
你想要工作的分支。
Git的 「藏匿」(如git stash
),正如你所看到的,獨立的分支。這裏的關鍵概念是每個存儲 - 你可以有多個活動 - 實際上是一個提交(或更確切地說,一組提交:兩個或三個,這取決於你存儲的內容)。但是,在您反對在分支機構上進行提交之前,我們必須再做一些區分。具體來說,「分支」一詞指的是兩三個不同的東西,在git中。
提交總是(必然)進入「提交圖」,因爲圖僅僅是由所有提交和它們的邊形成的東西。如果「分支」一詞意味着「提交圖的一部分」,這些存儲提交在分支上。但「分支」這個詞也指的是標識分支的名稱提示提交,並且在這裏,這些提交提交不會推進分支提示。 (見this post,也Jubobs,對的「分支」的多重含義的更多細節。)
的git stash
命令查看當前索引/緩存和工作樹的狀態,並從他們身上,使新的提交如果 - 這個「如果」事實證明是非常重要的 - 如果他們有未保存的分階段或未分階段的變化。其中一個新提交(可從其中找到其他提交)保存在特殊參考名稱stash
下。儘管沒有任何新的提交被添加到當前分支,所以它們不在任何命名的分支上。從這個意義上說,它們獨立於當前分支 - 但是因爲它們是提交,所以它們具有父提交ID,並且從特定意義上講,它們直接附加到完成時提交的提交。
這對於最終用戶來說意味着什麼往往是「沒有」:你可能不在乎,也不必關心。但是,如果您曾使用git stash branch
將存儲轉換爲分支,則意味着新分支將從存儲所附的提交中分離出來。 (這一點,因爲它的出現,通常是你想要什麼。)與定義,做git stash save && git checkout ... && git stash pop
別名或宏
一個風險是第一步,git stash save
,可以什麼都不做。如果它什麼都不做 - 如果它不在「存儲堆棧」上推送新的存儲 - 然後它成功了,並且你的別名或宏將繼續檢出其他分支,然後(嘗試)從藏匿處堆積出來。
如果在該堆棧上還有另一個(不同的)存儲器,那麼你打算在其他地方使用,那麼你只是試圖將它彈出到你剛切換到的分支中。
注意,有兩個堆疊的「如果」在這兒,必須持有,這個特定的錯誤兩個條件咬:
- 你需要什麼都沒有藏匿,並
- 你需要有一些現存的你不要想要彈出。
解決此問題的一種方法是使用腳本,而不僅僅是一個簡單的git別名來執行分支交換存儲序列。在腳本中,像往常一樣運行git stash
,但在存儲之前和之後,檢查stash
參考所解析的SHA-1(如果有)。如果這個變化,git stash save
保存了一些東西,所以有一些東西可以彈出,你可以繼續做結賬和流行的順序。如果它沒有改變 - 如果前後沒有隱藏,或者如果堆棧頂部的存儲仍然在堆棧的頂部,那麼沒有任何可以彈出的東西,你應該只是做一個結帳。
還有另一個bug可以咬你這裏;看到this answer到一個有點不同的問題,其中包括一些shell代碼表示上述「只有當save
實際推動某些東西」的規則彈出。
*如果我要切換分支,它會在切換到新分支之前自動保存我的工作副本。如果您有未提交的更改與您正在檢查的分支發生衝突,那麼Git不會讓您這樣做。你需要「手動」存儲它們; Git不會自動爲你做。 – Jubobs
好吧,知道我不只是錯過了一些東西。我猜想SourceTree中的彈出窗口詢問你是否想要放棄本地更改也應該提醒您在切換之前隱藏它們。 – Mathieson
如果你從命令行使用Git,我相信你會有更好的體驗,但這只是我的看法。特別是,我不確定SourceTree是否允許您定義別名/宏。 – Jubobs