Git

知识整理

Linux基础操作

在现今的软件开发中,Linux系统及其命令行的使用,已经是一项必不可少的技能。虽然有其他基于Git的图形化软件,但是Git只能通过命令行进行操作。因此,掌握一些基础的Linux操作命令很有必要。

创建某个目录

有时我们需要创建目录,这时就需要使用命令mkdir。通过mkdir,可以在指定的目录下创建文件夹,其用法如下:

  • 在当前目录下,创建目录helloGitmkdir helloGit
  • /home目录下,创建目录helloGitmkdir /home/helloGit

mkdir的其他高级用法请参考其他Linux资料。

创建文件

创建文件可以使用命令touch,其用法如下:

  • 在当前目录下,创建文件helloGit.txttouch helloGit.txt
  • /home目录下,创建文件helloGit.txttouch /home/helloGit.txt
进入目录

进入某个目录,需要用到命令cd,其用法如下:

  • 进入helloGit目录:cd helloGit`

这样的用法默认了helloGit目录,存在于当前目录下。也可以在cd命令中,直接指定进入当前目录:    cd ./helloGit

  • 进入/home/helloGit目录:   cd /home/helloGit

  • 返回到上一级目录: 在Linux系统下,上一级目录可以用‘…’代替,如:

    #进入上一级目录
    cd ..
    
    #进入上一级目录的再上一级目录
    cd ../../
    
    #进入上一级目录下的helloGit
    cd../helloGit
    

使用Git前的准备

安装

Git可以使用源码安装,具体的安装过程请参考Git官网教程或者GithubGit仓库的用户指南。 但对于初学用户,还是建议大家直接安装。

  • Linux下安装:

    #Fedora下安装
    yum install git-core
    
    #Ubuntu等Debian类体系结构系统下
    apt-get install git
    
  • Mac上安装:在 Mac 上安装 Git 有两种方式。可以使用图形化的 Git 安装工具,网址为图形化Git工具安装地址;另一种是通过MacPorts 安装。如果已经装好了 MacPorts,请用下面的命令安装 Gitsudo port install git-core +svn +doc +bash_completion +gitweb

  • Windows下安装:在 Windows 上安装 Git,可以使用msysGit 的项目提供的安装包,可以到 GitHub 的页面上,下载 exe 安装文件并运行:  http://msysgit.github.com/ 完成安装之后,就可以使用命令行的 git 工具了。建议大家最好使用Unix风格的shell来运行Git。另外,Linux也有其他图形化的Git工具,如Tortoisegit。不过,还是建议大家直接使用shell来运行Git

Git配置

由于Git是一个分布式的版本控制系统,所以当利用它进行分工协作时,必须区分不同的机器。这一点可以通过配置机器的名字和邮箱完成。Git初始使用时,也会提示进行配置。配置命令如下:

$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"

在实际的使用过程中,可以将“Your Name”“email@example”替换为自己实际的名字和邮箱。

Git本地仓库操作

如何创建一个本地版本库

首先,我们需要创建一个目录,做为我们的本地版本库,然后使用git init命令,将其初始化为一个本地版本库,如下:

#在/home目录下,创建repo目录
mkdir /home/repo

#进入repo目录
cd /home/repo

#将repo初始化为一个本地版本库
git init

通过上述命令,即可在/home目录下,创建repo目录,并将其初始化为一个版本库。

如何将修改保存到暂存区

本地版本库就相当于一个存放在本地的仓库,里面记录了我们本地文件的各种版本及不同版本之间的差异。当我们添加、删除或者修改了文件之后,我们必须将修改添加至工作区以暂时保存(Git的工作原理请认真阅读背景知识部分)。

添加修改,并保存至工作区,需要用到git add命令,git add命令的使用方式如下所示:

#添加所有修改git add .#添加hello.txt文件git add hello.txt

如上所示,当需要添加所有文件至工作区时,使用git add .,如果想添加指定文件,只需要像示例中添加hello.txt一样,将文件名做为参数名,传给git add即可。

查看工作区状态

当你创建完helloGit.txt,而且没有将其添加到暂存区域时,如果使用git status命令,你会得到类似于下面的输出(中文):

# 位于分支 master
#
# 初始提交
#
# 未跟踪的文件:
#   (使用 "git add <file>..." 以包含要提交的内容)
#
#    helloGit.txt
提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)

或者这种(英文):

On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
        modified:   src/gitTraining
no changes added to commit (use "git add" and/or "git commit -a")

这是什么?这是提示你工作区有被修改的文件,未提交至暂存区。 当你执行完git add之后,会得到类似于下面的输出:

# 位于分支 master
#
# 初始提交
#
# 要提交的变更:
#   (使用 "git rm --cached <file>..." 撤出暂存区)
#
#    新文件:    helloGit.txt
#

或者这种:

On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
        modified:   src/gitTraining.java

这是在提醒你,暂存区有哪些内容需要提交到本地仓库。

其实git status命令用来查看当前工作区的状态,即有哪些已经修改,还尚未提交到暂存区的文件。在实际的开发过程中,面对复杂的程序文件,你经常需要查看一下,自己对哪些文件做了修改,此时git status命令就很有用了。

撤销修改

如果你不小心把不想添加的东西添加到暂存区,或者想丢弃已经添加的内容,这个时候你该怎么办呢?不用着急,这个时候git checkout命令就可以大显身手了。

checkout命令用法如下:

git checkout helloGit.txt

这样就能把已经添加到本地的helloGit.txt从暂存区中移除。

如何将修改提交到本地仓库

将修改添加到暂存区,只是将你的工作暂时保存,并没有添加到本地的仓库中。这个过程可以类比写文件,将修改添加至暂存区,就相当于把内容先放入缓存区。因此,我们必须将工作区的内容提交到本地版本库去,才算是真正地保存了修改。

提交修改到本地仓库,使用命令git commit,其使用方式如下所示:

git commit -m "示例提交"

-m参数后面跟的是本次提交的具体内容,用来说明你这次的提交,主要是做了哪些修改,这个说明内容是必须的。

解析commit的输出结果

在执行完git commit命令之后,会得到类似于下面的返回结果:

[master(根提交) 37302ce] 添加helloGit.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 helloGit.txt

其中:

  • “添加helloGit.txt”“-m”的参数,即执行的命令为git commit -m "添加helloGit.txt"
  • “1 file changed, 0 insertions(+), 0 deletions(-)” 提示改动信息;
  • “37302ce”这个字符串则是本次提交的Idcommit Id唯一对应一次提交。
令人惊喜的git log和git status

当执行完git commit后,如果你试着执行以下git log你可能会得到如下的输出:

commit 37302ce99137cf30fabc14784d23ea63cadb928b
Author: educoder <educoder@163.com>
Date:   Sun Dec 24 23:35:48 2017 +0800
    添加helloGit.txt

其中:

  • “commit 37302ce99137cf30fabc14784d23ea63cadb928b”中的后面这一串字符就是完整的commit id
  • “Author”就是这次提交的作者,它就是我们在git config中配置的user.name
  • 最后输出的“添加helloGit.txt”,是我们在提交时添加的信息。

如果有多次提交即commit,在执行git log时,会输出每一次的提交的具体信息。这样的话,什么时候(Date)由什么人(Author)提交了什么内容(“添加helloGit.txt”)就一目了然了。

Git远程仓库操作

克隆操作

克隆,顾名思义,就是要获取远程版本库的完整拷贝。通过克隆操作,你可以将整个远程版本库的各种细节复制到本地,并且会建立起本地版本库和远程版本库的对应关系。

克隆操作需要用到的命令是git clone,它的具体用法如下所示:

git clone https://sample.git

通过这样的操作,就能将远程版本库复制到本地了,而且会默认克隆到sample文件夹下(对应于远程版本库地址中指定的sample)。同时,你也可以根据需要,指定克隆到其他目录下,其命令格式为:

git clone xxx.git "指定目录"

这样就能将代码都复制到指定目录下。

Git服务器

在团队开发中,我们必须选用一台主机做为Git服务器来存放远程版本库。这样团队中的每个开发者,就可以基于一个共同的远程版本库进行开发。目前提供代码托管(即可以将远程版本库存放于其上的)的平台有Github、码云等,同时我们也可以搭建一台私有的运行Git的服务器,来做为远程Git服务器。Github等平台的使用,及本地Git服务器的搭建,会在后续的实训中具体介绍。本地Git服务器,可以配置不同的连接方式,如shellgitbash。为了给挑战者提供一个便利的实训环境,我们为每个人配置了一台本地Git服务器,并允许以bash方式进行操作,即可以通过类似于/home/sample.git这种形式的地址,做为远程仓库地址进行操作,而不是像https://sample.git这种形式。

推送本地内容到远程仓库

推送本地内容时,会将所有未推送至远程仓库的内容,都提到远程仓库。它用到的命令是git push,使用方法如下:

git push 远程仓库名 本地分支名 远程分支名

具体的使用方法如下:

git push origin master master

这样就将本地分支的内容,推送到远程仓库originmaster分支了。 git push的另外一种用法如下:

git push -u 远程仓库名 本地分支名 远程分支名

-u参数的作用是,建立起本地master分支和远程master分支之间的对应关系,下一次如果再推送master分支,就可以忽略远程分支名了,如下所示:

#初次推送
git push -u origin master master

#再次推送
git push origin master
拉取远程分支到本地

拉取远程仓库的内容到本地,需要使用git pull命令,其命令格式为:

git pull 远程主机名 远程分支名 本地分支名

其使用示例如下:

#将远程仓库origin的master分支的内容拉取到本地master分支
git pull origin master:master

但是,在使用过程中,也可能会出现一种情况:远程分支和本地分支对同一内容做了修改,这就会导致将远程分支的修改,合并到本地分支的时候发生冲突。这个时候,可以选择解决冲突,然后合并(解决冲突会在后续的实训中介绍)。也可以选择直接强制拉取,使用远程分支的修改,覆盖本地分支的修改。强制拉取需要用到-f参数,语法格式如下:

git pull 远程主机名 远程分支名 本地分支名 -f

具体的使用示例如下:

#将远程仓库origin的master分支的内容拉取到本地master分支
git pull origin master:master -f

Git分支管理

创建本地分支

当初始化一个版本库并进行第一次提交的时候,如果没有创建指定分支,并切换到该分支,commit操作默认会在本地创建master分支,并将内容提交到master分支。一般我们会在版本库中维护一个master分支,如下图所示:

在这里插入图片描述

我们在master分支上,进行了C1C2C3三次提交,且当前指针指向C3提交。 一般情况下,我们只会将已经成熟的代码存放到master分支,而将正在开发的代码或者测试版的代码放到其他分支。这时,我们就需要新建分支,以在该分支进行开发。如下图:

在这里插入图片描述

当我们在主分支进行了C2提交后,新建了develop分支,并在其上进行了两次提交。此时,工作区指针HEAD指向develop分支。 创建本地分支用到的命令是git branch,而分支切换用到的命令是git checkoutgit checkout是有很多用途的命令,在这里我们只讲它在分支操作中的使用。下面我们详细介绍这两个命令的使用。

  • 分支切换 可以使用git checkout 命令切换到其他分支。如你本地有master分支和develop分支,目前你正处于develop分支进行开发,现在你想切换到master去,则可以执行下面的操作: git checkout master 这样就能切换到master分支继续进行开发。

  • 创建新的分支 当你需要创建一个新的分支的时候,可以使用git branch命令,其具体使用格式为:

    git branch 新的分支名字
    

    使用示例如下:

    #创建名为new_branch的新分支
    git branch new_branch
    
  • 创建新分支的同时切换 切换到一个新的分支,有一个更为简洁的命令:git checkout -b,它的使用格式为: git checkout -b 新的分支 名字 其具体使用方法如下: git checkout -b new_branch 这样就可以创建,并切换到了new_branch分支。

删除本地分支

现在我们来看一个实际的例子。请看下图:

在这里插入图片描述

首先,我们在master工作到 C1,然后开始一个新分支develop分支,做为测试版的代码分支。提交到C5的时候,又需要临时解决一个问题,于是从C5的地方又分出一个分支issue。提交到C7的时候,该issue被解决。issue分支已经失去其意义,则需要将其删除,以保持本地版本库分支树的干净。我们将issue分支上的代码,合并到develop上之后,就可将issue分支删除。删除issue分支后的分支树如下:

在这里插入图片描述

其中,C8为合并issue分支所进行的提交。

删除本地分支,需要用到git branch命令,且需要-D参数,具体命令格式为:git branch -D 需要删除的分支的名字 具体使用示例如下:

#删除develop分支git branch -D develop

示例中的命令,能够将本地分支develop删除。

删除远程分支

删除分支用到的git命令是git push,在具体的使用过程中有不同的用法。

  • 通过推送空分支到远程分支,实现删除。 一个删除远程分支的方法是,推送一个空分支到远程指定分支,以实现删除。推送本地分支到远程分支的方法是: git push 远程主机名 本地分支:远程分支

与之类似,推送空分支实现删除的方法是:git push 远程主机名 :远程分支 即:前没有指定本地分支名。具体的使用示例如下:

#删除远程develop分支,其中origin为远程仓库名
git push origin :develop
  • 通过delete参数删除远程分支: 除了推送空分支到远程分支外,也可以通过delete参数实现删除。具体的命令格式为:

    git push 远程主机名 --delete 远程分支名
    

    具体使用示例如下:

    #删除远程develop分支,其中origin为远程主机名
    git push origin --delete develop
    
本地分支合并

分支合并需要用到git merge命令,具体的命令格式为:git merge 需要合并的分支 在具体使用中,如当前处于master分支,需要将develop分支合并到master分支,则具体的使用方式如下:git merge develop 同时,分支合并也分为正常合并和快进式合并,通过为git merge添加参数,即可实现不同操作。

  • 快进式合并 默认情况下,Git执行"快进式合并",即fast-farward merge,会直接将被合并的分支指向需要合并的分支。如下图:

在这里插入图片描述

当需要将右侧分支(develop)合并到左侧分支(master)时,master分支会生成一个指针,直接指向develop。快进式合并为默认合并方式,不需要添加任何其他参数,使用git merge 需要合并的分支即可完成。

  • 正常合并 正常合并的方式如下图:

在这里插入图片描述

如图所示,Master分支上产生了一次新的提交,也就是说生成一个新节点完成了合并,这样的话,版本演进更清晰。

下面我们以一个具体的例子,来演示一下这两种合并方式的区别:

  1. 创建master分支,并在其上提交hello文件;

  2. master分支切换到新分支develop,并进行两次提交,分别将hello1hello2两个文件提交到develop分支;

  3. 切换回master分支,执行git merge develop进行快进式合并,然后查看master分支的日志,得到如下提示信息:

在这里插入图片描述

如上图可知,master分支多了develop分支上的两次提交信息。

  1. master分支回退到合并前状态,再次执行git merge --no-ff develop,进行非快进式合并,然后再次查看日志:

在这里插入图片描述

可见,master分支发生了分叉,且master多了一次提交。

通过以上分析,两种合并方式的区别就很明显了。

日志和版本回退

强大的git log

在之前,我们已经介绍了git log的基本使用方法,这里我们要进一步介绍git log的使用。

  • 查看提交的内容差异 git log提供了-p参数,用于查看每次提交之间的内容差异,如下:   git log -p 即可显示每次提交之间的变化:
commit 92f972422350ef603beb2740a78f57d0f98c1738 (HEAD -> master, origin/mast
Author: educoder <user@sample.com>
Date:   Sat Jan 6 15:57:52 2018 +0800
    第一次提交
diff --git a/7-1.sh b/7-1.sh
new file mode 100644
index 0000000..fa7cc9c
--- /dev/null
+++ b/7-1.sh
@@ -0,0 +1 @@
+###
\ No newline at end of file
diff --git a/7-2.sh b/7-2.sh
new file mode 100644
index 0000000..fa7cc9c
--- /dev/null
+++ b/7-2.sh
@@ -0,0 +1 @@
+###
\ No newline at end of file
diff --git a/7-3.sh b/7-3.sh
new file mode 100644
index 0000000..fa7cc9c
--- /dev/null
+++ b/7-3.sh
@@ -0,0 +1 @@
+###
\ No newline at end of file
diff --git a/7-4.sh b/7-4.sh
new file mode 100644
index 0000000..fa7cc9c
--- /dev/null
+++ b/7-4.sh

而如果想限制显示的范围,则可以再添加参数用于限定:git log -p -2 如上,则仅显示最近的两次更新。 如上所示,这一选项附带了每次commit的内容变化,这就为代码审查或者浏览某个搭档的修改内容,提供了很好的参考。

  • 其他git log选项:
    1. 单词层面对比 Git提供了--word-diff选项,可以显示单词层面的差异。当需要在书籍、论文这种很大的文本文件上,进行对比的时候,这个功能就非常有用。
    2. 显示简要的增改行数 Git提供了--stat选项,则可以仅显示增加或者减少了多少行。
    3. pretty选项 使用--pretty 选项选项,可以指定不同的显示属性,如oneline 将每个提交放在一行显示。 shortfullfuller 可以指定展示的信息的多少。
版本回退
git revert实现版本回退

当将有错误的文件add进暂存区后,可以使用git reset丢弃修改。即:git reset HEAD 文件名 但此时修改仍旧保留在工作区。

如果尚未add进暂存区,则可以使用:git reset --hard HEAD` 这样就能彻底丢弃修改,即将修改从暂存区及工作区彻底删除。

