[COMING SOON] Git


Git access

For Use
Developers git clone $USER@git.test.NetBSD.org:/git/$REPO
Anonymous SSH git clone anongit@anongit.test.NetBSD.org:/git/$REPO
Anonymous HTTPS git clone https://anongit.test.NetBSD.org/$REPO
Browsing https://gitweb.test.NetBSD.org

Developers MUST clone from git.test.NetBSD.org in order to push to it. Developers MUST NOT push anything to git.test.NetBSD.org based on cloning or pulling from anongit.test.NetBSD.org.

Repositories

  main draft
NetBSD source src src@draft
NetBSD X11 source xsrc xsrc@draft
Packages pkgsrc pkgsrc@draft
Testing sandbox testsrc testsrc@draft

Main repositories.  The main repositories such as src and pkgsrc, without the @draft suffix, have only long-term branches and tags.

History rewriting (rebasing and pushing forced updates with git push -f) is forbidden, branches are never deleted, and—outside the vendor/* namespace—new branches may only be created by releng and admins.

Draft repositories.  The @draft repositories are for work in progress destined for future merge to a long-term branch, which may be created, rebased, rewritten, or deleted by any developer at any time.

A change by developer jrandomdev@NetBSD.org meant for the next NetBSD 11.x release to fix the veeblefitzer for PR 12345, for example, should be pushed to src@draft branch netbsd-11/jrandomdev-pr12345-fixveeblefitzer. When releng merges it into src branch netbsd-11 to complete the pullup, the draft branch will be deleted.

Git branches in the @draft repositories correspond to draft-phase changesets on topics in the Mercurial @draft repositories.

Developer workflow

Software prerequisites.  Install devel/git-base from pkgsrc. Create a file ~/.gitconfig with the following contents to configure what name Git will put on commits you make:

[user]
	name = J. Random Developer
	email = jrandomdev@NetBSD.org

You can alternatively configure Git on a per-repository basis instead by editing $REPO/.git/config instead; see the git-config(1) man page for more details.

To start.  Clone the Git repository:

$ git clone jrandomdev@git.test.NetBSD.org:/git/src

The initial clone may take a long time, and if interrupted, Git is unable to automatically save its progress and pick up where it left off. An alternative is to start with a shallow clone, and then—if you need the history—to iteratively deepen it with git fetch:

$ git clone --depth=1 jrandomdev@git.test.NetBSD.org:/git/src
$ cd src
$ git fetch --deepen=10000
$ git fetch --deepen=20000
$ git fetch --deepen=30000
...
$ git fetch --deepen=300000
$ git fetch --unshallow

Other alternatives are partial clones, for which the repository supports the filters blob:none (blobless) and tree:0 (treeless). See GitHub's blog post on partial/shallow clones for more information on when to choose which type of partial or shallow clone. You can also have multiple working trees sharing the same repository data, e.g. to work on checkouts of two different branches at the same time, using git-worktree(1).

To make and publish changes.  Once you have edited some files in the working tree, such as sys/kern/kern_wotsit.c:

  1. Record the changes in the staging area:
    $ git add sys/kern/kern_wotsit.c
  2. Create a local commit with the changes in the staging area and a commit message:
    $ git commit
    Make sure to cite any relevant problem report with the magic string PR $CATEGORY/$NUMBER in the commit message.
  3. Review your changes and the history and what you're about to push:
    $ git show
    $ git log --graph
    $ git push --dry-run
  4. Publish your changes to the central repository:
    $ git push

If someone else has already pushed changes since you last updated, you will see a message like this:

$ git push
To jrandomdev@git.test.NetBSD.org:/git/src
 ! [rejected]        default -> default (fetch first)
error: failed to push some refs to 'jrandomdev@git.test.NetBSD.org:/git/src'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Do not merge or use plain git pull; instead, rebase. We require a linear history, so you should fetch, rebase your changes, and retry:

$ git fetch
$ git rebase origin/default
$ git push

You can also use git pull --rebase instead of git fetch and then git rebase origin/default.

Note: Developers must set $USER@NetBSD.org or $USER@pkgsrc.org as the email address for changesets, by setting user.email in the per-user ~/.gitconfig or the per-repository $REPO/.git/config file.

If you already made a commit but can't push it because it has the wrong email address, you can fix it with git commit --amend --reset-author. If you made multiple commits, you can edit them with git rebase --interactive; see the git-rebase(1) man page for details. Using git log --graph default origin/default may help to identify the rebase parameters.

Note that the equivalent of cvs commit is three steps in git: 1. git add to record changes to be committed in the staging area (even changes to existing files, not just adding new files), 2. git commit to locally create a commit object, and then 3. git push to publish it to the central repository.

To track development.  From the src directory, fetch new changes from the central repository:

$ git fetch

If you don't have any local commits, you can update your working tree to the latest change:

$ git merge --ff-only origin/default

git merge --ff-only, perhaps confusingly, does not actually create merge commits; it just advances the current branch in what Git calls a fast-forward merge. We use (non-fast-forward) merge commits only for vendor branches. If you do have local commits, you need to rebase them—the history is required to be linear:

$ git rebase origin/default

If git rebase fails with merge conflicts, you must resolve them and record the resolution with git add, git commit, and git rebase --continue before proceeding. You can also git rebase --abort to go back to the way things were before you started rebase in case you want to start over.

You can also switch the working tree to different commits with git checkout or git switch, or switch the current branch to different commits with git reset. Beware: using these may leave commits without any ref pointing at them (e.g., a branch or a tag), which git may then delete at some point. Git treats refs as precious, but commits as potential garbage to be cleaned up periodically.

If you get lost.  Before you follow the xkcd git procedure, review the output of these commands, and share them with developers or admins you're asking for help, as well as the contents of ~/.gitconfig and $REPO/.git/config, and the output of any command you're having trouble with:

$ git status
$ git show
$ git log --graph --all

As an alternative, you can also use Mercurial instead.

Draft branches for work in progress and pullups

If you are working on a change that is not ready for commit, you can push to a draft branch the @draft repository where you are free to edit and amend it before it is applied to the main branch.

First, create a remote to track the @draft repository:

$ git remote add draft jrandomdev@git.test.NetBSD.org:/git/src@draft

To create a draft branch.  Switch to a new local git branch and make some commits on the branch:

$ git switch --create jrandomdev-pr12345-fixveeblefitzer
$ ... edit/commit/review ...

When you're ready to share it, push it to the draft remote under the name of the main branch it's meant to be applied to:

$ git push --set-upstream draft jrandomdev-pr12345-fixveeblefitzer:default/jrandomdev-pr12345-fixveeblefitzer

As others review the draft and request changes, you can amend it and push your updates with git push -f:

$ ... edit/commit --amend/review ...
$ git push -f draft jrandomdev-pr12345-fixveeblefitzer

(If you accidentally use git push -f with the main repository instead of the draft one, it will reject the forced push unless the -f made no difference anyway.)

To get at an existing draft branch.  If you want to review a draft branch that another developer has posted, you can fetch it from draft remote and create your own local branch to track it:

$ git fetch draft default/alyssaphacker-pr54321-turboencabulator
$ git switch --create alyssaphacker-pr54321-turboencabulator --track draft/default/alyssaphacker-pr54321-turboencabulator

When a draft branch is done.  We require the history to be linear, so first rebase the changes onto the main branch:

$ git fetch
$ git switch jrandomdev-pr12345-fixveeblefitzer
$ git rebase origin/default

If that succeeded with no merge conflicts (and if any applicable tests still pass), then you can merge it into the main branch:

$ git switch default
$ git merge --ff-only jrandomdev-pr12345-fixveeblefitzer
$ git push origin default

And you can delete the draft branch:

$ git push draft :default/jrandomdev-pr12345-fixveeblefitzer

In the future, we may make it mandatory for all changes to start as draft branches for automatic verification and testing before being merged to the main branch.

To draft a pullup.  If you have a change you want to pull up so that appears in the next NetBSD 11.x release, use git cherry-pick to apply it onto a draft branch destined for the netbsd-11:

$ git switch --create jrandomdev-pr31415-typofixes
$ git cherry-pick 01234abcd
$ git push --set-upstream draft jrandomdev-pr31415-typofixes:netbsd-11/jrandomdev-pr31415-typofixes

Then you can can ask releng to pull up the draft branch netbsd-11/jrandomdev-pr31415-typofixes.