Skip to content

GitLab - Rebase 操作

在 Git 中,Rebasing(变基)是将一系列提交移动或合并到新的基础提交上的过程。当你正在一个功能分支上工作,该分支与主分支(通常命名为 ‘main’ 或 ‘master’)产生了分歧时,Rebasing 允许你将 ‘main’ 分支的最新更改合并到你的功能分支中。与创建合并提交不同,Rebase 通过重写历史,使你的功能分支看起来像是从 ‘main’ 的最新提交处开始的。

这会带来更整洁、更线性的项目历史。它特别适用于在将功能分支合并到主分支之前进行操作。

rebase 和 merge 都用于将一个分支的更改整合到另一个分支中。

  • git merge:在当前分支中创建一个新的“合并提交”,将两个分支的历史连接起来。项目历史将显示分支的分歧和合并。这是非破坏性的;现有分支不会改变。
  • git rebase:将当前分支的提交重新应用到另一个分支的末端(tip)。它通过为原始分支中的每个提交创建全新的提交来重写项目历史。这可以使历史记录看起来更整洁、更线性。

Rebasing 的黄金法则:永远不要对已推送到公共/共享仓库的提交进行 Rebase。Rebasing 重写历史,这可能会给那些基于原始提交进行工作的协作者带来严重问题。

让我们通过一个例子来演示。假设你有一个名为 my-feature 的功能分支,并且你想合并 main 分支的最新更改。

步骤 1:确保你的本地 main 分支是最新的。

$ git checkout main
$ git pull origin main

步骤 2:切换回你的功能分支。

$ git checkout my-feature

步骤 3:将你的功能分支 rebase 到 main 分支上。

$ git rebase main

此命令告诉 Git 将 my-feature 分支上所有不在 main 分支上的提交取出,将 my-feature 分支指向 main 分支的最新提交,然后将那些唯一的提交逐个重新应用到 my-feature 的新末端。

示例场景演练:

  1. 从 main 分支创建并切换到一个新分支,例如 feature-x:
$ git checkout -b feature-x main
Switched to a new branch 'feature-x'
  1. 在 feature-x 分支上做一些更改,添加一个新文件,并提交它:
$ echo "Initial feature work" > feature_file.txt
$ git add feature_file.txt
$ git commit -m "Add initial feature file"
  1. 同时,main 分支上进行了其他工作。为了模拟这一点,切换到 main,进行更改并提交:
$ git checkout main
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
$ echo "Update on main" > main_update.txt
$ git add main_update.txt
$ git commit -m "Add update on main branch"
  1. 现在,切换回 feature-x 分支,将其 rebase 到更新后的 main 上:
$ git checkout feature-x
Switched to branch 'feature-x'
  1. 执行 rebase:
$ git rebase main
Successfully rebased and updated refs/heads/feature-x.

此时,你的 feature-x 分支包含了其原始提交以及自 feature-x 分支创建以来 main 分支上的所有提交。feature-x 的历史将看起来是线性的,就好像它是在 main 分支最新更改之后顺序开发的。

如果 Git 在重新应用你的提交时遇到冲突,rebase 过程将暂停。你需要手动解决冲突:

  1. 打开冲突文件并编辑它们以解决差异。
  2. 暂存已解决的文件:git add <冲突文件>。
  3. 继续 rebase:git rebase —continue。
  4. 或者,如果你想中止 rebase:git rebase —abort。

如果你之前已将你的功能分支推送到远程仓库(例如 GitLab),然后在本地对其进行了 rebase,Git 将阻止你进行简单的 git push。这是因为 rebase 重写了历史。你需要强制推送:

$ git push origin feature-x --force-with-lease

--force-with-lease 通常比 --force 更安全,因为它会检查远程分支自你上次拉取后是否已被其他人更新。

警告:仅在你确定没有其他人在该特定分支上工作或已与你的团队协调过后,才进行强制推送。

  • 在继续开发之前,使用主分支的最新更改更新你的本地功能分支。
  • 在共享或合并本地提交之前(使用交互式 rebase git rebase -i)清理它们。
  • 在提交合并请求(pull request)之前,以确保历史干净、线性,更易于审查。

理解 rebase 对于维护一个干净且易于理解的 Git 历史至关重要,特别是在托管于 GitLab 等平台上的协作项目中。