2016-08-18 81 views
1

我有一個裸露的git存儲庫B,從中我已經克隆了兩個存儲庫C和D.然後我添加了一些更改爲C的內容,後來被推送到B,最後被D拉出。是同步的。強制推送後修復歷史記錄

現在我想最後刪除推由C犯,所以我下面的:

$ git reset HEAD^ --hard 
$ git push -f 

(從http://christoph.ruegg.name/blog/git-howto-revert-a-commit-already-pushed-to-a-remote-reposit.html

和DI做:

$ git pull 

和我得到的輸出如下:

[[email protected] git1]$ git pull 
From /home/mkm/projects/git_tests/git1 
+ a5d681f...c481973 master  -> origin/master (forced update) 
Already up-to-date. 

git log給了我與以前完全相同的輸出。我想D上的歷史與C上的歷史相同。我從What and where does one potentially lose stuff when git says "forced update"?知道最後的git pull將我的歷史記錄與服務器上已更改的歷史記錄合併在一起,但實際上會發生什麼?我希望歷史在任何地方都能保持同步。

我知道我可以做git恢復提交,這是在這樣的場景中推薦的aproach,但我想了解爲什麼在強制推送的情況下,歷史將不會保持同步。

+0

我不認爲在這種情況下恢復提交,即使*有意義*,因爲你已經正式覆蓋(並丟失)從C的角度提交。 – Makoto

+0

你不想做'git pull'因爲它會合並您的本地更改。由於您只刪除了最後一次提交併且在本地仍然有提交,這只是一個提升。所以'git pull'是你不「看到」這個變化的原因。 'git fetch'和'git reset --hard'更好地反映了這一點。保管和備份,因爲這是版本控制,而不是備份。 – hakre

+0

@Makoto通過使用git-revert我的意思是完全取代'git reset HEAD^--hard; git push -f'。 – mike

回答

3

讓我們試着畫出你的資料庫的歷史(越高以上):

commit 1 --> o <-- the initial commit 
       | 
       ... 
       | 
commit N-1 --> o <-- B and C are here now 
       | 
commit N --> o <-- D is here 

你創造了一些提交對C(最多提交N),推到B,從D拉。所有三個回購與他們的master分行同步指向承諾N。 (如果您的分支沒有命名爲master,那麼只需輸入它的名字並閱讀)。

然後你強制master分支C回去承諾N-1並檢查出來(這是什麼git reset --hard做什麼)。

另外,您還強制Bmaster分支返回承諾N-1。這是git push -f在這方面所做的。

現在,承諾NBC存儲庫中不再存在。 這是您創造上C的提交1 .. N-1,他們推到B,從D(有B,同步CD)拉它們,然後在你創建的D提交N。它似乎從未在BC上創建提交N

然後在D上運行git pull,沒有任何變化。這是因爲在後臺git pull運行git fetch其次是git merge

git fetch從遠程存儲庫(B)檢索本地存儲庫中尚不存在的所有可重新提交的提交。這種情況沒有; B具有D上的提交子集。它還了解B上分行的當前位置。

git merge發現本地回購(D)是遠程回購(B)之前的一次提交,它無關。

爲了使D樣子B你可以D然後git reset --hard B/master運行git fetch。它將強制移動的master分支,其中的master分支然後將檢查出來。它基本上做git reset --hard HEAD~1做的B


這是不完全正確。該提交仍然存在,但無法使用分支進行訪問。這使得它成爲將在下一個垃圾回收中被刪除的孤立提交。雖然它仍然存在於存儲庫中,但可以使用其散列進行訪問,並且可以通過創建指向它的分支來恢復它。

+0

現在其全部清楚:-) – mike