Now that you’ve seen how to do fetches, merges, and pulls from a remote tracking branch within Visual Studio, let’s rinse and repeat from the command line. Personally, it’s been easier to first grasp these concepts using Visual Studio, then rinse and repeat at the command line level.
I have to know the truth behind what the UI is doing 🙂
If you want to view the full list of remotes, similar to the full list shown in Team Explorer – Branches
From the command line, you can do
$ git branch -a
You’ll see the same list (well almost the same list. I’m not sure yet what the remotes/origin/HEAD is doing yet… stay tuned unless someone wants to beat me to the answer in the comments!)
Note how the local branch `for-review` is listed first (which kinda gets blended in color-wise with the command), then master, then the remote tracking branches.
Something that has confused me for a long time until I wrote yesterday’s post was whether “remotes/origin/why-not” was the same as “origin/why-not” or even the made-up “remotes/why-not” (which I don’t think a branch is ever referred to as such). Now that I can visualize what both the command line and Visual Studio are doing, it’s easier to get my head wrapped around these remote tracking branches.
Suppose this time you have conflicts when you do a Pull, meaning your local branch had a conflicting change that was committed locally (but not yet pushed – see Outgoing Commits 1 in screenshot below) and someone else (let’s say you via GitHub.com UI) made a corresponding conflicting change on the remote.
Here’s the UI setup in Team Explorer. Click on Pull.
Git halts the pull operation (at the merge portion) when it detects the conflicting changes, as expected.
From here it should be familiar territory by now. Clicking conflicts brings you to a merge conflict screen.
Clicking Merge brings up the 3 way merge tool (or choose a take remote or a keep local). If you go the Merge tool route, make sure you click “Accept Merge” at the top. Gets me every time.
Once you’ve accepted the merge (or choose to use the remote or local version), click Commit Merge.
Now we have to commit those our resulting merge. Click Commit Staged in Changes pane in Team Explorer.
and you’re done! Reviewing the local master history shows the merge commit now as the tip.
Still thinking re yesterday how a Pull is different than a Fetch + Merge. I guess if you know you want to download changes, but not ready to deal with any potential conflicts at this time (e.g. going offline for a while or got other things to do right now), Fetch is the way to go. If you know you’re ready to start playing with the code on your local branch, then Pull is the way to go, I think.
Today’s tip shows how to combine doing a Fetch and a Merge by using the Pull command.
Suppose you have some incoming commits that you’re ready to merge into your local branch. In this example, I’ve create a new file on master on GitHub and I want to bring that commit into my local master branch.
Instead of fetching to review the commits that are going to be applied, we’ll assume you’ve already looked at GitHub to see what will be merged in.
The result of the Pull command shows a message at the top of the Team Explorer.
Viewing the history on the master branch shows the tip (the top of the branch) having the newly merged in commit from GitHub.
This begs the question: Why use Fetch? Why not always do a Pull? I believe the answer is
- if you want to verify what commits have been downloaded
- if you want to know if you’ll run into any merge conflicts before doing the Pull (the merge portion of Pull). However, I’m not sure how you can know if you’re going to have any merge conflicts, if you haven’t first merged the commits somewhere. I guess you could manually review the changes. Perhaps someone reading this knows what I’m missing.
In yesterday’s example, you saw how to create a local branch from a remote tracking branch. In today’s tip, you’ll download new changes from the server into your local branch.
Suppose you know there are changes on a GitHub repo (in today’s example) you want to download to your computer.
First, switch to the branch you want to pull down, e.g. `for-review` is the branch with the changes I want. You can go to Team Explorer – Sync pane and click Fetch under Incoming Commits (or at the top of the pane).
After fetching, the window will show the new commits that have been downloaded but not applied to my local branch. That’s why this says “Incoming Commits”. The remote tracking branch remotes/for-review has these two commits (downloaded somewhere – not sure exactly where) but they have not been merged into your local branch (because we only “Fetched” the incoming commits, but haven’t done anything with them yet.)
Now suppose you are ready to do something with these “incoming commits”, i.e. get the into your local branch `for-review`. Remember, your local branch is a just branch of the remote tracking branch, so you need to merge these 2 commits from the remote tracking branch into your local branch.
The only thing that should look differently is the from branch name “origin/for-review”.
Click Merge to merge in the two incoming commits from the remote branch.
Go to View history to see the resulting timeline.
Sync will show 0 incoming commits now that they have been merged.
Yep, I already know what you’re thinking. I’m breaking down the steps manually and there’s this thing call Pull. Stay tuned to tomorrow’s tip 🙂
Similar to yesterday’s tip, but today, you’ll see how to resolve a conflict when rebasing within Visual Studio.
Suppose you have the same line in the same file modified in different branches. Just something simple to trigger a merge conflict. Or more likely, you’ve added one file in master and you’ve added another file in an experiment branch. Then you get a conflict when rebasing because your project file needs help merging the two newly added files.
First, you’ll get the message that there are conflicts.
Click on the Conflicts: 1 link.
Clicking on the Merge button will bring up the built-in merge tool.
Make whatever selections you want, and then hit Accept Merge.
Now View Changes, as you’ve resolved the conflicts, but still need to finish the rebase.
And finally finish the rebase! (For some reason, I can’t stop hearing the Mortal Kombat game in my head.)
And now you’ll see that the experiment branch has been merged onto master.
Suppose you’ve added a new file to your solution in a branch called `experiment` for experimental purposes. You are happy with this new file and want to merge this back into master. Well, let’s say you (or someone like you*) made a change in master.
Since this is on your local machine, you can decide “do I want to have the history of the experiment branch or do I want a clean, linear timeline?” Guess which adventure you’re going to choose today 🙂
Here’s the visual setup.
Notice how the tip of experiment has a commit that’s not in Master, and vice versa, the tip of master has a commit that’s not in experiment.
First, we’ll use Team Explorer to rebase experiment unto master. BTW I love how Team Explorer uses full sentences to confirm your intent.
Now after the rebase, you’ll see two things:
- The commit from master is now shown in the experiment branch (recall the visualization from previous posts – the master pointer is now behind experimental pointer)
- The commit ID for “added experimental code” has changed (You can compare to the first image in this blog post to verify)
And lastly, let’s get master caught up to experiment by doing a merge. Yay for full sentences in the below image!
And now when you refresh Master history, you’ll see the changes.
*I couldn’t resist. I listened to way too much Matchbox 20 in my youth, “I wish the real world would just stop hassling me .”
This might be a bug with the Git Visualization tool. Via the command line, if your branch can already perform a fast-forward merge, Git won’t let you do a rebase. However, the visualization tool allows for it.
Suppose you create a new branch `experiment` and add 1 commit. Then you try to do a rebase on master. You’ll get the following error.
My guess why this makes sense is because Git is protecting you (or others from you) from rewriting history. In other words, there’s nothing to rewind, so no rebase.
However, the visualization tool allows for it, but I think this is a bug. Hence why always important to experiment IRL!