DEV Community

Udara Dananjaya
Udara Dananjaya

Posted on

Mastering Git and GitHub: Advanced Git Commands - Part 4

Welcome to Part 4 of our Git and GitHub series! By now, you should be well-versed in Git’s basic commands and some advanced workflows. In this final section of the series, we will dive into some critical aspects of Git and GitHub that are essential for managing large teams and complex repositories.

In this part, we’ll explore Git rebasing in depth, cherry-picking commits, squashing commits for clean history, rebasing pull requests, and managing Git tags for releases. We'll also go over strategies for branch management, submodule best practices, and GitHub CLI (Command-Line Interface) usage.

Let’s finish our journey through advanced Git techniques with a focus on collaboration, release management, and streamlining your workflows.


Table of Contents (Part 4)

  1. Rebasing in Depth: Streamlining Your Commit History
    • Why Use Rebase?
    • Interactive Rebase Best Practices
  2. Cherry-Picking Commits
    • Applying Specific Commits to Another Branch
  3. Squashing Commits: Creating a Clean History
  4. Rebasing Pull Requests: Best Practices for Merging PRs
  5. Managing Git Tags for Releases
  6. Branch Management Strategies
  7. Best Practices for Working with Submodules
  8. GitHub CLI: Speeding Up Your Workflow
  9. Conclusion

1. Rebasing in Depth: Streamlining Your Commit History

Rebasing is an incredibly powerful tool for streamlining and cleaning up your Git history. It allows you to move or combine a sequence of commits to a new base commit. This can make your project history more linear and easier to follow, which is especially useful in collaborative settings.

Why Use Rebase?

Rebasing is useful when you want to:

  • Keep a clean and linear commit history.
  • Avoid "merge commits" cluttering your history.
  • Incorporate changes from one branch onto another without creating unnecessary merge commits.

For example, if you're working on a feature branch and need to incorporate the latest changes from main, rebasing allows you to replay your changes on top of the current state of main rather than merging it.

Interactive Rebase Best Practices

Interactive rebase is a powerful tool for editing, reordering, squashing, or even dropping commits. To start an interactive rebase, use the following command:

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

Where n is the number of commits you want to rebase. Once you execute this command, Git will open your default editor with a list of commits, and you can manipulate them by changing the commands at the beginning of each line (e.g., pick, reword, squash).

  • Reordering commits: Simply change the order of the commit lines.
  • Squashing commits: To combine multiple commits into one, change pick to squash for all but the first commit in the series.
  • Rewording commit messages: Use reword to modify a commit message.

Example:

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

After finishing the rebase, run:

git rebase --continue
Enter fullscreen mode Exit fullscreen mode

Best Practices for Rebasing

  • Avoid rebasing shared branches: Rebasing rewrites history, so avoid rebasing branches that others are already using. If you rebase a shared branch, you’ll force others to resolve conflicts when they pull from the remote.
  • Always rebase onto the latest main branch: Before merging a feature branch, make sure to rebase it onto the latest main or develop to keep your history clean.

2. Cherry-Picking Commits: Applying Specific Commits to Another Branch

Sometimes, you may want to apply a commit from one branch to another without merging the entire branch. This is where cherry-picking comes in. Cherry-picking allows you to apply individual commits to another branch.

Cherry-Pick a Commit

  1. Identify the commit hash you want to apply:
   git log
Enter fullscreen mode Exit fullscreen mode
  1. Cherry-pick the commit using the commit hash:
   git cherry-pick <commit_hash>
Enter fullscreen mode Exit fullscreen mode
  1. If there are conflicts, resolve them as usual:
   git status
   git add <file>
   git cherry-pick --continue
Enter fullscreen mode Exit fullscreen mode

Cherry-picking is useful when you need to selectively apply bug fixes, features, or changes that are specific to another branch without pulling in the entire history.


3. Squashing Commits: Creating a Clean History

Squashing commits is the process of combining multiple commits into one. This is often done before merging a feature branch into main to ensure that the commit history remains clean and focused.

Squashing Commits Using Rebase

  1. Start an interactive rebase with the number of commits you want to squash:
   git rebase -i HEAD~n
Enter fullscreen mode Exit fullscreen mode
  1. In the editor, change pick to squash for the commits you want to combine. Leave the first commit as pick:
   pick e3a1b35 Add new feature
   squash 7d62c88 Fix bug in new feature
   squash 89b6c11 Update README
Enter fullscreen mode Exit fullscreen mode
  1. After saving and closing the editor, Git will combine these commits into one. It will then prompt you to edit the commit message. You can keep one of the original messages or write a new one.

Squashing commits is an excellent way to avoid clutter in your history, especially for small, related changes like fixing typos or minor bugs.


4. Rebasing Pull Requests: Best Practices for Merging PRs