git checkout丢弃修改

当将错误的文件add进暂存区后,使用git checkout无法将修改从暂存区中撤销,必须要先使用git reset将修改从暂存区中撤销。

如果只是工作区有了修改,则可以直接使用git checkout进行撤销,具体操作如下:

git chekcout -- hello

通过这种方式,就可将hello文件自上个commit之后,尚未add进暂存区的修改丢弃。

git reset实现版本回退

git reset也能实现版本回退,但是git revertgit reset也存在一定的区别 :

  • git revert是用一次新的commit来回滚之前的commitgit reset是直接删除指定的commit
  • 在回滚这一操作上看,效果差不多。但是,在日后继续merge以前的老版本时有区别。因为git revert是用一次逆向的commit,“中和”之前的提交,因此日后合并老的branch时,导致这部分改变不会再次出现。但是git reset是把某些commit在某个branch上删除,因而和老的branch再次merge时,这些被回滚的commit应该还会被引入;
  • git reset 是把HEAD向后移动了一下,而git revertHEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。

git reset用法如下:

  • git reset HEAD 回到前一次 commit。也可以用于将错误的文件添加进暂存区后,想回退取消,如:git reset HEAD 文件名
  • git reset HEAD^ 回到前前一次 commit
  • git reset commit 比如:commit = fa042ce57ebbe5b,回到指定的版本,撤销也会作为一次提交进行保存。

