《吐血整理》一篇文章教你学废Git版本管理(下)

简介: 一篇文章教你学废Git版本管理

5.分支合并「git merge」 VS 「git rebase」


Git中,可以使用「git merge」和「git rebase」两个命令来进行分支的合并。

git merge合并分支


合并的方式分为两种:快速合并普通合并,两者的区别在于: 「前者合并后看不出曾经做过合并,而后合并后的历史会有分支记录」 如图所示:



快速合并,默认,快速合并有一个前提:「当前分支的每个提交都在另一个分支中」, Git不创建任何新的commit,只是将当前分支指向合并进来的分支。下面演示下快速合并, 执行git reset 切换到第四次commit,然后执行git merge develop合并master分支。



普通合并,添加**–no-ff**参数表示禁用快速合并。



另外有时会有这样的场景:合并的分支中有很多commit记录是无需在分支中体现的,一个commit 就够了。可以借助**--squash**参数来压缩提交,示例如下:



附:git merge的常用参数:


git merge -ff           # 快速合并,默认参数
git merge -ff-only      # 只有快速合并的情况才合并
git merge --no-ff       # 不使用快速合并
git merge -n 分支名     # 合并分支,不会在合并后显示合并前后的不同状态
git merge -stat 分支名  # 合并分支,合并结束后显示合并前后的不同状态
git merge -e 分支名     # 合并分支,合并前调用编辑器,可自行编写commit


Tips: git-merge除了用来合并分支外,拉取远程仓库更新时也可用到(git fetch + git merge)


git reabse合并分支


rebase(衍合,变基),网上很多教程写得很高深莫测,其实并没有那么复杂, 只是这种合并会让树整洁,易于跟踪。以上面4中的结果为例,先把master分支 和develop分支重置到最新的commit。



先走一波前面的merge合并方式:



接着再试试rebase合并方式:



Git会把每个提交都取消掉,并把他们临时保存为补丁,比如经过一些冲突解决,生成新的commit, 旧的commit会被丢弃,还会被git的gc回收,这样的结果就是一条直线的树。


6.解决合并冲突


在分支的合并的时候,并不是每次都能直接合并的,有时会遇到合并冲突,特别是在多人协作的时候。 出现合并冲突后,需要解决完冲突,才能继续合并。


举个简单的例子,A和B在master分支上开辟出两个分支来完成相关的功能, A做完了,把自己的分支合并到master分支,此时master分支向前移动了几次commit, 接着B也完成了他的功能,想把自己分支合并到master分支,如果改动的文件和和A改动 的文件相同的话,此时就会合并失败,然后需要处理完冲突,才能够继续合并!


接下来我们来简单的模拟合并冲突,先来试试merge:


merge分支后处理冲突



如图,合并完A分支后合并B分支出现了冲突,接着键入:git status查看冲突的文件:



可以看到未合并的两个文件,1.txt和2.txt,打开其中一个文件:



<<< 和 >>>包裹着的就是冲突内容,保留自己想要的内容,处理完后删掉<<<和>>>,修改完后:



2.txt文件也如法炮制,接着add,然后commit即可,合并结束。



rebase分支后处理冲突



如图,A合并成功,在合并B的时候,出现了合并冲突,有三个可选的操作:


git rebase --continue # 处理完冲突后,继续处理下一个补丁
git rebase --abort # 放弃所有的冲突处理,恢复rebase前的情况
git rebase --skip # 跳过当前的补丁,处理下一个补丁,不建议使用,补丁部分的commit会丢失!


键入git status查看冲突文件:



接着处理1.txt文件中的冲突,解决完成后,先键入git add,接着键入git rebase --continue处理下一个冲突:



处理接下来的冲突,直到没有冲突为止:



可以看到使用rebase合并,最后的分支线是一条直线。另外,使用rebase合并中途出差错, 可以使用git rebase --abort恢复rebase前的状态。


7.删除分支


合并完的分支,基本没什么用了,可以使用下述命令删除:


git branch -d 分支名    # 删除分支,分支上有未提交更改是不能删除的
git branch -D 分支名    # 强行删除分支,尽管这个分支上有未提交的更改


8.恢复误删分支


两步:找出被删分支最新的commit的Hash值,然后恢复分支:


git log --branches="被删除的分支名"     # 找到被删分支最新的commit版本号
git branch 分支名 版本号(前七位即可)    # 恢复被删分支


9.切换分支时暂存未commit的更改「git stash」


