回滚远程 git 回购但维护本地更改

Rolling back remote git repo but maintaining local changes

一位合作者本应推送到一个单独的分支,但却向回购的 master 提交了大约 60 次。他现在对该分支进行了哈希处理。我需要:

  1. 还原他的更改
  2. 理想情况下,将他所做的更改推送到单独的分支
  3. 提交并推送我在 master 分支上所做的本地更改

如何在 git / sourcetree 中执行此操作而不丢失我拥有的本地更新?

我不知道在 sourcetree 中执行此操作的等效步骤,但这是从终端执行此操作的方法。希望您可以在 sourcetree 中复制这些步骤。

要完成这些任务,您将使用 git reset --hardgit push -f。您将需要确保您的遥控器允许非快进推送(防止非快进推送的设置在您遥控器的 .git/config 文件中 [receive] > denyNonFastforwards = true 下。只需将其设置为 'false' 在你修理东西的时候临时)

  1. 克隆遥控器
    • git clone <url> <fix-the-repo>
  2. 配备了 master 应该具备的 SHA:
    • cd <fix-the-repo>
  3. 创建您的协作者应该推送到的功能分支
    • git checkout master
    • git branch feature(master 和 feature 现在指向同一个 commit-id)
  4. 将 master 重置为它应该的样子
    • git reset --hard <SHA>
  5. 将更新的分支指针推送到远程
    • git push -f origin master
    • git push origin feature
  6. 转到您的本地存储库
    • cd <local-repo>
  7. 获取遥控器以确保一切正常
    • git fetch origin(您应该会看到有关强制更新 master 分支的消息)
    • git log --oneline --decorate --graph --all
  8. 推送您的本地更改
    • git push origin master

哇哦!

如果你能直接登录服务器,你就可以在那里轻松解决所有问题,但你必须了解一些Git的内幕。

如果没有,最好的办法是使用临时存储库(即新的 git clone)或临时工作树(即 git worktree add,假设您的 Git至少版本 2.6 左右)在您控制的具有推送访问权限的机器上。这根本不需要任何特殊的 Git 专业知识,但如果您正在使用 git worktree add,您将不需要在您的 master 分支上(即,如果您在您的内部工作自己的分支,你在这里很好)。

要使用新的临时克隆,运行 git clone 像往常一样(在新目录中创建新克隆)。然后 chdir (cd) 像往常一样进入新的克隆。你应该在 master;如果不是,运行 git checkout master。你的 master 将匹配 origin/master 因为这是一个新的克隆。

要使用临时工作树,运行 git add worktree ../fix master 来自常规工作树的顶层。 Chdir 进入新的工作树,它现在在你自己的 master 分支上。 运行 git fetch origin && git reset --hard origin/master 更新您的 master 以匹配 origin/master.

现在您的 master 已与其他人的 master 同步,后者应该是其他分支,创建他应该创建的分支:git checkout -b feature 或其他。然后像往常一样将新分支推送到服务器。

接下来,按原样设置 master。在这里你有两个选择:你可以使用 git reset --hard 回滚他的所有更改,这很好,只要你能让你自己、他和任何其他获得他的更改的人同样回滚。 (对于 you,如果您将自己的存储库与临时工作树一起使用,则此回滚是完全自动的。)或者,您可以创建一个 new 提交给使用他应该留在原地的树的主人。无论哪种方式,您都必须确定要恢复的提交。

做前者,运行git reset --hard <commit-hash>。要执行后者,运行 git rm -rf . && git checkout <commit-hash> -- . && git commit(注意这里有多余的点)。前者倒带master,删除提交;后者创建一个新的提交,它与之前的提交具有相同的树(这就是为什么我们首先删除所有内容,然后检查之前提交的所有内容)。

现在,对于后一种情况,您可以照常 git push origin master。对于前一种 (git reset) 情况,您必须 git push --force origin master.

--force 方法的危险在于,正在推送到 master 的其他用户可能会在您执行所有这些操作时进行更改;您将失去 他们的 也会更改。但是由于现在情况不佳,您应该确保没有其他人进行这些更改。)

您现在已完成或基本完成:您可以删除克隆或临时工作树。如果您使用了克隆 并且 使用了 "reset master" 方法,您可能还需要重置您自己的存储库的 master,如果您选择了其他人的提交并将它们合并到您自己的克隆中(不是临时克隆的那个)。如果你只是添加了一个新的提交来修复他的错误,那么你一直都很好。

这相对简单明了。

  1. 创建一个临时分支,指向 master 应该 的分支。例如,如果你有最新的 master except 错误提交版本,你会 运行:

    git branch tmpMaster origin/master
    ## Or
    git branch tmpMaster sha_of_good_master
    
  2. 获取他们对 master 所做的更改

    git fetch --all
    
  3. 将他们的更改推送到新分支

    git push origin origin/master:newBranch
    
  4. 强推应该掌握的东西。

    git push --force origin tmpMaster:master
    

如果我对您的问题的理解正确,您可以执行以下操作:

要保持​​您当前的未提交 更改(如果有):

  • 收藏它们以备后用:
git stash

要保存他的更改:

  • 使用他的更改创建一个新的本地分支:
git checkout -b BRANCH_NAME
  • (可选)将他的更改推送到 github:
git push origin BRANCH_NAME


现在他的更改在新的远程分支上是安全的。


要还原主服务器上的更改:

  • 回到master分支:
git checkout master
  • 将 master 重置为更改前的提交:
git reset --hard COMMIT_HASH
  • 推送更新的分支:
git push -f origin master


您可能需要检查您的 .git/config 文件中的 denyNonFastforwards 标志是否设置为 true(您可以将其更改为 false 并在之后撤消)。


要取回您之前隐藏的更改:

  • 应用最后的存储:
git stash apply

就是这样!