Welcome to Part 4 of this review of the Pluralsight course Using Git with a GUI by Xavier Morera.
Xavier is an entrepreneur, project manager, technical author, trainer, Certified Scrum Professional & Scrum Master and Certified Microsoft Professional and Microsoft MVP.
He has spent a great deal of his career working on cutting-edge projects with a primary focus on .NET, Solr and occasionally iOS. He’s also a fellow Simple Programmer blogger.
In the module we go beyond the basics.
Also in this series:
Git to the Next Level (With a GUI)
In this module we get started with a quote:
“Small commits allow for big wins”
Cherry-pick is a very useful command for moving a specific commit from one branch to another.
Demo: Cherry Pick
We see three branches: master, NewBranch and ConflictBranch.
On NewBranch there’s a “On new branch.txt” that we want to move into master.
There’s another commit to “Conflict file.txt” that we don’t want to commit.
Cherry Pick is one of the options in the right click menu. Just right click on the commit that you want to move to master and then left click on Cherry Pick.
We then see a confirmation dialog. Click Yes. That’s all there is to it!
Blame and Search
Blame helps to determine who made changes and why. In TFS it’s known as annotate.
Xavier also describes the search functionality available in SourceTree.
Using Blame is really simple: right click a file and choose Blame Selected.
Xavier also shows off the search functionality found in the Search tab. We see there’s a dropdown offering the categories:
- Commit Messages
- File Changes
Merging vs. Rebasing
Xavier compares and contrasts merging with rebasing.
Whereas merging brings two branches together, rebasing applies commits on top linearly.
Xavier covers the Golden Rules of Rebasing: Don’t rebase in a public branch.
He advises us to always think “Is anyone else looking at this branch?”
Xavier teaches the pros and cons of merging and rebasing.
Demo: Merge vs. Rebase
Xavier starts off with a merging demo and we see the branches get merged together.
Then we start over for the rebase demo. History is linear here – we don’t see the changes as happening in different branches.
Fast Forward Merge
If there are no commits in master, a fast forward merge is possible, and it’s like a rebase.
Demo: Fast Forward Merge
In this demo Xavier selects the checkbox “Create a new commit even if fast-forward is possible”.
Then he demonstrates a hard reset for discarding changes.
It is down to personal preference. I like to do standard merge commits so that history is not rewritten.
Tags are used to mark important points in history.
Typically tags are used to mark releases, but you can use them for other uses as well or instead.
There are two types of tags: Lightweight and Annotated.
A lightweight tag is a pointer to a specific commit.
An annotated tag is a full object with SHA1, tagger name, email, date, message.
The default type of tag is the annotated tag.
Tags can be pushed to the origin, as we see next…
Xavier begins by adding a tag to the master branch.
We see SourceTree’s Add Tag dialog with radio buttons “Working copy parent” and “specified commit”.
There’s also a “Push tag” checkbox, and an advanced options section.
In the advanced options sections there are “move existing tag” and “Lightweight tag (not recommended)” checkboxes.
We can also change from the Add Tag tab, to the Remove tag tab.
If you try to go back in time and commit directly, it will not have a head, and SourceTree gives the warning dialog:
Checking out this commit will create a detached HEAD, and you will no longer be on any branch (unless you subsequently create a new one).
Are you sure that’s what you want?
Xavier says there is a way of checking out on a specific commit.
Demo: Detached Head
We see that we can switch to a new branch by double clicking on the branch label on a commit.
But if you double-click on a commit that’s not the tip of a branch, then you get the warning appear about creating a detached HEAD.
If we click OK then we see a new label “HEAD” appear beside the commit message.
Xavier shows us a better alternative using the New Branch dialog.
The moral of this lesson is don’t check out a specific commit because that will create a detached head.
We can rewrite history, using the rebase interactively command:
> git rebase -i
It’s not recommended to do this as part of your daily workflow. Never amend public comments.
Demo: Reordering Commits
We don’t have the option to rebase interactively from a child commits. We find the parent commit 7fd5e3a (which was committed before the children),
right click on it and choose “Rebase children of 7fd5e3a interactively…”
We then see a new dialog with the title “Interactive rebase from d8e52c3” and there are two commits here that we can reorder. We also have the options:
– Edit Message
– Squash with previous
Xavier shows us how to reorder these commits.
Editing and Amending Commits
We can edit commit comments on the command line with
> git commit –amend
We can also change the author of one of our commits
> git filter-branch
Using SourceTree, this is even easier, as we’ll see in the next lesson.
Demo: Editing and Amending Commits
Xavier adds the file “this file goes also with first file added.txt”, stages this change, and clicks Commit.
Now, in the commit window there’s a dropdown “Commit options…” and one of the options here is “Amend latest commit”
This option adds the file to the existing commit. So this can be useful if we accidentally missed off a single file from our earlier commit.
We can also change the commit message using Rebase interactively. In the Interactive rebase screen we click the “Edit Message” button and then update the commit message as we like.
Sometimes we might end up in a situation with a load of commits with not very useful “WIP” (work in progress) commit messages.
We can bundle these together with the squash command. This is another one of the rebase interactively options.
To squash, or not to squash…
Squashing is a controversial topic. Xavier is on the “We’re all adults here” side of the debate.
As long as you know what you are doing, it can make your history more readable.
Demo: Squash Commits
Again this trick is done in the Interactive rebase dialog. Either click the “Squash with previous” button, or drag the top commit down to the one below it.
Xavier warns that we should try to avoid deleting.
However we have the ability to do this by right clicking on a commit and choosing “Reset current branch to this commit”.
Demo: Deleting Commits
There are three different modes:
Soft – keep all local changes
Mixed – keep working copy but reset index
Hard – discard all working copy changes
Xavier demonstrates all of these options.
If you accidentally commit something you shouldn’t have, it is better to reverse the commit that to delete it.
> git revert
Demo: Reverse Commit
We see that this is done in SourceTree through the right click menu, and the option is “Reverse commit…”
This displays a confirmation dialog, and if we choose Yes and new commit is made that reverses the earlier commit.
Recovering Deleted Commits
What if you accidentally HARD delete a commit that you needed? You can recover from this, but it’s not something that you can do within SourceTree.
> git reflog
> git fsck –lost-found
Demo: Recovering Deleted Commits
Xavier demonstrates this using the Windows Powershell command line:
> git fsck –lost-found
We see a list of all dangling commits. But we don’t know which one we need to recover, so we type:
> git reflog
We find the SHA1 that we need, and copy it. Then we confirm this is the correct commit:
> git show 351c1f9
We see that this is the commit that we need to recover. We do this by merging:
> git merge 351c1f9
If we need to perform an action that isn’t available in SourceTree, one option is to create scripts via custom actions.
Demo: Custom Actions
Suppose we want to edit an HTML file. We open the current version, and see it opens in the browser rather than an editor.
In SourceTree Tools->Options there’s a Custom Actions tab.
Here we can add a new custom action, giving it a menu caption, and the path of the program we want to execute.
We also specify $File as the parameter.