简体   繁体   中英

Using git, how do I merge the main (upstream) branch into a topic branch but see the differences as if I merged the topic branch into the main branch?

Using git, how do I merge the main (upstream) branch into a topic branch but see the differences as if I merged the topic branch into the main branch?

It is our habit, when a topic branch is ready, to do the merge into the main branch (with git) as a two-stage process:

  1. Merge the main branch into the topic branch. Push the topic branch, which triggers tests on an external test system to check that the application functionality still works as expected.
  2. Merge the topic branch into the main branch. Push the main branch, which triggers the tests again.

The advantage of this is that if there are any problems with the merged version, then they are likely to show up already in the topic branch where they don't bother the other developers yet.

The disadvantage is that when merging the main branch into the topic branch, then the reported differences are those introduced into the main branch by other developers. There can be very many of them, and I wasn't involved in making any of them, so it is difficult for me to verify that the merge did not make any mistakes.

If instead I immediately merge the topic branch into the main branch, without first merging the main branch into the topic branch, then the reported differences are only those introduced by me for the topic branch. Those are fewer in number, and I am intimately familiar with them, so it is a lot easier for me to verify that the merge did not make any mistakes, but then we don't get the advantage of first testing the combination in the context of the topic branch.

I cannot run the tests locally before pushing, so it is not an option to merge the topic branch into the main branch, then test, resolve any problems, and only then push the main branch.

Assuming that the merges go well, it doesn't matter for the final code whether I merge the topic branch into the main branch or the main branch into the topic branch: In both cases I end up with the same code, but associated with different branches.

What I would like is to have the merged code in the topic branch, but to see the differences as if I merged the topic branch into the main branch. What is the most convenient way to do that?

The clunky way is to have two local copies of the repository, with the main branch checked out in one of them and the topic branch checked out in the other one. Merge the topic branch into the main branch in the first repository copy (see only my own diffs -- excellent!), then copy the source code but not the .git directory to the other repository copy, and commit into the topic branch. This is cumbersome and wasteful of disk space.

I also tried merging the topic branch into the main branch (but not pushing!) and then doing a hard reset of the topic branch onto the merge commit in the main branch, but that merely moves the topic branch marker, losing the connection with the previous commits in the topic branch.

EDIT : I moved my own solutions from here to an Answer, 2019-11-29, at the suggestion of a comment.

FIRST PARTIAL SOLUTION, ADDED 2018-01-19

I've found a partial solution to my problem. When I'm in the middle of merging the main branch into the topic branch, then

git diff --stat MERGE_HEAD...

(note the three dots at the end) shows how many lines in which files have changed in the topic branch since the most recent common ancestor with the main branch. Those are the files that would be reported as changed if I instead merged the topic branch into the main branch; those are the files that I changed.

In my merge of the main branch into the topic branch, I can ignore all files that aren't in that list from git diff. Those files to be ignored weren't changed by me, so I do not need to double-check them for merge problems that git cannot detect.

SECOND PARTIAL SOLUTION, ADDED 2018-01-23

This solution is based on a comment that Steve added below this question, with some additions.

  1. Make a new temporary branch on master and merge topic branch into this. Change the commit message to something like "Merge main branch into topic branch", similar to what it would be if you merged the main branch into the topic branch directly. (The default commit message mentions the temporary branch, which we're going to delete shortly, so it will be confusing if the commit message refers to it. Also, the effective merge direction is going to be the reverse of what the default commit message says.)
  2. Switch to the topic branch and merge (fast-forward) the temporary branch into this. Delete the temporary branch. Then push the topic branch to trigger the tests.
  3. merge (probably with --no-ff?) the now tested topic branch into master.

THIRD PARTIAL SOLUTION

And a colleague of mine suggested a third way to reduce the pain: Use a worktree to get a cheap second copy of the main branch without having to clone the entire repository again. Assuming that you're in the main repository directory "repo" with the topic branch checked out:

# create worktree and check out main-branch in it:
git worktree add ../repo-worktree main-branch
cd ../repo-worktree
git merge topic-branch
# (resolve any merge conflicts)
# copy changed files to the main repository:
cp <changed-files> ../repo
cd ../repo    # go to main repository
git add -u    # stage copied files (no new ones!)
git commit -m "merged main branch into topic branch"

# when you don't need the worktree anymore, then
rm -rf ../repo-worktree  # removes worktree
git worktree prune       # removes obsolete worktree administrative files

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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