有时我们可能在某个分支上正编写着代码,然后有一些突发的情况,需要 我们暂时切换到 其他分支上,比如要紧急修复bug,或者切换分支给同事 review代码,此时如果直接切换 分支是会提示切换失败的,因为这个分支 上做的更改还没有提交,你可以直接add后commit, 然后再切换,不过我们习惯写完某个功能再提交,我们想:


先暂存这个分支上的改动,切去其他分支上搞完事,然后回来继续 继续在之前的改动上写代码。


那么可以使用:


git stash   # 保存当前的改动


然后放心的切换分支,然后再切换回来,接着使用:


git stash apply     # 恢复保存改动


另外有一点一定要注意!!!可以stash多个改动!!如果你切换到另一个分支 又stash了,然后切换回来stash apply是恢复成另一个分支的stash!!! 如果你这样stash了多次的话,我建议你先键入:


git stash list      # 查看stash列表


找到自己想恢复的那个



比如这里恢复的应该是master上的stash,可以使用下述命令进行恢复:


git stash apply stash@{1}


10.分支重命名


git branch -m 老分支名 新分支名     # 分支重命名


11.把提交的commit从一个分支放到另一个分支「git cherry-pick」


有时我们可能需要把某个分支上的一次commit放到另一个分支上,此时可以使用git cherry-pick, 比如下面这样两个分支:


master分支:A -> B -> C feature分支:a -> b


现在想把feature分支上的b,放到master的后,可以这样操作:


  • Step 1:切换到feature分支上,git log拿到b commit的版本号(SHA1)。


  • Step 2:切换到master分支,键入:git cherry-pick 版本号。



0x5、Git远程仓库


1.远程仓库概述


在实际开发过程中,基本都是团队协作的形式进行,即多人一起负责同一个项目,那如何共享同一份代码并进行管理呢?可以用到「Git远程仓库」。可以自己搭建,或选择专业的代码托管平台,比如:Github,Git@OSC,GitCafe,GitLab,coding.net,gitc,BitBucket,Geakit,Douban CODE 等。当然,如果有条件的话,肯定是自己搭建的爽一些,可控,还可以做一些订制(集成编译,机器人提醒等),简单点的可以试试「Gogs」,可玩性更高的可以试试「GitLab」。


2.本地仓库与远程仓库建立关联「git remote」


在Github上新建了一个项目仓库,会生成对应的仓库链接,如:



键入下述命令进行关联:


git remote add origin 远程仓库地址


接着可键入下述命令查看关联情况:


git remote      # 列出已经存在的远程分支
git remote -v   # 查看远程仓库的地址



3.推送本地仓库到远程仓库「git push」


建立完关联后,我们可以使用git push命令把本地更改推送到远程仓库


git push -u origin master


-u参数:作为第一次提交使用,作用是把本地master分支和远程master分支关联起来(设置默认远程主机),后续提交不需要这个参数!



另外,如果想修改远程仓库地址,可通过下述命令:


# 直接修改远程仓库地址
git remote set-url origin 远程仓库地址
# 也可以先删除origin后再添加
git remote rm origin               # 删除仓库关联
git remote add origin 远程仓库地址   # 添加仓库关联


你还可以直接修改「.git文件夹中的config文件」,直接替换圈住位置内容即可:



还有一点:「origin」并不是固定的东西,只是后面「仓库地址的一个别名」!!可以写成其他的东西,然后你也可以设置多个仓库关联,用不同的别名标志,比如:


git remote add github https://github.com/coder-pig/SimpleTea.git
git remote add osc git@git.oschina.net:coder-pig/SimpleTea.git


4.克隆远程仓库「git clone」


把项目推送到远程仓库后,其他开发者就可以通过git clone命令把项目克隆到本地


git clone 仓库地址          # 克隆项目到当前文件夹下
git clone 仓库地址 目录名    # 克隆项目到特定目录下
# 注:git clone命令只会建立master分支,如果想克隆特定远程分支,可在克隆后:
git checkout -t origin/dev 
# 该命令等同于
git checkout -b dev origin/dev
# 除此之外,还可以:
git fetch origin 远程分支:本地分支 # 会在本地新建分支,但不会自动切换,还需checkout
git branch --set-upstream 本地分支 远程分支 # 建立本地分支与远程分支的链接


5.同步远程仓库更新「git fetch」VS 「git pull」


获取远程仓库更新的方法有两种:fetchpull,简要讲解下两者的区别:


git fetch


仅仅只是从远处服务器获取到最新版本到本地,假如你不去合并(merge),本地工作空间是不会发生变化的!比如:在Github上创建一个README.md文件,然后调 git fetch 去获取远程仓库的更新。



