这是用户在 2024-11-29 19:55 为 https://dzone.com/articles/merging-vs-rebasing 保存的双语快照页面,由 沉浸式翻译 提供双语支持。了解如何保存?
DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The dawn of observability across the SDLC has fully disrupted standard performance monitoring and management practices. See why.
整个 SDLC 可观察性的曙光已经完全打破了标准的性能监控和管理实践。了解原因。

Apache Kafka: a streaming engine for collecting, caching, and processing high volumes of data in real time. Explore the essentials now.

Observability and Performance: Join our Virtual Roundtable as a panel of SMEs discuss key trends in the observability space.

Platform Engineering: Enhance the developer experience, establish secure environments, automate self-service tools, and streamline workflows

Related 相关

  • On Git and Cognitive Load
    关于 Git 和认知负荷
  • Git: Basic Terms and Commands Explained
    Git:基本术语和命令解释
  • Top 35 Git Commands With Examples
    带示例的前 35 条 Git 命令
  • Git Reset HEAD
    Git 重置 HEAD

Trending 趋势

  • Single Sign-On Testing: A Step-by-Step Guide
    单点登录测试:分步指南
  • Implementing a RAG Model for PDF Content Extraction and Query Answering
    实现用于 PDF 内容提取和查询回答的 RAG 模型
  • Building a RAG Model Pipeline Using Python With Online Text Data
    利用在线文本数据,使用 Python 构建 RAG 模型管道
  • Formatting Strings in Java: String.format() Method
    在 Java 中格式化字符串:String.format() 方法
  1. DZone
  2. Testing, Deployment, and Maintenance
  3. Deployment
  4. Merging vs. Rebasing

  5. DZone 测试、部署和维护 部署合并与重新分区

Merging vs. Rebasing 合并与重排

While merging and rebasing are similar in Git, they serve two different functions. Here's what you should know to keep your histories as clean or as complete as you like.
虽然合并和重定向在 Git 中很相似,但它们却有两种不同的功能。下面是你应该知道的,让你的历史记录保持干净或完整。

By 
Tim Pettersen user avatar
Tim Pettersen
·
Apr. 11, 17 · Tutorial
作者: Tim Pettersen user avatar Tim Pettersen - 四月 11, 17 - 教程
Likes (179) 赞 (179)
Comment (9) 评论 (9)
Save 节省
Tweet 鸣叫
Share 分享
77.4K Views 77.4K 次浏览

Join the DZone community and get the full member experience.

Join For Free
加入 DZone 社区,获得完整的会员体验。免费加入

The git rebase command has a reputation for being magical Git voodoo that beginners should stay away from, but it can actually make life much easier for a development team when used with care. In this article, we’ll compare git rebase with the related git merge command and identify all of the potential opportunities to incorporate rebasing into the typical Git workflow.
git rebase 命令因其神奇的 Git 巫术而声名狼藉,初学者应该敬而远之,但如果谨慎使用,它实际上可以让开发团队的工作变得更加轻松。在本文中,我们将比较 git rebase 和相关的 git merge 命令,并找出将重定向纳入典型 Git 工作流程的所有潜在机会。

Conceptual Overview 概念概述

The first thing to understand about git rebase is that it solves the same problem as git merge. Both of these commands are designed to integrate changes from one branch into another branch—they just do it in very different ways.
首先要了解的是, git rebase 和 git merge 解决的是同样的问题。这两条命令都是为了将一个分支中的修改整合到另一个分支中,只是实现的方式截然不同。

Consider what happens when you start working on a new feature in a dedicated branch, then another team member updates the master branch with new commits. This results in a forked history, which should be familiar to anyone who has used Git as a collaboration tool.
想想看,当你在一个专用分支中开始开发一项新功能时,另一个团队成员又在 master 分支中更新了新提交,这会发生什么?使用过 Git 作为协作工具的人应该不会对这种情况感到陌生。

A forked commit history

Now, let’s say that the new commits in master are relevant to the feature that you’re working on. To incorporate the new commits into your feature branch, you have two options: merging or rebasing.
现在,假设 master 中的新提交与您正在开发的功能相关。要将新提交合并到 feature 分支中,有两个选择:合并或重定向。