另外git reset也可以指定reset的模式:hardsoftmixedmergedkeep。 这几种模式的差别如下:

  • --soft 缓存区和工作目录都不会被改变;
  • --mixed – 默认选项。缓存区和你指定的提交同步,但工作目录不受影响;
  • --hard – 缓存区和工作目录,都同步到你指定的提交。

几种模式的具体使用方法如下:

#直接丢弃工作区和暂存区的修改
git reset --hard HEAD

#暂存区内容保留,工作区修改丢弃
git reset --mixed HEAD

#暂存区和工作区内容都保留
git reset --soft HEAD
删除文件

删除文件需要用到的命令是git rm,且git rm有参数--cached

当我们需要删除暂存区或分支上的文件,同时工作区也不再需要这个文件了,可以使用:

git rm 文件路径

当我们需要删除暂存区或分支上的文件,但本地又需要使用, 只是不希望这个文件被提交到版本库,可以使用:

git rm --cached 文件路径

文件已添加至暂存区

如果文件被添加到了暂存区,这种情况下直接使用git rm file_path会报错:

$ git rm hello.txt
error: the following file has changes staged in the index:
    hello.txt
(use --cached to keep the file, or -f to force removal)

根据提示我们可以得知,这个时候,如果不想保留hello.txt,则可以使用:git rm hello.txt -f 如果想保留hello.txt到工作区则可以使用:git rm --cached hello.txt

