欧美亚洲中文,在线国自产视频,欧洲一区在线观看视频,亚洲综合中文字幕在线观看

      1. <dfn id="rfwes"></dfn>
          <object id="rfwes"></object>
        1. 站長(zhǎng)資訊網(wǎng)
          最全最豐富的資訊網(wǎng)站

          實(shí)例講解!Git工具之高級(jí)合并

          本篇文章給大家?guī)?lái)啦Git的相關(guān)知識(shí),其中主要介紹了高級(jí)合并,包括了合并沖突、撤銷合并等相關(guān)問(wèn)題,希望對(duì)大家有幫助。

          實(shí)例講解!Git工具之高級(jí)合并

          推薦學(xué)習(xí):《Git學(xué)習(xí)教程》

          高級(jí)合并

          在 Git 中合并是相當(dāng)容易的。 因?yàn)?Git 使多次合并另一個(gè)分支變得很容易,這意味著你可以有一個(gè)始終保持最新的長(zhǎng)期分支, 經(jīng)常解決小的沖突,比在一系列提交后解決一個(gè)巨大的沖突要好。

          然而,有時(shí)也會(huì)有棘手的沖突。 不像其他的版本控制系統(tǒng),Git 并不會(huì)嘗試過(guò)于聰明的合并沖突解決方案。 Git 的哲學(xué)是聰明地決定無(wú)歧義的合并方案,但是如果有沖突,它不會(huì)嘗試智能地自動(dòng)解決它。 因此,如果很久之后才合并兩個(gè)分叉的分支,你可能會(huì)撞上一些問(wèn)題。

          在本節(jié)中,我們將會(huì)仔細(xì)查看那些問(wèn)題是什么以及 Git 給了我們什么工具來(lái)幫助我們處理這些更難辦的情形。 我們也會(huì)了解你可以做的不同的、非標(biāo)準(zhǔn)類型的合并,也會(huì)看到如何后退到合并之前。

          合并沖突

          我們?cè)?遇到?jīng)_突時(shí)的分支合并 介紹了解決合并沖突的一些基礎(chǔ)知識(shí), 對(duì)于更復(fù)雜的沖突,Git 提供了幾個(gè)工具來(lái)幫助你指出將會(huì)發(fā)生什么以及如何更好地處理沖突。

          首先,在做一次可能有沖突的合并前盡可能保證工作目錄是干凈的。 如果你有正在做的工作,要么提交到一個(gè)臨時(shí)分支要么儲(chǔ)藏它。 這使你可以撤消在這里嘗試做的 任何事情 。 如果在你嘗試一次合并時(shí)工作目錄中有未保存的改動(dòng),下面的這些技巧可能會(huì)使你丟失那些工作。

          讓我們通過(guò)一個(gè)非常簡(jiǎn)單的例子來(lái)了解一下。 我們有一個(gè)超級(jí)簡(jiǎn)單的打印 hello world 的 Ruby 文件。

          #! /usr/bin/env ruby  def hello   puts 'hello world' end  hello()

          在我們的倉(cāng)庫(kù)中,創(chuàng)建一個(gè)名為 whitespace 的新分支并將所有 Unix 換行符修改為 DOS 換行符, 實(shí)質(zhì)上雖然改變了文件的每一行,但改變的都只是空白字符。 然后我們修改行 “hello world” 為 “hello mundo”。

          $ git checkout -b whitespace Switched to a new branch 'whitespace'  $ unix2dos hello.rb unix2dos: converting file hello.rb to DOS format ... $ git commit -am 'converted hello.rb to DOS' [whitespace 3270f76] converted hello.rb to DOS  1 file changed, 7 insertions(+), 7 deletions(-)  $ vim hello.rb $ git diff -b diff --git a/hello.rb b/hello.rb index ac51efd..e85207e 100755 --- a/hello.rb +++ b/hello.rb @@ -1,7 +1,7 @@  #! /usr/bin/env ruby   def hello -  puts 'hello world' +  puts 'hello mundo'^M  end   hello()  $ git commit -am 'hello mundo change' [whitespace 6d338d2] hello mundo change  1 file changed, 1 insertion(+), 1 deletion(-)

          現(xiàn)在我們切換回我們的 master 分支并為函數(shù)增加一些注釋。

          $ git checkout master Switched to branch 'master'  $ vim hello.rb $ git diff diff --git a/hello.rb b/hello.rb index ac51efd..36c06c8 100755 --- a/hello.rb +++ b/hello.rb @@ -1,5 +1,6 @@  #! /usr/bin/env ruby  +# prints out a greeting  def hello    puts 'hello world'  end  $ git commit -am 'document the function' [master bec6336] document the function  1 file changed, 1 insertion(+)

          現(xiàn)在我們嘗試合并入我們的 whitespace 分支,因?yàn)樾薷牧丝瞻鬃址院喜?huì)出現(xiàn)沖突。

          $ git merge whitespace Auto-merging hello.rb CONFLICT (content): Merge conflict in hello.rb Automatic merge failed; fix conflicts and then commit the result.

          中斷一次合并

          我們現(xiàn)在有幾個(gè)選項(xiàng)。 首先,讓我們介紹如何擺脫這個(gè)情況。 你可能不想處理沖突這種情況,完全可以通過(guò) git merge --abort 來(lái)簡(jiǎn)單地退出合并。

          $ git status -sb ## master UU hello.rb  $ git merge --abort  $ git status -sb ## master

          git merge --abort 選項(xiàng)會(huì)嘗試恢復(fù)到你運(yùn)行合并前的狀態(tài)。 但當(dāng)運(yùn)行命令前,在工作目錄中有未儲(chǔ)藏、未提交的修改時(shí)它不能完美處理,除此之外它都工作地很好。

          如果出于某些原因你想要重來(lái)一次,也可以運(yùn)行 git reset --hard HEAD 回到上一次提交的狀態(tài)。 請(qǐng)牢記此時(shí)任何未提交的工作都會(huì)丟失,所以請(qǐng)確認(rèn)你不需要保留任何改動(dòng)。

          忽略空白

          在這個(gè)特定的例子中,沖突與空白有關(guān)。 我們知道這點(diǎn)是因?yàn)檫@個(gè)例子很簡(jiǎn)單,但是在實(shí)際的例子中發(fā)現(xiàn)這樣的沖突也很容易, 因?yàn)槊恳恍卸急灰瞥诹硪贿吤恳恍杏直患踊貋?lái)了。 默認(rèn)情況下,Git 認(rèn)為所有這些行都改動(dòng)了,所以它不會(huì)合并文件。

          默認(rèn)合并策略可以帶有參數(shù),其中的幾個(gè)正好是關(guān)于忽略空白改動(dòng)的。 如果你看到在一次合并中有大量關(guān)于空白的問(wèn)題,你可以直接中止它并重做一次, 這次使用 -Xignore-all-space-Xignore-space-change 選項(xiàng)。 第一個(gè)選項(xiàng)在比較行時(shí) 完全忽略 空白修改,第二個(gè)選項(xiàng)將一個(gè)空白符與多個(gè)連續(xù)的空白字符視作等價(jià)的。

          $ git merge -Xignore-space-change whitespace Auto-merging hello.rb Merge made by the 'recursive' strategy.  hello.rb | 2 +-  1 file changed, 1 insertion(+), 1 deletion(-)

          因?yàn)樵诒纠?,?shí)際上文件修改并沒(méi)有沖突,一旦我們忽略空白修改,每一行都能被很好地合并。

          如果你的團(tuán)隊(duì)中的某個(gè)人可能不小心重新格式化空格為制表符或者相反的操作,這會(huì)是一個(gè)救命稻草。

          手動(dòng)文件再合并

          雖然 Git 對(duì)空白的預(yù)處理做得很好,還有很多其他類型的修改,Git 也許無(wú)法自動(dòng)處理,但是腳本可以處理它們。 例如,假設(shè) Git 無(wú)法處理空白修改因此我們需要手動(dòng)處理。

          我們真正想要做的是對(duì)將要合并入的文件在真正合并前運(yùn)行 dos2unix 程序。 所以如果那樣的話,我們?cè)撊绾巫觯?/p>

          首先,我們進(jìn)入到了合并沖突狀態(tài)。 然后我們想要我的版本的文件,他們的版本的文件(從我們將要合并入的分支)和共同的版本的文件(從分支叉開(kāi)時(shí)的位置)的拷貝。 然后我們想要修復(fù)任何一邊的文件,并且為這個(gè)單獨(dú)的文件重試一次合并。

          獲得這三個(gè)文件版本實(shí)際上相當(dāng)容易。 Git 在索引中存儲(chǔ)了所有這些版本,在 “stages” 下每一個(gè)都有一個(gè)數(shù)字與它們關(guān)聯(lián)。 Stage 1 是它們共同的祖先版本,stage 2 是你的版本,stage 3 來(lái)自于 MERGE_HEAD,即你將要合并入的版本(“theirs”)。

          通過(guò) git show 命令與一個(gè)特別的語(yǔ)法,你可以將沖突文件的這些版本釋放出一份拷貝。

          $ git show :1:hello.rb > hello.common.rb $ git show :2:hello.rb > hello.ours.rb $ git show :3:hello.rb > hello.theirs.rb

          如果你想要更專業(yè)一點(diǎn),也可以使用 ls-files -u 底層命令來(lái)得到這些文件的 Git blob 對(duì)象的實(shí)際 SHA-1 值。

          $ git ls-files -u 100755 ac51efdc3df4f4fd328d1a02ad05331d8e2c9111 1	hello.rb 100755 36c06c8752c78d2aff89571132f3bf7841a7b5c3 2	hello.rb 100755 e85207e04dfdd5eb0a1e9febbc67fd837c44a1cd 3	hello.rb

          :1:hello.rb 只是查找那個(gè) blob 對(duì)象 SHA-1 值的簡(jiǎn)寫(xiě)。

          既然在我們的工作目錄中已經(jīng)有這所有三個(gè)階段的內(nèi)容,我們可以手工修復(fù)它們來(lái)修復(fù)空白問(wèn)題,然后使用鮮為人知的 git merge-file 命令來(lái)重新合并那個(gè)文件。

          $ dos2unix hello.theirs.rb dos2unix: converting file hello.theirs.rb to Unix format ...  $ git merge-file -p      hello.ours.rb hello.common.rb hello.theirs.rb > hello.rb  $ git diff -b diff --cc hello.rb index 36c06c8,e85207e..0000000 --- a/hello.rb +++ b/hello.rb @@@ -1,8 -1,7 +1,8 @@@   #! /usr/bin/env ruby   +# prints out a greeting   def hello -   puts 'hello world' +   puts 'hello mundo'   end    hello()

          在這時(shí)我們已經(jīng)漂亮地合并了那個(gè)文件。 實(shí)際上,這比使用 ignore-space-change 選項(xiàng)要更好,因?yàn)樵诤喜⑶罢嬲匦迯?fù)了空白修改而不是簡(jiǎn)單地忽略它們。 在使用 ignore-space-change 進(jìn)行合并操作后,我們最終得到了有幾行是 DOS 行尾的文件,從而使提交內(nèi)容混亂了。

          如果你想要在最終提交前看一下我們這邊與另一邊之間實(shí)際的修改, 你可以使用 git diff 來(lái)比較將要提交作為合并結(jié)果的工作目錄與其中任意一個(gè)階段的文件差異。 讓我們看看它們。

          要在合并前比較結(jié)果與在你的分支上的內(nèi)容,換一句話說(shuō),看看合并引入了什么,可以運(yùn)行 git diff --ours

          $ git diff --ours * Unmerged path hello.rb diff --git a/hello.rb b/hello.rb index 36c06c8..44d0a25 100755 --- a/hello.rb +++ b/hello.rb @@ -2,7 +2,7 @@   # prints out a greeting  def hello -  puts 'hello world' +  puts 'hello mundo'  end   hello()

          這里我們可以很容易地看到在我們的分支上發(fā)生了什么,在這次合并中我們實(shí)際引入到這個(gè)文件的改動(dòng),是修改了其中一行。

          如果我們想要查看合并的結(jié)果與他們那邊有什么不同,可以運(yùn)行 git diff --theirs。 在本例及后續(xù)的例子中,我們會(huì)使用 -b 來(lái)去除空白,因?yàn)槲覀儗⑺c Git 中的, 而不是我們清理過(guò)的 hello.theirs.rb 文件比較。

          $ git diff --theirs -b * Unmerged path hello.rb diff --git a/hello.rb b/hello.rb index e85207e..44d0a25 100755 --- a/hello.rb +++ b/hello.rb @@ -1,5 +1,6 @@  #! /usr/bin/env ruby  +# prints out a greeting  def hello    puts 'hello mundo'  end

          最終,你可以通過(guò) git diff --base 來(lái)查看文件在兩邊是如何改動(dòng)的。

          $ git diff --base -b * Unmerged path hello.rb diff --git a/hello.rb b/hello.rb index ac51efd..44d0a25 100755 --- a/hello.rb +++ b/hello.rb @@ -1,7 +1,8 @@  #! /usr/bin/env ruby  +# prints out a greeting  def hello -  puts 'hello world' +  puts 'hello mundo'  end   hello()

          在這時(shí)我們可以使用 git clean 命令來(lái)清理我們?yōu)槭謩?dòng)合并而創(chuàng)建但不再有用的額外文件。

          $ git clean -f Removing hello.common.rb Removing hello.ours.rb Removing hello.theirs.rb

          檢出沖突

          也許有時(shí)我們并不滿意這樣的解決方案,或許有時(shí)還要手動(dòng)編輯一邊或者兩邊的沖突,但還是依舊無(wú)法正常工作,這時(shí)我們需要

          贊(0)
          分享到: 更多 (0)
          網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)