Skip to content

Advanced Git: Rebase, Stash, Cherry-pick, and More

Published: at 11:06 PM

Introduction

In the previous article, we covered the basics of Git, including repository setup, branching, committing, and viewing diffs. Now, we’ll dive into more advanced Git features to help you manage your repository more efficiently and handle complex workflows. Here’s a continuation of the Git tutorial, covering more advanced topics not included in the first part.

Table of contents

Open Table of contents

Git Rebase

git rebase allows you to move or “replay” commits from one branch onto another. This is useful for keeping a clean and linear project history. Unlike git merge, which creates a new merge commit, git rebase applies the commits on top of another base branch.

Basic Rebase

Let’s say you want to rebase feature-branch onto main:

git checkout feature-branch
git rebase main

This reapplies the commits from feature-branch on top of the main branch, keeping a linear commit history without a merge commit.

Interactive Rebase

Interactive rebasing (git rebase -i) allows you to change commit history by squashing, reordering, or even editing past commits.

git rebase -i HEAD~3

This will open the last three commits in an editor. You can mark commits as pick, squash, or edit. For example:

pick   abc123 First commit
squash def456 Second commit (squash with first)
pick   ghi789 Third commit

This will squash the second commit into the first, combining their changes.


Git Stash

git stash allows you to temporarily save changes that are not ready for a commit, without committing them to the branch. This is useful when you need to switch branches but don’t want to lose your current work.

Stashing Changes

Run the following to stash uncommitted changes:

git stash

This saves your changes and restores the working directory to the last commit state.

Applying a Stash

When you’re ready to apply the stashed changes, use:

git stash apply

This re-applies the most recent stash, but it doesn’t remove it from the stash list.

Listing and Dropping Stashes

To list all stashed changes:

git stash list

To drop (delete) a specific stash from the list:

git stash drop stash@{0}

Cherry-pick

git cherry-pick allows you to apply individual commits from one branch into another branch. This is useful when you want to take specific changes without merging the entire branch.

Example

To cherry-pick a specific commit from feature-branch into main:

git checkout main
git cherry-pick abc123 # Commit hash from feature-branch

This command applies the changes from commit abc123 to your main branch without bringing in other changes from the feature-branch.


Reset vs. Revert

Both git reset and git revert are used to undo changes, but they work differently.

Soft, Mixed, and Hard Reset

The git reset command can operate in different modes, depending on how much of your working directory you want to change:

  1. Soft reset: Only moves the commit history, leaving your changes in the working directory.

    git reset --soft HEAD~1
  2. Mixed reset (default): Moves the commit history and the staged changes, leaving unstaged changes in the working directory.

    git reset HEAD~1
  3. Hard reset: Moves the commit history and completely discards both staged and unstaged changes.

    git reset --hard HEAD~1

Revert Example

To revert a specific commit, keeping the history intact:

git revert abc123

This creates a new commit that undoes the changes introduced by abc123.


Resolving Merge Conflicts

Merge conflicts occur when Git cannot automatically merge changes. When this happens, you’ll need to manually resolve the conflicts.

Steps to Resolve Merge Conflicts

  1. Git will say which files are in conflict after a merge attempt.

    git status
  2. Open the conflicting files, and you’ll see conflict markers (<<<<<<<, =======, >>>>>>>), indicating different changes. Manually resolve the conflicts by editing the file.

  3. After resolving the conflicts, mark the files as resolved:

    git add file_with_conflict.txt
  4. Complete the merge:

    git commit

Amending Commits

git commit --amend allows you to change the most recent commit. You can use it to edit the commit message or include more changes that were missed.

Example

To change the most recent commit:

git commit --amend

This opens the commit message in your editor, allowing you to change it. If you also want to add new changes, stage the changes before running --amend.


Working with Tags

Tags are useful for marking specific points in the history, like releases or major milestones. Git supports both lightweight and annotated tags.

Creating a Tag

To create an annotated tag:

git tag -a v1.0 -m "Version 1.0"

This creates a tag v1.0 with a message.

Listing Tags

To see all the tags in your repository:

git tag

Pushing Tags

Tags are not pushed by default. To push a specific tag:

git push origin v1.0

To push all tags:

git push --tags

Conclusion

This guide covered more advanced Git features like rebasing, stashing, cherry-picking, and resolving conflicts. These tools provide you with greater flexibility and control over your project history and workflow. As you become more experienced with Git, mastering these commands will help you maintain a cleaner and more efficient codebase.

For more information, check out the official Git documentation.


With these advanced commands, you can now handle more complex Git scenarios and workflows with confidence!