Core commands:
| svn checkout svn+ssh://USER@MACHINE.ORG/PATH/TO/MODULE/trunk MODULE | eg clone ssh://USER@MACHINE.ORG/PATH/TO/MODULE.REPO |
| svn status | eg status |
| svn update | eg update |
| svn diff | eg diff |
| svn add FILE | eg add FILE |
| svn commit | eg commit |
| eg push |
Other common commands:
| svn blame FILE | eg blame FILE |
| svn cat FILE | eg cat FILE |
| svn help [COMMAND] | eg help [COMMAND] |
| svn info | eg info |
| svn mv OLDNAME NEWNAME | eg mv OLDNAME NEWNAME |
| svn resolved PATH... | eg resolved PATH... |
| svn revert PATH... | eg revert PATH... |
| svn rm FILE... | eg rm FILE... |
SUMMARY: checkout/clone and commit are slightly different, the rest of the basic commands are the same.
Switch to an older version, or possibly a newer version (see the Revision specifiers section below).
| svn update -r REVISION | eg switch REVISION |
Switching the working copy over to another branch
| svn switch svn+ssh://USER@SVN.MACHINE.ORG/PATH/TO/MODULE/branches/BRANCHNAME | eg switch BRANCHNAME |
Create a tag in a public repository
| svn cp . svn+ssh://USER@SVN.MACHINE.ORG/PATH/TO/MODULE/tags/TAGNAME | eg tag TAGNAME |
| eg push --tag TAGNAME |
Create a local tag that does not appear in a public repository
| Not Available | eg tag TAGNAME |
Create a branch in a public repository
| svn cp . svn+ssh://USER@SVN.MACHINE.ORG/PATH/TO/MODULE/branches/BRANCHNAME | eg branch BRANCHNAME |
| eg push --branch BRANCHNAME |
Create a local branch that does not appear in a public repository
| Not Available | eg branch BRANCHNAME |
For the next three examples, I am assuming that the distinction between recording locally or centrally is not relevant. If you want to record changes on some public server, follow each of the eg commit steps with an 'eg push'
Record changes, using the log message specified on the command line
| svn commit -m MESSAGE | eg commit -m MESSAGE |
Record changes, using the text from a specified file for the log message
| svn commit -F FILE_WITH_LOG_MESSAGE | eg commit -F FILE_WITH_LOG_MESSAGE |
Record changes to just certain files
| svn commit FILE1 FILE2... | eg commit FILE1 FILE2... |
Record changes locally only (perhaps you are offline or just need to checkpoint your work without going through a peer review yet)
| Not Available | eg commit |
Modify the last commit (possibly including extra files, more changes, or just a different log message); note that this is a bad idea if the previous commit has been pushed to a public location.
| Not Available | eg commit --amend |
Stash changes away and return to a clean slate
| cd /PATH/TO/TOP/OF/REPOSITORY | eg stash [save OPTIONAL STASH DESCRIPTION TEXT] |
| svn diff > NAME-OF-STASH.PATCH |
Applying an old stash
| cd /PATH/TO/TOP/OF/REPOSITORY | eg stash apply [OPTIONAL STASH DESCRIPTION TEXT] |
| patch -p0 < NAME-OF-STASH.PATCH |
Listing available stashes
| ls *.PATCH # Hope you don't have lots of other patches | eg stash list |
Revert changes to files foo.cc and baz.py since the last commit
| svn revert foo.cc baz.py | eg revert foo.cc baz.py |
Revert all the changes since REVISION (see the Revision specifiers section below)
| cd /PATH/TO/TOP/OF/REPOSITORY | eg revert --since REVISION |
| svn diff -r REVISION | patch -p0 -R |
Revert all the changes made in REVISION (OLDREVISION below is obtained by taking REVISION and subtracting one; see the Revision specifiers section below)
| cd /PATH/TO/TOP/OF/REPOSITORY | eg revert --in REVISION |
| svn diff -r OLDREVISION:REVISION | patch -p0 -R |
To understand the form of REVISION, REV1, etc. in this section, see the Revision specifiers section below.
Show the changes made since a specified REVISION, in patch format
| svn diff -r REVISION | eg diff REVISION |
Show the changes between REV1 and REV2 to FILE
| svn diff -r REV1:REV2 FILE | eg diff REV1 REV2 FILE |
Show the changes between the branch BRANCH and revision REVISION (for the subversion case, we have to assume that REVISION was a change made to trunk, otherwise the svn command changes).
| svn diff svn+ssh://USER@SVN.MACHINE.ORG/PATH/TO/MODULE/branches/BRANCH svn+ssh://USER@SVN.MACHINE.ORG/PATH/TO/MODULE/trunk@REVISION | eg diff BRANCH REVISION |
Show the changes between the branch BRANCH and the working copy
| Not Available | eg diff BRANCH |
Show the changes between the tag TAG and mainline development (trunk for svn and master for eg)
| svn diff svn+ssh://USER@SVN.MACHINE.ORG/PATH/TO/MODULE/tags/TAG svn+ssh://USER@SVN.MACHINE.ORG/PATH/TO/MODULE/trunk | eg diff TAG master |
Show the changes between the tag TAG and the working copy
| Not Available | eg diff TAG |
Show the changes on the current branch since 2 commits before the last one on this branch
| svn log # Look for the revision corresponding to two commits ago | eg diff HEAD~2 |
| svn diff -r REVISION_WE_LOOKED_UP |
Create a new empty repository and associated working copy
| svnadmin create /RANDOM/PATH/FOR/REPOSITORY | mkdir project |
| svn mkdir file:///RANDOM/PATH/FOR/REPOSITORY/project/{trunk,tags,branches} -m "Set up initial repository structure" | cd project |
| svn checkout file:///RANDOM/PATH/FOR/REPOSITORY/project/trunk project | eg init |
| cd project |
Create a new repository and associated working copy, based on an import of files in an existing directory
| svnadmin create /RANDOM/PATH/FOR/REPOSITORY | cd project |
| svn import project file:///RANDOM/PATH/FOR/REPOSITORY/project/trunk -m "Initial import of project" | eg init |
| rm -rf project | eg add . |
| svn checkout file:///RANDOM/PATH/FOR/REPOSITORY/project/trunk project | eg commit -m "Initial import of project" |
| cd project |
Merge all changes that were not previously merged in from branch BRANCH into the working copy
| svn info svn+ssh://USER@SVN.MACHINE.ORG/PATH/TO/MODULE/branches/BRANCH | eg merge BRANCH |
| <Somehow pick out which changes have not yet been merged in, to obtain the revision range REV1:REV2> | |
| svn merge -r REV1:REV2 svn+ssh://USER@SVN.MACHINE.ORG/PATH/TO/MODULE/branches/BRANCH |
Mark the current changes in some files as being "ready to be committed"
| Not Available | eg stage FILE1 FILE2... |
Get the changes to FILE1 and FILE2 that are staged (i.e. "ready to be committed")
| Not Available | eg diff --staged FILE1 FILE2 |
Get all unstaged changes (i.e. changes that haven't explicitly been marked as ready to be committed)
| Not Available | eg diff --unstaged |
Get all changes (both staged and unstaged) to a file
| Not Applicable | eg diff FILE |
Commit all changes (whether staged or not)
| Not Applicable | eg commit -a |
Commit only the staged changes
| Not Available | eg commit --staged |
Unstage the changes to a file
| Not Available | eg unstage FILE |
This is a feature of subversion that may be dropped in the future (look for "detachability" in the email pointed to by that link), in order to gain some of the advantages of other systems like git.
Get a copy of just one file, with no associated working copy
| svn export svn+ssh://USER@MACHINE.ORG/PATH/TO/MODULE/trunk/PATH/TO/FILE | Not Available |
Check out one subdirectory, and have it serve as a working copy
| svn checkout svn+ssh://USER@MACHINE.ORG/PATH/TO/MODULE/trunk/PATH/TO/SUBDIR | Not Available |
This section skips some of the more advanced pulling operations you can do with "refspecs", remote tracking branches, and named remote repositories.
Pull the changes from someone's published http repository (assumes they only have one branch in their repository, or that you have pulled from it before)
| Not Available | eg pull http://WWW.SERVER.ORG/~USER/PATH/TO/REPO.GIT |
Pull the changes from the stable branch of Bob's project in his home directory
| Not Available | eg pull --branch stable /HOME/BOB/PROJECT |
Pull changes from both the testing and funny-stuff branches of a fellow developer's repository on a remote machine (accessed via ssh), merging both branches into your working copy. Then after seeing the merge succeed and be committed, decide to undo the work.
| Not Available | eg pull --branch testing --branch funny-stuff USER@MACHINE.ORG:/PATH/TO/PROJECT |
| eg reset --working-copy ORIG_HEAD |
Publish a copy of your repository on the a machine you have ssh access to
| <Configure an svn server to run on the remote machine; see chapter 6 of the svnbook> | eg publish USER@EG.EXAMPLE.COM:PUBLIC_HTML/MY_COOL_PROJECT |
| ssh ADMIN@SVN.EXAMPLE.COM "svnadmin create /PATH/TO/REPOSITORIES/SVN-MIRROR" | |
| <Configure remote svn repository's pre-revprop-change and start-commit hook script to make the repository read-only, or deal with your "recipe for disaster"; see the repository replication section of the svnbook> | |
| svnsync initialize http://SVN.EXAMPLE.COM/SVN-MIRROR /PATH/TO/LOCAL/REPOSITORY --username SYNCUSER --password SYNCPASS | |
| svnsync synchronize http://SVN.EXAMPLE.COM/SVN-MIRROR --username SYNCUSER --password SYNCPASS |
Update the remote repository copy
| svnsync synchronize http://SVN.EXAMPLE.COM/SVN-MIRROR --username SYNCUSER --password SYNCPASS | eg push |
Getting a checkout based on the repository copy
| svn checkout http://SVN.EXAMPLE.COM/SVN-MIRROR/trunk PROJECTNAME | eg clone http://EG.EXAMPLE.COM/~USER/MY_COOL_PROJECT PROJECTNAME |
An important note: All of the steps below for eg can be done offline, disconnected from the original repository that you cloned from -- and as a side effect, the operations are also much faster in eg. For svn, log and update both require network connectivity to the original repository and operations are relatively slower. This speed and online vs. offline behavior of eg and svn is true of other operations as well, but the distinction is even more pronounced in this use case than in others.
Getting started at tracking down the buggy commit
| <Somehow determine a good revision from history, as well as the bad revision (usually the current one). Typically, one uses 'svn log' and one's own memory for this.> | <Somehow determine a good revision from history, as well as the bad revision (usually the current one). Typically, one uses 'eg log' and one's own memory for this.> |
| eg bisect start |
Doing the first split
| <Somehow determine a revision in the middle of the good and bad ones. If there are few commits on other branches, averaging the two might work. Otherwise, use 'svn log' and start counting.> | eg bisect bad [REVISION_OTHER_THAN_CURRENT_ONE] |
| svn update -r REVISION_IN_MIDDLE | eg bisect good REVISION |
If you have to manually test each revision, repeat the following steps as often as necessary:
Checking out a given split
| <Compile, link, test; see if this revision is good or bad.> | <Compile, link, test; see if this revision is good or bad.> |
If the most recently tested revision is good, do the following and jump back to the "checking out a given split" step above.
| <Somehow determine a revision in the middle of the new good one and the previously determined bad one. If there are few commits on other branches, averaging the two might work. Otherwise, use 'svn log' and start counting.> | eg bisect good |
| svn update -r REVISION_IN_MIDDLE |
If the most recently tested revision is bad, do the following and jump back to the "checking out a given split" step above.
| <Somehow determine a revision in the middle of the new bad one and the previously determined good one. If there are few commits on other branches, averaging the two might work. Otherwise, use 'svn log' and start counting.> | eg bisect bad |
| svn update -r REVISION_IN_MIDDLE |
If you have a script that can compile, link, and test whether a revision works, you can simply use:
Automate all the testing and splitting steps in a single command
| Not Available | eg bisect run NAME_OF_SCRIPT |
Returning the working copy to normal when you are done
| svn update | eg bisect reset |
Note: This section is not about reverting changes from previous commits by recording a new commit with the old contents. See the reverting changes section for that; this section is about actually removing recent commits from the current branch. This is rarely a good thing to do with commits that have been made available to other people (it can break future merging), but can come in quite handy for commits that have been kept local.
Remove the last 3 commits from the current branch, also returning the working copy to the state of the repository before the last 3 commits. (Note that HEAD always refers to the current branch in eg)
| Not Available | eg reset --working-copy HEAD~3 |
Remove the last 2 commits from the current branch, but leave the working copy as it is (could be used, for example, to turn the last two commits into a single commit).
| Not Available | eg reset HEAD~2 |
Retroactively place the last 6 commits of the current branch on a different branch, and switch to that branch
| Not Available | eg branch NEW_DIFFERENT_BRANCH |
| eg reset --working-copy HEAD~6 | |
| eg switch NEW_DIFFERENT_BRANCH |
Technically, one can also add commits to the current branch and move the current branch to match an entirely different branch...
Note: An independent patch set would typically be tracked in eg using a separate local branch with all the patches applied in order. This usually doesn't make sense in subversion, since branches are shared and global, so an independent patch set is typically kept as a series of files. One can use eg with a set of separate patch files easily, but maintaining a patch set as a separate branch in subversion makes no sense -- svn has no facility for updating the patches to be relative to new changes on trunk.
Using subversion, you must repeat the following sequence for each patch:
Update the next patch in the series (whose name we refer to as PATCH, as a placeholder)
| rsync -a ./ ../extra-working-copy | |
| patch -p1 < PATCH | |
| <Carefully check the patch output to see if there were any conflicts or hunks that did not apply. Manually fix up any such problems> | |
| diff -pru ../extra-working-copy ./ > PATCH |
Using eg, you can update the whole patch set as follows:
Take all the patches on the current branch since the branchpoint from BRANCH, and update the patches to be relative to the current tip of BRANCH.
| Not Available | eg rebase --against BRANCH |
With eg if any patches could not be automatically rewritten with the above command, then when the above command stops simply fix up the relevant files and then run
Resolving conflicts when rebasing
| Not Applicable | eg resolved FILE... |
| Not Available | eg rebase --continue |
Note: Using eg, there is a powerful --interactive flag to rebase that allows you to easily split, combine, remove, insert, reorder, or edit commits. Run 'eg help rebase' for details.
List all named remote repositories ('remotes' for short)
| Not Available | eg info |
Add a new remote, giving it an associated name
| Not Available | eg remote add REMOTENAME URL |
You can use the nickname of a remote repository in the place of a URL, but there are also some additional things you can do with remotes:
Create/update a local branch named REMOTENAME/BRANCH for each branch of a remote (such branches are called remote tracking branches)
| Not Available | eg fetch REMOTENAME |
Remote tracking branches can be used the same as normal branches (but it's bad form to checkout/switch to such branches and commit to them; create a separate branch instead). Some examples to make it clear:
List all remote tracking branches
| Not Available | eg branch -r |
Merge the remote tracking branch bob/stable into the current branch
| Not Available | eg merge bob/stable |
Get a history of the changes on the jim/eye-candy branch
| Not Available | eg log jim/eye-candy |
Create a new branch named my-testing based off of the remote tracking branch jenny/testing
| Not Available | eg branch my-testing jenny/testing |
Pull changes from the 'fixes' branch of a remote and merge it into the current branch (i.e. standard pull behavior) AND also update all remote tracking branches associated with the remote (i.e. act as if 'eg fetch REMOTENAME' was also run)
| Not Available | eg pull --branch fixes REMOTENAME |
Delete a named remote repository, including all related remote tracking branches (and any special configuration settings for the named remote)
| Not Available | eg remote rm REMOTENAME |
Grab updates from all(*) named remote repositories, i.e. run 'eg fetch REMOTE' for each remote
| Not Available | eg remote update |
Version control systems use different methods to refer to different versions of the repository. svn counts forward globally, while eg counts backwards relative to each branch. Thus a typical version for svn would be something like "218" while for eg it would be "master~23". You can use the "svn log" and "eg log" commands to get the name of a revision for a particular commit.
The tilde character ("~") is used in eg since minus signs can serve as dashes in branch names (master-23 could be a branch).
A few extra notable advantages not obvious from the list above:
For subversion:
For git: