Skip to content

Instantly share code, notes, and snippets.

@albertpark
Last active May 14, 2020 01:28
Show Gist options
  • Save albertpark/4bc2690765ca74c983815c4a029116ee to your computer and use it in GitHub Desktop.
Save albertpark/4bc2690765ca74c983815c4a029116ee to your computer and use it in GitHub Desktop.

Git Merge Bubbles Nightmare

Updated May 12, 2020

Intro

So I complete a script program that works wonders on a Windows OS. Great! Next I test it on a Linux OS. I clone my repository on a Linux machine and test the code. What do you know, there is a bug and the code crashes immediately. Story of every coder's life. I do what we must do and dig into the code to fix this issue. I modify the code and re-test it. The bug is fixed and update the code. I send out a command with a git commit followed by a git push back to the remote. Now I am back to my Windows machine to make sure it did not break anything. I do a git pull and test the code. Something is not quiet right so I do this couple times back and forth to make sure I cover all the cases. Everything is perfect!

Well I was dead wrong. I have fallen into the newbie git pit and create git merge bubbles. In case you are wondering what they look like they look horrendus. Here was my first newbie git merge bubbles.

git merge bubbles

I need to clean up this mess and pop these merge bubbles. So after doing some git studying I figure out that I have to revert back where the bubble started. Safe thing to do at this point is to make a copy of your repository so you have the final polished code backed up. I introduce you to a hard reset.

Hard Reset

I will be using my actual repository to explain how we will be using this hard reset. To have a better understanding of this we will look at the actual respository branch graph by typing git log --oneline --graph. I will be using my own custom git log which is renamed to git lg:

→ $ git lg
*   87f30da 16 hours ago [albertpark] - (HEAD -> develop, origin/develop) Merge branch 'develop' of https://bitbucket.org/albertpark/multi-remote into develop
|\
| * 5d5bcfb 16 hours ago [albertpark] - Code formatting
* |   7939ee5 16 hours ago [albertpark] - Merge branch 'develop' of https://bitbucket.org/albertpark/multi-remote into develop
|\ \
| |/
| * 9f0461a 17 hours ago [albertpark] - Compatibility with Linux Bash version 4.1
* | 05c13aa 17 hours ago [albertpark] - Improved README.md description and usage example
|/
* c75afb1 17 hours ago [albertpark] - Added configuration option to select the remote origin
* 1c17122 18 hours ago [albertpark] - Improved error message when missing options
* d311e0f 22 hours ago [albertpark] - Only displaying the remote add command if it was successful
...

Note: When you have a longer graph there will be a : input area at the bottom of the screen where you can navigate up and down with your arrows. From here just simple press q to quit out of the graph mode.

Tip: My git log config alias @ ~.gitconfig:

[alias]
    lg = log --graph --oneline --abbrev-commit --decorate --format=format:'%C(bold red)%h%C(reset) %C(bold green)%ar%C(reset) - %C(white)%s%C(reset) %C(bold blue){%an}%C(reset)%C(bold yellow)%d%C(reset)' --all

In my branch you can see there are couple of merge bubbles within the develop branch. Just to get familiar with what a hard reset does we will do some exercise. Let's say we want to hard reset to the commit right before the HEAD:

→ $ git reset --hard HEAD^
HEAD is now at 7939ee5 Merge branch 'develop' of https://bitbucket.org/albertpark/multi-remote into develop

The HEAD of the release branch is now pointing at the second commit:

→ $ git lg
*   7939ee5 16 hours ago [albertpark] - (HEAD -> develop) Merge branch 'develop' of https://bitbucket.org/albertpark/multi-remote into develop
|\
| * 9f0461a 17 hours ago [albertpark] - Compatibility with Linux Bash version 4.1
* | 05c13aa 17 hours ago [albertpark] - Improved README.md description and usage example
|/
* c75afb1 17 hours ago [albertpark] - Added configuration option to select the remote origin
* 1c17122 18 hours ago [albertpark] - Improved error message when missing options
* d311e0f 22 hours ago [albertpark] - Only displaying the remote add command if it was successful
...

Just by doing this we have popped one of the merge bubble. You will also notice the code is now reverted back locally. If you forgot to save a backup copy not to worry. I will show you how to undo the hard reset.

