DEV Community

koushikmaya
koushikmaya

Posted on

# Week 6 Task 3: Advanced Git Workflows

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

or:

Rebase
Enter fullscreen mode Exit fullscreen mode

2. Git Merge

Merge combines two branch histories.

For example:

git switch feature
git merge main
Enter fullscreen mode Exit fullscreen mode

Git may create a merge commit:

A---B---C-------M  feature
     \         /
      D---E---
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Run:

git switch feature
git rebase main
Enter fullscreen mode Exit fullscreen mode

Git effectively replays the feature commits on top of C:

A---B---C---D'---E'  feature
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

we get:

A---B---C---D'---E'
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

6. Squashing Commits

Suppose we have:

A
B Add login
C Fix typo
D Fix another typo
E Add tests
Enter fullscreen mode Exit fullscreen mode

The commits C and D may not be meaningful as separate commits.

We can squash them.

Run:

git rebase -i HEAD~4
Enter fullscreen mode Exit fullscreen mode

Then change:

pick B Add login
pick C Fix typo
pick D Fix another typo
pick E Add tests
Enter fullscreen mode Exit fullscreen mode

to:

pick B Add login
squash C Fix typo
squash D Fix another typo
pick E Add tests
Enter fullscreen mode Exit fullscreen mode

The result is approximately:

A
B Add login
E Add tests
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

into meaningful commits such as:

feat: add login
test: add login tests
Enter fullscreen mode Exit fullscreen mode

7. Reordering Commits

Interactive rebase can also reorder commits.

Suppose:

pick A Add feature
pick B Add tests
pick C Fix feature
Enter fullscreen mode Exit fullscreen mode

We can reorder them:

pick A Add feature
pick C Fix feature
pick B Add tests
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Git pauses at commit B.

We can then modify files:

git add .
git commit --amend
Enter fullscreen mode Exit fullscreen mode

After finishing:

git rebase --continue
Enter fullscreen mode Exit fullscreen mode

This is useful when a previous commit needs correction.


9. Important Rebase Commands

During a rebase, useful commands include:

git rebase --continue
Enter fullscreen mode Exit fullscreen mode

Continue after resolving a problem.

git rebase --abort
Enter fullscreen mode Exit fullscreen mode

Cancel the rebase and return to the previous state.

git rebase --skip
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Branch B:

Hello Developer
Enter fullscreen mode Exit fullscreen mode

Git doesn't know which version should remain.

It marks the file:

<<<<<<< HEAD
Hello Koushik
=======
Hello Developer
>>>>>>> feature
Enter fullscreen mode Exit fullscreen mode

These markers mean:

<<<<<<< HEAD
Your current branch's version

=======
Other branch's version

>>>>>>> feature
Enter fullscreen mode Exit fullscreen mode

11. How to Resolve a Conflict

First check the conflicted files:

git status
Enter fullscreen mode Exit fullscreen mode

Open the file and decide what the final content should be.

For example, we may choose:

Hello Koushik
Enter fullscreen mode Exit fullscreen mode

Remove the conflict markers.

Then stage the resolved file:

git add filename
Enter fullscreen mode Exit fullscreen mode

If you were doing a merge:

git commit
Enter fullscreen mode Exit fullscreen mode

If you were doing a rebase:

git rebase --continue
Enter fullscreen mode Exit fullscreen mode

12. Abort a Conflict Resolution

If things become confusing, you can cancel the operation.

For a merge:

git merge --abort
Enter fullscreen mode Exit fullscreen mode

For a rebase:

git rebase --abort
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

You don't want to commit incomplete work.

You can use:

git stash
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

This:

  1. Applies the stashed changes.
  2. Removes the stash from the stash list.

You can see existing stashes using:

git stash list
Enter fullscreen mode Exit fullscreen mode

Example:

stash@{0}: WIP on feature/login
stash@{1}: WIP on feature/profile
Enter fullscreen mode Exit fullscreen mode

15. stash vs stash pop vs stash apply

git stash

Temporarily saves changes:

git stash
Enter fullscreen mode Exit fullscreen mode

git stash apply

Restores the stash but keeps it in the stash list:

git stash apply
Enter fullscreen mode Exit fullscreen mode

git stash pop

Restores the stash and removes it from the stash list:

git stash pop
Enter fullscreen mode Exit fullscreen mode

git stash drop

Deletes a specific stash:

git stash drop stash@{0}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Suppose commit D contains a useful bug fix.

We can move only D to main:

git switch main
git cherry-pick <commit-id>
Enter fullscreen mode Exit fullscreen mode

The result is:

A---B---C---D'
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

18. Cherry-pick Conflicts

Cherry-picking can also cause conflicts.

If a conflict occurs:

git status
Enter fullscreen mode Exit fullscreen mode

Resolve the conflicting files.

Then:

git add .
Enter fullscreen mode Exit fullscreen mode

Continue:

git cherry-pick --continue
Enter fullscreen mode Exit fullscreen mode

To cancel:

git cherry-pick --abort
Enter fullscreen mode Exit fullscreen mode

19. Git Revert

git revert creates a new commit that reverses the changes introduced by an earlier commit.

Suppose:

A---B---C
Enter fullscreen mode Exit fullscreen mode

Commit C introduced a bug.

Instead of deleting C from history, we can run:

git revert C
Enter fullscreen mode Exit fullscreen mode

Git creates a new commit:

A---B---C---C'
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

We can run:

git reset --hard B
Enter fullscreen mode Exit fullscreen mode

The branch moves back:

A---B
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Moves the branch pointer but keeps the changes staged.

Useful when you want to redo a commit.


--mixed

git reset --mixed HEAD~1
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

23. Merge vs Rebase vs Cherry-pick

These commands solve different problems.

Merge

Combine two branch histories.

git merge main
Enter fullscreen mode Exit fullscreen mode

Rebase

Replay my commits on top of another branch.

git rebase main
Enter fullscreen mode Exit fullscreen mode

Cherry-pick

Take one specific commit and apply it here.

git cherry-pick <commit-id>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

24. Practical Example

Imagine working on a login feature.

You create:

git switch -c feature/login
Enter fullscreen mode Exit fullscreen mode

You make several commits:

feat: add login
fix: typo
fix: validation
test: add login tests
Enter fullscreen mode Exit fullscreen mode

Before opening a PR, you decide to clean the history.

You use:

git rebase -i HEAD~4
Enter fullscreen mode Exit fullscreen mode

Then squash the small fix commits.

Your history becomes:

feat: add login
test: add login tests
Enter fullscreen mode Exit fullscreen mode

While rebasing, you encounter a conflict.

You:

git status
Enter fullscreen mode Exit fullscreen mode

Fix the file, then:

git add .
git rebase --continue
Enter fullscreen mode Exit fullscreen mode

Later, you realize another branch contains a useful standalone bug fix.

Instead of merging the entire branch:

git cherry-pick <commit-id>
Enter fullscreen mode Exit fullscreen mode

Finally, if a bad commit has already been pushed to the shared branch, you can safely undo it with:

git revert <commit-id>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

and:

git rebase
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)