Tag: merges

How to configure an external diff and merge tool in Git – 104

One of my favorite Nintendo NES games was Dragon Warrior. It made you finish the game. At level 30, you couldn’t gain any more experience points. The mentor wizard person (because there’s always a mentor wizard person) would tell you, “Aren’t you strong enough to defeat the DragonLord?”

As I debated whether I knew enough to write a tip about configuring your git diff and merge tools, I ask myself “Aren’t you strong enough to defeat the git diff merge config tool?!”

More about the game at bottom of post…

For today’s tip, I’m using the git-scm instructions and this translation for Windows

Let’s start by engaging in epic battle with the git-scm instructions. I’m going to assume you’ve installed p4merge. Yes I know there are others, but for now, I’m going to follow these instructions. The journey to 3rd degree black belt starts with a single punch.

These are the two lines I get stuck on:

$ git config --global merge.tool extMerge
$ git config --global mergetool.extMerge.cmd \
  'extMerge "$BASE" "$LOCAL" "$REMOTE" "$MERGED"'

so why need two lines? Perhaps I’m not recalling enough of my shell programming or the translation fails over to Windows? The instructions say

Set up a merge wrapper script named extMerge that calls your binary with all the arguments provided

so `extMerge` is a variable. But why can’t you have it all on the same line?? What am I missing?

and also, what is “mergetool”? is it yet another variable? and how does it differ from merge.tool?

Anyways…

I’ll assume you have p4merge installed here in C:\Program Files\Perforce

Thanks to these for Windows we can setup p4merge as our merge and diff tools using Git Shell (I’m using Git Bash)

$ git config –global diff.tool p4merge
$ git config –global difftool.p4merge.path ‘C:\Program Files\Perforce\p4merge.exe’

$ git config –global merge.tool p4merge
$ git config –global mergetool.p4merge.path ‘C:\Program Files\Perforce\p4merge.exe’

Now let’s create a merge conflict, but this time, I’m going to keep my heart rate low when the (master|MERGING) appears! Btw I called my branch `conflicting` just because.

merge conflict state

now you can type in git mergetool

git mergetool showing p4merge

I’m not going to go over p4merge, but I think the “error” showing for the base file is because p4merge is trying to do a 3-way merge, but only has 2 files. Don’t quote me on this.

After modifying the resulting myfile1.text and hitting save in p4merge and closing it, we’re back to the merge conflict state. This used to freak me out because git didn’t “move on”. But now I know what to do!

You can do a `git status` to verify where you are at.

git status showing myfile1.txt as staged to be committed

Perfect! We’re done with myfile1.txt and it is staged. Since it is staged, we can simply commit it via `git commit -m “my merge message”`

committing the merge shows in the log

And boom! I’ve now done epic battle with one of my most feared Git foes.

The most memorable aspect of the game was the ending… but not for the reasons you’d think. The game had their basic “hero” ending, but it also offered a twist. Before going into battle with the Dragonlord, he’d ask you to join him in being evil and taking over the universe. If you said yes, the game would “freeze” and IIRC, it would erase your saved game! I’ve never heard of another game doing this. There’s the “did you give a dog a sandwich?” story, but not a “come join the dark side” option destroying your saved game!

How to manually commit your own merge commit – 103

Following from yesterday’s tip, suppose you have a branch that you plan to merge, but before the merge is committed, you want to verify things. Perhaps you want to hit F5 or perform some other testing. In other words, you are telling git, “Do the merge, but allow me to hit the commit button.”

I guess this is an inverse of “sudo make me a sandwich” which would be “hey sudo, about that sandwich, if you take all the stuff out of the refrigerator, I’ll finish making it myself.”

git merge –no-ff –no-commit branch-name

Note: I’m using the –no-ff option because I don’t have an actual merge conflict in my branch, so I need to tell git not to do a fast-forward.

git status showing all conflicts fixed but you are still merging

If you do a `git status` you’ll see that all conflicts fixed, but you’re still merging, just as the scary (master|MERGING) tells you.

Notice how the next line tells you to do a `git commit`and the Changes to be committed looks like a good old staging message.

From here, we just need to do a `git commit` (which would open your `git config core.editor` – mine is set to notepad. baby steps)

Or you could skip the editor (in case the scary Vi appears) and do

git commit -m “my merge message”

git commit -m "merged mybranch4" then a git log

And doing a `git log` shows the initial readme being added, then the commit from the mybranch4, then the merge commit!

How to practice not freaking out when you see (master|MERGING) by using git merge –abort – 102

I feel that a lot of Git tutorials forget what that raw, primal panic feels like when you see your branch name change to (master|MERGING). For me personally, 80% of the panic comes from not knowing “how do I get out of this state?! How can we pretend this never happened??”

