tl;dr
If you find yourself using cherry-pick
or rebase -i
every time you want to promote changes through a Pull Request, your process and tools configuration are wrong.
Consider using feature branches
Feature (or topic if you read the git scm book) branches that extend from the trunk (master
) are focused and disposable. Not only does this model make Pull Requests and releases easier to understand it's also much easier to manage than keeping 2 or 3 lifetime branches in and out of sync at the appropriate time in the appropriate rhythm.
Be truthful about what needs to be under version control
Having files in one lifetime branch of a repo that are never meant to be brought into the other lifetime branches is a strong indication that those files don't really need to be under version control. While these files may be necessary to develop your product they clearly don't represent real portions of your deliverable. This is exactly the reason the .gitignore
file exists. Setup your .gitignore
file to allow those files to live in the work-space without being tracked.
Implementing the .gitignore
file properly should eliminate the need to do the work that is getting you into merge conflicts in the first place, and using feature branches off one lifetime branch as opposed to 3 lifetime branches will make everything else about implementing DevOps practices for your team and code much easier to understand and maintain.
With that said...
Fixing the general issue of resolving merge conflicts locally
These suggestions are assuming that your PR is trying to put changes from branch_name
into origin\QA
Azure devops (formerly VSTS) is asking you to resolve the merge conflicts locally and push those changes to your PR.
After your step 5. you need a local copy of the PR target branch (I'm guessing QA) from the remote (usually identified as origin
in your local repo).
Once you've done that, get back to branch_name
and run git merge localQA
. This should show you that the merge cannot be completed b/c of the conflicts. Now you need to open the files listed in git status
that are not added to the index and correct the conflict. When the file conflicts are corrected, you can commit the merge and push.
To take a different approach to your current situation
Don't delete all the files in branch_name
and checkout
selectively from master, which I assume represents origin/DEV
. Instead, cut your branch_name
from an up-to-date local copy of origin\QA
. This will get you started with a QA copy of the files you want. Then from that branch you can git checkout master -- fileA etc.
to rewrite those changes into your QA copy. Now you can push the QA copy to origin
and create a PR.
If you're savvy you may have already noticed that this way of doing things is exactly like having a single lifetime branch (QA) that uses PRs to get changes from feature branches. This is because the commits from DEV don't ever actually make it out of DEV.
When you use git checkout <tree-ish> -- [pathspec]
you are not moving a commit you are moving changes. For example..
Say I have a branch master
and create a branch test
for some changes and add a file.

Now, if I create a new branch and use the checkout <tree-ish> -- [pathspec]
you'll see that it is creating a new set of changes for me to commit.

In my example of how you're using version control, if master
represents your origin/QA
and test
represents origin/DEV
, why should I even bother with the test
branch at all if I'm going to create new commit(s) on newTest
that represent the changes made in test
? I (you) sholudn't.
An additional alternative
Use git rebase -i
on your branch to SPLIT THE COMMITS so that the files you want to ignore are in a commit you can ignore. With this approach, you should still create the branch from origin/QA
or whatever your PR target is. Then you can use cherry-pick
on the commit(s) you want from the development branch and use a PR between this branch and the target.
Understand: using Rebase in this way is rewriting the history of your branch. Some would argue this is unwise, so be sure you know what you're doing