Git notes
From Noah.org
Git is my current favorite VCS (or RCS or SCCS or SCMS or VC or whatever). I'm trying to phase out Subversion in favor of Git. Subversion is fundamentally flawed. What it does do it does well, but it does not do things in a way that makes sense (to me). It's slow and uses a lot of disk space. In the past I discounted the disk space wasting as irrelevant because storage is cheap, but now I've changed my mind. There have been many times when all that wasted disk space was a problem.
Contents |
git remote
When using git-remote over ssh it seems that you have to use the full path on the remote server, and not the path relative to the user you are connecting as. Also, you must put a trailing slash on the path. For example:
git ls-remote ssh://username@www.example.org/home/username/repositorium/engineering/
git clone
git clone git fetch git pull
config
git config --global user.name "Noah Spurrier" git config --global user.email noah@noah.org git config --global core.editor vim git config --global color.ui auto git config --global merge.tool vimdiff
git archive
This is like an export. It retrieves a remote git repository without the .git metadata (history).
git archive --remote=ssh://username@www.example.org/home/username/repositorium/engineering/ HEAD > git_archive.tar
You can also use this to retrieve subdirectories of repositories. The follow retrieves only the subdirectory "dotfiles". Note that the selection of subdirectory is made after HEAD::
git archive --remote=ssh://username@www.example.org/home/username/repositorium/engineering/ --prefix=dotfiles/ HEAD:dotfiles > dotfiles_archive.tar
fix commits with the wrong committer/author name or email address
This basically completely rewrites your history. All of your git hashes will change.
git filter-branch --env-filter 'GIT_AUTHOR_NAME="Noah Spurrier";GIT_AUTHOR_EMAIL="noah@noah.org";GIT_COMMITTER_NAME="Noah Spurrier";GIT_COMMITTER_EMAIL="noah@noah.org";' HEAD
Git Commit: git/svn commit differences are confusing to newbies
Do a `git commit -a` in most cases.
Git stages commits into an index before they are committed, so a commit is a two step process. The `git-status` command will show which modifications have been indexed for the next commit. The `git-add` command will index a modified or new file for the next commit.
A `git fetch` also is done as a two step process. I especially like this feature. When you do a `git fetch` files are pulled from a remote server, but they are not immediately merged into your working copy. I despise this about SVN. Instead the remote files (actually their diffs) are held in the index where you can browse them and choose which parts to merge into your working copy.
Notice that the message below from `git-status` says two things. It shows files that have been modified and it shows which of those changes have been added to the commit. Notice here that one file is modified, but no changes have actually been added to the commit.
$ git-status # On branch master # Changed but not updated: # (use "git add <file>..." to update what will be committed) # # modified: dotfiles/.vimrc # no changes added to commit (use "git add" and/or "git commit -a")
You can have git automatically index all modified files with `git commit -a`. This is usually what most SVN users expect.
git-svn
dcommit
- When you want to do "svn up", instead do "git svn rebase". If you have conflicts use `git mergetool` then `git rebase --continue`.
- When you have everything up-to-date do `git svn dcommit`.
- If git complains about files not being up-to-date do `git svn rebase` again.
VCS command translation
See also this table in Wikipedia: VCS commands
| git | subversion | notes |
|---|---|---|
| git clone url | svn checkout url | `git+ssh` works just like `svn+ssh` git clone git+ssh://noah@www.example.org/home/noah/src |
| git pull | svn update | |
| git status | svn status | The output from git is more clear. |
| git -f checkout path | svn revert path | This deletes your local changes. |
| git add file | svn add file | |
| git rm file | svn rm file | |
| git mv file | svn mv file | |
| git commit -a | svn commit | |
| git log | svn log | |
| git show rev:path/to/file | svn cat url | |
| git show rev:path/to/directory | svn list url | |
| git show rev | svn log -rrev url | |
| git branch branch_name | svn copy http://example.com/svn/trunk http://example.com/svn/branches/branch_name | |
| git merge --no-commit branch_name | svn merge -r 20:HEAD http://example.com/svn/branches/branch_name | This is reason #1 why SVN sucks. Merge tracking is crap. As of version 1.5 they have some limited support for merge tracking, but it still blows. |
| git tag -a tag_name | svn copy http://example.com/svn/trunk http://example.com/svn/tags/tag_name | SVN doesn't really have tags. Most people just use copy. The downside is that people can commit to tags, which kind of defeats the purpose. |