2015-09-28 119 views
1

我創建了一個本地分支(git checkout -b),其中我做了一些髒提交(「WIP」等)。我從來沒有推到遙遠的地方。我現在想推前一些提交重命名/壁球:Git rebase一個沒有遠程的本地分支

$ git rebase -i 
There is no tracking information for the current branch. 
Please specify which branch you want to rebase against. 
See git-rebase(1) for details 

    git rebase <branch> 

If you wish to set tracking information for this branch you can do so with: 

    git branch --set-upstream-to=origin/<branch> feature/position-preview 

話,我的建議:

$ git branch --set-upstream-to=origin/feature/my-feature feature/my-feature 
error: the requested upstream branch 'origin/position-preview' does not exist 
hint: 
hint: If you are planning on basing your work on an upstream 
hint: branch that already exists at the remote, you may need to 
hint: run "git fetch" to retrieve it. 
hint: 
hint: If you are planning to push out a new local branch that 
hint: will track its remote counterpart, you may want to use 
hint: "git push -u" to set the upstream config as you push. 

的事情是,我不想push -u,因爲它是,因爲它會導致不良的歷史。

如何重新綁定我的新本地分支?

回答

0

Git的文檔的muchderision主題...有很好的理由:

git的變基[-i | --interactive] [選項] [--exec <CMD>] [--onto <newbase>] [<上游> [<分支>]]

此處該參數被標記upstream,和有幫助的( ?)從命令輸出參考git branch --set-upstream-toorigin/<branch>,這意味着您的本地分支必須有一個像origin/my-feature這樣的遠程分支才能工作。但事實並非如此。

git rebase做什麼是副本一系列提交,每個拷貝發生,如果你想在一個特定的運行git cherry-pick提交。通過複製每提交一個線性提交圖中的提交,您將獲得複製開發分支的效果。 我認爲,這使得以圖表形式更有意義。例如,假設你有這樣的順序:

... <- o <- A <- B <-- master 
     \ 
      C <- D <- E <-- my-feature 

其中每個字母代表一些特定的承諾,其中一個大丑40個字符的SHA-1的數和提交歷史my-feature與commit-連接起來master的歷史記錄在提交o。如果您在master上創建了新分支my-feature,然後又回到分支master,進行了兩次提交,然後轉至my-feature並進行了三次提交(每次提交的實際順序)無所謂:我只需要你在master上做了兩個,現在我把他們作爲現在作爲第一個A和第二個B,並且在my-feature上有三個。現在

,因爲它與發展情況,你可能會決定它將使基礎上,master當前提示,即更有意義C -through- E,有C的父提交是B

一個非常手動的方法來實現這一目標是:

$ git checkout master 
$ git checkout -b new-my-feature 
$ git cherry-pick <id of commit C> 
$ git cherry-pick <id of commit D> 
$ git cherry-pick <id of commit E> 

這使得一個新的分支,new-my-feature,並複製三個提交,這個結果:

   C' - D' - E' <-- new-my-feature 
      /
... o - A - B <-- master 
     \ 
     C - D - E <-- my-feature 

的方式混帳構造新的提交C'將比較樹 - 關聯的源快照 - 對於C與其父提交o的樹,將相同的更改應用於t ree for B,然後重新使用提交消息C進行新的提交。換句話說,提交C'C的「副本」。 D'D相同,E'E相同。

在任何情況下,如果你把這個第三圖像,然後刪除my-feature分支標籤,並重新命名new-my-featuremy-feature,你得到的是:

   C' - D' - E' <-- my-feature 
      /
... o - A - B <-- master 

原來的三所老my-feature提交的「丟失「(他們通過」reflog「條目保存30天,但這些條目通常不可見,以免混淆視圖)。

git rebase所做的是自動執行此過程:它找到要複製的提交序列,將序列複製到其他提交中,然後移動分支標籤。

你可以指定的是,所有沒有非常好記錄的選項都是分支名稱 - 默認爲當前分支 - 通常在某種程度上,間接地指向停止複製的點。 「目標」提交,重定位爲--onto <newbase>,默認爲您給出的參數(如果有的話),請撥打<upstream>

這種工作方式依賴於理解其他相當重要的東西,這會影響雙點符號。

