Git Overview

Git main site: git-scm.com/

Git GUI: Visual Studio Code and various others

Purpose

  • To save snapshot/ commit
  • Version control
  • Collaborating on same file/project at the same time
  • Splitting production and development code
    • For example: having the main branch be the production code
    • The side branch will be for current development where testing and changes can be done without affecting production build
    • Once changes are done, then the side branch can be merge with the main one (through pull requests) and then delete the side branch

Git Concepts

The 4 Levels of Git

  • Remote repo level: the central location of the repo
    • Git Providers: GitHub, GitLab, GitBucket
  • Local repo level: a copy of the repo on the local computer including any local changes made to it
    • Local repo use push/pull to synch changes with remote repo
  • Stage area level: the area where changes to the files/folders are made before being commited to the local repo
  • Local folder level: the development code on the computer

Branches

Create a copy of same code in main repo to work on without affecting the main branch

  • Use to make changes without affecting the production code (i.e. main branch)
  • Example: create a branch to fix a bug/ add feature, and once it's done, commit and push it to the remote repo branch, and do a pull request to have it merged with the main one

You can only have one copy of the repo locally; if the repo have multiple branches, switching branches will change the local folders to match that branch

  • i.e. Only one branch of a repo can exist in the local folder at a time

HEAD

The HEAD is the pointer to the commit you're currently working on.

  • When switching branch, it will move to the last commit in that branch
  • When switching branch and the branch is new, it's just a copy of the previous branch, but it's pointing to the lastest commit of the new branch