文件已提交至分支

如果文件已经被提交到了某个分支,则可以使用如下命令:

#从当前分支中彻底删除‘文件路径’指定的文件
git rm 文件路径

具体使用方法如:

git rm hello.txt

或者:

#从本地版本库中将‘文件路径’指定的文件删除,并保留到工作区
git rm --cached 文件路径

具体使用方法如下:

git rm --cached hello.txt

但是无论使用哪种方式,都相当于在本地做了修改,在git rm --cached之后,使用git status查看版本库状态,可以得到如下输出:

$ git status
On branch master
Initial commit
Unt\fracked files:
  (use "git add <file>..." to include in what will be committed)
        hello.txt
nothing added to commit but unt\fracked files present (use "git add" to t\frack)

因此,还需要通过git commit操作将修改提交。

通过以上分析可知,从仓库中删除文件的一般过程为:

git rm <--cached> 文件名git commit -m "提交信息"

标签

在开发过程中,commit ID是一串无序的字符,它虽然能唯一标记一次代码提交,即一个版本。但是,它很难记忆和辨识。所以,为了给不同的版本起一个容易辨识的名字,我们可以给这次提交打上一个标签,用不同的标签来对应不同的版本。这样,就相当于给这次提交生成了一个快照。实际上,在为某次提交创建标签的时候,Git会为标签生成一个指针,以指向其对应的提交。然后,我们就可以通过标签找到对应的提交,这样对我们版本发布和代码审查都很有帮助。

