DEV Community

Udara Dananjaya
Udara Dananjaya

Posted on

Mastering Git and GitHub: Advanced Git Commands - Part 2

In the first part of our Git and GitHub guide, we covered the fundamental commands and some essential advanced techniques for manipulating your Git history. In this second part, we will explore even more advanced Git operations that are useful for maintaining a clean and efficient repository. Whether you're working on large teams or solo projects, these techniques will help you stay organized, avoid mistakes, and improve your workflow.

We'll dive into interactive rebase, stash management, submodules, tagging, and more. Understanding these advanced commands will not only help you manage your code history more effectively but also provide you with tools to collaborate better and manage your codebase in a more sophisticated way.


Table of Contents (Part 2)

  1. Interactive Rebase: Fine-Tuning Your Commit History
  2. Stashing: Saving and Applying Changes Temporarily
  3. Git Submodules: Managing External Repositories
  4. Tagging: Marking Specific Points in History
  5. Git Hooks: Automating Tasks on Events
  6. Conclusion and Best Practices

1. Interactive Rebase: Fine-Tuning Your Commit History

One of the most powerful tools in Git for rewriting commit history is interactive rebase. This command allows you to edit, reorder, squash, or remove commits in your history.

To start an interactive rebase:

git rebase -i <commit_hash>
Enter fullscreen mode Exit fullscreen mode

Where <commit_hash> is the commit ID you want to rebase onto. For example, if you want to rebase your branch onto the 3rd commit from the HEAD, use:

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

This opens an editor with a list of commits in the rebase window, allowing you to perform the following actions:

  • pick: Keep the commit as is.
  • reword: Change the commit message.
  • edit: Modify the commit’s content.
  • squash: Combine the commit with the previous one.
  • fixup: Similar to squash, but the commit message is discarded.
  • drop: Remove the commit from the history.

Example of an interactive rebase list:

pick e3a1b35 Add new feature
squash 7d62c88 Fix bug in new feature
reword 89b6c11 Update README
drop 7a4e2b3 Remove unnecessary test
Enter fullscreen mode Exit fullscreen mode

After making your changes and saving the file, Git will apply them. If there are conflicts, you’ll need to resolve them manually. Once done, use:

git rebase --continue
Enter fullscreen mode Exit fullscreen mode

Interactive rebasing allows you to clean up your history by combining commits or removing unnecessary ones, making the history easier to understand.


2. Stashing: Saving and Applying Changes Temporarily

Sometimes, you need to switch branches but don’t want to commit your current changes. Git stash allows you to save your uncommitted changes temporarily and apply them later.

Saving Changes to Stash

To stash your changes:

git stash
Enter fullscreen mode Exit fullscreen mode

This saves your changes (both staged and unstaged) and reverts your working directory to the state of the last commit.

You can also stash with a message:

git stash save "WIP: working on new feature"
Enter fullscreen mode Exit fullscreen mode

Viewing Your Stashes

To see a list of stashes:

git stash list
Enter fullscreen mode Exit fullscreen mode

This will show you all the stashes with their respective IDs (e.g., stash@{0}, stash@{1}).

Applying or Popping Stashes

To apply the latest stash:

git stash apply
Enter fullscreen mode Exit fullscreen mode

Or apply a specific stash:

git stash apply stash@{1}
Enter fullscreen mode Exit fullscreen mode

To remove the stash after applying it:

git stash pop
Enter fullscreen mode Exit fullscreen mode

This command applies the stash and removes it from the stash list. If you want to drop a stash without applying it, use:

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

Stashing is incredibly useful for temporarily saving your work without committing, especially if you're working on something that isn't ready to be shared yet.


3. Git Submodules: Managing External Repositories

Sometimes, you might need to incorporate an external repository into your project. This is where Git submodules come into play. A submodule is essentially a Git repository inside another Git repository.

Adding a Submodule

To add a submodule to your project:

git submodule add <repository_url> <path_to_submodule>
Enter fullscreen mode Exit fullscreen mode

This clones the external repository into a directory of your choice. For example:

git submodule add https://github.com/username/some-repo.git submodules/some-repo
Enter fullscreen mode Exit fullscreen mode

This will initialize the submodule and add it to your project as a new folder.

Cloning a Repository with Submodules

When cloning a repository with submodules, you can use the following command to clone the main repository and initialize the submodules:

git clone --recurse-submodules <repository_url>
Enter fullscreen mode Exit fullscreen mode

If you've already cloned the repository but forgot to initialize the submodules, run:

git submodule update --init --recursive
Enter fullscreen mode Exit fullscreen mode

Updating Submodules

To update the submodule to the latest commit in its remote repository:

git submodule update --remote
Enter fullscreen mode Exit fullscreen mode

Submodules can be tricky to manage, so always be aware of their state and ensure they’re updated when necessary.


4. Tagging: Marking Specific Points in History

Git tags are used to mark specific points in history, such as version releases or milestones, making it easier to reference those points later.

Creating a Tag

To create a tag on your current commit:

git tag v1.0
Enter fullscreen mode Exit fullscreen mode

You can also tag a specific commit by specifying its hash:

git tag v1.0 <commit_hash>
Enter fullscreen mode Exit fullscreen mode

Pushing Tags to Remote

By default, tags are not pushed when you run git push. To push a specific tag to the remote:

git push origin v1.0
Enter fullscreen mode Exit fullscreen mode

To push all tags:

git push --tags
Enter fullscreen mode Exit fullscreen mode

Viewing Tags

To list all tags:

git tag
Enter fullscreen mode Exit fullscreen mode

Tags are often used to mark releases, so using them effectively can help you track significant points in your project’s history.


5. Git Hooks: Automating Tasks on Events

Git hooks are scripts that Git executes before or after certain actions, such as committing, pushing, or merging. Hooks are stored in the /.git/hooks directory of your repository and can be used to automate tasks like running tests or formatting code before a commit.

Common Hooks

  • pre-commit: Runs before a commit is made, often used to run linters or tests.
  • post-commit: Runs after a commit is made.
  • pre-push: Runs before pushing changes to a remote repository.

For example, you can set up a pre-commit hook to run tests before every commit. Simply create a script inside the .git/hooks folder named pre-commit, and make sure it’s executable:

#!/bin/sh
npm test
Enter fullscreen mode Exit fullscreen mode

Now, before each commit, Git will run the tests.

Git hooks can automate many aspects of your workflow, saving time and reducing human error.


6. Conclusion and Best Practices

Advanced Git techniques like interactive rebase, stashing, submodules, tagging, and git hooks offer a wealth of tools for managing and automating your Git workflow. These tools allow you to fine-tune your commit history, organize your work better, and integrate external repositories seamlessly into your project.

As you continue to use Git in your daily development, consider implementing these techniques to:

  • Clean up commit history using interactive rebase and squash commits.
  • Temporarily store changes with stash for an efficient workflow.
  • Manage external dependencies with submodules.
  • Mark important points in your project's history with tags.
  • Automate repetitive tasks using Git hooks.

By combining these advanced commands with the best practices outlined in Part 1 of this series, you’ll be able to work more efficiently, collaborate more effectively, and maintain a clean and organized codebase.

Happy coding!


Further Reading:

Top comments (0)