Git offers a robust set of commands for managing projects of any scale. While the basics get the job done, delving into more advanced Git commands can significantly enhance productivity and streamline workflows. This article explores a collection of sophisticated Git techniques, including examples, to help you master your repository management.
1. Selective and Shallow Git Clone
Selective Cloning: To clone a specific branch without fetching all remote branches, use:
git clone --branch <branch_name> --single-branch <repository_url>
Shallow Cloning: To clone a repository with a limited number of commits in the history, thereby speeding up the cloning process, use:
git clone --depth <depth> <repository_url>
where <depth>
is the number of commits you want to include in the history.
2. Inspecting Git History
Pretty Printing Log: For a more comprehensive view of the log, use:
git log --pretty=format:"%h - %an, %ar : %s"
This command shows the commit hash, author name, relative commit date, and commit message in a custom format.
Graphical Log View: To see the project history as a graph in the command line, use:
git log --graph --oneline --all
3. Comparing Revisions
Diff between Commits: To compare changes between two commits, use:
git diff <commit1> <commit2>
Changes Since a Specific Commit: To see what has changed since a specific commit, use:
git diff <commit> HEAD
4. Advanced Committing
Amend Commits: To modify the most recent commit, perhaps to adjust the commit message or add forgotten files, use:
git commit --amend
Interactive Staging: To selectively stage changes (useful for breaking up changes into logical commits), use:
git add -p
5. Rebasing and Rewriting History
Interactive Rebase: To reorganize, edit, or squash commits, use:
git rebase -i HEAD~<number_of_commits>
This command allows for a variety of actions on the specified number of commits from the current HEAD.
6. Cherry-picking
Applying Commits from Another Branch: To apply a specific commit from another branch into your current branch, use:
git cherry-pick <commit_hash>
7. Merging and Conflicts Resolution
Merge: To merge another branch into your current branch, use:
git merge <branch_name>
Resolving Conflicts: After a merge, conflicts can be resolved manually in the affected files. Mark the files as resolved using:
git add <resolved_file>
8. Managing Multiple Remotes and Branches
Adding a Remote: To add a new remote repository, use:
git remote add <remote_name> <repository_url>
Fetching from a Specific Remote: To update your local with changes from a specific remote, use:
git fetch <remote_name>
Pushing to a Specific Remote: To push changes to a specific remote branch, use:
git push <remote_name> <branch>
9. Keeping Repositories Tidy
Pruning Remote-tracking Branches: To remove references to remote branches that no longer exist, use:
git remote prune <remote_name>
Cleaning Untracked Files: To clean your working directory by removing untracked files, use:
git clean -fd
These advanced commands and techniques offer powerful ways to manage your Git repositories more effectively. Incorporating them into your daily workflow can lead to increased efficiency and a deeper understanding of Git’s capabilities. Always remember to proceed with caution when modifying history or performing operations that can alter the state of your repository permanently.
10. Working with Tags
Creating Tags: Tags are used to mark specific points in a repository’s history as important, typically for releases.
git tag -a v1.0 -m "Release version 1.0"
Pushing Tags to Remote: After creating tags locally, they need to be explicitly pushed to the remote repository.
git push origin --tags
11. Stashing Changes
Stashing Your Work: To temporarily store modified, tracked files in order to switch branches:
git stash
Applying Stashed Changes: To reapply previously stashed changes onto the current working directory:
git stash pop
12. Reflog – Recovering Lost Commits
Git reflog is a mechanism to record updates to the tip of branches and other Git actions, making it possible to recover lost commits.
git reflog
After finding the commit you want to recover, you can check it out to a new branch:
git checkout -b <new_branch_name> <commit_hash>
13. Bisect – Debugging by Binary Search
When trying to find the commit that introduced a bug, git bisect
can be used to perform a binary search between a known good and bad state.
- Start bisect session:shCopy code
git bisect start
- Mark the current version as bad:shCopy code
git bisect bad
- Mark the last known good commit:shCopy code
git bisect good <commit_hash_of_good_commit>
Git will then checkout a commit halfway between the good and bad commits. Test this commit, and mark it as good or bad accordingly. Repeat this process until Git isolates the bad commit.
14. Advanced Branch Management
Renaming Branches: To rename your current branch:
git branch -m <new_name>
Deleting Branches Locally and Remotely: To delete a branch locally:
git branch -d <branch_name>
To delete a branch remotely:
git push <remote_name> --delete <branch_name>
15. Worktrees – Multiple Working Trees
Git worktrees allow you to have multiple working trees attached to the same repository, making it easy to work on multiple branches simultaneously without the need to stash/unstash changes.
- Add a new worktree:shCopy code
git worktree add <path_to_new_worktree> <branch>
16. Submodule Management
When your project depends on code in another repository, you can manage this dependency as a submodule.
- Adding a submodule:shCopy code
git submodule add <repository_url> <path_where_to_place_it>
- Initializing and fetching submodule content:shCopy code
git submodule update --init --recursive
17. Rewriting Author History
If you need to change the author/committer history (e.g., for GDPR compliance), Git provides a powerful filter-branch command.
git filter-branch --env-filter ' OLD_EMAIL="[email protected]" CORRECT_NAME="Your Correct Name" CORRECT_EMAIL="[email protected]" if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ] then export GIT_COMMITTER_NAME="$CORRECT_NAME" export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL" fi if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ] then export GIT_AUTHOR_NAME="$CORRECT_NAME" export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL" fi ' --tag-name-filter cat -- --branches --tags
Caution: filter-branch
and operations that rewrite history can have significant implications for collaborative projects. They should be used with care, especially on shared branches.
These additional advanced Git commands and scenarios provide deeper insights and tools for managing your projects with precision. Mastery of these techniques will not only boost your productivity but also enhance your ability to maintain clean, efficient, and organized repositories.