2010-03-20 30 views
4

我使用git在兩臺不同的機器上對我的主目錄進行了版本升級。我希望他們每個人都使用單獨的分支,並從一個共同的分支拉。因此,大多數提交應該交給那個公共分支,除非提交了特定於該計算機的某些內容,在這種情況下,應該將提交交給檢出的計算機特定分支。在這種情況下,轉換分支顯然不是一個很好的選擇。致力於未檢出的分支

this post中提到我想要做的事情是不可能的,但是我發現答案很鈍,也許沒有考慮到使用管道命令的可能性。不幸的是,我沒有足夠的信譽來評論該主題。我更懷疑有什麼辦法可以做到這一點,並希望通過問好人來拯救我自己一個小時或幾個小時的答案。

那麼有可能在不首先檢查分支的情況下提交到不同的分支?理想情況下,我想以與git commit通常一樣的方式使用索引。

+0

順便說一句,我同意其他問題沒有得到滿意的回答。你可能不應該承諾除HEAD以外的任何地方,但如果你決定真的想要,你可以做到。這個問題值得回答。 – Cascabel 2010-03-20 01:02:14

+0

希望你仍然在看這個 - 我記得'git apply'的'--cached'選項。它使這更容易 - 看看我的答案。 – Cascabel 2010-03-21 01:16:42

回答

12

我相信做你想做的事的最好方法是在機器特定的分支上進行提交,然後用git rebase移動它們。這與我自己的主目錄大致相同 - 與您的情況基本相同。

# make a new branch starting from branch machine_1 
git checkout -b move_to_master  
# make whatever commits you need to 
git rebase --onto master machine_1 move_to_master 
git checkout master 
git merge move_to_master # this is a fast-forward 
git checkout machine_1 
git merge master 

如果你不小心犯創建move_to_master之前machine_1,只需創建move_to_master,然後重新回到machine_1它所屬的地方,並按照剩下的步驟。

但是,您的問題值得回答,並且我已經在底部提供了幾個備選方案。

創建承諾不會在當前分支

注意事項:非常非常小心!這是可怕的東西!

它是可能提交到未使用管道命令檢出的分支,只是不是非常需要。你必須讓你的索引到你想要的狀態(這可能是棘手的),然後你可以使用git commit-tree

git commit-tree -p $PARENT_COMMIT < $COMMIT_MESSAGE_FILE 

這將打印到標準輸出新創建的commit對象的SHA1;假設PARENT_COMMIT是一個分支的頂端,則必須使用git update-ref分支更新到它:

git update-ref -m "commit: [commit subject]" $BRANCH $NEW_SHA1 

如果你這個腳本,你可以在一個班輪實現它爲git update-ref -m ... $(git commit tree ...)。這是最可怕的一步。如果你更新你的其他分支到錯誤的地方,它有點糟糕。儘管如此,您仍然可以找出將其重新設置回git reflog show $BRANCH的位置。

無論如何,這只是簡單的部分。真正困難的是在沒有真正檢出文件的情況下將索引變成你想要的狀態。公共命令的兩個您可以使用:

  • git read-tree - 讀取樹信息進入指數,但不更新所有(GIT結賬工作樹大致相當於混帳讀取樹,git的結帳指數,和git update-ref HEAD)。你可以使用它來使索引包含未簽出分支的內容,而不是HEAD。
  • git update-index - 修改索引。您可以使用它從工作樹中添加,刪除或刷新索引中的文件。
  • git checkout-index - 將指定路徑從索引複製到工作樹中。在使用讀取樹之後,可以使用它來獲取要更改的單個文件,對其進行修改,然後使用update-index將其恢復。 「修改它」的步驟可能很複雜 - 例如,在完成所有這些之前,您可以使用git diff創建一個補丁,然後在此處應用git apply。
  • git apply --cached使用--cached選項,可以將補丁直接應用於索引中的版本,而無需觸摸工作樹。因此,您可以創建一個diff,讀取其他分支的樹,將其應用於索引,commit-tree,然後設置。這可能是最令人敬畏的做法。

之所以這麼辛苦,是因爲所有的git命令讓你能夠訪問它的所有強大的合併功能,這都依賴於工作樹中的文件。當你考慮它時,你想要做的任務是合併 - 你在一個分支上有差異,並且你想在另一個分支上應用它。獲得結果的方法是使用原始分支上的差異,與其他分支共同的祖先以及另一分支的尖端進行三向合併。沒有其他分支簽出,你不能真正做到這一點合併!

