GitPopular Posts

Get Going With Git — Part 2

In the previous post, we discussed the workflow and basic commands of Git. In this post, we will discuss Git branching in detail.

Branching means you diverge from the main line of development and continue to do work without messing with that main line.

Git stores data as snapshots rather than as a series of changesets or differences. Git stores a commit object that contains a pointer to the snapshot of the content you staged when you committed. When you make changes and commit again, the next commit stores the pointer to the commit immediately before it.

Creating a new branch

When you create a branch, Git creates a new pointer to the same commit you are currently on.

$ git branch feature

Git knows which branch you are on, but how does it do that? By maintaining a special pointer called HEAD. Due to the fact that we only created a new branch, but have not switched to it yet, the HEAD is still pointing to the master branch. You can check where HEAD points to using the git log command.

$ git log
commit 8756f0969c505ef24e9577afd2167487a03152ce (HEAD -> master, origin/main, origin/HEAD, main, feature)

Switching Branches

To switch to an existing branch, just run the git checkout <branch> or git switch <branch> command which we move HEAD to point to the branch.

$ git checkout feature
OR
$ git switch feature

To create a new branch and switch to that new branch at the same time, can be done using any of the below commands.

$ git checkout -b hotfix
OR
$ git switch -c hotfix

Branch Merging

All you have to do is check out the branch you wish to merge into and then run the git merge command.

$ git checkout master
$ git merge hotfix

Deleting a branch

Now we have merged the hotfix changes to master so now we can delete the hotfix branch by using option -d

$ git branch -d hotfix

Branch Management

The git branch command does more than just create and delete branches. If you run it with no options, it will list all current branches. The * indicates the branch you have currently checked out, in another word where HEAD points to.

$ git branch
feature
hotfix
main
* master

Renaming branch name

Rename the branch locally.

$ git branch --move old-branch-name new-branch-name

To reflect the rename changes on the remote

$ git push --set-upstream origin new-branch-name

Now delete the old branch on remote

$ git push origin --delete old-branch-name

Pushing branches

When you want to share a branch, you need to push it up to a remote.

$ git push origin hotfix

Tracking Branches

Checking out a local branch from a remote branch automatically creates a tracking branch. Tracking branches are the local branches that have a direct relationship to a remote branch.

$ git checkout --track origin/feature
Branch feature set up to track remote branch feature from origin. Switched to a new branch 'feature'

To set up a local branch with a different name than the remote branch

$ git checkout -b feat origin/feature
Branch 'feat' set up to track remote branch 'feature' from 'origin'.Switched to a new branch 'feat'

Pulling branches

To fetch all the changes on the server that you don’t have yet, it will not modify your working directory at all.

$ git fetch --all

The command git pull is essentially a git fetch immediately followed by a git merge.

$ git pull

Rebasing

In Git, there are two main ways to integrate changes from one branch into another using merge and rebase.

Let’s consider an example where a master branch has some commits and a new branch feature was created from it, commits were made to both master and feature branches.

  • Merge — It performs a three-way merge between the two latest branch snapshots M3 and F0 and the most recent common ancestor of the two M2, creating a new commit.
$ git checkout master
$ git merge feature
  • Rebase — There is another way, you can take the patch of the change that was introduced in F0 and reapply it on top of M3. This is called rebasing. With the rebase command, you can take all the changes that were committed on one branch and replay them on a different branch.
$ git checkout feature
$ git rebase master

This operation works by going to the common ancestor of the two branches M2, getting the diff introduced by each commit of the branch you’re on, saving those diffs to temporary files, resetting the current branch to the same commit as the branch you are rebasing onto, and finally applying each change in turn.

Now switch back to the master branch and do a merge.

$ git checkout master
$ git merge feature

Stashing

Stashing takes the dirty state of your working directory and saves it on a stack of unfinished changes that you can reapply at any time.

$ git status
On branch featureChanges to be committed:
(use "git restore --staged <file>..." to unstage)
new file: ReadMe.txtChanges not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: LICENSE.txt
modified: ReadMe.txt

Now you want to switch branches but don’t want to commit to what you have been working on, you can stash your changes.

$  git stash
Saved working directory and index state WIP on feature: 8756f0969c5 User-data file watching is broken in shared process (fixes #141176)

Check for all stashes you have stored.

$ git stash list
stash@{0}: WIP on feature: 8756f0969c5 User-data file watching is broken in shared process (fixes #141176)stash@{1}: WIP on feature: 8756f0969c5 User-data file watching is broken in shared process (fixes #141176)

You can apply the previously-stored stash with git stash apply <stash>. If you don’t specify a stash, Git assumes the most recent stash and tries to apply it.

$ git stash apply stash@{1}
On branch featureChanges to be committed:
(use "git restore --staged <file>..." to unstage)
new file: ReadMe.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: LICENSE.txt

The apply option only tries to apply for the stashed work, you continue to have it on your stack. To remove it you can run git stash drop <stash>. If you don’t specify a stash, Git discards the changes from the top of the stash stack.

$ git stash drop stash@{1}
Dropped stash@{1} (73369720c9909779a3f41924527073463e7b9c54)

It’s only by getting your hands dirty with Git that you’ll learn it.

Leave a Reply

Your email address will not be published.