GitSvnCrashCourse

From Git SCM Wiki
Jump to: navigation, search

OBSOLETE CONTENT

This wiki has been archived and the content is no longer updated. Please visit git-scm.com/doc for up-to-date documentation.

Welcome to the Git crash course for SVN users! This introduces you to Git based on your current Subversion knowledge. If you want to migrate your company from SVN to Git, see the SVN migration page. If you want a list of common commands, see the Git Cheat Sheet (or the git-svn guide if you are using Git as a subversion client. Many non-SVN-specific guides are also available. This crash course is based on Pasky's unmaintained version.

Contents


For those too impatient to read, here's what you need to use someone else's Git project:

git clone url
git pull
git commit -a && git push

svn checkout url
svn update
svn commit

And here's what you need to use an SVN project:

git svn clone --stdlayout url
git svn rebase
git commit -a && git svn dcommit

svn checkout url
svn update
svn commit

Before You Start

SVN is based on an older version control system called CVS, and its designers followed a simple rule: when in doubt, do like CVS. Git also takes a form of inspiration from CVS, and its designer also followed a simple rule: when in doubt, do exactly the opposite of CVS. This approach lead to many technical innovations, but also lead to a lot of extra headscratching among migrators. You have been warned.

How to Read Me

This page shows Git commands in a bold, fixed-width font: git help. Non-git commands are just fixed width: svn help. Within a command, text you need to add yourself is in italics: git help command. In tables, Git commands are shown on the left with a blue background, SVN commands on the right with grey. If you are in a hurry, just skimming over the tables should give you a good idea about the basics.

Before running any command the first time, it's recommended that you skim through its manual page. Many of the commands have very useful and interesting features (that we won't list here) and sometimes there are some extra notes you might want to know. You can also get help on any Git command by doing git command -h or git help command.

Configuring Git

SVN includes your username in your commits, whereas Git includes your real name and your e-mail address. You should add these before you start using Git:

git config --global user.name "Your Name"
git config --global user.email you@yourdomain.example.com

git config is the command to set configuration options. While you're configuring, here are some other things you might like to do:

git config --global color.ui auto # colorised `git diff`, etc.
git config --global alias.st status # make `git st` work
git config -l # list all configuration options

You might also want to look at some other SVN-like aliases.

Things You Should Know

Here are some concepts that will help you understand Git. If you are in a hurry, you can skip this section and come back when you get confused - you should be able to pick up a lot about Git with just your intuition.

Checkouts and Repositories. Each Subversion project has one central repository which stores all the history. Everyone has a checkout of the repository, which they update from and commit to. Each Git project gives everyone a personal repository, and lets them pull from and push to each other. Many Git projects use an "official" repository that they agree to treat like an SVN repository.

URLs and paths. In Subversion, a URL identifies the location of the repository, and the path inside the repository identifies the branch or tag. So svn://svn.example.com/trunk might be the URL for the trunk branch of your repository. In Git, the URL is still the location of a repository, but branches and tags are labels you access with Git commands. So git://git.example.com/ might be the URL for a whole Git repository.

Visualize. Git version history can get complicated, especially in big projects. You may like to look at your repository with the gitk viewer to understand what's going on.

Revisions. Subversion identifies revisions with numbers starting at 1 and going up in each revision. That's fine when one central repository keeps track of all the numbers, but who decides the next revision number if everyone has their own repository? Git uses unique 40-character identifiers instead - SHA-1 hashes that you can think of as random strings. These numbers look kinda scary, but you don't actually use them that often. Git has nicknames for the commits you use most often, has relative names for other interesting commits, and lets you refer to the rest by the first half-dozen characters in their identifier. For example, your current commit is always called HEAD, the parent of the current commit is HEAD^ and the grandparent is HEAD^^ (you can go on adding carets). The commit abc123def456abc789def012abc345def678abc9 can be referred to as abc123 (and you can use abc123^, abc123^^ etc.). See the git-rev-parse manpage if you want to know which commit trunk@{tea-time.last.Wednesday}~2 refers to.

Creating a New Repository

Let's step through how you create and update a new project in Git and SVN.

If you are creating a new project, you would:

mkdir myproject; cd myproject
git init
svnadmin create myproject_repo
svn checkout file://myproject_repo myproject

If you are putting an existing project under version control, you would cd to your project directory, then:

git init
git add .
git commit
svnadmin create myproject_repo
svn import . myproject_repo

git init initializes the repository, git add . adds all the files under the current directory and git commit creates the initial import.

Remember - Git does not have separate places for a repository and your working copy - the working copy always already contains the repository as well, in the .git subdirectory. (Of course you can have special repositories that do not have a working copy attached - bare repositories. These are useful for having a repo over at some server where you don't do any actual work but which serves just for pushing and pulling.)

If you are downloading someone else's Git project, you would do this instead:

git clone url myproject
svn checkout url

Or to download an SVN project into Git:

git svn clone --stdlayout url myproject
svn checkout url

git clone and git svn clone download the complete contents of a remote repository and create a local copy of it. --stdlayout tells Git that it should look in the standard trunk/tags/branches directories for branches (see the git-svn manual if your project uses a different layout).

Now your tree is officially tracked by Git. One nice thing to note - no matter how many subdirectories your project has, there's only one .git directory that contains all the version control information. Do some random changes to your tree now - poke around in a few files or something.

Making Changes

When you've edited some files, next you add them to version control. First you check what you've done:

git diff svn diff | less

That's it. This is one of the more powerful commands. To get a diff with a specific revision and path do:

git diff rev path svn diff -rrev path

There is a more concise representation of changes available:

git status svn status

This will show the concise changes summary as well as list any files that you haven't either ignored or told Git about. In addition, it will also show at the top which branch you are in.

The status command also shows the "untracked files" that Git doesn't know what to do with. You can handle these by:

git clean
git add files
$EDITOR .gitignore
rm -rf files
svn add files
svn propedit svn:ignore .

In fact you need to tell Git when you add, move or remove any files, just like SVN:

git add file
git rm file
git mv file
svn add file
svn rm file
svn mv file

You can also recursively add/remove whole directories and so on; Git's cool!

If you made changes to a file that you want to undo, you can get back the last version you committed:

git checkout path svn revert path

So, it's about time for us to commit our changes:

git commit -a svn commit

This looks the same, but there are two important differences:

First, you have to specify -a if you want to commit all your files, instead of just those files you've recently done a git add or git rm on. This can be frustrating at first, but several important techniques are based on it (for example, git add -p lets you add part of a file - see the git-add manual page for details).

Second, Git commits are private by default - they aren't pushed to any central server. We'll talk about pushing changes later, but private commits have some important benefits. For example, when you realise you left some debugging in your last commit, or made a typo in the commit message, you can do git commit --amend to fix it, or even do git reset HEAD^ to toss the commit away completely without affecting your files.

A few words about the commit message: it is customary to have a short commit summary as the first line of the message, because many tools just show the first line of the message. You can specify the commit message using the -m parameter (extra -m arguments will create extra paragraphs in the commit message).