git reflog
reflog是引用日志reference logs的简称,它完整的记录了git仓库中HEAD指针的变化历史,比如commit、reset、checkout、switch、merge、pull、rebase、cherry-pick、revert等,也就是说只要HEAD发生变化,就会有一条日志。
比如我从test分支切换到main分支,然后再切换回test分支,输入git reflog会有如下的记录:
41fc2e7 (HEAD -> test, master) HEAD@{0}: checkout: moving from main to test
7876a29 (main) HEAD@{1}: checkout: moving from test to main从日志中可以看到操作详情,开头的字符串就是HEAD的commit hash。其他情况类似。
示例:
当我们使用git reset --hard 7d8be96回退代码后,又突然后悔了,而且撤回的提交别的分支也没有。这时候git reflog就派上用场了。这时候使用git relog命令输出如下:
7d8be96 (HEAD -> test) HEAD@{0}: reset: moving to 7d8be96e69dea59e2600ba2af3e1671d040281f9
41fc2e7 (master) HEAD@{1}: checkout: moving from main to test
7876a29 (main) HEAD@{2}: checkout: moving from test to main可以看到首条日志就是我们刚刚的操作reset,而我们想要回退到第二步,即从main刚切换到test的状态,这时只需要使用命令git reset --hard <font style="color:rgb(38, 38, 38);background-color:rgb(250, 250, 250);">41fc2e7</font>就能够无损恢复了。此时reflog如下:
41fc2e7 (HEAD -> test, master) HEAD@{0}: reset: moving to 41fc2e7
7d8be96 HEAD@{1}: reset: moving to 7d8be96e69dea59e2600ba2af3e1671d040281f9
41fc2e7 (HEAD -> test, master) HEAD@{2}: checkout: moving from main to test
7876a29 (main) HEAD@{3}: checkout: moving from test to main同理只要我们的操作被记录在了reflog中,都可以像乘时光机那样恢复到“过去”
git push --force-with-lease
假如有一个提交A和提交B,在push到仓库之后,突然发现B中有一些问题,于是通过git reset撤销了B这个提交的变更,在修改完之后生成一个新的提交C。这时问题就来了,当我们push的时候git会提示报错,不允许你提交,这时候我们可以用git push --force强制提交。但是会产生另一个问题,如果另一个同事在这个分支上推送了新的提交D,那么在git push --force时,就会把同事的代码给覆盖掉,这是一个非常恐怖的事情。
好在git给我们了解决方法,这种情况下应该使用git push --force-with-lease,它在推送时会检测当前远程分支的指向是否和上次fetch / pull时的指向一致,只有一致的情况下才会允许推送,从而有效避免覆盖别人代码的情况。
git commit --amend --no-edit
当我们完成一些修改commit之后,突然发现还有一些小地方需要修改,修改完之后直接使用git commit --amend --no-edit可以将这个修改和上次提交合并,当然提交的commit hash会变更。
--amend: 意思是“修正”。它告诉 git 不要生成一个新的提交(commit),而是把当前的改动“追加”到最近的一次提交上。从 git 的角度看,旧的提交被删除了,取而代之的是一个包含旧内容 + 新内容的新提交。--no-edit: 意思是“不要编辑”。通常使用--amend时,git 会打开编辑器让你修改提交信息。加上这个参数后,Git 会直接沿用上一次的提交信息,不再弹出编辑器。
注意:如果修改已经提交到远程分支,那么最好使用git push --force-with-lease命令进行提交。
版本选择符(~、^、@)
| 写法 | 描述 | 查看方式 |
|---|---|---|
| HEAD~3 | 当前 commit 的祖父的祖父(沿着父链 3 步) | git show HEAD~3 |
| HEAD^3 | 当前 commit 的第 3 个父节点(merge 才有) | git show HEAD^3 |
| HEAD@{3} | HEAD 三次操作之前的位置(来自 reflog) | git show HEAD@{3} |
其中的HEAD可以更换为任意的commit hash
git cherry-pick
将提交
git cherry-pick A..D;代表挑选从A到D之间的提交(A, D],等价于git cherry-pick B C Dgit cherry-pick A C F;代表挑选提交A、C、F,他们可以不是连续的
git add 或者 stash 的-p参数
在已有多处改动的前提下,想要只提交某几行的变更,并且保留其他代码,可在git add或者git stash后添加-p参数,此命令将你的改动按照git规则分为多个块(hunk),以交互的方式依次询问你每个hunk是否需要提交,输入y为提交,n为不提交,输入e的话,可以手动控制hunk中每一行是否提交。
git checkout -
可以切换到上一个编辑的分支,多次执行的效果是在两个分支之间来回切换。
从任意提交新建分支
git checkout -b <新分支名> <commit hash>
如上,如果不填写commit hash,以当前HEAD指针新建分支,否则以所填commit hash新建分支。
参考资料:
chatgpt


Comments | NOTHING