# Git Book [Git Book](https://git-scm.com/book/en/v2) ## Chapter 1: Getting Started * Git tracks snapshots, not differences (virtual filesystem) * Nearly every operation is local * Has integrity included * Generally only adds data ### Three states | Working Directory | Staging area | .git repository | |------------------:|:------------:|:----------------| | <= | = checkout= | =< | | stage >= | => | | | | commit >= | => | ### First time setup * Global: /etc/gitconfig * Per-user: .gitconfig * Per-project: .git/config ``` $ git config --global user.name "John Doe" $ git config --global user.email johndoe@example.com $ git config --global core.editor vim $ git config --list ``` ### Get help * git help 'verb' * git 'verb' --help * man git-'verb' ## Chapter 2: Git Basics ### Getting a Repository * New repositor: `$ git init` * Clone existing: `$ git clone https://github.com/libgit2/libgit2 [mygitlib]` ### Reordering Changes | Untracked | Unmodified | Modified | Staged | |----------:|:----------:|:--------:|:-------| | add the file >= | == | == | => | | | edit the file >= | => | | | | | stage the file >= | => | | <= | =< remove the file | | | | | <= | == | =< commit the file | * Checking the status: `$ git status` * Adding file(s) `$ git add .` `$ git add README.md` `$ git add *.c` * Staging modified files `$ git add modified.file` * The same file can be staged and unstaged, if it was edited after staging! * Short status `git status -s` - Left letter: status of the staging area - Right letter: status of the working tree - ??: untracked - A : added to the staging area - MM: modified, staged, modified again - M: modified, not yet staged - M : modified and staged * ignore files over .gitignore Examples: - `*.a`: no a-files... - `!lib.a`: ...except for lib.a - `/TODO`: ignore TODO in the current directory, but not in other directories - `build/`: ignore all files in the build directory - `doc/*.txt`: ignore txt files in the doc directory - `doc/**/*.pdf`: ignore txt files in doc and all its subdirs ### View staged and unstaged changes * See unstaged changes: `$ git diff` * See staged changed: `$ git diff --staged` or `$ git diff --cached` ### Committing your changes * Commit staged files: `$ git commit` or `$ got commit -m "my message"` * Skip the staging area: `$ git commit -a -m "my message"` - it's equivalent to `git add .` followed by `$ git commit -m "my message"` ### Removing files * `$ git rm` removes files from the _staging_ area and removes it from the drive. * if you first remove a file with `$ rm` the change will be recorded. You must still type `$ git rm` to remove it from the stage area before committing. * if you modified a file and already added it to the staging area, you must use -f to force the removal. This is a security feature, because the data couldn't be recovered by git. * You can remove files from the staging area but keep it on the drive (e.g. if you forgot to put them in .gitignore). `$ git rm --cached` ### Moving files * Git is smart about file moves. therefore the two options are equivalent: - `$ git mv a b` - `$ mv a b` followed by `$ git rm a && git add b` ### Viewing the history * Generally with `$ git log` * show diffs of changes and limit to last N entries: `$ git log -p -N` * show abbreviated stats: `$ git log --stat` * use --pretty=keyword option. Keywords are - oneline - short - full - fuller - format ``` $ git log --pretty=format:"%h - %an, %ar : %s" %H, %h: Commit hash, abbrev. commit hash %T, %t: Tree hash, abbrev. tree hash %P, %p: Parent hash, abbrev. parent hash %an, %ae: Author name, author email %ad, %ar: Author date, author date, relative %cn, %ce: Committer name, committer email %cd, %cr: Committer date, committer date, relative %s: Subject ``` * Show graph: `git log --pretty=format:"%h %s" --graph` * other options: - `-(n)` show only the last n commits - `--since`, `--after` Limit to commits after a date - `--until`, `--before` Limit to commits before a date - `--author` Filter by author - `--committer` Filter by committer - `--grep` Filter by content of the commit string - `-S` Only show commits adding or removing code matching the string ### Undoing things * You forgot to stage some files. Use `$ git commit --amend` to commit remaining files. Works only, if no changes were made since last commit. * Unstage a staged file: `$ git reset HEAD ` * Unmodify a modify file: `'git checkout -- `. Consider branching or stashing instead. ### Working with remotes * Showing repositories: `$ git remote -v` * Adding remotes: `$ git remote add ` * Fetching from remotes (receive data you don't have yet): `$ git fetch ` * Pulling from remotes (fetching and merging): `$ git pull ` * Fetching and pulling by default works on tracked remote branches. * Pushing to remotes: `$ git push origin master` * Show information about a remote: `$ git remote show origin` - Fetch URL - Push URL - HEAD branch - Remote branches - Local branch configured for 'git pull' - Local ref configured for 'git push' * Renaming remotes: `$ git remote rename pb paul` * Removing remotes: `$ git remote remove paul` ### Working with tags * listing tags: `$ git tag` * listing tags of a series: `$ git tag -l "v1.8.5*"` * There are two types of tags: - lightweight - annotated * A lightweight tag is like a branch that doesn't change. * An annotated tag is checksummed, contains tagger name, email and date. They have a tagging message and can be signed with GPG. * `-m` specifies the tag message. * creating an annotated tag: `$ git tag -a v1.4 -m "my version 1.4"` * creating a lightweight tag: `$ git tag v1.4-lw` * show information about a tag: `$ git show v1.4` * You can tag after other commits have been made: ``` $ git log --pretty=oneline 15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment' a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support 0d52aaab4479697da7686c15f77a3d64d9165190 one more thing $ git tag -a v1.2 a6b4c9 ``` * sharing tags with remotes: `$ git push origin v1.5` * to push all tags at once: `$ git push origin --tags` * You can't check out tags in git. You must checkout a branch at a specific tag: - `$ git checkout -b version2 v2.0.0` ### Aliases * Can be done with `$ git config --global alias.co checkout` * or in the .gitconfig file * usefull aliases: - co checkout - br branch - ci commit - st status - unstage reset HEAD -- - last log -1 HEAD - visual !gitk ## Chapter 3: Git Branches ### What are branches * When committing, git stores an object with: - pointer to the snapshot of the content you staged - authors name and email - the message you typed - pointers to the commit(s) that directly came before this commit (parents) * zero parents for initial commit * one parent for normal commits * multiple parents for merges * Therefore, in git a branch is a lightweight pointer to one of these commits * The default branch name is `master` ### Working with branches * Creating a new branch `$ git branch testing` - creates a new pointer to the same commit * HEAD is a special pointer that points at the commit you're currently on * Switch branches `$ git checkout testing` - This moves the HEAD cursor to testing * Creating a branch is lightweight (writing the 40byte hash + a newline to a file) * Shorthand for branching and switching `$ git checkout -b testing` * Switching is not allowed, if there are uncommitted changes in a branch ### Basic merging * Merge another branch into the current one: `$ git merge testing` * If a file was edited in more than one branch, a conflict will result and needs to be resolved before the next checkin. * you can manually resolve the conflict or use `$ git mergetool` * After the resolution, you can commit the changes. ### Branch management * `$ git branch` gives a list of current branches. * `$ git branch -v` gives the same list, but with the latest commit messages. * To see what branches are already merged, use `$ git branch --merged` * To see what branches that haven't been merged yet, use `$ git branch --un-merged` * Deleting branches that haven't been merged fails. ### Branching workflows 1. Long running branches * Used like different levels of hierarchy * Basically one long linear line of commits, branches used as tags. * Can be used to achieve different levels of stability 1. Topic branches * Branches diverge at any point * allows to context-switch quickly * can keep different parts of development isolated for longer times * more challenging to merge. ### Remote branches * Show remote references like branches and tags: `$ git remote show [remote]` * Remote-tracking branches are references to the state of remote branches. - They're moved every time you do a network communication.