Rebasing is also an excellent way to clean up pull requests before merging. If you have an open pull request (PR), you can rebase it onto the latest main branch to avoid unnecessary merge commits and ensure your feature is based on the most recent version of the code.

Rebasing a Pull Request

  1. Fetch the latest changes from the main branch:
   git fetch origin main
Enter fullscreen mode Exit fullscreen mode
  1. Checkout the branch associated with your PR:
   git checkout feature/your-feature-branch
Enter fullscreen mode Exit fullscreen mode
  1. Rebase your branch onto main:
   git rebase origin/main
Enter fullscreen mode Exit fullscreen mode
  1. If there are conflicts, resolve them manually and continue the rebase:
   git add <file>
   git rebase --continue
Enter fullscreen mode Exit fullscreen mode
  1. Push your changes back to the remote:
   git push --force-with-lease
Enter fullscreen mode Exit fullscreen mode

Rebasing a PR ensures that your changes are built on top of the latest code in the project, which minimizes conflicts when merging.


5. Managing Git Tags for Releases

Git tags are markers in your Git history that help you mark specific commits, usually for important milestones like releases. Tags are often used to indicate version numbers and are essential for managing software releases.

Creating Tags

  1. Lightweight tags: These are simply references to a specific commit.
   git tag v1.0.0
Enter fullscreen mode Exit fullscreen mode
  1. Annotated tags: These tags contain metadata such as the tagger’s name, email, and date, and are recommended for releases.
   git tag -a v1.0.0 -m "Release version 1.0.0"
Enter fullscreen mode Exit fullscreen mode

Pushing Tags to the Remote

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

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

Or push all tags:

git push --tags
Enter fullscreen mode Exit fullscreen mode

Listing Tags

To list all tags in your repository:

git tag
Enter fullscreen mode Exit fullscreen mode

Deleting Tags

To delete a local tag:

git tag -d v1.0.0
Enter fullscreen mode Exit fullscreen mode

To delete a remote tag:

git push --delete origin v1.0.0
Enter fullscreen mode Exit fullscreen mode

6. Branch Management Strategies

Effective branch management is crucial when working with Git, especially in larger projects with multiple contributors. Here are some strategies to keep things organized:

  • Use feature branches: Always create a new branch for each feature or bug fix, and never work directly on main or develop.
  • Naming conventions: Use descriptive names for your branches (e.g., feature/login, bugfix/button-color, hotfix/security-patch).
  • Delete merged branches: After a feature branch has been merged, delete it to keep the repository clean.

Deleting a Branch Locally

git branch -d feature/your-feature-branch
Enter fullscreen mode Exit fullscreen mode

Deleting a Remote Branch

git push origin --delete feature/your-feature-branch
Enter fullscreen mode Exit fullscreen mode

7. Best Practices for Working with Submodules

If your project uses Git submodules, it’s important to understand the best practices for managing them.

Adding a Submodule

git submodule add <repository-url> <path-to-submodule>
Enter fullscreen mode Exit fullscreen mode

Initializing and Updating Submodules

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

Removing a Submodule

  1. Remove the submodule entry from .gitmodules:
   git submodule deinit -f <path-to-submodule>
Enter fullscreen mode Exit fullscreen mode
  1. Remove the submodule directory:
   git rm --cached <path-to-submodule>
Enter fullscreen mode Exit fullscreen mode
  1. Commit the change:
   git commit -m "Remove submodule"
Enter fullscreen mode Exit fullscreen mode
  1. Delete the submodule files:
   rm -rf <path-to-submodule>
Enter fullscreen mode Exit fullscreen mode

8. GitHub CLI: Speeding Up Your Workflow

The GitHub CLI (gh) is a command-line tool that allows you to interact with GitHub directly from your terminal. It’s incredibly useful for managing repositories, pull requests, issues, and releases without leaving your command line.

Installing GitHub CLI

To install GitHub CLI, use:

brew install gh
Enter fullscreen mode Exit fullscreen mode

Common GitHub CLI Commands

  • Create a pull request:
   gh pr create --base main --head feature/your-feature-branch --title "Your PR Title" --body "Description of your changes"
Enter fullscreen mode Exit fullscreen mode
  • View pull requests:
   gh pr list
Enter fullscreen mode Exit fullscreen mode
  • Merge a pull request:
   gh pr merge <pr-number> --merge
Enter fullscreen mode Exit fullscreen mode

9. Conclusion

This fourth and final part of our Git and GitHub series has covered some of the most advanced Git techniques and strategies to help you manage complex workflows and repositories. From rebasing and cherry-picking commits to managing release tags and using the GitHub CLI, these tips will make you a more efficient and effective developer.

Whether you're working on solo projects or collaborating with large teams, mastering these Git commands and workflows will keep your codebase clean, organized, and easy to navigate.

Thanks for reading! We hope these articles have been helpful in your journey toward mastering Git and GitHub. Happy coding!


Further Reading:

Top comments (0)