2017-07-14 354 views
0

我爲子項目創建了master的my_branch(請參見下圖)。我不得不從my_branch中刪除很多文件,因爲它們與子項目無關,但這些文件仍然在master中需要。有一段時間,開發發生在master和my_branch中。重建或合併Git分支但保留已刪除的文件

既然子項目已經完成,我想要將my_branch中的更改重新綁定或合併到master。但我想保留所有在my_branch中刪除但仍然存在於master中的文件。最簡單的方法是什麼?

我意識到我應該已經創建了一個單獨的存儲庫並重構項目。但鑑於目前的情況,我能做些什麼,最好不要手動?

不幸的是,我不能假定所有被刪除的文件都在單獨的提交中。

* 172c3f3 (origin/my_branch, my_branch) comment 
| * e4f6849 (origin/master, origin/HEAD, master) Merge branch asdf 
| |\ 
| | * c796e73 aafg 
| |/ 
| * 75720e5 Merge branch zxcv 
| |\ 
| | * 7c694e9 changes 
| |/ 
* | 61370ac some 
* | 8afc0be development, 
* | d14263b bugfixes, 
* | 0d5a17f testing, 
* | 588cf8f maybe some cleanup 
* | 588cf8f here and there 
* | e1f990b and a lot of files 
* | 146212b removed 
* | 09c6278 but they are still needed in master 
|/ 
* 9a53a83 my_branch created here 
+0

這裏思考了我的頭頂部開始my_branch,然後提交主。將my_branch合併(或重新綁定)爲master。然後再次追蹤所有文件? – jrahhali

回答

1

UPDATE - 我以前的如何處理一個重訂期間edit提交的解釋是不夠不清楚是不準確的。澄清


一個可行的方法(如本建議)是編輯合併。有一個潛在的缺點,因爲這種合併會違反某些命令所做的假設(例如rebase,即使當給出--preserve-merges時也是如此)。這可能導致此類命令在報告成功時悄然產生損壞的結果。

還有一個選擇,雖然它比較複雜。它還涉及重寫分支的歷史,但是你提到你可能重新分支分支,所以我認爲這不是問題。

這裏的想法是從歷史中丟棄文件刪除,以便文件始終存在於創建分支時的狀態。 (說實話大概是本來應該做的事情。)

最好的程序取決於很多事情。有些更普遍可行(但更多參與),而另一些更容易執行(但只有在某些事情是真的時才起作用)。

聽起來好像這些文件不是一次全部刪除,而是在發生其他更改的相同提交中被刪除。

這可能是一個交互式重新分配工作。當然你可以用filter-branch做到這一點。這兩者的一些組合也可能是一種選擇。

如果my_branch與您所描繪的線性一樣 - 在分支上沒有合併提交 - 那麼您可能可以通過交互式底圖獲取。

git rebase --interactive master my_branch 

在彈出待辦列表,標註任何承諾可能包含不必要的缺失爲edit(而不是默認的pick)。隨着rebase的進展,它會在暫時提交每個補丁後暫停。要找到不需要的刪除,你可以做類似

git diff --diff-filter D --no-renames --name-only HEAD^ 

(更簡單的命令將工作;這試圖讓剛剛被刪除的文件名的列表,以便您可以檢查要反轉哪些特別的,你可能會或可能。不想要--no-renames;它的目的是爲了避免意外觸發重命名檢測,可能會阻止刪除顯示,但如果你真的重命名了很多文件,這將導致它顯示爲刪除。)

要反轉特別刪除

git checkout HEAD^ -- path/and/filename 

當你有刪除逆轉

git add . 
git commit --amend 

以上底墊命令也將完成你的工作的重訂基期到的master尖端。如果你不需要想要 - 例如如果你想工作合併到master而是 - 你可以不喜歡

git rebase --interactive `git merge-base my_branch master` my_branch 

的東西,如果這似乎說明書,或者如果有,將阻止其工作的複雜性,那麼你可能會喜歡filter-branch - 但要警告說,如果歷史很大,這可能會很緩慢。

在這種情況下,你需要的是一個tree-filter重新添加刪除的文件。您在刪除在主untrack所有文件 - 我會通過獲取所有文件的本地副本作爲合併基礎的

git checkout `git merge-base master my_branch` 
cp all/the/files/that/were/deleted some/path/where/I/can/find/them/later 

然後

git filter-branch --tree-filter 'cp some/path/where/I/can/find/them/later all/the/files/that/were/deleted' -- my_branch 
+0

謝謝,馬克,這是教育。我能夠使用你的方法來進行合併(我並不需要所有這些)。我也使用了部分Ben的答案。 –

1

master分支,做了合併,並通過--no-commit標誌:

git merge my_branch --no-commit

現在你可以取消刪除合併要刪除的文件:

git reset HEAD <file>

git checkout -- <file>

命令git status會告訴你哪些文件是要刪除,如果你願意的話,你可以分析一個腳本這個輸出選擇性地復位/簽出的所有被刪除的文件

,然後進行提交最終的結果:

git commit

+0

聽起來不錯 - 我會盡量報告。 –

+1

雖然這看起來很簡單,應該工作,但我不一定會推薦它。原因是如果他們遇到你的合併,進一步的重組可能會造成嚴重破壞。如果使用默認策略合併會成功(但會產生不想要的結果),那麼使用'--no-commit'來編輯合併會有些危險。如果你知道你永遠不能通過合併這個回購合併,如果你已經有所謂的「邪惡合併」 - 那就沒問題。如果沒有,我會考慮採取不同的方法(我將作爲一個單獨的答案發布) –

+0

感謝Ben和Mark:我使用了您的建議的元素,但是Mark's更有用。 –