Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Take a look at part about version control for single developer in my answer to "<a href="https://stackoverflow.com/questions/802573/difference-between-git-and-cvs/824241#824241">Difference between GIT and CVS</a>" question here on StackOverflow. Some of those issues do still apply also to Subversion versus Git (or other distributed VCS: Mercurial, Bazaar, or less known: Monotone, Darcs), even if Subversion is improvement over CVS.</p> <p><strong>DISCLAIMER:</strong> I use Git (so I am biased), and know Subversion only from documentation (and other resources), never having used it myself. I might be then mistaken about Subversion capabilities.</p> <p>Below there are list of differences between Git over Subversion for a single developer, on single machine (single account):</p> <ul> <li><p><strong>Setting up repository.</strong> Git stores repository in <code>.git</code> directory in top directory of your project. Starting a new project from unversioned tree of files is as easy as doing "git init" in a top directory of your project (and then of course "git add ." to add files, and e.g. "git commit -m 'Initial commit'" to create first commit).</p> <p>In Subversion (in any centralized version control system) you need to set up central repository (unless you did that earlier) using "svnadmin create" (well, you need to do that only once). Then you have to import files into Subversion using "svn import" (or "svn add")... But note that after the import is finished, the original tree is <em>not</em> converted into a working copy. To start working, you still need to "svn checkout" a fresh working copy of the tree.</p></li> <li><p><strong>Repository and repository metadata.</strong> Git stores both repository (i.e. information about revisions and branches, etc.) and repository metadata (e.g. your identity, list of ignored files, which branch is currently checked out) in <code>.git</code> directory in <strong><em>top directory</em></strong> of your projects. </p> <p>Subversion stores repository in separate area you have to put for that purpose, and stores repository metadata (e.g. where central repository is, identity used to contact central repository, and I think also properties like <code>svn:ignore</code>) are stored in <code>.svn</code> directory in <strong><em>each directory</em></strong> of your project. <em>(Note that Subversion stores pristine copy of your checkout, to have fast "svn status" and "svn diff")</em></p></li> <li><p><strong>Naming revisions / version numbers.</strong> Subversion uses global revision identifiers in the form of single number specifying revision (so you can for example refer to r344, revision 344). Subversion also supports a few symbolic revision specifiers: HEAD, BASE, COMITTED, PREV.</p> <p>In Git each version of a project (each commit) has its unique name given by 40 hexdigits SHA-1 id; usually first 7-8 characters are enough to identify a commit (you can't use simple numbering scheme for versions in distributed version control system -- that requires central numbering authority). But Git offers also other kinds of revision specifiers, for example <code>HEAD^</code> means parent of a current commit, <code>master~5</code> means revision 5 ancestors back (in straight first-parent line) from top commit on a 'master' branch, <code>v1.6.3-rc2</code> might mean revision tagged <code>v1.6.3-rc2</code>.</p> <p>See also <a href="http://blogs.gnome.org/newren/2008/03/31/many-different-kinds-of-revision-specifiers/" rel="nofollow noreferrer">Many different kinds of revision specifiers</a> blog post by Elijah Newren.</p></li> <li><p><strong>Easy branching and merging.</strong> In Git creating and merging branches is very easy; Git remembers all required info by itself (so merging a branch is as easu as "git merge branchname")... it had to, because distributed development naturally leads to multiple branches. Git uses heuristic similarity-based rename detection, so it while merging it can deal with the case where one side renamed file (and other similar cases related to renaming). This means that you are able to use <em>topic branches</em> workflow, i.e. develop a separate feature in multiple steps in separate feature branch.</p> <p>Branches have an unusual implementation in Subversion; they are handled by a namespacing <em>convention</em>: a branch is the combination of revisions within the global repository that exist within a certain namespace. Creating a new branch is done by copying an existing set of files from one namespace to another, recorded as a revision itself. Subversion made it easy to create new branch... but up till version 1.5 you had to use extra tools such as SVK or svnmerge extensions to be able to <em>merge</em> easily. Subversion 1.5 introduced <code>svn:mergeinfo</code> property, but even then merging is slightly more complicated than in Git; also you need to use extra options to show and make use of merge tracking information in tools such as "svn log" and "svn blame". I have heard that it doesn't work correctly in more complicated situations (criss-cross merge), and cannot deal currently with renames (there is even chance of silent corruption in such case). See also (for example) <a href="http://article.gmane.org/gmane.comp.version-control.git/127461" rel="nofollow noreferrer" title="Re: Merging in Subversion 1.5 (was: Re: Using git to track my PhD thesis, couple of questions)">this post on git mailing list</a> by Dmitry Potapov, explaining intended use case for <code>svn:mergeinfo</code> and its (current) limitations.</p></li> <li><p><strong>Tagging.</strong> In Git tags are <strong><em>immutable</em></strong>, can have comment associated with them, and can be signed using PGP/GPG signature (and verified). They are made using "git tag". You can refer to revision using tag name. </p> <p>In Subversion tags use the same path_info-like namespace <strong><em>convention</em></strong> as branches (recommended convention is <code>svnroot/project/tags/tagname</code>), and are not protected against changing. They are made using "svn copy". They can have comment associated with [the commit creating a tag].</p></li> <li><p><strong>Keyword expansion.</strong> Git offers very, very limited set of keywords as compared to Subversion (by default). This is because of two facts: changes in Git are per repository and not per file, and Git avoids modifying files that did not change when switching to other branch or revinding to other point in history. If you want to embed revision number using Git, you should do this using your build system, e.g. following exaple of GIT-VERSION-GEN script in Linux kernel sources and in Git sources. There is also <code>'ident'</code> gitattribute which allows expansion of "$Id$" keyword to SHA-1 identifier of <em>file contents</em> (not identifier of a commit).</p> <p>Both Git and Subversion do keyword expansion only on request.</p></li> <li><p><strong>Binary files.</strong> Both Git and Subversion deal correctly woth binary files. Git does binary file detection using similar algorithm to the one used by e.g. GNU diff, unless overriden on per-path basis using gitattributes. Subversion does it in slightly different way, by detecting type of file during adding file and setting <code>svn:mime-type</code> property, which you can then modify. Both Git and Subversion can do <strong><em>end of line character conversion</em></strong> on demand; Git has additionally <code>core.safecrlf</code> config option which warn and <em>prevent irreversible change</em> (all CR to all CRLF is reversible, mixed CR and CRLF is not reversible).</p></li> <li><p><strong>Ignoring files.</strong> Git stores ignore patterns using in-tree <code>.gitignore</code> file, which can be put under version control and distributed; it usually contain patterns for build products and other generated files, and in <code>.git/info/excludes</code> file, which usually contains ignore patterns specific to user or system, e.g. ignore pattersn for backup files of your editor. Git patterns apply recursively, unless patter contain directory delimiter i.e. forward slash character '/', then it is anchored to directory <code>.gitignore</code> file is; to top dir for <code>.git/info/excludes</code>. (There is also <code>core.excludesfile</code> configuration variable; this variable can exist in per-user <code>~/.gitconfig</code> configuration file, and point to per-user ignore file).</p> <p>Subversion uses <code>global-ignores</code> runtime configuration option (which generally apply to particular computer or by a particular user of a computer), and "<code>svn:ignore</code>" property on SVN-versioned directories. However unlike the <code>global-ignores</code> option (and in <code>.gitignore</code>), the patterns found in the "<code>svn:ignore</code>" property apply only to the directory on which that property is set, and not to any of its subdirectories. Also, Subversion does not recognize the use of the <code>!</code> prefix to pattern as exception mechanism.</p></li> <li><p><strong>Amending commits.</strong> distributed VCS such as Git act of publishing is separate from creating a commit, one can change (edit, rewrite) unpublished part of history without inconveniencing other users. In particular if you notice typo (or other error) in commit message, or a bug in commit, you can simply use "git commit --amend". <em>(Note: technically it is re-creating a commit, not changing existing commit; the changed commit has different identifier)</em>.</p> <p>Subversion allows only to modify commit message after the fact, by changing appropriate property.</p></li> <li><p><strong>Tools.</strong> On one hand Git offers richer set of commands. One of more important is "git bisect" that can be used to find a commit (revision) that introduced a bug; if your commits are small and self-contained it should be fairly easy then to discover where the bug is.</p> <p>On the other hand, Subversion because exists longer, has perhaps wider set of third party tools, and Subversion support in tools, than Git. Or at least more mature. Especially on MS Windows. </p></li> </ul> <hr> <p>And there is another issue, which might be quite important later:</p> <ul> <li><p><strong>Publishing repository.</strong> If (when?) at some time you would want to share your repository, turning it from one-person project developed on a single home computer, to something other contribute, with Git is as simple as creating empty repository on server or on one of existing git hosting sites / software hosting sites with git support (like <a href="http://repo.or.cz" rel="nofollow noreferrer">http://repo.or.cz</a>, <a href="http://github.com" rel="nofollow noreferrer">GitHub</a>, <a href="http://gitorious.org" rel="nofollow noreferrer">Gitorious</a>, InDefero; more--also for other DVCS--are listed in <a href="https://stackoverflow.com/questions/2274191/subversion-version-of-github/2275657#2275657">that answer</a>), and then pusing your project to this public repository.</p> <p>I guess it is more complicated with Subversion, if you don't start at software hosting site with Subversion support (like SourceForge) from the beginning, unless you don't want to preserve existing revision history. On the other hand for example Google Code suggest to use <strong><em>svnsync</em></strong> tool (part of the standard Subversion distribution), as explained in <a href="http://www.dataliberation.org/google/code-project-hosting" rel="nofollow noreferrer">Google Products‎ > ‎Project Hosting (the Data Liberation Front)</a> article.</p></li> </ul> <hr> <p>Take a look also at <a href="http://whygitisbetterthanx.com/" rel="nofollow noreferrer">http://whygitisbetterthanx.com/</a> site. </p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload