前言

实习过程中,用到的 git 操作挺多的,除了一些基础的克隆、提交、推送、合并等命令,还用到了一些比较复杂的命令,这里就说说我实习过程中经常用的 git 命令。

比较差异

HEAD

指向当前所在的分支的最新提交

master…HEAD

当前分支从分叉点以来的改动(忽略 master 的新提交)

master..HEAD

比较 master 最新版和HEAD最新版(包括 master 的新提交)

1
2
# 列出当前分支相比于master分支发生了改动的文件名
git diff --name-only master...HEAD

变基操作

git rebase

将一个分支上的更改移到另一个分支之上,保持提交历史线性

1
2
3
4
5
# 将当前分支的提交“变基”到 `master` 分支的最新提交之上,同时保持历史记录是线性且干净的
git rebase master

# 在rebase的过程中,想放弃rebase
git rebase --abort

git merge 和 git rebase的区别

git merge master 操作线路图

  1. 查找差异:Git 发现 masterfeature 新(有 M3M4)。
  2. 创建合并提交: Git 在 feature 分支上创建一个全新的提交 C,这个提交拥有两个父提交(F2M4)。
  3. 结果: feature 分支的历史图出现了分叉,但真实地记录了两个分支交汇的时间点。
1
2
3
M1 -- M2 ------------------ M4 (master)
\ /
F1 -- F2 -- (C) (feature) <-- C是合并提交

git rebase master 操作线路图

  1. 剪切:Git 识别并保存 feature 分支上独有的提交(F1F2)。
  2. 移动基底: Git 将 feature 分支的起点移动到最新的 master 提交 (M4)。
  3. 粘贴/重放 : Git 按照顺序,在 M4 之后重新生成等效的新提交(F1'F2')。这些新提交拥有不同的哈希值
  4. 结果:你的 feature 分支历史变得线性且干净,看起来就像是从最新的 M4 之后才开始工作一样。
1
2
M1 -- M2 -- M3 -- M4 -- F1' -- F2' (master & feature) <-- 线性历史
<-- F1', F2' 是新的提交

⚠️ 注意事项

  • 不要对已推送的提交执行 rebase:如果你已经把分支推送到远程仓库并和其他人共享,rebase 会重写提交历史,可能导致协作混乱。

重置操作

基本命令

1
2
3
4
5
# 硬重置-将 HEAD、暂存区、工作区全部重置为指定提交的状态。 
git reset --hard

# 软重置-仅移动 HEAD 指针到指定提交,保留所有更改在暂存区中
git reset --soft

使用场景

1
2
3
4
5
6
# 将当前分支强制同步到远程 `pub/sandbox` 分支的最新状态
# 1. 获取远程 pub/sandbox 的最新状态
git fetch origin pub/sandbox

# 2. 强制本地重置为远程状态(假设你已在 sandbox 分支)
git reset --hard origin/pub/sandbox

远程分支被重置后git 出现分叉

在开发过程中,如果有人因为某些原因,重置了远程分支,本地仓库与远程仓库的历史记录不再一致,会出现“分叉”。Git 会提示类似:
Git 分叉状态
解决办法

1
2
3
4
5
# 同步远程分支代码
git fetch origin pub/sandbox

# 将本地沙盒分支同步到远程分支
git reset --hard origin/pub/sandbox

git cherry-pick

精确地把某个提交复制一份,“摘”到当前分支上

基础语法

1
2
3
4
5
6
7
8
9
10
git cherry-pick <commit-hash>

# 连续摘取多个Commit
git cherry-pick <hash-1> <hash-2> <hash-3>

# 摘取一个范围的 Commit
git cherry-pick <start-hash>..<end-hash>

# 只应用更改,不自动创建 Commit
git cherry-pick -n <commit-hash>

<commit-hash>:想要“摘取”的那个Commit的完整或简短哈希值。

git rebase -i

在将一系列 commit 应用到另一个基点 base 之前,有机会编辑、修改、整理这些提交记录。

假如现在我想将我的分支上已有的提交,合并成一个提交,可以进行如下操作:

先选择正确的基点

1
2
# 这会列出最近的 4 个提交
git rebase -i HEAD~4

会出现类似下面的窗口:
Git rebase 交互界面

现在想将后面的三个提交合并到第一个中,只需要将前面的 pick 改成 squash
修改 pick 为 squash
保存并关闭编辑器。
Git 会立即进入下一个环节:因为它看到了 squash 指令,它会再次打开编辑器,让你合并和编写新的、最终的提交信息。
合并提交信息编辑

你需要做的是:

  1. 删除所有不必要的行
  2. 编写一个能代表所有这些更改的简洁提交信息。

最终的提交消息
最终提交消息

编辑好提交消息后,保存并退出,出现一下提示,表示 squash 完成
Squash 完成提示

推送到远程:因为你重写了历史,所以需要使用以下命令重写远程仓库历史:

1
git push --force-with-lease

现在远程仓库也只有 squash 后的一次提交了
远程仓库最终状态