導(dǎo)言
git之所以復(fù)雜,是維護(hù)了本地分支,本地主干。遠(yuǎn)程分支,遠(yuǎn)程主干,以及工作區(qū)和暫存區(qū)之間的關(guān)系。
- 工作區(qū):在idea中實(shí)際上是創(chuàng)建文件,但未add,此時(shí)文件是
紅色的。 - 暫存區(qū):在idea中文件進(jìn)行add,但是沒有commit,此時(shí)文件是
綠色的。 - 分支/主干:在idea中進(jìn)行commit,此時(shí)文件是
白色的。
在本地中,因?yàn)槭枪昧艘惶状a,兩個(gè)分支,所以工作區(qū)和暫存區(qū)的內(nèi)容在各個(gè)分支中是共享的。
但若是代碼提交到分支上,那么主干上看不到提交到分支的代碼。實(shí)際上主干和分支是兩個(gè)指針。若是分支代碼版本是新的,那么如下圖所示:

我們?nèi)鬰heckout(切換分支)到master,是看不到dev最新commit的代碼的。
而實(shí)際上我們合并分支時(shí),只是將master指針指向dev節(jié)點(diǎn)上,完成了快速合并。(故在dev分支上進(jìn)行merge(合并))。
注:合并分支時(shí),項(xiàng)目中 不能存在 只add(即idea綠色文件)的文件。
理論
每次提交Git都把它們串成一條時(shí)間線,這條時(shí)間線就是一個(gè)分支。截止到目前,只有一條時(shí)間線,在Git里,這個(gè)分支叫主分支,即master分支。
HEAD嚴(yán)格來說不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是當(dāng)前分支。
上面的是什么意思呢?
每次提交,master分支都會(huì)向前移動(dòng)一步,這樣,隨著你不斷提交,master分支的線也越來越長(zhǎng)

當(dāng)我們創(chuàng)建新的分支,例如
dev時(shí),Git新建了一個(gè)指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當(dāng)前分支在dev上:

不過,從現(xiàn)在開始,對(duì)工作區(qū)的修改和提交就是針對(duì)
dev分支了,比如新提交一次后,dev指針往前移動(dòng)一步,而master指針不變:

假如我們?cè)?code>dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最簡(jiǎn)單的方法,就是直接把master指向dev的當(dāng)前提交,就完成了合并:

所以Git合并分支也很快!就改改指針,工作區(qū)內(nèi)容也不變!
合并完分支后,甚至可以刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉后,我們就剩下了一條master分支:

真是太神奇了,你看得出來有些提交是通過分支完成的嗎?
1. 文件初創(chuàng)
1.1. 新建文件

1.2、查詢文件狀態(tài)
命令:git status

1.3. 將文件保存到暫存區(qū)
命令:git add 文件名,再次使用git status查詢狀態(tài)。

1.4.將文件保存到當(dāng)前分支(本地倉(cāng)庫(kù))
命令:git commit -m '注釋'

1.5. 查詢文件修改的內(nèi)容
命令:git diff 文件名

使用git status查詢狀態(tài),使用git diff 文件名 查詢差異。
git提交文件只要兩步:
- 使用
git add把文件添加進(jìn)去,實(shí)際上就是把文件(工作區(qū))添加到暫存區(qū)。- 使用
git commit提交更改,實(shí)際上就是把暫存區(qū)的所有內(nèi)容提交到當(dāng)前分支上。

2. 文件回退
2.1. 查詢分支日志
命令:git log 可以查詢當(dāng)前分支的提交日志??梢允褂?code>q退出。

2.2. 分支回退版本
命令:git reset --hard HEAD^ 那么如果要回退到上上個(gè)版本只需把HEAD^ 改成 HEAD^^。是將當(dāng)前分支上的文件回退一個(gè)版本。
回退git reset --hard HEAD是回退暫存區(qū)的文件。

2.3. 獲取版本號(hào)
命令:git reflog若是我們將客戶窗口關(guān)閉(git log命令失效),或者回退到某個(gè)版本。那么需要該命令獲取版本號(hào)。

