For a software developer, learning to work with Git is essentially a requirement that comes with the job description. Working with local and remote repositories, committing changes, and managing branches: these are some basics of Git you have to know like the back of your hands.
But beyond these basics, Git provides more advanced commands to make your life easier. They can improve your productivity and solve some not-so-uncommon problems you encounter when collaborating on a project with tens and hundreds of other developers. If you’ve been looking to become a pro at working with Git, these are the commands you should keep within your reach.
In today’s tutorial, we’ll walk you through five of these advanced Git concepts. From git bisect to git rebase, they can save a lot of time you spend scouring over Stack Overflow forums when a version control problem occurs.
Find Bugs Fast with git bisect
Assume the repository you’re contributing to has a handful of failing tests because of a bug. Nobody has yet been able to pin down the cause or the commit that started it. And finding the bad commit is especially hard because hundreds of new commits have been made to the repository after the last working commit.
Git bisect allows you to find the exact commit that created the bug fast in situations like this. When you provide a known “good” commit and “bad” commit, it uses binary search to reach the first problematic commit in the least amount of time.
Running a bisect operation start with the command:
git bisect start
You can identify the reference of a good commit, where everything was working as expected, and a bad commit, where causes test fails, by viewing the commit history using
git log. You need to provide these two commits to bisect using the following two commands.
git bisect good <good-commit-ref> git bisect bad <bad-commit-ref>
As soon as you run
git bisect bad, it checks out the commit at the midpoint between good and bad commits, allowing you to review it. If the tests are still failing in the checked-out commit, you can let bisect know it by running
git bisect bad. On the other hand, if it’s is a good commit, run
git bisect good.
After this step, bisect again checks out the mid-commit between updated good and bad commits so that you can review the code and run tests to figure out whether it’s good or bad. It continues this process until it reaches the first bad commit.
You can stop the bisect operation and go to the final commit using,
git bisect reset
Pick and Apply Individual Commits with git cherry-pick
Even though it doesn’t happen often, we sometimes come across scenarios where we want to pick a specific commit from another branch in the repository and apply it to the one we are working on.
For example, you might want to pick the changes you have mistakenly committed to another branch and apply them to the right one. Or you might want to apply a solution someone else has provided to the branch you’re working on without writing the code from scratch. If you use
git merge in situations like this, it can apply changes that aren’t relevant to your current branch.
Therefore, in such cases,
git cherry-pick might be the command you should use.
When executing this command, you should first retrieve the reference to the commit you want to pick using logs. Then, check out the branch you wish to apply the picked commit.
git checkout feature-1
Now, you can apply the commit with:
git cherry-pick <commit-ref>
If you want to just stage the changes to this branch without committing them, you should use:
git cherry-pick <commit-ref> --no-commit
It’s important to note that using this command might not be the best course of action to take in some instances. Depending on how you use
git cherry-pick, it can create duplicate commits in your branch. The commit you apply can also introduce new bugs and errors to your branch. So, if you cherry-pick commits using Git, make sure it’s the last resort you turn to after trying out all the other options.
Change the Base of a Branch with git rebase
Usually, we use the
git merge command to combine the changes made to two repository branches. If we view the repository’s commit history after a merging operation, it will be confusing to follow with the interleaving commits from the two branches.
What if we want to make the commit history of our project easier to follow by making the history of the merging branch align linearly with the other one? This is where
git rebase steps in.
In a few words, the responsibility of the rebase command is changing the base commit of a branch. Let’s discuss what this exactly means with an example.
Let’s say you have two branches in your repository: main and feature. After creating the feature branch, your team has added commits to both these branches. But now, you want to merge the feature branch into the main branch before release. At this point, you can run
git rebase on your feature branch before merging it using
git merge. It changes the base of the feature branch to the last commit in your master branch like the following image shows.
The rebase command gives your feature branch a linearly compatible history with the master branch, unlike before. Now, if you run
git merge, the commit history of the master branch will be less confusing and easier to follow.
Using this command is quite simple. First, check out the branch you want to rebase. Then run this.
git rebase <base-branch-name>
git rebase is a command you should use with caution because it rewrites the history of a branch. You can lose helpful information stored in the branch history during the process. It can also have a negative impact if you’re working on a branch with many contributors. So, it’s best to limit the usage to personal branches unless you’re 100% on the same page with all your team members.
Easily Select Files to Commit with git add -p
git add command is one of the essential steps in the Git workflow. It stages the files in the project directory that need to be committed. We use different versions of this command depending on the particular occasion.
git add <file-path>to stage files in a specific path.
git add .to stage modified and new files.
But if you want to review the changes in each file part by part (as patches) before deciding whether to stage them or not, you can use the
git add -p command. It displays the changes made to a file as several hunks and prompts you to select whether to stage each one or not.
Here are the selections Git provides for each hunk. You should type the respective letter when prompted to confirm your decision.
- y: stage this hunk
- n: do not stage this hunk
- q: quit; do not stage this hunk or any of the remaining ones
- a: stage this hunk and all later hunks in the file
- d: do not stage this hunk or any of the later hunks in the file
- e: manually edit the current hunk
Change Your Last Commit Message with git commit –amend
How many times do you find yourself wanting to change your last commit because you made a mistake or forgot to add something important?
git commit --amend allows you to do exactly that.
With this command, you can change your last commit message or combine the currently staged changes with the previous commit without creating an entirely new commit. This step doesn’t just alter the previous commit; it replaces the commit with a wholly new one.
Let’s see how to use this command for amending commits.
If you want to change the message:
git commit --amend -m <commit message>
If you want to combine the staged changes, first add the modified files using
git add. Then amend the last commit like this:
git commit --amend --no-edit
If you had already pushed the last commit to a remote repository, you’d have to use the
git push --force-with-lease command for pushing the modified commit.
Again, since this amending operation alters the commit history, you should be careful about when and where you use it.
In this post, we introduced five advanced Git concepts and commands you can use for efficient version control. However, what we discussed here are only a few impressive commands Git offers to developers. But we hope that they’ll come in handy when you run into similar problems like those we discussed here.
If you have any favorite Git commands that make your life easier, don’t forget to share them in the comment section below. Thank you for reading!