git 进阶
保证日常正常的使用只需要记忆不到二十个命令即可,但是要是达到所有操作都了然于心那不记忆上千个操作可是不行的。当然,日常中我们也不推荐这么做,大多数时候我们只需要翻阅一下git官方文档或者面向Google编程即可解决问题。
问题是有时候我们针对于实际使用的中的问题不知道该如何处理,这个时候面向Google可能也没没用,因为我们需要的是解决问题的思路,或者针对于我们开发中遇到的问题该如何来处理。
1. 冲突处理
处理git的冲突应该是日常开发中较为高频的问题了,一个不小心,一句pull
或者merge
就有可能引起自动合并失败从而导致冲突发生,这个时候莫要惊慌,因为这个是常规操作(斜眼笑)。
首先,pull
和merge
时git会尝试自动合并代码,如果自动合并失败,就会导致冲突的发生。
首先git diff
查看冲突的文件形式如下:
<<<<<<< HEAD
// 当前代码
=======
// 远程发生冲突的新代码
>>>>>>> commit
看到这个不要慌,同志们,我们要克服心理恐惧,告诉自己这些都是常规操作。首先这个时候,发生冲突的文件是等待修复冲突状态,我们可以直接对冲突的地方进行修改,然后添加更改到merged
中去进行提交即可。
处理冲突的方式有通常是以下三种,耐心挨个解决所有冲突即可:
- 删除老代码,保留新代码
- 删除新代码,保留老代码
- 代码逻辑较复杂,需要视情况处理
2. 切换远程依赖
日常开发中,偶尔会遇到切换远程仓库的问题,这个时候需要我们修改连接的远程仓库地址。
有两种方式:
- 先删除,后添加
git remote rm origin
git remote add origin [url]
- 直接修改
git remote set-url origin [url]
3. 删除远程分支
删除远程分支有两个方法:
git push origin --delete [branch-name]
git branch -dr [remote/branch]
4. 分支重命名
- 重命名git本地分支
git branch -m [old-local-branch] [new-local-branch]
- 重命名git远程分支。
重名远程分支其实为先修改本地分支名称,然后删除对应的远程分支,最后推送本地分支到远程即可。
# 1. 重命名远程分支对应的本地分支
git branch -m [old-local-branch] [new-local-branch]
# 2. 删除远程分支
git branch -dr [remote/branch]
# 3. 重新推送新命名的本地分支到远程
git push origin new_local_branch_name
5. 合并部分commit
merge
是合并代码的常规操作,但是有时候我们并不想全部合并,而是想合并其中的一到两次commit
到另外一个分支,这个时候就需要 cheery-pick
命令了。
git cherry-pick [commit-id] ...
但是需要注意的是,
cherry-pick
真正的操作并不是把原来的commit
也应用到新的分支,而是复制了一份commit
。说白了就是原来的commit
的内容拿过来,作为一次提交,引用到指定的另一个分支,可能会引起冲突。因为是一次新的提交,所以最后的head
是不一样的。
6. 添加ssh公钥到远程server
每一次提交输入账号密码不是一个好的选择。本着简化操作的原则,我们可以使用ssh协议,然后利用rsa公钥,来完成身份认证和推送,从而避免频繁的输入账号密码。
大体的步骤为:
- 在本地生成ssh公钥
- 在server的设置中添加ssh公钥
- 直接在本地推送即可完成推送
首先,在本地生成ssh公钥,不想输入加密字符串的话直接两次回车即可
$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/liuyi/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/schacon/.ssh/id_rsa.
Your public key has been saved in /Users/schacon/.ssh/id_rsa.pub.
The key fingerprint is:
XXXXXXXXXXXXXXXXXXXXXXXX//这里是具体的key 指纹
然后查看rsa公钥,添加的远程server中
$ cat ~/.ssh/id_rsa.pub
ssh-rsa XXXXXXXXXXXXXXXXXXXXXXXXXXX//一大堆十六进制字符串
这里以github为例:
在登录后,Setting
-> SSH and GPG keys
-> new SSH key
:
输入ssh的title和复制的ssh key 保存即可。在操作成功后,推送代码时github会使用ssh key校验推送者的身份。体现在操作上就是啥也不用再干,直接无脑推送即可。
7. 对文件的追踪处理
取消对某个文件的追踪但不删除
git rm --cached [file-name]
对某个文件取消跟踪的同时删除文件
git rm --f [file-name]
当然,如果以后再也不需要取消追踪的文件了,最好还是添加进.ignore
中比较报销。
8. 暂存
场景: 在开发中,很多时候我们还没有将一个完整的逻辑写完的时候又需要去响应其他的bug或者代码之类。这个时候,新写的代码没开发完肯定是不能提交的,但是这个时候确实别的事情比较紧急,需要放下手头的工作去去优先响应。冲突点就在于响应的代码需要提交,且不包含当前开发一半的新代码。
所以,需求就变成了:能不能把手头写了一半的东西先暂时的存储在暂存区之外的地方。当然了,git肯定是支持的,那就是stash
。
暂存就是可以将当前工作区处于脏状态的文件存储在一个暂存栈中,清理出一个干净工作区。而后面,可以在任何合适的时候将暂存的内容拿出来应用到工作区中。
# 暂存当前处于“脏”状态的文件
git stash
# 查看暂存区栈
git stash list
# 应用最后一次暂存的内容并删除栈中所应用的那一次暂存
# pop 相当于 限制性 apply ,然后再remove
git stash pop
如果一次暂存的内容不多,这样操作完全没有问题。但是现实遇到的问题往往比较麻烦,很多时候我们暂存了一些东西,但是很久之后才想起来需要应用到当前代码,或者暂存之后,代码变动比较大,这个时候应用暂存的东西出来肯定会造成一大批的冲突。此时硬着头皮应用暂存的代码只会让工作区一片狼藉。有一个比较好的做法就是将暂存区的内容应用到一个新创建的分支,然后在分支慢慢的修改和测试,直到完成开发后应用的主开发分支。
# 创建一个新的分支,应用暂存区的内容到新分支
# 相当于执行 先执行新建分支操作,后执行pop操作
git stash branch [stash-branch]
9. git 别名
场景:有时候你需要按照指定的格式输出git日志,于是你google了半天,查阅了很多资料,终于将这个复杂而有冗长的命令构造出来并成功应用。让人沮丧的是,此时你只明白了其中的原理但是没有记住具体的命令。下次如果还需要在此执行类似操作的时候,还需要再重新google,也许你会比上一次快,但是实质上并没有任何变化。这样操作同时也不符合git的理念。
git 有一个比较好的设计就是支持别名。你可以给一个相当复杂的操作起一个别名,然后下次直接把这个当做git的命令来执行即可,使用起来相当方便。
先举个简单的例子,每一次查看git的日志的时候我们其实关注的重点是最后一次谁提交了什么
$ git log -1
commit xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(HEAD -> develop)
Author: XXX
Date: 2018-04-27 11:42:20 +0800
移除mybatis插件
为了简化这个操作方便操作我们可以这样做
上面举得例子已经可以说明问题了,但是不够明显。比如,你查阅了半天的资料拼接了一个如下的命令:
相信我,没有人想把这种命令拼写第二遍。最好的做法就是给这个命令起一个别名,下次直接应用别名即可。
10. 新建远程分支对应的本地分支
通常如果A同事新建了一个分支并推送的服务器端,此时B同事需要在新建的分支上修改的话,就需要现将新分支拉到本地,通常这样的场景有两种做法可以通过远程的分支来建立对应的本地分支:
# 1. checkout
git checkout -b <本地分支名> origin/<远程分支名>
# 2. fetch
git fetch origin <远程分支名>:<本地分支名>