When working with Git, the two prevailing workflows are Gitflow and feature branches. In my honest opinion, being more of a subscriber to continuous integration, I feel that the feature branch workflow is the better choice. Therefore, feature branches will be the focus of this article.
If you are new to Git and Git-workflows, I suggest reading the atlassian.com Git Workflow article in addition to this as there is more detail there than is presented here.
I admit, using Bash in the command line with the standard configuration leaves a bit to be desired when it comes to awareness of state. A tool that I suggest using follows these instructions on setting up GIT Bash autocompletion. This tool will assist you to better visualize the state of a branch in regards to changes and being in sync with the remote repo.
When working in a decentralized workflow, the concepts can be simple. Master represents the official history and should always be deployable. With each new scope of work, aka feature, a developer creates a new branch. For clarity, make sure to use descriptive names like transaction-fail-message or github-oauth for your branches.
Although you may have a feature like ‘user login and registration’, it may not be appropriate to create a feature branch at this level since there is too much work to be done. Instead, it may better to break these large deliverables down into smaller bits of work that can be continuously integrated into the project.
Remember, commit early and often.
That being said, there are times when a single branch will be needed to deliver a large feature or prepare for a release. In this scenario, I’d suggest reading over the Git Commit Guidelines created by the Angular team at Google. As they put it, it is a series of “… precise rules over how our git commit messages can be formatted.” As of late, I have been making heavy use of these commit message guidelines in all the projects I am working on.
Before you create a branch, always be sure that you have all the upstream changes from the origin/master branch.
Before I pull, I make sure I am on the right branch. I have GIT Bash autocompletion installed, so it is clear from the prompt. Otherwise, the following command is good for listing out the branches you have locally as well as designating the branch that you are currently on.
$ git branch
The checked out branch will have a *
before the name. If the return designates anything other than master
, switch to master
$ git checkout master
Once on master, when you are ready to pull updates, use the following:
$ git pull origin master
Depending on your setup, you may even be able to just run the following:
$ git pull
The git pull
command combines two other commands, git fetch
and git merge
. When doing a fetch
, the resulting commits are stored as a remote branch that allows you to review the changes before merging. Merging, on the other hand, can involve additional steps and flags in the command, but more on that later. For now, I’ll stick with git pull
.
Now that I am all up to date with the remote repo, I’ll create a branch. For efficiency, I will use the following:
$ git checkout -b my-new-feature-branch
This command will create a new branch from master
as well as check out that new branch at the same time. Doing a git branch
here again will list out the branches in the local repo and place a *
before the branch that is checked out.
master
* my-new-feature-branch
No. There is a command that allows you to create a new branch from any other branch while having checked out yet another branch. WHAT?!
$ git checkout -b transaction-fail-message master
In that example, say I was in branch github-oauth
, and I needed to create a new branch and then check out the new branch. By adding master
at the end of that command, Git will create a new branch from master and then move me (check out) to that new branch.
This is a nice command, but make sure you understand what you are doing before you do this. Creating bad branches can cause a real headache when trying to merge back into master.
In any Git project, you will find a .gitignore
file. This is a simple registry file where you can list the files you DO NOT want to commit to the repo; i.e., any files that contain secret information like keys and tokens or any sensitive server configurations.
To read more about the basics of a .gitignore
file, read [ignoring files][ignorefiles] from the Github site.
The only thing I want to mention is that if a resource has already been added to Git’s control, adding it later to the .gitignore
file will not ignore that file. The thing to remember here is that the intention is to remove the file from Git control, not from the disk. To do this, use the following command:
$ git rm --cached
For example, say we had a directory with the file index.html
and then the file config.yml
, but the config file had a lot of secret info and it was accidentally added to the Git version control.
In the .gitignore
file, we would first add config.yml
then in the command prompt, run:
$ git rm --cached config.yml
After running the command, you should see that config.yml
is still in the directory; but by running the following command, you would see that it is NOT being tracked by Git:
$ git ls-tree -r master --name-only