git Notes - robbiehume/CS-Notes GitHub Wiki

Links:


General

  • Each developer has a local repository which is a copy/version of the remote repository
    • The remote directory is "the source of truth"; it's the most up to date version
  • Github / GitLab tracks history of commits
  • A branch is a copy of a repository at a certain point in time that has different changes
    • It allows you to work on and test a new feature without directly affecting the master branch
    • Once you're sure the feature branch is working okay, you merge it with the master branch
    • On the feature branch, you can still continuously update it with the most recent updates from master
  • Staging area (AKA index): place to temporarily adding files to be included in the next commit
  • Show commit graph: git log --all --decorate --oneline --graph
    • Or just do git log --oneline for a simpler version
  • Get help with a command: git help <command>
  • Git head and refs overview
  • HEAD is the commit on which you based the changes in the working tree? (link)
  • Can use git show to see commit info
    • See the commit info and file diffs: git show <commit ID>
      • Can also use HEAD~; ex: git show HEAD~2 (to see 2 commits back)
    • See full version of file in commit: git show <commit ID>:<file path (relative)>

Setup

Set git name and email:

Clone a remote repo: git clone <url> <where to clone>

  • If cloning to current directory, just do git clone <url>

Initialize local repository (not cloning a remote repo): git init

  • Then git remote add origin <repo_url>
  • Then git push -u origin main

Setting up SSH keys:

  • ssh-keygen
    • Hit enter for the default location, and type a password or hit enter for no password
  • Add key (cat .ssh/id_rsa.pub) to GitLab/GitHub account

Staging / Committing

Seeing file differences (git diff)

  • "What are the differences between these git diff commands?"

  • See files that changed: git diff --name-only

  • git diff shows the differences between the current state of your project (working directory/tree) and the index; it shows what changes are not yet staged

  • git diff --cached will compare the index with HEAD. This will show the difference between what has been added to the index (staged) and your last commit: the changes that are staged for the next commit

    • Ex: if you changed two files since last commit, and staged one of them, git diff HEAD would show the differences in both files; git diff --cached would only show the differences in the staged file
  • git diff HEAD will show all changes in the working directory since your last commit; what you would be committing if you run git commit -a

    • It's the combination of changes in git diff and git diff --cached
  • See changes of already staged file(s): git diff --cached // can pass filename to just diff it

  • See differences between files on different branches: git diff branch1 branch2 -- file_name

    • If comparing a remote branch, run git fetch first to make sure it's updated
    • See differences between remote master and local branch: git diff origin/master -- <file_path> // fetch master first before running.
      • link; master could be replaced in the example with any branch name
  • See changes between staged file(s) and another branch:

    • Compare specific file: git diff --cached <other_branch> -- <file_path>
    • Compare all staged files: git diff --cached <other_branch>
    • If --cached not added, then it'll compare against the file(s) in the working directory
  • See changes between branches: git diff branch1..branch2

    • Ex: git diff dev_branch..origin/main; see differences between local dev branch and remote main branch
    • Can also do it for commits: git diff commitID1..commitID2
  • See commit changes between branches: git log branch1..branch2

  • Ignore white space: git diff -w...

image

Branching:

  • Branching strategy
  • git switch can now be used to checkout a branch (link)
  • Create new branch: git checkout -b <new_branch_name> (new switch command: git switch -c <new_branch_name>)
    • Push new branch to remote: git push -u origin <branch_name>
  • Checkout branch: git checkout <branch_name>
  • See all branches: git branch -a
  • Delete branch:
    • Delete branch locally: git branch -d <branch_name>
      • -d deletes the local branch only if you have already pushed and merged it with your remote branches
      • Can use -D (-d --force) to delete the branch regardless of its push and merge status
    • Delete branch from remote repo: git push -d origin <branch_name>
    • Delete local reference to deleted remote branch: git remote update origin --prune
  • Branching strategies

HEAD is a pointer to the most recent commit on the current branch, it tells you what is checked out

Pushing / Pulling / Fetching

Pull requests:

  • This is a feature provided by a git hosting service (GitHub, GitLab, etc.) so may slightly vary between them
  • Pull requests are a way to communicate about code and review it
  • It allows other team members to review the code and provide feedback before merging
  • Pull requests are based upon branches, not individual commits

Fetching

  • Update remote branches: git fetch

Pulling

Upstream (-u)

Merging

  • Selectively merge certain files: link ALWAYS pull down any changes from remote to your local master before merging in changes from your local dev branch

Merge a branch:

  • git merge <branch_name> : merges branch_name into the current branch
  • When git performs a merge, it looks for 3 commits
    1. common ancestor commit: the latest commit in common
    2. last commit on parent branch
    3. last commit on child branch
  • git merge connects all these commits together

Types of merges:

  • Fast-forward merge: there is a direct commit path between the two branches
    • This is when the parent branch hasn't changed since the child branched off
  • 3-way merge: need a merge commit to combine the two branches

Merge conflict:

  • Merge conflicts can occur when merging changes from a different source cause contradictions
    • Can also occur from a pull, rebase, or stash
  • Usually caused when trying to merge branches that have changed the same line(s) in the same file(s)
  • Manually solve the merge conflict, then commit the change
  • Fix the file (resolve the merge conflict), add those changes, then commit the changes, and then you should be able to push/pull again
  • Instead of resolving a merge conflict, you can also undo it by going back to the state before the conflict happened
    • This is done with the --abort flag

Check if branch is merged: git branch --merged

Rebase:

Merge situations

Merge local branch with master without losing local changes: Link

  • On local branch
  • git stash
  • git checkout master
  • git pull origin master
  • git checkout <local branch>
  • git merge master
  • git stash pop

Merging new changes from local dev branch and new changes others made to master:

  • Push new local dev branch commits to remote dev
  • Checkout local master, then pull from remote master
  • Checkout local dev and merge in local master, then push to remote dev
  • Checkout local master and merge in dev, then push to remote master
  • Checkout local dev again and the repeat process when new changes are made to master

If local changes conflict with the upstream changes and git pull refuses to overwrite your changes

  In that case, you can stash your changes away, perform a pull, and then unstash

  • git stash
  • git pull
  • git stash pop

Misc. commands

  • See list of git branches ordered by commit time: git for-each-ref --sort=-committerdate
    • Add refs/heads/ to end of command if only want to see remote branches

Extra notes from SC trip

  • Organize related files into different commits
    • If you have multiple modified files that aren't all related, then it's best to group them into separate commits
  • Can do git add -p <file> to stage only certain changes within a file

Branching strategy

  • It's good to have a written best practice for a branching strategy

Two strategies

  • GitHub Flow

    • Have a main branch and use short-lived branches for features / bug fixes
  • GitFlow

    • Have a main, develop, release, and feature branch
    • Feature and release branches get deleted when done

Can undo a merge if there is a conflict: git merge --abort

Rebase

  • Rebase doesn't have a merge commit; it rewrites commit history
  • Steps (rebase dev)
    • First git will remove all the commits on dev branch that happened after the common ancestor commit
    • Then it will apply the new commits from the main branch
    • Then it will apply the commits that were removed in the first step, on top of the new commits from main
  • Never rebase commits that you've already pushed/shared on a remote repository
    • Instead, use rebase for cleaning up your local commit history before merging it into a shared team branch

image image

⚠️ **GitHub.com Fallback** ⚠️