The Merge Option 合并选项

The easiest option is to merge the master branch into the feature branch using something like the following:
最简单的方法是将 master 分支合并到功能分支,具体做法如下:

2
1
git checkout feature
2
git merge master


Or, you can condense this to a one-liner:
或者,你也可以用一句话来概括:

1
1
git merge master feature


This creates a new “merge commit” in the feature branch that ties together the histories of both branches, giving you a branch structure that looks like this:
这将在 feature 分支中创建一个新的 "合并提交",并将两个分支的历史记录合并在一起,从而形成如下的分支结构:

Merging master into the feature branch

Merging is nice because it’s a non-destructive operation. The existing branches are not changed in any way. This avoids all of the potential pitfalls of rebasing (discussed below).
合并的好处在于它是一种非破坏性操作。现有的分支不会有任何改变。这就避免了重定向的所有潜在隐患(下文将讨论)。

On the other hand, this also means that the feature branch will have an extraneous merge commit every time you need to incorporate upstream changes. If master is very active, this can pollute your feature branch’s history quite a bit. While it’s possible to mitigate this issue with advanced git log options, it can make it hard for other developers to understand the history of the project.
另一方面,这也意味着 feature 分支在每次需要纳入上游变更时,都会有一个无关的合并提交。如果 master 非常活跃,这就会严重污染特性分支的历史记录。虽然可以通过高级 git log 选项来缓解这一问题,但这会让其他开发人员很难了解项目的历史。

The Rebase Option 重置选项

As an alternative to merging, you can rebase the feature branch onto master branch using the following commands:
作为合并的替代方法,您可以使用以下命令将 feature 分支重定向到 master 分支:

2
1
git checkout feature
2
git rebase master


This moves the entire feature branch to begin on the tip of the master branch, effectively incorporating all of the new commits in master. But, instead of using a merge commit, rebasing re-writesthe project history by creating brand new commits for each commit in the original branch.
这样,整个 feature 分支就会从 master 分支的顶端开始,从而有效合并了 master 中的所有新提交。不过,重定向不是使用合并提交,而是为原始分支中的每个提交创建全新的提交,从而重写项目历史。

Rebasing the feature branch onto master

The major benefit of rebasing is that you get a much cleaner project history. First, it eliminates the unnecessary merge commits required by git merge. Second, as you can see in the above diagram, rebasing also results in a perfectly linear project history—you can follow the tip of feature all the way to the beginning of the project without any forks. This makes it easier to navigate your project with commands like git log, git bisect, and gitk.
重定向的主要好处是,项目历史记录更加清晰。首先,它消除了 git merge 所要求的不必要的合并提交。其次,如上图所示,重定向还能带来完美的线性项目历史--你可以沿着 feature 的提示一直追溯到项目的开头,而不需要任何分叉。这使得使用 git log 、 git bisect 和 gitk 等命令浏览项目变得更加容易。

But, there are two trade-offs for this pristine commit history: safety and traceability. If you don’t follow the Golden Rule of Rebasing, re-writing project history can be potentially catastrophic for your collaboration workflow. And, less importantly, rebasing loses the context provided by a merge commit—you can’t see when upstream changes were incorporated into the feature.
但是,这种原始的提交历史有两个代价:安全性和可追溯性。如果不遵循 "重定向黄金法则",重写项目历史可能会给协作工作流程带来灾难。更重要的是,重写会丢失合并提交所提供的上下文--你无法看到上游变更是何时纳入功能的。

Interactive Rebasing 交互式重新定标

Interactive rebasing gives you the opportunity to alter commits as they are moved to the new branch. This is even more powerful than an automated rebase, since it offers complete control over the branch’s commit history. Typically, this is used to clean up a messy history before merging a feature branch into master.
交互式重置让你有机会在提交移动到新分支时对其进行修改。交互式重定向比自动重定向更强大,因为它能完全控制分支的提交历史。通常情况下,在将特性分支合并到 master 之前,会使用这种方法来清理杂乱的历史记录。

