簡體   English   中英

GIT - 合並沖突后如何從提交中刪除文件?

[英]GIT - How to remove a file from a commit after a merge conflict?

情況如下:我的本地機器上有兩個提交。 首先,我添加了兩個我想丟棄的文件。 我不在乎他們是否丟失了,我也不在乎歷史。 在第二次提交中,我有幾個合並沖突,必須解決(雖然不是在這兩個文件中)。 所以我不知道軟重置在這里是否是個好主意,因為合並沖突。 也許最好重新推送所有內容,然后從存儲庫中刪除文件? IDk ..但我不想再次處理合並沖突。 謝謝。

假設您在自己的 Git 存儲庫中有兩個提交,您從未允許任何其他 Git 存儲庫“查看”。 例如,假設 (a) 您從未使用git push將它們發送給其他人,並且 (b) 您不允許隨機用戶進入您的筆記本電腦並閱讀您的所有文件。

在這種情況下,您的狀態很好,因為沒有其他人擁有這些提交 這意味着您有各種選擇。

...我不想再次處理合並沖突。

這會稍微減少您的選項集。

這里要記住的事情是:

  • Git 都是關於提交的。 提交具有 hash ID,因此您可以判斷任何給定的 Git 存儲庫是否具有任何給定的提交。 For example, you can just run git show hash-ID —I recommend cutting and pasting the hash ID from somewhere else because typing one in correctly is way too hard—and see if this Git knows about this hash ID.

  • Git 本身使用分支名稱查找hash ID。 這就是 Git 使用分支名稱的目的:查找 hash ID。 可以隨心所欲地使用它們; Git將使用每個名稱來查找一個特定的提交 hash ID。

