我們的內(nèi)網(wǎng)有使用gitlab作為我們的版本控制工具锅移,最近組里出現(xiàn)了一次誤操作,沒有更新服務(wù)器的代碼到本地倉庫在抛,直接使用git push -f 強制將本地的修改覆蓋了遠(yuǎn)程倉庫的版本满着,將其他人的commit都給沖掉了蟹地,而且無法使用通常的git reset方式回滾授翻,因為使用 git log查看遠(yuǎn)程倉庫的提交歷史已經(jīng)沒有其他同事在這之前提交的commit記錄了或悲。
一般遇到這種情況孙咪,如果同事A將本地覆蓋了遠(yuǎn)程,覆蓋了同事B和同事C的commit巡语,而同事B和C本地倉庫依舊有他們的提交翎蹈,這個時候同事B和C只需要同步一下遠(yuǎn)程,然后再git push -f一下他們的提交捌臊,這樣就能將被覆蓋的commit重新合并到遠(yuǎn)程倉庫里面。
但是我遇到的情況比較特殊兜材,因為當(dāng)時同事B和同事C是在gitlab的網(wǎng)頁版直接編輯的文件理澎,并通過Gitlab提交,也就是說所有人本地都沒有同事B和同事C提交的內(nèi)容曙寡,這個時候同事A使用git push -f直接就沖掉了記錄糠爬,所以就沒辦法通過上面的辦法來回滾了。
廢話那么多举庶,下面記錄下找回的過程:
1 場景
Original:
(remote origin:)
branch master -> commit 111111
(local)
branch master -> commit 22222
After git push -f:
(remote origin:)
branch master -> commit 22222
2 找回步驟
(1)這個方法的前提是你有權(quán)限登陸部署了Gitlab的服務(wù)器执隧,我們需要找到Gitlab保存?zhèn)}庫的目錄,首先通過ssh登陸上Gitlab的服務(wù)器户侥,然后找到gitlab的存放倉庫的地方镀琉,默認(rèn)是在/var/opt/gitlab/git-data/repositories
。
在這個目錄下找到自己要回滾的倉庫蕊唐,并cd到該倉庫屋摔。
(2)在執(zhí)行回滾操作前一定要先進(jìn)行倉庫備份:
tar cvzf project-backup.tgz /path/to/project.git
備份好之后才可以進(jìn)行下面的操作。
首先gitlab的倉庫的目錄是這樣的:
config description HEAD hooks hooks.old.xxx info objects refs
在當(dāng)前目錄使用git fsck
工具找回上次執(zhí)行的危險操作替梨,直接執(zhí)行git fsck
命令钓试,該命令顯示所有未被其他對象引用 (指向) 的所有對象,會有如下輸出:
dangling commit ab1afef80fac8e34258ff41fc1b867c702daa24b
ab1afef80fac8e34258ff41fc1b867c702daa24就是可能被丟棄的commit副瀑,也就是被沖掉的commit弓熏,具體是自己想要的哪個,可以:
git log ab1afef80fac8e34258ff41fc1b867c702daa24
查看在這之前的commit歷史糠睡,找到自己想要回滾的commit挽鞠。
(3)找到了想要回滾的commit 哈希值,是不是可以在本地倉庫執(zhí)行
git reset --HEAD ab1afef80fac8e34258ff41fc1b867c702daa24
實現(xiàn)回滾了呢狈孔?答案是不可以的滞谢,因為倉庫關(guān)于被覆蓋的對象已經(jīng)被清除了,所以clone下來的倉庫是沒有被覆蓋的對象可以回滾的除抛,所以回滾操作還是需要在gitlab的實際倉庫里操作狮杨。
echo ab1afef80fac8e34258ff41fc1b867c702daa24 > refs/heads/master
將commit 哈希值直接添加到refs/heads/master文件里,然后克隆遠(yuǎn)程倉庫到本地到忽,你會發(fā)現(xiàn)以前的commit又神奇的回來了橄教。
具體的原理需要大家自己去了解git的原理清寇,參考這幾篇文章:
https://git-scm.com/book/zh/v1/Git-內(nèi)部原理-維護(hù)及數(shù)據(jù)恢復(fù)
https://superuser.com/questions/297973/how-can-i-recover-from-an-accidental-git-push-f/298015#298015
希望對大家有所幫助。
Regards护蝶,
codjust