Git
Git is a distributed version control system that allows multiple developers to work on the same codebase without interfering with one another.
Setup & Configuration
Installing Git
Git is a distributed version control system, to install it (linux-based systems):
sudo apt-get install git
Configuring Git
Set username and email: This sets your identification for every commit.
git config --global user.name "Your Name"
git config --global user.email "youremail@example.com"
List all global configurations: Shows your git configuration details.
git config --global --list
Unset a specific configuration: For instance, to remove the globally set username.
git config --global --unset user.name
Setting Up Authentication for GitLab
SSH Authentication:
ssh-keygen -t rsa -b 4096 -C "youremail@example.com"
cat ~/.ssh/id_rsa.pub
Repository Operations
Setting Up GitLab Repository
A step-by-step guide to set up a new project on GitLab:
Login to GitLab.
Click on the "+" icon at the top right.
Select "New project".
Cloning a Repository
Copy a remote repository to your local machine:
git clone https://gitlab.com/yourusername/yourrepository.git
Integrating an Existing Folder with GitLab
Link your local folder with a GitLab repository:
cd /path/to/your/folder
git init
git remote add origin git@gitlab.com:yourusername/yourrepository.git
git add .
git commit -m "Initial commit or relevant message"
git push -u origin main
Regular Workflow & Common Commands
Synchronize with Remote Repository
Update your local branch with the latest changes from the remote repository:
git pull
Committing Changes
After making your desired changes, save them to your local repository and then push to the remote repository:
git add .
git commit -m "Descriptive commit message"
git push
Branch Management
Creating, Renaming, and Deleting Branches
Handle multiple lines of development within a single repository:
git branch new_branch_name
git branch -m old_name new_name
git branch -d branch_name
git push origin --delete branch_name
Switching Between Branches & Commits
Move between different versions or branches within the repository:
git checkout branch_name
git checkout commit_hash
Recovering Lost Files
Check Reflog
git reflog
Identify commit before loss: Look for relevant HEAD@{n}
entry.
Create Temporary Branch
git branch temp-branch <commit-SHA>
Recover Files
Checkout temporary branch:
git checkout temp-branch
Files at this state are recoverable. Copy them to a safe location.
Merge or Cherry-Pick to Current Branch
Merge:
git checkout <current-branch>
git merge temp-branch
Cherry-Pick:
git cherry-pick <commit-SHA>
Restoring Committed Branches
If you've accidentally removed a branch in Git, don't worry! You can typically recover it with a few simple steps.
Every action in git is logged.
To find the last commit of the deleted branch:
git reflog
For example, you might see an entry like:
abcdef1 HEAD@{2}: checkout: moving from feature-branch to main
Now that you have the commit hash, you can restore the branch.
Let's assume you want to recover a branch named feature-branch
:
feature-branch
:git checkout -b feature-branch abcdef1
Conflict Resolution & Reversion
Handling Merge Conflicts
When merging or pulling, conflicts may occur. These steps guide you through resolution:
git add resolved_file.ext
git commit
Reverting and Resetting Changes
In Git, you may often find yourself needing to undo changes. Two primary commands to do this are git revert
and git reset
. Each serves a different purpose and should be used based on your specific needs.
git revert
Purpose: The git revert
command is used to reverse the changes made by a specific commit. It creates a new commit that undoes the changes from a previous commit.
git revert commit_hash
Replace commit_hash
with the hash of the commit you want to revert.
Scenario: Use git revert
when you need to undo changes but want to keep the history of the original commit. This is a safe method to undo changes in a shared repository because it doesn't alter the project's history.
git reset
Purpose: The git reset
command is used to reset the current HEAD to a specified state. It can be used to unstage files, change the current branch's HEAD to a different commit, and even discard changes in your working directory depending on the options used.
git reset --hard branch_or_commit_name
Replace branch_or_commit_name
with the name of the branch or the hash of the commit you want to reset to.
--soft
: Moves the HEAD to a specified commit but keeps your staged changes and working directory.--mixed
(default): Resets the index but not the working tree. Changes are kept but not marked for commit.--hard
: Resets the index and working tree. Any changes to tracked files in the working tree since the specified commit are discarded.
Scenario: Use git reset
when you need to completely undo changes in a local repository. Be cautious with git reset --hard
, as it can permanently erase changes. It's best used when you have uncommitted changes that you want to discard.
Understanding HEAD and Its Notation
In Git, HEAD
is a reference to the last commit in the currently checked-out branch. It represents the tip of the current branch.
Notation:
HEAD~1
: Refers to the commit before the current one.HEAD~2
: Refers to two commits before the current one.And so on, where
HEAD~n
refers to the 'n-th' commit before the current HEAD.
git reset with HEAD Notation
To undo the last commit, keeping the changes in the working directory:
git reset --soft HEAD~1
To completely remove the last commit:
git reset --hard HEAD~1
Scenario: This is particularly useful when you need to undo recent commits in your local repository.
Best Practices
Use
git revert
for public/shared branches to maintain a record of changes.Use
git reset
for local or private changes where rewriting history is acceptable.Always ensure you have backups of your work before using
git reset --hard
.
Merging dev
into main
and Resolving Conflicts
dev
into main
and Resolving ConflictsMerging Branches
Once you've finished development on the dev
branch and it's ready for merging into main
:
dev
branch and it's ready for merging into main
:git checkout main
git merge dev
Identifying and Resolving Conflicts
Sometimes, Git can't auto-merge changes and will report a conflict.
Identify the conflicted files:
git status
Open the conflicted files in your preferred editor (like VSCode). Conflicts are marked with <<<<<<< HEAD
, =======
, and >>>>>>> branch-name
.
Manually resolve the conflict by choosing which code to retain and which to discard.
Once you've resolved the conflict in the file:
git add conflicted-file-name
After resolving all conflicts, continue the merge process with a commit:
git commit -m "Resolved conflicts while merging dev into main"
After successfully merging and resolving conflicts, you'd want to update the remote repository:
git push origin main
Cleaning Up Local References in VSCode
VScode sometimes holds onto old branch references that no longer exist on the remote.
It's a good practice to prune these references regularly.
Pruning Local Branch References
To remove stale branches from your local that no longer exist on the remote:
git fetch -p
Advanced Operations
Stashing, Tagging, and Searching
Various advanced operations for better Git management:
git stash
git stash apply
git stash drop
git tag v1.0 commit_hash
git log --grep="search_term"
git grep "search_term"
Viewing Commit History & Using git blame
Examine the modification history of your repository:
git log
git log --oneline --graph --all
git blame filename.ext
Troubleshooting & Miscellaneous
Dealing with Authentication Issues
Switch between SSH and HTTPS, or troubleshoot common authentication issues:
git remote set-url origin git@gitlab.com:yourusername/yourrepository.git
Update Default Branch on GitLab
Change the primary branch of your GitLab repository:
Go to your project.
Navigate to "Settings" > "Repository".
Set the new default branch.
Detailed Commit Inspection
Show Commit Details
Display changes associated with a specific commit:
git show commit_hash
Reflog
Shows a log of where your HEAD and branch references have been:
git reflog
Working with Remotes
List Remote Repositories
Show all remote repositories connected to the local repository:
git remote -v
Add Remote Repository
Connect a new remote repository to the local repository:
git remote add remote_name remote_url
Remove Remote Repository
Remove a connection to a remote repository:
git remote remove remote_name
Fetch from Remote
Download branches and/or tags from another repository, without making any changes to your local branches:
git fetch remote_name
Patching
Creating a Patch
Create a patch file of the changes between two commits:
git format-patch older_commit_hash^..newer_commit_hash
Apply a Patch
Apply changes from a patch file to the code:
git apply patch_name.patch
Rebasing
Rebase
Apply a series of commits from one branch onto another, effectively re-writing history. Useful for a clean commit history but can be dangerous if not understood well:
git rebase branch_name
Abort Rebase
Stop the rebase process and return to the initial state:
git rebase --abort
Continue Rebase After Conflict Resolution
Continue the rebase process after resolving merge conflicts:
git rebase --continue
Cleaning Up
Remove untracked files from the working directory. This doesn't remove untracked folders or files specified in .gitignore:
.gitignore:
git clean -n # Shows which files would be removed
git clean -f # Force remove files
Prune
Remove objects that are no longer pointed to by any commit. This cleans up your local repository:
git gc # Garbage collector
git prune
Submodules
Add a Submodule
Add another repository as a submodule in the current repository. Useful when using other projects or shared code:
git submodule add repository_url path_to_add_submodule
Update Submodule
Update the registered submodules:
git submodule update --init --recursive
Bisect
Find by binary search the commit that introduced a bug:
git bisect start
git bisect bad # Specify the commit where the bug is present
git bisect good commit_hash # Specify the latest commit where the bug is absent
Then, Git will check out a commit in the middle of that range.
Test the code, and then mark that commit as good
or bad
.
Repeat the process until the culprit commit is found. Finally:
git bisect reset # End the bisect session
Last updated