Best Git Practices For Managing Your Project

See the original article on my website:
https://patrykkosieradzki.com/best-git-practices-for-managing-your-project/

Having troubles managing git history in your project? You should read this.

Creating new branches

Main branches

  • master branch
  • develop branch

Support branches

The different types of branches you may want to use are:

  • Feature branches (for ex. feature/<TASK_ID>-Short-feature-description)
  • Defect branches (for ex. defect/<TASK_ID>-Short-defect-description)
  • Release branches (for ex. release/<release_version>)
  • Hotfix branches (for ex. hotfix/<short_hotfix_description>)

Committing

Use proper naming!

For example, naming like this IS UNNACEPTABLE:

  • “added ui”
  • “added logic”
  • “resolved PR comments part 2”
  • “rebasing”
  • etc.

Trust me, I’ve seen things like this in a few projects and the git tree was a mess…

Preferably, use one of these approaches:

2. Past tense
[By applying this commit, I] Removed deprecated methods from extensions

3. What does the commit do?
[This commit] Removes deprecated methods from extensions

REMEMBER TO ALWAYS ADD TASK ID, IF YOU HAVE ONE:

So finally, the commit would look like this:
“ABC-123 Removes deprecated methods from extensions“

Amending commits

git commit --amend

Once you do that, a new commit is created and we will push it ON TOP of the old commit. That’s why we need to use push force:

git push -f origin feature/ABC-123_Some_cool_feature

Merging VS Rebasing

Consider what happens when you start working on a new feature in a dedicated branch, then another team member updates the develop branch with new commits. This results in a forked history, which should be familiar to anyone who has used Git as a collaboration tool.

Now, let’s say that the new commits in develop are relevant to the feature that you’re working on. To incorporate the new commits into your feature branch, you have two options: merging or rebasing.

Merging

Merging is nice because it’s a non-destructive operation. The existing branches are not changed in any way. This avoids all of the potential pitfalls of rebasing (discussed below).

On the other hand, this also means that the feature branch will have an extraneous merge commit every time you need to incorporate upstream changes. If master is very active, this can pollute your feature branch’s history quite a bit. While it’s possible to mitigate this issue with advanced git log options, it can make it hard for other developers to understand the history of the project.

On the other hand, this also means that the feature branch will have an extraneous merge commit every time you need to incorporate upstream changes. If develop is very active, this can pollute your feature branch’s history quite a bit. While it’s possible to mitigate this issue with advanced git log options, it can make it hard for other developers to understand the history of the project.

Rebasing

The major benefit of rebasing is that you get a much cleaner project history. First, it eliminates the unnecessary merge commits required by git merge. Second, as you can see in the above diagram, rebasing also results in a perfectly linear project history — you can follow the tip of feature all the way to the beginning of the project without any forks. This makes it easier to navigate your project with commands like git log, git bisect, and gitk.

But, there are two trade-offs for this pristine commit history: safety and traceability. If you don’t follow the Golden Rule of Rebasing , re-writing project history can be potentially catastrophic for your collaboration workflow. And, less importantly, rebasing loses the context provided by a merge commit — you can’t see when upstream changes were incorporated into the feature.

Remember that after rebasing if commits are added to our past then you have to PUSH FORCE them to your branch. If commits are added on the top (for example rebasing feature branch to develop, then you can use a simple push).

The Verdict

BUT

If you’re not the only one working on a branch and for example someone changed the history/amended commit/squashed them/etc. it’s better to use merge. If you’d want to use rebase in this situation you’d have to reset your branch and cherry pick the changes from you other brach for example.

Useful git commands that you MUST learn to save yourself in critical situations

Git stash

Git status

Git log

Git reflog

Git reset (soft/mixed/hard)

Git rebase interactive

Running this command gives you a list of commits in your text editor that looks something like this:

pick f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

Git cherry pick

Wow, that’s a lot of new git commands

If you have any questions about Git in general, don’t be scared and reach out to me, cheers!

Senior Android Developer, ProAndroidDev writer, “AndroidTalks” podcast owner