This page will give you a quickstart guide to git and the MINIX 3 git workflow.
A general Git quickstart site: [[http://gitready.com|gitready.com]].
====== Git Basics ======
Git is a distributed version control system. As such, you don't just checkout a specific revision of your project as in subversion. Instead, you make a clone of the entire repository, including all history. You can 'commit' changes locally to your repository, but will need to 'push' them if you want your changes into a remote repository or, in our case, the main minix git repository. The workflow is that you edit files as normal, use 'git add' to add files, and 'git commit' to commit to your locally cloned repository. To push your changes to the master repository, do a 'git push.'
====== Installing Git ======
Git is available in pkgsrc. You can install git by running the following command as root:
# pkgin up
# pkgin in git-base
If you would like to clone the MINIX 3 repository on a non-MINIX platform, please see the [[http://git-scm.com/book/en/v2/Getting-Started-Installing-Git|Pro Git book]].
====== Configuring Git ======
Now, you will need to set your git config so that your full name and email address (that git will use in commit messages) are correct.
$ git config --global user.name "John Doe"
$ git config --global user.email "johndoe@minix3.org"
**Note: MINIX 3 developers should ideally use their minix3.org email addresses.**
We want to rebase branches on pull, so do:
$ git config --global branch.autosetuprebase always
If you cloned your repository before setting this option, you must re-clone it. Or you can set this manually in the per-repo config, but that syntax isn't described here.
Also, useful:
$ git config --global color.ui auto
This will create a .gitconfig in your home directory. If you would like to send patches via email, the following snippet will also be useful. You can also use 'git config' to set each variable.
[sendemail]
smtpuser = john.doe@gmail.com
smtpserver = smtp.gmail.com
smtpserverport = 587
smtpencryption = tls
Please consult the Git documentation for more information.
Also, git relies on the local date and time being correct to make sensible commit messages; so please check your time and timezone are sensible.
====== Cloning the repository ======
The following two sections contain instructions for developers with direct git access, and for community members. To be clear: most people do //not// have direct git access. If you are not sure whether you have access, please see the instructions for community members.
===== For community members =====
Community members can clone like so:
$ git clone git://git.minix3.org/minix
Then, you can push changes to gitorious, github, etc. Please see the github and gitorious docs for more info.
To clone the developer repos, you would do the following. This step is optional. You only need to do it if you you want to use one of the developer repos.
$ cd minix
# Add developer repo as a git remote
$ git remote add minix-sandbox git://git.minix3.org/minix-sandbox
# Fetch the remote minix-sandbox repo's contents
git fetch minix-sandbox
# Create a tracking branch called "sandbox" that tracks the "sandbox" branch in the minix-sandbox repository
# and checkout the local "sandbox" branch
git checkout --track minix-sandbox/sandbox
===== For developers with direct git access =====
If you have been given access to (or own) a developer repository, you would do the following to use it. Replace minix-sandbox with a repository that actually exists.
$ cd minix
# Add personal repo as a git remote
$ git remote add minix-sandbox git@git.minix3.org:minix-sandbox
# Fetch the remote minix-sandbox repo's contents
git fetch minix-sandbox
# Create a tracking branch called "sandbox" that tracks the "sandbox" branch in the minix-sandbox repository
# and checkout the local "sandbox" branch
git checkout --track minix-sandbox/sandbox
So, you will create a branch in your local repository called "sandbox." This branch will track the "sandbox" branch in the remote repository minix-sandbox. See [[http://git.minix3.org/?p=minix-sandbox.git;a=summary|minix-sandbox on gitweb]].
====== Basic Git Workflows ======
==== Creating a Topic Branch ====
First, you will create a topic (short-lived) branch for your work. The branch will be named //bug_fix//. This branch is a local branch. It does not exist on the remote repository unless you explicitly tell git to create a branch in the remote repository.
$ cd minix
# checkout the sandbox branch first, so bug_fix branch will be based on sandbox
$ git checkout sandbox
$ git checkout -b bug_fix
**Note: you should create a new branch for every bug/feature/experiment/idea you have. Branches are cheap. We want to keep the public branches in your repositories (e.g., the "master" branch in the main repo, the "sandbox" branch in minix-sandbox repo, the "smp" branch in minix-smp repo) pristine, so please use a local (private) topic branch.**
==== Committing to Your Local Repo ====
Now, you can edit files using your text editor of choice. When you want to add a new file, you will type:
# Edit some files
$ vim blah.c
# Create a new file
$ touch file1
# Add the new file to your local git repository
$ git add file1
Before you commit, you should review your changes by doing:
$ git diff
Then, you can commit to your local repository using:
$ git commit -a -m"commit message"
For git beginners, you should use the '-a' flag for 'commit'. It allows you to ignore git's staging area. Once you become more familiar with git, you'll come to appreciate the staging area.
**Note: The first line of your commit message should describe your change in a small sentence (50 chars or less). Add more details after one newline. Wrap the commit at 72 characters.**
You can examine your commit by doing:
$ git show
==== Updating Your Branch ====
To update your local sandbox branch with changes from the main repo:
# update local master branch with contents from remote repo
$ git checkout master
$ git pull --rebase
# Merge the master branch into your local sandbox branch
$ git checkout sandbox
$ git merge master
**Note: This must be a merge. Otherwise, the SHA1 hashes will change, and it will cause problems if you push this branch.**
To update your branch with changes from the developer repo:
# update sandbox with contents from remote repo
$ git checkout sandbox
$ git pull --rebase
# rebase your changes on top of the new commits from sandbox
$ git checkout bug_fix
$ git rebase sandbox
**Note: You can rebase here, since you will not be pushing the bug_fix topic branch.**
==== Pushing Changes to Your Developer Repo ====
Once you're done editing your branch, you can merge it into the 'sandbox' branch and push to the remote repo's 'sandbox' branch:
# checkout the sandbox branch and merge in your changes
$ git checkout sandbox
# merge bug_fix branch into sandbox, collapsing all commits
$ git merge --squash bug_fix
# Now commit the changes
$ git commit -a -m"Commit message"
# See what the commit looks like
$ git show
# Before you push, see which commits you're about to push
$ git log minix-sandbox/sandbox..sandbox
# dry-run of git push to make sure everything's ok
$ git push --dry-run
# push to the sandbox branch in the remote repo
$ git push
Note: this will collapse all the changes in your 'sandbox' branch into one commit to master.
If the push fails, it's most likely because your local 'sandbox' branch is out of date. You can update master by doing:
$ git pull --rebase
$ git push
==== Pushing Changes to the Main Repo ====
Pushing changes to the main minix repository directly is **not possible**. Instead, we use a reviewing system for patches, which are automatically pushed to the main repository once approved. Right now, for developers without direct access to the gerrit reviewing system, we request that you create a [[https://github.com/Stichting-MINIX-Research-Foundation/minix/pulls|pull request on the MINIX3 GitHub page]]. Someone with the appropriate access will then do the rest for you. Thank you!
====== Merging ======
Fast-forwards. What's that? Well, it's a simple concept but you can't really tell from the name. It's just a word for a set of commits that can be applied to someone else's current state by simply replaying them, i.e. without merging. The changes are a pure extension. If you pull someone else's changes in, and you have no locally committed changes, then that pull will simply be a fast-forward. More significantly, if you want to push your own changes, but you're pushing to a place that has diverged, i.e. received commits since you started making your local commits, git will complain if the change does not result in a fast-forward, i.e. the change has to be merged with the other change. Do this by pulling over the new changes, then pushing again, effectively rebasing your working copy. Put simply, pull has the power to merge (it's fetch + merge), push does not.
====== Committing ======
To commit, use //git commit -a//, which is the equivalent of svn commit, i.e adding and committing changes in all tracked files:
Once you become more comfortable with git, you can skip the '-a' and make full use of the staging area. The staging area is where you stage your current commit before it is actually committed to the repository. If you change or add files in/to a working directory, 'git commit' still won't do anything. You have to explicitly say 'git add' to added files and changed files. Then they get added to the staging area, and you can commit them. This also means there are is no single 'svn diff' equivalent, something I use quite a lot to see 'what am i about to commit.' There are two git diffs: 'git diff' shows you the differences between your working copy and the staging area, i.e. the difference between your working copy and the staged copy. 'git diff --staged' shows you what *staged* changes there are between the Staging Area and the latest commit, i.e. what you are about to commit. Most of the time the staging area and the current commit will have the same copies. You will probably use 'git diff' to find out what changes you have made to the working copy, then 'git add' to put those changes into the Index, then 'git commit' to put those changes into a new commit.
If you want to get something unstaged, do 'git reset.' If you want to get the original file back before your changes, do 'git checkout .'
If you want to modify a commit, you can use:
# Redo a commit (if you forgot a file, for instance)
$ git commit -a -m"Awesome commit" --amend
# Undo a commit (leaving changes in working tree)
$ git reset HEAD^
====== Inspecting Your Git Repository ======
If you want to inspect the repository, you can use 'git log':
# Standard log
$ git log
# Also shows a diffstat
$ git log --stat
# Also shows the patch
$ git log -p
# Shorter history (shows first line of commits)
$ git log --summary
# Another format
$ git whatchanged
You can use 'git diff' to see what local changes you've made:
# Diff your local tree against the last commit
$ git diff
# Diff your staged changes against the last commit
$ git diff --staged
To find out what branches are in your repository:
# List only local branches
$ git branch
# Also list remote branches
$ git branch -a
You can search the repository using 'git grep':
# grep entire repo
$ git grep kernel_call
# grep only subdir
$ git grep kernel_call ./kernel
====== Git Policies and Recommendations ======
* Don't work on the master branch or any public branches directly. Create a local branch instead, so you can keep the public branches clean.
* Don't rebase commits that you've pushed to a public repository. That is, on long-lived feature branches (e.g., sandbox), you shouldn't rebase against other branches.
* Don't make unnecessary merge commits. Always do a //git pull --rebase//
* Don't use 'git push --force'
* Don't commit extraneous whitespace. Before you do a commit, you should do a 'git diff' and make sure you don't see any red.
* Use the commit message format from Pro Git, especially the part about the first line being only 50 characters or less:
Short (50 chars or less) summary of changes
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body. The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Typically a hyphen or asterisk is used for the bullet, preceded by a
single space, with blank lines in between, but conventions vary here
* Use your minix3.org email address when committing.
====== Git web interface and Mirrors ======
There is git web interface at http://git.minix3.org.
There are also automatic mirrors on github.com:
* MINIX: https://github.com/Stichting-MINIX-Research-Foundation/minix.git
* PKGSRC: https://github.com/Stichting-MINIX-Research-Foundation/pkgsrc.git
There are also manually updated mirrors on repo.or.cz:
* URLs: git://repo.or.cz/minix.git and http://repo.or.cz/r/minix.git)
* URLs: git://repo.or.cz/minix-pkgsrc.git and http://repo.or.cz/r/minix-pkgsrc.git)
* URLs: git://github.com/minix3/minix.git and https://github.com/minix3/minix.git)
* URLs: git://github.com/minix3/pkgsrc.git and https://github.com/minix3/pkgsrc.git)
TODO: Add gitorious mirror
====== Granting Commit Access ======
We are using gitosis to do our account management for developers and those who need commit access to our repostiories. Gitosis is a very thin layer between git on unix and providing read/write access to many other users. Not even the Gitosis admin(s) need unix access in order to add/remove users and groups, add git repositories, and manage access. Users are identified by ssh keys. Gitosis is controlled by cloning and committing to its config file and keyfile directory.
If you have access (i.e. a Gitosis admin has added your keyfile, and has given your key Gitosis admin powers), clone the Gitosis config and update it like so. The example is adding someone's keyfile. The git repository syntax implies ssh. the unix user is always Gitosis, and users are identified using which ssh keys were used to connect.
$ git clone git@git.minix3.org:gitosis-admin
$ cd gitosis-admin
$ cp ~/user1.pub keydir
$ vi gitosis.conf
(refer to this user as 'user1' in adding him to groups or repository lines)
$ git add keydir/user1.pub gitosis.conf
$ git commit
$ git push
For more information: http://wiki.archlinux.org/index.php/Gitosis
====== Making Your Own Private Repository ======
To keep your personal working branches easily stored in more than once place, it is suggested to do this in your own repository ([[http://book.git-scm.com/3_distributed_workflows.html|git book chapter here]]). You can easily rebase your work on the master one, and merge your changes with master.
To do this in Gitosis, add a repository in gitosis.conf and let the minix group write to it, in this example minix-beng. Change into this:
[group minix]
members = @gitosis-admin
writable = pkgsrc minix minix-beng
And add this:
[repo minix-beng]
daemon = yes
description = Ben's repo
owner = Ben
Now, to fill your repository with the master repository, do this:
$ git clone git@git.minix3.org:minix
$ cd minix
To tell git about your remote repository and push the contents of the minix3-beng branch there:
$ git remote add minix-beng git@git.minix3.org:minix-beng
$ git push minix-beng master
Now, you have your own repository.
====== Advanced Git ======
===== Mailing Patches =====
Use 'git send-email' or TopGit'
===== Rebasing =====
For local branches that you will not be pushing, you can rebase your changes against master. This will preserve a linear history.
$ git checkout beng
$ git rebase master
Doing countless little experimental commits, e.g. to save your work remotely before doing a risky experiment, which would look messy in svn, is no problem; you can always rewrite history and clean up the commit history squeaky clean (i.e. reorder commits, merge commits together, take a commit right out) before merging your work with master. The swiss army chainsaw of commit editing is [[http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html|git rebase]]. See especially git rebase -i. But see also the warning about this changing commit id's - you can only do this if you're the only user of your branch. [[http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#problems-With-rewriting-history|problems with rewriting history]].
====== TopGit ======
!TopGit is recommended. See the [[http://repo.or.cz/w/topgit.git?a=blob;f=README|TopGit Readme]] and this [[http://blog.grogmaster.com/2008/12/topgit-means-never-having-to-wait-for.html|TopGit workflow]].
Basic workflow:
* tg create wip/
* Edit .topmsg (Will become commit message and your patch email) and .topdeps (list all patches/topic branches this patch depends upon)
* git commit -a -m"inital patch version"
* Keep modifying your patch and making commits
* To update your branch from master, do a tg update (TopGit will recursively update all branches this branch depends upon)
* To mail out your patch: tg mail
* To push to the main repo: tg export submit/ (This will collapse the branches like --squash)
* Then, git checkout master
* git merge submit/
* git push
====== Further Reading ======
If you want to learn more about git, check out the [[http://progit.org|Pro Git book]] and the [[http://gitcasts.com|Gitcast Videos]]. If you want to really get how git works under the hood, you should read [[http://ftp.newartisans.com/pub/git.from.bottom.up.pdf|Git From the Bottom Up]].
Here's the full list of git resources:
* [[http://schacon.github.com/git/everyday.html|Everyday GIT With 20 Commands Or So]]
* [[https://git.wiki.kernel.org/articles/g/i/t/GitSvnCrashCourse_512d.html|Git-SVN Crash Course]]
* [[http://book.git-scm.com|Git Book]]
* [[http://schacon.github.com/git/user-manual.html|Git User’s Manual]]
* [[http://schacon.github.com/git/gittutorial.html|A Tutorial Introduction to Git: Part One]]
* [[http://schacon.github.com/git/gittutorial-2.html|A Tutorial Introduction to Git: Part Two]]
* [[http://eagain.net/articles/git-for-computer-scientists|Git for Computer Scientists]]
* [[http://www-cs-students.stanford.edu/~blynn/gitmagic|Git Magic]]
* [[http://progit.org/book|Pro Git]]
* [[http://ftp.newartisans.com/pub/git.from.bottom.up.pdf|Git From the Bottom Up]]
* [[http://gitcasts.com|Gitcasts]]