Git is actually easier than svn
This might be seem to some like a bold or controversial statement, but git is easier to use than svn!
Note: I’m not claiming here that git is better, I’m claiming it’s easier to use.
I’ve found many articles that claim the contrary, yet either I have a completely different workflow, or most arguments are outdated.
Also notice that both programs are moving targets (especially git), as both are still developed, and thus some of my claims will get invalidated.
First I want to counter-argument some critiques of git (compared to svn)
I actually do not know, because with both programs I’m not concerned with what those do behind the scenes, but with what I can do. Talking about the content of
.git, from a user-perspective, makes no sense, as normally I do not check
.svn either, and with both programs, I do not need to.
Thus this argument is irrelevant, but probably it’s the opposite.
Either way, the Subversion information model is at least leakier.
For example, querying tags on git is
git tag, querying all branches is
git branch --all. In Subversion, it is
svn ls <path>. In Subversion, branches and tags all are copies.
In git, you do not need to know how they are implemented.
The fact that it is known how branches are created in Subversion is inconvenient for multiple reasons. The branch path and file path are in the same namespace but they have different semantics - this is often confusing.
Worst, when the number of tags and branches grows, it is natural to try to organize them better. And organizing better means moving those directories, or creating directories at different locations. Thus doing
svn ls https://example.com/svn/project/branches/ does not necessarily list any branch and does not necessarily list all branches. The same holds for tags.
Also, Subversion saves more metadata compared to git, like if a file has been moved, is binary or textual, and so on. This metadata is not saved, for example, in a patch file, thus saving the diff in a patch file or committing changes is not 100% equivalent, and can lead to nasty surprises, especially when renaming files.
Nevertheless, it is useful to understand how a tool works, to be able to predict how it works in certain situations without memorizing all documentation, or how to solve new problems.
Until now, in git, I only needed to know the following concepts for explaining most of its behaviors
commits are uniquely identified by a hash
the hash is created from previous commits, the diff, and commit message
a commits only knows its parent(s), but not its children(s)
git tracks content, not files
There are surely crazy commands in git, especially for advanced tasks. For the most basic tasks,
pull will do the job. When working with branches one should learn
merge. Those are sufficient for working together on a project with multiple people.
As mentioned previously,
git branch --all is much better than
svn ls http://example.com/svn/project/branches/.
Also generally git makes it easy to experiment because it is possible to undo nearly every operation, and every operation is recorded, so it is easier to learn how a command works with a first-hand approach, and without disturbing the rest of the team.
In Subversion, one needs a dummy server for testing. But most of the time it will be used for simple tests, it is difficult to create a reasonable difficult merge condition that one wants to try to solve cleanly and/or multiple times. Thus it gets harder to make enough experience without fearing to break something, and without polluting the repository history.
And what about creating a branch?
In Subversion it would be
svn copy https://example.com/svn/project/trunk https://example.com/svn/project/branches/my-branch -m "Creating a private branch", depending where
trunk and the branches are located.
In git, it is
git branch <branchname>
Subversion syntax is more difficult, as it has more parameters than git. Also, it’s a copy, not a branch (like in git), but it is used as a branch.
Also in Subversion, those operations are not reversible (they appear in history) and not private (everyone can see your branch).
Actually, it is the opposite.
With git, the contributor can test locally with much more ease. It can create commits, revert them… it can actually use the revision control system! In Subversion, if you are a new contributor, you will not normally have write rights to the repository and you might send your changes, for example, via a patch per mail. Thus you cannot use Subversion, except for diffing and creating patches (unless making your private server), and also patches do not contain all the information that a commit would contain (like renamed files).
With git, the contributor is a first-class citizen, even if it does not have write permissions. It can work with the version control systems like the maintainers that have access rights, and the patches created with
git contain all the information that would be contained in a commit.
Also with git another workflow (used for example by platforms like GitHub) is possible. Forking the repository and creating merge requests, which is, strictly speaking, equivalent to sending patches.
In both cases, a new contributor does not even necessarily need to learn how branches work, or how to do merges. But in the case of Subversion, this might be preferred if for easing the job to contributors, they are granted write rights to the repository. With git, it is not necessary as they can already use it.
Actually, this is true for any revision control system, depending on what we want to know. Subversion history does not lie if the question asked is: "in which order did the content got committed?", but it does not show much more relevant information.
For example, I do not immediately check in Subversion all my changes (but I do so in git). First I try to make a working solution. This is normally cluttered with unnecessary comments that would only distract other maintainers and contributors, and commented-out code. Then I try to split those parts of the solution, where it makes sense, to some reusable piece of code, or just move in the appropriate module/library. In the meantime, I also review the comments and remove older commented-out trials, as try to simplify the code, remove useless logging, etc. etc. Eventually, I also add tests where missing, or fix those that I broke but did not bother to fix immediately.
With Subversion, I need to store somewhere outside of the revision control system all my intermediary and temporary states. If I would not do it, you would probably see a history of commits that goes like "first attempt to implement", "remove comment", "WIP", "fix ci-build on platform X", "fix ci-test on platform Y", "undo unintended changes", and so on. Especially "undo unintended changes" is for the blame view, a killer.
With git, I can save my changes early, save them often, even save them automatically every 2 minutes, and still clean up all the mess before making the changes official. With Subversion, I need to use an external tool (as creating a branch is too cumbersome), and in both cases, there is little to no support for collapsing different changes together.
Is your workflow different than mine? Probably. But then, this is irrelevant, because we do not all work the same way. Subversion restrictions make it harder to work, and there is no added value.
Everyone can verify if git history has been tampered (if they have their own copy), and centralized servers make it possible to configure that the master branch (or trunk, main, …) is protected from rewrites. I do not know about Subversion.
This is true only for committing everything to the servers, and when working without branches. This might be the simplest task but is not the most common, especially when working with other people. For all other operations, with Subversion, everything is more complicated, or at least error-prone.
For example, suppose I’ve implemented a feature and also cleaned something up. Both changes are also on the same file. I do not want to commit both changes together, as I want to make two commits with two different messages, to make them both more visible, ease the review process, and ensure that both changes can be built independently. In Subversion, I need to store elsewhere all comments and unrelated changes to the first commit I want to make, verify that file-wide only things relevant to the commit are there (and compile to ensure I’ve not removed too much), and commit. Then reapply partially some (or all) of the saved changes, recheck for correctness, make a new commit. And so on.
With git, it is possible to commit only a subset of a file, thus no need to store elsewhere the unrelated changes. I can also use git to "hide" the things I do not want to commit. It gives me the possibility to use the same tool I use for tracking my work with colleagues. With Subversion, I need to track my work by hand.
Also creating a branch needs more commands in Subversion. As shown earlier,
svn copy is used to create a branch on the server, but before we can begin to work it needs to be checked out. With git, the branch is created locally and can be immediately used.
Yes, and so it is possible for most operations on any non-locked down system.
For example, I can create an empty file with the touch command:
touch file.txt. Or, from a POSIX shell, use
printf and the redirect command:
printf '' > file.txt Or from the file manager (explorer.exe in Windows, caja in MATE, dolphin, …), left click, create new, empty file (or something similar). With vi:
vi file.txt then
And what about showing the content? Or manipulating the content?
Even on Windows, opening a file with Microsoft Word can be done in several ways:
move a document over the Microsoft Word icon
Execute Microsoft Word, then open from the menu the document
Double-click the document, if the file association is correct, it will be opened with Microsoft Word
And other ways too.
Of course, it is not good if it is unclear which method is better for a specific task, or what are the up and downsides of every method. And it might be the case sometimes, but I do not believe this should be a major issue.
Thus, generally yes, there are more ways to accomplish something, but that because git offers a more extensible API.
For example, branches can be created in multiple ways (
git checkout -b,
git switch -c, …), but they are handled consistently.
Now that I’ve tackled the main reason why Subversion should be easier to use (but it’s not), some of the reasons why I find git easier to use
git output is colorized by default, which makes it easier for the human eye to parse the relevant information. Of course, it is possible to parse Subversion outputs too (link to repo), but it is a layer on top of Subversion which needs to be added.
Especially when checking the log, normally I’m not interested in what happened in the last hour or last days, not what happened at the beginning of the project. git pages the output directly (with less or something similar), thus after typing
git log I can see the last commits, and can scroll downwards to older entries.
With Subversion, when typing
svn log, the console is cluttered with all log entries, and I have to scroll upwards to find the most relevant. Like colorizing, it is possible to add a default pager to Subversion too. Again, it is a layer on top of it, which makes Subversion by itself less user-friendly.
While the git interface offers great possibilities for automating tasks (though aliases, porcelain commands, …) it also has nice interactive commands that Subversion misses.
For example when adding part of files (
git add -p), merging, rebasing, or bisecting errors.
git log shows the parents of a merge commit. In Subversion, when there is a merge, I just see all changes happening at once.
In git, I see there is a merge, and the merge commit has two parents, one per branch. It makes it much easier to track where changes come from and why they happened
git tracks content, not files. Thus when one function is moved from one file to another, git can show this information (with the blame view), while in svn this is not possible. Only for the particular use-case
svn mv, thus when the whole file is moved,
svn blame can show this information, but if you are working with patches sent via mail, this information is discarded.
In 7 years of development with git, it never happened to me to encounter a corrupted
.git folder, except once when playing with git-annex. Otherwise, from time to time I had to remove some
.lock file because probably I interrupted abruptly some operations, but that’s it.
With Subversion, at least 5 years development, it happened much more often than I needed to run
svn fsck, and at least once the status was that much corrupted that I had to clone the whole repo again. Maybe it was just bad luck, but git simple repo file formats are simpler, and this reduces the chances that corruption might happen.
While the robustness/corruption generally does not affect the ease of use, in some situations it does. It happened to me that adding and committing a file with Subversion generated an empty (or incomplete) commit. After a couple of trials, I noticed that also other commands, like
svn diff or
svn add, were misbehaving. I cloned thus the repository again in a separate folder and copied over my changes. Unfortunately, as Subversion did not notice that it was in an inconsistent state, I have polluted the history with non-sensical commits.
mkdir foo; cd foo; git init
That’s it. As a consequence, I tend to use a lot of git repository for different files. I have one for my documents, one for some pictures, one for my music collection, and of course one for every development project. Then there are documents, or groups of documents, that I track separately, so they live in their own repository. Is an overkill to use a version control system? For some files it might be, especially because I do not use most features (branches, tagging, …), but just commit the new changes.
But it has the big advantage that I can always recheck the older version of the documents I am managing.
And if I just add one remote, I automatically have a backup copy, with complete revision history.
And I can use it to synchronize the content between different devices (in this case branches can come handy to avoid conflicts).
Using Subversion would not be possible because it always requires a server.
With git, when querying the local status with
git status, git can show additional information, for example during a rebase, merge or cherry-pick, to help the user to finish the task, for example
> git status On branch master Your branch is up to date with 'origin/master'. You are currently cherry-picking commit 0796854. (fix conflicts and run "git cherry-pick --continue") (use "git cherry-pick --skip" to skip this patch) (use "git cherry-pick --abort" to cancel the cherry-pick operation) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: foo.txt Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: bar.txt modified: baz.txt
I’m surely not the only one thinking that git is easier to use svn, there must be a reason why svn popularity dropped so much. Surely not all developers are masochists, that want to use a difficult tool just to show off.
Sure, git and Subversion have a non-overlapping feature sets and do some things differently, thus it is hard to say if one is better than the other.
But for comparable features, and those used in most projects are probably branching, tagging, and saving the work on a centralized repository, git
offers more tools
makes all contributors first-class citizens
makes it easier to experiment
makes it easier to learn how to use git
and makes, all in all, easier to use than Subversion
Do you want to share your opinion? Or is there an error, some parts that are not clear enough?
You can contact me here.