合併不會發生在推,他們發生在git merge
(嗯,和pull
,但這只是取+合併,因此,合併發生在合併)。
似乎更有可能的是你做了這樣的事情:
<get copy from origin/develop>
<wait around for remote's origin/develop to acquire new commits>
git checkout develop # get onto (local) develop branch
<edit>
git commit -m message # create some new commit(s)
git push origin develop # attempt to push -- but this fails!
git pull
這是一個創建的合併提交(M
以上),這最後一步,因爲pull
意味着fetch
(獲得所有這些新提交的是現在在origin/develop
),然後merge
(帶上您的本地develop
並將您的提交與剛剛提取的新提交合並)。
如果您還沒有git push
編這個新的結果,那麼遠程回購沒有或者您的本地提交的,那些你已經標記C*
和M
。在這種情況下,你的狀態很好! (您可以通過運行git fetch
再次檢查,以確保您的本地回購的origin/develop
相匹配的遙控器中,然後做git log origin/develop
,看看裏面是什麼。)
它可以幫助記住,有兩個完全獨立的git回購這裏:你的,與你的東西;和你在這裏打電話給origin
的那個。 (我們稱之爲機器X
。)如果您要登錄到X
,它有它自己的單獨的提交歷史和分支名稱等等。在那邊,你可以將目錄切換到回購站,運行git log -1 develop
,並查看該分支的最新動態。
現在,如果您註銷X
並回到自己的機器上,則可以運行git log -1 origin/develop
。如果這與您在X
上看到的相同,則get fetch
沒有任何更新,因爲git fetch
確實(但更高效)所做的是登錄到X
並查看develop
中的內容。任何X
有你沒有在origin/develop
,fetch
帶來並增加到origin/develop
。現在您可以與X
同步了。 X
沒有你的東西,但你有他們的。
如果你再取做merge
(包括一個由pull
暗示),git會,如果有,做一個合併提交...額外的步驟,但是這一切都是你的回購,在分支的尖端(在這種情況下仍然是develop
)。除非並且直到你將這個合併提交到X
(或者X
上的某人從你那裏提取你的提交,但是現在讓我們忽略它:-)),X
將不會擁有它。
無論如何,只要遠程(X
這裏)沒有你的合併提交,你是黃金。由於他們沒有它,沒有人做。您可以執行develop
分支的rebase
以將您的提交(C*
)置於origin/develop
之上。這將擺脫合併提交(M
),然後你可以推一個簡單的快進到origin/develop
。
如果X
確實有您的合併提交 - 即,如果你以後你推pull
ED和得到了合併,那麼你就完蛋了(在某種程度上),因爲想必其他人獲得X
和目前正在使用你的合併提交。可以在X
上回滾回購,類似於您可以在自己的回購中使用git reset
和git rebase
等的方式執行此操作,但這通常是一個糟糕的主意。
現在,假設你有
有事實上被推到其他回購(在機器
X
),但你絕對確定沒有人看到你的變化,你一定要重置它們,而不是恢復他們(回覆數量爲「精神抖」「,並留下緊縮記錄,這可讓所有人輕鬆恢復,但也讓他們看到你的錯誤:-))。
這裏的竅門:你首先需要獲得計算機X的回購說「分支devel
的尖端提交C7」,其中C7是從早期你自己的圖,只是重新編號,使我可以以不同的方式命名每個提交:
--------------------------- C*--- M
--- C4 --- C5 --- C6 --- C7 ----/
那麼,你怎麼能做到這一點?那麼,一種方法是登錄X
, cd
進入回購(即使它是--bare
),並在那裏使用git update-ref
。假設C7的SHA1實際上是50db850
(如「git log」所示)。然後,你可以這樣做:
localhost$ ssh X
X$ cd /path/to/repo.git
X$ git update-ref refs/heads/develop 50db850
但是,如果你不能登錄X
,甚至只是不想,你可以做同樣的git push -f
。 (這有其他優點:特別是你的混帳回購協議就知道origin/develop
已倒,一旦push -f
成功完成。)只是做一個本地分支尖端指向正確的承諾:
localhost$ git branch resetter 50db850
localhost$ git log resetter # make sure it looks right
...
localhost$ git push -f origin resetter:develop
Total 0 (delta 0), reused 0 (delta 0)
To ssh://[redacted]
+ 21011c9...50db850 resetter -> develop (forced update)
localhost$ git branch -d resetter # we don't need it anymore
完成此操作後,機器X將恢復到您想要的狀態,並且您可以繼續操作,如果您從未推送過您不喜歡的合併。
注意,當你做push -f
,是否有人對M
頂部取得新的提交,這些將也成爲無形的(技術上他們仍然在那裏,您的合併一起提交,但他們「失去了「lost+found
感覺git fsck --lost-found
,並在幾個月後,他們將永遠消失)。
再次和非常重要:這種「共享回購的回退」的是爲共享式回購的其他用戶的一個很大的痛苦,所以真的確定你做之前還是可以的。
這類瑣碎的合併甚至不需要恢復的。將合併留在那裏沒有任何根本性的錯誤。但是,如果你正在處理更嚴重的錯誤合併,除了你的「oops」記錄之外,還有另一個缺點來恢復合併:它稍後會使「更改」更改變得更困難,因爲稍後的「合併故意「會看到早先的合併和想法:好吧,我不需要重新合併那些的變化。您必須「恢復恢復」。
我認爲這裏的正確結束課程是:看看(git log
),然後再推以確保您要推送的內容是您打算推送的內容。
或者更容易和更簡單:git ls-remote
。這使用獲取協議代碼來查看遠程具有的內容。但它隱藏了我要去的主題,即遙控器就像你的回購一樣!
即將推出的Git版本2的發行都有新的「安全功能」,這將是可用以git push -f
。但他們還沒有出來,所以這對你沒有幫助。我會稍後重新編輯它們,以便記錄它們。在此之前,請注意請注意:在這一點上,您正在與其他嘗試將新內容推送到共享存儲庫的任何人競爭。
您甚至可以通過原始SHA-1 ID執行此操作。雖然分支名稱可以連續多次正確輸入。
保留和過期是通過git的「reflogs」。共享服務器可能不會記錄所有ref更新;如果沒有,只有已經有新提交的私人回購纔會保留它們。最短的默認過期時間爲30天,即約一個月,對於不再從分支提示中獲得的提交。但是請注意,這是一個沒有趣味,瘋狂的爭吵,使得每個人都在通過他們的倉庫搜索「丟失」的提交之後,將其從共享倉庫中「推卸責任」後進行搜索。
哇,非常感謝這個廣泛的答案。不幸的是我把它推到了X.因爲我確信沒有其他人提出了新的提取,所以我想知道是否可以撤銷這些更改。 有一件事我真的不清楚:如果我重置兩個步驟,我是否留下了其中一個分支或兩者? – dmeu 2012-04-17 07:51:11
好吧,推之後,如果你真的確定* :-) ...你想要做的就是讓X關於分支'devel'的提示的想法倒回一點。讓我編輯答案... – torek 2012-04-17 07:59:36
呵呵,如果你把git reset HEAD〜2'移回兩步,這真的等於告訴git:「設置我現在所在的分支的尖端」 - 這很可能是你的'通過查找HEAD〜2開發' - 「到您提交的提交ID。如果你想看看是什麼提交,首先'git show HEAD〜2'。如果你從上圖中提交'M','HEAD〜2'是'M〜2',它通過'M'和'C *'備份。可能不是你想要的。 – torek 2012-04-17 08:55:43