GIT高级使用及其原理
前言
学习重点
1. git clone远程代码
git clone
远程代码的过程如下图所示:
现在让我们在本地模拟这个过程
- 初始化本地远程代码仓库,使用如下命令:
git init --bare
使用示例,在本地创建两个远程代码仓库a
、b
,如下图所示:
执行以上命令之后,a.remote
与b.remote
文件夹中将会多出以下图中所示文件:
假设现在有两个开发者Alice
以及Michael
,并且Alice
创建了一个iOS
工程DemoApp
,并且初始化了git
,如下图所示:
Alice
开始编写代码了,编写的代码如下图所示:
Alice
找到了Michael
,由于两人异地,所以Alice
需要将代码上传到远程代码仓库,好让Michael
可以下载自己编写到一半的代码,两个人可以一块进行开发维护,所以需要使用git
命令添加一个远程代码仓库,如下所示:
//查看本地添加到远程代码仓库
git remote
//本地添加远程代码仓库
//-t 指定本地要track远程的哪个分支
git remote add -t 远程代码仓库分支名 远程仓库本地别名 远程仓库地址
使用示例,如下图所示:
将代码保存到git
并提交代码
然后将本地仓库中的代码提交到远程,需要使用如下命令:
git push 远程代码仓库本地别名
//报错使用
git push --set-upstream origin 远程仓库分支名
使用示例,如下图所示:
现在Michael
就可以从远程代码仓库a.remote中拉取Alice
编写的代码了,如下图所示
然后使用如下命令拉取远程仓库中的代码:
git pull
使用示例,如下图所示:
然后Michael
就可以开始愉快的编写代码了。
2. git是如何产生冲突的
现在Alice
与Michael
开始一块编写代码了,Alice
编写了一段代码,并提交到了本地代码仓库以及远程代码仓库,如下图所示:
Alice
又编写了一段代码,并提交到了本地代码仓库以及远程代码仓库,如下图所示:
两次提交过后,提交记录如下所示:
//查看提交记录
git log --oneline --decorate --graph --stat
但是Michael
并不知道Alice
提交了两次代码到远程代码仓库,就接着在本地编写代码了,首先Michael
在21
行编写了一段代码并提交到了本地代码仓库,如下图所示:
接着Michael
又在22
行编写了一段代码并提交到了本地代码仓库,如下图所示:
Michael
本地提交记录如下图所示:
紧接着Michael
将本地代码仓库中的代码push
到远程代码仓库,如下图所示:
由以上的错误信息可知,产生了代码冲突,你可以使用如下命令区解决冲突:
//使用以下命令查看git支持的合并工具列表
git mergetool --tool-help
//配置git mergetool,这里使用的是xcode自带的工具
git config merge.tool opendiff
//使用合并工具
git mergetool
在Xcode
中显示的冲突代码如下图所示:
Michael
觉得自己写的代码没有Alice
好,于是就将Alice
的代码删除了,然后接着将代码提交到了远程仓库,如下图所示:
但Michael
如此做有一点很不好,就是会使远程代码仓库master
分支看起来很臃肿,产生如下图所示的很多瘤子,不容易理解以及维护。
Michael
思来想去,觉得这样很不妥当,于是就使用如下的命令回退到了合并之前的commit
:
//可以使用下面的命令查看如何回退合并代码之后的commit
git rev-parse --help
//回退合并代码之后的commit
git reset --hard ORIG_HEAD
使用示例,如下图所示:
查看回退合并之后的commit
的提交记录,如下图所示:
3. 如何解决git冲突
Michael
如果想要更好的解决以上的代码冲突,就不能直接pull
代码了,应该先做一个rebase
操作,命令如下所示:
git pull 远程代码仓库别名 远程代码仓库分支 --rebase
使用示例,如下图所示:
执行这个命令之后,会报错,这是因为出现了代码冲突,如下图所示:
以上执行过程是先将Michael
这边产生冲突的commit
对象b3066aa
与远程代码仓库中的HEAD
进行比较,直到比较到Michael
的commit对象最后一个子节点结点,因此这里选择保留Alice
的代码,如下图所示:
然后保存修改的代码到git
文件系统以及修改文件的关键信息到index
文件中,继续执行rebase操作,需要用的如下的命令:
git rebase --continue
使用示例,如下图所示:
执行这个命令之后,会报错,这是因为出现了代码冲突,如下图所示:
这里比较的是Michael
最后的commit对象261820e,发现出现了代码冲突,因此报错,这里依旧选择保留Alice
的代码,如下图所示:
然后保存修改的代码到git
文件系统以及修改文件的关键信息到index
文件中,继续执行rebase
操作,如下图所示:
然后就提示我们rebase
操作执行成功了,查看此时的代码提交信息,如下图所示:
会发现rebase
操作将Michael
这边的提交对象追加到了远程代码分支提交对象的最后面,并没有产生一般pull
、merge
操作产生的肿瘤分支,这样就很容易理解以及管理代码了。
4. rebase使用实例
首先定义如下图所示的目录结构,并在Alice
文件夹中创建一个iOS
工程:
这个工程的目录结构如下所示:
在a.remote
文件夹中初始化远程代码仓库,如下图所示:
回到Alice
文件夹中初始化git,添加远程代码仓库a.remote
以及提交项目工程代码,如下图所示:
将本地仓库中的代码push
到远程代码仓库,如下图所示:
假设代码已经开发了很长时间,Alice
主要负责主框架
以及Home
模块的代码编写,并且他已经提交了好几次代码,这里只将第一次提交的操作完整展示出来,如下图所示:
;pull
远程仓库代码,push
本地仓库代码到远程仓库的master
分支
;接着Alice
又多次提交代码到远程仓库,提交记录(使用命令: git log --oneline --decorate --graph --stat
查看)如下所示:
;除了在终端查看提交记录以外,也可以使用GitUp
图形化工具来查看(可以点击GitUp
到官网下载),使用如下图所示:
现在Alice
又开始编写Home
模块的代码了,因此创建了一个分支Alice_Home
并切换过去,如下图所示:
Alice
在Home
模块编写了代码并提交到远程仓库,如下图所示:
接着,Alice
又多次在Alice_Home
编写并提交代码,提交记录如下所示:
然后,Alice
又切换到master
分支,修改了Home
模块的代码并进行了提交,如下图所示:
此时,各个分支情况如下图所示:
然后Alice
执行了合并分支的rebase
操作,将Alice_Home
分支的代码合并到主分支master
上,使用的命令如下所示:
//将命令中的分支rebase到当前分支中
git rebase 分支名
使用工具解决冲突,并提交代码,如下图所示:
保存修改的代码到git
文件系统以及修改文件的关键信息到index
文件中,然后继续rebase
,继续rebase,如图所示:
然后我们在来查看一下分支情况,如下图所示:
可以看到的是目前已经将Alice_Home中的提交对象rebase到了本地仓库的master分支中了,因此可以将Alice_Home分支从本地删除了,如下所示:
删除之后,当前分支情况如下所示(左边是本地master
分支,右边是远程master
分支):
但是还需要将本地仓库master
分支rebase
到远程仓库的master
分支,执行命令如下图所示:
首次rebase
操作没有出现什么冲突,因此先执行git add .
命令,再执行如下命令跳过此次rebase
:
git rebase --skip
过程如下图所示:
接着出现了代码冲突,解决冲突后,执行git add .
命令,然后继续rebase
,如下图所示:
rebase
完成之后,提交代码并push
本地仓库master
分支代码到远程仓库master
分支,如下图所示:
最后,分支情况如下图所示:
其实以上是以两路合并的方式显示冲突的,当解决这些冲突的时候容易照成混乱,可以使用如下的命令配置以三路合并的方式显示冲突代码:
git config merge.conflictstyle diff3
使用示例,如下图所示:
如果你在rebase
的过程中,需要取消掉当前rebase
操作,恢复到rebase
之前的代码,可以使用如下的命令:
git rebase --abort
5. 编辑分支中的commit对象
其实,在开发工程中也可以对分支上的commit
对象进行修改、合并、删除等操作,在演示之前,先来看看之前的工程的commit
对象信息,如下图所示:
如果需要对某个commit
对象信息进行编辑,可以使用如下的命令:
git rebase -i commit对象id
使用示例(对id
为8ff1e8f
的commit
对象进行编辑,最好选择它之前的commit
对象id
作为参数),如下图所示:
5.1 修改某个commit
对象的信息
如果你想要修改id
为8ff1e8f
的commit
对象的提交信息,可以按如下的方式操作:
保存并退出后,输入git commit --amend
命令,如下图所示:
然后在对提交信息进行编辑,如下图所示:
保存并退出后,修改成功会提示你如下图所示信息:
最后,还需要执行git rebase --continue
命令结束本次rebase
,如下图所示:
注意:修改某个commit对象其实是新创建了一个commit对象(新的提交信息)替换原来的commit对象
5.2 压缩多个commit
对象
- 如果想要压缩多个
commit
对象,可以按如下的方式操作:
然后会进入到如下编辑界面:
压缩成功之后,提示信息如下图所示:
查看分支中的提交对象,如下图所示:
5.3 删除某个commit
对象以及其之后的所有commit
对象
- 如果想要删除某个
commit
对象以及其之后的commit
对象,可以按如下的方式操作:
删除之后,分支中剩下的commit
对象如下图所示:
5.4 amend的作用
可以使用如下图所示命令查看amend
的作用:
使用示例如下所示:
首先进入commit
的编辑模式:
创建并编辑一个test.txt
文件,如下图所示:
添加这个文本文件到暂缓区,如下图所示:
在原来的commit
的基础上编辑这个commit
(编辑之后就成为一个新的commit
对象),并替换掉原来的commit
对象,如下图所示:
查看当前分支中commit
对象情况,如下图所示:
转载自:https://juejin.cn/post/7017429292854280205