[英]Why won't --autostash option work ??? (used with git pull --rebase)
[英]Why does git pull autostash require a rebase?
如果我在本地存儲庫中編輯某些文件而不提交它們,並嘗試git pull
,那么它失敗的明顯原因是 git 不知道我打算如何協調對這些文件的新拉取更改與我擁有的未提交版本。
我知道解決方案是git pull --rebase --autostash
。 但為什么--rebase
是必要的?
如果為 true,則在獲取后將當前分支重新設置在上游分支之上。
git-rebase - 在另一個基礎提示之上重新應用提交
但在上述情況下,不需要在拉取的內容之上重新應用本地提交,只有未提交的更改。 為什么 git 決定要求--rebase
做--autostash
是否有某種邏輯,或者這只是偶然的?
TL;DR:這是一個歷史性的意外。
請記住git pull
的意思是:
運行git fetch
以從其他一些 Git 存儲庫獲取新提交。 任何人都可以隨時安全地執行此操作,因此此步驟基本上始終有效(除非由於某種原因您的網絡出現故障或其他原因)。
然后,假設第 1 步有效,運行第二個Git 命令以某種方式與當前分支混淆。
第2步是有問題的。 實際運行的命令通常是git merge
; 另一個選項是git rebase
。
現在,如果你有未提交的工作,你不能運行git merge
或git rebase
(有一個例外,我稍后會留下)。 在這種情況下,第 1 步很好,但第 2 步不是。
autostash 選項基本上為您運行git stash push
,而git stash push
意味着提交我現在擁有的內容,但沒有分支,然后執行git reset --hard
現在)。 完成后,第 2 步現在總是可行的。 如果第 2 步成功完成(盡管並非總是如此,無論您使用哪個第二個命令),Git 都會為您運行git stash pop
。
您可以在這里提出幾個合理的問題。 一個是:為什么在git merge
之前不允許這樣做? 您可以 stash、rebase 和 pop,但您也可以 stash、merge 和 pop; 如果你可以存儲、合並和彈出,為什么不把它作為一個選項呢? 唯一真正的答案是:當 rebase 是一個花哨的 shell 腳本時,將--autostash
選項添加到 rebase 並且在那里添加它更容易。 合並命令不是一個花哨的 shell 腳本,而且更難在其中添加它。
另一個問題是我認為您確實問過的問題:如果您沒有自己的提交,並且在需要時進行了git stash push
,則git merge
- 在這種情況下,默認情況下會執行快進操作,這意味着它實際上並沒有合並任何東西——並且git rebase
最終會做同樣的事情:直接檢查另一個 Git 的最新提交(並且在 pull 的第 2 步中沒有失敗)。 同樣,人們可能想知道為什么不允許--autostash
處理這兩種情況。 同樣,唯一真正的答案是“因為添加到變基代碼路徑更容易”。
我們應該注意到,即使git merge
可以進行快進,但它並不總是這樣做。 特別是,您可以使用git merge --no-ff
強制 Git 進行真正的合並而不是快進操作。 您可以使用git config
將其設置為在 pull ( pull.ff
) 或 always ( merge.ff
) 上發生。 因此,即使它可以進行快進,pull 也可能會進行合並。 盡管如此,如果它可以快進,它會做的合並就會成功,我們又回到了和以前一樣的情況。
現在是時候提到一種特殊情況了。 當git merge
可以並且確實選擇執行快進操作時 - 本質上, git checkout
出會在提交圖中將分支名稱向前拖動 - 而不是真正的合並, Z0BCC70105AD2795063E31FE7也可以執行此操作。未提交的工作,只要未提交的工作位於結帳未更新的文件中。 因此,有一種git pull
使用git merge
的情況,不需要自動存儲。 盡管如此,實際上做一個推/快進/彈出序列會很好,而且我們真的又回到了歷史事故。
如果你對這類事情有強烈的感覺,你總是可以編寫一個補丁來教 Git 如何進行git pull
和/或git merge
與自動存儲合並。 Git 的源代碼可用; 例如,參見https://github.com/git/git上的僅發布克隆。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.