You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
produces a 40-digit hexadecimal number when given data
the value should always be the same if given input is the same
also called content-addressable storage system because the content can be used to generate the key
three types of objects:
blobs
trees
commits
Example .git directory
$> tree .git
.git
├── COMMIT_EDITMSG
├── HEAD # usually points to the current branch / commit
├── config
├── description
│── FETCH_HEAD
├── index
│── ORIG_HEAD
│── packed-refs
│── hooks
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 43
│ │ └── 388fee19744e8893467331d7853a6475a227b8
│ ├── 58
│ │ └── 1caa0fe56cf01dc028cc0b089d364993e046b6
│ ├── 98
│ │ └── 0a0d5f19a64b4b30a87d4206aade58726b60e3
│ ├── info
│ └── pack
└── refs
├── heads
│ └── branch_a
│ └── branch_b
│ └── master
│── remotes
└── tags
Blobs & trees
Blobs
blobs are unique
blobs are stored in the object directory of .git as a subdirectory starting with the first two chars of the hash
Git stores the compressed data in a blob, along with metadata in the header
identifer blob
size of content
/0 delimiter
content
Git hash object
asking for the SHA1 of contents ... git hash-object --stdin
generating the SHA1 of the contents, with metadata ... openssl sha1
when running a cache method the same result is always achieved
Trees
info on filenames and directory structures are stored in a tree
trees contain pointers (using SHA1) to blobs and other trees (directed graph)
trees also contains metadata
type of pointer (blob or tree
filename or directory name
mode (executable file, symbolic link, etc.)
identical content is only stored once -> saving tons of space on hd
Commits
commits point to a tree and contain metadata on
author and committer
data
message
parent commit (>= 1)
the SHA1 of the commit is the hash of all that info
commits are code snapshots
commits can not be changed --> history manipulation
when edited a new SHA1 hash is assigned (even if files do not change, the created date will)
References
references are pointers to commits
tags
branches
HEAH - a pointer to the current commit, the last commit made (special type of pointer)
changing branches is fast, since only pointers are changed
NOTE: Simple repo has 1 tree, 1 blob, and 1 commit. Object content (blob, tree, commit) is compressed and can not be read with a simple cat command, instead git cat-file.
Git areas & staging
Working area
untracked files
files ready for staging
Staging area
also called index or cache
files to be part of the next commit
diff between current and last commit
a "clean" staging area is not empty
baseline staging area contains a copy of the files of the latest commit and the assigned SHA1
index is a binary file in the Git repo
unstaged files are not removed, but replaced by a copy
Repo
contains all commits
Staging
save uncommitted work
safe from destructive operations, e.g. switching between branches
References, commits & branches
pointers to commits
three types of references
tags & annotated tags
branches
HEAH
Branches
is a pointer to a particular commit
the current branch pointer moves with every commit to the repo
HEAD
indicates current branch (Git knows what the next parent will be)
points at the name of the current branch
can point at a commit (= detached HEAD)
moves when
a new commit is made in the currently active branch or
a new branch is checked out
HEAD-less or detached HEAD
specific commit checkout moves HEAD to this commit
the HEAD will point to a new SHA1
no references pointing to the commits made (detached state)
solution to detached HEAD
create new branch pointing to the last commit git branch [new_branch] [commit] (the last commit because the other ones point to their parents)
discard changes (dangling commits), which will be garbage collected -> no longer referenced in Git
Tags
lightweight tags are simple pointers to a commit
tags with no argument -> value is captured in the HEAD
annotated tags git tag -a
point to a commit
have additional info such as author, message, date
not commonly used
the commit a tag points to does not change (snapshot)
Merging & rebasing
merge commits are markers
merge commits can have several parents
fast-forward commit: new commits are added on top of the master branch and the master pointer is moved automatically (linearized commit)
the history of a merge commit can be retained by git merge [branch] --no-ff --> merge commit will be forced
merge conflicts
attempt to merge, but files have diverged
Git stops until conflicts are resolved
Git RERERE — reuse recorded resolution
Git saves how conflicts were resolved and applies it again
useful for refactoring, rebasing
git config rerere.enabled true, use flag --global for all projects
History & diffs
good commits help to preserve the history of a code base, etc.
good commit messages
encapsulates one logical idea
have a title and body with a precise description of the current behavior, the purpose of the fix, and side effects
are in future tense
broken into 72 char lines
Fixing mistakes
Git checkout
restore working tree files (moving the HEAD pointer)
switch branches (moving the HEAD pointer to the new branch)
files (no pointer moving)
Git clean
cleans working area by deleting all untracked files permanently
Git reset
performs different actions depending on the arguments
with a path
without a path
default: git reset --mixed
commits
moves the HEAD pointer and the branch reference
optionally modifies files
file paths
moves the HEAD pointer and modifies files
three types:
soft: HEAD
mixed: HEAD + staging area
hard: HEAD + staging area + working area
can change history
Git keeps the previous value of HEAD in a variable called ORIG_HEAD
so in case of an accidental reset, the original state (HEAD) can be restored
NOTE: Never push changed history to a shared or public repo.
Git revert
the "safe" reset
revert does not change history
creates a new commit that introduces the opposite changes from the specified commit
the original commit stays in the repo
used to undo a commit that has already been shared
Rebase & amend
Git amend
amend is useful to make changes to the previous commit
every amend leads to a new commit with a different date
when amending, the original commit and amended commit (copy of the original commit) have different SHAs, since commits can not be edited
the original commit has no references pointing to it and will be garbage collected
Git rebase
a commit gets a new base commit (parent)
useful when feature branch and master have diverged
all latest changes are pulled in from the master and copies of own commits are applied on top of them by changing the parent commit of the own commits (git rebase master)
the feature branch is then up-to-date
advantages
commits can be edited
commits can be removed
commits can be combined
commits can be reordered
commits can be inserted and are then replayed on top of the new HEAD
fix previous mistakes in code
Git history is kept neat and clean
interactive rebase with -i or --interactive flag
opens an editor with a list of to-dos
commits are picked in the specified order
format: [command] [commit] [commit_message]
interactive rebase with a shortcut git rebase -i [commit_to_fix]^ (the ^ specifies the parent commit)
useful to split commits into multiple ones
rebase with command execution
git rebase -i --exec "run-tests" [commit]
used as a flag when rebasing
execute specified command when doing interactive rebase
stops in case of failure
Abort
before rebase is done, if things are going wrong
before rebasing, make a copy of the current branch by creating a new branch git branch [branch_backup]
if rebase succeeds but messed up git reset [branch_backup] --hard
BEST PRACTICE: Commit often, perfect later, publish once. Before pushing work to a shared repo, rebase to clean up the commit history.
Remote repos & forks
Remotes
remote is a Git repo stored on the web, in GitHub
origin is the default name of a remote Git gives to the server the repo was cloned from
cloning means fetching the whole repo and making it a local copy
remotes options are read & write or read only
Forks
a fork is a copy of a repo stored in a GitHub account
forks can be cloned to a local computer
read & write options
merging changes to original via pull requests
stay up-to-date with an upstream
upstream repo is the base repo the fork was created from
set up an upstream to pull down changes after forking the base repo git remote add upstream [url]
Distributed version control system for versioning files and folders
Fast, free, and open source
Efficient collaboration tool for any kind of project
Simultaneous working on projects by using multiple local branches
Simple and easy backup of the main server
Integrated review process
The basic ideas of Git:
The object database is the rather elegant system used to store the history of project-files, directories, and commits.
The index file is a cache of the state of a directory tree, used to create commits, check out working directories, and hold the various trees involved in a merge.
Git introduction
Git is a fast, scalable, free, and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.
Git offers an unusually rich command set that provides both high-level operations and full access to internals.
It outclasses SCM tools like Subversion, CVS, Perforce, and ClearCase with features like cheap local branching, convenient staging areas, and multiple workflows.
Git allows to have multiple local branches that can be entirely independent of each other. Notably, not all branches have to be pushed when pushing to a remote repository.
Git is distributed, which means that the entire repository is cloned ensuring a full backup of the main server.
Unlike the other systems, Git has something called the staging area or index. This is an intermediate area where commits can be formatted and reviewed before completing the commit. Git also makes it easy to ignore this feature. If a -a flag is added to the commit command, all changes to all files are added to the staging area.
Git commands are divided into high level ("porcelain") commands and low level ("plumbing") commands.
Getting started with repositories
Create a repository
git init
git add README.md # can be skipped
git commit -m "Initial commit"# can be skipped
git remote add origin [url]
git push -u origin master # push on remote master branch
cd old-repository.git
git push --mirror https://github.com/exampleuser/new-repository.git
Remove the temporary local repository you created earlier.
cd ..
rm -rf old-repository.git
Git high level commands
Setup & configuration
git [command] -h — display options for the specified command
git config — query / set / replace / unset global and repository options
git config --global color.ui auto — enables helpful colorization of command line output
git config --global user.name "[user_name]" — globally sets the name attached to commit transactions
git config --global user.email "[[email protected]]" — sets the email attached to commit transactions
git config --list — show all config settings
git config user.name — show the username
git config user.email — shows the email
git config rerere.enabled true (--global) — turn on Git Reuse Recorded Resolution (globally for all projects)
git help — display help information about Git
git rerere diff — show merge conflicts
Getting & creating projects
git clone — clone a repository into a new directory, including all of the files, branches, and commits
git clone [directory] [new_directory] — clone the directory named [directory] inside the current working directory into a new directory named [new_directory] inside the current working directory
git clone [url] [new_directory] — clone directory with the link [url] into a new directory named [new_directory]
git init — create an empty Git local repository or reinitialize an existing one
git mv [file] [new_folder]" — move file named [file] to a new folder [new_folder]
git remote — manage the set of repositories ("remotes") whose branches are tracked
git remote add origin [url] — add a remote connection between the local repository and the remote with the link [url]
git remote add upstream [url] — add a remote connection to the forked remote upstream (repo) with the link [url]
git remote set-url — add a remote repository (i.e. connect local repo to Github)
git worktree list — lists all existing working trees (a repository can have multiple working trees)
Basic snapshotting
git add . — add all changes in the current directory to all files in the staging area
git add -u — update all tracked files in the entire working tree (e.g. added and deleted ones)
git add -a / git add --all — add all changes to all files in the staging area
git add [file1] [file2] — add contents of [file1] and [file2] to the index / staging area
git add --update / git add -u — update the index just where it already has an entry matching [pathspec]; if no [pathspec] is given, all tracked files in the entire working tree are updated
git add --verbose / git add -v — be verbose when adding all changes to the staging area
git commit — record and add changes to the repository
git commit -a — automatically stage and record all files that have been modified and deleted, but new files unknown to Git are not affected
git commit -m "[message]" — instantly add a commit message to the commit
git commit -a -m "[message] — stage changes and add a commit message
git commit -v — show unified diff between the HEAD commit and what would be committed at the bottom of the commit message template to help the user describe the commit
git notes — add, remove, or read notes attached to objects, without touching the objects themselves
git status — show the working tree status
Note: Do not fix generated files such as package-lock.json. Re-generate these files.
Clean-up
git clean — clear working area by deleting untracked files
git clean --dry-run — check cleanup affected files before deletion
git clean -f / git clean --force — remove untracked files from the working tree
git clean -d — clean both files and directories
Stashing
git checkout [stash_name] -- [file] — grab a single file from a stash
git stash --all / git stash -a — keep all files, even ignored ones
git stash apply — apply the last stash
git stash apply stash@{0} — apply the recently created stash
git stash apply stash@{n} — apply the specified n-th stash
git stash branch [optional_stash_name] / git stash branch [branch_name] stash@{n} — start a new branch from a stash
git stash clear — remove all stashes
git stash drop — remove the last stash
git stash drop stash@{n} — remove the n-th stash
git stash list — list all stashed changes
git stash pop — remove the last stash and applying changes (impossible if there's a merge conflict)
git stash pop stash@{n} — remove the specified stash n
git stash push — save local modifications to a new stash entry
git stash save "WIP: [foo bar buzz]" — name stashes for easy reference
git stash show stash@{n} — show the contents (detailed information) of a specific stash (reference)
git stash show -p stash@{n} — show the diff between the specified stash and the respective commit
Tagging
git show [tag] — look at the tag or tagged contents
git show-ref --tags — list all tags and what commit they are pointing to
git tag [tag] — add the specified tag
git tag — list all tags in a repo
git tag -a [tag] -m "[message]" — add annotated tag with a message
git tag --points-at [commit] — list all the tags pointing ot a commit
Patching
git add --patch / git add -p — stage commits in hunks (partial staging) -> type ? and press enter after Stage this hunk to show shortcut keys explanations
git am — split mail messages in a mailbox into commit log message, authorship information and patches, and applies them to the current branch
git am --abort — restore the original branch and abort the patching operation
git am --continue — make a commit using the authorship and commit log extracted from the e-mail message and the current index file, and continue after a patch failure
git am --skip — skip the current patch when restarting an aborted patch
git am --show-current-patch — show the message at which git am has stopped due to conflicts
git apply — apply a patch to files and/or to the index
git stash --patch / git stash -p — add to stash in hunks (git will intelligently break up the changes into hunks)
Undoing & resetting
git checkout -- [file] — replace working area copy with the version from staging area (files are overwritten without warning!) -> discard changes made to the file in the working area
git checkout [commit] -- [file] — update the staging area to match the commit and update the working area to match the staging area (files are overwritten without warning!)
git checkout [deleting_commit]^ -- [file] — restore a deleted file
git commit --amend — manipulate previous commit to add files or change commit message, the message from the original commit is used as the starting point, instead of an empty message, when no other message is specified from the command line via options such as -m
git commit --fixup [commit] — create new commit to amend the specified commit (message starts with "fixup")
git mv [file] — rename a file in the next commit
git rebase -i [commit_to_fix]^ — interactive rebase
git rebase -i --autosquash [commit]^ — squash fixup commit with the parent of the specified commit
git rebase -i --exec "run-tests" [commit] — execute specified command after commit when interactive rebasing
git rebase --abort — undo rebase and reset HEAD to the original branch
git rebase --continue — continue rebase
git rebase master — rewind HEAD back to master and add new commits (copy) on top aka give a commit a new base commit (parent)
git reset — reset current HEAD to the specified state (unstage files)
git reset ORIG_HEAD — undo a git reset
git reset -- [file] — copy file from commit to staging area without moving the HEAD pointer
git reset [branch] --hard — reset back to specified branch
git reset HEAD [file] — unstage file added to the working directory
git reset [commit] -- [file] — copy file from the specified commit to the staging area without moving the HEAD pointer (reset the staging area), does not work with flags (hard, soft, mixed)
git reset [commit] — undo all commits after the specified commit, preserving changes locally
git reset --hard [commit] — discard all history and changes back to the specified commit
git reset --soft HEAD(~) — move HEAD pointer to previous commit
git reset --mixed HEAD — (default) move the HEAD pointer to previous commit and copy the file from the commit, that it is pointing to, to the staging area
git reset --hard HEAD — move HEAD pointer to previous commit, copy the file from the commit to the staging area and to the working area
git reset --hard — reset the index and working tree (changes to tracked files in the working tree since commit are discarded)
git reset --merge ORIG_HEAD — undo a merge while preserving any uncommitted changes with the --merge flag
git restore — restore specified paths in the working tree with some contents from a restore source
git revert [commit] — reverts the specified commit, reverting the changes that the related patch introduced, and records a new commit indicating the reversion (the original commit stays in the repo)
git rm [file] — remove file named [file] from the working tree and index
NOTE:-- signifies the end of a command operation and the start of positional parameters.
Sharing & updating projects
git cherry -v — show commits, which have not been pushed upstream yet
git cherry-pick — apply changes introduced by one or more existing commits recording a new commit for each
git fetch — download objects and refs from a remote repository to keep local repo up-to-date with remote (no changes to local repo)
git pull — fetch from a remote repository and integrate (merge) with the current local branch of the working directory / shorthand for git fetch && git merge
git pull [remote_name] [branch_name] — fetch from a remote repository and integrate with another repository or a local branch / shorthand for git fetch && git merge FETCH_HEAD, e.g. git pull origin feature_1
git pull --rebase — fetch, update local branch to copy upstream branch, and replay any commits made via rebase (no extra merge commit)
git push — update remote refs along with associated objects
git push -u origin master — upstream, initial update, e.g. push changes of the remote "origin" to the branch named "master" / shorthand for git push --set-upstream origin master
git push [remote_name] [branch_name] — push changes to the specified remote, e.g. git push origin feature
git push --tags — push all local tags to remote repo
git push [tag] — push specified local tag to remote repo
git submodule — initialize, update, or inspect submodules
NOTE: Tags are not automatically pushed to the remote repo.
Branching & merging
git branch — show existing branches
git branch -r— show all remote branches
git branch -a — show branches in both local and remote repo
git branch -v — show the last commit on each branch
git branch -vv — show which remote / upstream branch is being tracked on local branch and check status
git branch -d [branch_name] — delete the branch [branch_name]
git branch -D [branch_name] — delete the specified branch irrespective of its merged status (-D is a shortcut for --delete --force)
git branch -m [new_branch_name] — rename current branch
git branch --merged master — shows all branches that have been merged with the master and can be cleaned up
git branch --no-merged master — show all branches that have not been merged yet with the master
git checkout -b [branch_name] — create and switch to the new branch named [branch_name] in one line
git checkout -t origin/[branch] — checkout a remote branch, with tracking
git checkout [branch_name] — move onto the specified branch
git checkout -b [local_branch] origin/[remote_branch] — Branch [local_branch] set up to track remote branch [remote_branch] from origin e.g. git checkout -b serverfix origin/serverfix
git merge — combines the specified branch’s history into the current branch
git merge [branch] --no-ff — merge while retaining the history (no fast-forward)
git show-branch — show local branches and associated commits
git show-branch -r — show remote branches and associated commits
git show-branch -a — show all branches and associated commits
git switch branch [branch_name] — switch to the specified branch
gitk — show graphical representation of the resulting history
git show — shows one or more objects (blobs, trees, tags, and commits), e.g. commits are displayed with log message, textual diff, and merge commit
git show [commit] — outputs metadata and content changes of the specified commit
git show [commit] --stat — show files changed in commit
git show [commit]:[file] — look at a file from another commit
Comparison
git diff — show unstaged changes between commits, between a commit and working tree, between the working tree and the index or a tree, between two trees, changes resulting from a merge, etc.
git diff --staged— show staged changes, which will be part of the next commit (--staged is a synonym for --cached)
git diff [first_branch]...[second_branch] — shows content differences between two branches
git range-diff — show the differences between two versions of a patch series, or more generally, two commit ranges (e.g. two versions of a branch)
Logging
git log — show commit logs and displays history of changes of the current branch; exit with q or add --no-pager to open the log in the CLI
git log --follow [file] — lists version history for a file, including renames
git log --oneline --graph --decorate --all — show all commit logs with commit number and message in one line
git log --graph — show commit logs with commit number, message, and author as a graph
git log --since="yesterday" — show commit logs since yesterday
git log --since=2.weeks — show commit logs from the last two weeks
git log --grep=author --author=name --since=2.weeks — search for commit messages, which match a regex
git log --name-status --follow (--) [file] — track files that have been renamed / changed
git log --diff-filter=R -- [find-renamed] — find only files that have been renamed
git log --diff-filter=M — filter and show only files that have been modified
git log --diff-filter=A — filter and show only files that have been added
git log --diff-filter=D — filter and show only files that have been deleted
git log --diff-filter=D -- [file] — filter commit of specified file that has been deleted
git log -p — display complete diffs at each step
git log [commit] — show history details of the specified commit
git shortlog — summarize git log output in a format suitable for inclusion in release announcements with each commit will grouped by author and title.
Git low level commands
git cat-file -t [SHA1 hash] — print the type of the object inside the .git/objects directory
git cat-file -p [SHA1 hash] — print the content of the object inside the .git/objects directory
cat HEAD — check out the HEAD pointer (e.g. master reference: ref: refs/heads/master) inside the .git directory
cat heads/master — check out the master reference and the commit pointed to (the last commit) inside the .git/refs directory
git ls-files -s — print out the content (files) with the mode, the SHA matching that in the repo, and the file name
git branch [new_branch] [commit] — detached HEAD: create new branch pointing to the last commit and save changes
git show-ref --heads — list all heads and what commit they are pointing to
How to commit and push changes including log messages to the GitHub repository using the command line
cd [repository] — access the Git repository / working directory
git add [file1] [file2] — add files modified to temporary staging area called index or staging area to be formatted or reviewed OR git add -a — add all changes to all files in the staging area
git commit — record files to repository OR git commit -m" [commit_message]" to avoid launching the editor Vim
If Vim pops up, enter commit message (with title and description)
git push — update remote refs along with associated objects
Switching branches
How to create new branches and switch between existing ones in order to add content
git branch — show existing branches
git branch [new_branch_name] — create a new branch named [new_branch_name]
git branch — show existing branches including the new branch
git switch branch [new_branch_name] — switch to the new branch
git commit -a — add file to the staging area of the new branch
git switch branch master — switch to the master branch
git merge [new_branch_name] — merge the changes in the new branch into the master
gitk — show graphical representation of the resulting history
git branch -d [new_branch_name] — delete the specified branch
Collaborating with others
How to clone a repository in order to collaborate with others and make, fetch, and pull changes
First person: git clone [original_repository] [clone_repository] — clone the original repository into a new directory possessing its own copy of the original project’s history
First person: git commit -a — add file to the staging area of the [clone_repository]
Second person: git pull [clone_repository] master — fetch changes from the remote branch (1. person) and merge them into the current branch (2. person);
better:
git fetch [clone_repository] mastergit log -p HEAD..FETCH_HEAD — fetch changes and show everything reachable from the FETCH_HEAD of the [clone_repository] and exclude everything reachable from the HEAD of the [original_repository]
Second person: gitk HEAD..FETCH_HEAD — visualize change history, everything that is reachable from either one, but exclude anything that is reachable from both of them