简体   繁体   English

在Git中,如何解决冲突后创建分支?

[英]In Git, how to create a branch after resolving conflicts?

I frequently find myself in this situation: 我经常发现自己处于这种情况:

  • pull changes from an upstream repo (implying merge) 从上游存储库中提取更改(暗示合并)
  • the merge causes conflicts 合并导致冲突
  • resolve the conflicts 解决冲突
  • decide to commit not to the current branch but a new one 决定不提交给当前分支,而是提交给新分支

In the last step, I use git checkout -b new-branch-name , but after invoking that command, the current head no longer has references to the pulled changes. 在最后一步中,我使用git checkout -b new-branch-name ,但是在调用该命令后,当前的头部不再引用已拉出的更改。 It only has one parent. 它只有一个父母。 It's no longer a merge. 它不再是合并。

How can I, while performing a merge, commit that merge to a new branch? 在执行合并时,如何将合并提交到新分支?

Personally, I avoid git pull . 就个人而言,我避免git pull By avoiding it, I can first run git fetch , then inspect what's coming in. Having looked, I then use git merge but usually wind up also avoiding this particular mistake in the first place because I can see that the merge might be difficult and start on a new branch in advance. 通过避免它,我可以先运行git fetch ,然后检查进来的内容。看过之后,我接着使用git merge但通常结束时也首先避免了此特定错误,因为我可以看到合并可能很困难并开始提前在新的分支上。

Still, it is useful to be able to recover ... and it's easy! 不过,能够恢复还是很有用的……而且很简单! Just do this, as you did already: 就像您已经做过的那样:

git pull
# oh no, merge conflicts!
# resolve conflicts
git commit                    # or git merge --continue

and commit to the wrong branch, and then fix it up afterward: 并提交到错误的分支,然后再对其进行修复:

git branch new-branch-name    # create new branch to contain the merge
git reset --hard HEAD^1       # back up current branch to first-parent
git checkout new-branch-name  # return to new branch

Diagrammatically, you start with: 以图解方式,您从开始:

    o--o--o   <-- your-branch (HEAD)
   /
...
   \
    o--o--o   <-- origin/your-branch

The conclusion of the merge advances your-branch to point to the new merge commit * you make: 合并的结论使your-branch指向新的合并提交*您进行以下操作:

    o--o--o
   /       \
...         *   <-- your-branch (HEAD)
   \       /
    o--o--o   <-- origin/your-branch

We now add a new branch, pointing to this same merge commit: 现在,我们添加一个分支,指向相同的合并提交:

    o--o--o
   /       \
...         *   <-- your-branch (HEAD), new-branch-name
   \       /
    o--o--o   <-- origin/your-branch

and then use git reset to drag the branch name to which HEAD is attached back one step, in the first-parent direction, which restores it to its previous commit: 然后使用git reset将与HEAD相连的分支名称沿第一个父级方向拖回一个步骤,从而将其恢复为先前的提交:

    o--o--o   <-- your-branch (HEAD)
   /       \
...         *   <-- new-branch-name
   \       /
    o--o--o   <-- origin/your-branch

and we're all set. 我们都准备好了。

All of this relies on a useful principle about Git: Git is really all about commits . 所有这些都依赖于有关Git的有用原理:Git实际上就是关于commit的全部。 The branch names move around all the time; 分支名称一直在移动; they're just how we find the commits. 它们就是我们找到提交的方式。 The commits are permanent (well, as long as we can find them) and unchangeable. 提交是永久性的(只要我们可以找到它们),并且不可更改。 Get the commits the way you like and then you can reshuffle the names at leisure. 以您喜欢的方式获取提交,然后可以随意重新命名

(If HEAD^1 is hard to type for various reasons, note that you can use any of HEAD^ or HEAD~ or even @^ or @~ . That is: (如果由于各种原因很难键入HEAD^1 ,请注意,您可以使用HEAD^HEAD~甚至@^@~ 。即:

  • HEAD and @ are synonyms. HEAD@是同义词。
  • The ^1 and ^ without 1, as suffixes, are synonyms: the 1 is implied if you omit it. 后缀^1^不带1,是同义词:如果省略,则暗指1
  • The ~1 and ~ without 1, as suffixes, are synonyms: the 1 is implied if you omit it. ~1~不带1作为后缀,是同义词:如果省略,则暗含1
  • While ^ and ~ do different things, both mean "go back some number of steps in the graph". 尽管^~做不同的事情,但是它们的意思都是“返回图中的一些步骤”。

The number after the ^ is the parent-number and is meaningful only for merge commits: 1 means first parent . ^之后的数字是父代数字,仅对合并提交有意义: 1表示第一个父代 So HEAD^1 means first parent of HEAD , and HEAD~1 means go back one first-parent . 所以HEAD^1手段的第一个父HEAD ,和HEAD~1手段回到一个第一-父母 Applying all the synonym rules is what gives us the @^ and @~ constructs.) 应用所有同义词规则是给我们@^@~构造的原因。)

Use a non-committing merge, change branch, commit there 使用非提交合并,更改分支,在此提交

git checkout <yourbranch>
git fetch
git merge --no-commit origin/<yourbranch>

# if conflicts : resolve conflicts then

git checkout -b <newbranch>

# if NO conflicts, just

git add path/to/relevant/files
git commit

Answering a slightly different question - if you've already used git checkout -b new-branch to create the branch, your merge isn't completely lost. 回答一个稍有不同的问题-如果您已经使用git checkout -b new-branch创建分支,则合并不会完全丢失。 Here's how I recovered: First, stash the changes. 这是我恢复的方式:首先,存储更改。 Then re-run the merge using strategy=ours , then re-apply the stashed changes and commit. 然后使用strategy=ours重新运行合并,然后重新应用隐藏的更改并提交。

git merge upstream/master
# resolve conflicts
git checkout -b new-branch
# oh, noes! merge lost.
git stash
git merge upstream/master --no-commit --strategy=ours
git stash pop
git commit

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM