Git setup
From FrugalWiki
Contents |
Comparing commands
The target is the following: You use some darcs commands on a daily basis. We try to provide the more-or less equivalent git version of those commands.
This means that listing here all darcs commands here is not a target, just the ones we can't live without :)
Most important ones (we use them by hand daily)
(I figured out a few commands for bzr, too, feel free to complete the table)
darcs | git | bzr |
dr init | git init | bzr init |
dr get url | git clone url | bzr branch url |
dr add | git add | bzr add |
undo dr add (not in dr) | git reset HEAD foo.c | bzr revert foo.c |
undo dr rm (not in dr) | git reset HEAD foo.c | bzr revert foo.c |
dr mv | git mv | bzr mv |
dr remove | git rm | bzr remove |
dr rec (interactive) | git add -i && git commit | not possible without plugins |
dr rec -a | git commit -a | bzr commit |
dr pull -a | git pull (conflict handling as usual) | bzr pull (if fails, you need bzr merge and bzr commit) |
dr push -a | git push (git checkout -f is needed on the server, dg tries to find out what will be pushed) (won't allow push on conflict as usual) | bzr push |
dr what | git status -a -v for commit -a, git status -v for commit | bzr diff |
dr what -s | git diff HEAD --name-status | bzr status |
dr chan | git log | bzr log |
dr chan --last 3 | git log -2 | bzr log --limit=3 |
dr chan -v | git log -p | not possible without plugins |
dr chan -s | git log --name-status | bzr log -v |
dr tag | git tag | bzr tag |
dr rollback | git revert (no "dr rev -a" is necessary after it) | "good question" (answer from a bzr expert) |
dr unrec | git reset --soft HEAD^ (only the last one) | bzr uncommit |
dr unpull | git reset --hard HEAD^ (only the last one; undo with "git reset --hard HEAD@{1}" - this was not possible using darcs) | bzr uncommit && bzr revert |
dr rev | git checkout file (cherry-picking not possible) if it fails, try git add -i and revert | not possible without plugins |
dr rev -a | git checkout -f | bzr revert |
These are important too (we use them in scripts / it's good how to do so)
darcs | git | bzr |
dr get --partial url | git clone --depth 0 url (this is good for repoman upd only: you can pull to it, but you can't push from it later) | support for shallow branches is being developed |
dr get --tag foo url | git clone; git reset --hard tagname | |
dr rec --pipe | git commit -F - | |
dr rec -m foo --edit-long-comment | git commit -m foo -e | |
dr push -p foo | git checkout -b mybranch; git cherry-pick commithash; git push origin mybranch:master | |
dr push --apply-as foo | git push --exec="sudo -u foo git-receive-pack" (or use git config remote.origin.receivepack "sudo -u foo git-receive-pack" once) | |
dr send | git format-patch -M && git send-email | |
dr apply | git am | |
dr chan --from-tag foo | git log 1.0.. | |
dr check | git fsck | |
dr repair | you are on your own (see later) | |
dr annotate | git annotate | |
dr resolve (conflict resolving) | conflicts are automatically marked (just like in darcs) | |
dr dist | git-archive --format=tar --prefix=foo-1.0/ HEAD | gzip -9v > foo-1.0.tar.gz |
Terminology
As you can see, if you modify something, then git commit won't commit it, you need to use git add or git commit -a. If you use git add then the given file (or if you use git add -i, the given hunks) will be 'staged', added to the 'index'. If something is staged, then git commit will write it to the object database on the next commit. If you want to undo this, then you'll need `git reset HEAD foo.c`, so that it'll be 'unstaged' again.
- git diff diffs between the index and the working dir
- git diff HEAD diffs between HEAD and the working dir
- git diff --cached diffs between HEAD and the index
Colors and pager
This will avoid git to start less on every git-diff:
$ echo "export GIT_PAGER=cat" >> ~/.bash_profile
Actually git-diff is way larger than darcs whatsnew, so it's harder to get the point. If you want to make it easier to read it's a good idea to enable colored output. More works with that fine.
$ echo "export GIT_PAGER=more" >> ~/.bash_profile $ git-config diff.color auto
Random notes
If any property of a patch is changed, it'll have a new hash. This includes changing the parent of a commit, which usually happens if you transfer a patch from one repo to another. Of course git merge will recognize that they are the same, but this is some difference to darcs.
If you just touch a file but you don't edit it, it's noted and you have to revert the change.
To create aliases:
$ git-config --global alias.st status
It's not easy to unpull older patches:
13:03 < siprbaum> say you you have a->b->c->d, you could say "git-base --onto a c d" and it should get you something like this: a->c'->d'
If you deleted a file using rm (forgot to use git rm), you need:
git ls-files -z --deleted | git update-index -z --remove --stdin
How to set the default pull/push url?
git config remote.origin.url machine:path
git push --dry-run
git log origin/master..master --no-merges
git pull --dry-run
git fetch; git log master..origin/master --no-merges
push the changes from the local 'foo' branch to the master branch of the server (origin)
git push origin foo:master
there is no tool like darcs repair in git. if an object is missing or corrupted, try to get it manually from the server
if you need the equivalent of darcs send:
$ git log -3 commit f3669033b325d8cd6a6933c2d61619566cea1936 Author: VMiklos <vmiklos@frugalware.org> Date: Thu Jun 14 23:00:27 2007 +0200 second commit c166730cf52cb4e75fc81c5434d26284effc11d3 Author: VMiklos <vmiklos@frugalware.org> Date: Thu Jun 14 23:00:20 2007 +0200 first commit dd6065cef2fa3e69d38da92c1ac1a88178ce01ec Merge: 6535545... 0101c8d... Author: VMiklos <vmiklos@frugalware.org> Date: Thu Jun 14 22:09:14 2007 +0200 Merge branch 'master' of /home/vmiklos/scm/git/test2/ $ git format-patch -n dd6065cef2fa3e69d38da92c1ac1a88178ce01ec..f3669033b325d8cd6a6933c2d61619566cea1936 0001-first.patch 0002-second.patch $ git send-email --to vmiklos@frugalware.org *.patch .. on the dark side.. $ cat *.patch |git am Applying 'first' Wrote tree 681fcb98ce2e09ade7a449b3ac19d59be31afc8b Committed: 45b13996fd31d11c30f53ac271ddccd5bcc875bf Applying 'second' Wrote tree d547b932fa8ee55cb0174f652d47f436d4b8f0df Committed: b6e59d8b21ef3a7356ba3eb1e18e643206cff330
to include tag names in git log:
git log -3 | git name-rev --tags --stdin
to download a repo while avoiding fetching the history (see also git clone's shallow feature):
git-archive --remote=url --format=tar HEAD |tar xf -
It seems that currently git does not handle dirs at all. This means:
- a dir is added when necessary (ie there is a new file in the dir)
- a dir is removed when it's empty
There is no pre-dist hook in git, here is how git itself handles autoconf:
dist: git.spec git-archive configure ./git-archive --format=tar \ --prefix=$(GIT_TARNAME)/ HEAD^{tree} > $(GIT_TARNAME).tar @mkdir -p $(GIT_TARNAME) @cp git.spec configure $(GIT_TARNAME) @echo $(GIT_VERSION) > $(GIT_TARNAME)/version @$(MAKE) -C git-gui TARDIR=../$(GIT_TARNAME)/git-gui dist-version $(TAR) rf $(GIT_TARNAME).tar \ $(GIT_TARNAME)/git.spec \ $(GIT_TARNAME)/configure \ $(GIT_TARNAME)/version \ $(GIT_TARNAME)/git-gui/version @rm -rf $(GIT_TARNAME) gzip -f -9 $(GIT_TARNAME).tar
Having multiple tags with the same name in darcs was possible. It isn't in git. Though you can always append "-f" to git tag so that the old tag will be removed.
To remove untracked files from a dir, you need:
git clean .
(there was no such command in darcs)
To allow a http/ftp/rsync fetch, you need to:
chmod +x .git/hooks/post-update
on the server.
If you publish a repo which was cloned from somewhere, don't forget to remove the remote refs:
rm -rf .git/refs/remotes
See this thread for more info.
Setting your email and name. By default git uses /etc/passwd and hostname to figure out these, but probably you want something like:
git config user.name "Foo Bar" git config user.email foo@bar.org
use "git config --global" instead of "git config" if you want to set it globally (i.e. not just for the current repo).
- listing tracked files
something like ls _darcs/pristine:
git ls-tree --name-only -r HEAD
- if you want to clean even ignored files, you need
git clean -x
Benefits
We know that git is faster than darcs, but here are few ~benchmarks:
- darcs changes takes minutes for a FB. git log takes a few seconds
- dr get --partial is usually slower than a full git clone
- repoman push
~/darcs/current/source/network/iptables$ time repoman -k push (...) real 4m4.038s ~/git/current/source/network/iptables$ time repoman -t current_git -k push (...) real 0m22.273s
Besides speed, there may be some other interesting features. Here is a short list of them.
- viewing older version of a file
git show tag_or_commit:path_to_file
- size. it seems that the git repos are smaller:
$ du -sh repos/pacman-g2/ 18M repos/pacman-g2/ $ du -sh repos-git/pacman-g2/ 3.0M repos-git/pacman-g2/
Testing
Upgrade pacman-tools and pacman-g2:
$ pacman -Q pacman-tools pacman-g2 pacman-tools 0.9.5-1 pacman-g2 3.5.9-1
Append these lines to your ~/.repoman.conf:
fst_root=~/git current_servers=("nick@git.frugalware.org:/home/ftp/pub/frugalware/frugalware-current")
Get the git repo:
mkdir ~/git cd ~/git dg get nick@git.frugalware.org:/home/ftp/pub/frugalware/frugalware-current current cd current git config remote.origin.receivepack "sudo -u vmiklos git-receive-pack"
Then do a package you wanted to bump anyway, such as:
cd ~/git/current/source/*/acpid (..) repoman rec repoman -k push
Limitations
- no way to add empty dirs a repo yet (thread)
- svn-like submodules not supported (thread)