Git howto
Contents
- 1 Working with freeplane's git repository
- 1.1 Installation
- 1.2 Checkout
- 1.3 Basic workflow with one branch
- 1.4 Using Tags
- 1.5 Working with branches
- 1.6 General workflow
- 1.7 Miscellaneous
Working with freeplane's git repository
You can (and probably want to) use eclipse for most operations. I try to explain this in each section, but it is a good idea to read the EGit documentation.
NOTE: These instructions cover the temporary freeplane repository on github, it will need to be adapted to the sourceforge hosting service.
There is a fun a Google Tech Talk by Linus Torvalds on git.
Installation
This chapter of the git book has some info about installing git from source or binary form on Linux/Mac OS X/Windows.
The author details (which will be recorded for each changeset) can be set globally:
$ git config --global user.name "Felix Natter" $ git config --global user.email "fnatter@gmx.net"
Checkout
Checking out is termed cloning in git speak:
$ cd ~ $ mkdir git $ cd git $ git clone https://github.com/fnatter/freeplane-git.git freeplane
If you want/have read-only access, use this as the last command:
$ git clone git://github.com/fnatter/freeplane-git.git freeplane
However, this will only configure the master branch (named trunk in other VCS's such as svn) locally:
$ git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/docear_trunk remotes/origin/master
In order to check out a branch (which is simply a reference to a commit) that currently only exists remotely (the remotes/origin/* references are called remote tracking branches), simply switch to that branch:
$ git checkout docear_trunk
This can be done more easily using Eclipse. This page also describes how to import a repository into eclipse.
Basic workflow with one branch
Please read the chapter on git basics in order to get started with git. You should understand how to stage and commit changes.
In the following there is a simplified list of steps for working with git. Please read the following sections!
- clone repo (see above)
- switch to the desired branch (see next section for more about branches!)
$ git checkout <branch> # Eclipse: Team->Switch to
- make sure you have the latest version of the branch (pull = fetch + merge)
$ git pull
(resolve and commit any merge conflicts)
- modify files...
- add the modifications to the index:
$ git add foo.java # (Team->Add to index in eclipse)
- create a commit from the changes in the index:
$ git commit [-m message]
(if you omit -m then you will be prompted for a commit message)
- create more commits, this is all done locally!
- push changesets (commits) to sourceforge:
$ git push
(you might have to pull before the push if someone has pushed to the branch after you pulled!)
Using Tags
Show all tags:
$ git tag
Search for a tag:
$ git tag -l "release-1.1*"
Show information about a tag:
$ git show release-1.1.2
Define a tag locally:
$ git tag -a <tagname> # (an editor opens for you to add a description)
Tags are not automatically transferred when doing a git push
,
you have to push individually:
$ git push origin <tagname>
or push all tags:
$ git push --tags origin
You might need a
$ git pull --tags
to get all tags. See git-fetch(1) for situations when you will need this (rarely).
TODO: sign tags?
Working with branches
Branches are very central to git. Do not hesitate to create feature, team and (of course) maintenance branches.
You probably want set push.default to tracking or upstream which makes sure that only the current branch is pushed to its upstream branch (and NOT all configured branches): Note: this option is ignored by current EGit. On EGit you get the same beahvior by selecting Team->Push To Upstream.
$ git config push.default tracking
(you can equivalently set this to upstream in recent git versions).
Switch to another branch
$ git checkout <branchname>
(Team->Switch To->... in Eclipse)
How to create a new branch
New (feature) branches should be named <user>/<feature>
or (if several devs work on a feature): <feature>
.
# commit everything that should go into the new branch $ git status $ git add <file> [...] $ git commit -m "my changes"
# create new branch locally $ git checkout -b <newbranch> # check commit log to see that above commit is in there $ git log # new branch must be visible and selected: $ git branch -a
# (make sure that the name of the new branch is correct! it is diffcult/impossible # to rename published branches!) # create branch remotely, use -u to automatically configure upstream location $ git push -u origin <newbranch> # this should output something like this: Branch <newbranch> set up to track remote branch <newbranch> from origin. # (Note: this is important if you want to use git pull/push without specifying a remote/refspec)
# remote branch of <newbranch> must be visible: $ git branch -a
So the short story is:
$ git checkout -b <newbranch> $ git push -u origin <newbranch>
Rename a local branch
$ git branch -m <old-branch-name> <new-branch-name>
TODO: how to rename the remote tracking branch => difficult!!
How to merge branches
$ git checkout <destination_branch> $ git merge <source_branch>
If you want to abort a merge (revert the working directory to the state before the merge command), do this:
$ git reset --hard
(WARNING: this will remove all uncommitted changes!!)
In eclipse, this can be achieved by:
- Team->Switch To and choose <destination_branch>
- Team->Merge... and choose <source_branch>
TODO: how to make eclipse update the list of branches etc. (e.g. if a branch has been deleted from the command line)??
Fast-Forward Merges (merge-nodes)
Often the creation of a merge commit (merge node) is not necessary,
and git merge
uses a fast-forward merge, omitting
the merge node:
$ git merge foo Updating 9e9a63a..732b657 Fast-forward testfoo.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testfoo.txt
results in:
* 732b657 commit in branch foo * [...]
Using the option --no-ff
you can force git to create a merge
node even if isn't absolutely necessary (non-fast-forward merge):
$ git merge --no-ff foo2 Merge made by the 'recursive' strategy. testfoo2.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testfoo2.txt
which will result in:
* 3890bc8 (HEAD, master) Merge branch 'foo2' |\ | * 6bc24c5 (foo2) commit on foo2 |/ * * [...]
This is useful when merging feature branches because it clearly shows the integration of a new feature. On the other hand, many merge nodes make the commit graph less readable.
Merge master->dev-branch
$ git checkout <devbranch> $ git merge master
Merge dev-branch->master
$ git checkout master $ git merge <devbranch>
How to remove a branch
# remove branch locally # (use -D instead if you want to delete a branch that is not fully merged into HEAD!) $ git branch -d <branchname>
If you accidentally deleted a (local) branch, you can recover it by
starting a new branch from the location that git branch -d <branchname>
echoed (or by searching for the last commit on that branch in git reflog
):
$ git branch -D foo Deleted branch foo (was 732b657). $ git branch foo 732b657
(remember that branches are simply pointers to commits)
Warning: this only works if the delete was quite recent as orphaned commits will be deleted after some time!
Delete a remote branch(!):
$ git push origin --delete <branchname>
Now the local and the remote tracking branch should be gone:
$ git branch -a docear_trunk * master remotes/origin/docear_trunk remotes/origin/master
NOTE: The stale branch will still exist in other checkouts, until you do a:
$ git remote prune origin
in that other checkout. TODO: but it still exists there as a local branch!
Check whether your branches are set up correctly
Make sure your branches are set up correctly for push/pull:
$ git remote show origin * remote origin Fetch URL: https://github.com/fnatter/freeplane-git.git Push URL: https://github.com/fnatter/freeplane-git.git HEAD branch: master Remote branches: docear_trunk tracked master tracked Local branches configured for 'git pull': docear_trunk merges with remote docear_trunk master merges with remote master Local refs configured for 'git push': docear_trunk pushes to docear_trunk (up to date) master pushes to master (up to date)
General workflow
Create a dev branch (see section on creating branches above).
Work on your feature branch
# switch to feature branch $ git checkout <feature>
# fetch and merge changes (in case another dev works on this) $ git pull
# you might have to resolve conflicts: (might want to use 'git mergetool' # or Eclipse/EGit) for each conflict x: 1. resolve conflict in x, remove markers 2. git add x # mark as resolved # commit the conflict resolution(s) $ git commit
$ git add ... $ git commit [...]
# This will push commits to the remote branch that is tracked # make sure that push.default=tracking|upstream (see above), # otherwise other branches will be pushed as well! $ git push [--dry-run]
Merging
Merge master -> <devbranch> (see section on merging above) every once-in-a-while.
After a final code review (on your dev branch), merge <devbranch> -> master (see section on merging above).
Miscellaneous
Undoing/editing commits
TODO: how to remove/edit a commit locally using rebase.
Undoing a commit that is already pushed
Use git revert <commit-hash>
, like this:
$ git revert b1e9b4c9755b091f95aaa3035aca04dcb02ec1fd
This will generate an inverse commit, it will not remove the original commit:
* 171881e (HEAD, master) Revert "a simple commit" * b1e9b4c a simple commit