在这里插入图片描述

如上图所示,我们为master分支上的三次提交,分别打上0.10.20.3三个标签。这样,当我们说0.1版本的时候,就对应了第一次提交的代码。这种方式大大降低了代码审查、团队交流及版本发布的复杂性。

查看标签

查看标签需要用到git tag命令,其具体使用示例如下: git tag

这样就能列出所有的标签,显示的标签按字母顺序排列,所以标签的先后并不表示重要程度的轻重。

如果标签过多,而你指向显示指定的某些标签,则可以使用正则表达式:

git tag -l 'v5.1.2.*'

如上,使用-l参数,并使用v5.1.2.*这一正则表达式,就过滤除了符合要求的标签,其中v5.1.2.*为正则表达式,它能够匹配所有前缀为v5.1.2的标签。实际执行过程中会得到类似于下方的输出:

v5.1.2.1
v5.1.2.2
v5.1.2.3
v5.1.2.4

上方输出信息,为我们列出了目前版本库中已有的四个标签。

创建标签
不含附注的标签

创建标签的命令格式为:

git tag 标签名 commitID

参数commitID标识了该标签对应的代码版本,如果不提供commitID,就默认为最近一次提交后的代码打标签。例如:

git tag v1.0
git tag v1.0 7f8buir2

语句1表示,为最新一次提交后的代码打上v1.0的标签;语句2则表示,为指定的版本7f8buir2打上标签v1.0

