Introduction
Git is more than just a tool for saving code. In a team environment, developers need to understand how to manage branches, clean up commit history, move specific changes between branches, temporarily store unfinished work, and safely undo changes.
In this task, I learned:
- Merge vs Rebase
- Interactive Rebase
- Squashing commits
- Reordering commits
- Editing commits
- Resolving Merge Conflicts
- Git Stash
- Cherry-pick
- Git Revert vs Reset
These commands are important when working on feature branches and collaborating through Pull Requests.
1. Merge vs Rebase
Both merge and rebase are used to incorporate changes from one branch into another.
Suppose we have:
A---B---C main
\
D---E feature
The feature branch was created from commit B.
Meanwhile, main received commit C.
Now we want the feature branch to contain the latest changes from main.
There are two common approaches:
Merge
or:
Rebase
2. Git Merge
Merge combines two branch histories.
For example:
git switch feature
git merge main
Git may create a merge commit:
A---B---C-------M feature
\ /
D---E---
The merge commit M connects the two histories.
Advantages of Merge
- Preserves the original history.
- Does not rewrite existing commits.
- Safe for branches that are already shared with other developers.
- Clearly shows where branches were combined.
Disadvantage
The history can become more complicated, especially when many branches are merged.
3. Git Rebase
Rebase moves your branch's commits so they are based on the latest commit from another branch.
Suppose we start with:
A---B---C main
D---E feature
Run:
git switch feature
git rebase main
Git effectively replays the feature commits on top of C:
A---B---C---D'---E' feature
The commits are recreated, which is why their commit IDs change.
Why Use Rebase?
Rebase can create a cleaner, more linear history.
Instead of:
A---B---C
\ D---E---M
we get:
A---B---C---D'---E'
This can make the project history easier to read.
4. Merge vs Rebase
The main difference is:
| Merge | Rebase |
|---|---|
| Combines histories | Replays commits |
| Usually creates a merge commit | Usually creates a linear history |
| Does not rewrite existing commits | Rewrites commit history |
| Safer for shared branches | Useful for cleaning private branches |
| Preserves branch structure | Produces cleaner history |
A useful rule is:
Do not rebase commits that other developers are already depending on unless the team explicitly agrees.
5. Interactive Rebase
Interactive rebase allows us to modify our recent commit history.
The command is:
git rebase -i HEAD~3
This means:
Open the last three commits for interactive editing.
Git may show something like:
pick abc123 Add login
pick def456 Fix login validation
pick ghi789 Add tests
We can change the commands to modify the history.
Common commands include:
pick → keep the commit
reword → change the commit message
edit → stop and modify the commit
squash → combine with previous commit
fixup → combine and discard this commit's message
drop → remove the commit
6. Squashing Commits
Suppose we have:
A
B Add login
C Fix typo
D Fix another typo
E Add tests
The commits C and D may not be meaningful as separate commits.
We can squash them.
Run:
git rebase -i HEAD~4
Then change:
pick B Add login
pick C Fix typo
pick D Fix another typo
pick E Add tests
to:
pick B Add login
squash C Fix typo
squash D Fix another typo
pick E Add tests
The result is approximately:
A
B Add login
E Add tests
The changes from C and D are combined into B.
Why Squash?
It helps turn messy development history such as:
fix typo
fix again
final fix
actually fix
oops
into meaningful commits such as:
feat: add login
test: add login tests
7. Reordering Commits
Interactive rebase can also reorder commits.
Suppose:
pick A Add feature
pick B Add tests
pick C Fix feature
We can reorder them:
pick A Add feature
pick C Fix feature
pick B Add tests
Git will replay them in that order.
However, changing commit order can cause conflicts if later commits depend on earlier ones.
8. Editing a Commit
Interactive rebase also allows us to stop at a particular commit.
Example:
pick A Add feature
edit B Add configuration
pick C Add tests
Git pauses at commit B.
We can then modify files:
git add .
git commit --amend
After finishing:
git rebase --continue
This is useful when a previous commit needs correction.
9. Important Rebase Commands
During a rebase, useful commands include:
git rebase --continue
Continue after resolving a problem.
git rebase --abort
Cancel the rebase and return to the previous state.
git rebase --skip
Skip the current commit.
10. Resolving Merge Conflicts
A merge conflict happens when Git cannot automatically determine which change should be kept.
For example, two branches modify the same line:
Branch A:
Hello Koushik
Branch B:
Hello Developer
Git doesn't know which version should remain.
It marks the file:
<<<<<<< HEAD
Hello Koushik
=======
Hello Developer
>>>>>>> feature
These markers mean:
<<<<<<< HEAD
Your current branch's version
=======
Other branch's version
>>>>>>> feature
11. How to Resolve a Conflict
First check the conflicted files:
git status
Open the file and decide what the final content should be.
For example, we may choose:
Hello Koushik
Remove the conflict markers.
Then stage the resolved file:
git add filename
If you were doing a merge:
git commit
If you were doing a rebase:
git rebase --continue
12. Abort a Conflict Resolution
If things become confusing, you can cancel the operation.
For a merge:
git merge --abort
For a rebase:
git rebase --abort
This is useful when you want to return to the state before the operation started.
13. Git Stash
Sometimes you have unfinished changes but need to switch branches.
For example:
feature/login
You are currently working on login, but suddenly you need to fix something on another branch.
Your working directory contains:
modified login.ts
modified auth.ts
You don't want to commit incomplete work.
You can use:
git stash
Git temporarily stores the changes and gives you a clean working directory.
14. Applying Stashed Changes
Later, you can restore the changes.
git stash pop
This:
- Applies the stashed changes.
- Removes the stash from the stash list.
You can see existing stashes using:
git stash list
Example:
stash@{0}: WIP on feature/login
stash@{1}: WIP on feature/profile
15. stash vs stash pop vs stash apply
git stash
Temporarily saves changes:
git stash
git stash apply
Restores the stash but keeps it in the stash list:
git stash apply
git stash pop
Restores the stash and removes it from the stash list:
git stash pop
git stash drop
Deletes a specific stash:
git stash drop stash@{0}
16. Cherry-pick
Cherry-pick is used when we want to take a specific commit from one branch and apply it to another branch.
Suppose:
main:
A---B---C
feature:
A---B---D---E
Suppose commit D contains a useful bug fix.
We can move only D to main:
git switch main
git cherry-pick <commit-id>
The result is:
A---B---C---D'
The change from D is copied into a new commit on main.
17. When Cherry-pick Is Useful
Cherry-pick is useful when:
- A specific bug fix is needed on another branch.
- You don't want to merge the entire feature branch.
- You need to move one particular commit.
- A fix needs to be applied to a release branch.
Example:
feature branch
|
└── fix authentication bug
↓
cherry-pick
↓
release branch
18. Cherry-pick Conflicts
Cherry-picking can also cause conflicts.
If a conflict occurs:
git status
Resolve the conflicting files.
Then:
git add .
Continue:
git cherry-pick --continue
To cancel:
git cherry-pick --abort
19. Git Revert
git revert creates a new commit that reverses the changes introduced by an earlier commit.
Suppose:
A---B---C
Commit C introduced a bug.
Instead of deleting C from history, we can run:
git revert C
Git creates a new commit:
A---B---C---C'
C' reverses the changes introduced by C.
Why Revert Is Useful
Revert is particularly useful for shared branches such as main because it preserves the existing history.
20. Git Reset
git reset moves the current branch pointer to another commit.
Suppose:
A---B---C---D
We can run:
git reset --hard B
The branch moves back:
A---B
Commits C and D are no longer part of the current branch history.
This is why reset must be used carefully.
21. Types of Git Reset
There are three important reset modes.
--soft
git reset --soft HEAD~1
Moves the branch pointer but keeps the changes staged.
Useful when you want to redo a commit.
--mixed
git reset --mixed HEAD~1
Moves the branch pointer and unstages the changes, but keeps the files modified.
This is the default reset mode.
--hard
git reset --hard HEAD~1
Moves the branch pointer and discards changes from the working tree and staging area.
This can permanently remove work, so use it carefully.
22. Revert vs Reset
This is one of the most important differences.
| Revert | Reset |
|---|---|
| Creates a new commit | Moves branch pointer |
| Preserves history | Can remove commits from branch history |
| Safer for shared branches | Risky on shared branches |
| Good for undoing published changes | Often used for local history cleanup |
Simple rule:
Shared / pushed history
↓
revert
Private / local history
↓
reset
23. Merge vs Rebase vs Cherry-pick
These commands solve different problems.
Merge
Combine two branch histories.
git merge main
Rebase
Replay my commits on top of another branch.
git rebase main
Cherry-pick
Take one specific commit and apply it here.
git cherry-pick <commit-id>
Think of them like this:
Merge
↓
Bring the whole branch history together
Rebase
↓
Move/replay my branch commits
Cherry-pick
↓
Take only a specific commit
24. Practical Example
Imagine working on a login feature.
You create:
git switch -c feature/login
You make several commits:
feat: add login
fix: typo
fix: validation
test: add login tests
Before opening a PR, you decide to clean the history.
You use:
git rebase -i HEAD~4
Then squash the small fix commits.
Your history becomes:
feat: add login
test: add login tests
While rebasing, you encounter a conflict.
You:
git status
Fix the file, then:
git add .
git rebase --continue
Later, you realize another branch contains a useful standalone bug fix.
Instead of merging the entire branch:
git cherry-pick <commit-id>
Finally, if a bad commit has already been pushed to the shared branch, you can safely undo it with:
git revert <commit-id>
This is how these commands work together in a real workflow.
25. Command Cheat Sheet
| Task | Command |
|---|---|
| Merge branch | git merge branch-name |
| Rebase | git rebase branch-name |
| Interactive rebase | git rebase -i HEAD~N |
| Continue rebase | git rebase --continue |
| Abort rebase | git rebase --abort |
| Stash changes | git stash |
| List stashes | git stash list |
| Apply stash | git stash apply |
| Apply and remove stash | git stash pop |
| Cherry-pick commit | git cherry-pick <commit> |
| Revert commit | git revert <commit> |
| Soft reset | git reset --soft HEAD~1 |
| Mixed reset | git reset --mixed HEAD~1 |
| Hard reset | git reset --hard HEAD~1 |
| Check status | git status |
26. Important Safety Rules
Some Git commands can rewrite history or discard work.
Be especially careful with:
git reset --hard
and:
git rebase
when working with shared branches.
A good general rule is:
Clean up your own private history, but avoid rewriting history that other developers are already using.
If a branch has already been pushed and shared, coordinate with the team before rewriting its history.
27. What I Learned
The main lesson from this task is that Git provides different tools for different situations.
Merge
↓
Combine branches
Rebase
↓
Create a cleaner linear history
Interactive Rebase
↓
Clean and edit commits
Conflict Resolution
↓
Manually choose the correct final version
Stash
↓
Temporarily save unfinished work
Cherry-pick
↓
Move one specific commit
Revert
↓
Safely undo a published commit
Reset
↓
Move local history backward
Understanding these commands makes it much easier to work confidently with feature branches and Pull Requests.
Conclusion
Advanced Git workflows are important for maintaining a clean and reliable project history.
Merge is useful for combining branch histories, while rebase can create a cleaner linear history. Interactive rebase allows developers to squash, reorder, edit, or remove commits before sharing them.
Merge conflicts are a normal part of collaborative development and can be resolved by manually choosing the correct final version.
Git stash provides a way to temporarily save unfinished work, while cherry-pick allows a specific commit to be applied to another branch.
Finally, understanding the difference between revert and reset is essential. Revert creates a new commit that undoes previous changes, while reset moves the branch pointer and can rewrite local history.
The most important thing is not memorizing every command. It is understanding which Git tool solves which problem and when it is safe to use it.
Top comments (0)