Key Files

  • git/ : folder that has local git settings
  • .gitconfig file
    • .gitconfig : global git setting file, usually in the User folder
    • .git/config : local git setting file, in the local repo location
  • .gitignore file : file in repo root that tells git what to ignore by listing out the files/folders in it, like log files
    • logs/ will ignore everything in logs folder
    • log.txt will ignore the file log.txt
    • logs/*.txt will ignore all .txt files inside the log folder
  • .gitkeep file : git ignores empty folder, so dev use this to make git recognize an empty folder by putting a .gitkeep file in there

Common Git Commands

  • git add .|filename : add all/filename changes to the staging area
  • git commit -m message : commit changes in staging area to local repo and tag the commit with the message
    • Message standard: describe changes, be in present tense, and max of 50 characters
  • git clone URL : clone the repo from the specified URL into the current directory
  • git push/pull : sync changes between local and remote repo
  • git status : view overview of changes
  • git log : give history of repo
    • git log --grep searchTerm : search through log
    • git log --oneline : display concise log format with only commit id and message on one line
  • git restore .|filename : undo changes in staging area
  • git revert commitId : revert the changes to the commit with the id
    • git does not delete history, but will add on to it by stating the changes that reverted the repo

Good Commands for Debugging

  • git stash : save any uncommited changes in the staging area
    • git stash pop : load the uncommited changes you saved back to the staging area
  • git switch branchName : switch to another branch, branchName, and move the current HEAD to point to the branch's last commit
    • git switch -c newBranch : create and switch to new branch, but since it's a new branch, it copies the main branch and all the commits you've done so far
  • git merge sourceBranch : merge current branch with source branch
  • git branch newBranch : create new branch without switching to it
  • git reset --hard HEAD~x|Head~commitHash : revert the current branch by 'x' commits or to the commitHash
    • git log --oneline : display concise log format with only commit id and message on one line
  • git revert commitHash : revert the changes to the commit with the id
  • git cherry-pick commitHash : copies the commit changes from commitHash to the current branch, but does not revert it in the old branch

Tagging

Tagging is used to mark the commits in a repo history, usually to mark releases (v1.0, v1.1, v2.0)

  • git tag tagName commitHash : create a lightweight tag with the name tagName for the commitHash
  • git tag -a tagName -m "message" commitHash : create an annotated tag that allow us to add a message to the tag (more commonly use)
  • git tag -ln : list tag with their annotations
  • git tag -ln "v1.*" : filter tag so only version 1 tags are shown
  • git tag --delete tagName : delete the tag with the name tagName
  • git push origin tagName : push a tag to the remote repo because tags are not pushed by default
  • git push origin --tags : push all tags to the remote repo
  • git fetch : fetch commits and tags

Merge Conflicts

GitHub docs: link

GitLab docs: link


Wrong Branch

  1. If working on the wrong branch and did NOT commit the changes yet:
    • Do the following and continue working on the correct branch
    • git stash
      git switch correct-branch
      git stash apply
    • If the correct branch doesn't exist yet then replace the second line with git switch -c correctBranch
  2. If working on the wrong branch and commited the changes 1 time, but did NOT push the changes:
    • Do the following and continue working on the correct branch
    • git reset --soft HEAD^
      git switch correct-branch
      git commit -c ORIG_HEAD
    • reset --soft Head^ will reverse the commit and put the changes back into the staging area
  3. If working on the wrong branch and commited many changes, but did NOT push the changes:
    • Do the following and continue working on the correct branch
    • git stash                       # skip if all changes are committed
      git branch new-branch       # create the new branch but does not switch to it
      git reset --hard origin/main    # reset current (wrong) branch to match the remote main
      git switch new-branch       # switch to correct branch         
      git stash pop                   # skip if all changes were committed
    • Now the commits are on the new branch, and you can merge it with the correct branch if it exist already
  4. If working on the wrong branch and you already pushed the changes:
    • Switch to the wrong branch, view the git log, git reverse the commits; then switch to the correct branch and git cherry-pick the right commits
    • git switch wrong_branch
      git revert commitHash1
      git switch right_branch
      git cherry-pick commitHash1
    • Now the commits are on the correct branch, and you can continue with your code

Git Commands Table

Editing files / folders

CommandDescription
git statusShow changed files, staged changes, and branch info.
git add <file>Stage a file's changes for the next commit.
git add -pInteractively stage hunks from files.
git restore <file>Discard unstaged changes in a file (restore from last commit).
git restore --staged <file>Unstage a file (remove from index but keep working changes).
git checkout -- <file>Old form to discard changes in a file (use git restore now).
git mv <old> <new>Rename or move a file (stages the change).
git rm <file>Remove a file and stage its deletion.

Branches

CommandDescription
git branch <name>Create a new branch pointing at the current commit (does not switch).
git switch <name>Switch to an existing branch.
git switch -c <name>Create a new branch and switch to it (shortcut for create+switch).
git merge <branch>Merge another branch into the current branch (creates a merge commit unless fast-forward).
git rebase <base>Reapply commits on top of <base> (rewrites history of the current branch).
git branch -d <name>Delete a branch (safe: only deletes if merged).
git branch -D <name>Force-delete a branch even if unmerged (dangerous).
git push origin --delete <name>Delete a remote branch.

Staging area & commits

CommandDescription
git add <file>Stage file changes (put changes into the index for the next commit).
git restore --staged <file>Unstage a file (remove it from the index).
git commit -m "msg"Create a commit from staged changes with message "msg".
git commit --amendAmend the most recent commit (modify message or add new staged changes).
git reset --soft <commit>Move HEAD to <commit> but keep staged and working changes.
git reset --mixed <commit>Move HEAD to <commit> and reset the index (unstage changes) but keep working files.
git reset --hard <commit>Move HEAD to <commit> and reset index + working tree (discard changes).
git stashSave uncommitted changes to the stash stack and clean the working directory.
git stash popApply the latest stash and remove it from the stash list.
git stash applyApply a stash but keep it in the stash list.

Repository management (remote & history)

CommandDescription
git initCreate a local repo in the current directory
git clone <url>Clone a remote repository to your local machine.
git remote add origin <url>Add a new remote repo and give it the alias origin.
git remote add <name> <url>Add a new remote reference. <name> is an alias (origin is commonly used), not the name of the repo
git remote -vList remotes and their URLs.
git fetchDownload commits, refs, and objects from remote without merging.
git pullgit fetch then merge (or rebase) remote changes into current branch.
git pushUpload local branch commits to the remote.
git logShow commit history for the current branch.
git reflogShow local history of HEAD movements (useful to recover lost commits).
git tag <name>Create a lightweight tag pointing at current commit.
git push --tagsPush local tags to the remote.
git gcRun garbage collection to optimize repository storage (housekeeping).