當您進行兩次提交時,您是從git checkout branch-name開始的。 (If you didn't run your own git checkout , Git already did, so one way or another, you might as well have done this.) Then you edited some files, used git add as usual, and ran git commit to make the第一次提交。 完成后,您可能已經運行了另一個git checkout ,或者沒有; 然后你運行了git merge ,或者做了一些運行git merge的事情,並進行了第二次提交,這是一個實際的合並提交——只有真正的合並才會有合並沖突。

值得畫出你現在擁有的東西。 您可以獲得git log來為您執行此操作(請參閱漂亮的 git 分支圖,尤其是這個答案),或者只是自己繪制。 你應該這樣做,而不是我,因為你有你的 Git 存儲庫,而我沒有,而且我繪制的假設 Git 存儲庫可能與你的實際存儲庫不匹配。 不過,您的提交可能看起來像這樣:

...--F--G--H---I   <-- master, origin/master
      \         \
       \      L--M   <-- feature (HEAD)
        \    /
         J--K   <-- origin/feature

也就是說,您首先自己提交了L

git checkout feature     # new branch `feature` identifies commit `K`
... do some work ...
git add ...
git commit               # creates commit L

然后你合並,使用git merge或者git pull或者類似的東西:

git merge origin/master  # creates commit M

一旦你繪制了情況就更容易討論哪些文件在哪些提交中。

首先,我添加了兩個我想丟棄的文件。

這兩個文件是提交L中的新文件。 也就是說,在比較提交K和提交L時,存儲在KL下的快照中可能有任意數量的更改,但在L中肯定也有兩個文件不在K中。

我不在乎他們是否丟失了,我也不在乎歷史。

這為您提供了很多選擇。

在第二次提交中,我有幾個合並沖突,必須解決(雖然不是在這兩個文件中)。

這意味着合並提交M包含您對問題Git在將 files-as-seen-in-snapshot- L與 files-as-seen-in-snapshot- I合並時遇到的問題的答案(其中LI是合並提交M的兩個父項)。

由於您不想重復該合並工作,因此無論您接下來選擇什么選項,您都應該堅持提交M至少一段時間。

選項:添加一個新的提交

您可以簡單地在M之后添加一個新的提交,在其中刪除文件:

git rm file1 file2
git commit

這增加了一個新的提交N

...--F--G--H---I   <-- master, origin/master
      \         \
       \      L--M--N   <-- feature (HEAD)
        \    /
         J--K   <-- origin/feature

您的名稱feature現在指的是新提交N ,其中不存在這兩個文件。

優點很明顯:這是非常快速和容易做到的。

缺點是這兩個文件仍然存在並且將永遠存在於提交LM中。 如果並且當您將提交N給任何人時,您還必須給他們提交LM ,現在每個人都會在這兩個提交中看到這兩個文件,如果他們看的話。

如果這不是問題,這是您最簡單的選擇。

您可以構建兩個新的提交

假設雖然您不太在意,但您不想將這兩個文件公開給其他任何人。 這很容易! 你可以構建兩個新的提交,像這樣開始:

git checkout -b better-feature <anything that identifies commit K>

您可以使用原始 hash ID,或者在這種特殊情況下,如圖所示,名稱origin/feature來識別提交K 你現在有:

...--F--G--H---I   <-- master, origin/master
      \         \
       \      L--M   <-- feature
        \    /
         J--K   <-- better-feature (HEAD), origin/feature

您現在可以復制提交L但尚未提交結果:

git cherry-pick -n <hash-of-L>

(例如,使用git log中的剪切和粘貼來獲取 hash ID)。 -n告訴 Git不要提交這個 現在您可以刪除兩個有問題的文件:

git rm file1 file2

然后提交:

git commit

獲取缺少這兩個文件的L副本,我們將其稱為L'

...--F--G--H---I   <-- master, origin/master
      \         \
       \      L--M--N   <-- feature
        \    /
         J--K   <-- origin/feature
             \
              L'  <-- better-feature (HEAD)

現在你必須重復合並。

我不想再次處理合並沖突。

這是這種方法的缺點:必須處理合並沖突。 但是您不必再次實際解決它們,您只需從現有提交M中復制現有解決方案即可。 您可以這樣做:

git merge origin/master     # just as before

Git 現在打印了很多東西,包括顯示與以前相同的兩個合並沖突。 但不是打開文件來編輯它們,或者使用git mergetool ,或者你上次做的任何事情,這次你只是告訴 Git:給我和我上次使用的答案相同的答案

假設兩個有沖突的合並文件被命名為conflicts/c1.txtconflicts/c2.txt 您現在將運行:

git checkout feature -- conflicts/c1.txt conflicts/c2.txt

文件現在已解決,使用您以前的分辨率! 使用git status來驗證這一點,並在您喜歡的編輯器或文件查看器中查看文件以查看更新的內容。

(在 Git 2.23 或更高版本中,您可能更喜歡使用git restore--source feature和兩個選項-s-w ,而不是git checkout 。但效果完全相同)

假設這解決了所有問題,並且您為所有其他文件采用了 Git 的解決方案,那么您現在已准備好完成合並。

最終結果是一個新的合並M' ,它對這兩個文件使用相同的分辨率。 與 commit M不同,但與 commit L'類似,commit M'缺少您這次故意未添加的兩個文件,因此:

git diff feature better-feature

(將提交M與提交M'進行比較)顯示這兩個文件被刪除。

您現在可以完全刪除name feature ,將better-feature重命名為feature ,在必要/適當的情況下設置新feature的上游,等等。 或者您可以使用git checkout -B feature better-feature強制名稱feature指向新提交,然后刪除名稱better-feature ,以獲得:

...--F--G--H---I   <-- master, origin/master
      \         \
       \      L'-M'  <-- feature (HEAD)
        \    /
         J--K   <-- origin/feature

現有的提交LM仍然存在,但是因為不再有可以找到它們的名稱,所以git log --all --decorate --graph --oneline不會顯示它們。 運行git push origin feature將發送到origin提交M'L' ,但不提交ML

你能想到的還有很多其他的選擇

還有很多其他方法可以實現您喜歡的任何結果。 Git 是一套工具,不是針對某個特定問題的特定解決方案。 不過,這兩個解決方案是使用 Git 提供的工具集制作的,應該可以解決您的特定問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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