To begin an interactive rebasing session, pass the i option to thegit rebase command:
要开始交互式重定向会话,请向 git rebase 命令传递 i 选项:

2
1
git checkout feature
2
git rebase -i master


This will open a text editor listing all of the commits that are about to be moved:
这将打开一个文本编辑器,列出所有即将被移动的提交:

1
pick 33d5b7a Message for commit #1
2
pick 9480b3d Message for commit #2
3
pick 5c67e61 Message for commit #3


This listing defines exactly what the branch will look like after the rebase is performed. By changing the pick command and/or re-ordering the entries, you can make the branch’s history look like whatever you want. For example, if the 2nd commit fixes a small problem in the 1st commit, you can condense them into a single commit with the fixup command:
该列表准确定义了分支在执行重置后的样子。通过修改 pick 命令和/或重新排列条目,你可以让分支的历史看起来像你想要的任何样子。例如,如果第 2 次提交修复了第 1 次提交中的一个小问题,就可以使用 fixup 命令将它们合并为一次提交:

3
1
pick 33d5b7a Message for commit #1
2
fixup 9480b3d Message for commit #2
3
pick 5c67e61 Message for commit #3


When you save and close the file, Git will perform the rebase according to your instructions, resulting in project history that looks like the following:
保存并关闭文件后,Git 会根据你的指示执行重置操作,项目历史记录如下:

Squashing a commit with an interactive rebase

Eliminating insignificant commits like this makes your feature’s history much easier to understand. This is something that git merge simply cannot do.
消除像这样无关紧要的提交会让您更容易理解功能的历史。这是 git merge 无法做到的。

The Golden Rule of Rebasing
重新定标黄金法则

Once you understand what rebasing is, the most important thing to learn is when not to do it. The golden rule of git rebase is to never use it on public branches.
了解了什么是重定向后,最重要的是要知道什么时候不能重定向。 git rebase 的黄金法则是永远不要在公共分支上使用它。

For example, think about what would happen if you rebased master onto your feature branch:
例如,想想如果将 master 重定向到 feature 分支上会发生什么:

Rebasing the master branch

The rebase moves all of the commits in master onto the tip of feature. The problem is that this only happened in yourrepository. All of the other developers are still working with the original master. Since rebasing results in brand new commits, Git will think that your master branch’s history has diverged from everybody else’s.
rebase 会将 master 中的所有提交移到 feature 的顶端。问题是,这只发生在你的版本库中。所有其他开发人员仍在使用原来的 master 。由于重定向会产生全新的提交,Git 会认为你的 master 分支的历史与其他人的不同。

The only way to synchronize the two master branches is to merge them back together, resulting in an extra merge commitand two sets of commits that contain the same changes (the original ones, and the ones from your rebased branch). Needless to say, this is a very confusing situation.
同步两个 master 分支的唯一方法就是将它们合并到一起,这样就会产生一个额外的合并提交和两组包含相同变更的提交(原始提交和从您的分支中重建的提交)。不用说,这种情况会非常混乱。

So, before you run git rebase, always ask yourself, “Is anyone else looking at this branch?” If the answer is yes, take your hands off the keyboard and start thinking about a non-destructive way to make your changes (e.g., the git revert command). Otherwise, you’re safe to re-write history as much as you like.
因此,在运行 git rebase 之前,一定要问问自己:"还有其他人在看这个分支吗?如果答案是肯定的,那就把手从键盘上拿开,开始考虑一种非破坏性的修改方式(比如 git revert 命令)。否则,你就可以随意重写历史了。

Force-Pushing 力推式

If you try to push the rebased master branch back to a remote repository, Git will prevent you from doing so because it conflicts with the remote master branch. But, you can force the push to go through by passing the --force flag, like so:
如果你想把重建后的 master 分支推送回远程仓库,Git 会阻止你这么做,因为它与远程的 master 分支冲突。不过,你可以通过 --force 标志来强制推送,就像这样:

2
1
# Be very careful with this command!
2
git push --force


