2014-01-21 60 views
7

關於強制輸入git push的問題不難發現(heretwo)。標準答案是這樣的:`git push --force`的其他後果?

如果你有強制git push,在技術上你可以--force選項,但在程序上你不應,因爲有人可能已經拉到某處小貓會死。

我認爲這是一般的賢者忠告 - 更安全的途徑是再次承諾,修復任何你破碎的東西。但是讓我們說,例如我知道(神奇地)沒有人已經提交了提交。或者更好的是,這是一個私人回購,所以沒有打破任何人的克隆的危險。

是否有任何其他--force後果是否爲推動,特別是技術後果?也許它會在遠程造成一些額外的垃圾,或者破壞X Corps的分析工具1.2.3版本,或者使得重新綁定更容易混淆,等等。任何事情?

編輯1:我有自己的軼事證據表明--force荷蘭國際集團的私人回購的推動的確顯得不造成任何問題。雖然我對知覺不感興趣,我正在尋找參考和/或這樣的證明。

回答

8

即使移動不是快進操作,強制推送也只是告訴遠程移動給定的標籤。 非快進可以(不一定)導致「放棄」提交:從某個引用不再可訪問的提交。

(它確實爲此當標籤運動上被其他部分所引用的曲線圖的一部分中出現例如,如果分支xyzzy點到序列中提交D

A-B-C-E <-- plugh 
    \/
    D <-- xyzzy 

然後標籤xyzzy會發生什麼,因爲標籤plugh使得提交D可達,因此以非快進方式將xyzzy移動到例如指向提交C根本不會影響提交D同樣,刪除標籤xyzzy完全也是無害的,至少在提交圖結構方面。)