包含附注的标签

如果需要像提交代码时增加提交日志那样,为每个标签添加说明信息,则需要使用:

git tag -a 标签名 -m "说明信息"

如:

git tag -a v1.0 -m 'version 1.0'

表示为此次打的标签,增加一个version 1.0的说明信息。

在查看标签时,可以使用git show命令,查看某个标签的附注信息。例如:git show v1.0表示要查看标签v1.0对应的附注信息。

推送标签
推送指定标签

推送指定标签到远程仓库的Git命令如下:

git push 远程主机名 tag名

其中,远程主机名为远程Git版本库对应的主机名,tag名为准备推送的标签名。

该命令使用示例如下:

git push origin v1.0

该语句表示将v1.0标签,推送到主机名为origin对应的远程仓库。

推送全部标签

推送指定标签需要用到: git push 远程主机名 --tags 其使用方法如下: git push origin --tags 其中origin为远程主机名,这样就能将全部标签推送至远程仓库。

删除标签
删除本地标签

删除本地标签,需要用到的命令格式为:

git tag -d 标签名

具体使用方法示例如下:

git tag -d v1.0

这样就能实现删除v1.0标签。

删除远程标签

删除远程tag,可以使用如下命令:

git push origin --delete tag 标签名

或者如下所示的命令:git push origin :refs/tags/<tagname> 即推送一个空的tag名到远程仓库,其中<tagname>指某个标签的名字。

这两种方式都能实现删除远程的指定标签。

冲突处理、忽略文件

冲突的产生
内容冲突

Git内容冲突产生的原因是,针对版本库中某个文件的某项内容,不同的操作对其做了不同的修改,以致于在合并不同的操作时发生矛盾。比如下面的例子:

  1. 我们在本地master分支,添加了文件hello,其内容如下:

    Learning English is easy and simple
    
  2. 然后,我们由master分支切换到一个新的分支develop,并修改hello文件内容如下:

    Learning English is easy & simple
    

    随后将其提交到了本地develop分支。

  3. 我们又切换回master分支,并再次对hello内容进行了修改:

    Learning English is easy or simple
    

    这样,当我们将develop分支合并到master分支的时候,就会出现冲突提示如下:

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

    冲突出现的原因是,我们在develop分支和master分支上,都对hello文件的内容做了修改,这样当将develop合并到master时,Git就不确定究竟应该采用哪个修改。

树冲突

方法文件名修改造成的冲突,称为树冲突。比如,A用户把文件C改名为AB用户把文件C改名为B,那么B合并这两个提交时,就会出现冲突:

CONFLICT (rename/rename): Rename "C"->"B" in branch "HEAD" rename
Automatic merge failed; fix conflicts and then commit the result.

此时如果使用git status查看版本库的状态,会得到如下提示信息:

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)
Unmerged paths:
  (use "git add/rm <file>..." as appropriate to mark resolution)
        added by them:   A
        added by us:     B
        both deleted:    C
no changes added to commit (use "git add" and/or "git commit -a")

树冲突产生的原因是,我们将同一文件名,在不同操作中,修改为不同的名字。

解决冲突
内容冲突

当产生内容冲突时,如果你打开冲突发生的文件,你会在冲突区域发现类似于下面的内容:

<<<<<<< HEAD
Learning English is easy or simple
=======
Learning English is easy & simple
>>>>>>> develop

这个就是我们上面所举的内容冲突的例子,冲突文件的内容。从中可以看到<<<<<<< HEAD=======包括的是我们当前分支的内容,而=======>>>>>>> develop之间的则是需要合并过来的内容,为了解决冲突我们可以手动解决这些冲突,也可以使用图形化工具帮助解决。如果以手动方式解决,我们可以编辑冲突区域内容为我们想要的内容,比如将其修改成如下内容:

Learning English is easy and simple

然后再执行git addgit commit操作提交,这样就能将冲突解决了。 即解决冲突的一般过程为:

  1. 手动编辑冲突区域;
  2. 执行git add,将编辑提交到暂存区;
  3. 执行git commit,将编辑提交到本地仓库以解决冲突。
树冲突

