Git has become the de-facto standard for version control in software development. Developers should have a good understanding of Git. Very often though developers learn only a few simple commands and overlook the powerful abilities of Git that can make version control much more efficient. I would like to share my findings in lesser-known features that could take the developer’s daily workflow to the next level.

Recover deleted branches

Branch deletion removes only the reference to the blog. The actual cleaning is done by the garbage collector, which is usually not for days or weeks depending on your settings and version. A branch can be easily recreated once we figure out the commit hash was for the tip of it. We can use git reflog which tracks the movement of HEAD and grep to limit tracks.

git reflog | grep deleted-branch

Command will reveal the hash and the number of movements of when the deleted branch was checkout out.

bc7tfe3 HEAD@{23}: checkout: moving from feature/new-stuff to deleted-branch

Then we can get back to that branch in one line.

git checkout -b deleted-branch bc7tfe3

The command allows you to go back to a time that you need and recover a code that is gone now.

Move changes to a correct branch

We may have a situation when we accidentally committed code. We can use a “soft” reset in that case, undo the last commit and leave the changes available.

git reset HEAD~ –soft
git stash

Move to the correct branch

git checkout correct-branch
git stash pop
git add .
git commit -m “my changes”;

Now changes will be on the correct branch. There is also an option to use cherry-pick for situations like that. I prefer soft reset because it can reset back more than one commit. We need to change the number after ~

git reset HEAD~2 –soft

Find a commit that breaks code

Git bisect performs a binary search between two given commits and then presents a specific commit’s details. One of the ways to use it is to be on the branch where the code has a problem. First, we invoke the bisect session and mark the current commit as a known problem commit.

git bisect start
git bisect bad

Next, find a commit hash where we know things were stable and indicate to bisect

git bisect good bc7tfe3

Git will split the range of commits between good and bad in half and checkout the midpoint commit. Now we can run our specs and mark that commit as “good” or “bad” accordingly. We can repeat that process until we find one possible commit remaining. Note that as long as you have one good commit and one bad, the commits can be even years apart

Remove a file from git, but not file system

We can accidentally add a file to git that we don’t want to commit. Running git rm will remove a file from the staging area and our file system, which may not be what we want. We need to make sure we only remove the staged version and add the file to our .gitignore to avoid making the same mistake:

git reset filename # alternative is to run git remove –cached filename
echo filename >> .gitignore

Avoid repeated mistakes with git hooks

It would be easy to avoid frequent mistakes by running certain checks or cleanup tasks at a defined stage of the git workflow. Hooks were exactly designed for scenarios like this. Every Git repository has a .git/hooks folder with a script for each hook. We can change or update these scripts as needed, and Git will execute corresponding when that events occur.

Below is an example hook to check branch names. Although there is no dedicated hook for the new branch creation event, we can use the pre-commit hook. We will be checking if the branch name is correct and exit with 0, otherwise we will print an error message and exit with 1. To get the current branch name we use this:

git rev-parse –abbrev-ref HEAD

The branch name should start with feature, bug or chore, and only contain lowercase letters, digits, and some special symbols.


And the final hook code would look like this:

current_branch_name=”$(git rev-parse –abbrev-ref HEAD)”
valid_branch_regex=”^(feature|bug|chore)\/[a-z0-9._-]+$”message=”The branch name should start with feature, bug or chore, and only contain lowercase letters, digits, and some special symbols. Please rename your branch to a valid name and try again.”if [[ ! $current_branch_name =~ $valid_branch_regex ]]
echo “$message”
exit 1
fiexit 0

Git has tons of commands, details, options, and is the very powerful tool that developers use every day. I hope that my findings will help other developers be a little more productive in Git commands.

For more than 17 years, gap intelligence has served manufacturers and sellers by providing world-class services monitoring, reporting, and analyzing the 4Ps: prices, promotions, placements, and products. Email us at or call us at 619-574-1100 to learn more.