Skip to content

Merge stuff #3

@lakruzz

Description

@lakruzz

To Recap the situation:

  • @denvercoder changed tiger to lion on the lion branch
  • @wwhite: changed mother to father on the father branch
  • @Julesw: Changed tiger to turtle on the turtle branch
  • YOU: Change an exclamation mark a punctuation mark directly on the master.
---
title: The Poem
---

%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'showBranches': true, 'showCommitLabel':true,'mainBranchName': 'master'}} }%%

gitGraph
   commit id: "Poem added" tag: "ancestor"
   branch lion
   branch father
   branch turtle
   checkout master
   commit id: "! is ."
   checkout lion
   commit id: "tiger is lion"
   checkout father
   commit id: "mother is father"
   checkout turtle
   commit id: "tiger is turtle"
Loading

OK it looks like a mess; four people hacking in the same file at the same time.!

Let's play a game: You are now the integration manager of a software project.

It's actually a title used (less frequently nowadays). It's the person who does all the merges - sometimes also referred to as merge manager or simply "The Merge Guy". Does that sound like a fun job? Naah! Luckily it's not as common as it used to be. Thanks to tools like git and GitHub and to the spread of more agile processes - most developers today are expected to merge their own stuff and and push it.

But the whole Pull request culture - which is very popular - and strongly advocated by GitHub - is kind of a relic from the past. A distributed - and claimed contemporary - approach to an old school integration manager role. We'll touch on this later when we talk about pull requests.

Your job is now to make all the branches of the poem come together as one on the master branch

Bring them in one at a time and commit each successful merge before you proceed onto the next.

%%{init: { 'logLevel': 'debug', 'theme': 'base', 'gitGraph': {'showBranches': true, 'showCommitLabel':true,'mainBranchName': 'master'}} }%%

gitGraph
   commit id: "Poem added" tag: "ancestor"
   branch lion
   branch father
   branch turtle
   checkout master
   commit id: "! is ."
   checkout lion
   commit id: "tiger is lion"
   checkout father
   commit id: "mother is father"
   checkout turtle
   commit id: "tiger is turtle"
   checkout master
   merge lion
   commit id: "merged lion"
   merge father
   commit id: "merged father"
   merge turtle
   commit id: "merged turtle"
Loading

One of these merges is not going to go down easy - can you predict where you'll run into problems?

To merge something in git is dead-easy: A merge is a pull; that means you merge a branch into some other branch. The command is called merge and the synopsis is:

git merge [-n] [--stat] [--no-commit] [--squash] [--[no-]edit]
	[--no-verify] [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]]
	[--[no-]allow-unrelated-histories]
	[--[no-]rerere-autoupdate] [-m <msg>] [-F <file>]
	[--into-name <branch>] [<commit>…​]
git merge (--continue | --abort | --quit)

This most common flow is:

  • git checkout the branch who shall receive the merge
  • git merge the branch you want to bring in.

Git will try to merge it without your help and but if it needs your attention it will halt the process in which case you will:

  • Fix the un-mergeable file manually in your editor.
  • Resume the merge by calling git merge again with of the switches --continue, --abort or --quit.

Lets try the first on:

git co master
git merge lion

....Argh! The merge will create a commit after the file merge if it goes well - but as you know, a commit requires a message. A message file MERGE_MSG is opened in the editor Type something meaningful. It suggested Merge branch 'lion'. Hmm? that's sufficiently meaningful, so just save/close the file. The commit happens as soon at the file is closed.

Try to run your tree alias:

git tree

It looks right!

Or open the command palette in your CodeSpace and search for "Commit Graph" - open the GitLen tool. Aaaah!

One down - let's continue. This time we don't fall into the manual process of closing the commit message file:

git co master
git merge father --no-edit

WTF!!! There's a merge conflict! That was unexpected!

All @wwhite did was to change "mother" to "father" and no one else altered that particular line. So if the algorithm favours change: "change rules" remember? then why are we blocked by ... yeah by what exactly?

image

It turns out that it's the change that YOU did on master - where you changed "!" to "." that's causing the conflict.

Maybe @denvercoder was favoured for making the merge before @wwhite - if it had been the other way around perhaps @denvercoder would have received the conflict.

Naah! - that's not it! @wwhite would have received a conflict anyway.

The reason why this is - is because the two lines changed are next to each other - they are in the same block. The merge algorithm insist on not making border-line decisions.

Let's abort - and and analyse the situation.

git merge --abort

Let's test if we could have predicted this try to run

git diff master father

Here's what I get:
image

Now see the diff to lion

git diff master lion

image

You see?

  • The master<>father diff is shown as one diff of two lines.
  • The master<>lion diff is shown as two diffs each of one line.

A subtle but important difference.

Wouldn't it be nice, if we had a git command like git mergetest or perhaps a switch --dry-run switch to git merge

Have a look at hit post on stack overflow: Is there a git-merge --dry-run option? Someone turned it into a nice alias

You can store it in your .gitconfig file if you want:

git config --file $(git root)/.gitconfig  alias.mergetest '!f(){ git merge --no-commit --no-ff "$1"; git merge --abort; echo "Merge aborted"; };f '

...and then try it out:

git co master
git mergetest father
git mergetest lion

Alright - there's apparently not escaping this manual merge, so let's get back to it - run this again:

git co master
git merge father --no-edit

And then fix the file in the editor - Use the merge editor. and when you have completet your work complete the merge of the file.

And then go back and run

git merge --continue

You are done - If you merge had more conflicting files, you would have had to continue until all was settled.

OK Last one:

git co master
git merge turtle --no-edit

Again you get a conflict - but this one was expected!

The first bird get's the worm,
But the last mouse get's the cheese

Now wrap up!

  • Push to GitHub
  • Make sure both your working directory and stage area are clean!

Nice graphs by the way eh? They are made from MarkDown code too!

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions