[#dvcs distributed version control]: [#version-help version and help] | [#repository local and remote repository] | [#working-directory working directory] | [#track-commit track and commit] | [#branch-merge branch and merge] | [#history history] | [#pull-push push and pulll] | [#configuration-files configuration files] | [#external-repositories external repositories] | [#packaging packaging] | [#integrity-check-garbage-collection integrity check and garbage collection]
[#vcs version control]: [#vcs svn] | [#vcs cvs] | [#vcs rcs]
[#archive-patch-tools archive and patch tools]: [#diff diff] | [#cpio cpio] | [#diff3 diff3] | [#ar ar] | [#tar tar] | [#patch patch] | [#zip zip] | [#diffstat diffstat] | [#jar jar] | [#rsync rsync] | [#colordiff colordiff]
||||||~ # version-help[#version-help-note version and help]||
||~ ||~ [#git git]||~ [#hg hg]||
||# show-version[#show-version-note show version]||$ git version||$ hg version||
||# list-subcommands[#list-subcommands-note list subcommands]||$ git help -a _
_
##gray|//commonly used subcommands only://## _
$ git help||$ hg [-v] help _
_
##gray|-v: //show aliases and global options//##||
||# help-for-subcommand[#help-for-subcommand-note get help for subcommand]||$ git help CMD||$ hg help CMD||
||# list-topics-guides[#list-topic-guides-note list topic guides]||$ git help -g||$ hg help||
||# help-for-topic[#help-for-topic-note get help for topic]||$ git help TOPIC||$ hg help TOPIC||
||||||~ # repository[#repository-note local and remote repository]||
||~ ||~ [#git git]||~ [#hg hg]||
||create repository from a directory||$ git init [DIR]||$ hg init [DIR]||
||create repository with no working directory||$ git init @@–@@bare [DIR] _
_
##gray|//puts repo in// DIR##||##gray|//none//##||
||clone entire repository||$ git clone [-b [#BRANCH BRANCH]] [-o NAME] [@@–@@depth NUM] [#URL URL] [DIR] _
_
##gray|-b: //checkout// BRANCH //in working dir// _
-o: //assign// NAME //to remote repo// _
@@–@@depth: //copy commit history to depth NUM//##|| ||
||repository url formats||##gray|@@ssh://[user@]host.xz[:port]/path/to/repo.git@@ _
@@git://host.xz[:port]/path/to/repo.git@@ _
@@http[s]://host.xz[:port]/path/to/repo.git@@ _
@@ftp[s]://host.xz[:port]/path/to/repo.git@@ _
@@rsync://host.xz/path/to/repo.git@@ _
@@/path/to/repo.git@@ _
@@file:///path/to/repo.git@@##||##gray|@@local/filesystem/path[#revision]@@ _
@@file://local/filesystem/path[#revision]@@ _
@@http://[user[:pass]@]host[:port]/[path][#revision]@@ _
@@https://[user[:pass]@]host[:port]/[path][#revision]@@ _
@@ssh://[user@]host[:port]/[path][#revision]@@##||
||clone branch from repository|| ||$ hg clone [-r REV|-b BRANCH] … URL [DIR]||
||clone repository; new repository has no working directory||$ git clone @@–@@bare [#URL URL] @@[@@[#DIR DIR]] _
_
##gray|//puts repo in// DIR##||$ hg clone -U URL [DIR] _
_
##gray|//puts repo in// DIR/.hg##||
||list remote repositories||$ git [@@[@@-v] show] remote _
_
##gray|-v: //show url of remote//##||$ hg paths||
||add remote repository||$ git remote add [-t [#BRANCH BRANCH]] … [#NAME NAME] [#URL URL] _
$ git remote add [-m [#BRANCH BRANCH]] [#NAME NAME] [#URL URL]||##gray|//edit the// [paths] //section of// .hg/hgrc##||
||remove remote repository||$ git remote rm [#REMOTE REMOTE]|| ||
||rename remote repository||$ git remote rename [#REMOTE REMOTE] [#NAME NAME] || ||
||show remote repository details||$ git remote show [-n] [#REMOTE REMOTE] _
_
##gray|-n: //do not connect to remote repo//##|| ||
||edit remote repository details||$ git remote set-head REMOTE (-a|-d) [#BRANCH BRANCH] _
$ git remote set-url @@–@@add [#REMOTE REMOTE] URL _
$ git remote set-url @@–@@delete [#REMOTE REMOTE] URL _
$ git remote set-branches [#REMOTE REMOTE] [@@–@@add]
@< >@BRANCH …|| ||
||||||~ # working-directory[#working-directory-note working directory]||
||~ ||~ [#git git]||~ [#hg hg]||
||# checkout-version[#checkout-version-note check out version]||$ git checkout -f _
_
##gray|-f: //overwrite changes in working dir and index//##||$ hg update [-c|-C] -r [#HG-REV REV] _
_
##gray|-c: //fail if changes in working dir// _
-C: //discard changes in working dir//##||
||list modified files||$ git status [-s] [@@–@@ignored] @@[@@[#PATH PATH]] … _
_
##gray|-s: @< >@//short format// _
@@–@@ignored: //also files excluded by// .gitignore##||$ hg status @@[@@[#HG-PATH PATH]]||
||# ignore-file[#ignore-file-note ignore file]||.gitignore||.hgignore||
||check out specific files||$ git checkout [TREEISH] @@–@@ PATHSPEC …||$ hg revert [-C] [-r [#HG-REV REV]] [#HG-PATH PATH] … _
_
##gray|-C: //do not create backups w/ .orig suffix//##||
||check out from index||$ git checkout -p [#PATHSPEC PATHSPEC] …||##gray|//no index//##||
||clear index||$ git reset|| ||
||clear index and working directory||$ git reset @@–@@hard||$ hg revert -C -a||
||list or remove untracked files||$ git clean (-f|-n) _
_
##gray|-f: //remove untracked files// _
-n: //list untracked files//##||$ hg purge [-p] _
_
##gray|-p: //remove untracked files// _
_
//without// -p //untracked files are listed//##||
||move working directory changes to shelf||$ git stash [push @@[@@-m [#STR STR]]]||$ hg [-n STR] shelve||
||list sets of changes in shelf||$ git stash list||$ hg shelve @@–@@list [-p] _
_
##gray|-p: //show each set of changes as diff//##||
||show set of changes in shelf as diff||$ git stash show @@[@@[#STASH STASH]]||##gray|//none//##||
||restore changes from shelf||$ git stash pop @@[@@[#STASH STASH]]||$ hg unshelve [STR]||
||delete set of changes from shelf||$ git stash drop [STASH]||$ hg shelve -d STR||
||clear shelf||$ git stash clear||$ hg shelve @@–@@clear||
||||||~ # track-commit[#track-commit-note track and commit]||
||~ ||~ [#git git]||~ [#hg hg]||
||track files||##gray|//files are not tracked; changes must be added to staging area before each commit//##||$ hg add [#HG-PATH PATH] …||
||track files matching pattern|| ||$ hg add -I [#HG-PATTERN PATTERN]||
||track all files in working directory|| ||$ hg add||
||add modified or new files to staging area||$ git add [#PATHSPEC PATHSPEC] … _
_
##gray|-u: //files already under version control only//##||##gray|//working directory is the staging area//##||
||add part of modified file to staging area||$ git add -e [#PATH PATH]|| ||
||track any new files in working directory, and remove any tracked files not in working directory|| ||$ hg addremove @@[@@[#HG-PATH PATH]] …||
||remove files from working directory and next commit||$ git rm [-f] [#PATH PATH] … _
_
##gray|-f: //force if changed in index//##||$ hg remove [-f] [#HG-PATH PATH] … _
_
##gray|-f: //force if added or changed//##||
||remove files matching pattern||$ git rm [-f] [#PATHSPEC PATHSPEC] … _
_
##gray|-f: //force if changed in index//##||$ hg remove [-f] -I [#HG-PATTERN PATTERN] _
_
##gray|-f: //force if added or changed//##||
||remove files in next commit which are no longer in working directory|| ||$ hg remove -A [#HG-PATH PATH] …||
||mark file to be removed in next commit without removing from working directory|| ||$ hg forget [#HG-PATH PATH] …||
||remove subdirectory from working directory and next commit||$ git rm -r [#DIR DIR]||$ hg remove [#HG-DIR DIR]||
||remove files from index||$ git rm @@–@@cached [#FILE FILE] …|| ||
||copy files from head to index||$ git reset -p [#FILE FILE] …|| ||
||copy files from index to working directory||$ git checkout -p [#PATH PATH] …|| ||
||# move[#move-note move file in working directory and next commit]||$ git mv [#PATH OLDPATH] [#PATH NEWPATH]||$ hg rename [#HG-PATH OLDPATH] [#HG-PATH NEWPATH]||
||# move-into-dir[#move-into-dir-note move files into directory]||$ git mv [#PATH PATH] … [#DIR DIR]||$ hg rename [#HG-PATH PATH] … [#HG-DIR DIR]||
||copy file in working directory and next commit|| ||$ hg copy (-A|-f) [#HG-PATH SRCPATH] [#HG-PATH DESTPATH] _
_
##gray|-A: //if file already copied// _
-f: //if target is tracked//##||
||show difference between staging area and head||$ git diff @@–@@cached @@[@@[#PATHSPEC PATHSPEC] …]||$ hg diff [PATH …]||
||show difference between working directory and staging area||$ git diff @@[@@[#PATHSPEC PATHSPEC] …]||##gray|//working directory and staging area are the same//##||
||diff options||##gray|@@–@@name-only: list modified file names _
@@–@@name-status: status (M, A, D, R, ..) and modified file names _
@@–@@stat: histogram of changes by file _
@@–@@dirstat: histogram of changes by directory _
@@–@@word-diff: show changes to line inline _
@@–@@word-diff-regex=REGEX: set regex used by @@–@@word-diff _
-W: show entire modified function in context _
@< >@ _
-R: reverse direction of diff _
-w: ignore whitespace differences _
@@–@@ignore-blank-lines: ignore blank lines _
@< >@ _
@@–@@quiet: no output; exit status 1 if changes, otherwise 0 _
@< >@##||##gray|@< >@ _
@< >@ _
@@–@@stat: histogram of changes by file _
@< >@ _
@< >@ _
@< >@ _
-p: show entire modified function in context _
-U NUM: show NUM lines of context _
@@–@@reverse: reverse direction of diff _
-w: ignore whitespace differences _
-b: ignore blank lines _
-X PATTERN: exclude files matching fileglob _
@< >@ _
-S: recurse into subrepos##||
||grep staging area||$ git grep @@–cached@@ [-i] [-v] [-E|F|P] [-h|H] [-l|L] [-n] \ _
@< >@@< >@-e STR TREEISH [@@–@@] PATHSPEC|| ||
||# commit-changes[#commit-changes-note commit changes in staging area]||$ git commit [-a] [-m [#STR STR]] _
_
##gray|-a: //add all modified files with version history to staging area before commit.//##||$ hg commit [-m [#HG-STR STR]]||
||commit changes to selected files in staging area||$ git commit [-m [#STR STR]] [#PATH PATH] …||$ hg commit [-m [#HG-STR STR]] PATH …||
||commit changes in working directory|| ||$ hg commit -A [-m [#HG-STR STR]]||
||amend most recent commit||$ git commit @@–@@amend||$ hg commit @@–@@amend||
||change author of most recent commit||$ git commit @@–@@amend @@–@@author=[#STR STR]||$ hg commit @@–@@amend -u STR||
||# commit-identifiers[#commit-identifiers-note commit identifiers]||##gray|//40 hex digit hashes, e.g:// _
_
@< >@bbf3837d6c9bb54f11a4c620a1c81975156c2a49 _
_
//A prefix can be used to refer to a commit if it uniquely specifies it; often an 8 digit prefix is sufficient.// _
_
HEAD //refers to the most recent commit of the current branch.//##||##gray|//Each revision has a 40 hex digit hash and a sequential integer identifier. The hash is unique across all repositories, but the sequential integer is local to the repository.// _
_
//A prefix can be used to refer to a revision if it uniquely specifies it; often an 8 digit prefix is sufficient.// _
_
//A period . refers to the parent revision of the working directory.// _
_
tip //refers to the most recent revision in the repository.//##||
||other ways to refer to commits||##gray|//A circumflex postfix can be used to refer to the parent commit of a commit, e.g.// _
_
@< >@bbf3837d6^ _
_
//The circumflex can be used multiple times to refer to a grandparent, great-grandparent, and so on:// _
_
@< >@bbf3837d6@@@@ _
@< >@bbf3837d6@@^@@ _
_
//An alternative to multiple circumflexes is tilde notation:// _
_
@< >@bbf3837d6~2 _
@< >@bbf3837d6~3 _
_
//when a commit has multiple parents (i.e. the commit is a merge), use a circumflex followed by a number:// _
_
@< >@bbf3837d6^2##|| ||
||resolve commit notation||$ git rev-parse [#COMMIT COMMIT] _
_
##gray|//e.g. to get commit id of parent of tip:// _
_
@< >@git rev-parse HEAD^##|| ||
||create commit which reverts another commit||$ git revert [-n] [#COMMIT COMMIT] _
_
##gray|-n: //no commit, just change working directory//##||$ hg backout -r [#HG-REV REV]||
||create commit which reverts a merge commit||$ git revert [-n] -m NUM [#COMMIT COMMIT] _
_
##gray|NUM //is the number of the parent (e.g. 1, 2, …) to restore//##|| ||
||create commits which revert a sequence of commits||$ git revert [-n] [#COMMIT COMMIT1]..[#COMMIT COMMIT2] _
_
##gray|//reverts commits from// COMMIT1 //up to but not including// COMMIT2. //Use triple dots// @@…@@ //to include// COMMIT2.##|| ||
||tag a commit||$ git tag [-f] [#NAME NAME] @@[@@[#COMMIT COMMIT]] _
_
##gray|-f: //replace existing tag with same// NAME## _
_
##gray|//if no commit specified,// HEAD //is tagged//##||$ hg tag [-r [#HG-REV REV]] [#HG-NAME NAME]||
||delete a tag||$ git tag -d [#TAG TAG]||$ hg tag @@–@@remove [#HG-NAME NAME]||
||list tags||$ git tag||$ hg tags||
||||||~ # branch-merge[#branch-merge-note branch and merge]||
||~ ||~ [#git git]||~ [#hg hg]||
||current branch||$ git rev-parse @@–@@abbrev-ref HEAD|| ||
||list branches||$ git branch [-r|-a] _
_
##gray|-r: list remote tracking branches _
-a: list local and remote tracking branches##||$ hg bookmarks||
||list branches containing commit||$ git branch (@@–@@contains|@@–@@merged) COMMIT _
_
##gray|@@–@@contains: branches descended from COMMIT _
@@–@@merged:branches ancestors of COMMIT##|| ||
||list branches by most recent commit||$ git branch @@–@@sort=-committerdate|| ||
||checkout branch||$ git checkout BRANCH _
_
##gray|-f: discard changes in index and working directory##||$ hg update BRANCH _
_
##gray|-C: discard changes in working directory _
-c: fail if changes in working directory##||
||move branch head without changing working directory||$ git reset [@@–@@soft] COMMIT|| ||
||create new branch by cloning branch||$ git checkout -b NAME [BRANCH]||$ hg bookmarks NAME||
||create a tracking branch||$ git branch @@–@@track NAME [BRANCH]|| ||
||create a branch from a commit||$ git branch NAME COMMIT||$ hg bookmarks -r REV NAME||
||rename a branch||$ git branch -m BRANCH NAME||$ hg bookmarks -m NAME1 NAME2||
||delete a branch||$ git branch (-d|-D) BRANCH _
_
##gray|-d: fail if tracking branch with unmerged commits _
-D: delete even if unmerged commits exist##||$ hg bookmarks -d NAME||
||# list-dedicated-commit-branches[#list-dedicated-commit-branches-note list “dedicated commit” branches]|| ||$ hg branches||
||show current “dedicated commit” branch|| ||$ hg branch||
||change branch of next commit|| ||$ hg branch BRANCH||
||list branch tips|| ||$ hg heads [-c] _
_
##gray|-c: include closed tips##||
||close branch tip|| ||$ hg commit @@–@@close-branch||
||merge||$ git merge [@@–@@squash] COMMIT … _
_
##gray|@@–@@squash: make changes to index and working directory only; do not create a commit##||$ hg merge [[-r] REV] _
_
##gray|//Only modifies working directory; must be following by// hg commit //to create a new changeset.//##||
||show conflicts||$ git status||$ hg resolve -l||
||mark file with conflicts as resolved||$ git add PATH||$ hg resolve PATH||
||unmark file with conflicts as resolved|| ||$ hg resolve -u PATH||
||abort merge||$ git merge @@–@@abort||$ hg update -C||
||rebase current branch||$ git rebase BRANCH|| ||
||continue rebase||$ git rebase @@–@@continue|| ||
||abort rebase||$ git rebase @@–@@abort|| ||
||squash commits||$ git rebase -i COMMIT _
_
##gray|commits after COMMIT can be squashed; change all after first from “pick” to “squash”##|| ||
||apply commit to current branch||$ git cherry-pick COMMIT ||$ hg graft -r REV||
||continue cherry pick||$ git cherry-pick @@–@@continue|| ||
||abort cherry pick||$ git cherry-pick @@–@@abort|| ||
||create detached head from branch and sequence of commits||$ git rebase @@–@@onto BRANCH COMMIT1 COMMIT2|| ||
||||||~ # history[#history-note history]||
||~ ||~ [#git git]||~ [#hg hg]||
||write version of file to standard out||$ git show COMMIT:FILE||$ hg cat -r REV FILE||
||annotate lines of file with commit info||$ git blame [-l] [-s] [-s] [#PATH PATH] #COMMIT COMMIT _
_
##gray|-l: //show full commit id (default is 8 chars)// _
-s: //suppress author name and timestamp// _
-w: //ignore whitespace differences//##||$ hg annotate -cudln [-r [#HG-REV REV]] @@[@@[#HG-PATH PATH]] _
_
##gray|-c: //changeset// _
-u: //author// _
-d: //date// _
-l: //line number// _
-n: //local revision number//##||
||commits which are ancestors of head/tip||$ git log [@@–@@parents] _
_
##gray|@@–@@parents: //after commit identifier show parent commit identifiers//##||$ hg log||
||commits as graph||$ git log @@–@@graph||$ hg log -G||
||first parent history||$ git log @@–@@first-parent|| ||
||chronological order||$ git log @@–@@reverse|| ||
||all commits in repository||$ git log [@@–@@source] @@–@@all _
_
##gray|@@–@@source: //print ref name after each commit//##|| ||
||limit commits||$ git log [@@–@@skip=NUM] -(n NUM|-NUM) _
_
##gray|@@–@@skip: //skip first NUM commits//##|| ||
||commits which touched files||$ git log [@@–@@follow] [@@–@@] PATH … _
_
##gray|@@–@@follow: //follow renamed files// _
@@–@@: //prevent interpreting// PATH //as option//##||$ hg log [-f] PATH … _
_
##gray|-f: //follow copied and renamed files//##||
||commits which touched lines||$ git log -L NUM,NUM:PATH|| ||
||one line commits||$ git log @@–@@oneline|| ||
||format string for commit||$ git log @@–@@pretty=format:FORMAT _
_
##gray|//format string specifiers:// _
_
%H commit hash _
%h abbrev. commit hash _
%T tree hash _
%t abbrev. tree hash _
%P parent hash(es) _
%p abbrev. parent hash(es) _
%s subject _
%b body _
%an author name _
%ae author email _
%ad author date _
%cn committer name _
%ce committer email _
%cd committer date _
%n newline _
%% percent sign##|| ||
||show commit diffs||$ git log -p|| ||
||show commits touching lines matching regular expression||$ git log -p [@@–@@pickaxe-all] -G REGEX||$ hg grep PATTERN||
||grep commit messages||$ git log @@–@@grep=REGEX||$ hg log @@–@@keyword STR _
_
##gray|//case insensitive search; also searches source//##||
||show changes to head||$ git reflog _
_
##gray|The output format is: _
_
@< >@ HEAD@{} _
_
is the number of changes since HEAD was at . HEAD@{} can be used as an alias for .## _
_
##gray|This outputs reflog info in log style:## _
_
$ git log -g|| ||
||difference between commit and its parent||$ git diff @@[–@@name-only@@]@@ [#COMMIT COMMIT]^ [#COMMIT COMMIT] [@@–@@] [PATH …]||$ hg diff -c [#HG-REV REV] @@[@@[#HG-PATH PATH] …]||
||difference between two comits||$ git diff @@[–@@name-only@@]@@ [#COMMIT COMMIT1] [#COMMIT COMMIT2] [@@–@@] [PATH …]||$ hg diff -r [#HG-REV REV1] -r [#HG-REV REV2] @@[@@[#HG-PATH PATH] …]||
||diff options||##gray|@@–@@name-only: list modified file names _
@@–@@name-status: status (M, A, D, R, ..) and modified file names _
@@–@@stat: histogram of changes by file _
@@–@@dirstat: histogram of changes by directory _
@@–@@word-diff: show changes to line inline _
@@–@@word-diff-regex=REGEX: set regex used by @@–@@word-diff _
-W: show entire modified function in context _
@< >@ _
-R: reverse direction of diff _
-w: ignore whitespace differences _
@@–@@ignore-blank-lines: ignore blank lines _
@< >@ _
@@–@@quiet: no output; exit status 1 if changes, otherwise 0 _
@< >@##||##gray|@< >@ _
@< >@ _
@@–@@stat: histogram of changes by file _
@< >@ _
@< >@ _
@< >@ _
-p: show entire modified function in context _
-U NUM: show NUM lines of context _
@@–@@reverse: reverse direction of diff _
-w: ignore whitespace differences _
-b: ignore blank lines _
-X PATTERN: exclude files matching fileglob _
@< >@ _
-S: recurse into subrepos##||
||grep commit||$ git grep [-i] [-v] [-E|F|P] [-h|H] [-l|L] [-n] \ _
@< >@@< >@-e [#STR STR] [#TREEISH TREEISH] @@[–]@@ [#PATHSPEC PATHSPEC]|| ||
||start bisection||$ git bisect [#COMMIT BADCOMMIT] [#COMMIT GOODCOMMIT]|| ||
||mark bisection commit as good||$ git bisect good|| ||
||mark bisection commit as bad||$ git bisect bad|| ||
||mark bisection commits automatically||$ git bisect run SCRIPT [ARG]… _
_
##gray|//Exit status of 0 indicates a good commit. Exit status of 125 indicates an untestable commit. Any other status in the range 1…127 indicates a bad commit.//##|| ||
||show bisection decisions||$ git bisect log|| ||
||terminate bisection||$ git bisect reset|| ||
||||||~ # pull-push[#pull-push-note push and pull]||
||~ ||~ [#git git]||~ [#hg hg]||
||pull commits from remote||$ git fetch [-f] [-t] [-p] [REPO] _
_
##gray|-f: force if update not a fast-forward _
-t: copy tags _
-p: remove local references gone from remote _
_
//Pulls from origin if REPO not specified.// _
_
//Updates remote tracking branches per refspec of REPO in .git/config.//##||$ hg pull [-u] [SOURCE] _
_
##gray|-u: //update working directory to most recent changeset//## _
_
##gray|//Pushes all revisions in local repository not on remote repository.//## _
_
##gray|//If no SOURCE specified, uses value of default in the [paths] section of .hg/hgrc.//##||
||pull commits from remote for branch||$ git fetch [-f] [-t] [-p] REPO REFSPEC||$ hg pull (-b BRANCH|-B BOOKMARK|-r REV) … [SOURCE] _
_
##gray|-b: //pull revisions on BRANCH and parents// _
-B: //pull BOOKMARKed revision and parents// _
-r: //pull REV and parents//##||
||pull commits from multiple remotes||$ git fetch [-f] [-t] -p|| ||
||show remote commits available for pulling|| ||$ hg incoming||
||pull commits from remote and merge current branch with remote head||$ git pull [-f] REPO [REFSPEC]|| ||
||push commits to remote||$ git push [-f] [@@–@@prune] [@@–@@tags] @@[@@[#REPO REPO]@@]@@||$ hg push [-f] [SOURCE]||
||push commits to remote for branch||$ git push [-f] [-u] [#REPO REPO] @@[@@BRANCH@@]@@ …||$ hg push @@–@@new-branch … [SOURCE]||
||delete remote branches||$ git push @@–@@delete [#REPO REPO] [#BRANCH BRANCH] …|| ||
||show commits which have not been pushed|| ||$ hg outgoing||
||move commits by archive||$ git bundle||$ hg bundle _
$ hg unbundle||
||||||~ # configuration-files[#configuration-files-note configuration files]||
||~ ||~ [#git git]||~ [#hg hg]||
||repository config file||.git/config||.hg/hgrc||
||user config file||/.gitconfig||/.hgrc||
||show config options||$ git help config||$ hg help config||
||set config value when cloning||$ git clone [-c SECTION.KEY=VAL] [#URL URL] @@[@@[#DIR DIR]]|| ||
||list configuration settings||$ git config -l [@@–@@global]||$ hg showconfig||
||show specific configuration setting||$ git config –get [–global] SECTION.KEY|| ||
||||||~ # external-repositories[#external-repositories-note external repositories]||
||~ ||~ [#git git]||~ [#hg hg]||
||external repository file||.gitmodules||.hgsub||
||external repository file format||[submodule “vendor/modules/system”] _
@< >@path = vendor/modules/system _
@< >@url = ../dm-kohana-core.git|| ||
||add submodule||$ git submodule add URL PATH _
_
##gray|//Records submodule in// .gitmodules. //If// PATH //does not exist,// URL //is cloned there.//##|| ||
||register submodules||$ git submodule init _
_
##gray|//Copies data from// .gitmodules //in index to// .git/config.##|| ||
|| ||$ git submodule update|| ||
||clone repository and external repositories||$ git clone @@–@@recursive URL|| ||
||||||~ # packaging[#packaging-note packaging]||
||~ ||~ [#git git]||~ [#hg hg]||
||create tarball||$ git archive @@–@@format=tar [#TREEISH TREEISH] > repo.tar||$ hg archive -t tar ../[#HG-NAME NAME].tar||
||create gzipped tarball||$ git archive @@–@@format=tgz [#TREEISH TREEISH] > repo.tgz|| ||
||create zip archive||$ git archive @@–@@format=zip [#TREEISH TREEISH] > repo.zip|| ||
||create a patch||$ git format-patch ???||$ hg export ???||
||apply patch||$ git apply ???||$ hg import ???||
||||||~ # integrity-check-garbage-collection[#integrity-check-garbage-collection-note integrity check and garbage collection]||
||~ ||~ [#git git]||~ [#hg hg]||
||# integrity-check[#integrity-check-note integrity check]||$ git fsck||$ hg verify||
||# garbage-collection[#garbage-collection-note garbage collection]||$ git gc||##gray|//none//##||
||~ ##EFEFEF|@@____________________________________________@@##||~ ##EFEFEF|@@_________________________________________________________________@@##||~ ##EFEFEF|@@____________________________________________________________________@@##||
- [#top Metasyntactic Variables]
||||~ git|| ||# BRANCHBRANCH||the name of a branch.|| ||# CMDCMD||the name of a version control command: the first argument of the base command.|| ||# COMMITCOMMIT||the [#HASH HASH] for a commit. A commit can be referenced indirectly via a branch or tag name or via commit notation. The symbolic references HEAD or FETCHHEAD can also be used to reference commits.|| ||# DIRDIR||a directory on the file system. In some cases it must exist; in others it will be created.|| ||# FILEFILE||a regular file on the file system. In some cases it must exist; in others it will be created.|| ||# HASHHASH||a 40 digit hex string used as an identifier for something in the object database.|| ||# HEADHEAD||the literal string HEAD.|| ||# NAMENAME||a name for an entity which will be created. Usually there are restrictions on the characters that can be used.|| ||# PATHPATH||a path on the file system. In some cases it must exist; in others it will be created.|| ||# PATHSPECPATHSPEC||like a file glob pattern, except that ? and * can match the directory separator: /. Characters special to the shell must be escaped.|| ||# REFSPECREFSPEC||[+]SRCREF:DESTREF where SRCREF and DESTREF are ref paths relative to the .git directory. SRCREF is on the remote repository in a fetch or a pull and on the local repository in a push. _ _ An asterisk can be used in place of a component of the relative path to match everything in the directory. If the SRCREF has an asterisk, the DESTREF must also have one. _ _ A plus sign prefix + is used to indicate that the update should be made even when it is not a fast-forward. _ _ If the SRCREF is the empty string, then the DESTREF is deleted. _ _ Leading components of SRCREF or DESTREF can be omitted if no ambiguity results.|| ||# REMOTEREMOTE||the name of a remote.|| ||# REPOREPO||A REMOTE or a URL.|| ||# STASHSTASH||stash identifier format: stash@{0}, stash@{1}, …|| ||# STRSTR||a string. There are no restrictions on the characters that can be used, but if they include whitespace or characters special to the shell they must be escaped or quoted.|| ||# TREEISHTREEISH||the [#HASH HASH] for a tree, a commit, or a tag. If the HASH is for a commit or a tag the tree in the commit is used.|| ||# URLURL||a url for a repository.|| ||||~ hg|| ||# HG-BRANCHBRANCH||the name of a branch.|| ||# HG-CMDCMD||the name of a version control command: the first argument of the base command.|| ||# HG-DIRDIR||a directory on the file system. In some cases it must exist; in others it will be created.|| ||# HG-FILEFILE||a regular file on the file system. In some cases it must exist; in others it will be created.|| ||# HG-NAMENAME||a name for an entity which will be created. Usually there are restrictions on the characters that can be used.|| ||# HG-PATHPATH||a path on the file system. In some cases it must exist; in others it will be created.|| ||# HG-PATTERNPATTERN||a file glob pattern. The metacharacters ?, , and @@*@@ are supported. Characters special to the shell must be escaped.|| ||# HG-REVREV||the revision number for a changeset. It can be either the local revision number, which is a small decimal integer, or the 12 hex digit universal revision number.|| ||# HG-SOURCESOURCE||A URL or a name for a URL in the [paths] section of the .hg/hgrc file|| ||# HG-STRSTR||a string. There are no restrictions on the characters that can be used, but if they include whitespace or characters special to the shell they must be escaped or quoted.|| ||# HG-URLURL||a url for a repository.||
# help-note + [#top Help]
# show-version-note ++ [#show-version show version]
# list-subcommands-note ++ [#list-subcommands list subcommands]
# help-for-subcommand-note ++ [#help-for-subcommand get help for subcommand]
# list-topic-guides-note ++ [#list-topic-guides list topic guides]
# help-for-topic-note ++ [#hep-for-topic get help for topic]
# repository-note + [#repository Local and Remote Repository]
When a set of files is edited, we can view the set of files as a sequence of //versions// or //revisions// which are ordered in time. A //repository// is a record of the versions of a set of files; it permits recovering the set files as they were at any of the recorded points in time.
A //working directory// (q.v the working directory of a process) can contain a copy of one of the file set versions; it can also be edited to create a new version of the file set. A //commit// is the act of recording the new version of the file set in the repository. This is done by comparing the working directory with the previous version or an empty file set in the case of an //initial commit//. The commit can also be regarded as the difference—that is, the output of {{diff -r}}—between the previous and the new version. This difference is also called the //changeset//.
When calculating the changeset, the version control system may ignore files in the working directory which are not //tracked files//.
A set of files and directories under version control is called a //repository//.
git
A file or directory under version control has one or more //versions//. One adds new versions to the repository by making a //commit//. The set of all files and directories in the repository can also be seen as having versions; these versions are called //commits//; they consist of at most one version of each file or directory in the repository.
hg
A file or directory under version control has one or more //revisions//. One adds new revisions to the repository by making a //commit//. The set of files and directories in the repository can also be seen as having revisions; these revisions are called //changesets//.
# working-directory-note + [#working-directory Working Directory]
# checkout-version-note ++ [#checkout-version check out version]
git:
These two commands appear to do the same thing:
code $ git checkout -f COMMIT $ git reset –hard COMMIT /code
++ list modified files
# ignore-file-note ++ [#ignore-file ignore file]
git
[http://schacon.github.com/git/gitignore.html man gitignore]
A list of file patterns, one per line. The patterns specify files that {{git status}} and {{git add}} should ignore. Shell glob syntax (i.e. the asterisk: *) can be used.
A .gitignore can be placed in any directory in the repository. The rules in a given .giitignore file will only apply to the current directory and the directories beneath it.
Lines starting with a pound sign: # are ignored.
A pattern starting with an exclamation point: ! will negate a pattern. This can be used to include files that were excluded by a pattern higher in the file matching a broader set of files.
hg
Unlike {{.gitignore}}, an {{.hgignore}} file must be in the root of the working directory.
The format is one Perl regular expression per line. All files which match the regular expression will be ignored.
Comments start with the pound sign: #
It is also possible to use glob syntax:
regexp to ignore twiddle files:
~$
glob to ignore compiled python files:
syntax: glob *.pyc
additional patterns will use regexp format:
syntax: regexp /code
# track-commit-note + [#track-commit Track and Commit]
git
Git keeps copies of all versions of files and directories that have been committed, as well as the commits themselves, in the directory {{.git/objects}}. All objects are identified by their 40 character SHA-1 checksum called the //hash//. There are three types of git objects in this directory: a //blob//, which is the contents of a file. A //tree//, which corresponds to file system directory; it contains the file system name of the objects, which can be blobs (regular files) or trees (directories) and their hashes. Finally, a //commit// contains the top level tree for the commit and the parents of the commit. There will be zero parents for the initial commit and more than one parent for a commit which was created by a merge. Git stores a separate, albeit compressed, copy of each version of a file, tree, or commit in the {{.git/objects}} directory.
The {{git cat-file -p HASH}} command, though not needed for day-to-day use, provides a way to inspect a git object. It shows the additional information stored in trees and commits which we have not mentioned here.
hg
Mercurial uses a storage format called a //revlog// to store the versions of a file. Most revlogs are kept in {{.hg/store/data}}. A revlog usually consists of two files: one with an {{.i}} suffix and another with a {{.d}} suffix. If the file is small and has little or no history, the revlog might consist of only a {{.i}} file. A revlog which tracks the history of a file is called a //filelog//. When the file is first committed, it is written to the filelog. Each time a commit is made which alters it, a delta describing the change is appended to the file. Thus, to fetch the current version of a file, all the deltas must be applied in order to the original version of the file. As a performance optimization, Mercurial will sometimes append the full version of the file to a filelog. Thus, when reconstructing the current version, one need only apply delta starting from the last time the full version was stored.
Mercurial stores a //manifest// for each revision of the repository. A reviion of the repository is called a //changeset//. The manifest is list of the pathnames relative to the root of all files in the changeset. Rather than store the manifests in separate files, all the manifests for the repository are stored in a revlog in {{.hg/store}}. Each time a new changeset is added to a repository by a {{push}}, {{pull}}, or {{commit}} command, it is assigned a local revision number which is the order in which it was appended to the local manifest revlog. If the changeset was pulled from a different repository, the local revision numbers might not match.
Information about changesets is also stored in the //changelog//, which is another type of revlog. The changelog has a pointer to manifest revision, pointers to parents of the changeset, and information about the committer.
git
Git has three types of objects: commits, trees, and blobs. Each is assigned a unique hash ID which is a 40 digit hex string. The identifier is called the hash, SHA1, object name, or object identifier with no difference in meaning. When the underlying object is a commit or tree it is also called a tree-ish.
Commit hashes are the hashes the user most commonly sees and needs to reference. Only as many of the digits that are necessary to uniquely identify an object in the object database need to be provided to a git command; usually the first 6 or 7 is sufficient.
HEAD is a special name which refers to the most recent commit of the current branch. It is stored in {{.git/HEAD}}. The previous commit is HEAD^ and the commit before that is HEAD@@@@. The is also numerical notation: HEAD~4 is 4 commits ahead of HEAD. If HEAD is the result of a merge, then the antecedents can be be referenced with HEAD^1 and HEAD^2.
hg
In Mercurial, every commit is assigned two identifiers: a //local revision number// and a universal //changeset identifier//. The local revision number is a small integer that is unique only to the local repository. The first local revision number issued is zero, and it increments with each local commit. The changeset identifier is a twelve digit hex number which is unique across all repositories.
The {{-r}} option is used to pass a mercurial commit identifier to a command. The argument can be a local revision number, a changeset identifier, or both separated by a colon.
# move-note ++ [#move move file in working directory and next commit]
It is desirable for a version control system to track file name changes. Otherwise commands like {{blame}} and {{log}} when used on a single path will not show activity before the name change. If the version control system is aware of a name change, it can correctly handle the case when merging where the name was changed on one branch and edited on the other.
git
Although Git provides a {{git mv}} subcommand, it does not actually track name changes. Instead, it will assume that a name change occurred during a commit when one file disappeared, another appeared, and they have similar contents. Hence, even if the user uses {{git rm}}, a Unix command {{mv}}, and {{git add}}, Git will preserve the history for the file.
hg
Mercurial keeps track of the name a file had in each revision of a filelog. The {{hg rename}} subcommand must be used to preserve history.
# move-into-dir-note ++ [#move-into-dir move file]
# commit-changes-note ++ [#commit-changes commit changes in staging area]
In the case of Git, the staging area is the index.
In the case of Mercurial, the staging area is the files in the working directory which are tracked.
# commit-identifiers-note ++ [#commit-identifiers commit identifiers]
mercurial:
{{null}} refers to an empty revision which is the parent of revision 0.
# branch-merge-note + [#branch-merge Branch and Merge]
git
Git has a low level feature called a //ref// which it uses to implement branches and tags. A ref is a file in {{.git/refs}} which contains the hash of a commit. Branches are in {{.git/refs/heads}} and tags are in {{.git/refs/tags}}. Whenever a commit is made, the value in {{.git/refs/heads/BRANCH}} is updated where BRANCH is the current branch. The values in {{.git/refs/tags/TAG}} do not change.
The name of the branch which is currently checked out is stored in {{.git/HEAD}}. It is stored as the relative path {{refs/head/NAME}}.
Git also stores remote branches and tags in {{.git/refs/remotes/REPO}}. The {{git branch -r}} command can be used to list remote branches. Remote branches have names of the form REPO/BRANCH, and each remote branch will usually have a tracking branch, which is a local branch named BRANCH. This will be the case for any branches which were copied when a repository is created via {{git clone}}. A tracking branch can also be created when a remote repository is added using {{git remote -t BRANCH REPO URL}}. {{git fetch}} will only update remote branches. {{git pull}} will update remote branches and merge them with their tracking branches.
The default branch is called {{master}}. It is created by {{git init}}, and is the branch that is copied by {{git clone}} if no branch is explicitly specified.
Commits have zero or more parent commits. {{git commit}} creates a commit with one parent, except in the case of the initial commit. {{git merge}} creates a commit with two or more parent commits. If the commit has three or more parents, the merge is called an octopus merge.
//staging numbers://
To perform a merge Git gets the tree contained in the common ancestor and puts its items into the staging area with staging number 1. It puts the current branch tree items in the staging area with staging number 2. It puts the tree items of the other branches in the staging area with staging number 3 or higher.
//fast-forward commits aren’t actually commits://
Suppose that {{bar}} is a branch of {{foo}}. If commits have subsequently been made to {{foo}} but not to bar, then running the following when {{bar}} is the current branch will perform a fast-forward:
In a fast-forward no merge commit is created. Instead the head of {{bar}} is simply moved to point to the same commit as the head of {{foo}}.
hg
A Mercurial branch is a name which is stored in a changeset. When a commit is made, the new changeset inherits the branch name of the previous changeset, unless a different name was specified before the commit with {{hg branch}}. To switch to a new branch one must make a commit.
Mercurial branches differ from Git branches in that:
- every commit belongs to a single branch
- a branch can have multiple heads
Mercurial tags are names for changesets. They are stored in the {{.hgtags}} file at the repository root. Creating a tag requires making a commit.
Mercurial does not support octopus merges. Thus changesets have at most two parents. A changeset created by {{hg merge}} sets the branch of the new changeset to be the branch of the first argument.
Changesets can have no branch specified. This is also called the {{default}} branch.
//bookmarks://
Mercurial bookmarks work like Git branches, with the exception that Mercurial does not have the equivalent of Git tracking branches.
# list-dedicated-commit-branches-note ++ [#list-dedicated-commit-branches list “dedicated commit” branches]
“dedicated commit” branches is the term used in this sheet to distinguish Mercurial-style branches from Git-style branches. Mercurial bookmarks are equivalent to Git-style branches.
In Git, branches are names which contain the hash of a commit. This commit is the head of the branch, and because each commit knows its parents, the entire history of the branch can be constructed. Git commits can belong to multiple branches, or they can belong to none at all. If a Git commit is not reachable from any branch or tag, it is at risk of being garbage collected.
In Mercurial, each changeset has a branch name associated with it. Thus, each changeset must belong to exactly one branch. Also, Mercurial branches can have multiple tips, whereas a Git branch always has a single head.
Mercurial does not provide a mechanism for renaming or deleting branches. The recommended way to get rid of unwanted branches is to rename the repository and then clone it to the original name with:
# history-note + [#history History]
# pull-push-note + [#pull-push Push and Pull]
git
The basic command for getting changes from a remote repository {{origin}} is:
Which branches are fetched is controlled by the {{fetch}} key in the {{remote}} section of {{.git/config}}. If the local repository was created by {{git clone}}, here is a likely value:
code [remote “origin”] fetch = +refs/heads/:refs/remotes/origin/ /code
In this case, {{git fetch origin}} connects to the remote repository and copies all of the remote branches to {{refs/remotes/origin}}. Then it adds all remote objects referred to by the remote branches to the local objects database. It also puts the remote HEAD into FETCH_HEAD. The + indicates that local branches should be updated even if the commits are not fast-forwards.
The basic command for sending changes back to the remote repository {{origin}} is:
Which branches are pushed is controlled by the {{push}} key in the {{remote}} section of {{.git/config}}. Here is an example entry which pushes commits on the master branch, and fails if the commits are not fast-forwards:
code [remote “origin”] push = refs/heads/master:refs/heads/master /code
A {{git pull}} is a {{git fetch}} followed by a {{git merge FETCH_HEAD}}, which {{git fetch}} sets to whatever was in {{HEAD}} on the remote repository.
hg
{{hg pull}} pulls changesets for all the remote branches that are also local branches unless branches are listed explicitly with the {{-b}} flag. {{hg pull -u}} is equivalent to {{hg pull}} followed by {{hg update}}. Pulling can create local branches with multiple heads, in which case an {{hg update}} will fail. An {{hg merge}} is used to merge the two heads, or an {{hg commit @@–@@close-branch}} is used to mark one of them as closed.
{{hg push}} pushes changsets for all local branches that are also remote branches unless branches are listed explicitly with the {{-b}} flag. A push which would create a branch with multiple heads will fail unless the {{-f}} flag is used. The {{@@–@@new-branch}} flag must be used to create a new branch.
# configuration-files-note + [#configuration-files Configuration Files]
# external-repositories-note + [#external-repositories External Repositories]
# packaging-note + [#packaging Packaging]
# integrity-check-garbage-collection-note + [#integrity-check-garbage-collection Integrity Check and Garbage Collection]
# integrity-check-note ++ [#integrity-check integrity check]
# garbage-collection-note ++ [#garbage-collection garbage collection]
# vcs + [#top Version Control]
[#svn svn] | [#cvs cvs] | [#rcs rcs] | [#sccs sccs]
||~ ||||~ distributed ||||~ client-server||~ local|| ||~ ||~ $ [#git git] CMD||~ $ [#hg hg] CMD||~ $ [#svn svn] CMD||~ $ [#cvs cvs] CMD||~ $ [#rcs rcs] CMD|| ||online documentation||[http://schacon.github.io/git/git-help.html help]||[http://www.selenic.com/mercurial/hg.1.html#help help]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.help.html help]||$ man cvs||$ man rcs|| ||||||||||||~ repository|| ||create new repository||[http://schacon.github.io/git/git-init.html init]||[http://www.selenic.com/mercurial/hg.1.html#init init]|| ||[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_2.html#IDX63 init]||$ mkdir RCS|| ||get local copy of repository from server or existing repository||[http://schacon.github.io/git/git-clone.html clone]||[http://www.selenic.com/mercurial/hg.1.html#clone clone]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.checkout.html checkout]/[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.checkout.html co]||[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_16.html#SEC129 checkout]/[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_16.html#SEC129 co]|| || ||show remote repositories||[http://schacon.github.io/git/git-remote.html remote] -v show||[http://www.selenic.com/mercurial/hg.1.html#paths paths]|| || || || ||add remote repository||[http://schacon.github.io/git/git-remote.html remote] add|| || || || || ||||||||||||~ working directory|| ||update working directory to most recent version of a branch||[http://schacon.github.io/git/git-checkout.html checkout]||[http://www.selenic.com/mercurial/hg.1.html#update update]/up||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.update.html update]/[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.update.html up]||[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_16.html#SEC165 update]||[http://linux.die.net/man/1/co co]|| ||lock a file|| || ||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.lock.html lock]|| ||[http://linux.die.net/man/1/co co] -l|| ||unlock a file|| || ||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.unlock.html unlock]|| ||[http://linux.die.net/man/1/co co] -u|| ||make working directory match the most recent commit||[http://schacon.github.io/git/git-reset.html reset]||[http://www.selenic.com/mercurial/hg.1.html#revert revert]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.revert.html revert]|| || || ||show files in working directory which don’t match the most recent commit||[http://schacon.github.io/git/git-status.html status]||[http://www.selenic.com/mercurial/hg.1.html#status status]/[http://www.selenic.com/mercurial/hg.1.html#status st]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.status.html status]/[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.status.html st]||[http://www.lodestar2.com/people/dyork/talks/2001/ols/frames/foil23.html status]|| || ||show difference between file in working directory and most recent commit||[http://schacon.github.io/git/git-diff.html diff]||[http://www.selenic.com/mercurial/hg.1.html#diff diff]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.diff.html diff]/[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.diff.html di]||[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_16.html#SEC137 diff]||[http://linux.die.net/man/1/rcsdiff diff]|| ||store uncommitted working directory changes in a temporary location||[http://schacon.github.io/git/git-stash.html stash]||[http://www.selenic.com/mercurial/hg.1.html#shelve shelve]|| || || || ||||||||||||~ tracking and committing|| ||put file under version control||[http://schacon.github.io/git/git-add.html add]||[http://www.selenic.com/mercurial/hg.1.html#add add]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.add.html add]||[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_7.html#IDX133 add]||[http://linux.die.net/man/1/ci ci] -i|| ||change name of a file under version control||[http://schacon.github.io/git/git-mv.html mv]||[http://www.selenic.com/mercurial/hg.1.html#rename rename]/[http://www.selenic.com/mercurial/hg.1.html#rename mv]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.move.html move]/[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.move.html mv]|| || || ||mark file as not present in the next commit||[http://schacon.github.io/git/git-rm.html rm]||[http://www.selenic.com/mercurial/hg.1.html#remove remove]/[http://www.selenic.com/mercurial/hg.1.html#remove rm]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.delete.html delete]/[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.delete.html rm]||[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_16.html#SEC160 remove]|| || ||create new commit||[http://schacon.github.io/git/git-commit.html commit]||[http://www.selenic.com/mercurial/hg.1.html#commit commit]/[http://www.selenic.com/mercurial/hg.1.html#commit ci]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.commit.html commit]/[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.commit.html ci]||[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_16.html#SEC132 commit]/[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_16.html#SEC132 ci]||[http://linux.die.net/man/1/ci ci]|| ||create commit which undoes the result of a previous commit||[http://schacon.github.io/git/git-revert.html revert]||[http://www.selenic.com/mercurial/hg.1.html#backout backout]|| || || || ||||||||||||~ branching and merging|| ||create branch||[http://schacon.github.io/git/git-branch.html branch]||http://www.selenic.com/mercurial/hg.1.html#branch branch||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.copy.html copy]/[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.copy.html cp]||[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_4.html#SEC49 tag -b]||[http://linux.die.net/man/1/ci ci] -r|| ||merge branches||[http://schacon.github.io/git/git-merge.html merge]||[http://www.selenic.com/mercurial/hg.1.html#merge merge]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.merge.html merge]|| || || ||move commits on a branch to the end of another branch||[http://schacon.github.io/git/git-rebase.html rebase]||[http://www.selenic.com/mercurial/hg.1.html#rebase rebase]|| || || || ||mark file with merge conflicts as resolved||[http://schacon.github.io/git/git-add.html add]||[http://www.selenic.com/mercurial/hg.1.html#resolve resolve]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.resolve.html resolve]|| || || ||||||||||||~ history|| ||annotate lines of source code with commit info||[http://schacon.github.io/git/git-blame.html blame]||[http://www.selenic.com/mercurial/hg.1.html#annotate annotate]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.blame.html blame]/[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.blame.html ann]||[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_16.html#SEC126 annotate]|| || ||show commit information for current branch in reverse chronological order||[http://schacon.github.io/git/git-log.html log]||[http://www.selenic.com/mercurial/hg.1.html#log log] -b tip||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.log.html log]||[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_16.html#SEC150 log]||[http://linux.die.net/man/1/rlog log]|| ||show difference between two commits||[http://schacon.github.io/git/git-diff.html diff]||[http://www.selenic.com/mercurial/hg.1.html#diff diff]|| || ||[http://linux.die.net/man/1/rcsdiff diff] -rREV1 -rREV2|| ||find commit which introduced a change||[http://schacon.github.io/git/git-log.html log] -S||[http://www.selenic.com/mercurial/hg.1.html#grep grep]|| || || || ||write contents of a file version to standard out||[http://schacon.github.io/git/git-show.html show]||[http://www.selenic.com/mercurial/hg.1.html#cat cat]||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.cat.html cat]||[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_16.html#SEC132 checkout -p]||[http://linux.die.net/man/1/co co]|| ||give name to a commit||[http://schacon.github.io/git/git-tag.html tag]||http://www.selenic.com/mercurial/hg.1.html#tag tag||[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.copy.html copy]/[http://svnbook.red-bean.com/en/1.7/svn.ref.svn.c.copy.html cp]||[http://ximbiot.com/cvs/manual/cvs-1.11.23/cvs_4.html#SEC49 tag]||$ rcs -nTAG:REV|| ||||||||||||~ pulling and pushing|| ||show commits available to be pulled or update tracking branches||[http://schacon.github.io/git/git-fetch.html fetch]||[http://www.selenic.com/mercurial/hg.1.html#incoming incoming]/[http://www.selenic.com/mercurial/hg.1.html#incoming in]|| || || || ||get commits from a remote repository||[http://schacon.github.io/git/git-pull.html pull]||[http://www.selenic.com/mercurial/hg.1.html#pull pull]|| || || || ||push commits to a remote repository||[http://schacon.github.io/git/git-push.html push]||[http://www.selenic.com/mercurial/hg.1.html#push push]|| || || || ||||||||||||~ configuration|| ||add user information||[http://schacon.github.io/git/git-config.html config]|| || || || || ||~ ##EFEFEF|@@________________________________________________@@##||~ ##EFEFEF|@@____________________@@##||~ ##EFEFEF|@@____________________@@##||~ ##EFEFEF|@@____________________@@##||~ ##EFEFEF|@@____________________@@##||~ ##EFEFEF|@@_______________________@@##||
# sccs + [#top sccs (1972)]
- [http://www.gnu.org/software/cssc/manual/index.html CSSC Documentation] CSSC is the GNU implementation of SCCS
- [http://basepath.com/aup/talks/SCCS-Slideshow.pdf The Source Code Control System] Rochkind 1975
In his 1975 paper Rochkind describes SCCS as a “radical departure from conventional methods for controlling source code”. SCCS was initially implemented in 1972 on the IBM 370. The implementation language was SNOBOL. Rochkind was an employee of Bell Laboratories and SCCS was soon ported to Unix where it became a cornerstone of the “Programmer’s Workbench”, a suite of software distributed with early Unix.
The radical departure of SCCS appears to be the decision to store every version of each file under source control. This is done in a space efficient manner by means of deltas: the original file is stored with a delta for each change. To get the most recent version of the file all of the deltas must be applied to the original file. Also stored with each delta is the name of the user who made the change, the date and time of the change, and a user supplied comment explaining the change.
SCCS introduces a file format so that the original file, the deltas, and the meta-information can all be stored in a single history file. If the original file was {{foo.c}}, a common early convention was for the history file to be named {{s.foo.c}}. In the original Unix implementation the SCCS commands were standalone Unix commands. Starting with the version of SCCS which Allman wrote for BSD Unix in 1980 the SCCS commands became arguments or subcommands to a {{sccs}} executable.
Here is an sample SCCS session. The file {{foo.txt}} is put under source control. It is then checked out, edited, and the change committed. Finally a non-editable copy of the most recent version is checked out.
code $ echo “foo” > foo.txt $ sccs admin -ifoo.txt s.foo.txt $ rm foo.txt $ sccs get -e s.foo.txt $ vi foo.txt $ sccs delta s.foo.txt $ sccs sccsdiff -r1.1 -r1.2 s.foo.txt $ sccs get -p s.foo.txt > foo.txt /code
The SCCS history file format consists of fields separated by the Ctrl-A (ASCII 1) characters. The fields are divided into headers, which contain the meta-information, and the body, which contains the original file and the deltas. The original file is given revision number 1, and the number is incremented with each change.
The body consists of the original file interspersed with nested insert blocks and delete blocks. The format for an insert block is
code ^AI REV added line one added line two … ^AE REV /code
where REV is the revision number for which the lines were added. Similarly the format for a delete block is
code ^AD REV deleted line one deleted line two … ^AE REV /code
When extracting a version of the file, the desired version is compared with each block. Insert blocks are ignored if they have a higher number than the desired version and delete blocks are ignored if they have a lower or equal number than the desired version.
# rcs + [#top rcs (1982)]
In RCS, the history file is always identified with a {{,v}} suffix; the history file for {{foo.txt}} is {{foo.txt,v}}. Because this convention is used consistently, RCS commands can take the original file as an argument instead of the history file like in SCCS.
One can keep the {{,v}} files in a separate directory. RCS has built in support for using a subdirectory named {{RCS}} in the same directory as the source. When this convention is used, it is not necessary to specify both the {{,v}} file and the source file when using {{rcs ci}} and {{rcs co}}. If the source code tree has subdirectories, each subdirectory should contain an {{RCS}} subdirectory.
RCS supports multiline commit messages and it adds the {{log}} command for getting all the commit messages for a file.
++ example session
Here is an example work session using RCS. It is equivalent to the SCCS work session in the previous section.
code $ echo “foo” > foo.txt $ rcs ci -i foo.txt $ rcs co -l foo.txt $ vi foo.txt $ rcs ci foo.txt $ rcs co foo.txt /code
{{make}} has a built-in rule for creating a file from its {{,v}} file. The file will be checked out as read-only.
++ rcs file format
- [http://linux.die.net/man/5/rcsfile man rcsfile] The RCS history file format
An RCS history file has four sections:
- head
- deltas
- description
- deltatexts
The head contains the revision number of the current version. If any of the revision numbers have been assigned symbolic names (i.e tags), they are listed here. If there
There is a delta section for each revision. It contains the time the revision was added to the history file and the author.
The description is a string describing the file. Strings are delimited by ampersands {{@}}. An ampersand in the string is escaped by doubling it.
There is a deltatext section for each revision. It contains a {{log}}, which is the commit message, and the {{text}}), which is either the full text of the revision or an {{ed}} style edit describing how to generate the revision from another revision. Both the {{log}} and the {{text}} are ampersand delimited strings with ampersands escaped by doubling.
Here is an example of a {{text}} which adds two lines after line 6:
code @a6 2 added line one added line two @ /code
Here is an example o a {{text}} which deletes two lines after line 6:
++ revision numbers and branching
RCS revision numbers consist of 2//n// positive integers joined by decimals. //n// is itself positive. By default the revision number given to a file when it is first placed under version control is 1.1.
RCS revision numbers with 2 integers refer to revisions on the trunk. RCS revision numbers with 4 integers refer to branches off the trunk. The first two integers indicate the trunk revision that is the root of the branch. RCS revision numbers with 6 integers refer to branches off of a branch of the trunk.
When a commit is made, by default the last integer of the revision is incremented.
When a branch is created off of a revision that does not have a branch, the revision number of the new revision is created from the revision number of the root of the branch by appending .1.1 to it. If the root revision already has a branch off of it, the new branch revision number will have a .2.1 appended to it.
# cvs + [#top cvs (1990)]
CVS uses RCS to manage the history of each file under version control.
How to set up a CVS repository:
code $ mkdir cvsroot $ export CVSROOT=/PATH/TO/cvsroot $ cvs init /code
For CVS commands to work, either the CVSROOT environment variable must be set or the location of the repository root must be passed to the command with each invocation using the {{-d}} option.
It is possible to set up a server on the repository host which listens on port 2041. The server uses {{ssh}} authentication, so the client must have an account on the host. To use the server, the client sets the {{CVSROOT}} environment variable to something like this:
code $ export CVSROOT=:pserver:foo.com:/PATH/TO/cvsroot /code
How to create a project in the repository:
code $ mkdir foo $ cd foo $ touch README $ cvs import foo FOO_CORP V1 /code
The 2nd and 3rd argument to {{cvs import}} are required and are used to create tags.
Here is an example of how to check out the {{foo}} project but name the working directory {{bar}}:
code $ cvs checkout -d bar foo /code
Files only needed to only needed to be added once, like Mercurial and unlike Git:
code $ cd bar $ vim Makefile $ cvs status $ cvs diff $ cvs add Makefile $ cvs commit -m ‘adding a Makefile’ $ cvs log /code
Branching is a three step process: (1) tag the commit you are branching from, (2) create the branch, and (3) update the working directory to the branch.
code $ cvs tag WUMPUSROOT $ cvs tag -r WUMPUSROOT -b WUMPUS $ cvs update -r WUMPUS /code
//How to merge//
# svn + [#top svn (2000)]
- [http://www.red-bean.com/kfogel/beautiful-code/bc-chapter-02.html Beautiful Code, Ch. 2: Subversion’s Delta Editor]
How to set up an SVN server:
code $ svnadmin create /PATH/TO/svn $ vim /PATH/TO/svn/conf/svnserve.conf $ vim /PATH/TO/svn/conf/passwd $ mkdir /tmp/empty $ svn import /tmp/empty file:///PATH/TO/svn/NAME $ svnserve -d -r /PATH/TO/svn –log-file /PATH/TO/svn/svnserve.log $ svn co svn://localhost/NAME /code
When editing {{svn/conf/svnserve.conf}}, add these lines to the {{[general]}} section:
code anon-access = none auth-access = write password-db = passwd /code
In {{svn/conf/passwd}}, create a username and password:
To have {{svnserver}} start automatically at boot on an Ubuntu server, put [http://odyniec.net/articles/ubuntu-subversion-server/svnserve this script] in {{/etc/init.d}}. Change the value of {{DAEMON_ARGS}} from {{-d -r /usr/local/svn/repos}} to {{-d -r /PATH/TO/svn –log-file /PATH/TO/svnserve.log}}.
# archive-patch-tools + [#top Archive and Patch Tools]
[#diff diff] | [#cpio cpio] | [#diff3 diff3] | [#ar ar] | [#tar tar] | [#patch patch] | [#zip zip] | [#diffstat diffstat] | [#jar jar] | [#rsync rsync] | [#colordiff colordiff]
# diff + [#top diff (1974)]
- [http://www.cs.dartmouth.edu/~doug/diff.ps An Algorithm for Differential File Comparison] Hunt & McIlroy 1976
- [http://linux.die.net/man/1/diff man diff]
To implement an efficient version control system one needs to find a minimal delta or difference between two similar text files. The problem led to the development of the Unix {{diff}} utility. Regarding a file as a sequence of lines, the problem can be treated as an example of the [http://en.wikipedia.org/wiki/Longest_common_subsequence_problem longest common subsequence problem]. The standard solution to this problem has O(nm) performance in both time and space, where {{n}} and {{m}} are the lengths of the two files. To facilitate quick comparison of lines, each line is replaced with a hash code. When implementing {{diff}} McIlroy developed an algorithm that was more efficient than the standard solution in most cases.
The standard {{diff}} notation prefixes lines with < and > to indicate whether the line originated in the first or second file. It also uses the letters {{a}}, {{c}}, and {{d}} to indicate lines being added, changed, or deleted:
code $ echo “foo” > foo.txt
$ echo “bar” > bar.txt
$ diff foo.txt bar.txt 1c1
< foo
bar
$ diff foo.txt /dev/null 1d0 < foo
$ diff /dev/null foo.txt 0a1
foo /code
These letters used in {{diff}} notation are also {{ed}} commands. In fact, {{diff -e}} will output an {{ed}} script which can be used to convert the first file into the second:
code $ diff -e foo.txt bar.txt > diff.ed
$ ( cat diff.ed ; echo “w” ) | ed foo.txt /code
The version of diff released with BSD 2.8 in 1981 added the {{-c}} option to show three lines of context around each change. This is called the //context format//.
The BSD 2.8 {{diff}} also added an {{-r}} option to perform a recursive diff on directories.
In 1990 the {{-u}} option was added, which gives a diff in//unified format//. In the //context format//, if a line is changed, the context is repeated: once around the old version of the line and once around the new. The uniformed format puts both version of the line in the same context, reducing the size of the diff file.
The {{-C NUM}} and {{-U NUM}} options are like the {{-c} and {{-u}} options, except that they show {{NUM}} lines of context.
//normal format://
code $ sed s/^root:/ROOT:/ /etc/passwd > /tmp/passwd
$ diff /etc/passwd /tmp/passwd 12c12
< root:*:0:0:System Administrator:/var/root:/bin/sh
ROOT:*:0:0:System Administrator:/var/root:/bin/sh /code
//ed script format://
code $ sed s/^root:/ROOT:/ /etc/passwd > /tmp/passwd
$ diff -e /etc/passwd /tmp/passwd 12c ROOT:*:0:0:System Administrator:/var/root:/bin/sh . /code
//context format://
code $ sed s/^root:/ROOT:/ /etc/passwd > /tmp/passwd
$ diff -c /etc/passwd /tmp/passwd *** /etc/passwd 2013-10-24 17:38:39.000000000 -0700 — /tmp/passwd 2014-04-26 12:57:57.000000000 -0700
*** 9,15 **** # Open Directory. ## nobody::-2:-2:Unprivileged User:/var/empty:/usr/bin/false ! root::0:0:System Administrator:/var/root:/bin/sh daemon::1:1:System Services:/var/root:/usr/bin/false _uucp::4:4:Unix to Unix Copy Protocol:/var/spool/uucp:/usr/sbin/uucico _taskgated::13:13:Task Gate Daemon:/var/empty:/usr/bin/false — 9,15 —- # Open Directory. ## nobody::-2:-2:Unprivileged User:/var/empty:/usr/bin/false ! ROOT::0:0:System Administrator:/var/root:/bin/sh daemon::1:1:System Services:/var/root:/usr/bin/false _uucp::4:4:Unix to Unix Copy Protocol:/var/spool/uucp:/usr/sbin/uucico _taskgated::13:13:Task Gate Daemon:/var/empty:/usr/bin/false /code
//unified format://
code $ sed s/^root:/ROOT:/ /etc/passwd > /tmp/passwd
$ diff -u /etc/passwd /tmp/passwd — /etc/passwd 2013-10-24 17:38:39.000000000 -0700 +++ /tmp/passwd 2014-04-26 12:57:57.000000000 -0700 @@ -9,7 +9,7 @@ # Open Directory. ## nobody::-2:-2:Unprivileged User:/var/empty:/usr/bin/false -root::0:0:System Administrator:/var/root:/bin/sh +ROOT::0:0:System Administrator:/var/root:/bin/sh daemon::1:1:System Services:/var/root:/usr/bin/false _uucp::4:4:Unix to Unix Copy Protocol:/var/spool/uucp:/usr/sbin/uucico _taskgated::13:13:Task Gate Daemon:/var/empty:/usr/bin/false /code
//recursive format://
code $ mkdir /tmp/a /tmp/b
$ cp /etc/passwd /tmp/a
$ $ sed s/^root:/ROOT:/ /etc/passwd > /tmp/b/passwd
$ diff -r /tmp/a /tmp/b diff -r /tmp/a/passwd /tmp/b/passwd 12c12
< root:*:0:0:System Administrator:/var/root:/bin/sh
ROOT:*:0:0:System Administrator:/var/root:/bin/sh /code
# cpio + [#top cpio (1977)]
- [http://linux.die.net/man/1/cpio man cpio]
- [http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_07 cpio file format (POSIX 2008)]
An ancient and to most people unfamiliar Unix archiving tool which is roughly equivalent to {{tar}}. The suffix {{.cpio}} is often used for {{cpio}} archive files.
The format is used by RPM packages, though RPM 5.0 and later also support the {{xar}} format. The Linux kernel since version 2.6 has a cpio archive called {{initramfs}} which it uses during the boot process. {{cpio}} is also used by the Mac OS X {{.pkg}} format.
The {{cpio}} file format is similar to the {{tar}} file format in that for each file which is added to an archive, a header and the file contents are appended to the archive file. In the case of {{cpio}} the header is smaller (76 bytes vs 512 bytes). This is in part because the header only contains the file name length; the actual file name is appended to the archive file between the header and the file contents. By contrast the {{tar}} format stores the name in fixed length fields, putting a limit on the possible path length. Another different is the {{cpio}} format lacks a checksum.
||||||||~ header format|| ||~ offset||~ length||~ field||~ description|| ||0||6||cmagic||The identifying value “070707”|| ||6||6||cdev|| || ||12||6||cino||cdev and cino together must be unique for each file in the archive|| ||18||6||cmode|| || ||24||6||cuid|| || ||30||6||cgid|| || ||36||6||cnlink||number of links to the file in the archive; can be incorrect if the -a flag was used to append files|| ||42||6||crdev||a place for implementations to store character or block special file information|| ||48||11||cmtime|| || ||59||6||cnamesize|| || ||65||11||c_filesize|| ||
Another difference between {{tar}} and {{cpio}} is that whereas {{tar}} takes the files to be archived on the command line, recursively descending any arguments which are directories, {{cpio}} when used with the {{-o}} flag takes its list of files to be archived from standard input. {{cpio}} was designed to be used with the {{find}} command. Similarly when using the {{i}} flag {{cpio}} reads the files to be extracted from an archive from standard input.
# diff3 + [#top diff3 (1979)]
- [http://linux.die.net/man/1/diff3 man diff3]
{{diff3}} displays the differences between three versions of the same file.
The three way diff is the foundation of branch merging. A two way diff is insufficient for merging because deleting a line in one branch looks like adding a line in the other branch. Only by comparing both branches with the original can these two cases be distinguished.
{{diff3}} has three basic invocations:
code diff3 EDIT1 ORIG EDIT2 diff3 -e EDIT1 ORIG EDIT2 diff3 -m EDIT1 ORIG EDIT2 /code
The first invocation writes a description of the three-way diff to standard out.
The second invocation writes an {{ed}} script to standard out which will merge the changes in EDIT2 to EDIT1.
The third invocation performs the merge. It writes a version of the file with changes from both EDIT1 and EDIT2 to standard out.
Here is an example of the output format used by the first invocation:
code $ cat /tmp/orig.txt a b c d e
$ cat /tmp/edit1.txt a b1 c d e f
$ cat /tmp/edit2.txt a b c d1 e
$ diff3 /tmp/edit1.txt /tmp/orig.txt /tmp/edit2.txt ====1 1:2c b1 2:2c 3:2c b ====3 1:4c 2:4c d 3:4c d1 ====1 1:6c f 2:5a 3:5a /code
Each hunk of the {{diff3}} output starts with four hyphens. All of the hunks in the example above are two-way hunks, meaning that two of the three files are the same. In this case the number of the differing file as it appears in the {{diff3}} arguments is placed after the hyphens.
Here is an example of a three-way hunk, where all three files differ and no number is placed after the hyphens:
code $ cat /tmp/orig.txt a
$ cat /tmp/edit1.txt
a1
$ cat /tmp/edit2.txt a2
$ diff3 /tmp/edit1.txt /tmp/orig.txt /tmp/edit2.txt
1:1c a1 2:1c a 3:1c a2 /code
# ar + [#top ar (1979)]
- [http://linux.die.net/man/1/ar man ar]
A tool on Unix systems to create static libraries from compiled objects. In other words, to create a {{.a}} file from a set of {{.o}} files. The format is understood by the linker—which these days is usually built into the compiler—and the loader {{ld}}.
The command line interface is broadly similar to tar. Here is how to create an archive; remove files from an archive; list the archive contents; extract files from an archive:
code ar -c NAME.a FILE … ar -d ARCHIVE FILE … ar -t ARCHIVE ar -x ARCHIVE FILE … /code
The {{ar}} file format is not standardized and may differ between systems.
The file format used by GNU {{ar}} on Linux starts with the new line terminated string “!”.
Each file starts with a 60 bytes header, followed by the file contents. The header has the following fixed-width fields:
||~ offfset||~ length||~ name|| ||0||16||file name in ASCII|| ||16||12||file modification timestamp|| ||28||6||uid|| ||34||6||gid|| ||40||8||file mode|| ||48||10||file size in bytes|| ||58||2||0x60 0x0A||
The space allocated for the file name in the header is quite short. GNU {{ar}} actually stores a special file named @@”//”@@ in the archive with a new line separated list of file names. A header can reference a name in this special file by storing “/” and a the decimal offset in the @@”//”@@ file of the file name. When file names are stored directly in the header, a “/” is used to mark the end of the file and the rest of the field is space padded. This supports spaces in the file name.
GNU {{ar}} also stores a special file named “/” is the archive for a symbol table. The format is
- a 32-bit integer containing the number of symbols
- a list of 32-bit integers, one for each symbol, containing the offset of the header in the archive for the file containing the symbol
- a list of null terminated strings, in the same order as the previous list, containing the symbol names
# tar + [#top tar (1979)]
- [http://linux.die.net/man/1/tar man tar]
The more portable twin of {{ar}}. Originally used for creating and using magnetic tape archives.
How to create a tar file; list the contents of a tar file; compare a tar file with the file system; and extract the contents of a tar file:
code tar [-]cf NAME.tar DIR tar [-]tf TARFILE tar [-]df TARFILE [DIR] tar [-]xf TARFILE /code
The {{-v}} option can be used with {{-c}} or {{-x}} to write the files being added or extracted to standard error.
Tar files store the files in sequential order. Each file is precede by a 512 byte header. The file itself is null byte padded to a multiple of 512 bytes.
Tar can write to and read from stdout. The following two invocations behave identically:
code tar cf - . | (cd DIR ; tar xf -) tar cf . - | tar xf - -C DIR /code
Tar can append data to an existing tar file. These commands append the contents of a directory to a tar file; append the contents of the directory which are newer than what is already on a tarfile; append subsequent tar files to the first tar file:
code tar [-]rf TARFILE DIR tar [-]uf TARFILE DIR tar [-]Af TARFILE1 TARFILE2 … /code
How to create a compressed tar file:
code tar [-]czf NAME.tar.gz tar [-]cjf NAME.tar.bz2 tar [-]cJf NAME.tar.xz /code
In 1988 POSIX extended the format of the header block in a backwardly compatible way. Additional header type flags were added in 2001.
||||||||~ header format|| ||~ offset||~ length||~ original format||~ ustar|| ||0||100||file name|| || ||100||8||file mode|| || ||108||8||owner user id|| || ||116||8||group id|| || ||124||12||file size in bytes|| || ||136||12||last modification time|| || ||148||8||header checksum|| || ||156||1||type flag|| || ||157||100||name of linked file|| || ||257||6|| ||"ustar”|| ||263||2|| ||"00”|| ||265||32|| ||owner user name|| ||297||32|| ||group name|| ||329||8|| ||device major number|| ||337||8|| ||device minor number|| ||345||155|| ||filename prefix||
||||||||~ header type flags|| ||~ flag||~ original meaning||~ ustar||~ 2001|| ||’\0’||normal file|| || || ||’0’||normal file|| || || ||’1’||hard line|| || || ||’2’||symlink|| || || ||’3’|| ||character device|| || ||’4’|| ||block device|| || ||’5’|| ||directory|| || ||’6’|| ||FIFO|| || ||’7’|| ||contiguous file|| || ||’g’|| || ||global extended header|| ||’x’|| || ||extended header for the next file||
# patch + [#top patch (1985)]
- [http://linux.die.net/man/1/patch man patch]
The {{patch}} command can apply the output of {{diff}} to the file that was the first argument of {{diff}} to recover the file that was the second argument of {{diff}}. {{patch}} reads the output of {{diff}} from standard input:
code $ echo “foo” > foo.txt $ echo “bar” > bar.txt $ diff foo.txt bar.txt > foo.patch $ patch foo.txt < foo.patch patching file foo.txt $ cat foo.txt bar /code
The above is only a slight improvement over what could have been achieved with {{diff -e}} and {{ed}}. The novelty of {{patch}} is its ability to apply a patch file to an entire directory:
code $ mkdir old $ echo “bar” > old/bar.txt $ echo “baz” > old/baz.txt $ cp -R old new $ echo “qux” > new/bar.txt $ diff -Naur old new > foo.patch $ rm -rf fnew $ patch -Np0 < foo.patch patching file old/bar.txt $ cat old/bar.txt qux /code
This is a good way to create a patch file:
When creating the patch file with {{diff}}, the {{-u}} or {{-c}} flags seem to be necessary so that {{patch}} has the file names. The {{-N}} flag is necessary if files are added or removed. The {{-a}} flag prevents {{diff}} from skipping files which it thinks are binary.
If the {{diff}} was performed outside of the directories, then the {{patch}} should be performed outside of the directory to be patched with the {{-p0}} flag. Optionally the {{patch}} can be performed inside the directory to be patched with the {{-p1}} flag. The {{-N}} flag instructs {{patch}} to not make a change if the patch appears to be reversed or already applied.
# zip + [#top zip (1989)]
- [http://linux.die.net/man/1/zip man zip]
{{zip}} combines file compression and archiving. It is a better choice for sharing files with Windows hosts than {{tar}}, which most Windows hosts don’t have installed.
code zip [-r] [-0] ARCHIVE FILE … zip -d ARCHIVE FILE … zip -u ARCHIVE [FILE …]
unzip -l ARCHIVE unzip ARCHIVE [FILE …] /code
Compression is the DEFLATE algorithm, or no compression if the {{-0}} flag is used.
{{zip}} stores the file name, file size, and last modification time of the file. The information is in a header which precedes the file itself and in the “central directory” at the end of the file.
By default {{zip}} does not recursively descend directories, adding their contents to the archive. Use the {{-r}} flag to get this behavior.
# diffstat + [#top diffstat (1992)]
Summarizes a recursive {{diff}} on two directories. It lists the files that were modified, added, or deleted with the number of lines which changed.
# jar + [#top jar (1995)]
{{jar}} supports some of the {{tar}} commands:
code jar cf NAME.jar DIR jar tf JARFILE jar xf JARFILE jar uf JARFILE DIR /code
{{jar}} can write to and read from stdout; the syntax is different from {{tar}}:
code jar c . | (cd DIR ; jar x) jar c . | jar x -C DIR /code
Use {{jar -e}} to make a jar file runnable by {{java}}. The argument to {{-e}} is a class with a {{main}} routine which will be used as the entry point.
code $ mkdir
$ cat > foo/A.java package foo;
public class A { public static void main(String[] args) { System.out.println(“A”); } }
$ sed s/A/B/ foo/A.java > foo/B.java
$ javac foo/*.java
$ jar cef foo.A foo.jar foo
$ java -jar foo.jar
A
/code
A jar file is a zip file; {{unzip}} can also be used to extract the contents. {{jar}} stores extra information about the jar file in {{META-INF/MANIFEST.MF}}:
code $ unzip foo.jar
$ cat META-INF/MANIFEST.MF Manifest-Version: 1.0 Created-By: 1.6.0_26 (Sun Microsystems Inc.) Main-Class: foo.A /code
# rsync + [#top rsync (1996)]
- [http://linux.die.net/man/1/rsync man rsync]
- [http://rsync.samba.org/tech_report/tech_report.html the rsync algorithm]
A tool for copying files and directories between hosts. Usually it uses {{ssh}}. It is faster than {{scp}} when some of the files are already on the destination or when copying files that have been modified.
Here is the usage for putting and getting:
code rysnc -a PATH … HOST:PATH rsync -a HOST:’PATH …’ PATH /code
The {{-a}} flag is equivalent to the flags {{-rptoglD}} which (1) recursively copy the contents of directories, (2) copy file permissions, (3) copy file times, (4) copy owner, (5) copy group, (6) copy symlinks, and (7) copy special devices.
Other useful flags are {{-v}} for verbose mode and {{@@–@@exclude}} which takes a file glob pattern to specify files to skip.
If the source and target paths have the same basename, then {{rsync}} will copy the contents of the source into the contents of the target. If the basenames are different, {{rsync}} will create a directory with the same name as the source inside the target. This behavior can be suppressed by putting a trailing slash / on the end of the source.
{{rsync}} can be used to backup a directory on a remote host. With the {{@@–@@backup}} flag, files which are already on the destination but have been modified on the source will be copied into a separate incremental directory with a tilde (~) suffix. The {{@@–@@backup-dir}} flag can be used to specify a different incremental directory.
# colordiff + [#top colordiff (2002)]
A version of {{diff}} which colorizes the output. It takes the same options as {{diff}}.