“git reset”与“git rebase”有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11225293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 14:01:46  来源:igfitidea点击:

What is the difference between "git reset" vs "git rebase"?

git

提问by Q10

I have been playing around with git (still very noob) and I wanted to know the difference between "reset" and "rebase". Is the one more powerful than the other?

我一直在玩 git (仍然非常菜鸟),我想知道“重置”和“重新设置”之间的区别。一个比另一个更强大吗?

Say I wanted to delete the 3 commits in bold from the history, which one will be better to use, or should I tag it and then delete it with git tag -d <tagname>?

假设我想从历史记录中删除粗体的 3 个提交,哪个更好用,或者我应该标记它然后用git tag -d <tagname>?

17a64df 2012-06-21 | Hello uses style.css (HEAD, origin/style, master),
a6792e4 2012-06-21 | Added css stylesheet
801e13e 2012-06-21 | Added README
5854339 2012-06-21 | Added index.html
0b1dd4c 2012-06-21 | Moved hello.html to lib
55649c3 2012-06-21 | Add an author/email comment
9b2f3ce 2012-06-21 | Added an author comment
cdb39b0 2012-06-21 | Commit p tags with text (v1.1)
b7b5fce 2012-06-21 | This reverts commit a6faf60631b5fbc6ee79b52a1bdac4c971b69ef8.
a6faf60 2012-06-21 | Revert "Oops, we didn't want this commit"
a006669 2012-06-21 | Oops, we didn't want this commit
262d1f7 2012-06-21 | Added HTML header (v1)
b1846e5 2012-06-21 | Added standard HTML page tags (v1-beta)
bf1131e 2012-06-21 | Added HI TAG
02b86d0 2012-06-21 | First Commit

17a64df 2012-06-21 | Hello 使用 style.css (HEAD, origin/style, master),
a6792e4 2012-06-21 | 添加 css 样式表
801e13e 2012-06-21 | 添加自述文件
5854339 2012-06-21 | 添加 index.html
0b1dd4c 2012-06-21 | 将 hello.html 移动到 lib
55649c3 2012-06-21 | 添加作者/电子邮件评论
9b2f3ce 2012-06-21 | 添加了作者评论
cdb39b0 2012-06-21 | 提交带有文本的 p 标签 (v1.1)
b7b5fce 2012-06-21 | 这将恢复提交 a6faf60631b5fbc6ee79b52a1bdac4c971b69ef8。
a6faf60 2012-06-21 | 回复“糟糕,我们不想要这个提交”
a006669 2012-06-21 | 糟糕,我们不想要这个提交
262d1f7 2012-06-21 | 添加了 HTML 标头 (v1)
b1846e5 2012-06-21 | 添加了标准 HTML 页面标签 (v1-beta)
bf1131e 2012-06-21 | 添加 HI TAG
02b86d0 2012-06-21 | 第一次提交

回答by poke

They are completely different. git-resetworks with refs, on your working directory and the index, without touching any commit objects (or other objects). git-rebaseon the other hand is used to rewrite previously made commit objects.

他们是完全不同的。git-reset在您的工作目录和索引上使用 refs,而无需触及任何提交对象(或其他对象)。git-rebase另一方面用于重写以前制作的提交对象。

So if you want to rewrite the history, git-rebaseis what you want. Note that you should neverrewrite history that was pushed and was available to someone else, as rebasing rewrites the objects making them incompatible with the old objects, resulting in a mess for anyone else involved.

所以如果你想改写历史,git-rebase就是你想要的。请注意,您永远不应该重写已推送并可供其他人使用的历史记录,因为变基会重写对象,使它们与旧对象不兼容,从而导致其他任何人陷入混乱。

That being said, what you want to do is interactive rebasing. Invoke it using git rebase -i 262d1f7and you should get a prompt looking like this:

话虽如此,您想要做的是交互式 rebase。使用它调用它git rebase -i 262d1f7,你应该得到一个如下所示的提示:

pick 262d1f7 Added HTML header (v1)
pick a006669 Oops, we didn't want this commit
pick a6faf60 Revert "Oops, we didn't want this commit"
pick b7b5fce This reverts commit a6faf60631b5fbc6ee79b52a1bdac4c971b69ef8.
pick cdb39b0 Commit p tags with text (v1.1)
pick 9b2f3ce Added an author comment
pick 55649c3 Add an author/email comment
pick 0b1dd4c Moved hello.html to lib
pick 5854339 Added index.html
pick 801e13e Added README
pick a6792e4 Added css stylesheet
pick 17a64df Hello uses style.css (HEAD, origin/style, master),

There, simply delete the lines for the commits you want to remove, save and exit the editor and Git will rewrite your history. Again, don't do thisif you already pushed the changes. In general having such commits in the history is perfectly fine.

在那里,只需删除要删除的提交的行,保存并退出编辑器,Git 将重写您的历史记录。同样,如果您已经推送了更改,请不要这样做。一般来说,在历史上有这样的提交是完全没问题的。

回答by Sydney

I hope this layman explanation is correct.

我希望这个外行的解释是正确的。

Both git reset and git rebase will affect your local branch. They will force your local branch to be in sync with a certain commit. The difference is that:

git reset 和 git rebase 都会影响你的本地分支。它们将强制您的本地分支与某个提交同步。不同之处在于:

  1. "git reset --hard {commit-id}" will use a commit in local history.
  2. "git rebase origin/{branch-name}" will use the latest commit in the repo
  1. “git reset --hard {commit-id}”将使用本地历史中的提交。
  2. "git rebase origin/{branch-name}" 将使用 repo 中的最新提交

Additional Info

附加信息

When to use reset?

什么时候使用重置?

Let's say you finish your work and commit locally. Then your cat walk across the keyboard, and somehow you carelessly commit your cat's work. Use reset.

假设您完成了工作并在本地提交。然后你的猫走过键盘,不知何故,你不小心把猫的工作交给了你。使用复位。

When to use rebase?

什么时候使用rebase?

Let's say you refactor the name of a function/class and this change affect many files. When you commit and try to push to origin, you realized your colleague has make some important changes and already pushed it to origin. Let's say you think refactoring the name again (using an IDE) is easier than going through all the conflict files, you can choose to rebase which will erase your work and keep your colleague's one untouched.

假设您重构了一个函数/类的名称,并且此更改会影响许多文件。当您提交并尝试推送到原点时,您意识到您的同事已经进行了一些重要的更改并且已经将其推送到原点。假设您认为再次重构名称(使用 IDE)比浏览所有冲突文件更容易,您可以选择重新定位,这将删除您的工作并保持您同事的工作不变。

Why is every answer/tutorial contains so much technical disclaimer?

为什么每个答案/教程都包含如此多的技术免责声明?

Because both reset and rebase can delete local changes forever. So users will need to know how to employ strategies (e.g. create a backup branch) to keep their work.

因为 reset 和 rebase 都可以永久删除本地更改。所以用户需要知道如何使用策略(例如创建一个备份分支)来保持他们的工作。