2.4. 分支回退指定版本
命令:git reset --hard 版本號(hào)(注意無空格)

2.5. 文件撤銷
命令:git checkout -- 文件名【注意有空格,注意 -- 】
需要注意的是:
- 未
add命令,可以還原;- 已經(jīng)執(zhí)行
git add命令,無論是否被commit均無法還原;

總結(jié):文件恢復(fù)的辦法:
第一:如果我知道要?jiǎng)h掉那些內(nèi)容的話,直接手動(dòng)更改去掉那些需要的文件,然后add添加到暫存區(qū),最后commit掉。
第二:我可以按以前的方法直接恢復(fù)到上一個(gè)版本。使用git reset --hard HEAD^;或者git reset --hard 版本號(hào)(注意無空格)。__
第三:git checkout -- 文件名,可以將工作區(qū)還原。
3. 文件刪除
將文件手動(dòng)刪除之后,使用git status查詢狀態(tài):

此時(shí),有兩種策略:(1)文件還原;(2)文件在當(dāng)前分支上刪除;
3.1 文件還原
命令:git checkout -- 文件名,因?yàn)橹皇窃?strong>工作區(qū)做出的修改,所以可以撤銷操作。

3.2 分支上刪除
命令:先執(zhí)行add命令,而后執(zhí)行commit命令。

文件在分支上刪除.png

4. 分支的創(chuàng)建和合并
4.1 分支的創(chuàng)建
git checkout 命令加上 –b參數(shù),表示創(chuàng)建并切換,相當(dāng)于如下2條命令
git branch dev (創(chuàng)建分支)
git checkout dev(切換分支)
git branch(查看所有分支):

4.2 多分支之間操作
在dev分支上修改TestSort.java文件,使用git diff 文件名命令查詢差異。

add+commit命令將工作區(qū)文件合并到dev分支上。

切換分支:命令:git checkout 分支名。并未在當(dāng)前分支上查詢到修改的信息。

4.3 分支合并
命令:git merge -d 分支A。將分支A合并到當(dāng)前分支。
Fast-forward信息,Git告訴我們,這次合并是“快進(jìn)模式”,也就是直接把fenzhi1指向dev的當(dāng)前提交,所以合并速度非?????梢圆榭次募?,已經(jīng)含有了dev分支的修改內(nèi)容。

4.4 分支刪除
命令:git branch -d 分支A。將分支A刪除。

查看分支:git branch
創(chuàng)建分支:git branch name
切換分支:git checkout name
創(chuàng)建+切換分支:git checkout –b name
合并某分支到當(dāng)前分支:git merge name
刪除分支:git branch –d name
5. 分支沖突
5.1 沖突的產(chǎn)生
在dev分支上,對(duì)TestSort.java文件進(jìn)行修改。然后提交到當(dāng)前分支。

通過命令:git checkout 分支名 切換分支后,查看分支內(nèi)容。

在master分支上修改同一個(gè)文件,然后提交到分支上。

以上是合并沖突的準(zhǔn)備工作
此時(shí),在將dev分支上代碼合并到主干(master)上時(shí),出現(xiàn)版本沖突。

于是我們開始檢查沖突的代碼:Git用<<<<<<<,=======,>>>>>>>標(biāo)記出不同分支的內(nèi)容,其中<<<HEAD是指主分支修改的內(nèi)容,>>>>>dev是指dev上修改的內(nèi)容。

我們修改沖突代碼后,將其重新放入暫存區(qū),然后提交到master主干上。

通常合并分支時(shí),git一般使用”Fast forward”模式,在這種模式下,刪除分支后,會(huì)丟掉分支信息,現(xiàn)在我們來使用帶參數(shù) –no-ff來禁用”Fast forward”模式。首先我們來做demo演示下:
- 創(chuàng)建一個(gè)dev分支。
- 修改readme.txt內(nèi)容。
- 添加到暫存區(qū)。
- 切換回主分支(master)。
- 合并dev分支,使用命令 git merge –no-ff -m “注釋” dev
- 查看歷史記錄



