2015-05-23 147 views
12

我使用了幾個軟件包(如gitlab),你通過從他們的git回購克隆安裝。它們通常會附帶一些config.example(版本控制下),您可以將其複製到您自己的config文件(不受版本控制,甚至在.gitignore中忽略)並適應您的需求。交互合併文件跟蹤與git和未跟蹤本地文件

當上遊軟件包更新,例如更改配置文件選項,顯然只會反映在config.example

是否有我失蹤,可以幫助我比較upstream/HEADconfig.example到新的變化Git命令的鏈條,甚至以交互方式將它們合併爲我的本地config文件?

如果我能得到類似git add/commit --interactive中的交互式修補程序模式,那將會很棒。

回答

2

git checkout --patch選擇差異的帥哥,最簡單的在這裏可能是把你的內容在上游路徑,這樣做,後清理:

cp config config.example 
git checkout -p upstream config.example 
mv config.example config 
git checkout @ config.example 

,將讓你的雙DIFF大塊的選擇從git add --patch

0

要在本地回購與upstream/HEAD相應的文件差異比較只是config.example你可以運行:

git diff upstream/HEAD config.example 

不幸的是我不知道的方法,使git的直接應用對文件的更改了Git不跟蹤。

+0

是的,我知道如何得到差異,但現在交互應用到'配置'是我的實際問題: -/ –

+0

您是否嘗試過將配置文件複製到config.example中,使用您的標準從原點合併的工具,然後將其移回配置並重置爲您提交到config.example的更改之前?如果文件不是太不同步,你應該至少得到一些幫助,以便改變什麼。 – 1337joe

2
  • 調用它(你的情況),您可以使用vimvimdiff合併工具。
  • Emacs可以用ediff-mode來做到這一點。
0

下面應該工作:

git diff <some-args> | perl -pe 's/path\/to\/changes\/file/path\/other/g' > t 
patch -p1 < t 
rm t 
1

如果你想充分git的合併,你可以得到的git與任意內容做到這一點通過建立一個索引條目git read-tree做,然後調用Git的正常在該條目上合併驅動程序。 Git將不同的內容版本稱爲「階段」;他們是1:原始的,2:你的,3:他們的。合併比較從1到2和從1到3的變化,並做它的事情。要對其進行設置,使用git update-index

orig_example=  # fill in the commit with the config.example you based yours on 
new_upstream=  # fill in the name of the upstream branch 

(while read; do printf "%s %s %s\t%s\n" $REPLY; done \ 
| git update-index --index-info) <<EOD 
100644 $(git rev-parse $orig_example:config.example) 1 config 
100644 $(git hash-object -w config)     2 config 
100644 $(git rev-parse $new_upstream:config.example) 3 config 
EOD 

,你已經上演的自定義內容合併爲路徑。現在做到這一點:

git merge-index git-merge-one-file -- config 

,它會要麼automerge或離開平常衝突的糞便,如果你要修復它,你喜歡和git rm --cached --ignore-unmatch(或保留)的索引條目。

順便說一下,您在索引中放置的路徑名(這裏的全部三個條目中的「配置」)不必已經存在或與任何事情有關。你可以將其命名爲「wip」或「deleteme」或任何你想要的。合併是索引條目中id'd的內容。

我認爲這可能會做你想在這裏。如果您確實想要從上游更改中進行選擇,則可以將自己的內容置於配置中。例如,做git checkout -p upstream -- config.example,即git add -p的倒數,然後將事情恢復原樣。

+0

我最喜歡這個答案的最後一段(剩下的對我來說似乎有點像黑魔法)。有了最後一段的想法,我可以做'cp config config.example; git checkout -p上游 - 配置。例如'然後交互決定如何合併更改並最終運行'mv config.example config && git reset config.example && git checkout - config.example'來設置回去。如果你把最後一段分成單獨的答案,我會接受它的清晰和簡單。 –

+1

好的,完成了。謝謝。 – jthill

2

你可以用很多方式來解決這個問題。我可以想到兩個:git-merge-file和舊的patchgit-merge-file方法提供了一些交互性,而patch方法不提供。

git-merge-file

解決方案比方說你有一個原始文件,您可以使用它創建一個本地版本的文件,config.localconfig.example。現在,當上遊更新config.example時,您可以按照以下步驟來合併任何新更改。

$ git fetch 
$ git show master:config.example > config.example.base 
$ git show origin/master:config.example > config.example.latest 
$ git merge-file config.local config.example.base config.example.latest 

這將更新config.local與通常的衝突標誌,它然後你會與你最喜歡的合併工具來解決(ediff在Emacs是不錯的,我敢肯定,有類似模式的VIM)。例如,下面的三個文件,

config.example.base

Original: 
      some config 

config.example.latest

Original: 
      some config 

Upstream: 
      new upstream config 

config.local

Original: 
      some config 

My changes: 
      some other config 

將被合併這樣的:

Original: 
      some config 

<<<<<<< config.local 
My changes: 
      some other config 
======= 
Upstream: 
      new upstream config 
>>>>>>> config.example.latest 

你很可能這個腳本毫不費力。順便說一句,git-merge-file可以在任何3個文件上操作,它們不需要版本控制在git下。這意味着可以使用它來合併任何三個文件!

解決方案與patch

假設相同的文件名,config.localconfig.example,下面應該工作。

$ git fetch 
$ git diff master..origin/master -- config.example | sed -e 's%\(^[-+]\{3\}\) .\+%\1 config.local%g' > /tmp/mypatch 
$ patch < /tmp/mypatch 
+0

我喜歡這個3路合併的答案,但可悲的是它並不像'git add -p'那樣互動,這意味着我無法真正查看新的配置選項。儘管如此,它還是讓我高興的,因爲這可能是其他人的選擇。 –