Welcome!

Git SCM - Lab 201

This lab is a review of the git branch command and a discussion of the overall Git branching model. Branching is a feature available in most modern version control systems. Branching in other VCS's can be an expensive operation in both time and disk space. In Git, branches are a part of your everyday development process.

The implementation behind Git branches is much more lightweight than other version control system models. Instead of copying files from directory to directory, Git stores a branch as a reference to a commit. In this sense, a branch represents the tip of a series of commits—it's not a container for commits. The history for a branch is extrapolated through the commit relationships.

Throughout this lab you'll learn how to use;

Switch between branches

List, create and delete branchs

Join branches together with merge

Undo-ing changes using reset

Congratulations!

You've completed the scenario!

Scenario Rating

The most important takeaways from this lab are:

git checkout can be used to create branches, switch branches, and checkout remote branches

Steps

Git SCM - Lab 201

Step1 of 4

Step 1 - Git branch

Branching is a feature available in most modern version control systems. Branching in other VCS's can be an expensive
operation in both time and disk space. In Git, branches are a part of your everyday development process.

Git branches are effectively a pointer to a snapshot of your changes. When you want to add a new feature or fix a bug—no
matter how big or how small—you spawn a new branch to encapsulate your changes. This makes it harder for unstable code
to get merged into the main code base, and it gives you the chance to clean up your future's history before merging it
into the main branch.

The diagram above visualizes a repository with two isolated lines of development, one for a little feature, and one
for a longer-running feature. By developing them in branches, it's not only possible to work on both of them in parallel,
but it also keeps the main master branch free from questionable code.

Task

Prepare environment

To start off we need to prepare the environment, go ahead and clone the repository you created in the previous lab with:

git clone http://git.itworx.cloud/<username>/simple-html-app.git .

And inspect all branches in the repository with;

git branch

Which shows that you have one branch only called master. This is synonymous with git branch --list.

Creating Branches

It's important to understand that branches are just pointers to commits. When you create a branch, all Git needs to do is
create a new pointer, it doesn't change the repository in any other way. Then, you create a branch using the following command:

git branch my-feature

git branch delete-me

The repository history remains unchanged. All you get is a new pointer to the current commit.

Note that this only creates the new branch. To start adding commits to it, you need to select it with git checkout, and
then use the standard git add and git commit commands.

git checkout my-feature

And inspect all branches in the repository with;

git branch

Which will show you that you now have three branches and that the currently active branch is my-feature.

Let's introduce some changes and cause the history to diverge a little bit, create a new file called about.html
and add the below content to the file;

On this page you'll find the about us!

Let's add and commit our changes with;

git add about.html

git commit -m 'Add about us page'

Now let's diverge the delete-me branch, go ahead and create a new file called delete-me.html and add the below
content to the file;

Useless content that will be trashed later on!

Let's add and commit our changes with;

git add delete-me.html

git commit -m 'To be deleted later on'

Creating remote branches

So far we've been working on local branch operations. The git branch command also works on remote branches. In order to
operate on remote branches, a remote repo must first be configured and added to the local repo config.

git push -u origin my-feature

This command will push a copy of the local branch my-feature to the remote repo origin.

Deleting branches

Once you've finished working on a branch and have merged it into the main code base, you're free to delete the branch
without losing any history with. You'll need to switch to a different branch first before deleting the intended branch.

git checkout master

git branch -d delete-me

The -d option tells git to delete the branch. But it will complain that the branch has not been fully merged yet. This
is a safegaurd before losing a branch by mistake that has not been merged yet. Use -D to delete branch (even if not merged);

git branch -D delete-me

Pushed branches may still exist in remote repos after they've been deleted from the local repository. To delete a remote
branch execute the following.

git push origin --delete my-feature

This will push a delete signal to the remote origin repository that triggers a delete of the remote my-feature branch.

Step 2 - Git checkout

In Git terms, a "checkout" is the act of switching between different versions of a line of development. The git checkout
command operates upon three distinct entities: files, commits, and branches. In addition to the definition of "checkout"
the phrase "checking out" is commonly used to imply the act of executing the git checkout command.

The git checkout command lets you navigate between the branches created by git branch. Checking out a branch updates
the files in the working directory to match the version stored in that branch, and it tells Git to record all new commits
on that branch. Think of it as a way to select which line of development you're working on.

Task

Check out existing branch

git checkout demo-feature

Create a new branch

git checkout works hand-in-hand with git branch. The git branch command can be used to create a new branch. When you
want to start a new feature, you create a new branch off master using git branch new_branch. Once created you can then
use git checkout new_branch to switch to that branch.

The git checkout command accepts a -b argument that acts as a convenience method which will create the new branch and
immediately switch to it. You can work on multiple features in a single repository by switching between them with git checkout. Go
ahead and checkout a new branch with;

git checkout -b stable

The above example simultaneously creates and checks out yet-another-branch. The -b option is a convenience flag that tells Git to run git branch before running git checkout .

git checkout -b unstable stable

By default git checkout -b will base the new-branch off the current HEAD. An optional additional branch parameter can be passed to git checkout. In the previous example, stable is passed which then bases new-branch unstable off of existing-branch instead of the current HEAD.

Switching Branches

Switching branches is a straightforward operation. Executing the following will point HEAD to the tip of stable branch.

git checkout stable

Git tracks a history of checkout operations in the reflog. You can execute git reflog to view the history.

Checkout a Remote Branch

When collaborating with a team it is common to utilize remote repositories. These repositories may be hosted and shared or they may be another colleague's local copy. Each remote repository will contain its own set of branches. In order to checkout a remote branch you have to first fetch the contents of the branch.

