Git Avoid Merge Again and Again for the Same Thing

Merging in Git is typically adequately piece of cake. Since Git makes it like shooting fish in a barrel to merge another branch multiple times, information technology ways that y'all can accept a very long lived branch only you can keep it upwardly to date as y'all go, solving modest conflicts oft, rather than exist suprised past ane enormous conflict at the end of the series.

However, sometimes catchy conflicts practise occur. Unlike some other version control systems, Git does not try to be overly clever about merge disharmonize resolution. Git's philosophy is to exist smart nearly determining when a merge resolution is unambiguous, but if there is a disharmonize, information technology does non endeavor to exist clever about automatically resolving it. Therefore, if you lot wait too long to merge two branches that diverge quickly, you tin can run into some issues.

In this department, we'll go over what some of those problems might be and what tools Git gives you to assistance handle these more than tricky situations. We'll also cover some of the unlike, not-standard types of merges yous can do, besides equally run into how to back out of merges that you've washed.

Merge Conflicts

While nosotros covered some basics on resolving merge conflicts in Basic Merge Conflicts, for more than circuitous conflicts, Git provides a few tools to help you figure out what's going on and how to better deal with the conflict.

First of all, if at all possible, attempt to make sure your working directory is clean before doing a merge that may have conflicts. If y'all have work in progress, either commit information technology to a temporary branch or stash it. This makes it so that you can undo annihilation you endeavor here. If you have unsaved changes in your working directory when you try a merge, some of these tips may help you lose that work.

Let's walk through a very uncomplicated example. We have a super simple Red file that prints howdy world.

            #! /usr/bin/env crimson  def hello   puts 'hi world' end  hi()          

In our repository, nosotros create a new branch named whitespace and proceed to change all the Unix line endings to DOS line endings, substantially changing every line of the file, but just with whitespace. And then we change the line "hello world" to "hullo mundo".

            $ git checkout -b whitespace Switched to a new branch 'whitespace'  $ unix2dos hello.rb unix2dos: converting file hello.rb to DOS format ... $ git commit -am 'converted hello.rb to DOS' [whitespace 3270f76] converted hullo.rb to DOS  i file inverse, 7 insertions(+), seven deletions(-)  $ vim hullo.rb $ git diff -w diff --git a/hello.rb b/hello.rb index ac51efd..e85207e 100755 --- a/hello.rb +++ b/howdy.rb @@ -i,7 +1,7 @@  #! /usr/bin/env ruby   def how-do-you-do -  puts 'hello globe' +  puts 'hello mundo'^M  terminate   hello()  $ git commit -am 'hello mundo change' [whitespace 6d338d2] how-do-you-do mundo change  1 file changed, 1 insertion(+), 1 deletion(-)          

Now nosotros switch back to our master branch and add some documentation for the role.

            $ git checkout master Switched to co-operative 'master'  $ vim howdy.rb $ git diff diff --git a/hello.rb b/how-do-you-do.rb index ac51efd..36c06c8 100755 --- a/hello.rb +++ b/hi.rb @@ -ane,v +ane,6 @@  #! /usr/bin/env cerise  +# prints out a greeting  def hullo    puts 'hello world'  stop  $ git commit -am 'document the function' [master bec6336] document the part  ane file changed, 1 insertion(+)          

At present we try to merge in our whitespace branch and we'll get conflicts because of the whitespace changes.

            $ git merge whitespace Auto-merging hello.rb CONFLICT (content): Merge disharmonize in hullo.rb Automatic merge failed; fix conflicts so commit the result.          

Aborting a Merge

We now take a few options. Start, permit'due south cover how to go out of this state of affairs. If you perhaps weren't expecting conflicts and don't want to quite bargain with the situation yet, you can simply back out of the merge with git merge --abort.

              $ git status -sb ## master UU how-do-you-do.rb  $ git merge --abort  $ git status -sb ## primary            

