回滚远程 git 回购但维护本地更改
Rolling back remote git repo but maintaining local changes
一位合作者本应推送到一个单独的分支,但却向回购的 master
提交了大约 60 次。他现在对该分支进行了哈希处理。我需要:
- 还原他的更改
- 理想情况下,将他所做的更改推送到单独的分支
- 提交并推送我在
master
分支上所做的本地更改
如何在 git / sourcetree 中执行此操作而不丢失我拥有的本地更新?
我不知道在 sourcetree 中执行此操作的等效步骤,但这是从终端执行此操作的方法。希望您可以在 sourcetree 中复制这些步骤。
要完成这些任务,您将使用 git reset --hard
和 git push -f
。您将需要确保您的遥控器允许非快进推送(防止非快进推送的设置在您遥控器的 .git/config 文件中 [receive] > denyNonFastforwards = true 下。只需将其设置为 'false' 在你修理东西的时候临时)
- 克隆遥控器
git clone <url> <fix-the-repo>
- 配备了 master 应该具备的 SHA:
cd <fix-the-repo>
- 创建您的协作者应该推送到的功能分支
git checkout master
git branch feature
(master 和 feature 现在指向同一个 commit-id)
- 将 master 重置为它应该的样子
git reset --hard <SHA>
- 将更新的分支指针推送到远程
git push -f origin master
git push origin feature
- 转到您的本地存储库
cd <local-repo>
- 获取遥控器以确保一切正常
git fetch origin
(您应该会看到有关强制更新 master 分支的消息)
git log --oneline --decorate --graph --all
- 推送您的本地更改
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
,如果您选择了其他人的提交并将它们合并到您自己的克隆中(不是临时克隆的那个)。如果你只是添加了一个新的提交来修复他的错误,那么你一直都很好。
这相对简单明了。
创建一个临时分支,指向 master 应该 的分支。例如,如果你有最新的 master except 错误提交版本,你会 运行:
git branch tmpMaster origin/master
## Or
git branch tmpMaster sha_of_good_master
获取他们对 master 所做的更改
git fetch --all
将他们的更改推送到新分支
git push origin origin/master:newBranch
强推应该掌握的东西。
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
就是这样!
一位合作者本应推送到一个单独的分支,但却向回购的 master
提交了大约 60 次。他现在对该分支进行了哈希处理。我需要:
- 还原他的更改
- 理想情况下,将他所做的更改推送到单独的分支
- 提交并推送我在
master
分支上所做的本地更改
如何在 git / sourcetree 中执行此操作而不丢失我拥有的本地更新?
我不知道在 sourcetree 中执行此操作的等效步骤,但这是从终端执行此操作的方法。希望您可以在 sourcetree 中复制这些步骤。
要完成这些任务,您将使用 git reset --hard
和 git push -f
。您将需要确保您的遥控器允许非快进推送(防止非快进推送的设置在您遥控器的 .git/config 文件中 [receive] > denyNonFastforwards = true 下。只需将其设置为 'false' 在你修理东西的时候临时)
- 克隆遥控器
git clone <url> <fix-the-repo>
- 配备了 master 应该具备的 SHA:
cd <fix-the-repo>
- 创建您的协作者应该推送到的功能分支
git checkout master
git branch feature
(master 和 feature 现在指向同一个 commit-id)
- 将 master 重置为它应该的样子
git reset --hard <SHA>
- 将更新的分支指针推送到远程
git push -f origin master
git push origin feature
- 转到您的本地存储库
cd <local-repo>
- 获取遥控器以确保一切正常
git fetch origin
(您应该会看到有关强制更新 master 分支的消息)git log --oneline --decorate --graph --all
- 推送您的本地更改
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
,如果您选择了其他人的提交并将它们合并到您自己的克隆中(不是临时克隆的那个)。如果你只是添加了一个新的提交来修复他的错误,那么你一直都很好。
这相对简单明了。
创建一个临时分支,指向 master 应该 的分支。例如,如果你有最新的 master except 错误提交版本,你会 运行:
git branch tmpMaster origin/master ## Or git branch tmpMaster sha_of_good_master
获取他们对 master 所做的更改
git fetch --all
将他们的更改推送到新分支
git push origin origin/master:newBranch
强推应该掌握的东西。
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
就是这样!