遠程裸倉庫(通常會向其中推送)通常不會記錄所有ref更新,因此這往往會觸發對任何放棄的提交的快速垃圾回收。 (請注意,如果您將它們放在自己的存儲庫中,則可以稍後恢復gc'ed提交 - 但這需要您通過網絡再次發送數據,並且如果您自己的repo被損壞,則可能導致數據丟失風險,電源故障或電腦着火)。

如果您有一些第三方軟件假定(部分或全部)分支標籤僅以快進方式移動,則說該軟件可能以有趣的方式失敗。我知道沒有這樣的軟件,如果它存在,我會稱它爲「破」,但人們通常似乎寫破碎的代碼,然後依賴它。


混帳允許標籤的舊版本沒有力量推動,如果此舉是快進,以同樣的方式分支標籤有望走高。較新的版本(我認爲在1.8.2中介紹過,但這只是內存),除非您使用強制,否則拒絕任何標記運動。當然,你可以隨時刪除,然後重新創建(可能在不同的地方)一個標籤,內置的鉤子就可以。因此,還有其他方式可以以任意方式移動標籤或分支,即使沒有力量。只要確保您要保留的提交圖的各個部分在每個操作中都有一些標籤。


,作爲使(自己)基礎重建困難後:是的,它可以這種效果,因爲你可能會強制推從「桌面」,因此,實際上,重新排列「共享bare-回購」。後來,在「筆記本電腦」上,您可能無法記住哪個提交您重新發布,找出它可能有點棘手,特別是在大型,高度活躍的存儲庫中。

幸運的是,即將推出的新git版本具有一項新功能,該功能使用您的reflog來確定是否以及何時發生了「上游基準」。也就是說,在上述情況下,您可以(在「筆記本電腦」上)讓git自動發現共享裸回購中的哪些提交已重新分配,以及「重新重新分配」您的筆記本電腦工作。 (這是今天git pull --rebase使用的方法的推廣,在混帳1.8.x.)

+0

+1。至於「新即將發佈的git版本有一個新功能,它使用你的reflogs來確定是否以及何時發生了」上游rebase「,它是'fork_point = $(git merge-base -fork-point origin /主題); git rebase - 去往origin/master $ fork_point topic'。請參閱http://stackoverflow.com/a/20423029/6309。我不能等待那個:) – VonC

+0

謝謝!這些正是我所尋找的細節。 –

2

我在我的私人存儲庫上始終使用--force,沒有不良副作用,因爲我知道什麼時候我強制進行更改以及對代碼有什麼後果。

--force的唯一問題是它會更改上游存儲庫中的歷史記錄,並且有人可能在更改歷史記錄之前更改了存儲庫的狀態。這會導致問題 - 這也是爲什麼它不是推薦的解決方案。但即使如此 - 這些問題可以被修復,他們只是需要一點工作。

因此,要回答這個問題 - 如果您只是想與自己在私人回購中共享代碼,並且沒有其他人會受到這些更改的影響,則不會有其他副作用。

+0

我不知道,所以我做了一個編輯也許我原來的問題還不夠清楚。 –

6

爲了補充託雷克的出色答卷:

的力推動可能會導致以後合併問題。

問題:

如果強制推送一個分支,你是從該分支刪除一些現有的提交(否則你就不需要給力)。如果(如torek的回答中所述)這些提交也是從另一個分支B引用的,那麼它們將保留在該分支中。如果稍後再合併兩個分支A和B,則A將包含「新」(強制)提交,並且B「舊」提交。

在這種情況下git merge可能不會做你想要的。在最好的情況下,你會遇到合併衝突。最壞的情況下,你不會但結果仍然是錯誤的。例如,如果你使用git rebase -i從A中刪除了一個提交c1,如果c1也在B中,那麼如果合併A和B,它將被重新引入。這可能會默默地重新引入一個bug :-(。因此,如果您強制推送,請確保您移除的提交不從其他分支/標籤引用(或強制推送這些分支/標籤)。


插圖中刪除承諾 「迴歸」

運行的bash腳本以下的。該腳本創建一個Git倉庫,枝主,BRANCH1具有如下的提交:

  • 好提交(BRANCH1)
  • 錯誤提交(主)
  • 初始

然後:

  • 使用git reset --hard放棄來自主人的「不良提交」
  • 合併BRANCH1成主從劇本

輸出:

Initialized empty Git repository in .... 
[... creating commits ...] 
### Bad commit in history: 
* 7549dcc (HEAD, master) bad commit 
* 31afec8 Initial 
### Removing bad commit: 
HEAD is now at 31afec8 Initial 
### Bad commit no longer in history: 
31afec8 (HEAD, master) Initial 
### Merging branch1: 
Updating 31afec8..be801e5 
Fast-forward 
0 files changed, 0 insertions(+), 0 deletions(-) 
create mode 100644 b 
create mode 100644 c 
### Bad commit is back! 
be801e5 (HEAD, master, branch1) good commit 
7549dcc bad commit 
31afec8 Initial 

正如你可以看到,使用git reset --hard 「壞承諾」 從主刪除。然而,「bad commit」仍然包含在branch1中,所以當branch1合併到master中時,「bad commit」會返回。

注意:本示例實際上並未強制推送,但如果您使用上游回購協議,則必須在移除錯誤提交後強制推送 - 結果將相同。

腳本:

#!/bin/bash 
set -e 
if [ -e gitrepo ]; then echo "Please remove gitrepo"; exit 1; fi 

git init gitrepo; cd gitrepo; git config core.pager cat 
touch a; git add a; git commit -m Initial 
touch b; git add b; git commit -m "bad commit" 
git checkout -b branch1; touch c; git add c; git commit -m "good commit" 
git checkout master 

echo "### Bad commit in history: " 
git log --oneline --decorate 

echo "### Removing bad commit: " 
git reset --hard HEAD~1 

echo "### Bad commit no longer in history: " 
git log --oneline --decorate 

echo "### Merging branch1: " 
git merge branch1 

echo "### Bad commit is back!" 
git log --oneline --decorate 
+0

合併通常一次只能查看三個文件:合併庫的版本,HEAD的版本以及合併的版本。因此,如果合併分支的尖端仍然乾淨地融合,那麼您就「安全」了。基本上,爲了讓合併工作,你需要修剪掉任何不需要的「尾部」提交。對於大毛茸茸的討厭的合併,你可能想要使用像git-imerge這樣的工具,然後你會希望整個鏈都是「乾淨的」(這裏再次說明,git 1.9的新代碼可以幫忙)。 – torek

+1

@torek:正如我試圖解釋的,如果分支幹淨地合併,你就不安全。如果你刪除了一個提交(使用'rebase -i' /'reset'),它會返回,如果它也在分支中,那可能不是你想要的。 – sleske

+0

嗯,我明白你的意思了:提交提交可能仍然包含一些或所有不需要的早期提交。是的,同意了。 – torek