Mastering Git:- Advanced Concepts
Introduction
In the previous article, we explored Git basics like creating a repository, committing changes, and pushing to a remote. If you’re familiar with those steps, you’re ready to move forward. This post is a practical journey through advanced Git concepts—presented in a real-world order and explained clearly so even beginners can follow along and start applying them with confidence.
1. Branching and Merging (Including Merge Strategies)
Start here: branching is the foundation of collaboration in Git.
Branches are like parallel versions of your project. You use them to develop features or fixes independently from the main line of work (main
or master
).
Create and Switch to a Branch
|
|
You’re now on a new branch called feature-login
. Make your changes and commit as usual.
Merging Back into Main
Once done, switch back to main
and merge your changes:
Now, let’s understand how Git decides how to merge:
Fast-Forward Merge
If no one else updated main
while you were working, Git just moves the branch pointer. This creates a clean, straight history.
|
|
You’ll see no extra commit.
True Merge Commit
If main
has new commits since you branched off, Git will create a merge commit:
|
|
This preserves both histories and shows exactly when the feature branch was merged.
Octopus Merge
Used when merging multiple unrelated branches at once:
|
|
All branches are merged if there are no conflicts. Ideal for housekeeping tasks.
“Ours” Merge Strategy
When you want to ignore the incoming branch’s changes but still record the merge:
|
|
Useful when deprecating a branch while preserving its history.
2. Rebasing for a Clean History
Rebasing rewrites the base of your branch so your changes appear as if they were made on top of the latest main branch.
This helps keep history linear and clean.
How to Rebase
Git replays your commits on top of main
, one by one.
If a conflict happens:
- Git will pause and let you fix the conflict.
- After fixing, stage the changes:
|
|
- Continue rebasing:
|
|
After the rebase is complete, you may need to force-push your branch:
|
|
When to Use It
Use rebase before opening a pull request to avoid unnecessary merge commits and simplify the project history.
3. Squashing Commits (Clean Up Before Merging)
When you’re developing a feature, it’s common to make several small commits—some meaningful, others like “fix typo” or “style update.” Before merging your branch or creating a pull request, it’s a good idea to squash those commits into one or two well-structured commits. This keeps the commit history clean and easier for your team to review.
How to Squash Commits
Let’s say you’ve made 5 commits. To squash them:
|
|
This opens an interactive editor showing your last 5 commits. You’ll see something like:
Change all but the first pick
to squash
(or simply s
):
Save and close the editor. Git will prompt you to write a new commit message. You can edit or combine the messages from the squashed commits.
What to Do Next
Once saved, you’ll have a single commit. Push it using:
|
|
This ensures your remote branch reflects your cleaned-up commit history, making code review easier.
4. Git Tags for Versioning
Tags are markers you place on specific commits—usually to indicate versions or releases. They make it easy to refer to key milestones in your project.
Creating a Tag
|
|
This tags the current commit with v1.0
. If you want to tag a previous commit:
|
|
Sharing Tags with Others
Tags aren’t pushed by default. To share them:
|
|
Or push all tags:
|
|
When to Use Tags
Use tags for marking release points like v1.0
, v2.1-beta
, or release-2024-01
. They’re useful when deploying or debugging a specific version.
5. Cherry-Picking Specific Changes
Sometimes, you only want one commit from another branch—not the whole thing. Cherry-picking helps you grab and apply that specific commit wherever needed.
Real Example
Let’s say your teammate fixed a bug on the hotfix
branch, and you need that fix in your release
branch.
This applies the changes from that commit onto your current branch.
Handling Conflicts
If conflicts arise during the cherry-pick:
After it finishes, test your branch to make sure the cherry-picked change integrates well.
6. Stashing Work in Progress
You’re mid-task when an urgent bug appears in another branch. But your current work isn’t ready to be committed. Use git stash
to quickly save your changes and switch branches without losing progress.
How to Stash
|
|
This stores your uncommitted changes temporarily and resets your working directory.
Now you can switch branches:
|
|
Applying Stashed Work
When you’re ready to resume:
|
|
Find your stash entry (e.g., stash@{0}
), then apply it:
|
|
If you no longer need it after applying:
|
|
Or pop it (apply and remove in one go):
|
|
Custom Named Stash
Give your stash context:
|
|
This makes it easier to recall why you stashed something.
7. Reflog for Recovery
Reflog tracks where your Git references (like HEAD or branch pointers) have been—even after operations like reset
or rebase
. It helps you recover lost commits that aren’t visible in the regular git log
.
View the Reflog
|
|
You’ll see a list of recent HEAD movements with commit hashes. Example:
Recover a Lost Commit
If you accidentally reset or deleted a branch:
|
|
Git usually retains reflog entries for 90 days (by default).
8. Bisecting to Find Bugs
Git Bisect is a tool that uses binary search to help you find the exact commit that introduced a bug. It’s efficient when you have many commits between a known good and bad state.
Starting Bisect
Git now checks out a middle commit. You test your code:
- If the bug is present:
|
|
- If the bug is not present:
|
|
Repeat the process. Git will continue narrowing it down.
End Bisect
Once Git identifies the problematic commit:
|
|
Use this commit’s hash to inspect or revert the change as needed.
9. Worktrees for Parallel Work
Worktrees let you have multiple working directories from the same Git repo. This is useful when you want to check out different branches at the same time without cloning the repo again.
Create a New Worktree
|
|
This checks out the feature-login
branch into a new directory one level above the current one.
Switch Between Worktrees
Just navigate into each folder and work independently. Changes in one don’t affect the other.
List All Worktrees
|
|
Remove a Worktree
|
|
Final Thoughts
Git is powerful, but it doesn’t have to be overwhelming. By mastering these commands step-by-step and applying them in real-world scenarios, you’ll grow more confident in managing code and collaborating with others.
Next up, we’ll explore working with remotes: pushing, pulling, managing remotes, and contributing to shared projects.
Stay curious, keep experimenting—and Git better every day!