Git Tools¶
This part is mainly from ProGit Ch7
Tip
这部分随缘更新,用到的时候再学,学完顺便总结一下
最近在 skypilot
进行高强度开发,因此遇见很多git中曾经不重视的问题,借此机会学习并进行汇总
Stashing and Cleaning¶
Examples¶
基础环境
Bash | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
使用场景
现在我在more
分支下新建两个文件:bxhu_add_not_commit.py
和 bxhu_not_add.py
.
Bash | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
为了更好的说明stash
的特性,我特地设置了两个文件,一个被追踪但未被提交,一个压根没被追踪。
现在的问题是,我突然要回到main
分支,新建一个6.py
;但是,上述两个文件都是我瞎写的,我甚至不想给它们commit,目前没法切换分支 ToT
Legal but not good
其实“目前没法切换分支”不完全准确,事实上也可以切换,但是这样很不安全,不符合规范
如果在 more
分支中添加了新文件而没有提交,当您切换回 main
分支时,这些文件会暂时出现在 main
分支的工作区。这种情况发生的原因是:
- 暂存文件
bxhu_add_not_commit.py
:- 该文件被
git add
暂存了但未提交。Git 会把暂存的更改带到切换后的分支上,因为暂存区的内容在 Git 看来是待定的,属于未完成的变更。
- 该文件被
- 未跟踪文件
bxhu_not_add.py
:- 未跟踪文件会一直停留在工作区中,跨分支切换时也会存在。Git 默认不会自动移除未跟踪的文件,除非通过
git clean
清理。
- 未跟踪文件会一直停留在工作区中,跨分支切换时也会存在。Git 默认不会自动移除未跟踪的文件,除非通过
因此我在这里,最规范的做法是:git stash
,暂存目前的变更进入缓冲区
From ProGit
Now you want to switch branches, but you don’t want to commit what you’ve been working on yet, so you’ll stash the changes. To push a new stash onto your stack, run git stash
or git stash push
:
现在我们进行stash操作:
stash状态1:
Bash | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
stash状态2:
Bash | |
---|---|
1 2 3 4 5 6 7 8 |
|
检查当前stash list:
Bash | |
---|---|
1 2 3 |
|
注意这里,stash@{0}
是最新的stash,stash@{1}
是之前的stash,以此类推...
现在假设我们==回到了 main
分支进行一系列操作,操作完,又回到 more
分支==,我们想要恢复之前的stash,那么我们可以使用git stash apply
命令:
先回到比较老的状态(stash@{1}
)试试:
Bash | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
再到最新的状态(stash@{0}
):
Bash | |
---|---|
1 2 3 4 5 6 |
|
注意这里,stash apply
之后,它会自动显示当前的status
,不需要再单独操作一次了
Summary¶
个人来看,stash
是一个“时间机器” for specific branch,它可以让我们在当前分支上,暂存当前的工作区,然后切换到其他分支,完成其他分支的工作,然后再切换回来,恢复之前的工作区。
这里总结一下常见的 stash
指令:
1) 保存修改
Bash | |
---|---|
1 2 |
|
Unstaged and Staged
- 默认情况下,
git stash
只会保存已跟踪的文件修改 (staged
) - 使用
git stash -u
可以同时保存未跟踪的文件 (staged + unstaged
)
2) 恢复修改
Bash | |
---|---|
1 2 |
|
3) 查看stash list
Bash | |
---|---|
1 |
|
4) 删除list条目
Bash | |
---|---|
1 2 |
|
My Choice:
git stash save "msg"
git stash list
git stash apply stash@{n}
git stash drop stash@{n}
Rebase and Merge¶
事实上这是一个历史遗留的疑惑点,正好今天有时间系统整理一下:
Bash | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
现在 commit timeline
长这样:
Difference¶
1)如果采取merge方案:
Bash | |
---|---|
1 2 |
|
2)如果采取rebase方案:
Bash | |
---|---|
1 2 3 4 |
|
中间态,在git rebase main
之后
最终态:after git merge feature
Exception Process¶
在feature分支merge到main分支的过程中,会出现一些常见的conflict错误,这里我们分类来说明解决方法:
Merge Conflict
首先确保你已经修改了有冲突的文件(file.txt),删除了冲突标记(<<<<<<
, =======
, >>>>>>>
)并保存了最终想要的内容。
这一步:
- 如果在vim中,就是逐个对比
<<<<<<
,=======
,>>>>>>>
区间内的异同,手动修改; - 如果在vscode中,可以利用“冲突合并编辑器”,直接点击“接受当前更改”或“接受传入更改”来解决冲突,非常方便 :)
1) 将修改后的文件添加到暂存区:
Bash | |
---|---|
1 |
|
2) 提交合并结果:
Bash | |
---|---|
1 |
|
PS, 如果在解决冲突过程中改变主意了,想要取消这次合并,可以使用:
Bash | |
---|---|
1 |
|
3) 如果之后需要推送到 remote repo,直接推送即可:
Bash | |
---|---|
1 |
|
检查状态的cmd
git status
, 查看当前冲突状态git diff
, 查看具体的冲突内容
Rebase Conflict
首先确保你已经修改了有冲突的文件(file.txt),删除了冲突标记(<<<<<<
, =======
, >>>>>>>
)并保存了最终想要的内容。
这里跟上面merge一模一样。
1) 将修改后的文件添加到暂存区:
Bash | |
---|---|
1 |
|
2) 继续 rebase 过程:
Bash | |
---|---|
1 |
|
abort in rebase
在 rebase 过程中可能需要多次解决冲突
放弃这次 rebase,回到之前的状态 (最初始状态):
Bash | |
---|---|
1 |
|
小心:这是回到最初始,而不是上一步状态!
3) rebase
完成后,如需推送到远程,要使用强制推送:
Bash | |
---|---|
1 |
|