Git Github Notes
Git Github Notes
Version Control (also known as Revision Control or Source Control) is a system that records changes to a file or
set of files over time so that you can recall specific versions later. It's an essential tool for any software
development project, but it can be used to track changes to any type of file (e.g., documents, websites, design
assets).
Imagine you're working on a document, and you save multiple copies with names like
document_final.docx , document_final_v2.docx , document_final_really_final.docx . This quickly becomes messy and makes it difficult to
track what changes were made in each version, or to revert to an older, working version if something goes wrong.
Version control solves this problem by providing a structured way to manage these changes.
Key aspects of version control include:
•
Tracking Changes: It keeps a detailed history of every modification made to your files.
•
Collaboration: It allows multiple people to work on the same project simultaneously without overwriting each
other's work.
•
Reversion: You can easily revert to previous versions of your files or the entire project.
•
Branching and Merging: It enables developers to work on separate features or bug fixes in isolation (branches)
and then integrate those changes back into the main project (merging).
Types of Version Control Systems
Git is by far the most popular Distributed Version Control System (DVCS) today, and for good reason. Here are its
key benefits:
1.
Distributed Nature:
◦
Resilience: Every developer has a full copy of the repository. If the central server fails, any developer's local
repository can be used to restore the project.
◦
Offline Work: Developers can commit changes locally even without an internet connection and push them later.
◦
Speed: Most operations (like committing, branching, merging) are performed locally, making them incredibly fast
compared to CVCS.
2.
Powerful Branching and Merging:
◦
Easy Branching: Git makes it incredibly easy and cheap to create branches. This encourages developers to work
on new features or bug fixes in isolated environments without affecting the main codebase.
◦
Robust Merging: Git's merging capabilities are highly sophisticated, making it efficient to integrate changes from
different branches back into the main line of development, even in complex scenarios.
3.
Data Integrity:
◦ Git uses a cryptographic hash (SHA-1) for every commit, ensuring that the history cannot be altered without
Git detecting it. This provides strong data integrity.
4.
Performance:
◦ As mentioned, local operations are very fast. Git is designed for performance, even with very large
repositories and extensive histories.
5.
Community and Ecosystem:
◦
Vast Community Support: Being the most popular VCS, Git has a massive community, meaning abundant
resources, tutorials, and support available online.
◦
Rich Tooling: There's a vast ecosystem of tools and platforms built around Git, such as GitHub, GitLab, Bitbucket,
various GUIs, and integrations with IDEs.
6.
Flexibility in Workflows:
◦ Git doesn't enforce a specific workflow, allowing teams to adopt various strategies like GitFlow, GitHub Flow,
or simple feature branching, depending on their needs.
7.
Open Source:
◦ Git is open-source, meaning it's free to use and has a transparent development process.
Windows
1. Download the Git Installer: Go to the official Git website and download the latest installer for Windows.
2. Run the Installer: Double-click the downloaded .exe file to start the installation wizard.
Select components (defaults are generally recommended, including Git Bash and Git GUI).
Adjust your PATH environment (the recommended option is "Git from the command line and also from 3rd-
party software").
Choose HTTPS transport backend (use the default "Use the OpenSSL library").
Configure line ending conversions (the default "Checkout Windows-style, commit Unix-style line endings"
is usually best).
Choose the default behavior for git pull (default is usually fine).
5. Verify Installation: Open Git Bash (or Command Prompt/PowerShell) and type git --version . You should see the
installed Git version.
macOS
1. Using Homebrew (Recommended):
If you don't have Homebrew installed, open your Terminal and run:
3. Xcode Command Line Tools: Git is also included with Xcode Command Line Tools. If you have Xcode
installed, you can install the tools by running:
xcode-select --install
4. Verify Installation: Open Terminal and type git --version . You should see the installed Git version.
Linux (Debian/Ubuntu)
1. Open Terminal: Open your terminal application.
3. Install Git:
4. Verify Installation:
git --version
Linux (Fedora)
1. Open Terminal: Open your terminal application.
2. Install Git:
3. Verify Installation:
git --version
Git Configuration
After installing Git, you should configure your user name and email address. These details will be associated with
your commits and are important for identifying who made which changes.
-global : This flag indicates that the configuration should apply to all repositories on your system. If you omit -
Example:
: Replace this with your actual email address. It's common practice to use the same email
"your.email@example.com"
Example:
git init
This command creates a new, empty Git repository in the current directory. It creates a hidden .git directory,
which contains all the necessary files for Git to track your project's history.
Steps:
1. Navigate to your project directory: Open your terminal or command prompt and use the cd command to
navigate to the root directory of your project.
cd /path/to/your/project
git init
You will see a message like: Initialized empty Git repository in /path/to/your/project/.git/
Now, your project directory is a Git repository, and Git can start tracking its changes.
Checking Status
The git status command is one of the most frequently used Git commands. It shows you the state of your working
directory and the staging area.
git status
This command tells you:
Which files are untracked (new files that Git isn't yet monitoring).
Which files are modified but not yet staged for commit.
Example Output (initial state after git init and creating a file):
Let's say you create a file named index.html in your project directory.
git status
Output:
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
index.html
nothing added to commit but untracked files present (use "git add" to track)
This output indicates that index.html is a new file that Git hasn't started tracking yet.
Staging Area (Index): This is an intermediate area where you prepare changes before committing them. You
can selectively add changes from different files to the staging area.
Commit: A commit is a snapshot of your repository at a specific point in time. It's a record of the changes
you've made, along with a message describing those changes.
<file> : The name of the file you want to add to the staging area.
Examples:
Add all changes in the current directory (including new files and modifications):
git add .
Add all changes to tracked files (but not untracked new files):
git add -u
git status
Output:
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: index.html
Now, index.html is in the staging area, ready for the next commit.
: This flag allows you to provide a short, descriptive message for your commit directly on the
m "message"
command line. This message is crucial for understanding the purpose of the changes in the future.
Example:
Now, your changes are permanently saved in the Git history as a commit. If you run git status again, it will show:
On branch master
nothing to commit, working tree clean
This indicates that all your changes have been committed, and your working directory matches the latest commit.
1. Untracked: These are new files that Git has not yet seen or been told to manage. They are not part of your
repository's history. When you run git status , untracked files appear under "Untracked files."
Action: To move an untracked file to the "staged" state, you use git add <file> .
2. Unmodified: These files are unchanged since your last commit. They are identical to the version in your last
commit.
3. Modified: These files have been changed since your last commit, but the changes have not yet been added to
the staging area. When you run git status , modified files appear under "Changes not staged for commit."
Action: To move a modified file's changes to the "staged" state, you use git add <file> .
4. Staged (or Index): These files contain changes that have been marked to be included in the next commit.
When you run git status , staged files appear under "Changes to be committed."
Action: To record the staged changes permanently in the repository's history, you use git commit -m "message" .
After a commit, the file moves back to the "unmodified" state.
git log
Common Options:
git log --oneline : Shows each commit on a single line, displaying a shortened commit hash and the commit
message. Useful for a concise overview.
git log --graph --oneline --decorate : Shows a textual graphical representation of the commit history, especially useful
for visualizing branches and merges.
git log -p : Shows the patch (diff) introduced by each commit. This lets you see the exact changes (lines
added/removed) for each commit.
git log <filename> : Shows the commit history for a specific file.
Example:
git log
Output (example):
commit b123456789abcdef0123456789abcdef01234567
Author: Alice Smith <alice.smith@example.com>
Date: Wed Jul 10 09:00:00 2024 +0530
commit a987654321fedcba987654321fedcba987654321
Author: Alice Smith <alice.smith@example.com>
Date: Wed Jul 10 09:30:00 2024 +0530
: The full or partial (first few characters) hash of the commit you want to inspect. You can get this
<commit_hash>
Example:
This would show you the changes made in the commit with the hash starting with b123456 .
Undoing Changes
: (Recommended modern command) Discards changes in the working directory for a specific file,
git restore <file>
reverting it to the state in the staging area or the last commit if not staged.
: Unstages a file, moving it from "Changes to be committed" back to "Changes not staged
git restore --staged <file>
Use Cases:
You've made changes to index.html and want to discard them and revert to the last committed version:
You've git add ed style.css but then realized you don't want to commit those changes yet (you want to unstage
it):
Caution: git restore and git checkout -- <file> will overwrite your local changes, so make sure you don't need them
before running these commands.
git reset
The git reset command is more powerful and can be used to uncommit changes, move the HEAD pointer, and
modify the staging area. It's often used to "undo" commits.
Important Modes:
Useful for combining multiple small commits into one larger commit before pushing.
Useful for undoing a commit and then re-staging/re-committing with different changes.
Permanently deletes all uncommitted changes and reverts your project to the exact state of the
specified commit. Use with extreme caution, as you can lose work.
Use Cases:
After this, your changes will be in the "modified" state, and you can git add and git commit again.
You want to completely wipe out all local changes and revert to a specific commit:
Caution: Avoid using git reset --hard on commits that have already been pushed to a shared remote repository, as it
can cause significant problems for collaborators.
Removing Files
Git provides a specific command for removing files from your repository while also removing them from your
working directory.
git rm <file>
This command removes a file from your working directory and stages the deletion for the next commit.
Use Cases:
You want to delete old_script.js from your project and record this deletion in Git:
git rm old_script.js
After running this, old_script.js will be deleted from your file system, and git status will show "deleted:
old_script.js" under "Changes to be committed". You then need to commit this change:
: This command removes the file from Git's tracking (staging area and future commits) but
git rm --cached <file>
keeps the file in your working directory. This is useful if you accidentally added a file that should not be
version-controlled (e.g., a large binary or a configuration file).
After this, sensitive_data.txt will remain in your directory but will no longer be tracked by Git. You might then add it
to your .gitignore file.
Important Note: If you simply delete a file using your operating system's file explorer ( rm file.txt or del file.txt ), Git will
detect it as a "deleted" file when you run git status . You would then need to git add <file> (or git add . ) to stage the
deletion, and then git commit it. Using git rm combines these steps.
What is a Branch?
Isolate Work: Develop new features or fix bugs in isolation from the main project.
Experiment: Try out new ideas without risking the stability of your main codebase.
By default, when you initialize a Git repository, you are on the master (or main in newer Git versions) branch. This is
typically considered the main, stable line of development.
Example:
# First, ensure you are on the branch you want to base your new branch off (e.g., master)
git checkout master
To see a list of all local branches and identify which one you're currently on, use:
git branch
Output (example):
feature/add-login
* master
Example:
Output:
Example:
Example:
It's generally recommended to use git switch for branch operations and git restore for file operations, as they provide
clearer intent.
Merging Branches
After working on a feature or bug fix in a separate branch, you'll eventually want to integrate those changes back
into another branch (often master or main ). This process is called merging.
1. Switch to the target branch: First, switch to the branch you want to merge changes into. This is typically your
master or main branch.
2. Perform the merge: Now, merge the changes from your feature branch into master .
Merge Scenarios:
Fast-Forward Merge: If the target branch (e.g., master ) has not had any new commits since the feature branch
was created, Git simply moves the master pointer forward to the tip of the feature branch. This is a "fast-
forward" merge, and no new merge commit is created.
Git will open your configured text editor to allow you to write a commit message for the merge commit (it
provides a default message). Save and close the editor to complete the merge.
1. Identify Conflict Markers: Open the conflicted files in your text editor. Git inserts special "conflict markers" to
show you the conflicting sections:
<<<<<<< HEAD
This is the content from the current branch (where HEAD is pointing).
=======
This is the content from the branch you are merging from.
>>>>>>> feature/add-login
<<<<<<< HEAD : Marks the beginning of the conflicting change from your current branch.
>>>>>>> <branch_name> : Marks the end of the conflicting change from the incoming branch.
2. Manually Edit the File: Carefully review the conflicting sections. You need to decide which changes to keep,
combine, or discard. Delete the conflict markers ( <<<<<<< , ======= , >>>>>>> ) and edit the code to the desired
final state.
Example Resolution:
Original conflict:
<div class="header">
<h1>Welcome</h1>
<<<<<<< HEAD
<p>Your personal dashboard</p>
=======
<p>Login to your account</p>
>>>>>>> feature/add-login
</div>
<div class="header">
<h1>Welcome</h1>
<p>Your personal dashboard</p>
<p>Login to your account</p>
3. Stage the Resolved File: After editing and saving the file, you need to tell Git that you've resolved the conflict
for that file by adding it to the staging area:
4. Commit the Merge: Once all conflicts are resolved and staged, complete the merge by creating a new
commit. Git will often pre-populate a merge commit message; you can accept it or modify it.
If you run git status during a conflict, it will guide you through the process, showing "Unmerged paths" and
instructions.
Deleting Branches
Once a feature branch has been merged into its target branch and is no longer needed, you can delete it to keep
your repository clean.
Example:
Output:
Example:
Remember that deleting a local branch does not delete it from any remote repositories (like GitHub). You would
need to push the deletion to the remote as well ( git push origin --delete <branch_name> ).
What is GitHub?
GitHub is a web-based platform that provides hosting for software development and version control using Git. It's
more than just a place to store your code; it's a powerful collaboration platform that offers:
Remote Repository Hosting: A central place to store your Git repositories, making them accessible to others
and providing a backup.
Collaboration Tools: Features like pull requests, issue tracking, project management boards, and wikis that
facilitate team collaboration.
Code Review: Streamlined processes for reviewing code changes before they are merged.
Open Source Community: The largest open-source community in the world, allowing developers to discover,
contribute to, and learn from millions of projects.
Continuous Integration/Deployment (CI/CD): Integration with various CI/CD tools (including GitHub Actions)
to automate testing and deployment.
While Git is the version control system, GitHub is a service that uses Git to host and manage projects.
2. Sign Up: Click on the "Sign up" button (usually in the top right corner).
3. Enter Details: Follow the prompts to enter your email address, create a password, and choose a username.
4. Verify Account: GitHub will send a verification email to the address you provided. Click the verification link in
the email.
5. Personalize (Optional): You might be asked a few questions about your experience and how you plan to use
GitHub. You can answer these or skip them.
Once your account is created, you'll have access to your GitHub dashboard.
2. New Repository:
On your GitHub dashboard, look for the "New" button (often a green button with a plus icon) in the left
sidebar under "Repositories" or in the top right corner of the page. Click it.
3. Repository Name:
Enter a Repository name (e.g., my-first-website , my-project ). Choose a short, memorable name.
4. Description (Optional):
5. Public or Private:
Choose if your repository should be Public (anyone can see it) or Private (only you and people you
explicitly share with can see it). For personal projects or learning, Public is often fine.
Check the "Add a README file" box. A README file is a plain text file that provides basic information about
your project.
Your new repository will now be created on GitHub, and you'll be redirected to its page.
Cloning Repositories
Cloning is the process of creating a local copy of a remote Git repository. When you clone a repository, you
download its entire history, including all branches and commits.
: The URL of the Git repository you want to clone. You can find this on the GitHub repository page
<repository_url>
by clicking the "Code" button (usually green) and copying the HTTPS or SSH URL.
Steps:
1. Navigate to your desired directory: Open your terminal or command prompt and cd into the directory where
you want to store your local copy of the repository.
cd /path/to/your/development/folder
2. Clone the repository: Copy the HTTPS URL from your GitHub repository (e.g., https://github.com/your-username/your-
repo.git ).
This will create a new directory named your-repo (or whatever the repository name is) in your current location,
containing all the files and the .git history.
origin : This is a conventional name given to the primary remote repository. You could name it something else,
but origin is the standard.
Steps:
cd /path/to/your/local/project
You can verify that the remote was added by running git remote -v .
u : Short for -set-upstream . This flag tells Git to remember that your local main (or master ) branch is associated
with the main (or master ) branch on the origin remote. After this, you can simply use git push and git pull without
specifying origin main .
origin : The name of your remote repository (as defined with git remote add ).
main (or master ): The name of the local branch you want to push, and the name of the remote branch you want
to push to. Newer Git versions default to main , older ones to master . Check your local branch name with git
branch .
Example:
This will push all your local commits from your main branch to the main branch on GitHub.
git push
This command uploads your local commits to the remote repository. You use this after you've made new commits
locally and want to share them with others or back them up on GitHub.
If you've already used git push -u origin main (or master ), you can simply use:
git push
If you haven't set up upstream tracking, or if you want to push a specific branch, you would use:
Example:
git pull
This command downloads changes from the remote repository and automatically merges them into your current
local branch. It's a combination of git fetch and git merge . You use this to get the latest changes that others have
pushed to the remote.
Example:
git fetch
This command downloads changes from the remote repository but does not automatically merge them into your
local branch. It updates your local copy of the remote's branches (e.g., origin/main ), allowing you to inspect
changes before merging them.
You want to see what changes have occurred on the remote without immediately integrating them into your
working directory.
You want to review changes from a remote branch before deciding to merge them.
Example:
After git fetch , you can compare your local branch with the remote tracking branch (e.g., git diff main origin/main ) or
merge manually ( git merge origin/main ).
Forking Repositories
Forking is a fundamental concept in GitHub collaboration, especially in the open-source world. When you "fork" a
repository, you create a personal copy of that repository on your GitHub account.
Why Fork?
Contribution without Direct Access: It allows you to contribute to a project without needing write access
to the original (upstream) repository. You make changes in your fork, and then propose those changes
back to the original.
Personal Experimentation: You can experiment with a project without affecting the original codebase.
Independent Development: You can use a fork as a starting point for your own project, even if you don't
intend to contribute back to the original.
How to Fork:
2. In the top right corner of the page, click the "Fork" button.
2. Clone your forked repository to your local machine: git clone https://github.com/your-username/forked-repo.git
3. Add the original repository as an "upstream" remote: This allows you to fetch changes from the original
project to keep your fork up-to-date.
cd forked-repo
git remote add upstream https://github.com/original-owner/original-repo.git
4. Make changes in your local fork, commit them, and push to your fork: git push origin your-feature-branch
Pull Requests
A Pull Request (PR) is the heart of collaboration on GitHub. It's a mechanism for you to propose changes from one
branch (often a feature branch in your fork) to another branch (often the main / master branch in the original
repository).
Tracks Progress: It acts as a record of the proposed changes, their discussion, and their eventual
integration.
Triggers CI/CD: PRs can automatically trigger automated tests and checks (e.g., via GitHub Actions) to
ensure code quality.
1. Push your changes to a branch in your forked repository (or directly to a branch in the original repo if you
have write access).
3. GitHub will often show a prominent "Compare & pull request" button if it detects new pushes. Click it.
4. Alternatively, navigate to the "Pull requests" tab and click "New pull request."
Base repository/branch: This is the repository and branch you want your changes to go into (e.g.,
original-owner/original-repo 's main branch).
Head repository/branch: This is your repository and branch that contains the changes you want to
propose (e.g., your-username/forked-repo 's your-feature-branch ).
6. Add a title and description: Provide a clear, concise title and a detailed description of your changes, why
they were made, and any relevant context.
1. Discussion: Reviewers and the PR author discuss the proposed changes. This can involve questions,
clarifications, and suggestions for improvement.
2. Comments: Reviewers can add comments directly to specific lines of code or general comments on the
PR.
3. Suggestions: Reviewers can suggest specific code changes directly within the PR interface, which the
author can apply with a single click.
4. Automated Checks: GitHub Actions or other CI/CD tools may run automated tests, linting, and other
checks. The results are displayed on the PR.
5. Approval/Changes Requested: Reviewers can approve the PR (signifying it's ready to merge) or request
changes.
6. Iteration: The PR author makes requested changes, pushes new commits to the same branch, and the
review process continues until the PR is approved.
7. Merge: Once approved and all checks pass, the PR can be merged into the base branch.
Keep PRs small: Smaller PRs are easier and faster to review.
Respond promptly: Address comments and questions from reviewers in a timely manner.
GitHub Issues
Linked Pull Requests: Issues can be linked to PRs, so you can see which code changes address a specific
issue.
Custom Fields: Define custom fields to track additional data (e.g., priority, status, estimated effort).
Views: Create different views (table, board, roadmap) to visualize your work in various ways.
Automations: Automate common tasks, like moving issues to a "Done" column when a linked PR is
merged.
Items: Projects can include issues, pull requests, and draft issues (simple notes).
What is CI/CD?
Continuous Integration (CI): The practice of frequently merging code changes into a central repository. CI
pipelines automatically build and test the code every time changes are pushed, helping to catch
integration issues early.
Continuous Deployment (CD): The practice of automatically deploying code changes to production (or
staging) environments after they pass CI tests.
Steps can run commands, use actions (reusable pieces of code from the GitHub Marketplace), or run
scripts.
Workflows are triggered by events (e.g., push to a branch, pull_request opened, issue_comment created,
schedule ).
Automated Testing: Run unit tests, integration tests, and end-to-end tests on every push or pull request.
Build Automation: Compile code, build Docker images, or create deployable artifacts.
Deployment: Automatically deploy applications to cloud providers (AWS, Azure, GCP) or other hosting
services.
Static Site Generation: Build and deploy static websites (e.g., using Jekyll, Hugo, Next.js).
name: CI Pipeline
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build-and-test:
runs-on: ubuntu-latest # The type of machine to run the job on
steps:
- name: Checkout code
uses: actions/checkout@v4 # Action to checkout your repository code
This simple workflow will run whenever code is pushed to main or a pull request is opened targeting main . It
checks out the code, sets up Node.js, installs dependencies, and runs tests.
Git Stash
How it works:
It records the current state of your working directory and index (staging area) but then reverts your
working directory to match the HEAD commit.
This allows you to switch branches, pull, or perform other Git operations without committing incomplete
work.
Your stashed changes are stored in a stack and can be reapplied later.
Common Commands:
git stash save "message" (or git stash ): Stashes your current changes with an optional message. If no message is
provided, Git creates a default message.
: Applies the stashed changes back to your working directory. By default, it applies
git stash apply [stash@{n}]
the most recent stash ( stash@{0} ). The stash remains in the stash list.
git stash pop [stash@{n}] : Applies the stashed changes and then immediately drops (removes) it from the stash
list. This is often preferred if you're sure you won't need the stash again.
git stash drop [stash@{n}] : Deletes a specific stash from the list without applying it.
Rebase vs Merge
git merge
How it works: git merge combines the changes from two branches by creating a new merge commit. This
merge commit has two parent commits, one from each of the merged branches.
Commit History: It preserves the exact history of both branches, showing exactly when and where the merge
occurred. The history is non-linear, as it shows parallel development.
When to use:
When you want to preserve the complete, accurate history of your project, including all merges and
parallel development.
When working on public or shared branches (e.g., main / master ), as rebasing shared history can cause
issues for collaborators.
Example:
git rebase
How it works: git rebase moves or "replays" a series of commits from one branch onto another. Instead of
creating a merge commit, it rewrites the commit history of the feature branch to appear as if development
happened directly on top of the target branch.
Commit History: It creates a linear history, making it look like all development happened sequentially. The
original commits on the feature branch are effectively discarded and new commits with different hashes are
created.
When to use:
When you want a clean, linear commit history, especially for personal feature branches before merging
them into a shared branch.
To incorporate upstream changes into your feature branch without creating unnecessary merge commits.
For "cleaning up" your commits (e.g., squashing multiple small commits into one) using git rebase -i
(interactive rebase).
Example:
This command takes all the commits on feature-branch that are not on main , and reapplies them one by one onto the
tip of main .
Key Difference Summary:
Commit History Non-linear, preserves merge points Linear, rewrites history of rebased branch
Merge Commit Creates a new merge commit Does not create a merge commit (unless conflicts)
Safety Safer for shared/public branches Can be dangerous on shared branches (rewrites history)
Clarity Shows actual development history (parallel work) Creates a cleaner, sequential-looking history
Rule of Thumb:
Rebase your private feature branches onto main / master to keep your history clean before merging.
Cherry Pick
The git cherry-pick command allows you to pick a specific commit from one branch and apply it to another branch.
This is useful when you only need a few specific changes from a branch, rather than merging the entire branch.
How it works: It takes the changes introduced by a single commit and creates a new commit with those same
changes on your current branch. The new commit will have a different hash than the original.
When to use:
To apply a specific feature from one branch to another without bringing over all other commits.
Example:
1. Find the commit hash you want to cherry-pick (e.g., using git log --oneline ). Let's say the commit hash is abcdef1 .
If there are conflicts, resolve them, git add the resolved files, and then git cherry-pick --continue .
Git Tags
Git tags are pointers to specific points in your repository's history. They are typically used to mark release points
(e.g., v1.0 , v2.0-beta ). Unlike branches, tags are fixed and do not move.
Types of Tags:
Lightweight Tags: Simple pointers to a commit, like a branch that never moves. They are just a name and
a commit hash.
Annotated Tags: Full objects in the Git database. They contain the tagger's name, email, and date, and
can have a tagging message. They are also signed with GPG for verification. Annotated tags are generally
recommended for releases.
Common Commands:
git tag
# Example Output:
# v1.0
# v1.1-beta
git push origin <tag_name> : Pushes a specific tag to the remote repository. Tags are not pushed by default with
git push .
git push origin --tags : Pushes all local tags to the remote repository.
git push origin --delete <tag_name> : Deletes a tag from the remote repository.
Prevent committing sensitive information: (e.g., API keys, configuration files with credentials).
1. Create a file named .gitignore in the root directory of your Git repository.
2. Add patterns to the file, one per line, specifying what to ignore.
.gitignore Patterns:
folder/ : Ignores the folder directory and all its contents anywhere in the repository.
!important.log : Negates a previous ignore rule. If .log is ignored, but important.log should be tracked, use this.
foo/**/bar : Matches bar in foo/bar , foo/a/bar , foo/a/b/bar , etc. (double asterisk for matching zero or more
directories).
Important: If a file is already tracked by Git (i.e., it's already in a commit), adding it to .gitignore will not stop Git
from tracking it. You need to untrack it first:
Git Flow
Git Flow is a more complex, highly structured branching model introduced by Vincent Driessen. It defines a strict
set of rules for branching and merging, making it suitable for projects with scheduled release cycles and hotfixes.
Key Branches:
develop : Integrates all the completed feature branches and serves as the main development branch.
release/* : Branches created off develop to prepare for a new production release (bug fixes, final touches).
hotfix/* : Branches created off master to quickly fix critical bugs in production.
Workflow Summary:
5. Bug fixes and final changes are made on the release branch.
6. The release branch is merged into both master (tagged with the version number) and develop .
Pros:
Clear separation of concerns for different types of development (features, releases, hotfixes).
Cons:
Can be overly complex for smaller teams or projects with continuous delivery.
GitHub Flow
GitHub Flow is a simpler, lightweight, and continuous delivery-oriented branching model. It's designed for
projects that deploy frequently and prioritize simplicity.
Key Branches:
feature/* (or any descriptive branch name): Short-lived branches created off master for any new work
(features, bug fixes, experiments).
Workflow Summary:
1. Create a new, descriptive branch from master for any new work.
3. Open a Pull Request (PR) when you need feedback or think the work is ready to merge.
4. Review the code, run automated tests, and discuss changes in the PR.
6. Merge the branch into master only after it's been reviewed, tested, and is ready for production.
Pros:
Ideal for web applications and projects with rapid deployment cycles.
Cons:
Might be too simplistic for projects with very strict release schedules or complex versioning requirements.
GitHub Flow: Choose if you prioritize continuous delivery, have a smaller team, or work on web applications
that deploy frequently.
Concept: All new development (features, bug fixes, experiments) should occur in dedicated branches rather
than directly on the master or develop branch.
Steps:
1. Create a new branch: From your main development branch ( master or develop ), create a new branch for
your feature. Use a descriptive name (e.g., feature/user-profile , bugfix/login-issue ).
2. Develop and Commit: Work on your feature, making regular, small, and descriptive commits to your
feature branch.
3. Push to Remote (Optional, but recommended for collaboration): Regularly push your feature branch to
the remote repository.
4. Keep up-to-date (Optional, but recommended): Periodically pull or rebase changes from the main
development branch into your feature branch to avoid large merge conflicts later.
5. Open a Pull Request: Once the feature is complete and tested locally, open a Pull Request to merge your
feature branch back into the main development branch.
6. Code Review and Merge: Participate in code review, address feedback, and once approved, merge the
feature branch.
7. Delete the feature branch: After merging, delete the local and remote feature branch to keep the
repository clean.
Benefits:
Code Review: Provides a natural point for code review before integration.
Release Management
Release management in Git refers to the process of preparing, stabilizing, and deploying new versions of your
software. The approach varies depending on your chosen Git workflow.
Only bug fixes and minor changes directly related to the release are allowed on this branch.
Once stable, the release branch is merged into master (and tagged) and back into develop .
New features are merged into master as soon as they are ready and tested.
Versioning (e.g., v1.0.0 ) is usually handled by creating Git tags on master at the point of deployment.
Git Tags: Always tag the commit that represents a release in master (or main ).
Release Notes/Changelog: Document the changes, new features, and bug fixes included in each release.
This can be generated from commit messages or manually curated.
Automated Testing: Ensure robust CI/CD pipelines run all necessary tests before a release.
Hotfixes
Hotfixes are urgent bug fixes applied directly to production code to resolve critical issues without waiting for the
next planned release cycle.
The hotfix branch is then merged into both master (and tagged) and develop . This ensures the fix is in
production and also integrated into the ongoing development.
# On master
git checkout master
git checkout -b hotfix/critical-bug-fix
After review and automated tests, the hotfix branch is merged into master and immediately deployed.
Since master is always deployable, a hotfix is essentially just a high-priority feature branch.
# On master
git checkout master
git checkout -b hotfix/critical-bug-fix
Minimal Changes: Only include the necessary changes for the fix.
Integration: Ensure the fix is integrated back into all relevant development branches.
What is SSH?
SSH (Secure Shell) is a cryptographic network protocol for secure data communication. In the context of Git, it
provides a secure channel over an unsecured network by using public-key cryptography.
1. You generate an SSH key pair on your local machine: a private key (kept secret on your computer) and a
public key (which you upload to GitHub).
2. When you connect to GitHub using SSH, your local machine uses your private key to prove your identity.
3. GitHub uses your public key to verify that you are who you claim to be.
4. This eliminates the need to enter your username and password (or personal access token) every time you
interact with the remote repository.
Benefits of SSH:
Security: More secure than password-based authentication, especially against brute-force attacks.
ls -al ~/.ssh
Follow the prompts (you can press Enter for default location and no passphrase, though a passphrase
adds an extra layer of security).
Copy the entire output, starting with ssh-ed25519 (or ssh-rsa ) and ending with your email.
ssh -T git@github.com
You should see a message like: Hi <your-username>! You've successfully authenticated, but GitHub does not provide shell access.
cd /path/to/your/repo
git remote set-url origin git@github.com:your-username/your-repo.git
Commit Signing
Commit signing allows you to cryptographically sign your Git commits and tags, ensuring their authenticity and
integrity. This verifies that the commit was indeed created by you and that its content hasn't been tampered with
since it was signed.
Verification: Others can verify that a commit truly came from you.
Compliance: Some organizations or projects may require signed commits for auditing or security policies.
How it works:
You use a GPG (GNU Privacy Guard) key to sign your commits. Your public GPG key is then uploaded to
GitHub (similar to SSH keys). When you push a signed commit, GitHub verifies the signature against your
public key.
1. Install GPG:
gpg --full-generate-key
Follow the prompts (choose RSA and RSA , default key size 3072 or 4096 , set an expiration, and provide your
real name and email address that matches your Git config). Remember your passphrase!
3. List your GPG keys and get your GPG key ID:
Look for a line like sec rsa3072/0xYOURGPGKEYID 2024-07-10 [SC] and copy the 0xYOURGPGKEYID part.
Copy the entire output, including -----BEGIN PGP PUBLIC KEY BLOCK----- and -----END PGP PUBLIC KEY BLOCK----- .
Paste your copied public GPG key into the "Key" field.
git add .
git commit -m "My first signed commit" # If commit.gpgsign is true
# Or: git commit -S -m "My first signed commit"
git push
On GitHub, you should now see a "Verified" badge next to your signed commit.
Imperative Mood: Use the imperative mood ("Add feature," not "Added feature" or "Adds feature").
Prefix (Optional): Consider a prefix like feat: , fix: , docs: , chore: , refactor: (e.g., feat: Add user authentication ).
2. Blank Line: Always include a blank line between the subject and the body. This is important for Git tools
like git log --oneline .
3. Body (Optional):
Explain Why and How: Elaborate on the motivation for the change, the problem it solves, and any
significant implementation details.
Reference Issues/PRs: Link to relevant issue trackers (e.g., Fixes #123 , Closes #456 ).
Resolves #789
asdfasdf (Meaningless)
What it does: Overwrites the remote branch's history with your local history, even if your local history is
different (e.g., after a git rebase ).
Danger: If others have pulled the old history, force pushing will cause their local repositories to diverge,
leading to difficult merge conflicts and potentially lost work for them.
When to use (with extreme caution): Only on branches that are strictly your own and no one else is
working on, or after coordinating carefully with your team. Use -force-with-lease for a safer force push, which
fails if the remote branch has new commits you haven't seen.
Problem: Git is optimized for tracking changes in text files. Committing large binary files (e.g., images,
videos, archives, compiled executables) can bloat your repository size, slow down operations ( clone ,
fetch ), and make history difficult to manage.
Solution: Use Git LFS (Large File Storage) for large files. Git LFS replaces large files in your repository with
small pointer files, while the actual file content is stored on a remote Git LFS server.
Also: Use .gitignore to prevent large build artifacts or temporary files from being committed in the first
place.
Problem: Accidentally committing API keys, passwords, private certificates, or other sensitive data. Once
committed, even if you delete the file in a subsequent commit, the sensitive data remains in the
repository's history.
Solution:
Use .gitignore to prevent sensitive files (e.g., .env files) from being committed.
If you accidentally commit sensitive data, you must use tools like git filter-repo (or the older git filter-branch )
to rewrite the history and remove the sensitive data permanently. This is a complex operation and
requires force pushing.
Problem: Working on an outdated local branch can lead to large and complex merge conflicts when you
finally try to integrate your changes.
Solution:
git pull frequently to get the latest changes from the remote.
Before starting new work, always git pull on your main development branch.
Problem: Bypasses code review, automated tests, and can introduce unstable or breaking changes
directly into your production-ready branch.
Solution: Always work on feature branches (or bugfix branches) and use Pull Requests for all changes
that merge into master / main . This is a cornerstone of collaborative workflows like GitHub Flow.
Problem: Git provides helpful messages. Ignoring them can lead to unexpected behavior or difficult-to-
diagnose issues later.
Solution: Read Git's output carefully. If you encounter an error or a warning, try to understand it before
proceeding. Git often suggests the next steps or commands to resolve the situation.
By understanding and applying these security measures and best practices, you can ensure a more secure,
efficient, and collaborative Git workflow.
How it works:
You push your static website files (HTML, CSS, JavaScript, images) to a specific branch (usually gh-pages
GitHub automatically builds (if using Jekyll) and deploys your site.
Key Features:
Custom Domains: You can use your own custom domain name.
Jekyll Support: Built-in support for Jekyll, a static site generator, allowing you to write content in
Markdown.
HTTPS Support: All GitHub Pages sites are served over HTTPS.
1. Create a Repository: Create a new public repository (or use an existing one).
2. Add your site files: Push your HTML, CSS, JS, and other static assets to your repository.
3. Configure Pages:
Under "Build and deployment", choose your source branch (e.g., main or gh-pages ) and optionally a
folder (e.g., /docs or /root ).
Click "Save".
GitHub CLI
The GitHub CLI (Command Line Interface) is a command-line tool that brings GitHub's features directly to your
terminal. It allows you to interact with GitHub without leaving your command line, streamlining many common
workflows.
Efficiency: Perform common GitHub tasks (creating PRs, managing issues, reviewing code) without
switching to a web browser.
Common Commands:
Installation:
Linux (Debian/Ubuntu):
Refer to the official GitHub CLI documentation for detailed installation instructions for your OS.
Git Submodules
Git submodules allow you to embed one Git repository inside another Git repository as a subdirectory. This is
useful when your project depends on a specific version of an external project, and you want to keep that
dependency separate but still track it within your main repository.
When your project has a strong dependency on an external library or component that is managed in its
own Git repository.
When you want to track a specific version of that dependency (not just the latest).
When you want to keep the dependency's history separate from your main project's history.
The parent repository stores a reference to a specific commit in the submodule's repository, not the actual
files.
Common Commands:
git submodule add <repository_url> <path> : Adds a new submodule. This clones the submodule into the specified
path and adds an entry to your .gitmodules file.
git submodule init : Initializes your local configuration file, copying the mapping from the .gitmodules file.
git submodule update : Fetches all data from the submodule project and checks out the commit specified in the
superproject.
Often combined: git submodule update --init --recursive (for nested submodules).
git clone --recurse-submodules <repository_url> : Clones the main repository and all its submodules in one go.
git submodule foreach git pull origin main : To update all submodules to their latest main branch (be careful, this can
change the superproject's state).
git rm <path_to_submodule> : Removes a submodule. You'll also need to remove its entry from .gitmodules and
.git/config .
Considerations/Drawbacks:
Complexity: Submodules can add complexity to your workflow, especially for new team members.
Version Management: You must explicitly update the submodule reference in the parent repository when
the submodule changes.
Alternatives: For many cases, package managers (npm, Composer, Maven, pip) or monorepo tools might
be simpler alternatives.
Avoid Repository Bloat: Keeps your Git repository small and fast, as large binaries are not stored directly
in the Git history.
Faster Operations: git clone , git fetch , and other operations become much faster because you're only
downloading small pointers initially.
Better Performance: Git is optimized for text diffs; LFS handles binaries efficiently.
Collaboration: Makes it feasible to collaborate on projects that include large assets (e.g., game
development, design, data science).
2. You tell Git LFS which file types to track (e.g., .psd , .mp4 , .zip ).
3. When you commit a file that matches a tracked pattern, Git replaces the file's content with a small
"pointer" file in your Git repository.
4. The actual large file is uploaded to the Git LFS server (e.g., GitHub's LFS server).
5. When someone clones or checks out a branch, Git LFS automatically downloads the actual large files
when needed.
3. Track file types: Tell Git LFS which file extensions or patterns to track. This adds entries to your .gitattributes
file.
# .gitattributes example
*.psd filter=lfs diff=lfs merge=lfs -text
assets/*.mp4 filter=lfs diff=lfs merge=lfs -text
5. Add and Commit: Stage and commit your files as usual. Git LFS will handle the large files automatically.
git add .
git commit -m "Add large PSD file"
6. Push:
git push
Git LFS will push the large files to the LFS server.
Important Notes:
Git LFS files are only stored on the LFS server, not directly in the .git directory.
If you're migrating an existing repository with large files, you'll need to use git lfs migrate to rewrite history
and convert existing large files to LFS pointers.
GitHub provides a certain amount of free Git LFS storage and bandwidth; exceeding this may incur costs.