Undo Hard Reset

To undo a hard reset we use the same command with a minor change:

→ $ git reset --hard HEAD@{1}
HEAD is now at 87f30da Merge branch 'develop' of https://bitbucket.org/albertpark/multi-remote into develop

→ $ git lg
*   87f30da 16 hours ago [albertpark] - (HEAD -> develop, origin/develop) Merge branch 'develop' of https://bitbucket.org/albertpark/multi-remote into develop
|\
| * 5d5bcfb 16 hours ago [albertpark] - Code formatting
* |   7939ee5 16 hours ago [albertpark] - Merge branch 'develop' of https://bitbucket.org/albertpark/multi-remote into develop
|\ \
| |/
| * 9f0461a 17 hours ago [albertpark] - Compatibility with Linux Bash version 4.1
* | 05c13aa 17 hours ago [albertpark] - Improved README.md description and usage example
|/
* c75afb1 17 hours ago [albertpark] - Added configuration option to select the remote origin
* 1c17122 18 hours ago [albertpark] - Improved error message when missing options
* d311e0f 22 hours ago [albertpark] - Only displaying the remote add command if it was successful
...

We can see that we are back to the original with the ugly merge bubbles. If you have not pushed the revent changes back to the remote here is where you can save off your backup in case you missed it the first time.

Note : Git uses a garbage collector that ensures that the local repository is optimized so you may not be able to undo your changes if you reset your commits were a long time ago.

Force Push

This time we will clean up the merge bubbles by resetting to the commit HEAD where the bubble starts c75afb1.

$ git reset --hard c75afb1
HEAD is now at c75afb1 Added configuration option to select the remote origin

→ $ git lg
* c75afb1 17 hours ago [albertpark] - (HEAD -> develop) Added configuration option to select the remote origin
* 1c17122 18 hours ago [albertpark] - Improved error message when missing options
* d311e0f 22 hours ago [albertpark] - Only displaying the remote add command if it was successful
* 158a930 22 hours ago [albertpark] - Removed the set -e flag in case there exists an origin
* 19b1e29 23 hours ago [albertpark] - Updated the logic for checking the .git folder
...

From here we will force a push so we can remove the merge bubbles:

→ $ git push --force
To https://bitbucket.org/albertpark/multi-remote.git
 + 247501f...c75afb1 develop -> develop (forced update)
Total 0 (delta 0), reused 0 (delta 0)

→ $ git lg
* c75afb1 18 hours ago [albertpark] - (HEAD -> develop, origin/develop) Added configuration option to select the remote origin
* 1c17122 18 hours ago [albertpark] - Improved error message when missing options
* d311e0f 22 hours ago [albertpark] - Only displaying the remote add command if it was successful
* 158a930 23 hours ago [albertpark] - Removed the set -e flag in case there exists an origin
* 19b1e29 23 hours ago [albertpark] - Updated the logic for checking the .git folder
...

Viola! The repository is merge bubble free. From here you can use the backup copy and merge the code back to the remote.

Note: Keep in mind this is not recommended method when you are on a repository with a team as this create a lot of problems for other people.

Pull Rebase

Going forward we do not want this to happen again. So if you have are working on a remote on mutilple locations you will need to update your local by doing a git pull. What many people fail to understand is this is a shortcut for git fetch followed by a git merge FETCH_HEAD. So to prevent this to happen all we need to add is a simple --rebase option at the end of our git pull command:

→ $ git pull origin --rebase
error: cannot pull with rebase: Your index contains uncommitted changes.
error: please commit or stash them.

Rebase Autostash

When you see the following error it means you have changes into your code. There is another option you can add to resolve this error:

→ $ git pull origin --rebase --autostash
Created autostash: 5b587d7
First, rewinding head to replay your work on top of it...
Applying: Compatibility with Linux Bash version 4.1
Applying: Code formatting
Applied autostash.

Extra

Best rule should be to always use the --rebase and --autostash option when using the git pull command. In case we forget to add these options in our commands we can actually set these up in our global configuration:

→ $ git config --global pull.rebase true
→ $ git config --global rebase.autoStash true

The --autostash option only works with --rebase, so it makes sense to set these two together.


References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment