mirror of
https://github.com/LCTT/TranslateProject.git
synced 2024-12-26 21:30:55 +08:00
TSL
This commit is contained in:
parent
067db949bb
commit
ed5ce13ff1
@ -1,80 +0,0 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (The life-changing magic of git rebase -i)
|
||||
[#]: via: (https://opensource.com/article/20/4/git-rebase-i)
|
||||
[#]: author: (Dave Neary https://opensource.com/users/dneary)
|
||||
|
||||
The life-changing magic of git rebase -i
|
||||
======
|
||||
Make everyone think you write perfect code the first time (and make your
|
||||
patches easier to review and merge).
|
||||
![Hands programming][1]
|
||||
|
||||
Software development is messy. So many wrong turns, typos to fix, quick hacks and kludges to correct later, off-by-one errors you find late in the process. With version control, you have a pristine record of every wrong turn and correction made during the process of creating the "perfect" final product—a patch ready to submit upstream. Like the outtakes from movies, they are a little embarrassing and sometimes amusing.
|
||||
|
||||
Wouldn't it be great if you could use version control to save your work regularly at waypoints, and then when you have something you are ready to submit for review, you could hide all of that private drafting work and just submit a single, perfect patch? Meet **git rebase -i**, the perfect way to rewrite history and make everyone think that you produce perfect code the first time!
|
||||
|
||||
### What does git rebase do?
|
||||
|
||||
In case you're not familiar with the intricacies of Git, here is a brief overview. Under the covers, Git associates different versions of your project with a unique identifier, which is made up of a hash of the parent node's unique identifier, and the difference between the new version and its parent node. This creates a tree of revisions, and each person who checks out the project gets their own copy. Different people can take the project in different directions, each starting from potentially different branch points.
|
||||
|
||||
![Master branch vs. private branch][2]
|
||||
|
||||
The master branch in the "origin" repo on the left and the private branch on your personal copy on the right.
|
||||
|
||||
There are two ways to integrate your work back with the master branch in the original repository: one is to use **git merge**, and the other is to use **git rebase**. They work in very different ways.
|
||||
|
||||
When you use **git merge**, a new commit is created on the master branch that includes all of the changes from origin plus all of your local changes. If there are any conflicts (for example, if someone else has changed a file you are also working with), these will be marked, and you have an opportunity to resolve the conflicts before committing this merge commit to your local repository. When you push your changes back to the parent repository, all of your local work will appear as a branch for other users of the Git repository.
|
||||
|
||||
But **git rebase** works differently. It rewinds your commits and replays those commits again from the tip of the master branch. This results in two main changes. First, since your commits are now branching off a different parent node, their hashes will be recalculated, and anyone who has cloned your repository may now have a broken copy of the repository. Second, you do not have a merge commit, so any merge conflicts are identified as your changes are being replayed onto the master branch, and you need to fix them before proceeding with the rebase. When you push your changes now, your work does not appear on a branch, and it looks as though you wrote all of your changes off the very latest commit to the master branch.
|
||||
|
||||
![Merge commits preserve history, and rebase rewrites history.][3]
|
||||
|
||||
Merge commits (left) preserve history, while rebase (right) rewrites history.
|
||||
|
||||
However, both of these options come with a downside: everyone can see all your scribbles and edits as you worked through problems locally before you were ready to share your code. This is where the **\--interactive** (or **-i** for short) flag to **git rebase** comes into the picture.
|
||||
|
||||
### Introducing git rebase -i
|
||||
|
||||
The big advantage of **git rebase** is that it rewrites history. But why stop at just pretending you branched off a later point? There is a way to go even further and rewrite how you arrived at your ready-to-propose code: **git rebase -i**, an interactive **git rebase**.
|
||||
|
||||
This feature is the "magic time machine" function in Git. The flag allows you to make sophisticated changes to revision history while doing a rebase. You can hide your mistakes! Merge many small changes into one pristine feature patch! Reorder how things appear in revision history!
|
||||
|
||||
![output of git rebase -i][4]
|
||||
|
||||
When you run **git rebase -i**, you get an editor session listing all of the commits that are being rebased and a number of options for what you can do to them. The default choice is **pick**.
|
||||
|
||||
* **Pick** maintains the commit in your history.
|
||||
* **Reword** allows you to change a commit message, perhaps to fix a typo or add additional commentary.
|
||||
* **Edit** allows you to make changes to the commit while in the process of replaying the branch.
|
||||
* **Squash** merges multiple commits into one.
|
||||
* You can reorder commits by moving them around in the file.
|
||||
|
||||
|
||||
|
||||
When you are finished, simply save the final result, and the rebase will execute. At each stage where you have chosen to modify a commit (either with **reword**, **edit**, **squash**, or when there is a conflict), the rebase stops and allows you to make the appropriate changes before continuing.
|
||||
|
||||
The example above results in "One-liner bug fix" and "Integrate new header everywhere" being merged into one commit, and "New header for docs website" and "D'oh - typo. Fixed" into another. Like magic, the work that went into the other commits is still there on your branch, but the associated commits have disappeared from your history!
|
||||
|
||||
This makes it easy to submit a clean patch to an upstream project using **git send-email** or by creating a pull request against the parent repository with your newly tidied up patchset. This has a number of advantages, including that it makes your code easier to review, easier to accept, and easier to merge.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/4/git-rebase-i
|
||||
|
||||
作者:[Dave Neary][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[译者ID](https://github.com/译者ID)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/dneary
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming-code-keyboard-laptop.png?itok=pGfEfu2S (Hands programming)
|
||||
[2]: https://opensource.com/sites/default/files/uploads/master-private-branches.png (Master branch vs. private branch)
|
||||
[3]: https://opensource.com/sites/default/files/uploads/merge-commit-vs-rebase.png (Merge commits preserve history, and rebase rewrites history.)
|
||||
[4]: https://opensource.com/sites/default/files/uploads/git-rebase-i.png (output of git rebase -i)
|
@ -0,0 +1,79 @@
|
||||
[#]: collector: (lujun9972)
|
||||
[#]: translator: (wxy)
|
||||
[#]: reviewer: ( )
|
||||
[#]: publisher: ( )
|
||||
[#]: url: ( )
|
||||
[#]: subject: (The life-changing magic of git rebase -i)
|
||||
[#]: via: (https://opensource.com/article/20/4/git-rebase-i)
|
||||
[#]: author: (Dave Neary https://opensource.com/users/dneary)
|
||||
|
||||
完美生活:git rebase -i
|
||||
======
|
||||
|
||||
> 让大家觉得你一次就能写出完美的代码,并让你的补丁更容易审核和合并。
|
||||
|
||||
![Hands programming][1]
|
||||
|
||||
软件开发是混乱的。有很多错误的转折、有需要修复的错别字、有需要修正的错误、有需要稍后纠正临时和粗陋的代码,还有在开发过程中以后发现的错位问题。有了版本控制,在创建“完美”的最终产品(即准备提交给上游的补丁)的过程中,你会有一个记录着每一个错误的转折和修正的原始记录。就像电影中的片段一样,它们有些尴尬,有时还很有趣。就像电影中的花絮一样,它们会让人有点尴尬,有时也会让人觉得好笑。
|
||||
|
||||
如果你能使用版本控制来定期保存你的工作线索,然后当你准备提交审核的东西时,可以隐藏所有这些私人草稿工作,只需提交一份单一的、完美的补丁就可以了,那不是很好吗?`git rebase -i`,是重写历史记录的完美方法,可以让大家觉得你一次就写出了完美的代码。
|
||||
|
||||
### git rebase 的作用是什么?
|
||||
|
||||
如果你不熟悉 Git 的复杂性,这里简单介绍一下。在幕后,Git 将项目的不同版本与唯一标识符关联起来,这个标识符由父节点的唯一标识符的哈希以及新版本与其父节点的差异组成。这样就形成了一棵修订树,每个检出项目的人都会得到自己的副本。不同的人可以把项目往不同的方向发展,每个人的出发点都可能是不同的分支点。
|
||||
|
||||
![Master branch vs. private branch][2]
|
||||
|
||||
*左边是 `origin` 版本库中的主分支,右边是你个人副本中的私有分支。*
|
||||
|
||||
有两种方法可以将你的工作与原始版本库中的主分支整合起来:一种是使用 合并:`git merge`,另一种是使用变基:`git rebase`。它们的工作方式非常不同。
|
||||
|
||||
当你使用 `git merge` 时,会在主分支上创建一个新的提交,其中包括所有来自 `origin` 的修改和所有本地的修改。如果有任何冲突(例如,如果别人修改了你也在修改的文件),则将这些冲突标记出来,并且你有机会在将该“合并提交”提交到本地版本库之前解决这些冲突。当你将更改推送回父版本库时,所有的本地工作都会以分支的形式出现在 Git 仓库的其他用户面前。
|
||||
|
||||
但是 `git rebase` 的工作方式不同。它回滚你的提交,并从主分支的顶端再次重放这些提交。这导致了两个主要的变化。首先,由于你的提交现在从一个不同的父节点分支出来,它们的哈希值会被重新计算,并且任何克隆了你的仓库的人都可能会有一个残破的仓库副本。第二,你没有一个合并提交,所以在将更改重放到主分支上时会识别出任何合并冲突,所以任何合并冲突都会被识别出来,因此,你需要在进行<ruby>变基<rt>rebase</rt></ruby>之前修复它们。当你现在推送你的修改时,你的工作不会出现在分支上,并且看起来像是你把所有的修改都写到了主分支的最新的提交上。
|
||||
|
||||
![Merge commits preserve history, and rebase rewrites history.][3]
|
||||
|
||||
*合并提交(左)保留了历史,而变基(右)重写历史。*
|
||||
|
||||
然而,这两种方式都有一个坏处:在你准备好分享代码之前,每个人都可以看到你在本地处理问题时的所有涂鸦和编辑。这就是 `git rebase` 的 `--interactive`(或简写 `-i`)标志的作用。
|
||||
|
||||
### 介绍 git rebase -i
|
||||
|
||||
`git rebase` 的最大优点是它重写了历史。但是,为什么仅止于假装你从后面的点分支出来呢?有一种更进一步方法可以重写你是如何准备就绪这些代码的:`git rebase -i`,交互式的 `git rebase`。
|
||||
|
||||
这个功能就是 Git 中的 "神奇的时间机器” 功能。这个标志允许你在做变基时对修订历史记录进行复杂的修改。你可以隐藏你的错误! 将许多小的修改合并到一个原始的功能补丁中! 重新排序修改历史记录中的内容
|
||||
|
||||
![output of git rebase -i][4]
|
||||
|
||||
当你运行 `git rebase -i` 时,你会得到一个编辑器会话,其中列出了所有正在被变基的提交,并有一些选项可以对它们做什么。默认的选择是 `pick`。
|
||||
|
||||
* `Pick`:会在你的历史记录中保留该提交。
|
||||
* `Reword`:允许你修改提交信息,可能是修复一个错别字或添加额外的注释。
|
||||
* `Edit`:允许你在重放分支的过程中对提交进行修改。
|
||||
* `Squash`:可以将多个提交合并为一个。
|
||||
* 你可以通过移动文件中的提交来重新排序。
|
||||
|
||||
当你完成后,只需保存最终结果,变基就会执行。在每个阶段,当你选择了修改提交(无论是用 `reword`、`edit`、`squash` 还是有冲突时),变基会停止,并允许你在继续提交之前进行适当的修改。
|
||||
|
||||
上面这个例子的结果是 “One-liner bug fix” 和 “Integate new header everywhere” 被合并到一个提交中,而 “New header for docs website” 和 “D'oh - typo. Fixed” 合并到另一个提交中。就像变魔术一样,其他提交的工作还在你的分支中,但相关的提交已经从你的历史记录中消失了!这样一来,你就可以很容易地提交干净的提交。
|
||||
|
||||
这使得使用 `git send-email` 或者用你新整理好的补丁集在父版本库中创建一个拉取请求来提交一个干净的补丁给上游项目变得很容易。这有很多好处,包括让你的代码更容易审核,更容易接受,也更容易合并。
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
via: https://opensource.com/article/20/4/git-rebase-i
|
||||
|
||||
作者:[Dave Neary][a]
|
||||
选题:[lujun9972][b]
|
||||
译者:[wxy](https://github.com/wxy)
|
||||
校对:[校对者ID](https://github.com/校对者ID)
|
||||
|
||||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||||
|
||||
[a]: https://opensource.com/users/dneary
|
||||
[b]: https://github.com/lujun9972
|
||||
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/programming-code-keyboard-laptop.png?itok=pGfEfu2S (Hands programming)
|
||||
[2]: https://opensource.com/sites/default/files/uploads/master-private-branches.png (Master branch vs. private branch)
|
||||
[3]: https://opensource.com/sites/default/files/uploads/merge-commit-vs-rebase.png (Merge commits preserve history, and rebase rewrites history.)
|
||||
[4]: https://opensource.com/sites/default/files/uploads/git-rebase-i.png (output of git rebase -i)
|
Loading…
Reference in New Issue
Block a user