git pull


一步到位,pull = fetch + merge,比如:同样修改Github上的README.md 文件,然后git pull 同步远程仓库的更新:



区别显而易见,使用git fetch会更安全一些,毕竟merge的时候,查看更新的情况,再决定是否进行合并。


6.git push 时的unrelated history问题


在Github创建新项目后,在repo处创建了README.md或其他文件,然后关联本地仓库,push时会报错: Push rejected: Push to origin/master was rejected,然后提示你pull一下,当你pull时又会报错: 「refusing to merge unrelated histories」,原因是两个仓库不同导致的,可使用下述命令解决:


git pull origin master --allow-unrelated-histories


除此之外,你还可以粗暴一点,直接用本地仓库「强制覆盖远程仓库」,但是 慎用!!!如果出问题了,只能看下其他人的电脑中是否有原始的本地仓库进行还原!!!


git push -f origin  # 慎用!!!


7.SSH Key避免每次push重复输入账号密码


私有项目,使用Https协议pull或push,都需要验证账号和密码,有点繁琐,如果想避免这种重复输入的情况,可以考虑使用SSH协议。SSH,Secureshell(安全外壳协议),专为远程登陆会话与其他网络服务提供安全性的协议,而SSH传输的数据是可以经过压缩的,可以加快传输的速度,出于安全性与速度,优先考虑使用SSH协议,而SSH的安全验证规则又分为基于密码和基于密钥两种!这里使用的是第二种,即在本地创建一对密钥「公钥(id_rsa.pub)和私钥(id_rsa)」然后把公钥内容贴到远程仓库设置中的ssh keys中,从而建立本地与远程的认证关系。配置SSH Key的流程如下:


  • ① 来到电脑的根目录下(假设还没创建过SSH key):



执行完ssh-keygen那个指令后,后面依次要你输入文件名直接回车 → 会生成两个默认的秘钥文件,接着提示输入密码,直接回车 → 如果这里你输入密码了的话,那么push的时候你还是需要输入密码,接着又输多一次密码直接回车 → 出现最下面的这串东西就说明ssh key已经创建成功了! 接着可以用编辑器打开id_rsa.pub文件或者键入下述命令复制内容:


clip <id_rsa.pub


打开Github,点击头像,选择:Settings,然后点击左侧SSH Keys,然后New SSH Key



然后Github会给你发来一个提示创建了一个新ssh key的邮件,无视就好,接下来我们可以键入:


**ssh -T git@github.com**


然后如果上面设置过密码则需要输入密码,否则直接输入yes然后一直按回车就好!,最后出现Hi xxx那句话就说明ssh key配置成功了!



其他远程仓库配置方法类似,另外如果想一个电脑管理多个SSH-Key,可移步至:

《Git拾遗:一机多SSH-Key管理》


0x6、Git工作流


关于Git工作流,Github上有一篇图文并茂写得很好的文章,就不细说了,只是简单介绍下,更多详情可见:《Git Workflows and Tutorials》


1.集中式工作流


类似于SVN,不过只有一条master分支,然后一群人就在这条分支上嗨,比如有小A和小B:


  • 1.项目管理者初始化仓库,然后推到远程仓库


  • 2.其他人克隆远程仓库项目到本地


  • 3.小A和小B完成各自的工作


  • 4.小A先完成了,git push origin master 把代码推送到远程仓库


  • 5.小B后完成了,此时推送代码到远程仓库,出现文件修改冲突


  • 6.小B需要先解决冲突,git pull –rebase origin master,然后rebase慢慢玩


  • 7.小B把冲突解决后,git push origin master 把代码推送到远程仓库


2.功能分支工作流


和集中式分部流相比只是分支再不是只有master,而是根据功能开辟新的分支而已,示例如下:


  • 1.小A要开发新功能,git branch -b new-feature 开辟新分支


  • 2.小A在new-feature上新功能相关的编写,他可以这个分支推到远程仓库


  • 3.功能完成后,发起请求pull request(合并请求),把new-feature合并到master分支


  • 4.仓库管理员可以看到小A的更改,可以进行一些评注,让小A做某些更改, 然后再发起pull request,或者把pull request拉到本地自行修改。


  • 5.仓库管理员觉得可以了,合并分支到master上,然后把new-feature分支删掉

:这里的仓库管理者是拥有仓库管理权限的人


3.Gitflow工作流


其实就是功能分支工作流做了一些规范而已,大概流程参见上面「一个简单的分支管理策略


4.Forking工作流


