適宜人群
這是一篇關(guān)于 git 沖突入門級(jí)的介紹搬瑰,以及簡略介紹 git 分支的應(yīng)用,大佬請繞行//手動(dòng)齜牙
另外還有一篇非常好的最最基礎(chǔ)的git使用命令請參考這篇寫得很好的博客:Git操作詳解
背景
最近在做一個(gè)微信小程序控硼,因?yàn)椴辉偈亲约阂粋€(gè)人獨(dú)自開發(fā),而是和兩個(gè)組員一起開發(fā)小程序前端頁面
那么不能再像在 GitHub 中托管辣雞 demo 一樣艾少,一直一條分支
直接 git pull origin master
然后git push origin master
然后看著 GitHub 又變綠了一點(diǎn)卡乾,發(fā)出一聲感嘆:“雖然今天的代碼一個(gè)都調(diào)不通,但是還是好累呢缚够!”
剛開始其實(shí)三個(gè)人也是用的一個(gè)分支幔妨,即 master 分支鹦赎,后來頁面數(shù)量多起來,愈發(fā)地混亂误堡,而且小程序頁面注冊古话,還有全局變量的設(shè)置,都在根目錄下的app.js
,app.json
...中進(jìn)行配置锁施,(我重新整理后的)小程序目錄大概如下:
所以項(xiàng)目 git 上傳就一直沖突不斷陪踩,基本上傳一次就沖突一次
入坑
當(dāng)項(xiàng)目中的兩個(gè)成員同時(shí)修改一個(gè)文件(不是文件夾),然后分別上傳到遠(yuǎn)程 git 倉庫就會(huì)產(chǎn)生沖突悉抵,一般 git 會(huì)整合的時(shí)候在發(fā)生沖突的文件中自動(dòng)生成三方合并標(biāo)記線(<<<<<<<肩狂、=======、>>>>>>>)來標(biāo)識(shí)各個(gè)成員的不同修改
Fine姥饰,F(xiàn)or example
- 在 GitHub 上創(chuàng)建了一個(gè)測試項(xiàng)目來模擬遠(yuǎn)程 git 倉庫
- 在電腦本地新建并使用兩個(gè)空文件夾
file1
傻谁,file2
模擬真實(shí)開發(fā)中的兩個(gè)項(xiàng)目成員- 在
file1
,file2
中分別clone下這個(gè)測試項(xiàng)目- 在
file1
列粪,file2
先后修改clone到本地的測試項(xiàng)目中的同一個(gè)文件test.text
中的內(nèi)容- 將修改后的
file1
审磁,file2
先后push到GitHub,你會(huì)發(fā)現(xiàn)沖突
具體過程:
在 test.text
文件中岂座, zb
是模擬的公共配置項(xiàng)代碼
成員 file1
在公共代碼下面配置了自己的代碼: 甲的修改
成員 file2
在公共代碼下面配置了自己的代碼: 乙的修改
于是他們兩個(gè)在互不知情的情況下修改了同一個(gè)文件力图,分別 push 到遠(yuǎn)程 git 倉庫
file1
先 pull,然后 push掺逼,這時(shí)候遠(yuǎn)程的 git 倉庫中的 test.text
中的內(nèi)容變成了 file1
修改后的內(nèi)容
這時(shí)候 file2
在 pull 的時(shí)候就會(huì)產(chǎn)生沖突吃媒,因?yàn)檫h(yuǎn)程的 git 倉庫 test.text
中的第二行和 file2
本地
git 倉庫 test.text
中的第二行內(nèi)容不一樣,git 本身無法判斷到底保留哪個(gè)
所以就會(huì)自動(dòng)處理沖突吕喘,全部保留下來赘那,下面圖片就是 git 自動(dòng)處理沖突后的打印出的信息:
git 并使用標(biāo)記線標(biāo)明代碼沖突來源和沖突的內(nèi)容,下圖就是
file2
的 test.text
在 git 自動(dòng)處理沖突后打開時(shí)候的內(nèi)容(頓時(shí)感覺自己的代碼被下了毒)稍稍解釋一哈這個(gè)里面的意思:
<<<<<<<HEAD 乙的修改
表示 git 提示這部分產(chǎn)生沖突的來源是HEAD氯质,沖突的內(nèi)容是
乙的修改
募舟,這個(gè) HEAD 是一個(gè)指針,指向的是file2
的最新提交記錄
=======
分隔符闻察,將沖突的內(nèi)容以及來源的不同信息隔開
甲的修改 >>>>>>>a35d5e7617aeb98bf382fa1a1af7579e976f9f4a
表示 git 提示這部分產(chǎn)生沖突來源是哈希值為
a35d5e7617aeb98bf382fa1a1af7579e976f9f4a
的提交記錄(每一個(gè)提交 commit 都會(huì)有一個(gè)獨(dú)有的哈希值拱礁,通過哈希值可以找到這個(gè)提交的所有信息),沖突的內(nèi)容是甲的修改
辕漂,這個(gè)提交記錄正是file1
的提交
這時(shí)候你就要自己手動(dòng)處理呢灶,看看到底保留哪一份代碼,或者還是都保留钉嘹,然后刪掉這些 git 自己增加的字符鸯乃,解決沖突后,繼續(xù) push 到遠(yuǎn)程 git 倉庫
那么這時(shí)候問題來了跋涣,如果是一個(gè)兩個(gè)文件沖突還好缨睡,像我自己目前這個(gè)小程序包含了大量的項(xiàng)目頁面鸟悴,配置等文件,每上傳一次奖年,來一次沖突细诸,沖突還是一大片的,這誰頂?shù)米陋守。?/p>
我的微信小程序項(xiàng)目的沖突就是這樣震贵,許多文件許多代碼段出現(xiàn)大量的<<<<<<<、=======嗅义、>>>>>>>標(biāo)記符:
填坑
解決這個(gè)坑的思路是這樣的:
- 三個(gè)人分別建立自己的分支屏歹,每個(gè)人在自己的分支上提交記錄,互不干擾
- 將公共的要配置的代碼放在gitignore中不傳到遠(yuǎn)程git倉庫中之碗,最后合并分支再統(tǒng)一處理
分支思想
如果是單獨(dú)開發(fā)蝙眶,開發(fā)者可以選擇一條分支進(jìn)行代碼托管
但是項(xiàng)目協(xié)作者一多,單分支就會(huì)出現(xiàn)問題:
上圖就是我之前的項(xiàng)目的問題褪那,大家都在同一條分支上進(jìn)行修改提交幽纷,不知不覺就會(huì)修改同一個(gè)文件,然后產(chǎn)生沖突的問題
所以就將每個(gè)人寫的項(xiàng)目獨(dú)立成一條分支博敬,然后就在自己的分支上盡情修改友浸,最后再合并成一條,這樣在開發(fā)的時(shí)候各個(gè)功能開發(fā)一起進(jìn)行偏窝,互不影響收恢,等各自完成后再合并部署,加快了進(jìn)度和主分支的完整性和可用性
如圖祭往,在
master
分支上第二次提交的節(jié)點(diǎn)上新建branch2
分支伦意,甲在 master
上繼續(xù)提交,乙在 branch2
上提交硼补,互不干擾合并分支:
當(dāng)分支上的功能完成驮肉,我們可以將
branch2
分支合并到 master
分支上,如上圖所示已骇,最后又合并成一條主分支离钝,然后就可以進(jìn)行完整功能測試和部署至服務(wù)器了那么問題來了,分支解決了沖突了么褪储?
其實(shí)分支的目的就是避免沖突卵渴,互不影響,提高效率乱豆,如果兩位開發(fā)者在兩條不同的分支修改同一份文件奖恰,最后合并的時(shí)候還是會(huì)有沖突的,git 還是搞不清楚到底保留哪一份代碼宛裕,于是又會(huì)它自己解決沖突瑟啃,又會(huì)出現(xiàn)那些三方合并標(biāo)記線
所以項(xiàng)目的模塊劃分,低耦合性很重要揩尸,我這個(gè)項(xiàng)目的解決方式是將這些公共的經(jīng)常修改的配置文件等都在 .gitignore 中配置好蛹屿,不傳到遠(yuǎn)程 git 倉庫中,最后統(tǒng)一分支的時(shí)候手動(dòng)選擇
相關(guān)命令
git branch
列出本地已經(jīng)存在的分支岩榆,并且在當(dāng)前分支的前面加 * 號(hào)標(biāo)記
- git branch -r 列出遠(yuǎn)程分支
- git branch -a 列出本地分支和遠(yuǎn)程分支
- git branch branch2 創(chuàng)建一個(gè)新的叫
branch2
的本地分支错负,但只是創(chuàng)建分支,沒有進(jìn)行分支切換
git chekout
切換分支
- git checkout master 切換到
master
分支 - git checkout -b branch2 新建并且切換到一條名為
branch2
的新分支
即這條命令包含了兩個(gè)過程:
1.git branch branch2 新建branch2
分支
2.git checkout branch2 指針 HEAD 指向切換到branch2
分支(也就是目前你都是在branch2
分支上修改)
git pull origin master
git push origin master
將本地 git 倉庫的 master 分支 push 到遠(yuǎn)程的test分支中勇边,照例還是要先 pull犹撒,后push
git log
打印git的提交記錄,后面可以跟參數(shù)
1.git log --oneline 可以使每條日志以簡短的形式一行輸出
2.git log --graph 可以使日志以圖的形式打印
參數(shù)可以連用,即:git log --oneline --graph 功能疊加
舉個(gè)例子:創(chuàng)建粒褒,合并分支過程
- git init
在空文件下初始化git - 在初始化 git 后的文件夾中創(chuàng)建并編輯相關(guān)代碼文件
- git add .
將自己修改好的代碼添加到暫存區(qū)(add后面有個(gè)空格和 . ) -
git commit -m "master第一次提交"
將暫存區(qū)的代碼提交到本地 git 倉庫中
此時(shí)的本地 git 倉庫:
- git checkout -b branch2
新建并且切換到branch2
新分支
這時(shí)候一個(gè)節(jié)點(diǎn)就包含了兩個(gè)指針识颊,一個(gè)master
,一個(gè)branch2
:
- 兩次 git commit
因?yàn)閮蓚€(gè)指針都包含在一個(gè)節(jié)點(diǎn)奕坟,所以要分離開兩個(gè)指針祥款,使之成為兩條獨(dú)立的分支
當(dāng)前 HEAD 指向branch2
,所以直接輸入git commit
然后切換至master
分支:git checkout master
月杉,繼續(xù)輸入:git commit
- 這時(shí)候不同開發(fā)者就可以在各個(gè)分支上進(jìn)行修改
假設(shè)master
分支上提交了一次刃跛,branch2
分支上也提交了一次 - git checkout master
如果在其他分支,這時(shí)候切換至master
分支苛萎,準(zhǔn)備合并 - git merge branch2
如果在其他分支桨昙,先使用git checkout master
命令切換至master
分支
再使用git merge branch2
將branch2
合并至master
分支 - git commit
再使用commit
,使 git 分支樹徹底合并:
10.git log --oneline --graph
之前的圖示都是我自己繪的腌歉,如果使用控制臺(tái)查看 git 的歷史提交記錄蛙酪,就是這樣:
如果你也是一步步按照我的步驟,這就是最后打印出來的圖示究履!
坑外話
其實(shí) git 博大精深滤否,林納斯作為 git 的創(chuàng)造者,畢竟是影響世界 IT 進(jìn)程的程序員最仑,牛皮不是沒有道理的藐俺,我這里也只是小敘一波,有什么錯(cuò)誤的不清晰的地方請大佬們指教泥彤,以后有什么更深入的理解也會(huì)持續(xù)更新(撒花)