【问题标题】:What is the difference between "git reset" vs "git rebase"?“git reset”与“git rebase”有什么区别?
【发布时间】:2012-06-28 19:56:42
【问题描述】:

我一直在玩 git(仍然很菜鸟),我想知道“reset”和“rebase”之间的区别。一个比另一个更强大吗?

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

17a64df 2012-06-21 |你好使用 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 |首次提交

【问题讨论】:

    标签: git


    【解决方案1】:

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

    所以如果你想重写历史,git-rebase 就是你想要的。请注意,您应该永远不要重写已推送并可供其他人使用的历史记录,因为变基会重写对象,使其与旧对象不兼容,从而给其他相关人员造成混乱。

    话虽如此,你想做的是interactive rebasing。使用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),
    

    在那里,只需删除您要删除的提交的行,保存并退出编辑器,Git 就会重写您的历史记录。同样,如果您已经推送了更改,不要这样做。一般来说,在历史记录中有这样的提交是非常好的。

    【讨论】:

    • 正在从变基中删除行,就像将单词“pick”更改为“s”来表示壁球?
    • @Ninjaxor 不,删除行将完全删除提交和它们从历史中引入的更改。就好像从未进行过提交一样。例如,如果您删除添加了一行的提交,那么该行将不会出现在 rebase 之后的任何后续提交中。另一方面,压缩仍然会保留提交中引入的更改,而只是摆脱单独的提交本身。
    【解决方案2】:

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

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

    1. "git reset --hard {commit-id}" 将使用本地历史中的提交。
    2. "git rebase origin/{branch-name}" 将使用 repo 中的最新提交

    其他信息

    什么时候使用重置?

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

    什么时候使用变基?

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

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

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

    【讨论】:

      【解决方案3】:

      虽然“git reset”绝对不是用于从历史记录中删除仅 3 次提交的工具,但我发现它至少在一种情况下非常有用,这似乎没有足够的文档记录并且仍然与所提出的问题相关:

      假设您有一个“environment-X”分支,用于部署到特定环境,除了一些明确定义的更改外,它应该(大多数)反映“主”分支。如果该分支的历史记录由于不正确的 git 使用或其他原因而出现乱码,那么将其重新设置在 master 之上并将其压缩 所有 的非 master 提交可能是一个不错的选择.

      在这种情况下,交互式变基可能会很困难,并且会导致很多冲突,需要一个一个手动修复。

      一个更简单的操作是

      1. 找到共同祖先提交:git merge-base master environment-X
      2. 重置为:git reset $commit(这将使磁盘上的文件保持不变)
      3. 添加并提交修改后的文件 - 作为奖励,这使您有机会验证没有意外更改
      4. 强制推送

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-28
        • 2021-07-04
        • 2011-04-08
        • 2015-01-17
        • 2013-05-15
        • 2020-06-22
        • 2011-09-11
        相关资源
        最近更新 更多