您的git log
命令顯示ajryan/dev
上的提交,但不顯示temp-a
上的提交。您的rebase
命令被告知重新綁定temp-a
而不是ajryan/dev
上的提交,但推測不存在這樣的提交。形象地:
... - o - o - o <-- HEAD=temp-a
\
o - o - o - * <-- ajryan/dev
因此,不存在提交拿起和重訂到提交我已經標有星號*
。所以rebase -i
生成一個單一的無操作命令。
如果執行任何操作,底墊操作應通過移動temp-a
指向最後提交*
後添加上,這將使temp-a
點提交*
結論。 (如果沒有發生,這是rebase
中的一個小錯誤。)但是,如果您刪除了無操作,則重設操作將被中止,並且temp-a
將不會移動。
需要注意的是,如果你沒有有對temp-a
你能變基他們,或重訂其他分支不同的項目。這裏有兩個以上的插圖,從幾乎相同的基礎,但有一個承諾是對temp-a
不是在ajryan/dev
:
... - o - o - o - @ <-- HEAD=temp-a
\
o - o - o - * <-- ajryan/dev
在這種情況下,你可以把@
提交的其他提交的頂:
... - o - o - o
\ (illustration 1)
o - o - o - * - @
或底部,其他提交如下:
... - o - o - o
\ (illustration 2)
@ - o - o - o - *
在這裏,我已經離開了標籤(temp-a
和ajryan/dev
)。這是有目的的:在git中,分支標籤很容易移動(並且實際上預計只要它處於「前進」方式就會移動)。所有的實際分支都存儲在提交本身中。 git rebase
實際上做的是複製舊承諾到新的,以便您可以更改他們的父母年齡和/或內容。
在插圖#1中,我們重新提交了承諾@
:現在它已提交*
作爲其父項。所有其他提交都沒有更改,因此只有提交@
必須被複制。
然而,在插圖#2中,我們重新提交了原始僅在ajryan/dev
上的整個提交鏈。提交@
本身不變,但我們必須複製原始o - o - o - *
提交中的全部四個:我們複製第一個o
以將其父項設置爲@
。這個新提交有一個新的不同的SHA-1 ID,所以我們複製第二個o
以使用新的提交ID作爲它的父代。第二個副本強制執行第三個副本,然後強制執行*
提交的最後一個副本。關於這一點,請參閱下一節。
在Git中,加入提交的兩個不同的鏈,你通常會使用git merge
:
A - B
/ \
... - o M <-- HEAD=branch
\ /
C - D
這裏合併提交M
連接兩個鏈A - B
和C - D
從o
叉掉。如果所有A
到D
都存在,並且您創建新提交M
,則A
到D
之間沒有任何反應:它們仍然與以前相同。
但是,對於簡單的開發,通常更好的做法是「重新分配」工作:使C
和D
位於A - B
的「頂部」。但要做到這一點,你必須拷貝提交,因爲提交git是永久的和不變的。您將C
複製到一個新的,略有不同的C'
,並將D
複製到一個新的,略有不同的D'
。這是不同的約C'
最主要的是,它的母公司是B
,不o
,這是不同的約D'
的是,其母公司是C'
,不C
主要的事情:
A - B - C' - D' <-- HEAD=branch
/
... - o
\
C - D [abandoned]
一旦底墊複製完成後,你簡單地拋棄舊C
和D
提交,並開始假裝C'
和D'
是原始提交:
A - B - C - D <-- HEAD=branch
/
... - o
現在我們沒有長呃需要在圖中的小糾結,因爲我們已經忘記了所有關於原C
和D
,歷史看起來就像這樣:
... - o - A - B - C - D <-- HEAD=branch
的骯髒的祕密(不那麼祕密,不是髒),是由於原始C
和D
仍然在那裏,他們只是看不見(對你)。如果其他人具有原始的兩個C
和D
提交,則會使其真正變髒。 Git commit IDs是其內容的加密校驗和,包括父母SHA-1 ID,因此原始C
和D
仍然存在,並且與C
和D
以及其他任何人不同。
當你從其他人處提交提交時,這一點很重要:如果你將他們的提交重新分配到你的工作上,那麼將更改的ID。你製作新的複製品,你可能會忘記他們有原件,但他們不知道你的新副本,他們沒有忘記他們的原始ID。
如果您稍後向他們提交了他們提交的重新發布的副本,他們需要做更多的工作來提取他們的提交副本,並可能移動他們所做的任何其他工作。
總之,除非您事先與他們(無論他們是誰)做出安排,否則像插圖#2所示的變形通常不是一個好主意。
那麼「快進」呢?那麼讓我們再看一下插圖#1。假設o - o - o - @
鏈來自其他人(「拉取請求」),並且您通過將工作重新分配到他們的賬戶上來添加提交*
。讓我們重新繪製圖形過,再添加一個扭結,並把ajryan/dev
標籤背面:
... - o - o - o [your original '@' commit, before rebasing, was here]
\
o - o - o - * <-- ajryan/dev
\
@ <-- HEAD=(something, maybe "dev")
現在讓我們進一步假設他們,無論他們是誰,對他們dev
分支o - o - o - *
序列,並沒有做任何額外的工作,以便他們的東西在標記爲*
的提交結束。如果您向他們提供此提交序列,他們可以將它提取出來,並將提交@
添加到他們的dev
分支,只需將其dev
標籤向下滑動即可將其指向@
標籤。現在讓我們也刪除我們的ajryan/dev
標籤,並理清這些圖紙中的扭結,並使用標籤dev
。這裏的結果:
... - o - o - o - o - o - o - * - @ <-- HEAD=dev
這是他們都會有,而且你會有什麼,一旦你無論是在同步是。這是一個非常簡單的歷史記錄,即使它與實際開發過程略有偏差(您在未看到鏈接以*
結尾的情況下提交@
)。但是這是一種「重新設計」,使得開發工作更容易,而且一般人們想要做的事情。
向右滑動標籤(包括像這樣的圖紙中的向下和向右或向上和向右)是「快進」操作。如果您運行git merge
與--ff-only
,它將只會執行「合併」,如果它真的是這種非合併快進。
底線:我想你想衍合@
提交到ajryan/dev
的工作,但你沒有有的@
承諾變基。這就是爲什麼rebase給你一個noop
。在這種情況下,簡單的非合併快速轉發git merge
就足以讓您的標籤與其標籤匹配。
這也是值得我們思考的是:當你做git log X..Y
你問混帳像我一樣在這裏繪製圖形:
... - o - o - o <-- X
\
o - o - o <-- Y
的X..Y
概念實際上是說:開始用這個圖,拿出熒光筆並突出顯示X
指向的提交,以及所有提交從那裏離開和/或上下的提交。(這留下了Y
指向的三個o
未標記)。然後,找到Y
所指向的所有未提交的提交,並記錄這些提交。
如果顛倒了X
和Y
,如git log Y..X
,你問混帳「跑熒光筆」在提交由Y
標記,其中僅只有兩個o
S於X
離開,然後登錄所有提交指向的通過X
尚未突出顯示。所以在這裏你得到X上的兩個o
,並且沒有共享的。
如果'temp-a'是'ajryan/dev'的祖先,那麼我認爲這是預期的。 – 2014-11-23 23:56:02