解决树冲突时,对于上面示例中的树冲突,如果最终决定采用文件B,我们可以采用如下方式解决:

git rm A
git rm C
git add B
git commit

即从本地仓库中删除AC文件,然后再添加B文件并最终提交。

强制操作
强制操作的分类

使用最频繁的强制操作,主要在以下几个方面:

  • 强制推送 如果远程的某个分支的内容需要被覆盖,这个时候就需要你进行强制推送,使用本地内容去覆盖该分支。
  • 强制合并 如果本地分支的内容需要被远程内容覆盖,这个时候就需要强制合并远程分支内容到本地。
  • 强制删除 如果你需要强制删除版本库、暂存区或者工作区的内容时,就需要强制删除。比如我们之前介绍的checkout,就可以使用-f参数,强制丢弃本地修改。
强制操作方法
  • 强制推送 强制推送和普通推送的区别,就在于在末尾加上了-f参数,即:

    git push 远程主机名 本地分支名:远程分支名 -f
    

    具体使用方法如下:

    #将本地分支强制推送到远程主机origin的master分支
    git push origin master:master -f
    
  • 强制合并 强制合并和普通合并的区别,也是其在末尾加上了-f参数,即:

    git pull 远程主机名 远程分支名:本地分支名 -f
    

    具体使用方法示例如下:

    #将远程master分支强制合并到本地master分支git pull origin master:master -f
    
忽略文件
如何忽略文件

Git工作区的根目录下,创建一个特殊的.gitignore文件,把要忽略的文件名或者文件名的通配符填进去,然后将.gitignore提交到本地仓库,这样Git就会在你添加或者提交时,自动忽略这些文件。

自定义忽略文件

如果我们需要自己定义忽略哪些文件,就需要将其添加到.gitignore文件中去。你可以使用文件的全称,或者使用正则匹配的通配符。如下所示:

# 忽略指定文件
HelloWrold.class

# 忽略指定文件夹
bin/bin/gen/

# 忽略.class的所有文件
*.class

# 忽略名称中末尾为ignore的文件夹
*ignore/

# 忽略名称中间包含ignore的文件夹
*ignore*/

TG参考答案

Git入门

本地版本库
第一关:本地版本库创建
#创建gitTraining文件夹
mkdir gitTraining

#进入gitTraining文件夹
cd gitTraining

#请添加初始化本地Git仓库的命令
#********** Begin **********#
git init
#********** End **********#
第2关:添加修改到暂存区
#创建gitTraining文件夹
mkdir gitTraining

#进入gitTraining文件夹
cd gitTraining

#请添加初始化本地Git仓库的命令
#********** Begin **********#
git init
#********** End **********#

#创建helloGit.txt文件
touch helloGit.txt

#请添加提交helloGit.txt到暂存区的命令
#********** Begin **********#
git add helloGit.txt
#********** End **********#
第3关:提交修改到本地仓库
#创建gitTraining文件夹
mkdir gitTraining

#进入gitTraining文件夹
cd gitTraining

#请添加初始化本地Git仓库的命令
#********** Begin **********#
git init
#********** End **********#

#创建helloGit.txt文件
touch helloGit.txt
 
#请添加提交helloGit.txt文件到暂存区的命令
#********** Begin **********#
git add helloGit.txt
#********** End **********#

#请添加提交helloGit.txt至本地仓库的命令
#********** Begin **********#
git commit -m "提交helloGit.txt至本地仓库"
#********** End **********#
远程版本库
第1关:clone远程版本库
#请在下面的Begin/End内填写语句以将远程版本库clone到本地
#********** Begin **********#
git clone /tmp/sample.git
#********** End **********#
第2关:添加远程版本库
#创建gitTrainging文件夹
mkdir gitTraining
#进入到gitTraining文件夹
cd gitTraining
#将gitTraining初始化为一个本地仓库
git init
#请在下面的Begin/End内填写语句添加符合要求的主机名和远程仓库
#********** Begin **********#
git remote add git /tmp/sample.git
#********** End **********#
第3关:推送本地内容到远程仓库
#创建gitTraining目录
mkdir gitTraining

#进入gitTraining目录
cd gitTraining

#将gitTraining初始化为一个本地仓库
git init

#创建helloGit.txt
touch helloGit.txt

#添加远程仓库
git remote add git /tmp/educoder.git

#将helloGit.txt添加到暂存区
git add helloGit.txt

#将helloGit.txt提交到本地仓库
git commit -m "hello Git!"


#请在下面的Begin/End内填写语句,将本地master分支的修改推送到
#远程仓库的master分支
#********** Begin **********#

git push git master master

