simfish:

Source Control

This workflow installs and configures GNU/Git, the decentralized version control system.

cover image


Requirements


Usage

To use this litdoc workflow, first download this file & build it.

guix ld build sc

To make git and associated codeberg-cli available in the current shell use,

guix ld sc

To load Emacs integration, run M-x workflow-select within an Emacs session. Then follow the on screen prompt and select sc.

Dependencies

This workflow installs git from the official GNU/Guix repository.

(specifications->manifest (list
   "git"
   "git-lfs"
   "codeberg-cli"))

Shell Integration

Shortcuts for quickly collecting git repository information.

gr: show full path to the root of the current git repository(if any).

gr(){
 git rev-parse --show-toplevel $@
 return $?
}

gg:shortcut to git status

gg(){
  git status
}

gl:show git log of the current repository.

gl(){
  git log $@
}

gu:undo last git commit

gu() {
   git reset --soft HEAD~1
}

gun:undo the last N git commits,

gun(){
   git reset --soft HEAD~${1:-1}
}

signoff:sign-off the last git commit of the current repository

singnoff(){
  git --amend --sign-off
}

Emacs Integration

Customization

Enable/Disable Emacs integration with forejo based code hosting

(defcustom sc:enable-forgejo-integration t
  "Forejo integration enable or disable(nil)"
  :type 'boolean)

When forgejo based code integration is enabled, this variable can be used to define the host base URL. The default value is codeberg.org.

(defcustom sc:forgejo-host "https:://codeberg.org"
  "Forgejo instance host URL"
  :type 'string)

Keybindings

Emacs Key Bindings

(kb::def :states 'normal
  "g"   '(:ignore t        :which-key  "git")
  "gs"  '(magit-status     :which-key  "status")
  "gl"  '(magit-log        :which-keu  "log"))

Forge

(when sc:enable-forgejo-integration
    (kb::def :states 'normal
        "g#"  '(magit::forge-push  :which-keu  "forge push")))

Packages

Package: magit

magit is the de-facto standard for integrating git with Emacs.

(use-package magit
   :guix (:name emacs-magit)
   :config
     (message "magit config ready!")
   :commands
   (magit-blame-mode
      magit-commit
      magit-log
      magit-status)
   :general
    <<magit-kb>>)

magit extension for working with Forge based hosts such as https://codeberg.org:

(use-package agitjo
    :guix (:name emacs-agitjo)
    :after magit
    :init
    (defun magit::forge-push ()
      (interactive)
      (require 'agitjo)
      (agitjo-push))
    :commands
    magit::forge-push 
    :config
    (agitjo-setup "#"))

Package: forgejo

Front-end for codeberg.org and Emacs integration

(use-package forgejo
    :guix (:name emacs-forgejo)
    :commands
    forgejo-vc
    :custom
    (forgejo-hosts '(("https://codeberg.org")))
    ;; Example watch rules
    (forgejo-watch-rules
     '(("thanosapollo/emacs-forgejo")
       ("guix/guix" . "state:open label:team-emacs")
       ("*" . "author:<your username>")))
    (forgejo-watch-filter-default "read:no"))
forgejo-vc

Application Notes

Git Workflow

The key to using git is crafting a good commit. A good commit should do one thing concisely and has to leave the repository in a working state. That's about it.

Commit Messages: the subject-line should describe what changed and why the change was introduced in 50 chars or less. And prefer imperative forms when possible.

if commit is applied, then [insert commit subject-line]This should make real good sense

Git Workflow? All things being equal, choose the simplest workflow. The forking workflow is one example See Forking workflow .

SSH Access: enable SSH protocol with git remote set-url command:

git remote set-url origin  [git@coffee.hub.com:user/path.git]

If you have not already setup an SSH key, one can be generated using the ssh-keygen command.

mkdir -p ~/some/personal/directory
pushd ~/some/personal/directory

#create two SSH keys for the sake of demonestration

ssh-keygen -t ed25519 -C "me@workforcofee"   -f "${HOME}/.ssh/coffee"
# => ~/.ssh/coffee.pub, public key
# => ~/.ssh/coffee,  private key

ssh-keygen -t ed25519 -C "me@workforbeans"   -f "${HOME}/.ssh/beans"
# => ~/.ssh/beans.pub, public key
# => ~/.ssh/beans, private key

# Register the keys on this machine
ssh-add coffee
ssh-add beans

Add the generated keys to ~/.ssh/config Notice, to unregister a given key-file you can run ssh-add -D ~/.ssh/coffee

Host coffee.hub
  HostName coffee.hub.com
  User     git
  IdentityFile ~/.ssh/coffee

Host git.beans
  HostName git.beans
  User git
  IdentityFile ~/.ssh/beans

Patch Workflow

Problem working in a code base, maybe big and complex like Emacs, and you want to make small modifications, patches, to each release or update with minimal merge conflict related issue.

Solution keep each patch simple and independent. Place each patch into its own branch.

That is, first get a fresh copy of upstream updates. Switch to a new branch to be used for the patched codebase.

git checkout -b tracking
git pull orgin main

Merge each patch branch one at a time and use --no-off option to help keep branch history. If there is a merge conflict, since each patch is small it should be much easier to address.

git merge --no-ff patch1
git merge --no-ff patch2
git merge --no-ff patch3

Test the tracking branch & finally merge it to the main branch.

Signing Commits

Git supports signing and verifying work, commits and tags, using GPGsn:]].

Select GPG Key: For the sake of simplicity assume there is one or more GPG key availablesn:]].To select from a list of available keys run,

gpg --list-keys --keyid-format long

pub   <PRIMARY-KEY-INFO>/<KEY_ID> <CREATE-DATETIME> [SC] [expires: <EXP-DATETIME]
      <FINGERPRINT>
uid                  <USER-INFO> <EMAIL>
sub   <SUB-KEY-INFO>/<SUBKEY-ID> <CREATE-DATETIME> [E] [expires: <EX-DATETIME>]

Take a note of <KEY-ID> and make sure the key is tagged with [S] which stands for signing. For example if the key is marked with [E], that means it can only be used with encryption.

Configuring git: add the selected <KEY-ID> to git configuration(.git/config).

git config user.signingkey <KEY-ID>
git config gpgSign true

Add GPG Key to Gitlab: add the public GPG key to Gitlab to enable commit verification following their guide. The public key can be generated using,

gpg --armor --export > gpg.public.txt

Signing Commits: once configured git commits and tags can be signed off using the --sign-off or its short form -S option,

git commit -S -m "commit description"

Also, git log --show-signatuers can be used to verify commits were signed off properly.