码迷,mamicode.com
首页 > 其他好文 > 详细

git命令行(2)

时间:2018-03-16 23:04:46      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:git 命令行

一、父提交的表示方法

1.HEAD引用

在.git/HEAD目录下存在一个HEAD文件,其记录着当前工作区对应的SHA1。如果当前工作区从某个分支检出(checkout),那么这个HEAD文件中的引用最终执行分支对应的SHA1,如果处于分离头状态(不对应分支,从某个commit检查),那么这个HEAD文件中保存的就是检出的commit SHA1。
技术分享图片

如果我们直接使用git checkout master分支,那么HEAD的值为ref: refs/heads/master。指向.git/refs/heads/master文件,其内容就是m6对应的SHA1。
如果我们使用git checkout ${m4.sha1} ,那么HEAD的值为 ${m4.sha1}
因此HEAD引用就是当前工作区对应的提交的SHA1

2.父提交的表示方法

可以使用~(波浪号)和^号表示父提交,但含义会略有不同。
</br>
^表示父提交的第几个提交,后面如果跟数字就是表示第几个父提交
例如上图中当前的工作区HEAD指向m10提交。那么HEAD^和HEAD^1相同都是指向m9。HEAD^^指向m8,而HEAD^2则是没有意义的,因为m10只有一个父提交就是m9。HEAD^^^指向是m7,HEAD^^^2指向d2(HEAD^^指向m8,后面的^2表示m8的第二个父提交)。分析^的时候如果^号后面没有数字则和^1等价,表示第一个父提交,如果存在数字就表示第几个父提交。
tips:如果^后面的形式如:^{commit},^{tree},^{blob},则表示当前对象的提交、树、blob对象。
</br>
~表示法:波浪号表示父提交的层次关系。那么HEAD~和HEAD~1相同都是指向m9。HEAD~ ~指向m8,而HEAD~2和HEAD\~\~是完全等价的。HEAD\~\~\~指向是m7,HEAD~3和其等价。因此d2就可以表示为HEAD~2^2(HEAD~2指向m8,后面的^2表示m8的第二个父提交),因此如果存在数字表示父提交的父提交的父提交...(数字就是几层父提交)

因此当我们使用git log命令的时候,可以打印部分父提交。
git log --oneline HEAD~8..HEAD~5

3.git reflog

当我们对任何的分支修改(commit、pull、push)的时候,在.git/logs/refs目录都会记录变更情况,因此完全不用担心提交记录丢失的情况。.git/logs/refs/heads记录本地分支的变更记录,.git\logs\refs\remotes记录远程分支在本地的变更情况。
当我们使用git reflog命令的时候就会显示HEAD引用的变更情况。
技术分享图片
同样可以通过git reflog master查看master分支的变更情况。
reflog表示法:HEAD@{1},表示HEAD引用之前的第一个变更。

git reset --hard HEAD@{1}。如果新拉取的代码有问题,但是拉取之前的代码不确定是否有问题,需要把代码回滚到拉取之前的代码,那么就可以执行这个命令

二、修改提交

本地提交代码的时候经常会出现需要更改提交、修改注释的情况,下面的几个命令可以实现修改提交。

1.git commit

git commit --amend可以方便的修改当前提及的注释。当执行这个命令的时候会弹出vim编辑器编辑注释信息(只修改提交注释信息)。

2.git reset

git reset命令可以把当前分支重置到某个提交。其选项有三个:

  • --hard:把工作区、暂存区的内容也重置到该提交
  • --mixed:默认选项,把暂存器的内容重置到该提交,但是保留当前工作区的内容
  • --soft:工作区、暂存器保留原来的内容,分支的引用重置到某个提交

3.git revert

如果我们的提交已经push到远程仓库上,别人已经pull下来了,如果你想删除某次提交,reset就不能使用了,而是使用revert命令,revert即对某次提交产生一个反作用的提交。

git revert HEAD~3 -----创建一个提交,回滚最近的第四次提交
git revert  master~5..master~2  ---回滚某个范围的提交 

4.git rebase

git rebase可以对当前没有push的提交进行更改,设想一下一个功能你可以本地进行了多次提交,但是push的时候你想把这些提×××并成一个,就可以使用git rebase命令编辑提交。
假设我们需要对如下m9-m13的提交编辑。
技术分享图片
场景一:把这些提交并成一个提交
技术分享图片
使用squash命令和上一个提×××并,然后重新修改提交日志

场景二:删除某个提交
删除某个提交直接把该提交对应的行去除或者使用remove命令。如果存在合并冲突,然后解决冲突。

技术分享图片
根据git命令行的提示,解决完冲突以后运行git add添加冲突的修改。

场景三:修改某个提交的日志:
使用edit命令或者reword命令修改,最好使用reword命令,这样rebase就可以之间弹出修改日志的vim编辑器,而不用git 弹出git commit --amend提示。