#********** End **********#
第4关:拉取远程分支到本地
#创建gitTraining目录
mkdir gitTraining

#进入gitTraining目录
cd gitTraining

#将gitTraining初始化为一个本地仓库
git init

#创建helloGit.txt
touch helloGit.txt

#添加远程仓库
git remote add git /tmp/educoder.git

#请在下面的Begin/End内填写语句以拉取远程仓库git的master分支内容到本地
#********** Begin **********#

git pull git master master

#********** End **********#
分支管理
第1关:创建本地分支
#创建gitTraining文件夹
mkdir gitTraining

#进入gitTraining文件夹
cd gitTraining

#将gitTraining初始化为一个本地仓库
git init

#请在下面的Bein/End星号线内,使用简洁的命令,新建gitTraining分支并切换到该分支
#********** Begin **********#
git checkout -b gitTraining

#********** End **********#

#创建helloGit.txt文件
touch helloGit.txt

#添加到暂存区
git add helloGit.txt

#提交到本地仓库
git commit -m "提交helloGit.txt到本地仓库"
第2关:删除本地分支
#进入本地仓库目录
cd gitTraining

#请在下方Begin至End星号线内填写git命令以删除git分支
#********** Begin **********#
git branch -D git

#********** End **********#
第3关:删除远程分支
#进入gitTraining
cd gitTraining

#请在下方Begin至End星号线内填写git命令以删除远程git分支
#********** Begin **********#
git push origin --delete git

#********** End **********#
第4关:本地分支合并
#进入gitTraining目录
cd gitTraining

#请在下方Begin至End星号线内填写git命令以合并git分支内容到master分支
#********** Begin **********#
git merge git

#********** End **********#
日志和版本回退
第1关:回到前一次提交
#进入gitTraining
cd gitTraining

#请在下方Begin至End星号线内填写git命令以撤销最近一次提交
#********** Begin **********#
git revert HEAD

#********** End **********#
第2关:回到指定提交
#进入gitTraining
cd gitTraining

#请在下方Begin至End星号线内填写git命令以回到第一次提交的版本
#********** Begin **********#
git reset --hard HEAD^^
#********** End **********#
第3关:撤销修改
#进入gitTraining
cd gitTraining

#请在下方Begin至End星号线内填写git命令以丢弃helloGit的修改
#********** Begin **********#

git checkout --  helloGit
#********** End **********#
第4关:删除文件
#进入gitTraining
cd gitTraining

#请在下方Begin至End星号线内填写git命令以丢弃helloGit的修改
#********** Begin **********#
git rm --cached helloGit
git commit -m "提交信息"
#********** End **********#
标签
第1关:创建标签
#创建gitTraining文件夹
mkdir gitTraining

#进入gitTraining文件夹
cd gitTraining

#将gitTraining初始化为一个本地仓库
git init

#创建helloGit.txt文件
touch helloGit.txt

#将helloGit.txt添加到暂存区
git add helloGit.txt

#将helloGit.txt提价到本地仓库
git commit -m "Git入门之标签实训第一关"

#请在下面的Bein/End星号线内填写Git命令为最近一次提交打上标签v1.0
#********** Begin **********#

git tag v1.0

#********** End **********#
第2关:推送指定标签
#进入gitTraining文件夹
cd gitTraining

#请在下面的Bein/End星号线内填写Git命令以将标签v1.0推送至远程仓库origin
#********** Begin **********#

git push origin v1.0
#********** End **********#
第3关:推送全部标签
#进入gitTraining文件夹
cd gitTraining

#请在下面的Bein/End星号线内填写Git命令为将所有标签推送至远程仓库
#********** Begin **********#
git push origin --tags

#********** End **********#
第4关:删除标签
#进入gitTraining文件夹
cd gitTraining

#请在下面的Bein/End星号线内填写Git命令以删除标签v1.0
#********** Begin **********#

git tag -d v1.0
#********** End **********#

Git进阶

冲突处理、忽略文件
第1关:解决冲突
Learning Git is easy,simple
第2关:强制操作
#创建gitTraining文件夹
mkdir gitTraining

#进入gitTraining文件夹
cd gitTraining

#将gitTraining初始化为一个本地版本库
git init

#创建helloGit2文件
touch helloGit2

#添加到暂存区
git add helloGit2

#提价到本地仓库
git commit -m "添加helloGit2"

#添加远程主机,命名为origin
git remote add origin /tmp/educoder.git

#请在下面的Bein/End星号线内填写Git命令将本地master分支强制推送到远程master分支
#********** Begin **********#

git push origin master:master -f

#********** End **********#
第3关:忽略文件
 ###
 *.xml
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