讓我們回到原來的圖形,我們再次做任何櫻桃採摘和分支標籤移動的,也就是說,之前我們變基之前有:

... - o - A - B <-- master 
     \ 
      C - D - E <-- my-feature 

現在讓我們來問git的是什麼版本在master..my-feature

$ git rev-list master..my-feature 
e59f6c2d348d465e3147b11098126d3965686098 
8413a79e67177d026d2d8e1ac66451b80bb25d62 
1f9e0a53489aaca7859722e037a47e93858cbc42 

(我做這些,但事實上這種設置,你會真正得到只有三個SHA-1)。

我認爲一個很好的方式來解釋這是在顏色填充/突出顯示(當然,我不能在這裏的文字做這個,所以你必須想像它)。

想象一下,您從my-feature的提示開始,即提交E。將此提交塗成綠色:這是「要使用」。然後,按照其父指針返回提交D。將此提交也刷爲綠色。跟着那個到C並且塗綠色;跟着那個到o並且繪製那個綠色,然後繼續到整個圖形中的o的父母。

然後,從master的提示開始,即提交B。將此提交塗成紅色:「停止」。然後,按照其父母提交A,並將其塗成紅色。按照o,用紅色油漆在綠色塗料上塗漆:「停止」。一路跟隨o的父母,用紅漆覆蓋他們所有的綠色塗料。

(如果你願意,你可以做紅的第1,那麼綠,只要你覆蓋任何紅配綠。)

結果,將提交該git rev-list應該列出,正是那些(仍然)是綠色的提交,這只是我們想要改變的三個提交。即使我們從Bmaster的提示開始了「紅色列表」,情況也是如此。

所有這一切的簡短版本是,爲了重組,我們想要的 - 至少現在 - 是git rebasemaster視爲「上游」。 rebase的「上游」參數提供了「紅色顏料」參數,master..my-feature修訂說明符的左半部分--onto參數:我們想要複製提交,以便它們在master的提示最後提交後出現。

實際上,您可以使用git branch --set-upstream-tomaster(在您自己的私人存儲庫中)設置爲my-feature的「上游」。上游不一定是像origin/branch這樣的遠程跟蹤分支。您自己的本地分支機構在此處可以正常工(但是請記住,如果您開始共享此分支 - 將其推送到遠程git存儲庫(如origin),那麼您可能希望在此時開始使用遠程跟蹤分支作爲「上游」,以提醒自己要分享,並獲得了較爲典型的變基流去。你可以做一個新的git branch --set-upstream-to在任何時候改變「上游」。)


單詞「分支」的另一個git文檔問題的例子。它至少有兩種不同的含義。在作爲該腳註段落的一部分的圖表中,master是一個「分支」(我喜歡稱其爲「分支標籤」或「分支名稱」)。同樣,my-feature是一個分支。在這種情況下,這兩種標籤分別簡單地標註一個特定的提交 - BE。但是,每個提交都有其自己的父提交指針:B指向AE指向D,依此類推。遵循這些父指向箭頭產生的提交鏈也是一個「分支」。

在其確切點停止調用此類鏈「分支」取決於你的觀點:my-feature可能會停止在提交o,而master可能會繼續回通過o。 Git在這裏並沒有太多的幫助,儘管沒有總是正確的答案:它確實取決於你想包含的內容。

有做這一個稍微更簡單的方法,因爲不是一個承諾作爲參數git cherry-pick可以採取更多:

$ git cherry-pick <id> <id> <id> 

例如,或者:

$ git cherry-pick my-feature~3..my-feature 

它使用在the gitrevisions documentation中描述的說明符可以讓git找到這三個ID。

1

事情是,沒有參數默認情況下rebase提議從最後一次提交推送rebase。不過,我們可以輕推它在正確的方向:

git rebase -i <hash> 

選擇提交前夕<hash>你想在歷史中看到的。這些哈希值可以通過git log獲得。

+1

像'HEAD〜1'(在最後一次提交之前提交)這樣的表達式也應該有效。如果有足夠的提交,它可能會更容易複製並粘貼來自日誌的散列,而不是計算您想要改變的提交數量。 – CoDEmanX

相關問題