git fetch --all

Uou can then checkout the remote branch like a local branch.

git checkout <remotebranch>

Step 3 - Git tag

Tags are ref's that point to specific points in Git history. Tagging is generally used to capture a point in history
that is used for a marked version release (i.e. v1.0.1). A tag is like a branch that doesn’t change.

Unlike branches, tags, after being created, have no further history of commits. This lab will cover the different
kind of tags, how to create tags, listing all tags, deleting tags, sharing tags, and more.

Git supports two types of tags: annotated and lightweight.

Annotated Tags

Annotated tags are stored as full objects in the Git database. To reiterate, they store extra meta data such as: the tagger name, email, and date. Similar to commits and commit messages Annotated tags have a tagging message.

Lightweight Tags

Lightweight tags are very much like a branch that doesn't change — it's just a pointer to a specific commit.

Task

Creating a Tag

In order to create a new annotated tag identified with v1.4, use;

git tag -a v1.4 -m "my version 1.4"

Which will create a new annotated tag with the commit message specified by -m option. This is a convenience method similar to git commit -m that will immediately create a new tag and forgo opening the local text editor in favor of saving the message passed in with the -m option.

To create a lightweight tag identified as v1.4-lw. Lightweight tags are created with the absence of the -a, -s, or -m options. Lightweight tags create a new tag checksum and store it in the .git/ directory of the project's repo.

git tag v1.4-lw

Go ahead and create few other tags with;

git tag v1.4-rc

git tag v1.5-rc

git tag -a v1.5 -m "my version 1.5"

Listing Tags

To list stored tags in a repo execute the following:

git tag

Your repository my have lots of tags at some point in time, to refine the list of tags the -l option can be passed with a wild card expression:

git tag -l *-rc

Which uses the -l option and a wildcard expression of *-rc which returns a list of all tags marked with a -rc prefix, traditionally used to identify release candidates.

Sharing: Pushing Tags to Remote

Sharing tags is similar to pushing branches. By default, git push will not push tags. Tags have to be explicitly passed to git push.

git push origin v1.4

To push multiple tags simultaneously pass the --tags option to git push command. When another user clones or pulls a repo they will receive the new tags.

git push origin --tags

Checking Out Tags

You can view the state of a repo at a tag by using the git checkout command.

git checkout v1.4

Which will checkout the v1.4 tag. This puts the repo in a detached HEAD state. This means any changes made will not update the tag. They will create a new detached commit. This new detached commit will not be part of any branch and will only be reachable directly by the commits SHA hash.

Return back to the master branch using git checkout master.

Deleting Tags

Deleting tags is a straightforward operation. Passing the -d option and a tag identifier to git tag will delete the identified tag.

git tag

git tag -d v1.4-lw

Protip

As a best practice try create a new branch anytime you're making changes in a detached HEAD state.

Step 4 - Git merge

git merge command lets you take the independent lines of development created by git branch and integrate
them into a single branch. git merge will combine multiple sequences of commits into one unified history.
In the most frequent use cases, git merge is used to combine two branches.

Preparing to merge

Before performing a merge there are a couple of preparation steps to take to ensure the merge goes smoothly.

Confirm the receiving branch

Execute git status to ensure that HEAD is pointing to the correct merge-receiving branch. If needed, execute
git checkout <receiving> to switch to the receiving branch. In our case we will execute git checkout master.

Fetch latest remote commits

Make sure the receiving branch and the merging branch are up-to-date with the latest remote changes. Execute
git fetch to pull the latest remote commits. Once the fetch is completed ensure the master branch has the
latest updates by executing git pull.

Now just to make sure that the master branch has the latest content from the upstream using;

git fetch

git pull

Merging

Once the previously discussed "preparing to merge" steps have been taken a merge can be initiated by executing
git merge <branch name> where is the name of the branch that will be merged into the receiving branch.

The useful --merged and --no-merged options can filter this list to branches that you have or have not yet merged into the branch you’re currently on. To see which branches are already merged into the branch you’re on, you can run git branch --merged.

Let's merge the my-feature branch into the master branch. First inspect the unmerged branch, use;

git branch --no-merged

Which will show you all the unmerged branches. Then start merged the my-feature branch, use;

At this point the local master branch is ahead of the remote master branch with one commit, use git push
to publish the local commits.

Delete merged branch

After you've merged the branch, it's now safe to do some house keeping and delete the merged branch, use;

git branch -d my-feature

Resolving conflict

If the two branches you're trying to merge both changed the same part of the same file, Git won't be able to figure out which version to use. When such a situation occurs, it stops right before the merge commit so that you can resolve the conflicts manually.

How conflicts are presented
When Git encounters a conflict during a merge, It will edit the content of the affected files with visual indicators that mark both sides of the conflicted content. These visual markers are: <<<<<<<, =======, and >>>>>>>. Its helpful to search a project for these indicators during a merge to find where conflicts need to be resolved.

here is some content not affected by the conflict
<<<<<<< master
this is conflicted text from master
=======
this is conflicted text from feature branch
>>>>>>> feature-717

Debugging Scenarios

Help

Katacoda offerings an Interactive Learning Environment for Developers. This course uses a command line and a pre-configured sandboxed environment for you to use. Below are useful commands when working with the environment.

cd <directory>

Change directory

ls

List directory

echo 'contents' > <file>

Write contents to a file

cat <file>

Output contents of file

Vim

In the case of certain exercises you will be required to edit files or text. The best approach is with Vim. Vim has two different modes, one for entering commands (Command Mode) and the other for entering text (Insert Mode). You need to switch between these two modes based on what you want to do. The basic commands are: