installation via terminal

For Ubuntu

sudo apt update
sudo apt install git

For Fedora

sudo dnf update
sudo dnf install git
git --version| | shows git version |'inst5'

initialization

git int| https://git-scm.com/docs/git-init |initializes a new git repository |'init1'
git clone <https or ssh> [help] clones a repo from github [ssh is preferred]

To partially clone a large repo:

git clone --filter=blob:none --sparse <SSH or Https, ex: https://github.com/user/huge-repo.git>
cd huge-repo
git sparse-checkout init --cone
git sparse-checkout set <path_to_folder#1> <path_to_folder#2>

git domains

Working directory/tree is the uncommitted area where you edit, create, and delete files.
Staging area (AKA index) is a middle ground to prepare the content of the next commit.
Local repository (stored in .git in the root project) contain the project history, configurations, branches, and tags.
Remote repository (for example github/bitbucket) is a copy of the project on another server, used for collaboration and backup. You can directly clone the remote repo (usually named origin), or fork it into your space (your forked repo is usually called origin, and the main repo is called upstream).
various areas of git domains (working directory, staging area, and the local repo)

configuration and setup

The global user configs are stored in ~/.gitconfig file. To set the global configs, applied to the user on a system, use git --global, but it is easier if you manually set your .gitconfig [sample .gitconfig].
The repository configs stores in .git/config. To set the repository configs, use git --local
git config | https://git-scm.com/docs/git-config | it has several flags, some are listed here. |'conf1'
git config --list| | shows all local and global user configs. Add --local/--global to see local or global configs.|'conf2'
git config user.name/email/... | | returns the username/email or other items for the current computer. First, returns local if exists, if not, returns global, if not returns system. |'conf3'
git config --global user.name &lt;firstname lastname&gt;| | sets global username|'conf4'
git config --global user.email &lt;valid-email&gt;| | sets global email id|'conf5'
git config --global diff.tool <diff tool, ex vimdiff> sets the diff tool
git config --global merge.tool <merge tool, ex vimdiff> sets the merge tool
To prevent accidental staging or committing of files, you can add .gitignore file to the root. Any folder/extension/file that you don't want to push to the repo, you can add it to this file. [sample .gitignore - reference]. Putting a name in .gitignore, without/, ignores both files and folders with that name. But if we add / at the end of the name, it only ignores folders.
Gitignore doesn't ignore already tracked files. To just stop tracking a file that is already in the repo, run:
git rm --cashed <path_to_file_to_be_removed>
Git ignores directories with no files in it. To keep track of an empty directory, one can add one dot file (such as .gitkeep).

basic operations and snapshotting

