簡體   English   中英

Git:從新分支恢復未提交的更改

[英]Git: Restore uncomitted changes from new branch

如果我有一個本地 git 存儲庫,在branch1中有未分階段的更改,請執行以下操作:

  1. 結帳到新分支: branch2
  2. 提交一些(不是全部)文件
  3. branch2運行git reset --hard
  4. 結帳回到branch1

如何在不丟失branch1更改的情況下做到這一點? 我必須從branch1branch2中運行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,但我們不應該.

使用 Git 時需要知道的絕對最小值

不幸的是,我們需要知道很多,至少最終是這樣。 吉特是棘手的! 有很多東西要學。 但是有一個最低限度的知識,這樣你就不會遇到麻煩,它是這樣的:

  • 存儲庫存儲提交 這不一定是它所存儲的全部,但這是主要的。

  • 提交是一個編號(按哈希 ID)存儲文件和元數據的東西。

  • 每個提交都存儲每個文件的完整快照以及該元數據。 快照就是這樣——一個快照——元數據會記住“關於這個提交本身的東西”,比如提交人的姓名和電子郵件地址。

  • 每次提交的所有部分都會一直凍結。 提交的任何內容都無法更改! 如果提交很糟糕,我們可以停止使用它,方法是制作一個我們使用的新的和改進的版本。 但這不會使舊的提交停止存在 話又說回來,就像在古老的謎語中一樣,如果一棵樹倒在森林里而周圍沒有人聽到它,它會發出“噪音”嗎(其中“噪音”的意思是“冒犯了所有聽到它的人”)? 如果找不到提交,它是否存在有關系嗎?

  • Git通過那些又大又丑的哈希 ID 來查找提交。 人類不擅長這些,所以 Git 也給了我們分支名稱之類的東西。 我們使用的名稱——分支名稱、標簽名稱和所有其他類型的名稱——為我們存儲哈希 ID。 每個名稱實際上只存儲一個哈希 ID,但這已經足夠了。

  • 因為提交快照都被凍結了(提交中的文件也神奇地進行了重復數據刪除——這很快就變得很重要,但您不必馬上知道),您實際上無法處理已提交的文件。 所以你沒有。 使用git checkoutgit switch檢查提交的行為告訴 Git提取保存的文件 這些成為您可以使用和處理/處理的普通文件

  • 這些普通文件不在存儲庫中! (嗯,在某種程度上這取決於我們如何定義repository ,但為了保持這個列表簡短,我們不要進入這個。)相反,它們位於您的工作樹work-tree中。

  • 最后,Git 從一個它用多個名稱調用的東西進行的提交: indexstaging 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM