一些常用的 Git 进阶知识与技巧
1. 同一电脑存在多个 Git 账号
假设我们在同一电脑上拥有多个 Git 账号,例如公司内部使用的是 Gitlab,个人使用的是 Github 或者 Gitee。那就会遇到一种情况,上班时想给个人开源项目提交代码,但是 Git 绑定的是公司的账号。
在这种情况下,我们可以让 Git 绑定多个不同的 ssh key,每个 ssh key 对应一个不同的 Git 服务器。
生成第一个 ssh key:
ssh-keygen -t rsa -C "xxx@xxx.xx"
生成第二个 ssh key:
ssh-keygen -t rsa -f path/to/file-C "xxx@xxx.xx"
参数
-f
表示指定生成的文件名, path/to/file
是文件名路径,例如 ~/.ssh/id_rsa_github
。执行上面两条命令后会得到两对 ssh key。
文章图片
这时还需要在该目录下创建一个
config
文件。写上以下内容:Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_github # 私钥文件路径Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/id_rsaHost gitee.com
HostName gitee.com
User git
IdentityFile ~/.ssh/id_rsa_github
这个配置文件的作用是指定私钥文件位置。
然后我们可以把第一个密钥配置到公司的 Gitlab 服务器,并把相应的 Git 账号和邮箱设成全局。
git config --global user.name "xxx"
git config --global user.email "xxx@xxx.xx"
然后把另一对 ssh key 配置到 Github 上,并在电脑上的 Github 项目里单独配置 Git 用户姓名和邮箱。
git config user.name "xxx"
git config user.email "xxx@xxx.xx"
至此,我们就大功告成了。可以同时在不同的 Gitlab 和 Github 项目上提交代码了。
2. 修改 git commit 记录的用户姓名和邮箱 假设电脑上同时存在 Gitlab 和 Github 项目,其中 Gitlab 用户信息已经全局配置过了。现在新拉了一个 Github 项目,提交了一个 commit 并且已经推送到了远程仓库。这时发现该项目未配置 Github 的用户信息,默认使用的是全局账号 Gitlab 的用户信息。
我们可以通过以下命令来修改最近一次提交的用户信息:
git commit --amend --author="username " --no-edit
username
是用户名,用户邮箱旁边的 <>
符号不能去掉。修改后再执行 git push -f
推送到远程仓库。如果要修改多个 commit 的用户信息怎么办? 可以通过以下的代码来修改:
git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "tanguangzhi@shiqiao.com" ];
then
GIT_AUTHOR_NAME="woai3c";
GIT_AUTHOR_EMAIL="411020382@qq.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD
将上述代码中的用户名和邮箱修改后,保存为
.sh
格式的文件,例如 edit.sh
。然后在项目根目录下执行 sh edit.sh
(windows 下可右击-> Git Bash Here
-> sh edit.sh
),再执行 git push -f
强推即可。3. 修改某个历史记录的消息 假设当前分支有
a b c d
四个 commit 记录:a
b
c
d
如果你想对
c
记录的消息进行修改。可以使用 git rebase
将 c
记录换到最前面,然后使用 git commit --amend
对其消息进行修改。具体操作步骤 执行以下命令对记录
d
前面的三个 commit 进行编辑:git rebase -i d
进行 vim 编辑界面后,移动光标到 c 记录上,按下
dd
剪切该记录,然后移动光标到第一行,按下 p
粘贴,再输入 :wq
保存。执行
git commit --amend
对切换顺序后的 c
记录进行修改。进入 vim 编辑界面后,按 i
进行修改,然后按 ESC
,再输入 :wq
保存。最后用前面讲过的
git rebase
操作将 c
记录恢复到原来的位置。文章图片
这个过程的执行结果就和上图一样,这是当前分支修改后和远程分支上的对比,箭头指向的记录消息就是修改后的消息。
如果想把修改后的记录同步到远程仓库,这时只要执行
git push -f
就可以了。第二种方式
- 使用
git checkout -b
从指定记录切出一个分支c - 在新分支使用
git commit --amend
修改提交消息 - 使用
git cherry-pick
将b a
记录,追加到新分支(注意,这里的b a
提交记录是指原分支上的 commit,也就是选取原分支上的b a
记录添加到新分支上,这样新分支上的记录就变成了a b c
,并且 c 记录的提交消息在第二步已经修改过) - 使用
git checout 原分支名
切换回原来的分支,再执行git rebase
合并新分支,最后强推到远程分支
commit3: 修复登录 bug
commit2: 添加 debug 语句
commit1: 添加 console 语句
例如上面的三个记录,前面的两个记录添加了很多调试代码,在最后一个记录终于修复了 bug,并且删除了调试代码。这时如果直接将 bugFix 分支合到 master 分支,就会把调试的记录也合并进来。
这时可以使用
git cherry-pick
只将最后一个记录合并到 master 分支。或者使用 git rebase
将 bugFix 分支另外两个记录抛弃,然后再合并。5.
^
和 ~
的区别
操作符 ^
与 ~
符一样,后面也可以跟一个数字。 ~
表示向上返回几代记录。但是该操作符后面的数字与
~
后面的不同,并不是用来指定向上返回几代,而是指定合并提交记录的第几个父记录。Git 默认选择合并提交的“第一个”父记录,在操作符
^
后跟一个数字可以改变这一默认行为。单看文字可能不太好理解,下面看几个示例。
文章图片
执行命令
git checkout main^
回到第一个父记录(原来 HEAD 指向 c3,现在指向 c1)。文章图片
执行命令
git checkout main^2
回到第二个父记录(原来 HEAD 指向 c3,现在指向 c2)。最后再来一个更复杂的示例:
GHIJ
\ /\ /
DEF
\|/ \
\ | /|
|/|
BC
\/
\ /
A
A == A^0
B = A^= A^1= A~1
C = A^2= A^2
D = A^^= A^1^1= A~2
E = B^2= A^^2
F = B^3= A^^3
G = A^^^ = A^1^1^1 = A~3
H = D^2= B^^2= A^^^2= A~2^2
I = F^= B^3^= A^^3^
J = F^2= B^3^2= A^^3^2
通过这些示例我们还能发现
~n
等于连续的 n 个 ^
。6.
git revert
与 git reset
的区别
git reset
可以回退 Git 的历史记录。例如当前分支有三个记录,并且 HEAD 指向 c 记录:c <- HEAD
b
a
如果我们想回退到 b 记录,只要执行
git reset b
就可以了:b <- HEAD
a
接着使用
git push -f
将回退版本后的分支强制推送到远程仓库,这样本地分支和远程分支就同步了。git push -f
git revert
也可以撤销记录,只不过它撤销的记录不会消失,这一点和 git reset
不一样。git reset
撤销的记录就跟消失了一样。现在我们用
git revert
来重新演示下刚才的操作:c
b
a
如果我们执行
git revert b
,则会在当前分支上再生成一个新的 commit 记录,变成 a b c b'
,这个 b'
的状态和记录 b
是一样的。也就是说,执行
git reset b
后,当前的分支记录会变成 a b
。执行 git revert b
后,当前的分支记录会变成 a b c b'
。【一些常用的 Git 进阶知识与技巧】如果你想让别人知道你撤销过记录,就使用
git revert
,因为它会留下撤销的记录,否则用 git reset
。参考资料
- 一台电脑绑定两个git帐号(GitHub和GitLab)
- Git-工具-重写历史
- learngitbranching
推荐阅读
- 昨夜小楼听风
- 为什么你的路演总会超时()
- 深入理解Go之generate
- 今天写一些什么
- 遗憾是生活的常态,但孝顺这件事,我希望每一个人都不留遗憾
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。
- 唱歌教学(导致嗓音损坏的几个常见的错误唱歌方法!)
- 迷茫是人生常态
- Hive常见问题汇总
- 数组常用方法一