Today’s tip is about how to get into and out of a merge conflict state, without creating any actual conflicts! I say no conflicts because the easier the setup, the easier it will be to practice, and eventually you’ll build up enough muscle memory to stay calm in future situations.

I have a branch called mybranch3 that simply contains a new file (e.g. touch myfile.txt). If I did just a `git merge –no-commit mybranch3` git would apply a fast-forward, so you have to add the –no-ff. I guess the fast-forward check take precedence in the git world. 

The –no-commit tells Git not to automatically do a merge commit, but rather, let you manually do the merge commit, as we’ll see in tomorrow’s tip.

git merge --no-ff --no-commit mybranch3

You could do a `git status` to figure out how to finish the merge (e.g. `git commit -m “merging mybranch3″`), but today’s tip is about practicing, “I’m taking my ball and going home.” You show Git who’s boss!

You’ll want to run the command `git merge –abort`

git merge --abort

and as you see from the `git log –oneline`, nothing was merged in from mybranch3. (the readme commit was my initial commit. I guess saying initial commit would have made more sense.)

P.S. this was my original vision for this series: take each option of each git command, play with it, try to break it, and blog about it. And it’s still my vision! But got to get through some of the more conceptual stuff first. I also want to get to the internal plumbing of trees, blobs, etc. Maybe in December 😉

How to know that a merge creates a git commit whereas a fast-forward does not – 101

I’m using several resources to teach myself Git: Ed’s Git for Visual Studio O’Reilly course, the Pro Git book, this particular Git Visualization tool, and the Git for Humans book. (If I’m missing a good intermediate resource, lmk!) As I study a concept in one course, I’ll go back and re-read that section in another book or course to see if there are any surprises that I didn’t catch the first time.

As I started re-reading the section on merging in Git for Humans, it hit me that I had missed one important difference between a git merge and a fast-forward – the merge commit!

I’ll use the Git Visualization tool to demo:

When you do a fast-forward merge, the commits from the feature branch (source branch?) are simply added to the master branch (target branch?), as soon in Tip 92 – how to do a fast forward merge 

git visualization tool showing how a fast forward does NOT introduce new commit ID

However, if we’re doing a real merge (e.g. there are conflicts that have to be resolved or you pass in the –no-ff option as we’ll have to do with this visualization tool), you’ll see that a new commit, called a merge commit, is added.

doing a real merge creates a merge commit

I guess Farris had it right (source)

I saw that movie when I was in elementary school. I promised myself when I got into high school I would take a day off and do all the things in that movie. The float scene was possible because of growing up in New Orleans, but the baseball part would have been challenging. I think the closest I’ve ever come to doing something like Farris Bueller was driving to Nintendo HQ (right by the gym I used to go to in Redmond), jumping out of the car, and screaming, “YES I MADE IT!” in homage to all those times as a little kid I entered to win a trip to Nintendo HQ via all those Nintendo Power magazines.

How to not quit your career when Git (via Visual Studio) adds <<<< HEAD into your code – 094

I studied Shotokan Karate for 20 years. At the start of each class, you’d say the Dojo Kun. At the beginning, I viewed the sayings as the rules of engagement, similar to FIFA laws. But over the years and decades, it starts to bleed into your subconscious as a way of viewing other situations in life. The most important of these rules is the last, “Refrain from violent behavior.”  The idea is you’re supposed to avoid any fights, etc. at all costs. Because of this philosophy, I have argued that karate is really the study of non-violence. I could go on and on about the importance of the only winning fight is the one that isn’t started, there’s no such thing as a first punch in karate, and so forth.

The first time I saw <<< HEAD and >>>> branch-name edited into my code*, my coffee mug went flying across the room.

Today’s tip is a walkthrough of resolving a merge conflict from within Visual Studio. We’ll cover command line in upcoming tips. Must… pace… self…

Suppose you have some existing output text in our ConsoleApplication in master. And you’re going to merge in text from a branch called decorations that also includes output text. Because both branches have changes in the same section, you’ll get a merge conflict. Let’s see how Visual Studio 2017 handles it.

First, do everything as shown in previous tips…

merging from decorations into master

But this time when you hit Merge, you’ll see the following

Merge in Progress - Conflicts: 1 message

Take a deep breath.

Now take another deep breath.

Resist the temptation to “fix” your code by removing the <<< HEAD and >>> decorations modifications. Let your build errors light up like rush hour traffic in your VS code margin gutter thingy.

Now click Conflicts: 1

You’ll be given an option to either Merge or simply take either the code from decorations or master w/o “merging”

Merge button for a conflicting file

Clicking the Merge button will take make use of that <<<< HEAD and >>> decorations gobbledygook by presenting you with a merge tool (in this case presented within VS).

