如何将多个 Git 提交(已推送)恢复到已发布的存储库?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10780228/
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
How can I revert multiple Git commits (already pushed) to a published repository?
提问by MEM
New to git, and already messing up.
git 新手,已经搞砸了。
I've commited and pushed some changes to a remote dev machine. I need to recover an older version, but keep the "bad progress" doing so far to keep working on a separate branch;
我已经提交并将一些更改推送到远程开发机器。我需要恢复旧版本,但要保持“糟糕的进展”,以便继续在单独的分支上工作;
I was thinking doing it like this:
我想这样做:
- Create a local branchnamed: "tested-thing"
- Revert local repositoryto the state where it worked (hopefully meaningful commits will help);
Push to remote
finish tests on tested-thing
- Merge"tested-thing" into dev
- Push to remote
- 创建一个名为:“tested-thing”的本地分支
- 将本地存储库恢复到它工作的状态(希望有意义的提交会有所帮助);
推送到远程
完成对被测物的测试
- 将“测试过的东西”合并到开发中
- 推送到远程
Between steps 3 and 5 other developers may commit and push, and I'm afraid this may result on a "merge tragedy" - Anyway, may this be a proper way to go ?
在第 3 步和第 5 步之间,其他开发人员可能会提交和推送,我担心这可能会导致“合并悲剧”——无论如何,这可能是一个正确的方法吗?
UPDATE:
更新:
The main problem here resides on 2)
这里的主要问题在于 2)
Here, on topic: "breaking work into a topic branch" http://learn.github.com/p/undoing.html
在这里,关于主题:“将工作分解为主题分支” http://learn.github.com/p/undoing.html
They suggest:
他们建议:
- $ git branch test
- $ git reset --hard a6b4c974
- $ git 分支测试
- $ git reset --hard a6b4c974
By doing so, other developers could still:
通过这样做,其他开发人员仍然可以:
$ git commit
(on the dev branch)
$ git commit
(在开发分支上)
and I can checkout to testand work it out until mergetime.
我可以结帐以测试并解决它,直到合并时间。
Despite all your options, this feels like to be a nice approach to follow. However, it's not stated if this can be done after we have pushed ?
尽管您有所有选择,但这感觉是一种很好的遵循方法。但是,没有说明是否可以在我们推送后完成?
Please note the following: Since I made those changes and I mess up the all thing, no one else have worked on the repository so far. So, if I revert the working directory, no one will notice.
请注意以下事项:由于我进行了这些更改并且搞砸了所有事情,因此到目前为止没有其他人在存储库上工作。所以,如果我恢复工作目录,没有人会注意到。
回答by Todd A. Jacobs
The Problem
问题
There are a number of work-flows you can use. The main point is not to break history in a published branch unless you've communicated with everyone who might consume the branch and are willing to do surgery on everyone's clones. It's best not to do that if you can avoid it.
您可以使用多种工作流程。重点是不要破坏已发布分支中的历史,除非您已与可能使用该分支并愿意对每个人的克隆进行手术的每个人进行了交流。如果可以避免,最好不要这样做。
Solutions for Published Branches
已发布分支的解决方案
Your outlined steps have merit. If you need the dev branch to be stable right away, do it that way. You have a number of tools for Debugging with Gitthat will help you find the right branch point, and then you can revert all the commits between your last stable commit and HEAD.
您概述的步骤是有价值的。如果您需要立即稳定 dev 分支,请这样做。您有许多使用 Git进行调试的工具,它们将帮助您找到正确的分支点,然后您可以恢复上次稳定提交和 HEAD 之间的所有提交。
Either revert commits one at a time, in reverse order, or use the <first_bad_commit>..<last_bad_commit>
range. Hashes are the simplest way to specify the commit range, but there are other notations. For example, if you've pushed 5 bad commits, you could revert them with:
要么以相反的顺序一次还原一次提交,要么使用<first_bad_commit>..<last_bad_commit>
范围。哈希是指定提交范围的最简单方法,但还有其他表示法。例如,如果您推送了 5 个错误提交,您可以使用以下命令还原它们:
# Revert a series using ancestor notation.
git revert --no-edit dev~5..dev
# Revert a series using commit hashes.
git revert --no-edit ffffffff..12345678
This will apply reversed patches to your working directory in sequence, working backwards towards your known-good commit. With the --no-editflag, the changes to your working directory will be automatically committed after each reversed patch is applied.
这将按顺序将反向补丁应用到您的工作目录,向后向您的已知良好提交工作。使用--no-edit标志,在应用每个反向补丁后,将自动提交对工作目录的更改。
See man 1 git-revert
for more options, and man 7 gitrevisions
for different ways to specify the commits to be reverted.
有关man 1 git-revert
更多选项以及man 7 gitrevisions
指定要还原的提交的不同方式,请参阅。
Alternatively, you can branch off your HEAD, fix things the way they need to be, and re-merge. Your build will be broken in the meantime, but this may make sense in some situations.
或者,您可以从 HEAD 分支,按照需要的方式修复问题,然后重新合并。在此期间,您的构建将被破坏,但这在某些情况下可能是有意义的。
The Danger Zone
危险地带
Of course, if you're absolutely surethat no one has pulled from the repository since your bad pushes, and if the remote is a bare repository, then you can do a non-fast-forward commit.
当然,如果您绝对确定自从您的错误推送以来没有人从存储库中提取,并且远程是一个裸存储库,那么您可以进行非快进提交。
git reset --hard <last_good_commit>
git push --force
This will leave the reflog intact on your system and the upstream host, but your bad commits will disappear from the directly-accessible history and won't propagate on pulls. Your old changes will hang around until the repositories are pruned, but only Git ninjas will be able to see or recover the commits you made by mistake.
这将使您的系统和上游主机上的 reflog 保持完整,但您的错误提交将从可直接访问的历史记录中消失,并且不会在拉取时传播。您的旧更改将一直存在,直到存储库被修剪,但只有 Git 忍者才能看到或恢复您错误提交的提交。
回答by AD7six
If you've already pushed things to a remote server (and you have other developers working off the same remote branch) the important thing to bear in mind is that you don't want to rewrite history
如果您已经将内容推送到远程服务器(并且您有其他开发人员在同一个远程分支上工作),那么要记住的重要一点是您不想重写历史记录
Don't use git reset --hard
不要使用 git reset --hard
You need to revert changes, otherwise any checkout that has the removed commits in its history will add them back to the remote repository the next time they push; and any other checkout will pull them in on the next pull thereafter.
您需要还原更改,否则任何在其历史记录中删除提交的检出都会在下次推送时将它们添加回远程存储库;并且任何其他结帐都会在此后的下一次拉动中将它们拉入。
If you have notpushed changes to a remote, you can use
如果您尚未将更改推送到远程,则可以使用
git reset --hard <hash>
If you havepushed changes, but are sure nobody has pulled them you can use
如果您有推变化,但肯定没有人把他们拉到你可以使用
git reset --hard
git push -f
If you havepushed changes, and someone has pulled them into their checkout you can still do it but the other team-member/checkout would need to collaborate:
如果你已经被推变化,有人拉他们到他们的结账你仍然可以做到这一点,但其他团队成员/结帐需要协作:
(you) git reset --hard <hash>
(you) git push -f
(them) git fetch
(them) git reset --hard origin/branch
But generally speaking that's turning into a mess. So, reverting:
但总的来说,这变得一团糟。所以,回归:
The commits to remove are the lastest
要删除的提交是最新的
This is possibly the most common case, you've done something - you've pushed them out and then realized they shouldn't exist.
这可能是最常见的情况,你做了一些事情——你把它们推出来然后意识到它们不应该存在。
First you need to identify the commit to which you want to go back to, you can do that with:
首先,您需要确定要返回的提交,您可以这样做:
git log
just look for the commit before your changes, and note the commit hash. you can limit the log to the most resent commits using the -n
flag: git log -n 5
只需在更改之前查找提交,并注意提交哈希。您可以使用以下-n
标志将日志限制为最重发的提交:git log -n 5
Then reset your branch to the state you want your other developers to see:
然后将您的分支重置为您希望其他开发人员看到的状态:
git revert <hash of first borked commit>..HEAD
The final step is to create your own local branch reapplying your reverted changes:
最后一步是创建您自己的本地分支,重新应用您已恢复的更改:
git branch my-new-branch
git checkout my-new-branch
git revert <hash of each revert commit> .
Continue working in my-new-branch
until you're done, then merge it in to your main development branch.
继续工作my-new-branch
直到完成,然后将其合并到您的主要开发分支。
The commits to remove are intermingled with other commits
要删除的提交与其他提交混合在一起
If the commits you want to revert are not all together, it's probably easiest to revert them individually. Again using git log
find the commits you want to remove and then:
如果您要还原的提交不是全部在一起,那么单独还原它们可能是最简单的。再次使用git log
找到要删除的提交,然后:
git revert <hash>
git revert <another hash>
..
Then, again, create your branch for continuing your work:
然后,再次创建您的分支以继续您的工作:
git branch my-new-branch
git checkout my-new-branch
git revert <hash of each revert commit> .
Then again, hack away and merge in when you're done.
再一次,当你完成后,砍掉并合并。
You should end up with a commit history which looks like this on my-new-branch
你应该最终得到一个看起来像这样的提交历史 my-new-branch
2012-05-28 10:11 AD7six o [my-new-branch] Revert "Revert "another mistake""
2012-05-28 10:11 AD7six o Revert "Revert "committing a mistake""
2012-05-28 10:09 AD7six o [master] Revert "committing a mistake"
2012-05-28 10:09 AD7six o Revert "another mistake"
2012-05-28 10:08 AD7six o another mistake
2012-05-28 10:08 AD7six o committing a mistake
2012-05-28 10:05 Bob I XYZ nearly works
Better way?
更好的方法?
Especially that now that you're aware of the dangers of several developers working in the same branch, consider using feature branches alwaysfor your work. All that means is working in a branch until something is finished, and only then merge it to your main branch. Also consider using tools such as git-flowto automate branch creation in a consistent way.
尤其是现在您已经意识到在同一分支中工作的多个开发人员的危险性,请考虑始终将功能分支用于您的工作。所有这一切都意味着在一个分支中工作,直到某些事情完成,然后才将其合并到您的主分支。还可以考虑使用git-flow等工具以一致的方式自动创建分支。
回答by Sireesh Yarlagadda
git revert HEAD -m 1
In the above code line. "Last argument represents"
在上面的代码行中。“最后一个参数代表”
- 1 - reverts one commits. 2 - reverts last commits. n - reverts last n commits
- 1 - 还原一次提交。2 - 恢复上次提交。n - 恢复最后 n 次提交
or
或者
git reset --hard siriwjdd
git reset --hard siriwjdd