====== Git Quick Start Guide ======
This page is to capture issues raised on IRC by other committers and users, so
we don't lose that info while it gets added to official documentation. The
steps here should mirror the more detailed instructions at the below URL:
* https://docs.freebsd.org/en/articles/committers-guide/#git-primer
====== Quick Start ======
===== Getting a git client =====
The simplest way to get started with git, today, is to install git from the
pre-packaged %%FreeBSD%% packages, or to build the same package yourself in the
usual fashion:
* the smallest package with least dependencies:
# pkg install -r FreeBSD git-lite
* the full blown git experience with many dependencies:
# pkg install -r FreeBSD git
* install from source build
# cd /usr/ports/devel/git && make install
You're now ready to go.
===== Getting the Repo =====
Pick an empty directory, let's call it ~/src/ports for example. A full clone
takes about 900MiB space. This step uses HTTPS so your ssh keys aren't yet
required.
# pick any GIT_PORTS_DIR you want
export GIT_PORTS_DIR=~/src/ports
# this step can take a while, in future it will be much quicker
git clone -o freebsd -b main https://git.freebsd.org/ports.git $GIT_PORTS_DIR
cd $GIT_PORTS_DIR
# now we add in your push URL, and fetching the old SVN notes so you can
# look for svn revisions in your git log
git remote set-url --push freebsd ssh://git@gitrepo.freebsd.org/ports.git
git config --add remote.freebsd.fetch "+refs/notes/*:refs/notes/*"
# now we enable "rebasing" which will float your latest commits to the top
# of the git tree, each time you pull new commits from the ports tree. This
# makes it very easy to catch up if somebody else committed in between your
# last fetch, and your attempted push.
git config pull.rebase true
# fetch the prepare-commit-msg hook
fetch https://cgit.freebsd.org/src/plain/tools/tools/git/hooks/prepare-commit-msg -o .git/hooks
chmod +x .git/hooks/prepare-commit-msg
You'll now need to add your username and user id, exactly as they are on freefall:
ssh you@freefall gen-gitconfig.sh
...
git config user.name "A Committer"
git config user.email "you@FreeBSD.org"
...
After these steps, you should have this in your ''%%$GIT_PORTS_DIR/.git/config %%'':
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "freebsd"]
url = https://git.freebsd.org/ports.git
fetch = +refs/heads/main:refs/remotes/freebsd/main
fetch = +refs/notes/*:refs/notes/*
pushurl = ssh://git@gitrepo.freebsd.org/ports.git
[branch "main"]
remote = freebsd
merge = refs/heads/main
[pull]
rebase=true
[user]
# these entries came from ssh you@freefall gen-gitconfig.sh
name = "A Committer"
email = "you@FreeBSD.org"
===== The First Pull =====
You can now "pull" in changes since your last update, just like "svn up",
for this specific branch. This first pull will also fetch the svn notes,
and any new commits at %%FreeBSD%%'s ports tree, that we don't yet have locally.
If I have any local commits that have not yet been pushed up to freebsd's
git repo, they will automatically be "rebased", which is floating my local
changes up to the tip of the git tree again. This ensures there's no conflicting
history on my local branch vs %%FreeBSD%%'s official history.
$ cd $GIT_PORTS_DIR
$ git pull freebsd main
remote: Enumerating objects: 45, done.
remote: Counting objects: 100% (45/45), done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 26 (delta 14), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (26/26), 4.40 KiB | 112.00 KiB/s, done.
From https://git.freebsd.org/ports
* branch main -> FETCH_HEAD
7143d361cb6b..ab8a59366f5a main -> freebsd/main
Successfully rebased and updated refs/heads/main.
==== Reviewing local git log ====
git's log subcommand has many options, but by default it shows you recent commits,
in last committed order, for the current branch. By default, the "tip" commit is
referred to as "HEAD" -- it's the most recent commit in your current working
directory. Once we make local changes, the local HEAD commit and the freebsd/main
commits won't be the same anymore.
$ git log --oneline
ab8a59366f5a (HEAD -> main, freebsd/main, freebsd/HEAD) x11-fonts/league-gothic: Update to 1.601
bafa49e87ea9 update check_ssl_cert to 2.0.0
...
===== Making changes =====
This is best served by following "Making Local Changes" on the official
https://docs.freebsd.org/en/articles/committers-guide/#git-primer docs,
but this should give you a ports-oriented view of that document.
* make a new branch if our changes are long-lived
* hack away
* stage our changes
* commit locally our changes
* rebase to pick up any upstream commits that we are missing
* push our changes back up
==== Make a branch ====
First we need to update our current status, to match the %%FreeBSD%% ports tree,
and then create a branch to work on. This is not mandatory, you can YOLO on
main locally and nobody will ever know, but it allows you to keep work in
progress ports in different branches easily, and supports advanced workflows
with git worktrees, which are covered in the git primer docs.
* check status
* update from freebsd tree
* create a branch
* get to work
$ git status
On branch main
Your branch is up to date with 'freebsd/main'.
nothing to commit, working tree clean
$ git pull --ff-only freebsd main
remote: Enumerating objects: 86, done.
remote: Counting objects: 100% (86/86), done.
remote: Compressing objects: 100% (52/52), done.
remote: Total 54 (delta 36), reused 1 (delta 1), pack-reused 0
Unpacking objects: 100% (54/54), 6.57 KiB | 103.00 KiB/s, done.
From https://git.freebsd.org/ports
* branch main -> FETCH_HEAD
532a4a844263..8ae6e04d5276 main -> freebsd/main
Updating 532a4a844263..8ae6e04d5276
Fast-forward
devel/ruby-build/Makefile | 2 +-
...
18 files changed, 57 insertions(+), 85 deletions(-)
create mode 100644 mail/wmbiff/files/pkg-message.in
...
$ git switch -c my-port-changes
Switched to a new branch 'my-port-changes'
==== Hack Hack Hack ====
You can always reset to the last commit with ''%%git reset --hard HEAD%%''.
If you have un-tracked files to purge, you can do so with ''%%git clean -ndx%%''
Remove the *-n* which is a dry-run flag.
$ cd cat/port
# hack hack hack
$ git status
On branch main
Your branch is up to date with 'freebsd/main'.
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git restore ..." to discard changes in working directory)
modified: Makefile
modified: distinfo
no changes added to commit (use "git add" and/or "git commit -a")
==== Staging Changes ====
This step is one of the most confusing for new-comers to git. Files exist in many states
in different places:
* new files, not part of git repo locally yet (untracked files)
* stuff you added, but is not "committed" locally in your ports tree (unstaged files)
* stuff already commited, that you have modified, but not "committed" locally (modified files)
* stuff committed and pushed upstream to %%FreeBSD%% official repo
''%%git status%%'' will always tell you what's happening, and ''%%git log%%'' will show you
the tip commit, or HEAD, of your local repo, and of the %%FreeBSD%% one too.
For now, remember that "staging changes" needs to be done before "committing changes" and
before "pushing my commits upstream".
$ git add .
## notice how the state of these files has changed from "not staged" to "to be committed":
$ git status
On branch main
Your branch is up to date with 'freebsd/main'.
Changes to be committed:
(use "git restore --staged ..." to unstage)
modified: Makefile
modified: distinfo
These changes are "staged" - you can have files in partial stages, with some diffs
in the file already staged, and other not yet staged. For the moment, just be aware
of this, and keep going.
$ git commit .
# your $EDITOR is summoned
You can replace . by specific filenames, a glob pattern, or the ''%%-A%%'' which is All
The Things.
Your editor will come up, with space for a commit message, and a summary of the files
git is expecting to add here. If you exit your editor here, with error code, or the
commit message is blank, no changes are made. At this point, all the changes are local
so you can keep fiddling until you get this right. Add a suitable message, see
https://docs.freebsd.org/en/articles/committers-guide/#commit-log-message for commentary.
cat/foo: Update to v1.2.3
- fixes the foobinator
- see https://example.org/CHANGELOG for details
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch main
# Your branch is up to date with 'freebsd/main'.
#
# Changes to be committed:
# modified: Makefile
# modified: distinfo
#
**Follow the Commit Message Convention**
Commit messages should follow the very common convention used by most git-hosted projects.
See https://docs.freebsd.org/en/articles/committers-guide/#commit-log-message for specifics.
The total line length (include 12 characters for commit SHA and whitespace) should be
less than 64 characters, to fit nicely in ''%%git log --oneline%%'', and in github, gitlab, gitea.
category/portname: Useful summary < 64 characters
A blank line, then additional information just as you would use in
svn for as many lines as you want.
At this point, we have:
* made some changes
* staged those changes
* committed **locally** those changes
* not yet pushed those upstream
You can safely change anything here - discard commits, re-edit files,
as nothing is public.
==== Reviewing local git log ====
git's log subcommand has many options, but by default it shows you recent commits,
in last committed order, for the current branch. By default, the "tip" commit is
referred to as "HEAD" -- it's the most recent commit in your current working
directory.
Here, you can see I have one *local* commit that hasn't yet been pushed up to
%%FreeBSD%% - the HEAD commit here is above the "freebsd/main" commit:
$ git log --oneline
e7edeb6d7cb7 (HEAD -> main) cat/foo: Update to v1.2.3
ab8a59366f5a (freebsd/main, freebsd/HEAD) x11-fonts/league-gothic: Update to 1.601
bafa49e87ea9 update check_ssl_cert to 2.0.0
...
I can see the diff I'm pushing in several ways. This one shows me the diff of the
tip commit:
$ git show HEAD
This one shows me the diff between what's upstream in %%FreeBSD%% (as of last git fetch/pull)
and my repo clone:"
$ git diff HEAD..freebsd/main
git diff HEAD..freebsd/main
diff --git cat/foo/Makefile cat/foo/Makefile
index 641245430b58..be61999c237a 100644
--- cat/foo/Makefile
+++ cat/foo/Makefile
@@ -2,7 +2,7 @@
PORTNAME= foo
DISTVERSIONPREFIX= v
-DISTVERSION= 1.2.2
+DISTVERSION= 1.2.3
...
==== Push Changes up to FreeBSD ====
This is the point of no return. Our local changes (commits) will be pushed up to %%FreeBSD%%'s
official repo, and just like a blockchain, any subsequent commits will need to be appended
after our ones.
There's a small problem, though, other diligent committers have already pushed their changes
upstream, and we don't have those yet. %%FreeBSD%%'s git repo doesn't allow diverging versions
of history, so we need to catch up the history, and "float" our changes up to the top of
the pile before committing. This process is called rebasing, and it sounds a bit scary, but
just works. Occasionally, if somebody else has modified the same files and git can't figure
out the right thing to do, we'll get an error here, and we will need to fix stuff up. A
great example is when two people try to use the same UNIX ID in GIDS/UIDs files, and there's
a "merge conflict". For the moment, let's ignore that, and assume the happy case.
# check there are no unmodified files lying around
$ git status -sb
## main...freebsd/main [ahead 1]
# pull in the upstream changes and float our diff to the top
$ git pull --ff-only freebsd main
remote: Enumerating objects: 137, done.
remote: Counting objects: 100% (137/137), done.
remote: Compressing objects: 100% (136/136), done.
remote: Total 137 (delta 38), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (137/137), 650.85 KiB | 4.97 MiB/s, done.
Resolving deltas: 100% (38/38), done.
From https://git.freebsd.org/ports
* branch main -> FETCH_HEAD
ab8a59366f5a..23642082e10d main -> freebsd/main
Successfully rebased and updated refs/heads/main.
Now, we're ready to push our commit up and be the tip (HEAD) commit of the official repo.
You don't need the -v flag but it might be interesting the first few times:
$ git push -v freebsd HEAD:main
Pushing to ssh://gitrepo.freebsd.org/ports.git
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 8 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 671 bytes | 671.00 KiB/s, done.
Total 6 (delta 3), reused 3 (delta 1), pack-reused 0
To ssh://gitrepo.freebsd.org/ports.git
23642082e10d..f190fc172c79 HEAD -> main
updating local tracking ref 'refs/remotes/freebsd/main'
$ git log
commit f190fc172c797a29e799f47373cf7004e30d2de8 (HEAD -> my-ports-changes, freebsd/main, freebsd/HEAD, main)
Author: Dave Cottlehuber
Date: Tue Apr 6 12:31:02 2021 +0000
cat/foo: Update to v1.2.3
At this point, we Crossed The Rubicon. We're live. Not in Kansas. Adults. Congrats!
==== Clean Up our Branch ====
All we need to do now is clean up and go to the pub. Except COVID, so cup of tea.
* switch back to our original branch
* see what the branches are related to
* bring it up to date with %%FreeBSD%% origin
* remove our temporary branch
$ git switch main
Switched to branch 'main'
Your branch is up to date with 'freebsd/main'.
$ git remote -v && git branch -vv
freebsd https://git.freebsd.org/ports.git (fetch)
freebsd ssh://git@gitrepo.freebsd.org/ports.git (push)
* main f190fc172c79 [freebsd/main] cat/foo: Update to v1.2.3
my-ports-changes f190fc172c79 cat/foo: Update to v1.2.3
$ git pull --ff-only freebsd main
From https://git.freebsd.org/ports
* branch main -> FETCH_HEAD
Already up to date.
$ git branch -d my-ports-changes
Deleted branch my-ports-changes (was f190fc172c79).
You'll notice above that, when we pulled changes from %%FreeBSD%% main into our main
git didn't need to fetch anything -- we already have all the changes locally, because
we just pushed them up.
===== Tips =====
* commit messages should be similar to ''%%cat/foo: Update to latest too v1.2.3%%'' see https://docs.freebsd.org/en/articles/committers-guide/#commit-log-message
===== Common Problems =====
==== ssh issues ====
$ git push
git@gitrepo.freebsd.org: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
This means that our git server is not accepting your public key. This should
be the same one used for your access to freefall. You can check this easily:
$ ssh git@gitrepo.freebsd.org
PTY allocation request failed on channel 1
hello $YOU, this is git@gitrepo running gitolite3 v3.6.12 on git 2.30.1
R W doc
R W ports
R W src
Connection to gitrepo.freebsd.org closed.
You can debug further using ''%%GIT_SSH_COMMAND="ssh -v" git ...%%'':
env GIT_SSH_COMMAND="ssh -v" git push
OpenSSH_8.4p1, OpenSSL 1.1.1k-freebsd 25 Mar 2021
debug1: Reading configuration data .ssh/config
debug1: .ssh/config line 1: Applying options for *
debug1: .ssh/config line 17: Applying options for *.freebsd.org
debug1: Reading configuration data /usr/local/etc/ssh/ssh_config
debug1: auto-mux: Trying existing master
debug1: Control socket "/tmp/.ssh-master-git@gitrepo.freebsd.org:22" does not exist
debug1: Connecting to gitrepo.freebsd.org [96.47.72.44] port 22.
debug1: Connection established.
...
debug1: No more authentication methods to try.
git@gitrepo.freebsd.org: Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
----
{{tag>Ports}}