Tag: visualizations

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.

How to make a commit in a detached HEAD state – 098

And one more quote from the same stack overflow answer, “it will still allow you to make commits (which will update HEAD), so the above short definition is still true if you think of a detached HEAD as a temporary branch without a name.”

What? We can still make commits? in a detached HEAD state?

Let’s be brave and give it a try in the visualization tool.

If we do a ‘git commit’ in the detached HEAD state, the visualization tools shows a commit being made to the side.

visualizing commit made in detached HEAD state

P.S. Have I proclaimed my love of this git visualization tool yet today?

So what on earth now? we have this thing floating out in nowhere. Well, we know it is a nameless branch… and we know we can merge branches… let’s try to merge it!

First, we’ll checkout master.

back to non-detached head but commit still floating out there

Then we’ll do the merge and verify the git log.

merged in floating git commit

and thus conclude my mathematical proof I truly have no idea how people are able to keep track of these one-off commits or whatever is going on in git without visualization tools. QED.

How to think about what the HEAD thingy actually is in Git – 097

My learning preference is through hands-on experimentation. I like taking things apart, putting them back together, or trying to break stuff. So let’s break apart this HEAD thingy.

According to this SO answer, it is a file.

saraf@TheBlueDog  ~/Source/Repos/scrap/detachedHeadPractice (master)
$ cat .git/HEAD
ref: refs/heads/master

and that file contains some content. I’d assume “ref” means reference, and “master” is the master branch we’ve been playing with. I’m not sure what “refs/heads/master” actually stands for, but I’ll figure that out later.

I keep hearing HEAD referred to as a pointer. This would make sense if it is a file that only contains the location(?) where to point to. That answers the literal question.

But what does the HEAD pointer do?

According to this stack overflow answer, “HEAD is a reference to the last commit in the currently checked-out branch.” Considering we have master checked out, that makes sense. Doing a git log would show all the commits in the repo.  If we switched to a branch and did a git log, we’d see all the commits for that branch.

But what about the detached HEAD state from yesterday?

Continuing with the same stack overflow answer, “A detached HEAD is the situation you end up in whenever you check out a commit (or tag) instead of a branch.”

Yep, we saw that yesterday. HEAD is pointing at the 2nd commit, whereas master is pointing at the 3rd.

visualization tool showing a detached HEAD state 

Now I had to re-read this line from the same stack overflow answer, “In this case, you have to imagine this as a temporary branch without a name; so instead of having a named branch reference, we only have HEAD.”

A temporary branch without a name??

Okay, what I think is happening is that if you were in a detached state (as shown above) and did a git log, you’d only see 2 commits, not 3.  Since you are seeing 2 commits, you are still technically on a branch. It’s just that this branch doesn’t have a name.

In other words, a Git pointer never points to just a single commit. A git pointer points to the last commit in that series of commits (which I guess is where the temporary nameless branch concept comes from). Which now begs the question… what’s really a git branch?

How to practice getting into and out of a detached HEAD state – 095

I promised that this blog would be a pun-free zone, but I must recommend Terry Pratchett’s The Thief of Time. It’s the last book of the “Death”  series. In fact, I recommend starting with Soul Music. Anyways I kept thinking of that creature as I wrote this tip.

So far, my two biggest lightbulb moments have come from learning about `git reflog` and this git visualization tool. Nothing came close to making sense until I combined those two.

Let’s use the visualization tool to practice getting in and out of a detached HEAD state.

First, let’s make a few commits…

initial setup in visualization tool

Next let’s checkout to the previous commit. Note: it helps to type in the commit id correctly, so ignore the “can’t find commit id”

visualization tool showing a detached HEAD state

Notice in the image above indicates that we’re in a detached HEAD state. Previously, I would have panicked because my last commit (the one master is pointing to) wouldn’t show up in the git log. But now because of this visualization tool, I can see that master is still there and that HEAD is just pointing at the previous commit.

To get out of the detached head state, you’ll need to git checkout master.  Previously, I would do git checkout commitID-master-is-pointing-to and still be in a detached state, frustrating me to no end.

back to a non-detatched head state

Now you’ll see that HEAD is pointing to master and we’re no longer in a detached HEAD state.

Tomorrow we’ll go over getting into and out of a detached HEAD state via the command line.

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. 

How to create a branch in Visual Studio – 088

It seems that I have to write these tips in triplicate: 1. command line, 2. Visual Studio, 3. git visualization tool. But that’s been the only way to prove to myself I’m grasping the concepts.

