2

We're using posh-git on Windows Powershell for source control.

We're in the unenviable position of storing some of our built assemblies in our git repo. I know all the sermons on why you shouldn't do that, but we have to live with it for now. Thankfully they are in a separate solution, but sometimes two people work on that solution in their own branch simultaneously, and the last one in gets to take the merge conflict. The process, of course, looks something like this:

  1. Person A lands their changes on develop.
  2. Person B merges those changes, which include both assemblies and update source code.
  3. Person B resolves conflicts, as has to confirm which version of each assembly they want to keep. This is annoying and time-consuming, and also unnecessary since Person B will rebuild the assembly after merging the source code anyway.
  4. Person B rebuilds the assemblies and makes a new commit to finish the merge.

The assemblies are in a folder in our Repo: /Source/Foundation Assemblies/

Person B cannot just take all changes from the remote, since their branch may have conflicting changes, but it would be helpful to just "take theirs" or "take mine" for the /Source/Foundation Assemblies/ folder only. Is this something that can be done with git?

A command line example would be helpful. Normally, the merge would just be:

git merge develop

I was thinking it might be possible to .gitignore the /Source/Foundation Assemblies/ folder, and then remove it from the .gitignore after the merge, but that is three steps. If we could do it in one from the command line, that would be GREAT!!!

Any help appreciated!

bopapa_1979
  • 8,949
  • 10
  • 51
  • 76

3 Answers3

2

You can do git merge develop -X theirs, and all conflicts will take the remote branch's copies.

Edit: Looking back over your question I see that you only want to take "theirs" for a particular subfolder. In that case, after git merge develop, do git checkout --theirs /Source/Foundation Assemblies/. This will replace the contents of that folder with "theirs". Then just git add /Source/Foundation Assemblies/ and you are good to go.

David Deutsch
  • 17,443
  • 4
  • 47
  • 54
  • This looks like the right thing, but it doesn't make any actual changes. I'm looking at exactly the same git status both before and after: C:\Src\Repos\Estream\Source [crosstrack-69-63284-ssrs-reports +162 ~711 -127 !109 | +0 ~0 -0 !109]>. The command I ran was: git checkout --theirs '.\Foundation Assemblies' I have tried about every variation to correctly denote "Foundation Assemblies," too. With single quotes, double quotes, without the ".\" at the beginning, without the "\" at the end, etc... – bopapa_1979 Feb 16 '16 at 20:53
  • Per my above comment, it may be worth noting that the repo is in a state of conflict when I begin. This is the point where I would normally run "git mergetool." The final output of my merge command was: Automatic merge failed; fix conflicts and then commit the result. – bopapa_1979 Feb 16 '16 at 20:54
  • @EricBurcham, did you make sure to `git add` the folder after the `git checkout --theirs`? – David Deutsch Feb 16 '16 at 21:54
  • Yes. Perhaps I was missing something. I'll try this again. – bopapa_1979 Feb 17 '16 at 19:51
2

The "right" way in your case is to rebuild the assemblies before committing the merge. I don't see why you would not do this. The steps as follows should work:

  1. resolve and git add all conflicted sources. Then whatever happens during merge should not affect what you commit.
  2. remove the conflicted assembly files. No need to do anything with their git information, just remove the files
  3. build the assemblies.
  4. git add the ready assemblies.
  5. Then commit. What you get is merge which includes both local and remote changes.

EDIT: try this:

  1. git rm --force -r <dirname>
  2. run your mergetool, now it should now mention the binary files (kdiff3 did not)
  3. build assemblies
  4. git add <dirname>
  5. commit

I tried this bash script to reproduce you case as I understand it.

max630
  • 8,762
  • 3
  • 30
  • 55
  • We use Beyond Compare to resolve merge conflicts. We invoke it by typing "git mergetool." Beyond Compare cannot resolve binary differences, so we have to let several hundred tabs open / close, and tell git to continue merging conflicts after each one. It is trivially easy, but takes a long time. Perhaps I should just DELETE the Foundation Assemblies folder, resolve conflicts, then build? – bopapa_1979 Feb 16 '16 at 20:57
  • I tried deleting the directory in question after calling "git merge," since we rebuild it anyway. However, calling "git mergetool" still tries to invoke the mergetool for each of the missing files, resulting in hundreds of outputs like this: Source/Foundation Assemblies/Foundation.Coding.Ftp.dll seems unchanged. Was the merge successful? [y/n] – bopapa_1979 Feb 16 '16 at 21:11
  • As far as I understand your case, this would also work. You can even remove all directory from git (something like `git rm --force `), and after build add it (`git add `). Try it if your merge tool still complains about conflicts. – max630 Feb 16 '16 at 21:11
  • Removing the directory still results in "git mergetool" showing a conflict for each file... One is modified and one is deleted, so I still have to accept all the deletions. But at least the mergetool does not launch once for each conflicted assemblies. I just have to tell it to take the deleted one each time, which is much faster. Still now what I'm wanting, though... – bopapa_1979 Feb 16 '16 at 21:40
  • for me removal with `git rm` worked, I only had to add `-r`. See the edit – max630 Feb 17 '16 at 05:25
  • The edited answer above wound up doing exactly what I wanted. Our final process looks something like this: 1. Fetch all. 2. Checkout develop. 3. Pull. 4. Checkout working branch. 5. Merge develop into working branch. 6. git rm --force -r '.\Foundation Assemblies' 7. Run mergetool and resolve "real" conflicts. 8. Build the Foundation solution to regenerate the "Foundation Assemblies" folder. 9. Re-add the "Foundation Assemblies" folder. – bopapa_1979 Feb 17 '16 at 19:48
0

You have several merge strategies which you can use:

resolve

This can only resolve two heads (i.e. the current branch and another branch you pulled from) using a 3-way merge algorithm. It tries to carefully detect criss-cross merge ambiguities and is considered generally safe and fast.

recursive

This can only resolve two heads using a 3-way merge algorithm. When there is more than one common ancestor that can be used for 3-way merge, it creates a merged tree of the common ancestors and uses that as the reference tree for the 3-way merge. This has been reported to result in fewer merge conflicts without causing mismerges by tests done on actual merge commits taken from Linux 2.6 kernel development history. Additionally this can detect and handle merges involving renames. This is the default merge strategy when pulling or merging one branch.

The 'recursive' strategy can take the following options:

ours

This option forces conflicting hunks to be auto-resolved cleanly by favoring 'our' version. Changes from the other tree that do not conflict with our side are reflected to the merge result. For a binary file, the entire contents are taken from our side.

This should not be confused with the 'ours' merge strategy, which does not even look at what the other tree contains at all. It discards everything the other tree did, declaring 'our' history contains all that happened in it.

theirs

This is the opposite of 'ours'.

and even more but those are the main ones.

Community
  • 1
  • 1
CodeWizard
  • 128,036
  • 21
  • 144
  • 167