Git: 如何撤销本地提交和添加文件?

Git: How to undo local commits and addition of file?

我错误地将文件添加到 master 并且也提交了。否则我必须在一个分支 feature_x

现在我知道有像git reset这样的命令了。我的问题是,如果我重置东西,它是否也会撤消我的代码或只是撤消文件并在 master 中提交?

如何避免在不丢失代码的情况下进行重置?

更新

代码还没有推送到远程。当我尝试时出现错误:

error: src refspec feature_x does not match any.

我通常使用:

git reset --soft HEAD^

如果我不确定我是否会删除我的提交。

它会让你回到暂存阶段。

好吧,我不知道我头顶的命令行方式,但大多数 git 客户端都有一个名为丢弃的按钮。在 sourcetree 中,这是你手环上的第 3 个按钮,这将丢弃任何本地更改,如果你已经提交了更改,请恢复它们。

如果你想从不同的分支推送你的代码,你不需要恢复你的提交。

  • 只需拉取 master 分支并从 master 创建新分支
  • 之后推送你的分支并创建一个合并请求
  • 合并您的代码
  • 拉主到本地

应该可以。

你目前在 master 分支上,意外提交了 X、Y 和 Z,如下所示:

A - B - C - X - Y - Z  <- master

现在您可以在当前使用的地方创建一个新分支

git branch feature-x

feature-x 分支将指向与 master 分支相同的提交,从而可以安全地将 master 分支重置为早期版本:

git reset --hard HEAD~3    # Move master branch 3 commits back

你现在有了这个

          X - Y - Z  <- feature-x
         /
A - B - C  <- master

现在您可以再次签出 feature-x 分支:

git checkout feature-x

如果我没理解错的话,您在 master 分支上提交了您不希望在 master 分支上提交的内容,但您仍然希望保持不变。您希望在分支 feature_x 上提交这些提交,而不是在 master 上。我假设你想要在 feature_x 而不是 master 上的提交是 master 上的最后一次提交,因此它们之间没有你想在 master 上保留的提交。

重要的是要知道,在 git 中,它 不是 内部提交 属性 在它创建的分支上。分支只是指代特定修订版的命名指针(与标签类似),如果在该分支是签出分支时提交它(与标签不同),它会自动移动到新修订版。

因此,

如果分支 feature_x 还不存在

  1. 如果您有想要保留的未提交更改(是否已添加到索引),请暂时保留它们并让它们远离

    git stash
    
  2. 转到master分支

    git checkout master
    
  3. 创建分支 feature_x 指向与 master 相同的提交

    git branch feature_x
    

    (除了 git checkout -b feature_x,这将保持 master 签出,而不是切换到新创建的 feature_x

  4. 在继续之前,请确保
    • none 以上命令失败或产生任何意外输出
    • master仍然是签出的分支
  5. 现在,让我们将 master 分支移动到您希望在 master 上的 最后一个 提交。

    如果那是 bitbucket 的 master 指向的提交,并且您将 bitbucket 存储库作为本地存储库中的远程 origin(使用 git remote -v 查找),则执行此操作如下:

    • 确保有关遥控器的本地存储库知识是最新的:

      git fetch
      
    • 将当前签出的分支(您的本地 master 分支)移动到远程 master 分支指向的提交:

      git reset --hard origin/master
      

    但是,如果在 master 上您不想要的提交之前,master 上还有一些您希望在 master 上继续的提交,但那些不是还存在于您的 bitbucket 存储库中,那么从您当前的本地 master 分支向后导航可能会更容易。比如说,你不想让 master 上的最后 5 次提交不在那里,而且它们是纯线性的(它们之间没有合并),你可以

    git reset --hard master~5
    

    如果情况比这更复杂(例如,在 master 上有你不想要的历史部分的合并),找出最后一个的 ID(sha1 哈希)会更容易在图形工具的帮助下提交你想要的 master,然后将 `master 移动到那个

    git reset --hard <commit id>
    

    例如,如果提交 ID 是 a1b2c3d4

    git reset --hard a1b2c3d4
    

如果分支feature_x已经存在...

... 并指向 master

的祖先

按上述步骤进行,但在第 1 步和第 2 步之间(即,在您签出 master 之前),将 feature_x 向前移动到当前 master

git checkout feature_x
git merge --ff-only master

并跳过第 3 步(创建分支 feature_x)。

... 并且有不在 master

上的提交

但是你想继续 feature_x 以及来自 master 的相关提交,那么你有几种可能性。

最简单和最安全的方法是将来自 master 的提交合并到 feature_x,再次在步骤 1 和 2 之间(即,在您签出 master 之前):

git checkout feature_x
git merge master  # You might want to modify the suggested commit message,
                  # as 'merge master into feature_x' will be confusing when
                  # those commits won't be ancestors of 'master' later on.

然后再次从第2步开始执行上述操作,跳过第3步。

如果你想要 feature_x 上的线性历史记录,可以选择将来自 master 的提交重新设置在 feature_x 上的提交之上(这样就好像你已经提交了它们一样feature_x 开始于 已经存在的提交之后)或者将 feature_x 的提交重新定位在 master 的提交之上(因此它将就好像之前在 master 上的提交已经在 feature_x 上提交,甚至在 之前 提交已经在那里)。 如果线性历史不是必须的,我建议不要使用这两种选择,因为变基会变得有点棘手并且需要对 git 有很好的理解。如果你仍然追求其中之一,请确保你知道你在做什么(阅读你使用的命令的帮助页面)并且你做的是正确的(确保你已经理解那些帮助页面并尽量避免打字错误)。尤其是第一次变基时(但后来也是),可能值得在本地克隆你的存储库,这样如果出现问题你就有备份。