This overwrites the remote master branch to match the rebased one from your repository and makes things very confusing for the rest of your team. So, be very careful to use this command only when you know exactly what you’re doing.
这会覆盖远程 master 分支,使其与版本库中重建的分支相匹配,这会让团队其他成员感到非常困惑。因此,只有在你非常清楚自己在做什么的情况下,才要非常小心地使用这条命令。

One of the only times you should be force-pushing is when you’ve performed a local cleanup after you’ve pushed a private feature branch to a remote repository (e.g., for backup purposes). This is like saying, “Oops, I didn’t really want to push that original version of the feature branch. Take the current one instead.” Again, it’s important that nobody is working off of the commits from the original version of the feature branch.
只有在将私有特性分支推送到远程版本库后进行本地清理(例如,出于备份目的)时,才应该强制推送。这就好像在说:"哎呀,我并不想推送原始版本的特性分支。用当前版本代替吧"。同样重要的是,没有人会使用原始版本特性分支的提交。

Workflow Walkthrough 工作流程演练

Rebasing can be incorporated into your existing Git workflow as much or as little as your team is comfortable with. In this section, we’ll take a look at the benefits that rebasing can offer at the various stages of a feature’s development.
在现有的 Git 工作流程中,可以根据团队的需要或多或少地进行重定向。在本节中,我们将介绍重定向在功能开发的各个阶段所能带来的好处。

The first step in any workflow that leverages git rebase is to create a dedicated branch for each feature. This gives you the necessary branch structure to safely utilize rebasing:
任何利用 git rebase 的工作流程的第一步都是为每个功能创建一个专用分支。这将为您提供必要的分支结构,以便安全地使用重定向:

Developing a feature in a dedicated branch

Local Cleanup 当地清理

One of the best ways to incorporate rebasing into your workflow is to clean up local, in-progress features. By periodically performing an interactive rebase, you can make sure each commit in your feature is focused and meaningful. This lets you write your code without worrying about breaking it up into isolated commits—you can fix it up after the fact.
将重置纳入工作流程的最佳方法之一就是清理本地的、进行中的特性。通过定期执行交互式重置,你可以确保功能中的每个提交都是有重点和有意义的。这样您在编写代码时就不必担心代码会被分割成孤立的提交--您可以在事后进行修复。

When calling git rebase, you have two options for the new base: The feature’s parent branch (e.g., master), or an earlier commit in your feature. We saw an example of the first option in theInteractive Rebasing section. The latter option is nice when you only need to fix up the last few commits. For example, the following command begins an interactive rebase of only the last 3 commits.
在调用 git rebase 时,您有两个选择:功能的父分支(例如 master ),或者功能中较早的提交。我们在 "交互式重定向 "部分看到了第一个选项的示例。当你只需要修复最后几次提交时,后一个选项就很不错。例如,下面的命令只对最后 3 次提交进行交互式重定向。

2
1
git checkout feature
2
git rebase -i HEAD~3


By specifying HEAD~3 as the new base, you’re not actually moving the branch—you’re just interactively re-writing the 3 commits that follow it. Note that this will not incorporate upstream changes into the feature branch.
将 HEAD~3 指定为新的基本分支,实际上并没有移动该分支,只是交互式地重写了其后的 3 次提交。请注意,这样做不会将上游改动纳入 feature 分支。

Rebasing onto Head~3

If you want to re-write the entire feature using this method, the git merge-base command can be useful to find the original base of the feature branch. The following returns the commit ID of the original base, which you can then pass to git rebase:
如果你想用这种方法重写整个功能, git merge-base 命令可以帮助你找到 feature 分支的原始基础。下面的命令会返回原始分支的提交 ID,你可以把它传给 git rebase :

1
1
git merge-base feature master


This use of interactive rebasing is a great way to introduce git rebase into your workflow, as it only affects local branches. The only thing other developers will see is your finished product, which should be a clean, easy-to-follow feature branch history.
使用交互式重定标是将 git rebase 引入工作流程的好方法,因为它只影响本地分支。其他开发人员看到的只是你的成品,而这应该是一个简洁、易懂的特性分支历史。