The git merge --arrest option tries to revert dorsum to your state earlier yous ran the merge. The but cases where information technology may not be able to practise this perfectly would be if you had unstashed, uncommitted changes in your working directory when you ran it, otherwise it should work fine.

If for some reason you find yourself in a horrible land and just desire to offset over, you can likewise run git reset --hard Head or wherever you want to go back to. Call up once again that this will accident away your working directory, and so make sure y'all don't want whatever changes there.

Ignoring Whitespace

In this specific case, the conflicts are whitespace related. Nosotros know this because the case is unproblematic, but it's as well pretty easy to tell in real cases when looking at the conflict because every line is removed on ane side and added once more on the other. By default, Git sees all of these lines as being inverse, and then it can't merge the files.

The default merge strategy tin can take arguments though, and a few of them are virtually properly ignoring whitespace changes. If yous see that you accept a lot of whitespace bug in a merge, you tin just abort it and do information technology again, this time with -Xignore-all-space or -Xignore-space-change. The first option ignores changes in any amount of existing whitespace, the 2d ignores all whitespace changes altogether.

              $ git merge -Xignore-all-space whitespace Motorcar-merging hello.rb Merge made past the 'recursive' strategy.  hello.rb | 2 +-  1 file inverse, 1 insertion(+), 1 deletion(-)            

Since in this example, the actual file changes were not conflicting, once we ignore the whitespace changes, everything merges just fine.

This is a lifesaver if yous accept someone on your squad who likes to occasionally reformat everything from spaces to tabs or vice-versa.

Manual File Re-merging

Though Git handles whitespace pre-processing pretty well, there are other types of changes that peradventure Git can't handle automatically, but are scriptable fixes. As an example, let'southward pretend that Git could not handle the whitespace alter and we needed to do information technology by paw.

What we really need to exercise is run the file we're trying to merge in through a dos2unix plan before trying the actual file merge. So how would we do that?

