Git 使用心得
使用 Git 会经常遇到各种奇怪需求,在这里分享一下,可能会持续更新?
改动历史提交记录
前排提醒:修改历史记录会对这条记录之后的 commit 都产生影响,具体表现为哈希值被修改,所以此功能不应该被滥用。如果你修改了已经推送到云端的内容,请尽量在 push 命令后面加上
--force-with-lease
你可能会在 rebase 过程中遇到冲突问题,这是正常现象,你需要对冲突的部分进行手动调整,然后执行
git add和git rebase --continue
如果你想对分支内的某条记录进行修改的话,可以先复制这个 commit 前一条记录的哈希值,然后输入下面的命令:
1 | git rebase -i <hash> |
就会弹出一个窗口,展示了这个提交之后的所有 commit 列表,注意不包含他自身。至于为什么,可以从 rebase 的字面意思来理解。如果我们填入的记录就是所谓的 base 的话,这个命令要做的就是改变这个 base 后面的内容,他本身自然就不需要被包含。
如果你正在跟着做的话,你可能会看到与下图类似的结构,接下来的操作都是通过将其中的 pick 改为其他的指令,必要时更改记录的位置顺序实现的。

除了直接复制 hash 值,我们还可以使用相对引用。比如你想更改的是第五个记录,只需将前面命令的 <hash> 部分更改为 HEAD~5,HEAD 是 0-base 的,所以他的含义与第六条记录的 hash 值等效。最终的效果自然也一样。
那么上面这些基本已经覆盖了 99% 的场景了,但是如果我们想更改这个仓库的第一个,也就是最老的记录,他并没有父记录,该怎么办?可以这样:
1 | git rebase -i --root |
改历史注释
如果你只想修改最后一次提交的内容,那么很幸运,直接输入这行命令就能便捷的修改
1 | git commit --amend -m <commit> |
然而如果这个 commit 的前面存在别的提交,就要用到前面讲到的 rebase 方法,将目标提交前面的 pick 删掉,改为 reword 或简写 r,关闭窗口,然后在新弹出的窗口中进行修改操作。
改历史内容
仍然是 rebase, 将 pick 改为 edit 或 e,就可以修改内容
修改完成后输入下面的命令即可:
1 | git add . |
具体含义就是将修改内容合并到最后一个 commit,并继续 rebase 流程
合并提交记录
将 pick 改为 squash 或 s,就可以合并到他的前一条记录中。如果想要合并的两条记录并不相邻呢?我们可以剪切较新的那条记录,插入到目标记录的下面,然后将 pick 改为 squash 即可
squash 是强制要求我们修改注释的,如果我们不想修改注释,可以使用 fixup 指令,他可以只将内容并入目标记录,不影响注释
如果我们一开始就明确了这个记录应该被合并,可以使用以下命令:
1 | git commit --fixup=<hash> |
这样 git 就能帮我们自动排好顺序并标注 fixup,我们只需要点关闭就好了
删除提交记录
将 pick 改为 drop 或 d
拆分提交记录
这个需求没有现成的轮子,需要配合其他的指令。先把目标记录改成 edit,然后输入:
1 | git reset HEAD~1 |
将代码全部恢复到工作区,然后挑选文件分批提交即可。如果需要对某个文件进行更细致的更改,可以自己手动调整
单独恢复某个文件
如果只想将单独的文件回退到某个 commit 的状态,可以使用 restore 命令,使用方法非常简单:
1 | git restore --source=<hash> <file> |
改动分支基点
如果你因为某些原因想要将分支基点转移到一个新的节点,rebase 同样能胜任这个工作。
步骤也很简单,首先切换到需要变基的分支,然后执行 rebase 命令即可,以转移到 master 最新节点为例:
1 | git checkout <branch> |
将某个记录应用到新的分支
切换到这个分支,然后使用 cherry-pick:
1 | git checkout <branch> |
回退记录
如果你在操作的时候遇到了问题,且比较难解决时,比较好的办法就是回退。我们可以输入:
1 | git reflog |
来查看修改记录,复制目标记录的 hash 值后输入:
1 | git reset --hard <hash> |
就顺利的完成了一次回退