Git的分支
什么是分支(branch)?
有分支就有主干,分支就是主干分离出来的枝干(好像废话呀),我们在实际开发项目的时候,会有一个主干(其实也是个分支,跟其他分支没有区别),可能这是跟生产代码完全一致。但是有一天可能需要上一个新的需求,直接在主分支上修改提交代码,可能就有问题了,有哪些问题呢?比如:这些需求可能在开发过程中,还未完全测试。放到了主分支,被打包上线怎么办(现今devops可是常规操作。);再比如即便代码测试完成,但是并没有确定什么时候上线呀。诸如此类都是问题。
那么分支就解决了上面这些问题。比如主分支叫做main,开发过程中可以创建一个dev分支。该功能开发测试都在这个分支,测试通过没有问题,并且确定要上线该功能的时候就可以将dev分支合并到主分支main。
查看分支
使用git branch 查看分支,他也支持很多参数,下面使用下常用的参数
# git branch 查看分支
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git branch
* main
# [-v | --verbose] 该参数会将最后一次提交日志列出来
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git branch -v
* main 8961921 第一次提交itlab1024.txt(after reset)
# [-r | --remotes]列出远端分支信息,因为我还未提交到远端,所以是空的
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git branch -r
创建分支
创建分支使用git branch 分支名
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git branch dev
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git branch -v
dev 8961921 第一次提交itlab1024.txt(after reset)
* main 8961921 第一次提交itlab1024.txt(after reset)
我通过git branch dev创建了一个dev分支,因为我是在main分支下创建的dev分支,所以dev分支的代码跟main的一样。
切换分支
切换分支使用git checkout 分支名
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git checkout dev
Switched to branch 'dev'
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev)
可以看到开始我是在main分支下,然后使用checkout,切换到了dev分支下。
合并创建和切换
创建分支和合并分支可以一步操作,使用git checkout -b 分支名
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git branch -D dev
Deleted branch dev (was 8961921).
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git checkout -b dev
Switched to a new branch 'dev'
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev)
修改分支代码
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev)
$ vim itlab1024.txt
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev)
$ cat itlab1024.txt
dev001
然后提交分支代码
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev)
$ git add .
warning: in the working copy of 'itlab1024.txt', LF will be replaced by CRLF the next time Git touches it
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev)
$ git commit -m "第一次提交dev分支代码"
[dev 298d140] 第一次提交dev分支代码
1 file changed, 1 insertion(+)
对比main和dev分支代码和日志
现在dev的分支
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev)
$ cat itlab1024.txt
dev001
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev)
$ git log
commit 298d1408123e278e59b0022f3690a5f3241db8ee (HEAD -> dev)
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 14:48:51 2022 +0800
第一次提交dev分支代码
commit 89619218aa9638434fd92338fe74cfb1b27d9373 (main)
Author: Eleven <itlab1024@163com>
Date: Sat Nov 5 20:48:13 2022 +0800
第一次提交itlab1024.txt(after reset)
再看下main分支
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev)
$ git checkout main
Switched to branch 'main'
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ cat itlab1024.txt
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git log
commit 89619218aa9638434fd92338fe74cfb1b27d9373 (HEAD -> main)
Author: Eleven <itlab1024@163com>
Date: Sat Nov 5 20:48:13 2022 +0800
第一次提交itlab1024.txt(after reset)
对比结果:
- itlab1024.txt在main分支中是空的,在dev下的内容是:dev001
- dev分支提交日志中比main多一次:commit id=298d1408123e278e59b0022f3690a5f3241db8ee
Merge(合并分支)
当dev分支开发完毕,测试通过了,那么需要合并到main分支,要发布生产环境了呀。
合并分支使用git merge。
使用说明:当前分支 执行git merge其他分支,结果就是将其他分支的内容合并到了当前分支。
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git merge dev
Updating 8961921..298d140
Fast-forward
itlab1024.txt | 1 +
1 file changed, 1 insertion(+)
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git log
commit 298d1408123e278e59b0022f3690a5f3241db8ee (HEAD -> main, dev)
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 14:48:51 2022 +0800
第一次提交dev分支代码
commit 89619218aa9638434fd92338fe74cfb1b27d9373
Author: Eleven <itlab1024@163com>
Date: Sat Nov 5 20:48:13 2022 +0800
第一次提交itlab1024.txt(after reset)
可以看到我在main分支下执行git merge dev,结果就是main分支下有了dev分支下的提交。
这里为了演示清晰,我重新创建一个dev02的分支
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git checkout -b dev02
Switched to a new branch 'dev02'
依然是修改下itlab1024.txt的代码,并提交到本地库
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev02)
$ vim itlab1024.txt
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev02)
$ cat itlab1024.txt
dev001
dev02-update
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev02)
$ git add .
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev02)
$ git commit -m "dev02分支的第一次提交"
[dev02 f33a145] dev02分支的第一次提交
1 file changed, 1 insertion(+)
冲突问题
上面演示的时候,使用merge,很顺利,没有发生冲突,但是实际开发中,可能会产生冲突的问题。
那么冲突产生的场景是什么呢?两个分支在同一个文件同一个位置进行了不同的修改就会产生冲突。此时git就不知道该哪个分支的代码了,必须要工作人员自己去修改。
首先看下main的itlab1024.txt的内容
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ cat itlab1024.txt
dev001
dev02-update
再看下dev02的itlab1024.txt的内容
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git checkout dev02
Switched to branch 'dev02'
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev02)
$ cat itlab1024.txt
dev001
dev02-update
连个分支的itlab1024.txt的内容是一样的。
现在要做一个操作。我在main分支中修改itlab1024.txt的第一行代码为a,在dev02分支中的itlab1024.txt的第一行代码修改为b。
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev02)
$ vim itlab1024.txt
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev02)
$ cat itlab1024.txt
b
dev02-update
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev02)
$ git commit -am "dev02分支修改第一行代码"
[dev02 cc50229] dev02分支修改第一行代码
1 file changed, 1 insertion(+), 1 deletion(-)
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev02)
$ git checkout main
Switched to branch 'main'
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ vim itlab1024.txt
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ cat itlab1024.txt
a
dev02-update
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git commit -am "修改main分支中的itlab1024.txt的第一行代码为a"
[main 42fabbe] 修改main分支中的itlab1024.txt的第一行代码为a
1 file changed, 1 insertion(+), 1 deletion(-)
修改完毕后,我们来看下main分支和dev02分支的日志
main:
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git log
commit 42fabbe3631c3ad0ff3c3ebcbe53b3979a7c3077 (HEAD -> main)
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 15:16:28 2022 +0800
修改main分支中的itlab1024.txt的第一行代码为a
commit f33a14526d17660053d5290b112060ebe7c8de4d
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 15:00:49 2022 +0800
dev02分支的第一次提交
commit 298d1408123e278e59b0022f3690a5f3241db8ee (dev)
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 14:48:51 2022 +0800
第一次提交dev分支代码
commit 89619218aa9638434fd92338fe74cfb1b27d9373
Author: Eleven <itlab1024@163com>
Date: Sat Nov 5 20:48:13 2022 +0800
第一次提交itlab1024.txt(after reset)
dev02:
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git checkout dev02
Switched to branch 'dev02'
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev02)
$ git log
commit cc50229a0c6479eeebbf355febbb4119d0f8b4a0 (HEAD -> dev02)
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 15:15:04 2022 +0800
dev02分支修改第一行代码
commit f33a14526d17660053d5290b112060ebe7c8de4d
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 15:00:49 2022 +0800
dev02分支的第一次提交
commit 298d1408123e278e59b0022f3690a5f3241db8ee (dev)
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 14:48:51 2022 +0800
第一次提交dev分支代码
commit 89619218aa9638434fd92338fe74cfb1b27d9373
Author: Eleven <itlab1024@163com>
Date: Sat Nov 5 20:48:13 2022 +0800
第一次提交itlab1024.txt(after reset)
可以看到两个分支的最后一次提交是不同的main的commit id = 42fabbe3631c3ad0ff3c3ebcbe53b3979a7c3077, dev02的commit id = cc50229a0c6479eeebbf355febbb4119d0f8b4a0。
接下来我切换到main分支,使用merge进行合并。
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (dev02)
$ git checkout main
Switched to branch 'main'
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git merge dev02
Auto-merging itlab1024.txt
CONFLICT (content): Merge conflict in itlab1024.txt
Automatic merge failed; fix conflicts and then commit the result.
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main|MERGING)
$ git status
On branch main
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: itlab1024.txt
no changes added to commit (use "git add" and/or "git commit -a")
可以看到提示了这样一句话,CONFLICT (content): Merge conflict in itlab1024.txt。这就是说代码冲突了,需要认为干预,使用git rebase也一样会冲突,这里就不演示了。
解决冲突
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main|MERGING)
$ git status
On branch main
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: itlab1024.txt
no changes added to commit (use "git add" and/or "git commit -a")
使用vim打开文件
可以看到main里的a和dev02分支提交的b都在这里。那么这里就需要手动处理了。比如我就想保留main分支的a,不要dev分支的b。可以修改为如下内容:
这里要说明下,要保留什么内容你自己觉得,比如你既不想要a也不想要保留b了,就填写个xxx可以不?完全可以。
还要注意解决冲突,要把里面的<<<<和===还有>>>行去掉。
修改后保存退出,再次查看状态
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main|MERGING)
$ git status
On branch main
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: itlab1024.txt
no changes added to commit (use "git add" and/or "git commit -a")
这时候需要使用git add标记冲突解决完毕。
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main|MERGING)
$ git add .
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main|MERGING)
然后使用git commit -m "消息",主要后面不用附件文件。.
当然也可以使用git merge --continue,此时会弹出来让你输入提交信息。其实跟上面是一样的。
保存文件后,控制台会输出如下信息:
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main|MERGING)
$ git merge --continue
[main 1fefe4a] Merge branch 'dev02'
再次查看日志
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git log
commit 1fefe4aa70c5e29770f0302a667c86e3577f1a03 (HEAD -> main)
Merge: 42fabbe cc50229
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 16:25:07 2022 +0800
Merge branch 'dev02'
commit 42fabbe3631c3ad0ff3c3ebcbe53b3979a7c3077
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 15:16:28 2022 +0800
修改main分支中的itlab1024.txt的第一行代码为a
commit cc50229a0c6479eeebbf355febbb4119d0f8b4a0 (dev02)
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 15:15:04 2022 +0800
dev02分支修改第一行代码
commit f33a14526d17660053d5290b112060ebe7c8de4d
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 15:00:49 2022 +0800
dev02分支的第一次提交
commit 298d1408123e278e59b0022f3690a5f3241db8ee (dev)
Author: Eleven <itlab1024@163com>
Date: Sun Nov 6 14:48:51 2022 +0800
第一次提交dev分支代码
commit 89619218aa9638434fd92338fe74cfb1b27d9373
Author: Eleven <itlab1024@163com>
Date: Sat Nov 5 20:48:13 2022 +0800
第一次提交itlab1024.txt(after reset)
可以看到commit id = 1fefe4aa70c5e29770f0302a667c86e3577f1a03就是我们合并后的commit ID。
删除分支
删除分支使用git branch [-d | -D] 分支名,大写-D是-d --force的缩写,也就是强制删除。
比如我删除dev和dev02分支
#删除dev分支
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git branch -d dev
Deleted branch dev (was 298d140).
#删除dev02分支
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git branch -d dev02
Deleted branch dev02 (was cc50229).
#查看分支列表
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git branch
* main
远端分支
之前所有操作都是在本地分支上的操作,我们可以在本地仓库上对远程分支进行操作。
还记得下main这张图不,跟Remote的操作还未讲解。
现在本地有main分支(其他分支,刚才我执行删除分支的时候都被删除掉了。)
拉取远端库到本地库
git 服务器有云托管的比如github、gitee,也可以使用开源gitlab自己搭建。我这里使用gitee来演示。
此时可以可以使用git clone将远端仓库克隆下来(后面会讲如何将本地仓库推送到远端)
克隆仓库有多种方式,我这里使用http方式。
18516@ZhenchaoShi MINGW64 /d/workspace
$ git clone https://gitee.com/itlab1024/git-tutor.git
Cloning into 'git-tutor'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (4/4), done.
上面的命令就会将远端仓库克隆到本地。
git clone做了哪些操作?
本地初始化了一个仓库:
18516@ZhenchaoShi MINGW64 /d/workspace
$ cd git-tutor/
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git branch -v
* main f0bd152 Initial commit
增加了远端配置:
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git remote -v
origin https://gitee.com/itlab1024/git-tutor.git (fetch)
origin https://gitee.com/itlab1024/git-tutor.git (push)
查看远端分支
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git branch -r
origin/HEAD -> origin/main
origin/main
可以看到远端有origin/main分支,这里有人会说origin是什么?就是一个远端的别名,如果有多个远端可以取多个别名。
推送代码到远端
推送代码使用git push
我这里将日记更新到README.md中,然后本地提交。并推送到远端.
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git status
On branch main
Your branch is up to date with 'origin/main'.
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: README.md
no changes added to commit (use "git add" and/or "git commit -a")
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git add .
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git commit -m "git教程说明文档"
[main f27c97b] git教程说明文档
1 file changed, 1241 insertions(+), 25 deletions(-)
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor (main)
$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 20 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 9.82 KiB | 4.91 MiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.4]
To https://gitee.com/itlab1024/git-tutor.git
f0bd152..f27c97b main -> main
执行推送的时候,会提示让你输出用户名密码。
检查下远端是否已经提交成功,打开gitee,查看仓库文件。
可以看到已经提交到远程仓库。
推送本地库到远程库
上面讲述了从远程仓库初始化本地仓库的例子,那么如果是我现有的本地仓库,然后想要将代码推送到远端怎么办呢?
- 添加远端仓库源
- 上面使用的git clone自动给我们做了增加远端源,此时我们需要手动自己做。
- 推送代码
- 这里需要注意的是代码可能推送不上去,具体看下面的操作。
#初始化仓库
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor2
$ git init
Initialized empty Git repository in D:/workspace/git-tutor2/.git/
#执行git push,肯定会出错,因为现在还没有远程库源
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor2 (main)
$ git push
fatal: No configured push destination.
Either specify the URL from the command-line or configure a remote repository using
git remote add <name> <url>
and then push using the remote name
git push <name>
# 使用git remote add 添加远程库
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor2 (main)
$ git remote add origin https://gitee.com/itlab1024/git-tutor2.git
# 推送仓库到远端
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor2 (main)
$ git push origin
fatal: The current branch main has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin main
To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.
# 关联分支,失败了,因为远端仓库和本地仓库代码并不同。
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor2 (main)
$ git push --set-upstream origin main
error: src refspec main does not match any
error: failed to push some refs to 'https://gitee.com/itlab1024/git-tutor2.git'
# 需要拉去远端代码并与本地仓库做合并。
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor2 (main)
$ git pull --rebase origin main
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), 2.06 KiB | 24.00 KiB/s, done.
From https://gitee.com/itlab1024/git-tutor2
* branch main -> FETCH_HEAD
* [new branch] main -> origin/main
# 推送成功
18516@ZhenchaoShi MINGW64 /d/workspace/git-tutor2 (main)
$ git push --set-upstream origin main
Everything up-to-date
branch 'main' set up to track 'origin/main'.
总结
可以根据一下步骤,创建本地仓库并推送到远端
git init
git remote add origin https://gitee.com/itlab1024/git-tutor2.git
git pull --rebase origin main
git push --set-upstream origin main