git master 分支和 'origin/master' 有分歧,如何“undiverge”分支?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2452226/
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
master branch and 'origin/master' have diverged, how to 'undiverge' branches'?
提问by Frank
Somehow my master and my origin/master branch have diverged.
I actually don't want them to diverge.
不知何故,我的 master 和我的 origin/master 分支发生了分歧。
我其实不想让他们分道扬镳。
How can I view these differences and 'merge' them?
如何查看这些差异并“合并”它们?
回答by VonC
You can review the differenceswith a:
您可以使用以下命令查看差异:
git log HEAD..origin/master
before pulling it(fetch + merge) (see also "How do you get git to always pull from a specific branch?")
在拉取它之前(获取 + 合并)(另请参阅“如何让 git 始终从特定分支拉取?”)
When you have a message like:
当您收到以下消息时:
"Your branch and 'origin/master' have diverged, # and have 1 and 1 different commit(s) each, respectively."
“您的分支和 'origin/master' 已经分歧,# 并且分别有 1 和 1 个不同的提交。”
, check if you need to update origin
. If origin
is up-to-date, then some commits have been pushed to origin
from another repo while you made your own commits locally.
,检查是否需要更新origin
。如果origin
是最新的,那么origin
当您在本地进行自己的提交时,一些提交已从另一个存储库推送到。
... o ---- o ---- A ---- B origin/master (upstream work)
\
C master (your work)
You based commit C on commit A because that was the latest work you had fetched from upstream at the time.
您基于提交 A 提交 C,因为这是您当时从上游获取的最新工作。
However, before you tried to push back to origin, someone else pushed commit B.
Development history has diverged into separate paths.
然而,在你尝试推回原点之前,其他人推了提交 B。
开发历史已经分为不同的路径。
You can then merge or rebase. See Pro Git: Git Branching - Rebasingfor details.
然后您可以合并或变基。有关详细信息,请参阅Pro Git:Git 分支 - 变基。
Merge
合并
Use the git merge command:
使用 git merge 命令:
$ git merge origin/master
This tells Git to integrate the changes from origin/master
into your work and create a merge commit.
The graph of history now looks like this:
这告诉 Git 将更改集成origin/master
到您的工作中并创建合并提交。
历史图现在看起来像这样:
... o ---- o ---- A ---- B origin/master (upstream work)
\ \
C ---- M master (your work)
The new merge, commit M, has two parents, each representing one path of development that led to the content stored in that commit.
新的合并提交 M 有两个父项,每个父项代表一条导致存储在该提交中的内容的开发路径。
Note that the history behind M is now non-linear.
请注意,M 背后的历史现在是非线性的。
Rebase
变基
Use the git rebase command:
使用 git rebase 命令:
$ git rebase origin/master
This tells Git to replay commit C (your work) as if you had based it on commit B instead of A.
CVS and Subversion users routinely rebase their local changes on top of upstream work when they update before commit.
Git just adds explicit separation between the commit and rebase steps.
这告诉 Git 重放提交 C(你的工作),就像你基于提交 B 而不是 A 一样
。CVS 和 Subversion 用户在提交之前更新时,通常会在上游工作之上重新调整他们的本地更改。
Git 只是在 commit 和 rebase 步骤之间添加了明确的分离。
The graph of history now looks like this:
历史图现在看起来像这样:
... o ---- o ---- A ---- B origin/master (upstream work)
\
C' master (your work)
Commit C' is a new commit created by the git rebase command.
It is different from C in two ways:
Commit C' 是由 git rebase 命令创建的新提交。
它在两个方面与 C 不同:
- It has a different history: B instead of A.
- Its content accounts for changes in both B and C; it is the same as M from the merge example.
- 它有不同的历史:B 而不是 A。
- 它的内容说明了 B 和 C 的变化;它与合并示例中的 M 相同。
Note that the history behind C' is still linear.
We have chosen (for now) to allow only linear history in cmake.org/cmake.git
.
This approach preserves the CVS-based workflow used previously and may ease the transition.
An attempt to push C' into our repository will work (assuming you have permissions and no one has pushed while you were rebasing).
请注意,C' 背后的历史仍然是线性的。
我们选择(现在)只允许cmake.org/cmake.git
.
这种方法保留了以前使用的基于 CVS 的工作流程,并且可以简化转换。
尝试将 C' 推送到我们的存储库中是可行的(假设您有权限并且在您变基时没有人推送)。
The git pull command provides a shorthand way to fetch from origin and rebase local work on it:
git pull 命令提供了一种从原点获取并在其上重新定位本地工作的速记方法:
$ git pull --rebase
This combines the above fetch and rebase steps into one command.
这将上述 fetch 和 rebase 步骤合并为一个命令。
回答by skiphoppy
I had this and am mystified as to what has caused it, even after reading the above responses. My solution was to do
即使在阅读了上述回复之后,我也有这种情况并且对导致它的原因感到困惑。我的解决方案是做
git reset --hard origin/master
Then that just resets my (local) copy of master (which I assume is screwed up) to the correct point, as represented by (remote) origin/master.
然后这只是将我的(本地)master 副本(我认为它搞砸了)重置到正确的点,如(远程)origin/master 所表示的那样。
WARNING: You will lose all changes not yet pushed to
origin/master
.
警告:您将丢失尚未推送到的所有更改
origin/master
。
回答by asitmoharna
git pull --rebase origin/master
is a single command that can help you most of the time.
是一个可以在大多数情况下为您提供帮助的命令。
Edit:Pulls the commits from the origin/master and applies your changes upon the newly pulled branch history.
编辑:从 origin/master 拉取提交并将您的更改应用于新拉取的分支历史记录。
回答by paneer_tikka
I found myself in this situation when I tried to rebasea branch that was tracking a remote branch, and I was trying to rebase it on master. In this scenario if you try to rebase, you'll most likely find your branch divergedand it can create a mess that isn't for git nubees!
我发现自己在这种情况下,当我试图变基一个分支,正在跟踪远程分支,我试图重订它的主人。在这种情况下,如果您尝试变基,您很可能会发现您的分支出现分歧,并且可能会造成不适合 git nubees 的混乱!
Let's say you are on branch my_remote_tracking_branch, which was branched from master
假设您在分支 my_remote_tracking_branch 上,该分支从 master 分支
$ git status
# On branch my_remote_tracking_branch
nothing to commit (working directory clean)
$ git status
# 在分支 my_remote_tracking_branch
无需提交(工作目录干净)
And now you are trying to rebase from master as:
现在您正在尝试从 master 变基为:
git rebase master
git rebase 大师
STOP NOW and save yourself some trouble! Instead, use merge as:
立即停止,为自己省去一些麻烦!相反,使用合并为:
git merge master
git合并大师
Yes, you'll end up with extra commits on your branch. But unless you are up for "un-diverging" branches, this will be a much smoother workflow than rebasing. See this blogfor a much more detailed explanation.
是的,你最终会在你的分支上得到额外的提交。但是,除非您准备使用“不发散”的分支,否则这将是一个比变基更顺畅的工作流程。有关更详细的解释,请参阅此博客。
On the other hand, if your branch is only a localbranch (i.e. not yet pushed to any remote) you should definitely do a rebase (and your branch will not divergein this case).
另一方面,如果您的分支只是一个本地分支(即尚未推送到任何远程分支),您绝对应该进行 rebase(并且在这种情况下您的分支不会发散)。
Now if you are reading this because you already arein a "diverged" scenario due to such rebase, you can get back to the last commit from origin (i.e. in an un-diverged state) by using:
现在,如果你正在读这篇文章,因为你已经是一个“分歧”的情况,由于这样的底垫中,你可以回到过去的使用从原点(即在未发散状态)承诺:
git reset --hard origin/my_remote_tracking_branch
git reset --hard origin/my_remote_tracking_branch
回答by Darren Cook
In my case here is what I did to cause the divergedmessage: I did git push
but then did git commit --amend
to add something to the commit message. Then I also did another commit.
在我的情况下,这是我为导致发散消息git push
所做的git commit --amend
事情:我做了但后来做了向提交消息添加了一些内容。然后我还做了另一个提交。
So in my case that simply meant origin/master was out of date. Because I knew no-one else was touching origin/master, the fix was trivial: git push -f
(where -f
means force)
所以在我的情况下,这只是意味着 origin/master 已经过时了。因为我知道没有其他人接触过起源/大师,所以修复是微不足道的:(git push -f
其中-f
意味着力)
回答by Laryx Decidua
In my case I have pushed changes to origin/master
and then realised I should not have done so :-( This was complicated by the fact that the local changes were in a subtree. So I went back to the last good commit before the "bad" local changes (using SourceTree) and then I got the "divergence message".
在我的情况下,我已经将更改推送到origin/master
,然后意识到我不应该这样做:-( 由于本地更改位于子树中,这很复杂。所以我回到了“坏”本地之前的最后一次好的提交更改(使用 SourceTree),然后我收到了“分歧消息”。
After fixing my mess locally (the details are not important here) I wanted to "move back in time" the remote origin/master
branch so that it would be in sync with the local master
again. The solution in my case was:
在本地修复我的烂摊子后(这里的细节不重要)我想“及时移动”远程origin/master
分支,以便它master
再次与本地同步。在我的情况下的解决方案是:
git push origin master -f
Note the -f
(force) switch. This deleted the "bad changes" that had been pushed to origin/master
by mistake and now the local and remote branches are in sync.
注意-f
(强制)开关。这删除了origin/master
错误推送的“错误更改”,现在本地和远程分支同步。
Please keep in mind that this is a potentially destructive operation so perform it only if you are 100% sure that "moving back" the remote master in time is OK.
请记住,这是一个潜在的破坏性操作,因此只有在您 100% 确定及时“移回”远程主站是可以的情况下才执行此操作。
回答by Bianca Daniciuc
I know there are plenty of answers here, but I think git reset --soft HEAD~1
deserves some attention, because it let you keep changes in the last local(not pushed) commit while solving the diverged state. I think this is a more versatile solution than pull with rebase
, because the local commit can be reviewed and even moved to another branch.
我知道这里有很多答案,但我认为git reset --soft HEAD~1
值得关注,因为它可以让您在解决分歧状态的同时保留最后一次本地(未推送)提交中的更改。我认为这是一个比 pull with 更通用的解决方案rebase
,因为本地提交可以被甚至移动到另一个分支。
The key is using --soft
, instead of the harsh --hard
. If there is more than 1 commit, a variation of HEAD~x
should work. So here are all the steps that solved my situation (I had 1 local commit and 8 commits in the remote):
关键是用--soft
,而不是苛刻--hard
。如果提交超过 1 次,则HEAD~x
应该使用 的变体。所以这里是解决我的情况的所有步骤(我有 1 个本地提交和 8 个在远程提交):
1)git reset --soft HEAD~1
to undo local commit. For the next steps, I've used the interface in SourceTree, but I think the following commands should also work:
1)git reset --soft HEAD~1
撤销本地提交。在接下来的步骤中,我使用了 SourceTree 中的接口,但我认为以下命令也应该有效:
2)git stash
to stash changes from 1). Now all the changes are safe and there's no divergence anymore.
2)git stash
隐藏 1) 中的更改。现在所有的变化都是安全的,不再有分歧了。
3)git pull
to get the remote changes.
3)git pull
获取远程更改。
4)git stash pop
or git stash apply
to apply the last stashed changes, followed by a new commit, if wanted. This step is optional, along with 2), when want to trash the changes in local commit. Also, when want to commit to another branch, this step should be done after switching to the desired one.
4)git stash pop
或git stash apply
应用上次隐藏的更改,然后根据需要进行新的提交。当想要删除本地提交中的更改时,此步骤与2)一起是可选的。此外,当想要提交到另一个分支时,这一步应该在切换到所需的分支后完成。
回答by C Johnson
To view the differences:
查看差异:
git difftool --dir-diff master origin/master
git difftool --dir-diff master origin/master
This will display the changes or differences between the two branches. In araxis (My favorite) it displays it in a folder diff style. Showing each of the changed files. I can then click on a file to see the details of the changes in the file.
这将显示两个分支之间的变化或差异。在 araxis(我最喜欢的)中,它以文件夹差异样式显示它。显示每个更改的文件。然后,我可以单击文件以查看文件中更改的详细信息。
回答by Mohammad Reza Esmaeilzadeh
In my case this was caused by not committing my conflict resolution.
在我的情况下,这是由于没有提交我的冲突解决方案造成的。
The problem was caused by running the git pull
command. Changes in the origin led to conflicts with my local repo, which I resolved. However, I did not commit them. The solution at this point is to commit the changes (git commit
the resolved file)
问题是由运行git pull
命令引起的。原点的变化导致与我的本地存储库发生冲突,我解决了这个问题。但是,我没有提交它们。此时的解决方案是提交更改(git commit
已解析的文件)
If you have also modified some files since resolving the conflict, the git status
command will show the local modifications as unstaged local modifications and merge resolution as staged local modifications. This can be properly resolved by committing changes from the merge first by git commit
, then adding and committing the unstaged changes as usual (e.g. by git commit -a
).
如果您在解决冲突后还修改了一些文件,则该git status
命令会将本地修改显示为未暂存的本地修改,并将合并解析显示为暂存的本地修改。这可以通过首先提交来自合并的更改 by git commit
,然后像往常一样添加和提交未暂存的更改(例如 by git commit -a
)来正确解决。
回答by LoveForDroid
I had same message when I was trying to edit last commit message, of already pushed commit, using: git commit --amend -m "New message"
When I pushed the changes using git push --force-with-lease repo_name branch_name
there were no issues.
当我尝试编辑已推送的最后提交消息时,我收到了相同的消息,使用:git commit --amend -m "New message"
当我使用推送更改git push --force-with-lease repo_name branch_name
时,没有任何问题。