像往常一樣,當用管道命令做事情時,你應該非常小心地理解一切是如何工作的,所以你不會毀掉你的倉庫。也就是說,在重構現有存儲庫(由其他人創建的存儲庫...不問)時,我實際上已經使用了這種方法。在這種情況下,我只重新安排提交 - 使用讀取樹而不是一般更新索引 - 因此它比您可能要做的要簡單得多。說了這麼多

替代方法

,還有你可能需要得到完成你想要什麼一對夫婦的其他方法。

  • 克隆您的存儲庫。如果你只跟蹤配置文件,這不會佔用太多額外的空間,而且事情會變得更容易。如果你真的很迷戀,你甚至可以使用git new-workdir(鏈接到git.git HEAD版本)腳本來創建一個工作目錄,而不是重複其餘的repo(它使用.git目錄中的符號鏈接) 。只要記住要小心地將一個workdir提交給在另一箇中簽出的分支 - 另一個將以其工作樹不同步的方式結束。

  • 寫一個提交包裝腳本 - 這是最接近使得單承諾的所有這些選項的另一個分支:

    git commit 
    orig_branch=$(git symbolic-ref HEAD) 
    orig_branch=${orig_branch#refs/heads/} 
    git checkout master 
    git cherry-pick $orig_branch 
    git checkout $orig_branch 
    git reset --hard HEAD^ 
    
+0

在HEAD之外提交所需的管道的良好描述。在處理索引時,還可以使用'GIT_INDEX_FILE'來避免在進行自定義提交時重複默認索引。除非工作樹超大,否則我建議使用Jefromi的第一種替代方法(clone/git-new-workdir)。在公共分支上(在clone/alt-workdir中)進行提交,將其推送(如果使用克隆),然後將其合併到機器特定的分支中。它應該更乾淨,更不容易出錯(因爲你有完整的工作樹來處理合並衝突等)。 – 2010-03-20 05:25:45

+0

您還將擁有完整的工作樹,並帶有櫻桃選擇/重新選擇選項 - 它們只涉及一個小分支交換。我也忘記了GIT_INDEX_FILE - 我要寫的是,所有的東西都爲它提供了一個選項,但是隻有讀取樹的功能,然後我顯得有點分心。 – Cascabel 2010-03-20 05:59:59

+0

非常具有啓發性。我不那麼使用那些管道命令。 +1 – VonC 2010-03-20 09:29:12

0

這可能是我誤解了你的請求,但讓我知道這是你在找什麼。

您從機器特定的分支開始。您進行了更改,但不是提交給特定於機器的分支,而是要將更改提交到通用分支。你應該做的是

git stash    # save your changes for later 
git checkout common # switch to the common branch 
git stash apply  # recall the stashed changes 
git commit    # commit as appropriate (on the common branch) 
git stash drop   # kill off the last stashed changes (this is optional) 
git checkout machine1 # go to your machine-specific branch 
git rebase common  # put your machine-specific changes after the common ones 
git checkout machine2 # [repeat] 
git rebase common 

或者,你可以使用git merge,而不是git rebase如果這不是您的更改如何應用。

這是否適用於您的情況?

+0

我已經決定我實際上不喜歡存儲解決方案,儘管我最初也是這樣建議的。問題是,如果只想提交一些更改,即使使用'--keep-index',事情也會變得複雜。對於一個很好的單提交包裝,請參閱我的帖子的底部。 – Cascabel 2010-03-20 01:32:12

+0

這種情況下使用'git stash'的問題是它需要切換分支。如果一個cron作業正在進行,那麼可能會有麻煩,因爲特定於機器的配置/命令不會在那裏。或者如果我分心並在不同的殼體上做某件事.. – intuited 2010-03-20 17:34:12

+0

Jefromi有詳細的方法來解決這個問題,並且你已經選擇了相應的答案。我很擔心你的工作目錄有未提交的更改,但由於目錄上的外部依賴關係(如'cron'),因此無法更改目錄中的內容。也許你可以在另一個目錄中進行更改,在那裏進行測試,然後將這些更改推送到'cron'使用的部署目錄。只是我的0.02美元。 – MikeSep 2010-03-21 22:43:37

1

我這樣做對我的視覺Git的參考項目。我運行make gh-pages,建立網站並將其提交到gh-pages分支,而無需切換分支。請參閱我的GitHub repo,特別是文件Makefile發佈。我可能應該使用​​作爲克里斯約翰森上面提到的,但這似乎工作正常。