分支策略:首先master主分支應(yīng)該是非常穩(wěn)定的,也就是用來發(fā)布新版本,一般情況下不允許在上面干活,干活一般情況下在新建的dev分支上干活,干完后,比如上要發(fā)布,或者說dev分支代碼穩(wěn)定后可以合并到主分支master上來。
6. (精華)多人協(xié)作
當(dāng)你從遠(yuǎn)程庫(kù)克隆時(shí)候,實(shí)際上Git自動(dòng)把本地的master分支和遠(yuǎn)程的master分支對(duì)應(yīng)起來了,并且遠(yuǎn)程庫(kù)的默認(rèn)名稱是
origin。
6.1 查詢遠(yuǎn)程倉(cāng)庫(kù)
要查看遠(yuǎn)程庫(kù)的信息 使用 git remote
要查看遠(yuǎn)程庫(kù)的詳細(xì)信息 使用 git remote –v

6.2 數(shù)據(jù)推送
命令:git push 遠(yuǎn)程服務(wù)器名 遠(yuǎn)程分支名,將信息push到遠(yuǎn)程倉(cāng)庫(kù)。

那么一般情況下,那些分支要推送呢?
master分支是主分支,因此要時(shí)刻與遠(yuǎn)程同步。
一些修復(fù)bug分支不需要推送到遠(yuǎn)程去,可以先合并到主分支上,然后把主分支master推送到遠(yuǎn)程去。
6.3 抓取分支:
命令:git push origin dev小胖將信息push到遠(yuǎn)程dev分支上

小伙伴要在dev分支上做開發(fā),就必須把遠(yuǎn)程的origin的dev分支到本地來,于是可以使用命令創(chuàng)建本地dev分支:git checkout –b dev origin/dev
現(xiàn)在小伙伴們就可以在dev分支上做開發(fā)了,開發(fā)完成后把dev分支推送到遠(yuǎn)程庫(kù)。

小胖將TestSort.java修改的內(nèi)容推送到遠(yuǎn)程。

小悠也想對(duì)TestSort.java這個(gè)文件信息修改。于是:

由上面可知:推送失敗,因?yàn)槲业男』锇樽钚绿峤坏暮臀以噲D推送的有沖突,解決的辦法也很簡(jiǎn)單,上面已經(jīng)提示我們,先用
git pull把最新的提交從origin/dev抓下來,然后在本地合并,(手動(dòng))解決沖突,再推送。
因此:多人協(xié)作工作模式一般是這樣的:
首先,可以試圖用git push origin branch-name推送自己的修改;
如果推送失敗,則因?yàn)檫h(yuǎn)程分支比你的本地更新早,需要先用git pull試圖合并。
如果合并有沖突,則需要解決沖突,并在本地提交。再用git push origin branch-name推送。
7. 應(yīng)用實(shí)戰(zhàn)(idea版本)
7.1 idea文件和git版本的關(guān)系

7.2 場(chǎng)景1
git使用場(chǎng)景:
開發(fā)過程中,忘記將主干上的代碼pull(遠(yuǎn)程分支下拉命令)或者merge(本地主干下拉命令)。且開發(fā)到一半時(shí)(已存在大量“藍(lán)色/綠色”文件),此時(shí)再想pull或者merge時(shí)候。出現(xiàn)
下拉代碼的異常
解決方案1:
如果你想保留剛才本地修改的代碼,并把git服務(wù)器上的代碼pull到本地(本地剛才修改的代碼將會(huì)被暫時(shí)封存起來)
git stash
git pull origin master
git stash pop



解決方案2:
如果你想完全地覆蓋本地的代碼,只保留服務(wù)器端代碼,則直接回退到上一個(gè)版本,再進(jìn)行pull:
git reset --hard
git pull origin master
文章參考:https://www.cnblogs.com/replaceroot/p/9825760.html
http://www.admin10000.com/document/5374.html
