Storage
-
git init Initialises a git repository
-
Objects are stored using SHA1 hashing which generates a 40 digit hexadecimal key
-
Types of Objects
-
blob - Compressed contents of a file
- Metadata: identifier, size, \0 delimiter, file contents
- Only 1 copy of identical files are stored, since they generate the same SHA1 key
---------------------- | blob | size | ---------------------- | \0 | | file contents | ----------------------
-
tree - The hierarchy structure between files in git
- Contains pointers (to blobs, to trees) along with metadata: pointer type (blob, tree), file/directory name, mode, \0 delimiter and size
---------------------- | tree | size | ---------------------- | \0 | ---------------------| | blob | SHA1 | file | | tree | SHA1 | dir | ----------------------
-
commit - Snapshots of the git repository
- Contains pointer to a tree along with metadata: author, committer, date, message, one or more parent commits
- The SHA1 key is generated based off all the metadata
---------------------- | commit | size | ---------------------- | tree | SHA1 | | parent | SHA1 | | author | name | | message | ".." | ----------------------
-
Areas
-
Working area contains untracked files, it's not managed by git
-
Staging area contains files that have undergone changes and are part of the next commit
-
Repository contains commit history and up-to-date files managed by git
-
git add Stage file for commit
-
git add -p Stage files into chunks, useful for large changes
-
git rm Remove file from staging area
-
git mv Rename file
-
git ls-files -s Display changes in staging area
Stashing
- Save uncommited work and protect from destructive operations
- git stash Stash working directory
- git stash list Show stash list
- git stash show stash@{n} Show specific stash contents
- git stash apply Apply latest stash
- git stash apply stash@{n} Apply specific stash
- git stash --include-untracked Include untracked files, recommended to use
- git stash --all Stash all files, even from .gitignore
- git stash save {name} Save stash with name
- git stash branch {branch} Start branch with stash applied
- git checkout {branch} -- {file} Checkout file from stash and overwrites
- git stash pop Remove latest stash and apply changes
- git stash drop Remove latest stash
- git stash drop stash@{n} Remove specific stash
- git stash clear Remove all stashes
References
- Tags and branches point to commits, stored in ./git/refs/heads/ and .git/refs/tags respectively
- HEAD points to the current commit or current branch if checking out
- cat .git/HEAD Shows where HEAD is pointing to
- git branch {new-branch} Create new branch
- git checkout {branch} Checkout to branch
- git checkout -b {new-branch} Create new branch and checkout after
Tags
-
Lightweight tags contain a pointer to a commit
- git tag {name}
-
Annotated tags can also store additional information, such as the author, message and date
- git tag -a {name} -m {message}
-
git tag List all tags
-
git show-ref --tags Show all tags and associated commit
-
git tag --points-at {commit} Show all tags pointing to that commit
-
git show {tag-name} Show contents of the tag
Detached HEAD
- To prevent this, make a new branch for the dangling commit
- git branch {branch-name} {commit}
Merging
-
Merges are types of commits
-
Fast forward
- If git finds a clear path between the commit and branch then git will just move the HEAD pointer
- This doesn't store the history of changes leading up to that commit
- To retain history, force a merge commit: git merge --no-ff
-
Merge conflicts occur when there are competing changes to files
-
git rerere (Reuse, Recorded, Resolution) can save how a conflict was resolved and reuse that resolution for future conflicts
-
git config rerere.enabled true Enables git rerere, can use --global flag to enable for all projects
Logs
- A good commit history preserves the code base and is useful for debugging/reviews
- git log Display commit history of repository
- git log --name-status --follow -- {file} Log files that have been moved/renamed
- git log --grep {regex} Filter commit message fitting regular expression
- git log --diff-filter={type} --stat Filter commits including/excluding the filter type
- A - Added
- D - Deleted
- M - Modified
Commits
- git commit -m {description} Snapshots working area, description should be thoughtful
- git show {commit} Show commit information
- git show {commit} --stat Shows number of changes in file
- git show {commit}:{file} Look at file from another commit
- git diff Show unstaged changes between commits, staging area and repository
- git diff --staged Show staged changes
- git branch --merged master Show which branches are merged with master and can be cleaned up
- git branch --no-merged master Show which branches aren't merged with master
Checkout
- Checkout can be used to restore working tree files, it changes HEAD to point at a new branch and copies the commit snapshot to the staging area
- git checkout -- {file} Copy content from staging to working area, overwriting files
- git checkout {commit} -- {file} Update staging area to match commit, then copies to working area to overwrite files
- git checkout {deleting-commit}^ -- {file} Restore a deleted file based off the commit that it occurred, referencing the parent commit
Reset
-
git reset --soft HEAD~ Moves HEAD to the previous commit
-
git reset --mixed HEAD~ Can omit --mixed flag. Moves HEAD to the previous commit, then copies the files to the staging area
-
git reset --hard HEAD~ Moves HEAD to the previous commit, then copies the files to the staging and working area
- This is a dangerous operation, it can overwrite files
-
git reset {file} Only moves file to staging area
-
git reset {commit} -- {file} Only moves file from a specific commit
-
git reset ORIG_HEAD Restores the original state, add --merge flag to preserve uncommitted changes
- Useful when using git reset accidentally
Revert
- Saves the commit that undos the previous changes, useful for commits that have accidentally been shared
- History doesn't change and riginal commit is still in repository
- git revert {commit} :
Amend
- Can make changes to previous commit, doesn't 'edit' because the SHA1 hash will be different
- Rather, a new commit containing the old changes is created and the old commit dangles
- git commit --amend After adding changes to the staging area, the last commit will amend
Rebase
-
Pulls changes from master and apply commits on top by changing the parent of the commits
-
git rebase master Rebase from feature branch, rewinds HEAD to point at commit
-
git rebase -i {commit}^ Opens an interactive rebase editor
-
To amend arbitrary commits:
- Add files
- git commit --fixup {SHA1} Creates new commit with message starting with 'fixup!'
- git rebase -i --autosquash {SHA1}^ References parent commit
-
git rebase -i -exec {tests} {commit} Run tests and stop rebase if a case fails
-
git rebase --abort Stops rebase before completion
-
git reset {branch} --hard Use if rebase 'succeeds' but something is working
- Good idea to create a backup branch before rebasing
Remote
- Remote is a git repository stored somewhere else, like the web or GitHub
- Fork repository for pull requests
- git clone {url} Clone repository to local machine
- git remote -v View remote repository
- git remote add upstream {url} Pull new changes from remote repository, not set by default
- git push -u origin {branch} Push changes to branch
- git fetch Pulls changes from remote repository, doesn't change local repository
- git pull Performs fetch then merges with local repository
- git pull --rebase Performs fetch and replays commits on top of local branch
- git cherry -v Shows commits which haven't been pushed upstream