git命令行(2)
一、父提交的表示方法
1.HEAD引用
在.git/HEAD目錄下存在一個(gè)HEAD文件,其記錄著當(dāng)前工作區(qū)對(duì)應(yīng)的SHA1。如果當(dāng)前工作區(qū)從某個(gè)分支檢出(checkout),那么這個(gè)HEAD文件中的引用最終執(zhí)行分支對(duì)應(yīng)的SHA1,如果處于分離頭狀態(tài)(不對(duì)應(yīng)分支,從某個(gè)commit檢查),那么這個(gè)HEAD文件中保存的就是檢出的commit SHA1。
如果我們直接使用git checkout master分支,那么HEAD的值為ref: refs/heads/master。指向.git/refs/heads/master文件,其內(nèi)容就是m6對(duì)應(yīng)的SHA1。
如果我們使用git checkout ${m4.sha1} ,那么HEAD的值為 ${m4.sha1}
因此HEAD引用就是當(dāng)前工作區(qū)對(duì)應(yīng)的提交的SHA1
2.父提交的表示方法
可以使用~(波浪號(hào))和^號(hào)表示父提交,但含義會(huì)略有不同。
</br>
^表示父提交的第幾個(gè)提交,后面如果跟數(shù)字就是表示第幾個(gè)父提交。
例如上圖中當(dāng)前的工作區(qū)HEAD指向m10提交。那么HEAD^和HEAD^1相同都是指向m9。HEAD^^指向m8,而HEAD^2則是沒(méi)有意義的,因?yàn)閙10只有一個(gè)父提交就是m9。HEAD^^^指向是m7,HEAD^^^2指向d2(HEAD^^指向m8,后面的^2表示m8的第二個(gè)父提交)。分析^的時(shí)候如果^號(hào)后面沒(méi)有數(shù)字則和^1等價(jià),表示第一個(gè)父提交,如果存在數(shù)字就表示第幾個(gè)父提交。
tips:如果^后面的形式如:^{commit},^{tree},^{blob},則表示當(dāng)前對(duì)象的提交、樹(shù)、blob對(duì)象。
</br>
~表示法:波浪號(hào)表示父提交的層次關(guān)系。那么HEAD~和HEAD~1相同都是指向m9。HEAD~ ~指向m8,而HEAD~2和HEAD~\~是完全等價(jià)的。HEAD~\~\~指向是m7,HEAD~3和其等價(jià)。因此d2就可以表示為HEAD~2^2(HEAD~2指向m8,后面的^2表示m8的第二個(gè)父提交),因此如果存在數(shù)字表示父提交的父提交的父提交...(數(shù)字就是幾層父提交)
因此當(dāng)我們使用git log命令的時(shí)候,可以打印部分父提交。
git log --oneline HEAD~8..HEAD~5
3.git reflog
當(dāng)我們對(duì)任何的分支修改(commit、pull、push)的時(shí)候,在.git/logs/refs目錄都會(huì)記錄變更情況,因此完全不用擔(dān)心提交記錄丟失的情況。.git/logs/refs/heads記錄本地分支的變更記錄,.git\logs\refs\remotes記錄遠(yuǎn)程分支在本地的變更情況。
當(dāng)我們使用git reflog命令的時(shí)候就會(huì)顯示HEAD引用的變更情況。
同樣可以通過(guò)git reflog master查看master分支的變更情況。
reflog表示法:HEAD@{1},表示HEAD引用之前的第一個(gè)變更。
git reset --hard HEAD@{1}。如果新拉取的代碼有問(wèn)題,但是拉取之前的代碼不確定是否有問(wèn)題,需要把代碼回滾到拉取之前的代碼,那么就可以執(zhí)行這個(gè)命令
二、修改提交
本地提交代碼的時(shí)候經(jīng)常會(huì)出現(xiàn)需要更改提交、修改注釋的情況,下面的幾個(gè)命令可以實(shí)現(xiàn)修改提交。
1.git commit
git commit --amend可以方便的修改當(dāng)前提及的注釋。當(dāng)執(zhí)行這個(gè)命令的時(shí)候會(huì)彈出vim編輯器編輯注釋信息(只修改提交注釋信息)。
2.git reset
git reset命令可以把當(dāng)前分支重置到某個(gè)提交。其選項(xiàng)有三個(gè):
- --hard:把工作區(qū)、暫存區(qū)的內(nèi)容也重置到該提交
- --mixed:默認(rèn)選項(xiàng),把暫存器的內(nèi)容重置到該提交,但是保留當(dāng)前工作區(qū)的內(nèi)容
- --soft:工作區(qū)、暫存器保留原來(lái)的內(nèi)容,分支的引用重置到某個(gè)提交
3.git revert
如果我們的提交已經(jīng)push到遠(yuǎn)程倉(cāng)庫(kù)上,別人已經(jīng)pull下來(lái)了,如果你想刪除某次提交,reset就不能使用了,而是使用revert命令,revert即對(duì)某次提交產(chǎn)生一個(gè)反作用的提交。
git revert HEAD~3 -----創(chuàng)建一個(gè)提交,回滾最近的第四次提交 git revert master~5..master~2 ---回滾某個(gè)范圍的提交4.git rebase
git rebase可以對(duì)當(dāng)前沒(méi)有push的提交進(jìn)行更改,設(shè)想一下一個(gè)功能你可以本地進(jìn)行了多次提交,但是push的時(shí)候你想把這些提×××并成一個(gè),就可以使用git rebase命令編輯提交。
假設(shè)我們需要對(duì)如下m9-m13的提交編輯。
場(chǎng)景一:把這些提交并成一個(gè)提交
使用squash命令和上一個(gè)提×××并,然后重新修改提交日志
場(chǎng)景二:刪除某個(gè)提交
刪除某個(gè)提交直接把該提交對(duì)應(yīng)的行去除或者使用remove命令。如果存在合并沖突,然后解決沖突。
根據(jù)git命令行的提示,解決完沖突以后運(yùn)行g(shù)it add添加沖突的修改。
場(chǎng)景三:修改某個(gè)提交的日志:
使用edit命令或者reword命令修改,最好使用reword命令,這樣rebase就可以之間彈出修改日志的vim編輯器,而不用git 彈出git commit --amend提示。
三、分支標(biāo)簽命令
1.git branch
使用branch命令可以管理分支。
$ git branch ------顯示本地分支 $git branch -a -------顯示本地和遠(yuǎn)程分支 $git branch xxxbranchName -------創(chuàng)建分支名xxxbranchName的分支,此時(shí)HEAD的引用仍然是指向原來(lái)的分支 $git branch -d xxxbranchName ---刪除某一個(gè)分支,如果該分支的修改沒(méi)有合并,那么刪除失敗 $git branch -D xxxbranchName -----強(qiáng)制刪除分支2.git tag
使用tag命令可以管理標(biāo)簽。標(biāo)簽和分支的區(qū)別是,標(biāo)簽是不可以修改的。如果要修改必須基于該標(biāo)簽拉出一個(gè)分支修改
$git tag -------------展示所有的tag $git tag xxxtagName ---------------新建xxxtagName的標(biāo)簽 $git tag -d xxxtagName ---------刪除xxxtagName的標(biāo)簽3.git checkout
checkout命令可以檢出某個(gè)提交或者分支。
$git checkout SHA-1 ----------檢出某個(gè)SHA-1對(duì)應(yīng)的提交 $git checkout xxxbranchName -------------我們使用git branch xxxbranchName的時(shí)候只是新建了這個(gè)分支,需要執(zhí)行該命令切換到該分支 $git checkout HEAD^ -----檢出到HEAD的第一個(gè)父提交 $git checkout -b xxxbranchName -------------新建xxxbranchName并檢出到該分支當(dāng)我們checkout除分支外的其他SHA-1都會(huì)提示我們處于detached HEAD狀態(tài),此時(shí).git/HEAD文件里面的內(nèi)容就是SHA-1
此時(shí)如果在分離頭上做的修改和提交想合并到其他分支需要用到merge和rebase等命令
四、合并命令
1.git merge
merge命令可以合并兩個(gè)多個(gè)提交,并生成一個(gè)新的提交。當(dāng)前分支始終是目標(biāo)分支。
假設(shè)歷史記錄如下,且當(dāng)前分支為master:
然后運(yùn)行 "git merge topic",將會(huì)產(chǎn)生一個(gè)新的提交H,其中H的父提交是C和G。
A---B---C topic/ \D---E---F---G---H master $ git merge fixes enhancements 可以合并多個(gè)分支到當(dāng)前分支 $git merge 8b9612d76178416c06da3b76cfab2945ddc98347 ----合并某個(gè)提交合并中沖突的處理:
$ git merge feture1 Auto-merging gameoflife-deploy/pom.xml CONFLICT (content): Merge conflict in gameoflife-deploy/pom.xml Automatic merge failed; fix conflicts and then commit the result.merge命令可以一次性把所有沖突的文件合并,然后提示用戶(hù)合并沖突去解決。解決完沖突以后,需要運(yùn)行g(shù)it add命令把文件添加到暫存區(qū)。繼續(xù)執(zhí)行g(shù)it merge --continue命令編輯新生成的提交的log信息。然后merge完成。
2.git rebase
rebase命令除了可以更改提交以外,同時(shí)可以合并代碼,不過(guò)和merge命令有些不同。
假設(shè)歷史記錄如下,且當(dāng)前分支為topic:
那么運(yùn)行g(shù)it rebase master的時(shí)候,其提交如下:
A'--B'--C' topic/D---E---F---G master其中A'、B'、C'和A、B、C已經(jīng)不是同一個(gè)提交(其tree對(duì)象不是同一個(gè),父提交也不是同一個(gè)),但是其修改的內(nèi)容是相同的。
rebase命令合并的時(shí)候從兩個(gè)分支(或者提交)公共的父提交開(kāi)始變基。
總體變基命令用的不多,而且場(chǎng)景比較復(fù)雜(可以查看其help文檔)。慎用
3.merge和rebase的區(qū)別
1、merge命令會(huì)產(chǎn)生一個(gè)合并提交,而變基不會(huì)。變基命令的提交樹(shù)會(huì)比較清晰,merge存在各種合并,看著比較混亂。
2、工作流不同,對(duì)于merge命令其合并是所有提交一次合并好,然后解決沖突,而變基命令只能一個(gè)提交一個(gè)提交的解決沖突。
4.Fast-forward快進(jìn)式合并
在合并的時(shí)候經(jīng)常會(huì)遇到快進(jìn)式合并,那么什么是快進(jìn)式合并么?
假設(shè)存在如下的場(chǎng)景:
而如果執(zhí)行g(shù)it merge topic --no-ff 非快進(jìn)式提交,測(cè)試如下的結(jié)果如下:
A---B---C/ \ D---E --------------M master會(huì)多產(chǎn)生一個(gè)提交M,其父提交為E和C。
5.git cherry-pick
可以使用cherry-pick摘取每個(gè)提交的內(nèi)容,并合并當(dāng)前分支
假設(shè)歷史記錄如下,且當(dāng)前分支為topic:
假設(shè)我們指向合并A、B到master分支,那么就可以使用cherry-pick命令
$git cherry-pick topic~2 topic~1A---B---C topic/D---E---F---G-----A'---B' master如果出現(xiàn)合并沖突,同樣需要處理沖突,然后使用git cherry-pick --continue命令繼續(xù)
6.git如何追蹤沖突
當(dāng)出現(xiàn)沖突的時(shí)候:
- .git/MERGE_HEAD 記錄合并進(jìn)來(lái)的提交的SHA1值。
- .git/MERGE_MSG包含當(dāng)解決沖突以后執(zhí)行g(shù)it commit后默認(rèn)的消息日志
- git的索引(暫存區(qū))里面每個(gè)沖突文件的三個(gè)副本:合并基礎(chǔ)、“我們的”版本和“他們的版本”。給這三個(gè)副本分配了各自的編號(hào)1、2、3.
- 沖突的版本(合并標(biāo)記和所有內(nèi)容)不存儲(chǔ)在暫存區(qū)內(nèi)。
可以使用git ls-files -u命令查看沖突的文件。
轉(zhuǎn)載于:https://blog.51cto.com/5162886/2087794
總結(jié)
- 上一篇: 专访驭势科技吴甘沙:无人驾驶硝烟弥漫,“
- 下一篇: composer安装及使用