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 gitConfiguring 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 --listUnset a specific configuration: For instance, to remove the globally set username.
git config --global --unset user.nameSetting Up Authentication for GitLab
SSH Authentication:
ssh-keygen -t rsa -b 4096 -C "youremail@example.com"cat ~/.ssh/id_rsa.pubRepository 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.gitIntegrating 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 mainRegular Workflow & Common Commands
Synchronize with Remote Repository
Update your local branch with the latest changes from the remote repository:
git pullCommitting 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 pushBranch 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_nameSwitching Between Branches & Commits
Move between different versions or branches within the repository:
git checkout branch_name
git checkout commit_hashRecovering Lost Files
Check Reflog
git reflogIdentify 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-branchFiles 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-branchCherry-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 reflogFor example, you might see an entry like:
abcdef1 HEAD@{2}: checkout: moving from feature-branch to mainNow 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 abcdef1Conflict Resolution & Reversion
Handling Merge Conflicts
When merging or pulling, conflicts may occur. These steps guide you through resolution:
git add resolved_file.ext
git commitReverting 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_hashReplace 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_nameReplace 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~nrefers 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~1To completely remove the last commit:
git reset --hard HEAD~1Scenario: This is particularly useful when you need to undo recent commits in your local repository.
Best Practices
Use
git revertfor public/shared branches to maintain a record of changes.Use
git resetfor 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 devIdentifying and Resolving Conflicts
Sometimes, Git can't auto-merge changes and will report a conflict.
Identify the conflicted files:
git statusOpen 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-nameAfter 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 mainCleaning 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 -pAdvanced 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.extTroubleshooting & 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.gitUpdate 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_hashReflog
Shows a log of where your HEAD and branch references have been:
git reflogWorking with Remotes
List Remote Repositories
Show all remote repositories connected to the local repository:
git remote -vAdd Remote Repository
Connect a new remote repository to the local repository:
git remote add remote_name remote_urlRemove Remote Repository
Remove a connection to a remote repository:
git remote remove remote_nameFetch from Remote
Download branches and/or tags from another repository, without making any changes to your local branches:
git fetch remote_namePatching
Creating a Patch
Create a patch file of the changes between two commits:
git format-patch older_commit_hash^..newer_commit_hashApply a Patch
Apply changes from a patch file to the code:
git apply patch_name.patchRebasing
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_nameAbort Rebase
Stop the rebase process and return to the initial state:
git rebase --abortContinue Rebase After Conflict Resolution
Continue the rebase process after resolving merge conflicts:
git rebase --continueCleaning 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 filesPrune
Remove objects that are no longer pointed to by any commit. This cleans up your local repository:
git gc # Garbage collector
git pruneSubmodules
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_submoduleUpdate Submodule
Update the registered submodules:
git submodule update --init --recursiveBisect
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 absentThen, 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 sessionLast updated
