做外贸推广哪个网站好,seo公司哪家好咨询,河南省建设信息网查询,郑州全面恢复正常#x1f601; 作者简介#xff1a;一名大四的学生#xff0c;致力学习前端开发技术 ⭐️个人主页#xff1a;夜宵饽饽的主页 ❔ 系列专栏#xff1a;Git等软件工具技术的使用 #x1f450;学习格言#xff1a;成功不是终点#xff0c;失败也并非末日#xff0c;最重要… 作者简介一名大四的学生致力学习前端开发技术 ⭐️个人主页夜宵饽饽的主页 ❔ 系列专栏Git等软件工具技术的使用 学习格言成功不是终点失败也并非末日最重要的是继续前进的勇气 前言 这里是关于git的分支管理和多人协作时的知识让大家真正学会运用git的分支管理而不是停留在命令上面,希望可以帮助到大家欢迎大家的补充和纠正 文章目录 第三章 分支管理3.1 创建与合并冲突3.2 解决冲突3.3 分支管理策略3.4 Bug分支3.5 多人协作3.5.1 推送分支3.5.2 抓取分支 第三章 分支管理
3.1 创建与合并冲突
在版本回退里你已经知道每次提交Git都把它们串成一条时间线这条时间线就是一个分支。截止到目前只有一条时间线在Git里这个分支叫主分支即master分支。HEAD严格来说不是指向提交而是指向mastermaster才是指向提交的所以HEAD指向的就是当前分支。
一开始的时候master分支是一条线Git用master指向最新的提交再用HEAD指向master就能确定当前分支以及当前分支的提交点 HEAD││▼master││▼
┌───┐ ┌───┐ ┌───┐
│ │───▶│ │───▶│ │
└───┘ └───┘ └───┘每次提交master分支都会向前移动一步这样随着你不断提交master分支的线也越来越长。
当我们创建新的分支例如dev时Git新建了一个指针叫dev指向master相同的提交再把HEAD指向dev就表示当前分支在dev上 master││▼
┌───┐ ┌───┐ ┌───┐
│ │───▶│ │───▶│ │
└───┘ └───┘ └───┘▲││dev▲││HEAD你看Git创建一个分支很快因为除了增加一个dev指针改改HEAD的指向工作区的文件都没有任何变化
不过从现在开始对工作区的修改和提交就是针对dev分支了比如新提交一次后dev指针往前移动一步而master指针不变 master││▼
┌───┐ ┌───┐ ┌───┐ ┌───┐
│ │───▶│ │───▶│ │───▶│ │
└───┘ └───┘ └───┘ └───┘▲││dev▲││HEAD假如我们在dev上的工作完成了就可以把dev合并到master上。Git怎么合并呢最简单的方法就是直接把master指向dev的当前提交就完成了合并 HEAD││▼master││▼
┌───┐ ┌───┐ ┌───┐ ┌───┐
│ │───▶│ │───▶│ │───▶│ │
└───┘ └───┘ └───┘ └───┘▲││dev所以Git合并分支也很快就改改指针工作区内容也不变
合并完分支后甚至可以删除dev分支。删除dev分支就是把dev指针给删掉删掉后我们就剩下了一条master分支 HEAD││▼master││▼
┌───┐ ┌───┐ ┌───┐ ┌───┐
│ │───▶│ │───▶│ │───▶│ │
└───┘ └───┘ └───┘ └───┘其他的命令可以在命令小结查找到我这里说一下有点难理解的合并分支的命令
$ git merge dev
Updating e5dfae5..2d46c90
Fast-forwardreadme.txt | 3 -1 file changed, 2 insertions(), 1 deletion(-)
git merge命令用于合并指定分支到当前分支。合并后再查看readme.txt的内容就可以看到和dev分支的最新提交是完全一样的。
注意到上面的Fast-forward信息Git告诉我们这次合并是“快进模式”也就是直接把master指向dev的当前提交所以合并速度非常快。
当然也不是每次合并都能Fast-forward我们后面会讲其他方式的合并
⭐️ 命令小结
查看分支git branch创建分支git branch name切换分支git checkout name或者 git switch name创建并切换分支git checkout -b name 或者 git switch -c name合并某个分支git merge name删除分支git branch -d name
3.2 解决冲突
当我们创建一个feature1的分支并修改了工作区文件的内容然后add和commit到版本库
当我们切换为master分支的时候也修改了工作区文件的内容还add和commit到版本库
于是就出现这种情况 HEAD││▼master││▼┌───┐┌─▶│ │
┌───┐ ┌───┐ ┌───┐ │ └───┘
│ │───▶│ │───▶│ │──┤
└───┘ └───┘ └───┘ │ ┌───┐└─▶│ │└───┘▲││feature1这种我们使用分支合并的时候无法快速合并因为有分支冲突的存在我们试看看
$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
我们可以看看readme文件是什么情况
Git is a distributed version control system.
Git is free software distributed under the GPL.HEAD
Creating a new branch is quick simple.Creating a new branch is quick AND simple.feature1这种时候我们需要手动修改文件然后再提交
Git is distributed version control system
Git is free software distributed under the GPL
Creating a new branch is quick AND simple再提交
$ git add readme.txt
$ git commit -m conflict fixed现在的分支图变成了 HEAD││▼master││▼┌───┐ ┌───┐┌─▶│ │───▶│ │
┌───┐ ┌───┐ ┌───┐ │ └───┘ └───┘
│ │───▶│ │───▶│ │──┤ ▲
└───┘ └───┘ └───┘ │ ┌───┐ │└─▶│ │──────┘└───┘▲││feature1我们可以使用git log来查看分支的合并情况
$ git log --graph --prettyoneline --abbrev-commit
* 55a2d4f (HEAD - master) conflict fixed
|\
| * 67d9043 AND simple
* | 5baf2da simple
|/
* 2d46c90 brancj test
* e5dfae5 remove test
* d9d1dc0 add test.txt
* bbacedf append GPL
* c440278 add distributed
* 6fe56b1 wrote a readme file最后删除feature1分支
$ git branch -d feature1
Deleted branch feature1 (was 67d9043).3.3 分支管理策略
我们通常在合并分支时是有两种模式的 Fast forward 模式快速合并 当你在合并分支时Git 会尝试使用 Fast forward 模式如果可能的话。如果两个分支的提交历史是线性的也就是说被合并的分支的所有提交都是基于当前分支的最新提交那么 Git 可以简单地将指针HEAD向前移动指向被合并分支的最新提交从而完成合并。这种模式下合并操作不会创建新的合并提交因为历史是线性的只需移动指针即可。 bashCopy code# 在当前分支上合并名为 feature 的分支使用 Fast forward 模式
git merge feature普通合并non-fast-forward模式 如果两个分支的提交历史不是线性的即存在分叉Git 将执行普通合并。这种情况下Git 会创建一个新的合并提交将两个分支的修改整合在一起。普通合并会保留每个分支的提交历史即使它们是并行的。 bashCopy code# 在当前分支上合并名为 feature 的分支强制执行普通合并
git merge --no-ff feature这两种模式我们在使用时如何选择呢我们可以来看看这两种模式下产生的提交历史 Fast forward 模式快速合并 没有删除分支 $ git log --graph --prettyoneline --abbrev-commit
* 62e7593 (HEAD - master, dev) add dev
* 55a2d4f conflict fixed
|\
| * 67d9043 AND simple
* | 5baf2da simple
|/
* 2d46c90 brancj test删除分支了 $ git log --graph --prettyoneline --abbrev-commit
* 62e7593 (HEAD - master) add dev
* 55a2d4f conflict fixed
|\
| * 67d9043 AND simple
* | 5baf2da simple
|/
* 2d46c90 brancj test图解 普通模式 没有删除分支 $ git log --graph --prettyoneline --abbrev-commit
* 16c6f76 (HEAD - master) merge with no-ff
|\
| * d70cf45 (dev) add dev history
|/
* 62e7593 add dev
* 55a2d4f conflict fixed
|\
| * 67d9043 AND simple
* | 5baf2da simple
|/
* 2d46c90 brancj test删除分支了 $ git log --graph --prettyoneline --abbrev-commit
* 16c6f76 (HEAD - master) merge with no-ff
|\
| * d70cf45 add dev history
|/
* 62e7593 add dev
* 55a2d4f conflict fixed
|\
| * 67d9043 AND simple
* | 5baf2da simple
|/
* 2d46c90 brancj test图解
⭐️ 总结
在实际开发中我们应该按照几个基本原则进行分支管理
首先master分支应该是非常稳定的也就是仅用来发布新版本平时不能在上面干活
那在哪干活呢干活都在dev分支上也就是说dev分支是不稳定的到某个时候比如1.0版本发布时再把dev分支合并到master上在master分支发布1.0版本
你和你的小伙伴们每个人都在dev分支上干活每个人都有自己的分支时不时地往dev分支上合并就可以了。
所以团队合作的分支看起来就像这样 合并分支时加上--no-ff参数就可以用普通模式合并合并后的历史有分支能看出来曾经做过合并而fast forward合并就看不出来曾经做过合并
3.4 Bug分支
软件开发中bug就像家常便饭一样。有了bug就需要修复在Git中由于分支是如此的强大所以每个bug都可以通过一个新的临时分支来修复修复后合并分支然后将临时分支删除。
当你接到一个修复一个代号101的bug的任务时很自然地你想创建一个分支issue-101来修复它但是等等当前正在dev上进行的工作还没有提交
$ git status
On branch dev
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.txtno changes added to commit (use git add and/or git commit -a) 我的误解
我只是想切换到master分支然后在master分支上面创建bug修改分支issue-101我为什么不能直接切换呢 答在切换分支时如果工作区有修改的话与切换分支会有冲突的切换分支会不成功所以说我们在切换分支时应该保证切换分支之前的分支是干净的什么叫分支干净呢一个分支是基于工作目录working directory的状态来维护的。当我们说切换分支之前是干净的状态时意味着工作目录中没有未提交的更改。这包括对文件的修改、新文件的添加和已跟踪文件的删除。
所以我们要先搞清楚怎么把工作区目录整理干净
现在的问题是提交是可以解决问题但是并不是你不想提交而是工作只进行到一半还没法提交预计完成还需1天时间。但是必须在两个小时内修复该bug怎么办
幸好Git还提供了一个stash功能可以把当前工作现场“储藏”起来等以后恢复现场后继续工作
$ git stash
Saved working directory and index state WIP on dev: f52c633 add merge现在用git status查看工作区就是干净的除非有没有被Git管理的文件因此可以放心地创建分支来修复bug。
接下来就是正常的切换master分支然后创建issue-101分支在issue-101分支修复bug然后合并分支到master 开始修复bug:
首先确定要在哪个分支上修复bug假定需要在master分支上修复就从master创建临时分支
$ git checkout master
Switched to branch master
Your branch is ahead of origin/master by 6 commits.(use git push to publish your local commits)$ git checkout -b issue-101
Switched to a new branch issue-101现在修复bug需要把“Git is free software …”改为“Git is a free software …”然后提交
$ git add readme.txt
$ git commit -m fix bug 101
[issue-101 4c805e2] fix bug 1011 file changed, 1 insertion(), 1 deletion(-)修复完成后切换到master分支并完成合并最后删除issue-101分支
$ git switch master
Switched to branch master
Your branch is ahead of origin/master by 6 commits.(use git push to publish your local commits)$ git merge --no-ff -m merged bug fix 101 issue-101
Merge made by the recursive strategy.readme.txt | 2 -1 file changed, 1 insertion(), 1 deletion(-)结束修复bug。
太棒了原计划两个小时的bug修复只花了5分钟现在是时候接着回到dev分支干活了
$ git switch dev
Switched to branch dev$ git status
On branch dev
nothing to commit, working tree clean工作区是干净的刚才的工作现场存到哪去了用git stash list命令看看
$ git stash list
stash{0}: WIP on dev: f52c633 add merge工作现场还在Git把stash内容存在某个地方了但是需要恢复一下有两个办法 一是用git stash apply恢复但是恢复后stash内容并不删除你需要用git stash drop来删除 另一种方式是用git stash pop恢复的同时把stash内容也删了
$ git stash pop
On branch dev
Changes to be committed:(use git reset HEAD file... to unstage)new file: hello.pyChanges 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: readme.txtDropped refs/stash{0} (5d677e2ee266f39ea296182fb2354265b91b3b2a)再用git stash list查看就看不到任何stash内容了
$ git stash list你可以多次stash恢复的时候先用git stash list查看然后恢复指定的stash用命令
$ git stash apply stash{0}在master分支上修复了bug后我们要想一想dev分支是早期从master分支分出来的所以这个bug其实在当前dev分支上也存在。
那怎么在dev分支上修复同样的bug重复操作一次提交不就行了
不我们可以有更简单的方法
同样的bug要在dev上修复我们只需要把4c805e2 fix bug 101这个提交所做的修改“复制”到dev分支。注意我们只想复制4c805e2 fix bug 101这个提交所做的修改并不是把整个master分支merge过来。 我的经验 就是一个问题还是合并冲突的问题如果我们把工作区给恢复之后再去使用这个命令去合并分支会有错误
$ git cherry-pick 3d22a83
error: Your local changes to the following files would be overwritten by merge:readme.txt
Please commit your changes or stash them before you merge.
Aborting
fatal: cherry-pick failed
依旧是工作区分支不干净导致无法合并分支所以我们可以再合并分支之前使用git status命令查看工作区是否干净
所以我们要先把工作区使用git stash存起来然后在合并bug分支在把工作区的内容给修复出来
对于合并冲突的情况有以下几种
同时修改同一行或同一片区域 如果两个不同的分支都修改了同一行代码或者在相邻的行上做了修改Git 无法判断应该保留哪个修改。这就导致了冲突。删除与修改冲突 一个分支删除了某个文件而另一个分支对该文件进行了修改。在合并时Git 不知道是应该保留修改还是应该保留删除。合并基的变更 如果两个分支的合并基共同的祖先 commit上有修改而这些修改分别被两个分支采用那么在合并时就会发生冲突 为了方便操作Git专门提供了一个cherry-pick命令让我们能复制一个特定的提交到当前分支
$ git branch
* devmaster
$ git cherry-pick 4c805e2
[master 1d4b803] fix bug 1011 file changed, 1 insertion(), 1 deletion(-)Git自动给dev分支做了一次提交注意这次提交的commit是1d4b803它并不同于master的4c805e2因为这两个commit只是改动相同但确实是两个不同的commit。用git cherry-pick我们就不需要在dev分支上手动再把修bug的过程重复一遍。
⭐️ 小结
修复bug时我们会通过创建新的bug分支进行修复然后合并最后删除
当手头工作没有完成时先把工作现场git stash一下然后去修复bug修复后再git stash pop回到工作现场
在master分支上修复的bug想要合并到当前dev分支可以用git cherry-pick commit命令把bug提交的修改“复制”到当前分支避免重复劳动。
3.5 多人协作
我们在对远程仓库克隆时实际上Git自动把本地的master分支和远程的master分支对应起来了远程仓库的默认名称是origin
我们可以使用git remote来查看远程看的信息
$ git remote
origin或者用git remote -v显式更详细的信息
$ git remote -v
origin gitgithub.com:michaelliao/learngit.git (fetch)
origin gitgithub.com:michaelliao/learngit.git (push)上面显示了可以抓取和推送的origin的地址。如果没有推送权限就看不到push的地址 3.5.1 推送分支
推送分支就是把该分支上的所有本地提交推送到远程库。推送时要指定本地分支这样Git就会把该分支推送到远程库对应的远程分支上
$ git push origin master如果要推送其他分支比如dev就改成
$ git push origin dev如果远程仓库不存在 dev 分支Git 会尝试创建该分支并将本地的 dev 分支推送到远程仓库。 小提醒在Git中分支完全可以在本地自己玩是否推送到远程仓库你可以有选择要看需求的
3.5.2 抓取分支
在多人协作时大家都会往master和dev分支上推送各自的修改
这种时候会有一种情况出现A和B用户都分别从远程仓库拉取或者克隆了代码这时候各自完成自己的代码工作A用户先完成了所以就把代码推送到远程仓库去了这种时候B用户再继续推送到远程仓库会失败的因为远程仓库的最新提交和B用户试图推送的提交有冲突
可以有以下解决方法
首先可以试图用git push origin branch-name推送自己的修改如果推送失败则因为远程分支比你的本地更新需要先用git pull试图合并如果合并有冲突则解决冲突解决的方法和分支管理中的解决冲突完全一样,并在本地提交没有冲突或者解决掉冲突后再用git push origin branch-name推送就能成功
❓ 产生的问题
有时候git pull时会出现这种情况
$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.git pull remote branchIf you wish to set tracking information for this branch you can do so with:git branch --set-upstream-toorigin/branch devgit pull也失败了原因是没有指定本地dev分支与远程origin/dev分支的链接根据提示设置dev和origin/dev的链接
$ git branch --set-upstream-toorigin/dev dev
Branch dev set up to track remote branch dev from origin.