But again, this only works for private feature branches. If you’re collaborating with other developers via the same feature branch, that branch is public, and you’re not allowed to re-write its history.
但同样,这只适用于私有特性分支。如果你通过同一特性分支与其他开发人员合作,那么该分支就是公共分支,你不能改写它的历史。

There is no git merge alternative for cleaning up local commits with an interactive rebase.
目前还没有其他 git merge 方法可以通过交互式 rebase 来清理本地提交。

Incorporating Upstream Changes Into a Feature
将上游更改纳入功能

In the Conceptual Overview section, we saw how a feature branch can incorporate upstream changes from master using either git merge or git rebase. Merging is a safe option that preserves the entire history of your repository, while rebasing creates a linear history by moving your feature branch onto the tip of master.
在 "概念概述 "部分,我们看到了特性分支如何使用 git merge 或 git rebase 来合并来自 master 的上游变更。合并是一个安全的选择,可以保留版本库的整个历史,而重定向则通过将功能分支移动到 master 的顶端来创建线性历史。

This use of git rebase is similar to a local cleanup (and can be performed simultaneously), but in the process it incorporates those upstream commits from master.
git rebase 的使用类似于本地清理(可同时执行),但在此过程中会纳入来自 master 的上游提交。

Keep in mind that it’s perfectly legal to rebase onto a remote branch instead of master. This can happen when collaborating on the same feature with another developer and you need to incorporate their changes into your repository.
请记住,将 master 重置到远程分支上是完全合法的。在与其他开发人员合作开发同一功能时,如果需要将他们的修改纳入自己的版本库,就可能发生这种情况。

For example, if you and another developer named John added commits to the feature branch, your repository might look like the following after fetching the remote feature branch from John’s repository:
例如,如果您和另一位名为 John 的开发人员向 feature 分支添加了提交,那么从 John 的版本库中获取远程 feature 分支后,您的版本库可能会如下所示:

Collaborating on the same feature branch

You can resolve this fork the exact same way as you integrate upstream changes from master: either merge your local featurewith john/feature, or rebase your local feature onto the tip of john/feature.
您可以采用与整合 master 上游更改完全相同的方式来解决此分叉问题:要么将本地 feature 与 john/feature 合并,要么将本地 feature 重定向到 john/feature 的顶端。

Merging vs. rebasing onto a remote branch

Note that this rebase doesn’t violate the Golden Rule of Rebasingbecause only your local feature commits are being moved—everything before that is untouched. This is like saying, “add my changes to what John has already done.” In most circumstances, this is more intuitive than synchronizing with the remote branch via a merge commit.
请注意,这种重置并不违反重置的黄金法则,因为只有您本地的 feature 提交被移动,之前的所有提交都不会被移动。这就好比说,"把我的改动添加到 John 已经完成的改动中"。在大多数情况下,这比通过合并提交与远程分支同步更直观。

By default, the git pull command performs a merge, but you can force it to integrate the remote branch with a rebase by passing it the --rebase option.
默认情况下, git pull 命令会执行合并,但你可以通过 --rebase 选项,强制它以 rebase 的方式整合远程分支。

Reviewing a Feature With a Pull Request
使用拉取请求审查功能

If you use pull requests as part of your code review process, you need to avoid using git rebase after creating the pull request. As soon as you make the pull request, other developers will be looking at your commits, which means that it’s a public branch. Re-writing its history will make it impossible for Git and your teammates to track any follow-up commits added to the feature.
如果您将拉取请求作为代码审查流程的一部分,则需要避免在创建拉取请求后使用 git rebase 。一旦你创建了拉取请求,其他开发人员就会查看你的提交,这意味着它是一个公共分支。重写其历史会导致 Git 和你的队友无法跟踪该特性的后续提交。

Any changes from other developers need to be incorporated with git merge instead of git rebase.
任何来自其他开发人员的修改都需要用 git merge 代替 git rebase 。