Offset, we get into the merge disharmonize state. Then nosotros want to get copies of my version of the file, their version (from the branch we're merging in) and the common version (from where both sides branched off). Then nosotros want to gear up up either their side or our side and re-attempt the merge once more for but this unmarried file.

Getting the three file versions is really pretty easy. Git stores all of these versions in the index nether "stages" which each accept numbers associated with them. Stage 1 is the mutual anecestor, stage ii is your version and stage 3 is from the MERGE_HEAD, the version yous're merging in ("theirs").

You can extract a copy of each of these versions of the conflicted file with the git evidence command and a special syntax.

              $ git show :1:hello.rb > hello.common.rb $ git show :2:hello.rb > howdy.ours.rb $ git show :three:hi.rb > hello.theirs.rb            

If yous want to get a little more hard core, you tin also use the ls-files -u plumbing control to get the actual SHAs of the Git blobs for each of these files.

              $ git ls-files -u 100755 ac51efdc3df4f4fd328d1a02ad05331d8e2c9111 1	hullo.rb 100755 36c06c8752c78d2aff89571132f3bf7841a7b5c3 2	how-do-you-do.rb 100755 e85207e04dfdd5eb0a1e9febbc67fd837c44a1cd 3	how-do-you-do.rb            

The :i:how-do-you-do.rb is just a shorthand for looking up that hulk SHA.

At present that we have the content of all three stages in our working directory, we tin manually fix up theirs to fix the whitespace issue and re-merge the file with the little-known git merge-file control which does just that.

              $ dos2unix hello.theirs.rb dos2unix: converting file hello.theirs.rb to Unix format ...  $ git merge-file -p \     how-do-you-do.ours.rb hello.mutual.rb hullo.theirs.rb > hullo.rb  $ git unequal -westward diff --cc hello.rb index 36c06c8,e85207e..0000000 --- a/hello.rb +++ b/hello.rb @@@ -1,eight -ane,7 +ane,8 @@@   #! /usr/bin/env ruby   +# prints out a greeting   def hi -   puts 'hello world' +   puts 'how-do-you-do mundo'   end    hello()            

At this signal we accept nicely merged the file. In fact, this actually works better than the ignore-all-infinite option because this actually fixes the whitespace changes before merge instead of only ignoring them. In the ignore-all-space merge, we really ended upwards with a few lines with DOS line endings, making things mixed.

If you desire to get an idea before finalizing this commit about what was actually changed betwixt ane side or the other, yous can ask git diff to compare what is in your working directory that you're well-nigh to commit equally the upshot of the merge to any of these stages. Allow's go through them all.

To compare your result to what you had in your co-operative before the merge, in other words, to see what the merge introduced, y'all tin run git diff --ours

              $ git diff --ours * Unmerged path hello.rb diff --git a/hello.rb b/hullo.rb index 36c06c8..44d0a25 100755 --- a/hello.rb +++ b/hello.rb @@ -2,7 +ii,7 @@   # prints out a greeting  def hello -  puts 'howdy world' +  puts 'hello mundo'  cease   hello()            

So here we tin can easily see that what happened in our branch, what nosotros're actually introducing to this file with this merge, is changing that single line.

If nosotros want to come across how the result of the merge differed from what was on their side, you can run git diff --theirs. In this and the following instance, nosotros take to use -westward to strip out the whitespace because we're comparison information technology to what is in Git, non our cleaned up hello.theirs.rb file.

              $ git unequal --theirs -w * Unmerged path hello.rb unequal --git a/how-do-you-do.rb b/hello.rb index e85207e..44d0a25 100755 --- a/hello.rb +++ b/hi.rb @@ -1,v +1,6 @@  #! /usr/bin/env blood-red  +# prints out a greeting  def hello    puts 'how-do-you-do mundo'  end            

Finally, yous can see how the file has changed from both sides with git unequal --base.

              $ git unequal --base -due west * Unmerged path hello.rb diff --git a/hello.rb b/hello.rb index ac51efd..44d0a25 100755 --- a/howdy.rb +++ b/how-do-you-do.rb @@ -ane,7 +ane,eight @@  #! /usr/bin/env ruby  +# prints out a greeting  def hello -  puts 'hello earth' +  puts 'hello mundo'  end   hello()            

At this point we tin can use the git make clean command to clear out the actress files nosotros created to do the transmission merge merely no longer need.

              $ git clean -f Removing hullo.common.rb Removing hi.ours.rb Removing hi.theirs.rb            

Checking Out Conflicts

Perhaps we're not happy with the resolution at this point for some reason, or maybe manually editing ane or both sides all the same didn't piece of work well and we need more than context.

Let'southward change up the example a little. For this example, we have two longer lived branches that each have a few commits in them simply create a legitimate content conflict when merged.

              $ git log --graph --oneline --decorate --all * f1270f7 (Caput, master) update README * 9af9d3b add together a README * 694971d update phrase to hola world | * e3eb223 (mundo) add more tests | * 7cff591 add testing script | * c3ffff1 changed text to howdy mundo |/ * b7dcc89 initial hello globe lawmaking            

We at present have three unique commits that live just on the primary co-operative and three others that live on the mundo branch. If nosotros try to merge the mundo branch in, nosotros get a disharmonize.

              $ git merge mundo Auto-merging hello.rb Conflict (content): Merge conflict in how-do-you-do.rb Automatic merge failed; set conflicts so commit the outcome.            

We would like to come across what the merge conflict is. If nosotros open upwardly the file, nosotros'll encounter something like this:

              #! /usr/bin/env ruby  def hello <<<<<<< Caput   puts 'hola world' =======   puts 'hello mundo' >>>>>>> mundo end  howdy()            

Both sides of the merge added content to this file, just some of the commits modified the file in the same place that acquired this conflict.

Allow'due south explore a couple of tools that you now have at your disposal to determine how this conflict came to be. Peradventure it's not obvious how exactly y'all should ready this conflict. You need more context.

I helpful tool is git checkout with the '--conflict' option. This will re-checkout the file again and supervene upon the merge conflict markers. This can be useful if you desire to reset the markers and try to resolve them once more.

You can pass --conflict either diff3 or merge (which is the default). If you pass information technology diff3, Git will use a slightly dissimilar version of disharmonize markers, non merely giving you the "ours" and "theirs" versions, only also the "base" version inline to give you more context.

              $ git checkout --conflict=diff3 hello.rb            

One time nosotros run that, the file will await similar this instead:

              #! /usr/bin/env ruby  def hello <<<<<<< ours   puts 'hola world' ||||||| base   puts 'hullo world' =======   puts 'hullo mundo' >>>>>>> theirs end  howdy()            

If yous like this format, you can gear up information technology as the default for hereafter merge conflicts by setting the merge.conflictstyle setting to diff3.

              $ git config --global merge.conflictstyle diff3            

The git checkout control can also accept --ours and --theirs options, which can be a really fast style of just choosing either i side or the other without merging things at all.

This can be specially useful for conflicts of binary files where you lot can simply choose 1 side, or where y'all but want to merge certain files in from another branch - you tin can do the merge and then checkout sure files from i side or the other before committing.

Merge Log

Some other useful tool when resolving merge conflicts is git log. This tin can assistance you get context on what may take contributed to the conflicts. Reviewing a little bit of history to recollect why two lines of evolution were touching the same area of lawmaking tin be really helpful sometimes.

To get a full list of all of the unique commits that were included in either branch involved in this merge, we can use the "triple dot" syntax that we learned in Triple Dot.

              $ git log --oneline --left-right HEAD...MERGE_HEAD < f1270f7 update README < 9af9d3b add a README < 694971d update phrase to hola earth > e3eb223 add more tests > 7cff591 add testing script > c3ffff1 inverse text to hello mundo            

That'southward a nice list of the vi total commits involved, too as which line of evolution each commit was on.

We can further simplify this though to give us much more specific context. If we add the --merge choice to git log, it will only show the commits in either side of the merge that touch a file that's currently conflicted.

              $ git log --oneline --left-correct --merge < 694971d update phrase to hola world > c3ffff1 changed text to hello mundo            

If you lot run that with the -p option instead, you get simply the diffs to the file that ended up in conflict. This can be really helpful in speedily giving y'all the context you lot need to help understand why something conflicts and how to more than intelligently resolve information technology.

Combined Diff Format

Since Git stages any merge results that are successful, when y'all run git unequal while in a conflicted merge state, y'all just get what is currently all the same in conflict. This tin be helpful to meet what you lot nevertheless have to resolve.

When y'all run git diff directly after a merge conflict, information technology will give you data in a rather unique diff output format.

              $ git diff diff --cc hi.rb alphabetize 0399cd5,59727f0..0000000 --- a/hello.rb +++ b/hello.rb @@@ -ane,7 -i,7 +1,11 @@@   #! /usr/bin/env ruby    def hello ++<<<<<<< Head  +  puts 'hola world' ++======= +   puts 'hello mundo' ++>>>>>>> mundo   end    hello()            

The format is called "Combined Diff" and gives you two columns of data adjacent to each line. The commencement cavalcade shows yous if that line is unlike (added or removed) betwixt the "ours" branch and the file in your working directory and the second cavalcade does the same between the "theirs" branch and your working directory copy.

And so in that example you can see that the <<<<<<< and >>>>>>> lines are in the working copy but were not in either side of the merge. This makes sense because the merge tool stuck them in there for our context, just we're expected to remove them.

If we resolve the disharmonize and run git unequal again, we'll encounter the same thing, simply it's a little more useful.

              $ vim hi.rb $ git diff unequal --cc hello.rb alphabetize 0399cd5,59727f0..0000000 --- a/hello.rb +++ b/how-do-you-do.rb @@@ -1,7 -one,7 +1,seven @@@   #! /usr/bin/env cherry    def hello -   puts 'hola world'  -  puts 'hello mundo' ++  puts 'hola mundo'   finish    hullo()            

This shows the states that "hola globe" was in our side but non in the working re-create, that "how-do-you-do mundo" was in their side but not in the working copy and finally that "hola mundo" was not in either side but is now in the working copy. This can exist useful to review earlier committing the resolution.

You can also get this from the git log for any merge afterward the fact to come across how something was resolved after the fact. Git volition output this format if you run git show on a merge commit, or if yous add together a --cc option to a git log -p (which by default only shows patches for non-merge commits).

              $ git log --cc -p -1 commit 14f41939956d80b9e17bb8721354c33f8d5b5a79 Merge: f1270f7 e3eb223 Author: Scott Chacon <schacon@gmail.com> Date:   Friday Sep xix 18:14:49 2014 +0200      Merge branch 'mundo'      Conflicts:         hello.rb  diff --cc hello.rb index 0399cd5,59727f0..e1d0799 --- a/howdy.rb +++ b/hello.rb @@@ -1,7 -1,seven +1,7 @@@   #! /usr/bin/env red    def howdy -   puts 'hola earth'  -  puts 'hello mundo' ++  puts 'hola mundo'   terminate    hello()            

Undoing Merges

Now that you know how to create a merge commit, yous'll probably make some by fault. One of the great things about working with Git is that it'south okay to make mistakes, considering it's possible (and in many cases easy) to fix them.

Merge commits are no unlike. Let's say y'all started work on a topic branch, accidentally merged it into master, and now your commit history looks like this:

Accidental merge commit.

Figure 138. Accidental merge commit

There are ii ways to approach this problem, depending on what your desired outcome is.

Fix the references

If the unwanted merge commit simply exists on your local repository, the easiest and best solution is to move the branches so that they point where y'all want them to. In most cases, if you follow the errant git merge with git reset --hard HEAD~, this volition reset the branch pointers then they await like this:

History after `git reset --hard HEAD~`.

Figure 139. History after git reset --hard Caput~

We covered reset dorsum in Reset Demystified, so it shouldn't exist besides hard to figure out what's going on here. Here'southward a quick refresher: reset --hard unremarkably goes through three steps:

  1. Move the branch Head points to. In this case, nosotros want to movement master to where it was before the merge commit (C6).

  2. Make the index wait like Head.

  3. Make the working directory look like the index.

The downside of this arroyo is that information technology's rewriting history, which can be problematic with a shared repository. Check out The Perils of Rebasing for more on what tin can happen; the short version is that if other people have the commits you're rewriting, yous should probably avoid reset. This approach also won't piece of work if any other commits have been created since the merge; moving the refs would effectively lose those changes.

Contrary the commit

If moving the branch pointers around isn't going to work for you, Git gives you the option of making a new commit which undoes all the changes from an existing ane. Git calls this performance a "revert", and in this particular scenario, you'd invoke it similar this:

              $ git revert -chiliad 1 HEAD [chief b1d8379] Revert "Merge co-operative 'topic'"            

The -one thousand 1 flag indicates which parent is the "mainline" and should be kept. When you invoke a merge into HEAD (git merge topic), the new commit has two parents: the first one is Caput (C6), and the second is the tip of the co-operative being merged in (C4). In this case, we want to disengage all the changes introduced by merging in parent #2 (C4), while keeping all the content from parent #1 (C6).

The history with the revert commit looks similar this:

History after `git revert -m 1`.

Figure 140. History after git revert -chiliad 1

The new commit ^M has exactly the aforementioned contents as C6, then starting from here information technology'due south as if the merge never happened, except that the now-unmerged commits are still in Head'southward history. Git will go confused if you try to merge topic into master again:

              $ git merge topic Already upwards-to-date.            

There's goose egg in topic that isn't already reachable from principal. What'due south worse, if you add together work to topic and merge once again, Git will merely bring in the changes since the reverted merge:

History with a bad merge.

Figure 141. History with a bad merge

The best way effectually this is to un-revert the original merge, since at present yous want to bring in the changes that were reverted out, then create a new merge commit:

              $ git revert ^M [master 09f0126] Revert "Revert "Merge co-operative 'topic'"" $ git merge topic            

History after re-merging a reverted merge.

Effigy 142. History after re-merging a reverted merge

In this case, M and ^M cancel out. ^^1000 effectively merges in the changes from C3 and C4, and C8 merges in the changes from C7, and then now topic is fully merged.

Other Types of Merges

So far we've covered the normal merge of two branches, usually handled with what is called the "recursive" strategy of merging. There are other ways to merge branches together however. Let'due south comprehend a few of them quickly.

Our or Theirs Preference

First of all, there is another useful thing nosotros tin can do with the normal "recursive" manner of merging. We've already seen the ignore-all-space and ignore-space-change options which are passed with a -X but we can also tell Git to favor 1 side or the other when information technology sees a conflict.

By default, when Git sees a conflict between two branches beingness merged, it will add merge conflict markers into your code and mark the file as conflicted and let you resolve it. If you lot would prefer for Git to simply cull a specific side and ignore the other side instead of letting yous manually merge the conflict, you can pass the merge command either a -Xours or -Xtheirs.

If Git sees this, it volition not add together conflict markers. Whatever differences that are mergable, it will merge. Any differences that conflict, it will merely choose the side you specify in whole, including binary files.

If we go back to the "hello world" case nosotros were using before, we can meet that merging in our branch causes conflicts.

              $ git merge mundo Auto-merging hello.rb Conflict (content): Merge conflict in hello.rb Resolved 'hello.rb' using previous resolution. Automatic merge failed; set up conflicts so commit the event.            

All the same if nosotros run it with -Xours or -Xtheirs it does non.

              $ git merge -Xours mundo Auto-merging hullo.rb Merge made by the 'recursive' strategy.  hello.rb | 2 +-  examination.sh  | two ++  2 files inverse, 3 insertions(+), 1 deletion(-)  create mode 100644 test.sh            

In that case, instead of getting conflict markers in the file with "hi mundo" on one side and "hola world" on the other, information technology will just pick "hola earth". Withal, all the other not-conflicting changes on that branch are merged successfully in.

This option tin as well be passed to the git merge-file command we saw earlier past running something like git merge-file --ours for individual file merges.

If you want to practice something like this simply not have Git even attempt to merge changes from the other side in, in that location is a more draconian option, which is the "ours" merge strategy. This is different from the "ours" recursive merge option.

This volition basically do a fake merge. It will record a new merge commit with both branches as parents, but information technology will not even look at the co-operative you're merging in. It will merely record as the upshot of the merge the exact code in your current branch.

              $ git merge -due south ours mundo Merge made past the 'ours' strategy. $ git diff Head HEAD~ $            

You tin can encounter that there is no departure between the branch nosotros were on and the event of the merge.

This can often exist useful to basically pull a fast one on Git into thinking that a branch is already merged when doing a merge afterward. For case, say you branched off a "release" branch and take done some work on it that y'all will want to merge back into your "master" branch at some point. In the meantime some bugfix on "main" needs to exist backported into your release branch. Yous can merge the bugfix co-operative into the release co-operative and too merge -s ours the same co-operative into your primary co-operative (even though the fix is already in that location) so when y'all afterwards merge the release branch again, at that place are no conflicts from the bugfix.

Subtree Merging

The idea of the subtree merge is that y'all have two projects, and one of the projects maps to a subdirectory of the other one and vice versa. When you specify a subtree merge, Git is often smart enough to figure out that one is a subtree of the other and merge appropriately.

We'll go through an case of adding a seperate project into an existing project and and then merging the code of the 2d into a subdirectory of the first.

First, nosotros'll add the Rack application to our projection. We'll add together the Rack project as a remote reference in our own projection and and then check information technology out into its own co-operative:

              $ git remote add rack_remote https://github.com/rack/rack $ git fetch rack_remote warning: no common commits remote: Counting objects: 3184, done. remote: Compressing objects: 100% (1465/1465), done. remote: Total 3184 (delta 1952), reused 2770 (delta 1675) Receiving objects: 100% (3184/3184), 677.42 KiB | 4 KiB/s, done. Resolving deltas: 100% (1952/1952), done. From https://github.com/rack/rack  * [new branch]      build      -> rack_remote/build  * [new branch]      master     -> rack_remote/master  * [new branch]      rack-0.4   -> rack_remote/rack-0.4  * [new branch]      rack-0.9   -> rack_remote/rack-0.9 $ git checkout -b rack_branch rack_remote/primary Branch rack_branch set to track remote branch refs/remotes/rack_remote/master. Switched to a new branch "rack_branch"            

At present we have the root of the Rack project in our rack_branch branch and our ain projection in the master branch. If you cheque out one and and so the other, you can see that they have different project roots:

              $ ls AUTHORS         KNOWN-Problems   Rakefile      contrib         lib COPYING         README         bin           case         exam $ git checkout primary Switched to co-operative "master" $ ls README            

This is sort of a strange concept. Not all the branches in your repository actually have to be branches of the same projection. It's not common, because information technology's rarely helpful, but information technology'southward fairly piece of cake to accept branches contain completely unlike histories.

In this case, nosotros want to pull the Rack project into our master project as a subdirectory. We can exercise that in Git with git read-tree. You lot'll learn more than nigh read-tree and its friends in Git Internals, but for at present know that information technology reads the root tree of one co-operative into your electric current staging area and working directory. Nosotros simply switched back to your principal co-operative, and we pull the rack branch into the rack subdirectory of our master branch of our main project:

              $ git read-tree --prefix=rack/ -u rack_branch            

When we commit, information technology looks like we accept all the Rack files nether that subdirectory – as though we copied them in from a tarball. What gets interesting is that we can fairly easily merge changes from i of the branches to the other. And so, if the Rack project updates, we can pull in upstream changes by switching to that branch and pulling:

              $ git checkout rack_branch $ git pull            

Then, we tin merge those changes back into our chief co-operative. We can use git merge -s subtree and information technology will piece of work fine; just Git will also merge the histories together, which we probably don't want. To pull in the changes and prepopulate the commit message, apply the --squash and --no-commit options as well as the -s subtree strategy selection:

              $ git checkout master $ git merge --squash -s subtree --no-commit rack_branch Squash commit -- non updating HEAD Automatic merge went well; stopped before committing equally requested            

All the changes from the Rack projection are merged in and ready to exist committed locally. You can also do the opposite – make changes in the rack subdirectory of your master branch and then merge them into your rack_branch branch after to submit them to the maintainers or push them upstream.

This gives us a way to have a workflow somewhat like to the submodule workflow without using submodules (which we will comprehend in Submodules). We can keep branches with other related projects in our repository and subtree merge them into our project occasionally. Information technology is nice in some ways, for instance all the code is committed to a single place. All the same, it has other drawbacks in that it's a chip more than circuitous and easier to make mistakes in reintegrating changes or accidentally pushing a co-operative into an unrelated repository.

Another slightly weird thing is that to get a diff betwixt what yous have in your rack subdirectory and the code in your rack_branch branch – to run across if you demand to merge them – you tin't employ the normal diff command. Instead, you must run git diff-tree with the branch you lot want to compare to:

              $ git unequal-tree -p rack_branch            

Or, to compare what is in your rack subdirectory with what the master branch on the server was the terminal time yous fetched, you can run

              $ git unequal-tree -p rack_remote/chief            

jamesforely74.blogspot.com

Source: https://git-scm.com/book/id/v2/Git-Tools-Advanced-Merging

0 Response to "Git Avoid Merge Again and Again for the Same Thing"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel