How to Work with Git Branches

Published Apr 25, 2018Last updated May 22, 2018
How to Work with Git Branches

In the current era, most software development companies work in a collaborative environment where several developers contribute to the same source code. While some will be fixing bugs the others would be implementing new and different features. The problem raises, how to maintain different versions of the same code base?

This is where the branch function shines! Branch allows each developer to isolate his/her work from others by creating a new branch from the original code base.

What Is a Branch?

Branch is an independent line of development. It works as a pointer to your next commits. Whenever a new branch is created, Git creates a new pointer while keeping the original code base untouched.

When you make your first commit in a repository, Git will automatically create a master branch by default. Every next commit you make will go to the master branch until you decide to create and switch over to another branch.

Creating Branches

Let's start with creating a new branch: git branch hello-world.

git-branch

This only creates the new branch. To start working on it, you will need to switch to the branch with git checkout. Now, you are ready to use standard git add and git commit commands.

You can see two different branches pointing to the same commit. How does Git know which branch is currently checked out? This is where the HEAD pointer comes into play!

git-branch-head-master

HEAD always points to the currently checked out branch or commit. In our case, it is the master. Let's git checkout hello-world and see what happens.

Git-branch-head-hello

As you can see, the HEAD is now pointing to the hello-world branch instead of master. The next step is to modify some files and create a new commit with git commit -m "commit message"

git-branch-new-commit

A new commit C5 was created in the branch hello-world. Pointers always move to the latest commit in that branch that we checked out. Changes in the hello-world branch did not affect any other branch. Branching enables you to isolate your work from others.

It is a common practice to create a new branch for each task (e.g. bug fixing, new features etc), which is a good practice because it allows others to easily identify what changes to expect, and also for backtracking purposes to understand why a particular code change is implemented. You can read more at Git Beginner's Guide for Dummies.

Create your own Ruby on Rails project and try it out! Make Rspec tests on a different branch and commit the changes.

Detached HEAD

As we have said before, HEAD always points to the currently checked out branch or commit. Checkout to a commit and see what happens with git checkout C0.

git-branch-checkout-commit

Now, the HEAD is pointing to C0. We are currently checked out to a remote branch. ==Is it possible to create a new commit while checkout to one?== Time to find it out! git commit -m "commit message"

git-branch-head-detached

The HEAD is detached and moves together with each new commit created. The newly created commit C6 is pointing to C0, that is now acting like a branch, but it is not.

Commits that are not reachable by any branch or tag will be garbage collected and removed from the repository after 30 days.

To avoid this, we simply need to create a new branch for the newly created commit and checkout to it. git checkout -b hotfix C6.

git-branch-hotfix

Always use branches when you are solving new problems to avoid disturbing your co-worker's features!

This post is originally published on Kolosek Blog.
Git Commands Ultimate Tutorial Part 2
In the previous Git Commands article, I wrote about how you can use Git options and what they can do. Today, we will extend our reach and discover everything there is to know about commonly used Git Commands.

Git Commands

Git commands are used to access the Git working directory and connect it to our remote repository, by making changes, viewing different files, and many other possibilities! Once your project is set, be sure to connect it with Git.

With the following commands and short descriptions, I will make it sure that you are ready to use Git whenever you need it. For a detailed description of all, the GIT commands please check git's official description.

$git config
You can use it to configure the author's name, email address, file formats and many more to be used with your commits.

git config --global user.name "Kolosek
git config --global user.email "kolosek@example.com"

$git init
By using this command you make sure that your git repository is initialized and creates the initial .git directory in a new or in an existing project. The output will be the following:

Initialized empty Git repository in /path/.git/

You can undo a $git init with rm -rf .git.

$git clone <path>
This creates a working copy of a Git repository from a remote source to your local repository. This is the first command you want to use when you are cloning a Git repository.

git clone /path/repository

Also, you can add the original location as a remote so you can easily fetch from it again and push it if you have permissions. Once the project has been cloned you can start working on it. Write your RSpec tests!

git clone git@github:user/repository.git

You can clone one specific branch at a time: git clone -b <branch_name><repository_url>:

git clone -b branch_name git@github:user/repository.git

$git add <file_name>
Add one or more files in your working directory to your index.

$git commit
Take all your changes written in the index to the HEAD branch with a -m message.

git commit -m "Commit these changes."

You can also commit any files you've added to git add, and also commit any files you've changed since then:

git commit -a

Note: Always commit all your changes even if its only a bunch of Capybara tests!

$git status
It shows you the status difference between an index and working directory files. Lists the files you've changed, untracked because they are only in your working directory and staged since they are ready to be committed.

On branch master
Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    File_name

nothing added to commit but untracked files present (use "git add" to track)

$git remote
Shows all the remote versions of your repository.

$git checkout <branch_name>: You can switch from an existing branch to another one or create a new branch and switch to it git checkout -b <branch_name>.

$git branch
With this, you can simply list all existing branches, including remote branches by using -a or create a new branch if a branch name is provided.

$git push
Pushes all changes to the remote repository.

git push origin <branch_name>

You can also delete a branch from your remote repository:

git push origin :<branch_name>

$git pull
Fetch and merge your changes in the remote repository to your working directory.