分布式工作流,每个开发者都拥有自己独立的仓库,为开源项目贡献代码常用,把项目fork到自己的远程仓库,完成相应更改,然后pull request到源仓库,源仓库管理者可以决定是否合并。


5.Pull Request工作流


和Forking工作流类似,Pull Requests是Bitbucket上方便开发者之间协作的功能


0x7、其他杂项


1.为开源项目贡献代码


你可以Clone别人的开源项目,在看别人代码的时候,觉得作者某些地方写得不好,写错,或者你有更好的想法,在本地修改后,想把修改push推送到开源项目上,是无法直接Push推送更改的。参与开源项目的方式有两种:


  • 方法一: 是让作者把你加为写作者,添加协作者流程: 点击仓库的SettingsCollaborators 然后输入想添加的人的用户名或者邮箱,点击 添加即可。


  • 方法二: 点击Fork按钮,把这个项目fork到自己的账号下,然后Clone到本地,然后做你想做的修改,commit提交,然后push到自己账号里的仓库,然后打开开源项目,点击,然后新建一个「pull request」,接着设置自己的仓库为源仓库,设置源分支,目标仓库与目标分支,然后还有pull request的标题和描述信息,填写完毕后,确定。 这个时候开源项目的作者就会收到一个pullrequest的请求,由他来进行审核,作者审查完代码觉得没问题的话,他可以点击一下merge按钮即可将这个pull request合并到自己的项目中,假如作者发现了你代码中还有些bug,他可以通过Pull Request跟你说明,要修复了xxBUG才允许合并,那么你再修改下BUG,提交,更改后的提交会进入Pull Request,然后作者再审核这样!


Tips:o(╯□╰)o假如作者不关闭或者merge你的这个Pull Request,你可以一直commit骚扰主项目…


2.SourceTree使用详解


命令行虽酷炫可装逼,但是有时用图形化工具还是能提高不少效率的,安利个巨好用的Git图形化工具SourceTree,官网下载地址:www.sourcetreeapp.com/,网上教程满天飞,笔者也不粘贴复制了,找到个写得还行的,有兴趣可移步至:《用SourceTree轻松Git项目图解》


参考文献与更多Git学习资料




相关文章
|
6月前
|
网络安全 开发工具 git
版本管理 git 常用命令
版本管理 git 常用命令
49 1
|
6月前
|
缓存 开发工具 数据安全/隐私保护
通过一篇文章带你玩转git和GitHub
在现代软件开发中,版本控制系统是不可或缺的工具。Git和Github是其中最受欢迎的组合。Git是一个开源的分布式版本控制系统,用于追踪代码的改动,而Github则是一个基于Git的代码托管平台,提供了代码托管、协作开发等功能。
149 2
通过一篇文章带你玩转git和GitHub
|
存储 缓存 运维
【运维知识高级篇】一篇文章带你搞懂Git!(Git安装+全局配置+Git初始化代码仓库+Git四大区域+Git四种状态+Git常用命令+Git分支+Git测试代码回滚)
【运维知识高级篇】一篇文章带你搞懂Git!(Git安装+全局配置+Git初始化代码仓库+Git四大区域+Git四种状态+Git常用命令+Git分支+Git测试代码回滚)
256 0
|
6月前
|
Linux Shell 开发工具
一篇文章带你快速入门使用Git
一篇文章带你快速入门使用Git
|
Cloud Native Go 开发工具
开源项目的版本管理:Git的最佳实践
开源项目的版本管理:Git的最佳实践
205 0
|
安全 程序员 开发工具
代码版本管理笔记 | Python 程序员也应该会的 Git 分支操作
代码版本管理笔记 | Python 程序员也应该会的 Git 分支操作
188 0
|
数据采集 安全 JavaScript
代码版本管理笔记 | Python 程序员也应该会的 Git 进阶操作
代码版本管理笔记 | Python 程序员也应该会的 Git 进阶操作
169 0
|
数据采集 缓存 安全
代码版本管理笔记 | Python 程序员也应该会的 Git 基础操作
代码版本管理笔记 | Python 程序员也应该会的 Git 基础操作
|
存储 Linux 开发工具
学会使用Git,看这一篇文章就够了
以上是 Git 的简介绍和常用命令说明。希望这篇文章能够帮助初学者更好地理解和掌握 Git 的使用。Git 在代码管理中是一个非常重要的工具,尤其是在多人协作的情况下。因此,掌握好这些基本命令是非常有必要的。
|
存储 缓存 Shell
一篇文章搞懂Git与Github
一篇文章搞懂Git与Github