2024-04-10
原文作者:吴声子夜歌 原文地址: https://blog.csdn.net/cold___play/article/details/136790400

Git

1、修改历史信息

要修改历史信息,可使用--amend参数来修改最后一次Commit的信息,但这仅限于最后一次,如果要改动其他更早的信息,就得使用其他方法了。

前面介绍过的git rebase指令有一种强大的互动模式,接下来的几节内容都是介绍怎样使用这种模式来改动过去的历史记录。首先看一下当前的状况:

    git log --oneline

202404102035152661.png

1.1、启动互动模式

下面使用Rebase指令整理一下:

    git rebase -i 4cb958a

-i参数是指要进入Rebase指令的“互动模式”,而后面的4cb958a是指这次Rebase指令的应用范围为“从现在到4cb958a这个Commit”,也就是最开始的那个Commit。这个指令会弹出一个Vim编辑器:

202404102035157362.png

这里需注意以下两点:

  1. 上面的顺序与git log指令的结果是相反的,但在SourceTree界面中是一样的。
  2. 上面的pick是指“保留这次的Commit,不做改动”,其他指令稍后会介绍。

修改指令,选取两行把pick改成reword(r):

202404102035161953.png

存档并离开之后,会立即弹出另一个Vim编辑器画面:

202404102035167304.png

修改第一个Commit信息,然后保存:

202404102035171385.png

修改第二个Commit信息,然后保存:

202404102035175706.png

再次查看历史记录:

202404102035179857.png

1.2、修改Commit信息的影响

看起来好像只是改了信息,只涉及单纯的文字变动,其实没有那么简单。如果仔细看,就会发现那两次Commit的SHA-1值都变了,这两次的Commit已经是全新的Commit对象了。

进行Rebase时,Commit对象并不是剪切、粘贴而已,因为要接的前一个Commit不同(其实时间也不同),所以会重新计算并做出一个新的Commit对象。

这里也是一样,看起来只是改字,但因为Commit对象的信息也会影响SHA-1的计算,所以Git会做出新的Commit对象来替代原来的Commit对象。

不止这样,因为这两个Commit对象被换掉了,在它之后的Commit因为前面的历史信息被改了,所以后面整串的Commit全部都重做新的Commit对象来替代旧的Commit对象。

1.3、取消Rebase

如果想要取消这次的Rebase,只需这样做:

    git reset ORIG_HEAD --hard

2、多个Commit合并位一个Commit

新增两个文件并分两次提交:

    echo "111" > 1.txt
    echo "222" > 2.txt
    git add .
    git commit 1.txt -m "add 1"
    git commit 2.txt -m "add 2"

查看记录:

202404102035184528.png

如果把这2个Commit合并为一个,就会让Commit看起来更简洁。可以使用互动模式的Rebase来处理:

    git rebase -i d249c0f

202404102035188509.png

这里使用squash指令,把上面的内容改为:

2024041020351926510.png

上面的改动表示cc722b0这个Commit会和前一个05b8f3eCommit合并在一起。

随后修改合并后的Commit信息:

2024041020351963411.png

再次查看记录,合并成功:

2024041020352014312.png

3、一个Commit拆解成多个Commit

继续使用上文中的案例,目的是把51422de这个Commit拆分为2个Commit,每个Commit只有一个文件即可。

    git rebase -i d249c0f

2024041020352059313.png

这次把要拆解的那个Commit的pick改成edit:

2024041020352128114.png

保存后,Rebase在执行到51422de这个Commit时就会停下来:

2024041020352169315.png

这时,因为要把当前这个Commit拆解成两个Commit,所以要使用Reset指令:

    git reset HEAD^

然后查看一下状态:

2024041020352204816.png

可以看到,1.txt和2.txt都被拆解出来放在工作目录中,且处于Untracked状态。还记得怎么Commit文件吗?就是用add + commit二段式指令:

    git add .
    git commit 1.txt -m "add 1"
    git commit 2.txt -m "add 2"

最后执行

    git rebase --continue

以完成rebase交互。

查看记录,完成了拆分:

2024041020352245417.png

4、在某些Commit之间插入新的Commit

还是使用上面案例,在(69204dc)add 2和(e061b15)add 1之间插入一个Commit。

    git rebase -i d249c0f

2024041020352302118.png

处于Rebase状态的Commit列表与平常看到的记录是相反的,所以如果想在某两个Commit之间再增加Commit,要注意停下来的那个点是不是正确的点。例如,要加在add 2和add 1之间增加Commit,需要停在add 1上:

2024041020352354619.png

保存后,Rebase操作执行,停在add 1的Commit上:

2024041020352402720.png

此时,就可以新增Commit了:

    echo "1.5" > 1.5.txt
    git add 1.5.txt
    git commit 1.5.txt -m "add 1.5"

随后继续执行Rebase操作:

    git rebase --continue

查看记录,插入Commit成功:

2024041020352437821.png

5、删除Commit

继续使用上述案例,删除掉add 1.5这个Commit。

要删除Commit很简单,在Rebase的过程中,把原来的pick改成drop,甚至直接将其删掉也可以。

    git rebase -i d249c0f

2024041020352479122.png

如果想删掉add 1.5,可以把该行的pick改成drop,或者直接删除掉该行:

2024041020352521423.png

存档、离开后便会开始进行Rebase。然后查看记录,删除成功:

2024041020352561724.png

6、调整Commit的顺序

继续使用上述案例,假设先在要互换add 1和add 2这两个Commit的顺序。

    git rebase -i d249c0f

2024041020352605025.png

只需要互换两个记录的顺序即可:

2024041020352653426.png

存档、离开后,Rebase就会继续做它的工作。然后查看记录,顺序已经调整成功:

2024041020352688527.png

7、Revert指令

7.1、取消Commit

继续使用上文案例,假设要取消最后的add 1这个Commit。

    git revert HEAD --no-edit

2024041020352727928.png

这样就把最后一次Commit的内容删掉了。虽然文件不见了,但是Commit增加了。

Revert指令是“再做一个新的Commit,来取消你不要的Commit”,所以Commit的数量才会增加。

7.2、取消Revert

如果做出来的Revert不想要了,可用以下几种方式来处理:

1、再开一个Revert

可以再开一个新的Revert,来Revert刚才那个Revert:

    git revert HEAD --no-edit

2024041020352774629.png

刚刚被删掉的1.txt又出现了,这样Commit又变多了。

2、直接使用Reset

如果要“砍掉”这个Revert,只需直接使用Reset指令:

    git reset HEAD^ --hard

8、Reset、Rebase和Revert区别

指令 修改历史记录 说明
Reset 把当前状态设置成某个指定Commit的状态,通常适用于尚未推出去的Commit
Rebase 不管是新增、改动、删除Commit,还是用来整理、编辑还没有推出去的Commit,都相当方便,但通常只适用于尚未推出去的Commit
Revert 新增一个Commit来反转(或说取消)另一个Commit的内容,原来的Commit依旧会保留在历史记录中。虽然会因此而增加Commit数量,但通常比较适用于已经推出去的Commit,或者不允许使用Reset或Rebase来修改历史记录指令的情景
阅读全文