赞
踩
HEAD是一个活动指针,指向的是正在活跃的分支。
【在当前HEAD指针指向的位置创建分支】
git branch b1
查看.git\refs\heads
目录:
【继续使用master分支开发】
echo '444' > aaa.txt
git commit -m '444' ./
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git log --oneline
2920850 (HEAD -> master) 444
57a8f94 (b1) 333
3ac4fa8 222
afb705d 111
【指定提交对象来创建分支】
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git branch b2 3ac4fa8 # 根据指定的提交对象来创建分支
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git log --oneline
2920850 (HEAD -> master) 444
57a8f94 (b1) 333
3ac4fa8 (b2) 222
afb705d 111
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ cat .git/refs/heads/b2
3ac4fa83b8c224518758b2b4ef7d2f214ac0224a
创建好了分支之后,我们可以使用git checkout
切换到其他分支进行开发;
git checkout {branchName}
【准备环境】
rm -rf .git ./* git init echo '111' >> aaa.txt git add ./ git commit -m '111' ./ echo '222' >> aaa.txt git commit -m '222' ./ echo '333' >> aaa.txt git commit -m '333' ./ Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git log --oneline 2130f83 (HEAD -> master) 333 86cbe2b 222 dad9d1a 111
【创建分支】
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) # 在当前位置创建b1分支
$ git branch b1
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) # 指定提交对象来创建分支
$ git branch b2 86cbe2b
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git log --oneline
2130f83 (HEAD -> master, b1) 333 # b1分支的位置
86cbe2b (b2) 222 # b2分支的位置
dad9d1a 111
【切换到b1分支进行开发】
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) # 切换到b1分支 $ git checkout b1 Switched to branch 'b1' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (b1) # HEAD指针指向了b1分支 $ git log --oneline 2130f83 (HEAD -> b1, master) 333 86cbe2b (b2) 222 dad9d1a 111 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (b1) # 编辑文件 $ echo "444" >> aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (b1) # 提交 $ git commit -m "b1 444" ./ Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (b1) # 查看文件内容 $ cat aaa.txt 111 222 333 444 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (b1) # 查看日志 $ git log --oneline 51b41c0 (HEAD -> b1) b1 444 # b1分支正在开发 2130f83 (master) 333 # master和b2分支留在原地 86cbe2b (b2) 222 dad9d1a 111 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (b1) # 切换到master分支 $ git checkout master Switched to branch 'master' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) # 查看日志 $ git log --oneline 2130f83 (HEAD -> master) 333 # HEAD指针指向了master分支 86cbe2b (b2) 222 dad9d1a 111 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) # 查看master分支工作状态的文件内容(文件内容是旧版本的) $ cat aaa.txt 111 222 333
【查看所有版本情况】
默认情况下使用git log
查询日志只能查询到之前的版本的日志,无法查询到比自身分支版本还要新的版本,通过--all
可以查询所有版本的提交日志;
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git log --oneline # 只能查询master分支之前版本的日志信息
2130f83 (HEAD -> master) 333
86cbe2b (b2) 222
dad9d1a 111
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) # 查询所有日志信息
$ git log --oneline --all
51b41c0 (b1) b1 444
2130f83 (HEAD -> master) 333
86cbe2b (b2) 222
dad9d1a 111
通常情况下,当前分支如果存在未提交的操作时,则无法切换到其他分支;所以我们切换分支时最好保证当前工作空间的状态为nothing to commit
;即:所有操作均已提交
在切换分支时,Git会对以下地方进行修改:
【代码示例】
rm -rf .git ./*
git init
echo '111' >> aaa.txt
git add ./
git commit -m '111' ./
git branch b1
echo '222' >> aaa.txt
git add ./
git commit -m '222' ./
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master)
$ git log --oneline --all
464d580 (HEAD -> master) 222
cc3429a (b1) 111
【操作master分支的文件但不提交,切换到b1分支发现切换失败】
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 编辑文件 $ echo "333" >> aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: aaa.txt no changes added to commit (use "git add" and/or "git commit -a") Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git checkout b1 error: Your local changes to the following files would be overwritten by checkout: aaa.txt Please commit your changes or stash them before you switch branches. Aborting
可以看出,如果当前分支存在未提交的操作时,Git不允许切换分支。但是有2种情况是例外的:
如果存在以上两种行为进行切换分支,则切换分支时不仅会对HEAD指针、工作空间等地方修改,还会对如下地方进行修改:
Tips:我们在切换分支时,要保证当前分支是提交的状态,否则会对其他分支造成不必要的影响;
新分支、新文件的操作都会影响工作空间和暂存区;
【演示新分支影响工作空间】
初始化仓库
rm -rf ./* .git
git init
echo '111' >> aaa.txt
git add ./
git commit -m '111' ./
git branch b1
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # b1分支创建后整个工作空间还没有提交过任何一次文件,属于新分支
$ git log --oneline --all
4b3c6bc (HEAD -> master, b1) 111 # 指针还是指向master分支的
在master分支编辑文件,然后切换到b1分支,查看工作空间的内容,发现变更了(影响了b1分支的工作空间内容):
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 编辑master分支的文件内容 $ echo "222" >> aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # master分支的状态 $ git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: aaa.txt no changes added to commit (use "git add" and/or "git commit -a") Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 切换到b1分支,发现能够切换成功 $ git checkout b1 Switched to branch 'b1' M aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) # b1分支的文件内容 $ cat aaa.txt 111 222 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) # b1分支的状态 $ git status On branch b1 Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: aaa.txt no changes added to commit (use "git add" and/or "git commit -a")
可以看到在遇到新分支时,当前工作空间的操作即使未提交也可以切换到其他分支,而且影响其他分支的工作空间状态及工作空间内容;注意,此时将master未提交的数据也影响到了b1分支,当分支切换到master然后提交,b1分支被影响的内容就消失了;
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) # 切换到master分支 $ git checkout master Switched to branch 'master' M aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 提交操作 $ git commit -m "222" ./ Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 切换到b1分支 $ git checkout b1 Switched to branch 'b1' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) # 查看内容,发现影响消失了 $ cat aaa.txt 111
重新切换到master分支,编辑文件未提交,切换到b1分支失败(此时b1分支不属于新分支了):
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1)
$ git checkout master
Switched to branch 'master'
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master)
$ echo "333" >> aaa.txt
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 切换到b1分支失败,此时b1分支不属于新分支了;
$ git checkout b1
error: Your local changes to the following files would be overwritten by checkout:
aaa.txt
Please commit your changes or stash them before you switch branches.
Aborting
【演示新文件影响工作空间】
把之前编辑的内容删除,将工作空间恢复到干净状态
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 把之前编辑的内容删除
$ vi aaa.txt
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master)
$ cat aaa.txt
111
222
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 工作空间又回到了干净状态(所有的操作均已提交)
$ git status
On branch master
nothing to commit, working tree clean
使用master创建一个新的文件,切换到b1分支,查看b1分支的工作空间内容,发现也多了一个bbb.txt文件(影响了b1分钟的工作空间):
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 编辑一个新的文件 $ echo "333" >> bbb.txt # 注意,此时创建了一个新的文件bbb.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git status On branch master Untracked files: (use "git add <file>..." to include in what will be committed) bbb.txt nothing added to commit but untracked files present (use "git add" to track) Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 切换到b1分支,发现切换成功 $ git checkout b1 Switched to branch 'b1' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) $ ll total 2 -rw-r--r-- 1 Adminstrator 197121 5 Oct 23 09:23 aaa.txt -rw-r--r-- 1 Adminstrator 197121 4 Oct 23 09:23 bbb.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) # b1的工作空间多了一个文件 $ git status On branch b1 Untracked files: (use "git add <file>..." to include in what will be committed) bbb.txt nothing added to commit but untracked files present (use "git add" to track)
切换到master分支,提交操作,然后切换回b1分支,发现b1分支的bbb.txt文件清除了:
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) # 切换回master分支 $ git checkout master Switched to branch 'master' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git add ./ Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 提交操作 $ git commit -m "333-bbb" ./ Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 切换到b1分支 $ git checkout b1 Switched to branch 'b1' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) $ git status On branch b1 nothing to commit, working tree clean Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) # b1工作空间的bbb.txt文件清除了 $ ll total 1 -rw-r--r-- 1 Adminstrator 197121 5 Oct 23 09:26 aaa.txt
【演示新分支影响暂存区】
初始化仓库:
rm -rf ./* .git
git init
echo '111' >> aaa.txt
git add ./
git commit -m '111' ./
git branch b1
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # b1分支创建后整个工作空间还没有提交过任何一次文件,属于新分支
$ git log --oneline --all
19fd84b (HEAD -> master, b1) 111 # 指针还是指向master分支的
在master分支编辑文件,然后添加到暂存区,切换到b1分支,查看b1分支的暂存区内容,发现变更了(影响了b1分支的暂存区);
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ echo "222" >> aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git add ./ warning: LF will be replaced by CRLF in aaa.txt. The file will have its original line endings in your working directory Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git checkout b1 Switched to branch 'b1' M aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) $ git ls-files -s 100644 a30a52a3be2c12cbc448a5c9be960577d13f4755 0 aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) $ git cat-file -p a30a52a3 111 222
重新切换回master,提交之前的操作,然后再切换回b1分支,查看暂存区内容,发现影响消除了(此时b1不再属于新分支了):
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) $ git checkout master Switched to branch 'master' M aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git commit -m "222" ./ warning: LF will be replaced by CRLF in aaa.txt. The file will have its original line endings in your working directory [master 2ae7cda] 222 1 file changed, 1 insertion(+) Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git checkout b1 Switched to branch 'b1' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) $ git ls-files -s 100644 58c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c 0 aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) $ git cat-file -p 58c9bdf9 111
切换回master分支,编辑文件,还没有提交,切换到b1分钟发现出错(此时b1分支不属于新分支了):
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master)
$ echo "333" >> aaa.txt
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master)
$ git add ./
warning: LF will be replaced by CRLF in aaa.txt.
The file will have its original line endings in your working directory
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master)
$ git checkout b1
error: Your local changes to the following files would be overwritten by checkout:
aaa.txt
Please commit your changes or stash them before you switch branches.
Aborting
【演示新文件影响工作空间】
提交之前的操作,将工作空间恢复到干净状态
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master)
$ git commit -m "333" ./
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master)
$ git log --oneline --all
f5d54ea (HEAD -> master) 333
2ae7cda 222
e9b98e3 (b1) 111
创建一个新文件,添加到暂存区,然后切换到b1分支,发现b1分支的暂存区也多了一个文件(影响了b1分支的暂存区):
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ echo "444-bbb" >> bbb.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git add ./ warning: LF will be replaced by CRLF in bbb.txt. The file will have its original line endings in your working directory Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git checkout b1 Switched to branch 'b1' A bbb.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) # b1分支的暂存区也多了一个文件 $ git ls-files -s 100644 58c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c 0 aaa.txt 100644 a864cef2a0696aabcc85e6e55f04dc12230bab84 0 bbb.txt
切换回master,提交之前的操作,然后再切换回b1分支,查询b1分支的暂存区内容被消除了(消除影响):
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) $ git checkout master Switched to branch 'master' A bbb.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git commit -m "444-bbb" ./ warning: LF will be replaced by CRLF in bbb.txt. The file will have its original line endings in your working directory [master d76cc6f] 444-bbb 1 file changed, 1 insertion(+) create mode 100644 bbb.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git checkout b1 Switched to branch 'b1' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) $ git ls-files -s 100644 58c9bdf9d017fcd178dc8c073cbfcbb7ff240d6c 0 aaa.txt
此时bbb.txt文件已经不属于新文件了,回到master分支,编辑bbb.txt文件,未提交,然后切换到b1分支,发现切换不了:
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) $ git checkout master Switched to branch 'master' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ echo "555-bbb" >> bbb.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git add ./ warning: LF will be replaced by CRLF in bbb.txt. The file will have its original line endings in your working directory Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git checkout b1 error: Your local changes to the following files would be overwritten by checkout: bbb.txt Please commit your changes or stash them before you switch branches. Aborting
git switch
是Git 2.23版本推出的一个新的命令,专门用于分支的切换,而git checkout
除了做分支的切换还有一些其他的功能,如恢复文件,恢复暂存区等;
初始化仓库:
rm -rf ./* .git
git init
echo '111' >> aaa.txt
git add ./
git commit -m '111' ./
使用git checkout恢复文件:
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ echo "222" >> aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: aaa.txt no changes added to commit (use "git add" and/or "git commit -a") Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git checkout aaa.txt Updated 1 path from the index Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git status On branch master nothing to commit, working tree clean
使用git checkout恢复暂存区:
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ echo "222" >> aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 添加到暂存区 $ git add ./ warning: LF will be replaced by CRLF in aaa.txt. The file will have its original line endings in your working directory Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git status On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git reset aaa.txt Unstaged changes after reset: M aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) $ git checkout aaa.txt Updated 1 path from the index Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (master) # 成功恢复 $ git status On branch master nothing to commit, working tree clean
但git switch
命令是专门用于切换分支的,并且git switch
切换分支也会存在我们探究的新分支、新文件切换时所带来的影响问题;
使用git switch
命令切换分支:
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 ((89dda87...)) $ git log --oneline --all 033f6b5 (master) 222 89dda87 (HEAD) 111 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 ((89dda87...)) $ git branch b1 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 ((89dda87...)) $ git switch b1 Switched to branch 'b1' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace/xiaohui/test01 (b1) $ git log --oneline --all 033f6b5 (master) 222 89dda87 (HEAD -> b1) 111
建立好分支后,我们可以使用分支进行开发功能,开发功能趋于成熟稳定后,我们可以将master分支与当前分支进行合并,这样其他分支的功能就集成到主分支上了,这也是当前主流的开发方式。
使用分支开发功能从角度上划分一般为同轴开发和非同轴开发。
git merge {branchName}
同轴开发:创建一个新分支,使用新分支开发,等待开发功能趋于成熟稳定后,我们可以将master分支与新分支进行合并,这样其他分支的功能就集成到主分支上了,这也是企业里面经常用的一种开发方式;
对于前面的版本想要合并后面的版本,我们称为快进合并
在同轴开发中,多个分支处于同一根开发轴上,后面版本的代码包含前面版本的代码,因此同轴开发一般只会存在快进合并;
【示例代码】
初始化项目:
rm -rf .git ./*
git init
echo '用户名+密码登录' >> login.txt
git add ./
git commit -m '用户名+密码登录功能完成' ./
①创建login分支
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git branch login
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git log --oneline --all
2f5d87a (HEAD -> master, login) 用户名+密码登录功能完成
②切换到login分支
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git checkout login
Switched to branch 'login'
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login)
$ git log --oneline --all
2f5d87a (HEAD -> login, master) 用户名+密码登录功能完成
③使用login分支开发:集成QQ登录
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login)
$ echo "集成QQ登录" >> login.txt
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login)
$ git commit -m "集成QQ登录" ./
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login)
$ git log --oneline --all
a879a6c (HEAD -> login) 集成QQ登录
2f5d87a (master) 用户名+密码登录功能完成
④使用login分支开发:集成微信登录
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login)
$ echo "集成微信登录" >> login.txt
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login)
$ git commit -m "集成微信登录" ./
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login)
$ git log --oneline --all
c5a2584 (HEAD -> login) 集成微信登录
a879a6c 集成QQ登录
2f5d87a (master) 用户名+密码登录功能完成
当login分支基于稳定后,将功能集成到maste分支:
⑤切换回master分支,将login分支的代码合并到master分支:
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login) $ git checkout master Switched to branch 'master' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ cat login.txt 用户名+密码登录 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git merge login Updating 2f5d87a..c5a2584 Fast-forward login.txt | 2 ++ 1 file changed, 2 insertions(+) Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ cat login.txt 用户名+密码登录 集成QQ登录 集成微信登录
将login分支的代码合并到master分支,其实本质上就是让master也指向与login一样的提交对象;
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) # master与login分支指向的是同一个Commit对象
$ cat .git/refs/heads/login
c5a258428f0bec398017159126f0b87b0d05a1e4
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ cat .git/refs/heads/master
c5a258428f0bec398017159126f0b87b0d05a1e4
非同轴开发:创建一个新分支,使用新分支开发,与此同时master分支也在开发行功能,等到新分支开发的功能完毕后,将master分支与新分支进行合并,将新分支集成到master分支中,但是新分支在开发过程中master分支也进行了一部分开发。
==在非同轴开发中,后面的版本(v3)需要合并前面的版本(v2),这种合并方式称为典型合并;==由于典型合并存在于非同轴
需要注意的是,如果是同轴开发,后面版本的内容肯定包含前面版本的内容,因此==同轴开发不存在典型合并==,只存在快进合并。另外,非同轴开发也存在快进合并,例如上图中的③步骤中,前面的版本(v2)想要合并后面的版本(v3),这也是一种快进合并。
总结:
Tips:典型合并必定是非同轴,快进合并可以是非同轴也可以是同轴。
【示例代码】
初始化项目:
rm -rf .git ./*
git init
echo '用户名+密码登录' >> project.txt
git add ./
git commit -m '用户名+密码登录功能完成' ./
①创建login分支:
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git branch login
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) # 查看不同轴的日志需要加上--graph
$ git log --oneline --all --graph
* 7c0b2a3 (HEAD -> master, login) 用户名+密码登录功能完成
②切换到login分支,使用login分支进行开发:
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git checkout login
Switched to branch 'login'
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login)
$ echo "集成QQ登录" >> project.txt
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login)
$ git commit -m "集成QQ登录" ./
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login)
$ git log --oneline --all --graph
* 9c968e0 (HEAD -> login) 集成QQ登录
* 7c0b2a3 (master) 用户名+密码登录功能完成
③切换回master分支添加注册功能:
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login) $ git checkout master Switched to branch 'master' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) # 查看master分支的project.txt文件,代码并没有合并过来 $ cat project.txt 用户名+密码登录 添加头像上传功能 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) # 查看日志,处于不同轴开发路径 $ git log --oneline --all --graph * fecdb41 (HEAD -> master) 添加头像上传功能 | * 9c968e0 (login) 集成QQ登录 |/ * 7c0b2a3 用户名+密码登录功能完成
④将login分支的合并到master分支:产生代码冲突
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git merge login
Auto-merging project.txt
CONFLICT (content): Merge conflict in project.txt
Automatic merge failed; fix conflicts and then commit the result.
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master|MERGING)
$ cat project.txt
用户名+密码登录
<<<<<<< HEAD
添加头像上传功能
=======
集成QQ登录
>>>>>>> login
解决代码冲突:
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master|MERGING) $ cat project.txt 用户名+密码登录 <<<<<<< HEAD 添加头像上传功能 ======= 集成QQ登录 >>>>>>> login Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master|MERGING) $ vi project.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master|MERGING) $ cat project.txt 用户名+密码登录 添加头像上传功能 集成QQ登录 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master|MERGING) $ git commit -a -m "合并login分支,并解决代码冲突" [master 9ccdde2] 合并login分支,并解决代码冲突 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git log --oneline --all --graph * 9ccdde2 (HEAD -> master) 合并login分支,并解决代码冲突 # 解决冲突后提交产生一次新的版本 |\ | * 9c968e0 (login) 集成QQ登录 * | fecdb41 添加头像上传功能 |/ * 7c0b2a3 用户名+密码登录功能完成
经过上一次合并后,master与login属于同轴了,当切换为login分支,可以使用快进合并来合并master分支;
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) # 切换为login分支 $ git checkout login Switched to branch 'login' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login) # login分支的代码 $ cat project.txt 用户名+密码登录 集成QQ登录 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login) $ git log --oneline --all --graph * 9ccdde2 (master) 合并login分支,并解决代码冲突 |\ | * 9c968e0 (HEAD -> login) 集成QQ登录 * | fecdb41 添加头像上传功能 |/ * 7c0b2a3 用户名+密码登录功能完成 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login) # 合并master分支 $ git merge master Updating 9c968e0..9ccdde2 Fast-forward project.txt | 1 + 1 file changed, 1 insertion(+) Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login) # 查看login分支的代码,发现master的代码被合并过来了 $ cat project.txt 用户名+密码登录 添加头像上传功能 集成QQ登录 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (login) $ git log --oneline --all --graph * 9ccdde2 (HEAD -> login, master) 合并login分支,并解决代码冲突 |\ | * 9c968e0 集成QQ登录 * | fecdb41 添加头像上传功能 |/ * 7c0b2a3 用户名+密码登录功能完成
Git存在代码冲突的情况分为协同开发时的代码冲突与分支合并时的代码冲突;其中分支合并时的代码冲突又分为快进合并代码冲突与典型合并代码冲突。
另外还需要注意的是,Git与SVN的代码冲突逻辑不一致。
Tips:我们本章主要讨论分支合并时的代码冲突。
Tips:同轴开发的快进合并是不会产生冲突的。
【SVN代码冲突模拟】
SVN的情况:两个用户编辑的代码是同一行则出现冲突
xiaohui | xiaolan |
---|---|
创建abc.txt | |
内容为: | |
111 | |
222 | |
执行add | |
执行commit | |
执行update | |
修改内容为: | |
111aaa | |
222 | |
执行commit | |
修改内容为: | |
111bbb | |
222 | |
执行update(冲突) |
如果"xiaolan"用户最后更改的文件内容为:
111
222bbb
然后再执行update,则不会出现代码冲突,因为SVN判断代码冲突的代码单元为行,即:两个用户编辑的不是同一行就不会出现代码冲突。
快进合并属于前面的版本合并后面的版本,需要注意的是==前面的版本并非是"旧版本",后面的版本并非是"新版本"==,这主要取决于是否是同轴开发。对于同轴开发,后面的版本自然是新版本,其内容肯定包含前面版本的内容。但对于非同轴开发,后面的版本内容大概率是不包含前面的版本内容的;
在同轴开发情况下,快进合并不会产生代码冲突,但如果在非同轴开发情况下,快进合并就会产生代码冲突了。我们观察下列操作:
master分支 | test分支 |
---|---|
创建abc.txt | |
内容为: | |
111 | |
222 | |
执行add | |
执行commit | |
创建分支 – 此时test分支的abc.txt的内容也是111、222 | |
修改内容为: | |
111aaa | |
222 | |
执行commit | |
切换到test分支 | |
修改内容为: | |
111 | |
222bbb | |
执行commit – 此时test分支和master分支已经不同轴了 | |
切换回master分支,合并test分支,属于快进合并,但会出现冲突 |
Tips:注意,上述操作在SVN中则不会认为是冲突,因为SVN判断是否冲突的标准是操作同一个文件的同一行记录;
【使用Git演示代码冲突】
①初始化项目
rm -rf .git ./* git init Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ vi aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ cat aaa.txt 111 222 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git add ./ Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git commit -m "111 222" ./
②创建test分支
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git branch test
③继续使用master分支开发
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git log --oneline --all --graph * d40d605 (HEAD -> master, test) 111 222 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ vi aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ cat aaa.txt 111aaa 222 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git commit -m "aaa" ./ Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git log --oneline --all --graph * 09fe9cb (HEAD -> master) aaa * d40d605 (test) 111 222
④切换到test分支开发
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git checkout test Switched to branch 'test' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) $ vi aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) # 注意,和master分支修改的文件内容不是同一行 $ cat aaa.txt 111 222bbb Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) $ git commit -m "bbb" ./ [test dfe1b42] bbb 1 file changed, 1 insertion(+), 1 deletion(-) Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) # 查看日志,test与master分支已经不同轴 $ git log --oneline --all --graph * dfe1b42 (HEAD -> test) bbb | * 09fe9cb (master) aaa |/ * d40d605 111 222
⑤切换回master分支,合并test分支,出现冲突:
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) # 切换回master分支 $ git checkout master Switched to branch 'master' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) # 合并test分支,属于快进合并,但是会产生冲突 $ git merge test Auto-merging aaa.txt CONFLICT (content): Merge conflict in aaa.txt Automatic merge failed; fix conflicts and then commit the result. Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master|MERGING) $ cat aaa.txt <<<<<<< HEAD 111aaa 222 ======= 111 222bbb >>>>>>> test Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master|MERGING) $ vi aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master|MERGING) $ cat aaa.txt 111aaa 222bbb Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master|MERGING) # 解决冲突 $ git commit -a -m "master合并test分支" [master adaec78] master合并test分支 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git log --oneline --all --graph * adaec78 (HEAD -> master) master合并test分支 |\ | * 7b14536 (test) bbb * | eeca4c9 aaa |/ * 5f41035 111 222
需要注意的是:此时切换回test分支,合并master分支内容不会出现冲突(属于快进合并,但是内容不一致,但不会出现冲突):因为master分支的内容是刚刚解决了冲突之后用户确定了的内容。
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git checkout test Switched to branch 'test' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git log --oneline --all --graph * adaec78 (master) master合并test分支 |\ | * 7b14536 (HEAD -> test) bbb * | eeca4c9 aaa |/ * 5f41035 111 222 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) $ cat aaa.txt 111 222bbb Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) $ git merge master Updating 7b14536..adaec78 Fast-forward aaa.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) $ cat aaa.txt 111aaa 222bbb Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git log --oneline --all --graph * adaec78 (HEAD -> test, master) master合并test分支 |\ | * 7b14536 () bbb * | eeca4c9 aaa |/ * 5f41035 111 222
典型合并时的代码冲突就是我们之前遇到的那种情况,典型合并属于不同轴的开发,并且后面版本需要合并前面版本的情况,由于不同轴,因此后面版本的内容不一定包含前面版本的内容,由于Git代码冲突的特点,因此典型合并必定会出现代码冲突,因为后面版本的内容不可能和前面版本内容一致。
我们观察下列操作:
master分支 | test分支 |
---|---|
创建abc.txt | |
内容为: | |
111 | |
222 | |
执行add | |
执行commit | |
创建分支 – 此时test分支的abc.txt的内容也是111、222 | |
修改内容为: | |
111aaa | |
222 | |
执行commit | |
切换到test分支 | |
修改内容为: | |
111 | |
222bbb | |
执行commit – 此时test分支和master分支已经不同轴了 | |
合并master分支的代码,属于典型合并,出现代码冲突。 |
【使用Git演示代码冲突】
①初始化项目:
rm -rf .git ./* git init Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ vi aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ cat aaa.txt 111 222 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git add ./ Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git commit -m "111 222" ./
②创建test分支
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git branch test
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master)
$ git log --oneline --all --graph
* 45fa06b (HEAD -> master, test) 111 222
③继续使用master分支开发
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git checkout master Already on 'master' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ vi aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ cat aaa.txt 111aaa 222 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git commit -m "aaa" ./ Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git log --oneline --all --graph * c86283b (HEAD -> master) aaa * 45fa06b (test) 111 222
④切换到test分支,继续开发
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (master) $ git checkout test Switched to branch 'test' Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) $ vi aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) $ cat aaa.txt 111 222bbb Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) $ git commit -m "bbb" ./ [test e61df5a] bbb 1 file changed, 1 insertion(+), 1 deletion(-) Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) $ git log --oneline --all --graph * e61df5a (HEAD -> test) bbb | * c86283b (master) aaa |/ * 45fa06b 111 222
⑤使用test分支合并master分支(属于典型合并)
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) $ git merge master Auto-merging aaa.txt CONFLICT (content): Merge conflict in aaa.txt Automatic merge failed; fix conflicts and then commit the result. Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test|MERGING) $ cat aaa.txt <<<<<<< HEAD 111 222bbb ======= 111aaa 222 >>>>>>> master Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test|MERGING) $ vi aaa.txt Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test|MERGING) $ cat aaa.txt 111aaa 222bbb Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test|MERGING) $ git commit -a -m "合并master分支,并解决冲突" [test 448d619] 合并master分支,并解决冲突 Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) $ git log --oneline --all --graph * 448d619 (HEAD -> test) 合并master分支,并解决冲突 |\ | * c86283b (master) aaa * | e61df5a bbb |/ * 45fa06b 111 222
同样的,如果此时切换回master分支,合并test分支虽然属于快进合并并且不同轴,但合并依旧不会出现冲突,因为test分支的内容是解决冲突并且经过用户确认之后的内容。
Adminstrator@LAPTOP-OC90J78H MINGW64 ~/Desktop/workspace (test) $ git log --oneline --all --graph * 448d619 (HEAD -> test) 合并master分支,并解决冲突 ### 给大家的福利 **零基础入门** 对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。 ![](https://img-blog.csdnimg.cn/img_convert/95608e9062782d28f4f04f821405d99a.png) 同时每个成长路线对应的板块都有配套的视频提供: ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a91b9e8100834e9291cfcf1695d8cd42.png#pic_center) 因篇幅有限,仅展示部分资料 **网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。** **[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/topics/618540462)** **一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。