If you're a developer today, you've probably learned Git, the version control system at the heart of modern software workflows. They know the basics – how repositories work, how branches are created and changes committed, and how those changes are merged and requirements are retrieved.
Now that you know the basics, it's time to level up a bit to take advantage of some of Git's more powerful features in your workflow. Here are five advanced Git features that are part of your current and future development efforts.
Simplify commit histories with Git Rebase
If you have two branches in a project (e.g. a development branch and a main branch) that both contain changes that need to be combined, the git merge command is the natural and easy way to unify them. A merge adds the development history of one branch as a merge promise for the other branch. While this preserves both histories in minute detail, it can make it difficult to keep track of the entire history of the project. In some cases, you may want a simpler, cleaner result.
The git rebase command also merges two branches, but does it a little differently. A git rebase rewrites a branch's commit history so that the other branch is integrated into it from the time it was created. This results in a less noisy and more linear commit history for this branch. It also means that potentially useful details about the other branch and the merge process are removed.
For this purpose, Rebase is best used when you have multiple private branches that you want to consolidate into a single, clean commit history before merging with a public branch. This way, you get the full benefit of hiring – by making a commit history more linear and less noisy – without obscuring important details about the commit history for your project.
Clean up mergers with git merge –squash
Another way to make mergers and subsequent commits quieter is to use the –squash option when merging Git. –Squash takes all commits from an incoming branch and combines them into a single consolidated commit.
The nice thing about a bruised merge is that you can choose how to apply the resulting hosted files. You can simply commit the entire set of changes as one, or you can commit some files at the same time if the changes are closely related. A crushed merge is also useful if the incoming branch's commit history is only useful in the context of that branch, or if it comes from a private branch that is discarded anyway.
As with a rebase, this technique is best used to commit internal branches to the master, but is also suitable for pull requests if necessary.
Accelerate troubleshooting with git bisect
Subtle regressions in code are the most difficult to figure out. Imagine you've just added a test to your code base to fix a bug, but you're not sure when the bug first happened … and you have hundreds or even thousands of commits in your repository. You can use the git bisect command to significantly reduce the amount of code you need to find to find the commit that caused the error.
When you enable bisect (git bisect start), you specify two points in your code base to narrow your search: one that you know things are bad (usually HEAD) and one that you know that things are still good. Bisect reviews a commit halfway between the bad and good commit and lets you run your tests. This binary division process is repeated until the commit that caused the errors is displayed.
git bisect is a stroke of luck for large code bases with long, complex commit histories that save you the hassle of working through every last commit in the hope that you will find your mistake sooner or later. At the very least, the amount of searching and testing you need to do is cut in half.
Apply commits again with Git Cherry-Pick
Many advanced Git commands are only useful in certain circumstances and are also ignored by moderately advanced users. But if you come across any of these special circumstances, it is worth knowing them.
Consider Git Cherry Pick. You can apply a specific commit – any commit from any branch – to another branch without making any other changes in the course of that commit. This is useful in some important circumstances:
You committed the wrong branch and want to quickly apply it to the correct branch.
You want to apply a fix from a branch to the trunk before continuing to work on the trunk code.
Note that besides applying the commit directly, you have a few options when you select it. For example, if you pass the –no-commit option, Cherry's commit is placed in the staging area of the current branch.
Organize projects elegantly with Git submodules
Just as most programming languages offer a way to import packages or modules, Git offers a way to automatically include the contents of one repository in another, a submodule. You can create a subdirectory within a repo and automatically populate it with the content of another repo by usually referencing a particular commit hash for consistency.
Note that Git submodules work best under the following conditions:
The submodules in question do not change often or are tied to a specific commit. All work on a submodule and not with a submodule should be managed separately.
Everyone uses a version of Git that supports submodules and understands the steps required to work with them. For example, submodule directories are not always automatically filled with the content of the submodule repository. You may need to use the git submodule update command on the repo to bring everything up to date.
Copyright © 2020 IDG Communications, Inc.