Month: April 2017

How to download changes from a remote branch (e.g. GitHub) into your local branch in Visual Studio – 117

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).

Fetch incoming commits from branch for-review

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.)

downloaded commits

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.

merge from origin/for-review into for-review 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.

for-review history shows the 2 incoming commits

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 🙂

How to create a local copy of a remote branch in Visual Studio – 116

Suppose you’ve cloned a project from a GitHub repo that contains multiple branches. By default, Git pulls down the main tracking branch (e.g. master in most cases). That’s why you see a local checked-out (bolded) master and a remotes/origin master branch.

For the other branches under remotes/origin, Git doesn’t automatically pull these down. The branches listed under remotes/origin are called “remote tracking branches”. I believe these are also referred to as “remote branches” but the “tracking” is implied. Can you have a remote branch that isn’t a remote tracking branch? I guess not. I guess even if you checked out a “remote tracking branch” without the tracking flag (or without the checkbox checked), you’d still have the original “remote tracking branch” alongside the local non-tracked branch.

Team Explorer - Branches showing remote tracking branches

You cannot check out these remote branches directly. I guess if you could, you’d be working directly on the server instead of your local machine, which wouldn’t make too much sense, and probably wouldn’t be possible since a bare git repo (aka the git server you’re checking out from) doesn’t have a concept of a working directory. No idea. Just thinking out loud here.

Suppose you want to checkout the `for-review` branch to do work. First you’d need to create a new branch. Note just like 13* we’re going the long way around, meaning we’re not going to choose the “checkout” command in the context menu. We’re going to manually create the local branch first, then checkout, to see the process.

First, right click on the remote branch, and select New Local Branch From on the context menu, just as if you were creating any other branch. The Create Branch window section will appear.

creating a local branch from a remote tracking branch

Note how Visual Studio auto-populates the name of the local branch as `for-review` You could change the local branch name. You could also do `private string @long`. I’m sure the `@long` is far worse.

Checking the Create Branch button creates the local `for review` branch. Because the default is the Checkout branch option checked, the `for-review` is bolded.

for-review local branch checked out

I believe the Checkout command on the context menu for a remote branch will perform the above steps, but I’m not sure if there are any differences. For example, I’d assume the checkout command keeps the defaults (e.g. Track remote branch and Checkout branch – of course). In any case, when I’m trying to learn something new, it is helpful for me to see what is going on step-by-step as much as possible.

If I have any of the above terminology wrong, please let me know!!

*Heaven Sent was one of the best Doctor Who episodes in a LONG time. Wow, just wow.

How to resolve a conflict during a rebase in Visual Studio – 115

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.

conflicts message in Team Explorer

Click on the Conflicts: 1 link.

resolve conflicts window in Team Explorer

Clicking on the Merge button will bring up the built-in merge tool.

Make whatever selections you want, and then hit Accept Merge.

Accept merge in VS tool

Now View Changes, as you’ve resolved the conflicts, but still need to finish the rebase.

resolve conflicts - view changes

And finally finish the rebase! (For some reason, I can’t stop hearing the Mortal Combat game in my head.)

rebase in progress - continue

And now you’ll see that the experiment branch has been merged onto master.

experiment pointer above master pointer

How to do a rebase in Visual Studio – 114

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.

experiment vs master branches histories side by side in VS

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.

rebase from the current branch experiment onto branch master

Now after the rebase, you’ll see two things:

    1. 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)
    2. The commit ID for “added experimental code” has changed (You can compare to the first image in this blog post to verify)

master pointer shown in experiment branch history

And lastly, let’s get master caught up to experiment by doing a merge. Yay for full sentences in the below image!

Merge from branch experiment into current branch master

And now when you refresh Master history, you’ll see the changes.

master pointer pointing to same commit as experiment

*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 .”

How to understand the "current branch is up-to-date" error when rebasing – 113

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.

Current branch experiment is up to date

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!

thinking this visualization is a bug

How to practice a rebase on the command line – 112

In yesterday’s tip, you saw how to visualize a rebase. Today’s tip allows you to practice performing a rebase via the command line.

First, we’ll have master contain one extra commit that isn’t included in your `experiment` branch. For example, you were working on `experiment` and a new commit was added to master (either by you, e.g. bug fix, or from a remote).

master log containing a fileMaster commit

Next, you’ll have a commit on `experiment` that isn’t on master.

experiment log adding a fileExperiment not on master

Since you are on your local machine, you can rewrite history because you haven’t shared or pushed these changes.

From the `experiment` branch, you’ll run

$ git rebase master

git rebase master

and then checkout master and merge in experiment to do the fast-forward merge.

fast-forward merge

One thing the visualization is able to emphasize is how the commit IDs are different for the “added fileExperiment”.

new commit ID

The commit ID `f041b71` is no longer `1601e09` (as shown in the 2nd image for added fileExperiment).

How to visualize a rebase in the Git Visualization tool – 111

If it wasn’t for this visualization tool, I’d never grasp Git concepts. Today’s tip follows the Git documentation for Rebasing

Suppose you’re experimenting locally on one branch (called creatively, `experiment`) and you want to rebase back onto master. For now, let’s imagine that master is a remote that you’ve cloned from somewhere. When the time comes to push those changes back, you don’t want your local Git history* to show merges commits from your local explorations. You’re going for the linear “look! I got it all right on the first try” history.

visualization setup of master vs experiment branches

First, you’ll want to make sure you’re on the `experiment` branch.

Next, you’ll use the command to rebase your current branch (experiment) onto master. I silently verbalize “onto” as the preposition to help me understand what the rebase command is going to do.

$ git rebase master

rebase visualization

Note how the rebase results in new commit IDs. If you take nothing else away today, note this:

Whenever you do a rebase, you are changing history.

more on this later.

Now to “finish the rebase.” This is where I’m so grateful for this visualization tool. Before seeing what was happening, I’d thought everything would be done for me.  Thanks to the visualization I can see based on the master pointer that I need to merge the experiment branch.

$ git checkout master

$ git merge experiment

moving master up to experiment

This last step should look familiar. The rebase makes our history look like all of our changes were based on the last commit on master. This would be the equivalent of being on the last commit of master, checking out a branch, making commits, and then performing a fast-forward merge from master.

There are just so many moving parts here that a visualization tool helps greatly.

*I mentioned previously about doing rebases on your local git history. The rule of rebasing is you should never do it if those commits have been previously pushed or shared somewhere, since you’re changing history, and Git hates it when you change history. There are ways out of it, but I’m saving that to explore in October timeframe.

A good recap from the documentation (last sentence, of course. always amazing how the most important info is often found at the very end of a document or email. a trick someone taught me once is to write out what you want to say, and the reverse the order of the paragraphs. I guess this blog post is proof of concept 😉 since I’m leaving the most important piece at the bottom!)

In general the way to get the best of both worlds is to rebase local changes you’ve made but haven’t shared yet before you push them in order to clean up your story, but never rebase anything you’ve pushed somewhere.