Command line

A college French professor once gave me the advice to never use contractions in class unless I was prepared to never ask him to slow down. I had just learned the equivalent of “I do not know” vs “I don’t know” (something like that).

Applying that advice to software, I don’t want to start using git shortcuts by combining commands until it is clear what the two commands are independently doing. (Yep, I’ll show the shortcut in a second… )

First, you’ll want to create a branch:

> git branch my-branch

Next, you’ll want to switch to that branch:

> git checkout my-branch

git branch addColor; git checkout addColor

Git Visualization

Okay that’s pretty straight forward, but what’s happening conceptually?

git visualization of creating and switching a branch

We are on master when we created a branch called addColor while on master and then switched to addColor.

The take home message is that addColor has everything that master has because we created the branch addColor while on Master.

Git Command Line Shortcut

Before we jump into the IDE, let’s take a sneak peek at that shortcut.

Note: in case anyone is following along at home, I first switch back to master to delete the addColor and then recreate using the shortcut.

The shortcut is

> git checkout -b addColor

deleting branch and then recreating using the shortcut

This shortcut says to checkout to addColor and if it doesn’t exist, create it.

Visual Studio

When you’re in Team Explorer, you can go to Branches, right click on the branch you want your new branch to be based on, right-click, and select New Local Branch From…

New Local Branch From... command in Team Explorer - Branches

Then give your new branch a name (and verify in the drop down you picked the correct branch) and leave the checkbox checked…

checkout branch option in Team Explorer

If you have the Checkout branch checkbox, you’re telling VS to create the branch and do the checkout so you’re now on the addColor branch instead of master.

If you uncheck it, it is the equivalent of creating the branch on the command line, but staying on master.

To confirm you’ve created and switched to the addColor branch, you’ll see that addColor is now in bold.

branches showing addColor now checked out

And the branch is also shown in the Visual Studio status bar.

addColor from status bar

How to recover from the "oh no! I did a git reset and now my files are gone!" – 087

If you don’t know about git reflog, your life is about to get much, much better. Prepare yourself. Git is about to make just a bit more sense.

Note: I use the git visualization tool at the bottom of this post, in case you want to jump straight to the “How on earth is this possible?! I give up. Git is just magic.”

Using yesterday’s tip, suppose you have a repo with 6 files each with their own commit.

git bash showing 6 commits

Cool. Now let’s say you did a `git reset –hard <commitID for file4>` to reset back to file 4. Note: any flavor of git reset will work for today’s scenario, since we’re not making any changes in our working directory (or so I think).

To recap these past several days:

  • git reset changes history and should be avoided if you’ve already shared those commits with others (e.g. you use it when you haven’t pushed yet.)
  • git revert undoes a commit by creating a new commit with those changes uncommitted (wow, what a sentence. My apologies.)

image

Notice how the above image confirms the git log only shows the commits up to file 4.

In addition,`ls` and `git ls-files` shows how files 5 and 6 are “gone”!

ls and git ls-files not showing files 5 and 6

will the real Git Log please stand up? please stand up. please stand up.

The command`git reflog` will show you the actual history of your git commands AND THEIR COMMIT IDS!!

output of git reflog

what?! what?! what?!

The lightbulb moment for me was that git was keeping those commits around, and not to mention git is also keeping an actual log of everything going on alongside my repo’s git log.

Let’s get those files back.

You’re going to do another git reset, but this time, you’re going to change history by rolling forward instead of rolling backwards.

so you’ll do `git reset –hard <commit id for file 6>`

git reset --hard commitID showing files 5 and 6 come back

and all our files are back. In fact, if we do a `git log` we’re back to where we were at.

git log showing all commits back

How on earth is this possible?! I give up. Git is just magic.

Let’s learn some magic tricks using the git visualization tool at http://git-school.github.io/visualizing-git/

alrighty. let’s rinse and repeat the setup

git visualization showing head and master at file 3

notice how the commits for files 4, 5, and 6 are there, but just dotted out (or whatever the official term is).

So we never “deleted” those commits. We just told git to hide them from ourselves, but not from git.

Now for the magic. We can do a reflog here in this tool.

using git reflog and git reset back to file 6 in tool

Notice how HEAD and master pointers just move back to that commit ID. That’s it. These HEAD and masters pointers are just that… pointers.

This is why people say “don’t delete your .git folder and start over.” Your changes aren’t “gone”. They are just playing hide and sneak because you told them to.

Got to  get back. Back to the past. Samurai Jack!!