Reputation: 395
I'm trying to merge changes from a patch branch into main. This is the message I see in github:
kewp wants to merge 36 commits into patch/SEO_prices_pages from development
When I click to resolve conflicts this is the message I see
Resolving conflicts between development and patch/SEO_prices_pages and committing changes development
Why is the commit being committed into development
? I am trying to update the patch branch with the development changes...
Upvotes: 4
Views: 2297
Reputation: 488163
There's a basic flaw in the question:
Why does git merge create a commit in source branch
It doesn't. GitHub, on the other hand ...
It's important to define terms here, and to distinguish very clearly between what Git does, and what GitHub does. GitHub is not Git! GitHub will host a Git repository for you, and then they add on their own features, to get you to use their service (instead of some competitor's). So when you use GitHub's add-ons, they may well do things that Git itself does not do. (If you like those things, GitHub are succeeding: remember, their goal is to get you to use them, and ultimately, to get you or someone else to pay them.)
[GitHub tells me]
kewp wants to merge 36 commits into patch/SEO_prices_pages from development
[but there are merge conflicts]
I'll assume here that kewp
is you and that development
is the name you gave GitHub when you sent some commits from your laptop/desktop/whatever computer, to the repository over on GitHub. Then you used GitHub's web interface to generate a GitHub Pull Request (PR), using your development
as the merge-from branch and patch/SEO_price_pages
as the merge-to branch, all within a single repository over on GitHub (so that no extra GitHub fork stuff is involved here).
A GitHub PR is not a Git merge. What GitHub do when you click on the "make PR" buttons does, however, involve attempting a git merge
in a Git repository stored on GitHub. This attempt may either succeed or fail. If it succeeds, the resulting merge commit can be found in the Git on GitHub; if not, there is no such merge commit.
A GitHub PR is assigned a number, unique to that repository on GitHub. (It's a number that is global across all operations within that repository: issues and PRs share the number space, so in a repository with no activity yet, if you create a few dozen issues before creating any PRs, the first PR will have a two-digit number.) This number becomes a Git namespace of the form refs/pull/number
. Within this namespace, GitHub create either one name, or two:
refs/pull/number/head
refers to the tip commit of the branch you asked to merge from; andrefs/pull/number/merge
, if it exists, refers to the merge commit that GitHub successfully made.This merge commit is not (yet) on any branch. If it exists, it exists in the Git repository over at GitHub, and is findable under the merge
name, but the phrase commit C is on branch B in Git is generally interpreted to mean that commit C is reachable from the tip commit of branch B.
(For much more on reachability, see Think Like (a) Git.)
Again, if the merge attempt fails, there is no merge commit here. Since there were merge conflicts in your case, there is a refs/pull/number/head
name, but there is no refs/pull/number/merge
name.
When you use Git on your laptop, you might perform a merge like this:
git checkout patch/SEO_prices_pages
git merge development
If there are conflicts, your Git will stop in the middle of the merge, with the results of the partially-completed merge left in both Git's index and your work-tree. You can now resolve these conflicts, using the stuff Git left behind in its index and your work-tree, any way you like. You then tell Git that you have resolved the conflicts, and use:
git merge --continue
to resume (and finish this time) the merge. The result is a new commit. The new commit is on—and at the tip of—the branch you had checked out, i.e., patch/SEO_prices_pages
. The branch you named in your git merge
command, i.e., development
, is entirely unchanged: that name still holds the same commit hash it held before you started all of this.
The merge resolution process occurred in Git's index, but your assist almost certainly used your files in your work-tree: your computer's non-Git commands can't use the files that are in Git's index, as they're in a special, compressed, Git-only format. To use an index file, you have to copy it out somewhere (typically with git checkout
or git checkout-index
), then work on it there, then copy it back over the old index file (typically with git add
).
The final commit has two parents: its first parent is the commit that was the tip of patch/SEO_prices_pages
a moment ago, and its second parent is the commit that still is the tip of development
.
The Git repositories on GitHub have no work-tree. (Each one does have an index, but it's mostly just vestigial.) This means that the usual tools are just not available.
What GitHub offer, at least today, is a sort of a trick. They save some of the conflict information somewhere—there's only one index and there might be multiple PRs "in flight", so it's not at all clear where, although Git does have the ability to use an alternative index, so perhaps there's an index per PR, though I would guess not—but since there is no work-tree, there is no place to just edit a file and then git add
it again.
Instead, what GitHub do when you use their conflict resolution tool is make more commits. They could make these commits by advancing the refs/pull/number/head
ref, and I think eventually they do advance it, but according to their own information page, they add the new commit—which uses your PR branch's tip commit's files as a starting point, but makes changes that will result in the git merge
not having a conflict—to your branch.
In this case, what this means is that they:
development
;development
, those files would no longer have merge conflicts with the files in the tip commit of patch/SEO_prices_pages
;This is the equivalent of you, on your laptop, doing:
git checkout development
(Note: this assumes your development
matches your GitHub's development
!) and then:
<edit each file that had conflicts>
<git add each such file>
git commit
git push origin development
except of course that by doing this directly with your GitHub repo, you don't get the commit on your laptop (yet).
Now that your GitHub repo development
has this new commit, GitHub can try the git merge
again. This time the merge will succeed and they will be able to create refs/pull/number/merge
.
When you actually are allowed to merge on GitHub, you will see that the green "merge" button has a dropdown arrow. Using the dropdown, you'll see that there are three options:
The first one does just what it says. It uses a normal everyday merge—the one GitHub already made will do just fine—and tacks that on to the target branch as usual.
The second one copies each of the to-be-merged commits to new commits that extend the target branch. GitHub do this even if the to-be-merge commits are already in the right position, graph-wise, to have been fast-forwarded. (I find this obnoxious myself: they should just fast-forward.)
The last one does the equivalent of running git checkout <target>; git merge --squash ...
. It probably uses the tree from the existing merge, by running git commit-tree
on GitHub, but the effect is the same.
Upvotes: 7