[英]Git: Restore uncomitted changes from new branch
如果我有一個本地 git 存儲庫,在branch1中有未分階段的更改,請執行以下操作:
git reset --hard
如何在不丟失branch1更改的情況下做到這一點? 我必須從branch1或branch2中運行git stash
還是先提交這些文件? 或者我仍然可以從使用 git 之前恢復我未提交的更改嗎?
您可以在運行git reset
時省略--hard
,因為這會恢復您未暫存的更改。 如果由於某種原因這不可行,則必須使用git stash
。
您在這里犯的基本錯誤是認為“更改”(分階段或非分階段)是“在一個分支中”。 他們不是! 無論我們使用哪種含義,在 Git 具有的分支一詞的許多含義中,這都是正確的。 事實上,正如tkausl 所評論的那樣,在一個非常重要的意義上,你正在做的工作,就像你正在做的工作一樣,根本不在存儲庫中。
太多的 Git 介紹性教程一開始就暗示,或者甚至直接聲稱 Git 是關於文件和分支的。 不是:這真的都是關於commits的。 提交是存儲庫中的內容,或者大部分內容。一旦提交了某些內容,它就會被安全地永久保存——嗯,幾乎永遠並且幾乎是安全的(例如,你總是可以完全銷毀存儲庫)。 所以我們應該首先關注提交。
不幸的是,提交本身似乎都是抽象和模糊的。 如果你讓 Git 向你展示一個提交——例如使用git show
show——你會得到這樣的輸出:
$ git show
commit e4a4b31577c7419497ac30cebe30d755b97752c5 (tag: v2.37.0, ...)
Author: Junio C Hamano <gitster@pobox.com>
Date: Mon Jun 27 09:17:55 2022 -0700
Git 2.37
Signed-off-by: Junio C Hamano <gitster@pobox.com>
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 120af376c1..b210b306b7 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.37.0-rc2
+DEF_VER=v2.37.0
LF='
'
那是承諾嗎? 嗯,這是一個提交的表示,就像下圖是一個女人的表示一樣。 這實際上不是女人,而是一幅畫。 但它實際上也不是一幅畫:它是一幅畫的 JPG。 請注意,在我們甚至可以就某事物的真正含義達成一致之前,我們可能不得不四處走動。 這是我們遇到的問題之一,定義什么是提交。
盡管如此,一旦我們使用了一點 Git,我們至少對什么是提交有了一個很好的模糊概念:它是一個編號(按哈希 ID)實體,就像上面的 commit e4a4b31577c7419497ac30cebe30d755b97752c5
一樣。 我們可以在不知道更多的情況下長時間使用 Git,但我們不應該.
不幸的是,我們需要知道很多,至少最終是這樣。 吉特是棘手的! 有很多東西要學。 但是有一個最低限度的知識,這樣你就不會遇到麻煩,它是這樣的:
存儲庫存儲提交。 這不一定是它所存儲的全部,但這是主要的。
提交是一個編號(按哈希 ID)存儲文件和元數據的東西。
每個提交都存儲每個文件的完整快照以及該元數據。 快照就是這樣——一個快照——元數據會記住“關於這個提交本身的東西”,比如提交人的姓名和電子郵件地址。
每次提交的所有部分都會一直凍結。 提交中的任何內容都無法更改! 如果提交很糟糕,我們可以停止使用它,方法是制作一個我們使用的新的和改進的版本。 但這不會使舊的提交停止存在。 話又說回來,就像在古老的謎語中一樣,如果一棵樹倒在森林里而周圍沒有人聽到它,它會發出“噪音”嗎(其中“噪音”的意思是“冒犯了所有聽到它的人”)? 如果找不到提交,它是否存在有關系嗎?
Git通過那些又大又丑的哈希 ID 來查找提交。 人類不擅長這些,所以 Git 也給了我們分支名稱之類的東西。 我們使用的名稱——分支名稱、標簽名稱和所有其他類型的名稱——為我們存儲哈希 ID。 每個名稱實際上只存儲一個哈希 ID,但這已經足夠了。
因為提交快照都被凍結了(提交中的文件也神奇地進行了重復數據刪除——這很快就變得很重要,但您不必馬上知道),您實際上無法處理已提交的文件。 所以你沒有。 使用git checkout
或git switch
檢查提交的行為告訴 Git提取保存的文件。 這些成為您可以使用和處理/處理的普通文件。
這些普通文件不在存儲庫中! (嗯,在某種程度上這取決於我們如何定義repository ,但為了保持這個列表簡短,我們不要進入這個。)相反,它們位於您的工作樹或work-tree中。
最后,Git 從一個它用多個名稱調用的東西進行新的提交: index或staging area ,或者(現在很少見) cache 。 這個東西的存在是 Git 讓你運行git add
這么多的原因,它解釋了很多其他 Git 的怪異之處。
當你剛剛開始時,你可以在這個索引/暫存區域的事情上保持模糊。 只要記住它的存在並且很重要——它保存着你提議的下一次提交——並盡快開始了解它的更多信息。
一旦你真正了解了這八件事,你就可以在 Git 中完成一些工作。 您可以參考它的手冊頁,其中一些甚至可能開始有點意義。 😀
不幸的是, git reset
命令是一個非常龐大且復雜的命令,它可以做很多事情。 但是你會看到——正如SebDieBin 回答的那樣———— --hard
擦除工作樹文件,用來自某個提交的文件替換它們。 由於您現在已經記住了以上幾點——好吧,也許您已經記住了——您將知道工作樹文件實際上並不在存儲庫中。 它們可能來自某些提交,但如果您從那時起更改了它們,則更新的文件僅存在於工作樹中。 刪除這些文件——刪除它們並用提交的版本替換它們——因此會刪除您的更改,並且由於這些更改從未在Git 中,Git 無法幫助您恢復它們。
你可以認為這意味着git reset --hard
很可怕,小心它,這是個好建議。 但這還遠遠不夠:還有許多其他Git 操作可以永久刪除 Git 幫助您取回未保存更改的能力。 你真正需要知道的是什么讓你更安全。 一旦你提交了一些東西——從 Git 的索引或暫存區制作每個文件的完整快照——只要你能找到提交的哈希 ID,提交的文件就會被安全地存儲。 好吧,例如,只要您的筆記本電腦不着火。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.