三、分支标签命令

1.git branch

使用branch命令可以管理分支。

$ git branch                ------显示本地分支
$git branch -a            -------显示本地和远程分支
$git branch xxxbranchName -------创建分支名xxxbranchName的分支,此时HEAD的引用仍然是指向原来的分支
$git branch -d xxxbranchName   ---删除某一个分支,如果该分支的修改没有合并,那么删除失败
$git branch -D xxxbranchName -----强制删除分支

2.git tag

使用tag命令可以管理标签。标签和分支的区别是,标签是不可以修改的。如果要修改必须基于该标签拉出一个分支修改

$git tag -------------展示所有的tag
$git tag xxxtagName ---------------新建xxxtagName的标签
$git tag -d xxxtagName ---------删除xxxtagName的标签

3.git checkout

checkout命令可以检出某个提交或者分支。

$git checkout SHA-1           ----------检出某个SHA-1对应的提交
$git checkout xxxbranchName -------------我们使用git branch xxxbranchName的时候只是新建了这个分支,需要执行该命令切换到该分支
$git checkout HEAD^               -----检出到HEAD的第一个父提交
$git checkout -b xxxbranchName -------------新建xxxbranchName并检出到该分支

当我们checkout除分支外的其他SHA-1都会提示我们处于detached HEAD状态,此时.git/HEAD文件里面的内容就是SHA-1
技术分享图片
此时如果在分离头上做的修改和提交想合并到其他分支需要用到merge和rebase等命令

四、合并命令

1.git merge

merge命令可以合并两个多个提交,并生成一个新的提交。
假设历史记录如下,且当前分支为master:

      A---B---C topic
     /
    D---E---F---G master

然后运行 "git merge topic",将会产生一个新的提交H,其中H的父提交是C和G。

      A---B---C topic
     /                  D---E---F---G---H master
$ git merge fixes enhancements 可以合并多个分支到当前分支
$git merge 8b9612d76178416c06da3b76cfab2945ddc98347    ----合并某个提交

合并中冲突的处理:

$ 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命令可以一次性把所有冲突的文件合并,然后提示用户合并冲突去解决。解决完冲突以后,需要运行git add命令把文件添加到暂存区。继续执行git merge --continue命令编辑新生成的提交的log信息。然后merge完成。

2.git rebase

rebase命令除了可以更改提交以外,同时可以合并代码,不过和merge命令有些不同。
假设历史记录如下,且当前分支为topic:

          A---B---C topic
         /
 D---E---F---G master

那么运行git rebase master的时候,其提交如下:

                         A‘--B‘--C‘ topic
                        /
    D---E---F---G master

其中A‘、B‘、C‘和A、B、C已经不是同一个提交(其tree对象不是同一个,父提交也不是同一个),但是其修改的内容是相同的。
rebase命令合并的时候从两个分支(或者提交)公共的父提交开始变基。
总体变基命令用的不多,而且场景比较复杂(可以查看其help文档)。慎用

3.merge和rebase的区别

1、merge命令会产生一个合并提交,而变基不会。变基命令的提交树会比较清晰,merge存在各种合并,看着比较混乱。
2、工作流不同,对于merge命令其合并是所有提交一次合并好,然后解决冲突,而变基命令只能一个提交一个提交的解决冲突。

merge:merge的时候把待合并的所有commit一次合并好,只显示一次冲突,解决完冲突以后运行一次git merge --continue就行。
rebase:  工作流程大概如下:
             commit =nextNeedMergeCommit()
              while(merge(commit)==confict)
                            {
                                resoveConfilec();
                                    rebaseContinue();
                                    commit =nextNeedMergeCommit()
                            }

4.Fast-forward快进式合并

在合并的时候经常会遇到快进式合并,那么什么是快进式合并么?
假设存在如下的场景:

          A---B---C topic
         /
 D---E           master
    那么我们执行git merge topic命令的时候,其结果就是快进式合并如下:

D---E --- A---B---C          master

而如果执行git merge topic --no-ff 非快进式提交,测试如下的结果如下:

          A---B---C
         /              D---E --------------M          master

会多产生一个提交M,其父提交为E和C。

5.git cherry-pick

可以使用cherry-pick摘取每个提交的内容,并合并当前分支
假设历史记录如下,且当前分支为topic:

          A---B---C topic
         /
 D---E---F---G master

假设我们指向合并A、B到master分支,那么就可以使用cherry-pick命令

$git cherry-pick topic~2 topic~1
          A---B---C topic
         /
 D---E---F---G-----A‘---B‘ master

如果出现合并冲突,同样需要处理冲突,然后使用git cherry-pick --continue命令继续

git命令行(2)

标签:git 命令行

原文地址:http://blog.51cto.com/5162886/2087794

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!