When moving to Git from SVN, there are some conceptual conflicts that causes a lot of troubles on daily work. This document intends to describe some basic differences between SVN and Git, so SVN users can learn faster and probably avoid problems.
1. Decentralized vs. Centralized workflow
The first big difference between Git and SVN is Git makes possible to have decentralized workflow when collaborating to other developers, while SVN is fully centralized.
On decentralized workflow you can duplicate (fork) a git repository, share this repository with friends while the original has it's own activity. It is also possible to send differences from duplicated repository to the original and fetch differences from original as well.
On centralized workflow, every change needs to be committed to a unique remote repository. Despite the fact you can have SVN mirrors, it is still centralized, because mirrors also get/send changes from/to central repository.
2. Commands equivalence
2.1. Getting the code
svn co https://svn.code.sf.net/p/tikiwiki/code/trunk tikiwiki
git clone email@example.com:tikiwiki/tiki.git tikiwiki
When working on a live Tiki files may have been modified on purpose and you don’t want to update them. (like .user.ini, lang/he/custom.php themes/mytheme/).
git statusor the "diff" command (see below).
However your working directory (local copy) may be out of synch and git will protect your files and forbid the pull (update) operation for Tiki (the branch used) files.
To solve this you can manually checkout (update) the file that is blocking the operation (or shelve it using stash).
git checkout file/path
You should be then able to proceed with git pull.
svn switch https://svn.code.sf.net/p/tikiwiki/code/branches/18.x . svn up
git checkout 18.x git pull
3. Commit, Pull, Push
When working on SVN workflow, every commit goes directly to SVN server and will be available to other developers when they update their working copies.
But on Git it is very different. When you initialize a git folder, you will have your project files on your working space, a new local Git repository at the root of your project and optionally, a remote repository, like we have on Github or Gitlab.
When you commit your changes using Git, these changes will be saved only in your local repository. To make your commits available to other devs, you have to *push* your changes to a remote repository. Also, if you want to get changes from other devs and apply on your working space, you have to *pull* these changes from remote repository.
echo 'my new change in a file' > README svn add README svn ci -m '[FIX] Added changes on README'
echo 'my new change in a file' > README git add README git commit -m '[FIX] Added changes on README' # It is possible to commit more changes before sending to remote. # After done, just push changes to remote repository git push
This will work fine if you version is up to date (no one committed since you update your checkout).
You will see merge messages and be asked to merge before pulling.
Chances are you’ll have to rebase your checkout (update/merge on your local version) before pushing your changes.
echo 'my new change in a file' > README git add README git commit -m '[FIX] Added changes on README' git pull --rebase git push
Another usual case is that your local version have file you modified and/or don’t want to commit (like a theme, custom language file, etc).
Git will see those modified files as "un-stashed" file and will block you from pushing back your committed files. You can use then the following:
echo 'my new change in a file' > README git add README git commit -m '[FIX] Added changes on README' git pull --rebase --autostash git push
To create branches on SVN, you have to create a branch on remote repository as well, so your team mates can have access to your branch. There is no way to create a local branch for testing purposes.
On Git, you create a branch in your local repository. Optionally, this branch can be sent to remote repository, with an extra command for that.
svn copy 'https://svn.code.sf.net/p/tikiwiki/code/trunk' 'https://svn.code.sf.net/p/tikiwiki/code/branches/task-icon-picker' svn co 'https://svn.code.sf.net/p/tikiwiki/code/branches/task-icon-picker' tiki-icon-picker
git branch task-icon-picker git checkout task-icon-picker # The last command created a branch on local repository, # so, to send it to remote repository git push -u origin task-icon-picker
5. Mark files to be committed
On SVN, if you have several changes on working space and try to commit that without specifying a file, all those changes will be committed.
But on Git, the behavior is different. You have to mark a file, folder or the entire working copy to be committed and then create the commit to save your changes.
svn add README.html svn ci -m '[NEW] HTML version for README'
git add README.html git commit -m '[NEW] HTML version for README' # But if there is no new files and the mission is commit all changes # just use the -a option git commit -a -m '[NEW] HTML version for README'
6. Revert and discard changes
On SVN, when you want to discard changes on your working copy, you use the command revert to discard those changes and start again.
But on Git, the concept to discard changes is different. You take the content of your local repository and copy over files on you working copy. So the changes are discarded. The revert on Git has another meaning.
The revert command on Git creates a commit that undoes the things of the other commit. So, if you added a line on a file and committed that, the revert command will create another commit removing the line on that file.
echo 'My new line on README' >> README svn revert README
svn merge -c-63929 README
echo 'My new line on README' >> README git checkout README
git revert 4543a31466d48