$git merge <branch_name>
Merges one or more branches into your active branch and if there are no conflicts it will automatically create a new commit.

In Kolosek, we commit all our changes to Git and make it sure to notify our team when they are merged with the rest of the application! Try to create your own application using Rails Associations.

$git diff
Show changes between your working tree and the index, between two branches, or changes between two files on disk. Example between branches:

git diff <source_branch> <target_branch>

$git reset
Reset your index and working directory to the state of your last commit.

git reset --hard origin/master

Note: git reset --hard will also undo the changes you made so far! Use git reset --soft if you want to keep your changes.

$git revert
Revert works in a very similar way to $git reset, but instead of resetting it will create a new commit that reverses everything introduced by the accidental commit.

$git tag
You can use tagging to mark a significant change you made, such as a release.

git tag 1.0.0 <commit_id>

Note: Always tag your new production releases. Try it out by implementing CarrierWave and adding a release tag to it!

$git log
It shows a listing of commits on a branch with corresponding details.

commit 134808af7c596be8d92c619f9efb94542874e1e3
Author: Kolosek <kolosek@example.com>
Date:   Fri Mar 23 14:24:54 2018 +0100

    [#1] First Commit

Conclusion

With this article, I have covered everything there is to know about Git commands. Don't forget, these are only the very basic and most commonly used commands. Hope this helped you to get started with Git!

Are you familiar with each of the mentioned commands?

Multiple Ways to Change Database Column in Rails
While working on a Rails application, we all have had to change the database column in some way. You can change the column name and the column type, as well as changing the column with the type conversion.

Changing the Column Name

Before you can change a column, you have to create it. Let's start with creating a model for profiles.

class CreateProfiles < ActiveRecord::Migration
  def change
    create_table :profiles do |t|
      t.references :user
      t.string :avatar
      t.string :name, null: false
    end
  end
end

Once you run rake db:migrate the profiles data will be migrated to the database. Then, change the column name. How can you do this?

There are 3 different ways to achieve that:

  • Making a new migration.
  • Fixing the existing migration.
  • Making a migration in order to change the table.

Note: Be sure to run rake db:migrate at the end of all the examples, so the changes will be saved in the database.

Making a New Migration to Change the Column Name

First, you need to create a new migration:

rails g migration rename_profile_name_to_full_name

Then, add a rename_column in the newly generated file, specifying which table and what column you want to change:

class RenameProfileNameToFullName < ActiveRecord::Migration
  def change
    rename_column :profiles, :name, :full_name
  end
end

And you are done!

Fixing an Existing Migration

Before you start, you should rollback the migration that you want to fix. Depending on when the migration was made you can do it in the following ways:

  • The last migration: rake db:rollback.
  • Calling the migration version: rake db:migrate:down VERSION=YOUR_MIGRATION_VERSION .

Once the rollback has been completed you are free to edit the model.

class CreateProfiles < ActiveRecord::Migration
  def change
    create_table :profiles do |t|
      t.references :user
      t.string :avatar
      t.string :full_name, null: false
    end
  end
end

Making a New Migration to Change the Table

You should only use this option when adding multiple changes to the table at once.

Start by creating a new migration:

rails g migration change_profiles

After the file has been created, specifying which column you want to change by adding a rename type on its place:

class ChangeProfiles < ActiveRecord::Migration
  def change
    change_table :profiles do |t|
       t.references :user
       t.string :avatar
       t.rename :name, :full_name   # t.string -> t.rename
    end
  end
end

Always run your RSpec tests after each change to the database to make it sure everything is working as intended. Also, please be careful with reserved names in Rails or SQL when renaming a column. Here is a list of reserved words to help you.

Changing the Column Type

This is a common change that every programmer encounters - you start with a model having an attribute of one type and then you realize it needs to be another. At first, you might think that you should store a profile name as a text when it should actually be a string.

Don't worry! You can easily fix this by generating a new migration:

rails g migration change_name_to_be_string_in_profiles

Now, open up the migration file and edit it in the following way:

class ChangeNameToBeStringInProfiles < ActiveRecord::Migration
  def change
    change_column :profiles, :name, :string
  end
end

Note that change_column is an irreversible migration. It will cause an error if you try to rollback. To prevent this, modify the usual change method in the migration to use two separate up and down methods like this:

class ChangeNameToBeStringInProfiles < ActiveRecord::Migration
  def up
    change_column :profiles, :name, :string
  end
  
  def down
    change_column :profiles, :name, :text
  end
end

Test this out! Start by creating a profile factory and change the name type to a string.

Changing the Column Type - Errors

There are times when simply changing the column type will not work. When you try to write a migration that converts a string column to an integer:

change_column :profile, :age, :integer

Your database will complain and raise an error:

PG::DatatypeMismatch: ERROR:  column "age" cannot be cast automatically to type integer
HINT:  Specify a USING expression to perform the conversion.

To solve this, we will follow the hint and specify in our migration how data should be converted. There are two ways to do this:

  • change_column :profile, :age, 'integer USING CAST(age AS integer)',
  • change_column :profile, :age, :integer, using: 'age::integer'.

That's it! Hope these steps helped you to change the database columns to your liking.

Discover and read more posts from Nebojsa Zoric
get started