Suppose you want both changes. You can click the checkboxes on both sides and you’ll see the result in the bottom screen.

VS merge tool

Notice how the resulting merge shows the Console.WriteLine() at the wrong location, which makes sense. The two code blocks were merged in a way that makes sense.

The bottom window is editable. A quick cut and paste puts the WriteLine() before the ReadLine() so it can be seen before the keypress to exit.

editing the resulting window screen

Hit Save and then hit Accept Merge at the top of the merge tool

Accept Merge button at the top of merge tool

And yet another button!! O_O

Now back in Team Explorer, click Commit Merge.

Commit Merge

Finally, we’re going to finish the merge by typing in a custom commit message and clicking Commit Staged

committing the merge with a custom message

And now when you view history, you’ll see the merge into master.

History - master w merge from decorations

*What I’ve realized from learning RoR and Node.js last year is that when you’re not using a full end-to-end IDE (e.g. text editors like atom, vi, sublime, etc.) you need another way to communicate changes and other sort of “metadata.” Hence the content of the code is modified, e.g. adding the <<<< HEAD directly into the file or adding a readme.md file to your repo (which doesn’t participate in the build). Once you start to know the backstory why things are the way they are, the world becomes a lot safer for coffee mugs.

How to do a non-fast forward merge in Visual Studio – 093

Yesterday’s tip was about how to do a fast forward merge, which shows all the commits still in a linear graph.

linear graph from a fast forward

Today’s tip is how to do a non-fast forward merge, meaning the graph history will show the branch being merged in

graph showing the branch merge for non-fast forward

Note: I had to use Visual Studio 2015 for this demo. There seems to be a bug in Visual Studio 2017 where the checkbox isn’t respecting local repo settings.

Let’s suppose you have a branch called test that you want to merge into master, but you want to retain the merge history in the graph.

Follow all the steps from yesterday’s tip, but today, you’ll uncheck the Commit changes after merging

image

Now you’ll get a message in Visual Studio. note: VS 2017 ignored the unchecked box and did the commit anyways.

merge in progress message

Train yourself to take a deep breath whenever you see a message from Git.

Switch to the Changes page, write a commit message, and hit commit staged.

committing a merge in progress in Changes window

And now your git history shows the merge from the branch.

merge from the branch now in the graph history

Visualizing what we did

We have a commit on the test branch we wish to merge, but retain the history.

git visualization tool showing a test branch

Now we’ll do a merge, but notice we’re using the –no-ff option, which means “no fast-forward” this time.

test being merged into master using no fast foward

Note: looks like the visualization tool requires at least 2 commits to demo the –no-ff option. Otherwise, you’ll get an error.

Does someone want to open a bug in the tool’s repository and call First! in the comments below?  I’m too tired from trying to stay awake to watch Samurai Jack. Why Comedy Central? Why did you think it was an okay April Fool’s Day joke to put some random cartoon on at the 8pm slot??  It’s only 9:47pm and I can’t stay awake to log bugs, much less make it to 11pm for Samurai Jack repeat. Or what if they don’t show Samurai Jack and repeat the cartoon?! See what your April Fool’s joke has done?!  I‘m off to bed.

How to do a fast forward merge in Visual Studio – 092

Yay!! I’m over 25% of the way into this series!! Which also means OMG is 2017 already 25% over yet?!?!

Today’s tip demos how you can do a straight forward merge in Visual Studio. No conflicts, etc.

Suppose you have have a method called DoNothing() that lives in a donothing branch.

1. Switch to the branch you want as a target

Double-click on the branch name. The bolded name will be the target branch. Checking out the target branch mimics Git command line functionality.

master branch checked out and bolded

2. Right-click the target branch and select Merge From…

Merge From... context menu

3. Click the merge button

We’ll get to what the checkbox means in a bit. As if I could stay away from blogging about a checkbox in VS!  =D

Merging donothing into master

And if all goes well, Team Explorer will give you a message

Repository updated to commit id in Team Explorer status bar

We’ll cover merge conflicts later.

Note this was a fast forward merge because there was nothing to merge, so there’s only the linear graph. A fast-forward is where Git realizes that you could have done each commit on that target branch, so it makes it look like that in graph form.

linear graph in commit history

To visualize what we’ve done in Git, here’s the setup. We have one commit in donothing that’s ahead of master.

branch donothing one commit ahead

Now we checkout master and do a git merge

git merge from donothing into master

Note how the tool assumes it’s a fast-forward merge. The tool must assume this because the tool doesn’t have a concept of a working directory or staging, so it can’t diff any files to detect conflicts. So the tool assumes there are no conflicts, hence a fast-forward merge.

We’ll look at non-fast forward merges next.