HEAD is a reference/pointer to the current checked out commit. The content of the checked out commit/HEAD is in the working directory. After each commit HEAD moves. If you check out a commit/SHA, HEAD points to the new checked out commit, and in this case, it is called Detached Head. To refer to commits before HEAD, without using SHAs, use ~ (or ^). Example: HEAD~ (reference to a commit before HEAD), HEAD~~ (reference to two commits before HEAD), HEAD~3 (reference to 3 commits before HEAD). In a log report, you may see: HEAD->master, which means HEAD refer to the master branch (or any other branches).
git status| https://git-scm.com/docs/git-status | shows staged and unstaged changes |'snap1'
git add &lt;file(s) or path&gt;| https://git-scm.com/docs/git-add | adds unstaged changes to stage for the next commit |'snap2'
git add -i | | (or --interactive) it opens interactive staging mode, to carefully pick what you want to stage. There are 8 options (status, update, revert, add untracked, patch, diff, quit, help). if you have multiple changes in your file, patch mode allows to stage portions/hunks of the changes (you can directly run git add -p to go to the patch option). Git decides how to split changes into hunks, but it can split the hunk even further, if you ask git. There should be at least one unchanged line btw changes. This is possible through patch, and split hunk (s option). |'add1'
git diff [help] shows diff of unstaged changes. [See flags here.]
git commit -m "commit message"| https://git-scm.com/docs/git-commit | commits staged changes with a [hint: use a short message (< 50 chars) in the first line, in the present tense. Add longer comments on the following line.] |'snap4'
git commit | | (with no -m) opens a text editor, which allows a multiline message |'snap5'
git commit -am "commit message" | | stages and commits all in one command |'snap6'
git commit --amend | | adds the current staged changes to the last commit (merge it with that) |'snap7'
git reset &lt;flags&gt; &lt;commit&gt; &lt;--&gt; &lt;path&gt; | https://git-scm.com/docs/git-reset | moves the HEAD to a specific commit, and depending on the options, it adjusts the files in the staging area and working dir |'reset0'
git reset | | the opposite of git add. Moves staged files to the working dir. |'reset1'
git reset --soft &lt;commit/branch/tag/HEAD/HEAD^...&gt; | | moves the HEAD to the specified commit/branch/tag/HEAD ... and the changes go to the staging area. Use it for your own repo, which has not been shared with others. |'reset2'
git reset --hard &lt;commit/branch/tag/HEAD/HEAD^/...&gt; | | moves the HEAD to the specified commit/branch/tag/HEAD ... and the current branch pointer back, Resets the staging area (index) to match commit/branch/tag/HEAD .... This is a destructive command, throws away all changes in both the staging area and the working directory, restoring your repo to exactly the specified commit/branch ... state. |'reset3'
git reset --mixed &lt;commit/branch/tag/HEAD/HEAD^/...&gt; | | moves the HEAD and changes the staging area to match repo, but it does not change the working dir |'reset4'
git restore &lt;file_name&gt; | https://git-scm.com/docs/git-restore | restores a file changes to HEAD. It is equivalent to "git checkout HEAD -- file_name" or "git reset --hard HEAD" |'snap6'
git rm &lt;file&gt; | https://git-scm.com/docs/git-rm | adds deleted files to the stage for commit |'snap7'
git mv &lt;source&gt; &lt;destination&gt; | https://git-scm.com/docs/git-mv | moves or renames an existing file/directory path and stages for commit. It is equivalent to three commands: mv source destination; git rm source; git add destination. |'snap8'
git clean &lt;flags&gt; | https://git-scm.com/docs/git-clean | removes untracked files in the working tree |'cln0'
git clean -n | | shows untracked files that would have been removed if you run git clean -f |'cln2'
git clean -f | | permanently deletes untracked files |'cln1'
git notes | https://git-scm.com/docs/git-notes | adds extra information (annotations) to commits withtout modifying the commit itself, i.e., instead of rewriting the history with "git commit --amend", it adds metadata alongside a commit. It usually used to add review comments, test results, ticket IDs, etc. To see commit notes: "git log --show-notes"|'note0'
git notes add -m "note message" &lt;SHA&gt; | | adds a "note message" to commit with SHA. if no commit SHA specifies, it adds the note to the latest commit. |'note1'
git notes edit &lt;SHA&gt; | | edits a commit note |'note2'
git notes remove &lt;SHA&gt; | | removes a commit note |'note3'
git push &lt;repo_alias, ex origin&gt; refs/notes/*| | pushes all notes to the remote repo (say origin). By default, git does not push notes to remote repo. |'note4'
git fetch &lt;repo_alias, ex origin&gt; refs/notes/*| | fetches new notes from the remote repo (say origin). |'note5'

inspection & comparison

git log <flags> [help] shows commit logs. You can adjust/decorate the output, using various flags. It is easier to use alias for long command.
git log | | shows all commits for current branch |'log1'
git log -n 5 | | shows the last 5 commits on this branch |'log2'
git log -1 | | shows the last commit on this branch |'log5'
git log --oneline --graph -decorate -n 20 | | shows the graphical connection of the last 20 commit message |'log6'
git log --since=2025-03-01 --until=2025-03-31 --author="John"| | shows John's commits btw 2025/03/01~31 |'log7'
git log --after=2.weeks --before=2.days | | shows commits from 2 weeks ago until 2 days ago |'log8'
git log --grep="search" | | find "search" in the log |'log9'
git log &lt;file&gt; | | shows commits that changed file |'log10'
git log -L 100,150:&lt;file&gt;| | shows all commits that changed lines 100-150 in file |'log11'
git log --stat| | shows commit statistics |'log12'
git log -p | | shows the changes with the commits |'log13'
git log --format="%h -by %an %aD-commited %cn %cD : %s" [help] formats the commits. Allowable options are: medium(default), short, full, fuller, email, raw, oneline, or String. See Pretty Format for more details.
git log &lt;commit#1&gt;..&lt;commit#2&gt; | | shows the commits after commit 1 upto commit 2 |'log15'
git log &lt;commit#1&gt;...&lt;commit#2&gt; | | shows commits that are unique to each side (not shared) |'log16'
git log --show-notes shows commit logs with notes. See git notes.
git log --follow -- &lt;filename&gt;| | shows the commit history for a file, including renames |'log18'
git shortlog | https://git-scm.com/docs/git-shortlog | summaries a git log, mainly used to see who committed what in a repository. Groups commits by author and shows a list of commit messages under each author. Useful for generating release notes or contributor summaries. |'inst12'
git diff &lt;options&gt; &lt;--&gt; &lt;path&gt; | https://git-scm.com/docs/git-diff | shows stage/unstaged changes |'diff0'
git diff | | shows the diff btw working dir and repo, not the staged files and the repo |'diff1'
git diff --name-only | | lists the changed files |'diff2'
git diff --staged | | shows the diff btw staged files and repo. |'diff3'
git diff &lt;commit/branch#1/tag#1&gt;..&lt;commit/branch#2/tag#2&gt; | | shows the difference btw two non-consecutive commits |'diff4'
git diff SHA1..SHA2 > changes.patch [help] to create the patch file [see patch].
git difftool <SHA/HEAD/HEAD^/...> [help] similar to git diff, but uses a diff tool (ex vimdiff) to show the changes. The diff tool must be specified in the global git config. [see here].
git range-diff &lt;branchA/commitA..branchB/commitB&gt; &lt;branchA/commitA..branchC/commitC&gt; | https://git-scm.com/docs/git-range-diff | compares two commit ranges side by side. Similar to a diff for sequences of commits instead of files. Super useful when rebasing or reviewing patch revisions. |'inst11'
git show &lt;SHA/commit/tag/tree&gt; | https://git-scm.com/docs/git-show | shows log message and diff for the commit/SHA. For tags it shows tag message and ref objs. |'show'

branching and merging

git branch &lt;flags&gt; | https://git-scm.com/docs/git-branch | To list, create, or delete branchs |'br0'
git branch | | lists all branches in the repo. Current branch has *. To list remote branchs add -a. | 'br1'
git branch --all | | lists all local and tracking branches | 'br2'
git branch -r | | shows the remote branches |'br3'
git branch --contains &lt;SHA&gt; | | finds the branch that contains SHA |'br4'
git branch &lt;br_name&gt; | | creates br_name branch |'br5'
git branch --merged| | shows all branches that are merged in the current branch (used to find and delete branches) |'br5'
git branch --no-merged | | shows branches not merged into the current one |'br6'
git branch -m &lt;oldName&gt; &lt;newName&gt; | | renames branch name (-m stands for move). OldName is optional, if not specified it changes the current branch. |'br7'
git branch -d &lt;branch_to_delete&gt; | | deletes a local branch that has been merged, you cannot be on the branch |'br9'
git branch -D &lt;branch_to_delete&gt; | | deletes a local branch that has NOT been merged, you cannot be on the branch |'br10'
git checkout &lt;flags&gt; | https://git-scm.com/docs/git-checkout | switch branches or restore working tree files |'co0'
git checkout &lt;branch name&gt; | | switches to branch name [same as git switch] |'co1'
git checkout -- file(s) | | discards changes (checks out the file from the repo). Similar to restore |'co2'
git checkout &lt;SHA/HEAD/branch&gt; -- file(s) | | retrieves/checks out file(s) from the SHA/HEAD in repo in the current working dir |'co3'
git checkout -b &lt;new_branch&gt; &lt;existing_branch/SHA/tag&gt; | | checks out a new branch from another branch or commit. it can be used to create a feature branc off of a remote branch |'co3'
git switch &lt;branch name&gt; | https://git-scm.com/docs/git-switch | switches to branch name [if the current branch has uncommitted changes, it cannot switch if changes in the working dir c onflict, but can switch if files are not being tracked] |'sw0'
git switch -c &lt;new branch name&gt; | | create and switches to new branch |'sw1'
git switch - | | switch back to the previous branch |'sw2'
git merge &lt;branch&gt; | https://git-scm.com/docs/git-merge | merge a branch (or a remote branch if name/branch) into the current branch (to update the branch) |'mr0'

There are four types of merges:

  • Fast-Forward: only possible if no additional commits is on the main (or any branch you are merging to) and merge brings the commit from the feature to main with no new commit. This is the default behavior (--ff). To avoid merging if fast-forward is not possible use --ff-only.
    A --- B --- C (main points at C)
                      \
                       D --- E   (feature points at E)
    After running the following: git checkout main - git merge feature
    A --- B --- C --- D --- E (main, feature both point at E)
    Git doesn't need to create a merge commit, it just moves main forward to point at E.
  • Recursive/Real merge: happens when we have some additional commits on the main after the new branch is initiated from the master. There is a possibility of merge conflict, which needs to be solved manually. Even if there is no new commits on the main branch, we can change the default to do a real merge by using --no-ff. It preserves the history. Before merge, it looks like:
    main:    A --- B --- C 
                          \
     feature:         D --- E  
    After merge:
    main:    A --- B --- C ---- F   (F is th new merge commit) 
                          \              /  
     feature:         D ---- E  

    To manage merge conflict, you can:

    • Abort merge: git merge --abort
    • Resolve the conflicts manually
    • Use a merge tool
  • Squash mergre: Squashes all changes from the feature branch into one commit in the main branch to produce a linear history. Individual commits from the feature branch are not preserved.
    main:    A --- B --- C --- F  (F is the squash commit) 
    feature:        D --- E
  • Rebase: It removes the commit history, (for example if it is very busy). If ff is not possible (as explained in the real merge, one can rebase and then do the ff) [see rebase].
  • git mergetool [help] runs the merge conflict resolution tool to help you resolve the merge conflict, instead of manually editing conflict markers (<<<<<<<, =======, >>>>>>>) in your files [conflict may happen with merge, rebase, and cherry-pick]. Each conflicted file opens in the merge tool. The merge tool must be specified in the global git config. [see here].
    git stash | https://git-scm.com/docs/git-stash | stashes/saves the unstaged changes and allows switching to other branches without committing the changes. Stash does not include untracked files, bcs there is no conflict. To include the untracked files, use -u (or --untracked-files).|'st0'
    git stash push &lt;filename&gt; || stashes only one file | 'st_file'
    git stash push -m "message" | | saves modified files and reverts them to the last committed state. The newer stashes save at top of the stack. |'st1'
    git stash list | | lists all the stashes on the branch |'st2'
    git stash show stash@{&lt;stash no.&gt;} | | shows an overview/summary of the changes for stash number # (files and by how much, not the actual diff) |'st3'
    git stash show -p stash@{&lt;stash no.&gt;} | | shows the actual changes in the stash |'st4'
    git stash apply stash@{&lt;stash no.&gt;} | | restores the changes but keeps the stash in the list. If not number specifies, it applies on the most recent stash.|'st5'
    git stash pop stash@{&lt;stash no.&gt;} | | restores the changes and deletes that stash number. If not number specifies, it applies on the most recent stash. No need to be on the original branch, can be applied on any branch. |'st6'
    When we do apply/pop stashes, we may (rarely) face conflicts. In that case we need to resolve the conflict.
    git stash drop stash@{&lt;stash no.&gt;} | | drops/deletes a specific stash number |'st7'
    git stash clear | | deletes all stashes |'st7'
    git tag &lt;flags&gt; | https://git-scm.com/docs/git-tag| creates, deletes, or verifies a tag. It has two types of tags: lightweight (no message) and annotated tag (with message). A tag is a bookmark on a particular commit and unlike branches, tags don't move—they're fixed references.|'tag0'
    git tag &lt;tag_name&gt; &lt;SHA&gt; | | creates a lightweight tag |'tag1'
    git tag -a &lt;tag_name&gt; -m &lt;tag_message&gt; &lt;SHA&gt; | | creates an annotated tag (most common), -a shows it is annotated. If you drop -m and the message, it opens the editor so that we can have a multiline message. If we leave -a but having -m, it assumes it is annotated. If we omit the commit SHA, it assumes the current HEAD as the commit. |'tag2'
    git push &lt;repo_alias, ex origin&gt; &lt;tag_name&gt; | | pushes the tag_name to the remote repo_alias (usually origin) |'tag3'
    git push &lt;repo_alias, ex origin&gt; --tags | | pushes all tags to the remote repo_alias (usually origin) (git push alone does not push the tags) |'tag4'
    git tag -l | | lists all tags. git tag and git tag --list do the same. |'tag5'
    git tag -l &lt;pattern, ex v2.*&gt; | | lists tags beginning with a pattern, here v2.* |'tag6'
    git tag -l -n | | lists tags with annotation |'tag7'
    git fetch --tags | | fetches only tags from the remote repo |'tag8'
    git checkout -b &lt;new_branch&gt; &lt;tag_name&gt;| | starts a new branch from a tag |'tag9'
    git tag --delete &lt;tag_name&gt; | | deletes tags locally (git tag -d &lt;tag_name&gt;) |'tag10'
    git push &lt;repo_alias, ex origin&gt; --delete &lt;tag_name&gt; | | deletes tag_name from the remote repo_alias (usually origin) |'tag11'
    git push &lt;repo_alias, ex origin&gt; :&lt;tag_name&gt; | | deletes tag_name from the remote repo_alias (usually origin) (same as above) |'tag12'
    git describe | https://git-scm.com/docs/git-describe | gives a human-readable name to a commit, based on the nearest tag in your repository. |'desc'
    git worktree | https://git-scm.com/docs/git-worktree | lets you have multiple working trees (directories) attached to a single Git repository, which means you can check out different branches at the same time without having to constantly git checkout back and forth (work on multiple branches in parallel without stashing, committing temporary work, or even copying the repo). |'wt0'
    git worktree add &lt;../feature-worktree&gt; &lt;feature-branch&gt; | | adds a new worktree (checks out a feature branch in another folder, while in the root of the repo) |'wt1'
    git worktree list | | lists all active worktrees |'wt2'
    git worktree remove &lt;../feature-worktree&gt; | | removes a working tree after you are done |'wt3'
    Three types of remote branches:
    1. Branch on the remote repository (on a server, such as github).
    2. Local snapshot of the remote branch (ex: original/develop), which is a snapshot of the remote branch, and it is called remote tracking branch. This is what you get with git fetch, and delete with the prune (see below). When collaborators delete branches, you need to delete it on your local repo.
    3. Local branches exist only on your system.
    git prune | https://git-scm.com/docs/git-prune | deletes all stale remote-tacking branches (not remote branches)[find the remote-tracking branch definition above]. A stale branch is a remote-tracking branch that does not track any remote branch because the actual remote branch has been deleted (by some collaborator). If you delete a remote branch, git automatically deletes your remote-tracking branch, but when collaborators delete a remote branch, your remote-tracking branch remains locally, and you should use this garbage collector to clean your local repo. Fetch does not automatically delete remote-tracking branch. The scope of git prune is local git objects. |'pr0'
    git prune --dry-run | | shows what would be pruned without deleting |'pr1'
    git fetch -p | | fetches and prunes |'pr2'
    git remote prune &lt;repo_alias, ex origin&gt; -dry-run | | shows which branches will be deleted |'pr3'
    git remote prune &lt;repo_alias, ex origin&gt; -dry-run | | deletes all stale remote-tracking branches. The scope is remote branch, such as origin/feature. |'pr4'

    sharing and updating

    git fetch &lt;or a name&gt;| https://git-scm.com/docs/git-fetch | brings the remote changes to the local origin/master (tracking branch) without merging to the local master |'br1'
    git pull | https://git-scm.com/docs/git-pull | fetches and merges from the remote branch. If the remote has changes and you want to push your changes, you need to run this first. |'br2'
    git push &lt;repo_alias, ex origin&gt; &lt;branch&gt; | https://git-scm.com/docs/git-push | updates remote branch by pushing the changes in the local branch to the remote repo_alias (usually origin) branch |'br3'
    git push -f &lt;repo_alias, ex origin&gt; &lt;branch&gt; | | forces push when local version is better than the remote version or versions have diverged and merging is undesirable |'br4'
    git push &lt;repo_alias, ex origin&gt; --delete &lt;branch&gt; | | deletes a remote branch (method 1) in repo_alias. Automatically deletes the remote-tracking branch at the same time. |'br5'
    git push &lt;repo_alias, ex origin&gt; :&lt;branch&gt; | | deletes a remote branch (method 2). By adding ":" to the branch name, it deletes the remote branch without deleting the local branch. |'br6'
    git remote | https://git-scm.com/docs/git-remote | manages set of tracked repositories |'rem0'
    git remote add &lt;name&gt; &lt;url&gt; | | adds a git url as name |'rem1'
    git remote -v | | shows info about the remote repo associated with the local repo |'rem2'
    git remote set-url origin https://github.com/username/new-repo.git | | changes the url of an existing remote repository (remote repo name) to a new one. It can also be used to change HTTPS to SSH. |'rem3'

    patching

    Patches are text files that represent changes (diffs) between commits. Two types of patches:
    1. unformatted patch: contains only the raw diff (file changes, additions, deletions), with no commit metadata (author, date, message, etc.).
    2. formatted patch: contains the raw diff (file changes, additions, deletions) and commit metadata (author, date, message, etc.).
    git diff &lt;SHA#1/ref#1/branch#1..SHA#2/ref#2/branch#2&gt; > &lt;patch/file_name, ex file.patch&gt | | drops changes to a file (unformatted patch) |'patch0'
    git format-patch &lt;SHA#1/ref#1/branch#1..SHA#2/ref#2/branch#2&gt; -o &lt;patch, ex. ~/patches/&gt; | https://git-scm.com/docs/git-format-patch | exports all commits in the range, each in one file. Files are ordered based on commits. It is recommended to use "-o path" to specify the directory to drop the patch files. |'patch1'
    git format-patch -&lt;#commits&gt; &lt;SHA/ref/branch, ex. HEAD&gt; -o &lt;patch, ex. ~/patches/&gt; | https://git-scm.com/docs/git-format-patch | exports #commits before SHA/ref/branch, each commit in a separate file. Files are ordered based on commits. It is recommended to use "-o path" to specify the directory to drop the patch files. |'patch2'
    git format-patch &lt;branch_name, ex. feature&gt; -o &lt;patch, ex. ~/patches/&gt; || exports all commits on the current branch which are not in the branch_name. Used to pass/share all changes that are not on a remote branch. |'patch3'
    git apply --reject --whitespace=fix &lt;patch/file_name, ex file.patch&gt | https://git-scm.com/docs/git-apply | applies the patch. Use only for unformatted patches (if use it with formatted patches, you lose metadata) |'app0'
    git am &lt;path-to-patches/*, ex. ~/patches/*&gt; | | applies all formatted patches |'app1'
    git am &lt;path-to-patches/patch-name, ex. ~/patches/0001_p1.path&gt; | | applies one formatted patch |'app2'
    git cherry-pick &lt;flags&gt; | https://git-scm.com/docs/git-cherry-pick | applies changes from one or more commits to the current branch. Each cherry-picked commit is recorded as a new commit on the current branch, with different SHA (unlike git merge or git rebase which bring in all changes). |'cpick0'
    git cherry-pick &lt;SHA&gt; || brings SHA commit from another branch to the current branch |'cpick1'
    git cherry-pick -e &lt;SHA&gt; || brings the commit range btw the two SHAs from another branch to the current branch and edits the commit message |'cpick2'
    git cherry-pick &lt;SHA#1..SHA#2&gt; || brings the commit range btw the two SHAs from another branch to the current branch |'cpick3'
    git cherry-pick &lt;SHA#1&gt; &lt;SHA#2&gt; &lt;SHA#3&gt; | | brings multiple commits from other branches to the current branch. It is recommended to order SHAs chronologically (olders first) to reduce the chance of conflict. |'cpick4'

    Cherry pick may result in conflicts. Here are the options:

    git add <fixed-files> if you resolved the conflict, run this to stage the changes.
    git cherry-pick --continue after resolving all conflicts, run this to finalize the cherry-pick commit.
    git cherry-pick --abort cancels the cherry-pick, restores branch to pre-cherry-pick state.
    git cherry-pick --skip skips the current commit (useful when cherry-picking multiple commits, and one fails)
    git revert &lt;flags&gt; | https://git-scm.com/docs/git-revert | undoes the changes introduced by a commit (or commits) by creating a new commit that reverses them. It does not delete history (safe for shared branches like main or master). |'rev0'
    git revert &lt;SHA&gt; || reverts an old commit by returning the file(s) to one commit before SHA, and adds a new commit saying Revert "SHA message" |'rev1'
    git revert &lt;SHA#1&gt; &lt;SHA#2&gt; (or &lt;SHA#1..SHA#2&gt;) || reverts an multiple old commits by returning the file(s) to one commit before SHA#1 |'rev11'
    git revert -e &lt;SHA&gt; || similar to the previous commends, but allows to change the commit message |'rev2'
    git revert -n &lt;SHA&gt; || reverts an old commit by returning the file(s) to one commit before SHA, and adds the changed files to the staging area, ready for commit |'rev3'

    Revert may result in conflicts. Here are the options:

    git add <fixed-files> if you resolved the conflict, run this to stage the changes.
    git revert --continue after resolving all conflicts, run this to finalize the revert commit.
    git revert --abort cancels the revert, restores branch to pre-revert state.
    git revert --skip skips the current commit (useful when reverting multiple commits, and one fails)
    git rebase &lt;flags/branch_name&gt; | https://git-scm.com/docs/git-rebase | reapplies commits from one branch onto another, creating a cleaner, linear history. The commits get new hashes because they were rewritten. Useful for syncing your branch with main before merging. As opposed to git merge, which creates a merge commit, git rebase rewrites the history with no extra commit. | 'rebase0'
    git rebase &lt;branch_name, ex main&gt; | | rebases current branch to tip of branch_name/main |'rebase1'
    git rebase &lt;branch_name, ex main&gt; &lt;feature_branch&gt; | | rebases feature_branch to tip of branch_name/main |'rebase2'

    Rebase may result in conflicts. Here are the options:

    git add <fixed-files> if you resolved the conflict, run this to stage the changes.
    git rebase --continue after resolving all conflicts, run this to finalize the rebase commit.
    git rebase --abort cancels the rebase, restores branch to pre-rebase state.
    git rebase --skip skips the current commit (useful when rebasing multiple commits, and one fails)
    git rebase --onto &lt;new_base (commit or branch)&gt; &lt;upstream (old_base/main)&gt; &lt;[new_branch]&gt; | | rebases new_branch ([optional] the branch whose commits are to be rebased, if omitted, the currently checked-out branch is assumed) which is coming off upstream (defines the point from which commits are cut off and prepared for rebase) to new_base (commit or branch where the commits will be replayed). The commits from the original branch would not be moved to the new branch. |'rebase7'

    debugging

    git bisect| https://git-scm.com/docs/git-bisect | helps you find the commit that introduced a bug (or fixed one) by doing a binary search through your commit history. It automatically checks out commits between a known good commit and a known bad commit. You mark each commit as good or bad. Git then narrows down the range until it finds the first bad commit. |'bisect0'

    Debugging workflow using git bisect:

    git bisect start start bisect operation
    git bisect bad Mark a bad commit (usually the current commit)
    git bisect good <SHA> mark a good commit with no bug
    Now starts the binary search. Test each commit to see if it a good or bad commit, and add it. Repeat until finished, which is when git messages the first bad commit.
    git bisect run <test_bug.sh> automate the bisect and test run.
    git bisect reset finishes the bisect process
    git blame &lt;flags/files&gt; | https://git-scm.com/docs/git-blame | shows who changed each line of a file and when | 'blame0'
    git blame -w &lt;file_name&gt; | | lists the history/commits of the file_name (-w ignore whitespace chages) |'blame1'
    git blame -L &lt;line#1,line#2 (or line#1,num_of_lines)&gt; &lt;file_name&gt; | | limits showing the history of file_name to line#1 to line#2 changes (or line#1 plus num_of_lines after line#1) |'blame2'
    git blame &lt;SHA&gt; &lt;file_name&gt; | | shows who last modified each line up to and including SHA (not the latest HEAD) |'blame3'
    git grep "&lt;search_phrase&gt;" | https://git-scm.com/docs/git-grep | similar to the regular Unix grep but searches inside your git repository instead of just the current working directory |'grep0'
    git grep "&lt;search_phrase&gt;" &lt;SHA/branch&gt; | | searches search_phrase in SHA commit or branch |'grep1'

    alias

    git config --global alias.&lt;new name&gt; "git <command>" [help] adds alias "alias=command" to ~/.gitconfig, used to shorten some long, widely used commads. [refer to the alias section of the sample .gitconfig]

    git prompt

    git-prompt refers to the git-aware shell prompt, a feature that adds git repo information directly into your command prompt. The info includes: branch name, repo status (dirty/clean), staged/unstaged changes, ahead/behind info, and rebase/merge/cherry-pick state. This helps you stay informed about your git repo status without needing to run separate git commands. To enable git-prompt, you typically need to source a script that comes with Git installations, usually named git-prompt.sh. This script defines a function __git_ps1 that you can include in your shell prompt (PS1) to display git info. You can download git-prompt from the git repository and copy that in ~/ directory. Here is the list of symbols used by git-prompt to indicate various states:
    * unstaged (dirty) changes
    + staged files
    - deletions
    ↑1 ahead of origin by 1 commit
    ↓2 behind origin by 2 commits
    (merge) in middle of merge
    (rebase) in rebase
    (cherry-pick) in cherry-pick
    (stash:3) 3 items in stash
    Here is a sample configuration to add git-prompt to your bash prompt (add this to your ~/.bashrc or ~/.bash_profile):

    # Show untracked files
    export GIT_PS1_SHOWUNTRACKEDFILES=1
    
    # Show stash count
    export GIT_PS1_SHOWSTASHSTATE=1
    
    # Show staged changes (+), modified (~), deleted (-)
    export GIT_PS1_SHOWDIRTYSTATE=1
    
    # Show ahead/behind counts relative to origin
    export GIT_PS1_SHOWUPSTREAM=auto
    
    # Show if you're in rebase/merge/cherry-pick
    export GIT_PS1_STATESEPARATOR=" "
    
    # Colors
    RED="\[\033[0;31m\]"
    GREEN="\[\033[0;32m\]"
    YELLOW="\[\033[0;33m\]"
    BLUE="\[\033[0;34m\]"
    RESET="\[\033[0m\]"
    
    if [ -f ~/.git-prompt.sh ]; then 
      source ~/.git-prompt.sh  
      export PS1="${GREEN}\u@\h ${BLUE}\w${RED}\$(__git_ps1 '(%s)')${RESET}\$ "  
    fi 
    

    reference

    git-scm.com