For this reason, it’s usually a good idea to clean up your code with an interactive rebase before submitting your pull request.
因此,通常在提交拉取请求之前,最好先通过交互式重置来清理代码。

Integrating an Approved Feature
整合已获批准的功能

After a feature has been approved by your team, you have the option of rebasing the feature onto the tip of the master branch before using git merge to integrate the feature into the main code base.
在功能获得团队批准后,您可以选择将功能重定向到 master 分支的顶端,然后再使用 git merge 将功能集成到主代码库中。

This is a similar situation to incorporating upstream changes into a feature branch, but since you’re not allowed to re-write commits in the master branch, you have to eventually use git merge to integrate the feature. However, by performing a rebase before the merge, you’re assured that the merge will be fast-forwarded, resulting in a perfectly linear history. This also gives you the chance to squash any follow-up commits added during a pull request.
这种情况与将上游变更纳入特性分支类似,但由于不允许重写 master 分支中的提交,所以最终必须使用 git merge 来整合特性。不过,如果在合并前执行重置,就能确保合并是快进的,从而实现完美的线性历史。这也为您提供了一个机会,可以压制在拉取请求中添加的任何后续提交。

Integrating a feature into master with and without a rebase

If you’re not entirely comfortable with git rebase, you can always perform the rebase in a temporary branch. That way, if you accidentally mess up your feature’s history, you can check out the original branch and try again. For example:
如果你对 git rebase 并不完全放心,可以在临时分支中执行重置。这样,如果不小心弄乱了特性的历史记录,就可以查看原始分支,然后再试一次。例如

6
1
git checkout feature
2
git checkout -b temporary-branch
3
git rebase -i master
4
# [Clean up the history]
5
git checkout master
6
git merge temporary-branch

Summary 摘要

And that’s all you really need to know to start rebasing your branches. If you would prefer a clean, linear history free of unnecessary merge commits, you should reach for git rebase instead of git merge when integrating changes from another branch.
这就是开始重排分支所需的全部知识。如果你更喜欢干净、线性的历史记录,而不希望出现不必要的合并提交,那么在整合来自其他分支的改动时,你应该选择 git rebase 而不是 git merge 。

On the other hand, if you want to preserve the complete history of your project and avoid the risk of re-writing public commits, you can stick with git merge. Either option is perfectly valid, but at least now you have the option of leveraging the benefits of git rebase.
另一方面,如果您想保留项目的完整历史,避免重写公共提交的风险,您可以坚持使用 git merge 。无论哪种选择都是完全正确的,但至少您现在可以选择利用 git rebase 的优势。

Branch (computer science)
分支(计算机科学)
Commit (data management)
承诺(数据管理)
Git History (command) 历史记录(命令) Command (computing) 指挥(计算) workplace 工作场所 dev 开发 Upstream (software development)
上游(软件开发)

Published at DZone with permission of Tim Pettersen, DZone MVB. See the original article here.
经 DZone MVB Tim Pettersen 许可发布于 DZone。点击此处查看原文。

Opinions expressed by DZone contributors are their own.
DZone 撰稿人的观点仅代表其本人。

Related

  • On Git and Cognitive Load
  • Git: Basic Terms and Commands Explained
  • Top 35 Git Commands With Examples
  • Git Reset HEAD

Partner Resources


Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US 关于我们

  • About DZone 关于 DZone
  • Support and feedback 支持和反馈
  • Community research 社区研究
  • Sitemap 网站地图

ADVERTISE 广告

  • Advertise with DZone 为 DZone 做广告

CONTRIBUTE ON DZONE 在 dzone 上投稿

  • Article Submission Guidelines
    文章提交指南
  • Become a Contributor 成为贡献者
  • Core Program 核心计划
  • Visit the Writers' Zone
    访问作家区

LEGAL 法律

  • Terms of Service 服务条款
  • Privacy Policy 隐私政策

CONTACT US 联系我们

  • 3343 Perimeter Hill Drive
  • Suite 100 100 号套房
  • Nashville, TN 37211 田纳西州纳什维尔 37211
  • support@dzone.com

Let's be friends: 我们做朋友吧

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!