什么是origin、origin/master和master
在了解origin、origin/master和master之前,我们需要先了解一下【git clone】命令做了一些什么:
自动将远程服务器命名为origin
下载该服务下的所有数据
创建一个指向远程master分支的指针,并将远程master分支命名为origin/master
创建名为master的本地分支,并且和远程分支处在同一个提交节点,如下图所示。
origin并不特别,就像分支名master在git中没有任何特殊意义一样,当执行【git init】命令时,master会作为初始分支的默认名字,因此使得master分支名被广泛使用,而origin是执行【git clone】命令时的默认服务器名称,当然可以通过指令【git clone -o cat】命令来使得默认服务器名称为cat,
而默认远程分支为cat/master。由此我们可以得知:①origin指的是远程服务器名称。②origin/master指的是远程默认分支。③master指的是本地默认分支。
追踪分支
从远程分支【checkout】一个本地分支,该本地分支被称为追踪分支(tracking branch),被追踪的分支被称为上游分支(upstream branch),追踪分支可以理解为是和远程分支有直接关联的本地分支,例如:我们执行【git clone】命令创建了本地仓库后,git会自动帮我们创建一个追踪origin/master分支的本地追踪分支master。如果我们在追踪分支里执行【git pull】命令,git会自动知道需要获取和merge的分支的服务器。
当然我们也可以根据需求添加其他的追踪分支,添加其他追踪分支的命令为:
#创建追踪分支
$ git checkout -b nativeBranchName remoteName/remoteBranchName
#备注:
# 本地分支的名称不一定要和远程分支的名称一致
#git为该命令提供了通用的--track简写操作:
$ git checkout --track remoteName/remoteBranchName
#备注:
# git会在本地帮我们自动创建一个跟远程分支同名的本地分支,并且该本地分支会自动追踪远程分支。
#git还为该命令提供了最简单的写法:
$ git checkout branchName
#备注:
# 如果checkout的分支本地不存在,但是和远程分支名一样,git会帮我们创建该本地分支并且自动追踪同名的远程分支,并且切换到该分支。
分支的基本操作
一个Git仓库可以维护很多开发分支。当我们在实际的项目开发过程中,会遇到多个需求同时要对一个文件进行修改的情况,那么此时为了便于开发人员进行需求的开发,我们往往会根据不同的需求来创建不同的分支,然后每个分支独立进行开发,当开发完成后再将这些分支进行合并,这样做的好处在于能够避免多个开发人员对同一个文件进行修改时容易产生混乱的局面。
- 创建分支
我们可以使用【git branch branchName】命令来创建一个新的开发分支,然后使用【git branch】命令来查看项目中存在的分支:
$ git branch experimental
$ git branch
experimental
* master
其中“experimental”是我们刚刚创建的分支,“master”分支是Git系统默认创建的主分支。星号(“*”)标识了你当工作在哪个分支下 。
- 切换分支
我们可以使用【git checkout branchName】来进行分支间的切换:
$ git checkout experimental
Switched to branch 'experimental'
$ git branch
* experimental
master
我们可以看到星号("*")标志在分支"experimental"上。此时我们在“experimental”分支的工作区中修改一些文件,然后再将这些文件进行提交操作,最后再切换到“master”分支上,那么会发生何种情况呢?
$ ll
total 1
drwxr-xr-x 1 Administrator 197121 0 3月 2 22:54 HelloProjet/
-rw-r--r-- 1 Administrator 197121 229 2月 7 13:12 helloWord.txt
$ tail -f helloWord.txt
1111111111111111111111111111111111111111111111111111111111111111
2222222222222222222222222222222222222222222222222222222222222222
3333333333333333333333333333333333333333333333333333333333333333
4444444444444444444444444444444
我们看到仓库中有一个文件夹和一个文本文件,文本文件的内容如上所示,那么此时我们该文本文件中的内容替换为“hello git”,然后提交,再切换到“master”分支,最后再查看"helloWord.txt"的内容:
#编辑helloWord.txt文件内容
$ vim helloWord.txt
#查看helloWord.txt文件内容
$ tail -f helloWord.txt
hello git
#提交修改文件至本地仓库
$ git commit -a
[experimental 57e1c3f] 修改helloWord文件
1 file changed, 1 insertion(+), 4 deletions(-)
#切换到master分支
$ git checkout master
Switched to branch 'master'
#查看master分支上的helloWord.txt文件内容
$ tail -f helloWord.txt
1111111111111111111111111111111111111111111111111111111111111111
2222222222222222222222222222222222222222222222222222222222222222
3333333333333333333333333333333333333333333333333333333333333333
4444444444444444444444444444444
我们现在可以看到原来在“experimental”分支下所作的修改已经不再了,这是因为我们现在切换回了“master”分支,所以原来那些修改就不存在了。但是当我们切换回“experimental”分支的时候,这些修改就会展示出来了:
#切换到experimental分支
$ git checkout experimental
Switched to branch 'experimental'
#查看helloWord.txt中的文件
$ tail -f helloWord.txt
hello git
- 删除分支
我们可以使用【git branch -d branchName】命令来删除一个分支,但是该命令只能删除已被当前分支合并的分支,如果你想要的强行删除某个分支的话,就只能使用【git branch -D branchName】:
$ git branch
experimental
* master
$ git branch -d experimental
error: The branch 'experimental' is not fully merged.
If you are sure you want to delete it, run 'git branch -D experimental'.
$ git branch -D experimental
Deleted branch experimental (was 57e1c3f).
$ git branch
* master
从上面的展示中我们可以看到,当我们在“master”分支中执行【git branch -d experimental】命令想要删除一个没有和“master”分支合并的“experimental”分支时,git会报错,但是当我们执行【git branch -D experimental】命令去删除“experimental”分支时,git就告诉我们删除成功了。
- 合并分支
当我们的开发人员把各自的需求都完成后,我们就需要将多个分支进行合并,此时我们可以使用【git merge branchName】命令来将“branchName”分支合并到当前分支上。分支合并的时候回存在两种情况:一种是两个分支没有修改同一个文件,那么这两个分支在进行合并的时候就不会存在冲突问题。第二种是两个分支同时修改了一个文件,那么在合并的时候就会存在冲突。
我们先看看两个分支没有涉及到修改同一个文件的情况,例如:
#我们先看看当前分支情况
$ git branch
experimental
* master
#我们的工作区间现在处在master分支上,那我们先看看master分支的文件情况
$ ll
total 1
drwxr-xr-x 1 Administrator 197121 0 3月 2 22:54 HelloProjet/
-rw-r--r-- 1 Administrator 197121 229 3月 2 23:25 helloWord.txt
#然后我们切换到experimental分支,看看experimental分支的文件情况
$ ll
total 2
drwxr-xr-x 1 Administrator 197121 0 3月 2 22:54 HelloProjet/
-rw-r--r-- 1 Administrator 197121 229 3月 2 23:25 helloWord.txt
-rw-r--r-- 1 Administrator 197121 10 3月 4 12:42 helloWord2.txt
#我们发现experimental分支比master分支要多了一个文件
#那么假如我们需要将这两个分支进行合并的话
#我们要先切换到master分支
$ git checkout master
Switched to branch 'master'
#然后执行分支合并的命令将experimental分支合并到master分支上
#如果执行合并命令后显示结果如下,则说明合并成功
$ git merge experimental
Updating d4e0d63..5a2aedb
Fast-forward
helloWord2.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 helloWord2.txt
#接着我们可以看到master分支上也多了一个helloWord2的文件
$ ll
total 2
drwxr-xr-x 1 Administrator 197121 0 3月 2 22:54 HelloProjet/
-rw-r--r-- 1 Administrator 197121 229 3月 2 23:25 helloWord.txt
-rw-r--r-- 1 Administrator 197121 10 3月 4 12:45 helloWord2.txt
#那么此时如果experimental分支没有作用的话,我们可以删除掉这个分支
#因为experimental分支是被当前分支合并了的,所以我们可以使用“-d”的命令进行删除
$ git branch -d experimental
Deleted branch experimental (was 5a2aedb).
接着我们来看看第二种存在冲突的情况下我们应该如何进行分支的合并:
#我们master分支的基础上创建一个experimental分支
$ git branch experimental
#然后我们切换到experimental分支
$ git checkout experimental
#我们查看experimental分支的文件情况
$ ll
total 2
drwxr-xr-x 1 Administrator 197121 0 3月 2 22:54 HelloProjet/
-rw-r--r-- 1 Administrator 197121 229 3月 2 23:25 helloWord.txt
-rw-r--r-- 1 Administrator 197121 10 3月 4 12:55 helloWord2.txt
#我们看看helloWord2.txt的文件内容
$ tail -f helloWord2.txt
helloWord2
#我们编辑helloWord2.txt文件,添加如下内容并提交
$ tail -f helloWord2.txt
helloWord2
helloWord3
helloWord4
$ git commit -a
warning: LF will be replaced by CRLF in helloWord2.txt.
The file will have its original line endings in your working directory
[master 0608bb2] 添加一些内容
1 file changed, 3 insertions(+), 1 deletion(-)
#然后我们切换到master,对master分支上的helloWord2.txt文件也进行一些修改并提交
$ git checkout master
Switched to branch 'master'
$ tail -f helloWord2.txt
helloWord2
helloWord5
helloWord6
$ git commit -a
warning: LF will be replaced by CRLF in helloWord2.txt.
The file will have its original line endings in your working directory
[master 0608bb2] 添加一些内容
1 file changed, 3 insertions(+), 1 deletion(-)
#接着我们执行分支合并的命令将experimental分支合并到master分支,此时就会存在冲突的问题了
$ git merge experimental
Auto-merging helloWord2.txt
CONFLICT (content): Merge conflict in helloWord2.txt
Automatic merge failed; fix conflicts and then commit the result.
#从上面的显示中我们可以看出,helloWord2.txt文件存在冲突,自动合并失败
#此时我们查看git的状态也可以看出有一个文件存在冲突
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: helloWord2.txt
#如果Git中存在冲突的文件,那么我们每次执行commit命令都会失败,那么此时怎么办呢
#首先,我们应该要解决helloWord2.txt文件的冲突,我们打开helloWord2.txt文件可以看到如下的内容
helloWord2
<<<<<<< HEAD
helloWord5
helloWord6
=======
helloWord3
helloWord4
>>>>>>> experimental
#我们可以看到文本中添加了“<<<<<<< HEAD”,“=======”和“>>>>>>> experimental”的标志符
#那这是什么呢,这就是git在告诉我们冲突的地方在哪里
#此时,我们需要手动合并这个存在冲突的位置,合并成我们想要的结果,然后删除掉标志符。合并结果如下
$ tail -f helloWord2.txt
helloWord2
helloWord3
helloWord4
helloWord5
helloWord6
#当我们将冲突文件手动合并成我们想要的内容时,我们再执行commit命令就可以了
$ git commit -a
[master 8670392] Merge branch 'experimental'
当我们合并两个分支后,我们可以在“Git Bash Here”窗口输入【gitk】命令来打开Git的图形化操作工具,我们可以在该工具中看到刚刚的“commit”对象存在两个父分支,一个指向当前分支,一个指向刚才合并进来的分支。如下所示:
- 撤销一个合并