· coding · 15 min read
GitHub and Git: A Field Guide for Practitioners
Python code reference and cookbook.

Context for the reader: This guide is part of my online commonplace book. It serves its purpose as a convenient personal reference, and I put online because several friends and work colleagues told me it’d be a good idea. I keep it to one page to ease long-term maintenance, to optimize for navigation with grep and Vim motions, and to lighten the burdens of cross-page complexity.
Who This Guide is For: I’ve only documented the tidbits on GitHub and Git I found most essential or the things that seemed I’d save a lot of time writing down instead of needing to figure out again. The goal here wasn’t to make a textbook or a beginner’s resource. Regardless of whether you’re junior, advanced, or a “grey beard”, some piece of this guide should be useful to you. Especially from the GitHub section.
GitHub Section Links
- GitHub
- GitHub CLI (gh) Cheatsheet
- GitHub Releases and Tags
- GitHub Workflows and
act
- GitHub Templates
- GitHub Badges from Shields
- GitHub Markdown
- GitHub Events
- GitHub: Cloning without Cloning
Git Section Linsk
- Git
GitHub
- GitHub CLI (gh) Cheatsheet
- GitHub Releases and Tags
- GitHub Workflows and
act
- GitHub Templates
- GitHub Badges from Shields
- GitHub Markdown
- GitHub Events
- GitHub: Cloning without Cloning
GitHub CLI (gh) Cheatsheet
Set the editor as vim instead of the default, nano.
gh config set editor vim
Other examples of gh config set
:
gh config set git_protocol ssh --host github.com
gh config set prompt disabled
# list commands
gh issue list
gh pr list
# list commands
gh pr status
gh repo view
gh pr create
: Creates a pull-request gh pr checks
:
GH Issues:
gh issue close
:
gh issue list
gh issue create --label bug
gh issue view 123 --web
[Click here to go back to the “GitHub” section]
GitHub Releases and Tags
A Git tag is similar to a Git reference, but the Git commit that it points to never changes. Git tags are helpful when you want to point to specific releases.
Tag objects (created with -a
, -s
, or -u
) are called “annotated” tags; they contain a creation date, the tagger name and e-mail, a tagging message, and an optional GnuPG signature. Whereas a “lightweight” tag is simply a name for an object (usually a commit object).
git tag -s v0.0.16 -m "Release description for v0.0.16"
Refs:
# set env var in sh script
export GPG_TTY=$(tty)
Delete a tag locally:
git tag -d [tag-name]
Delete a tag on origin:
git push origin --delete [tag-name]
[Click here to go back to the “GitHub” section]
Releasing Projects on GitHub
Releases are deployable software iterations you can package and make available for a wider audience to download and use.
Ref: https://docs.github.com/en/repositories/releasing-projects-on-github
About Releases (Docs): https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases
[Click here to go back to the “GitHub” section]
GitHub Workflows and act
Run and test workflows locally with nektos/act. Note that it depends on docker
to run the workflows.
Installation bash script
curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash
On MacOS:
brew install act
Example commands:
# Command structure:
act [<event>] [options]
If no event name passed, will default to "on: push"
# Run a specific job:
act -j test
# List the actions for the default event:
act -l
# List the actions for a specific event:
act workflow_dispatch -l
# Run the default (`push`) event:
act
# Run a specific event:
act pull_request
# Run in dry-run mode:
act -n
# Enable verbose-logging (can be used with any of the above commands)
act -v
[Click here to go back to the “GitHub” section]
GitHub Templates
## Problem
Provide a clear and concise description of what the bug is, including what currently happens and what you expected to happen.
## Steps to Reproduce
Please list the steps to reproduce the bug.
## Possible Solution(s)
Not obligatory, but suggest a fix/reason for the bug, or ideas how to implement the addition or change.
## Version
Include info on the commit, tag, release, machine used, or local environment.
[Click here to go back to the “GitHub” section]
GitHub Badges from Shields
Badges are concise, consistent, legible images for open source projects. They are common in GitHub README
s and other webpages and support many package registries, distributions, continuous integration services, and social networks. They look like this:
Badges come from shields.io. Its source code is hosted at github.com/badges/shields and serves roughly a billion images each month.
Colors
Color options are available with keywords, 6-symbol hex codes, and 3-symbol hex codes.
Template for a Custom Badge
https://img.shields.io/badge/<leftLabel>-<rightMsg>-<color>
[Click here to go back to the “GitHub” section]
GitHub Markdown
Notes, Tips, and Warnings
> [!NOTE]
> Highlights information that users should take into account, even when skimming.
> [!TIP]
> Optional information to help a user be more successful.
> [!IMPORTANT]
> Crucial information necessary for users to succeed.
> [!WARNING]
> Critical content demanding immediate user attention due to potential risks.
> [!CAUTION]
> Negative potential consequences of an action.
Becomes:
Ref: https://github.com/orgs/community/discussions/16925
Collapsible sections in markdown
Tags: dropdown, menu, collapse, expand


<details>
<summary>[Display Text]</summary>
### Markdown Content
</details>
[Show SVG text to copy]
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M6 7V54H61C61.7956 54 62.5587 54.3161 63.1213 54.8787C63.6839 55.4413 64 56.2044 64 57C64 57.7956 63.6839 58.5587 63.1213 59.1213C62.5587 59.6839 61.7956 60 61 60H3C2.20435 60 1.44129 59.6839 0.87868 59.1213C0.31607 58.5587 0 57.7956 0 57L0 7C0 6.20435 0.31607 5.44129 0.87868 4.87868C1.44129 4.31607 2.20435 4 3 4C3.79565 4 4.55871 4.31607 5.12132 4.87868C5.68393 5.44129 6 6.20435 6 7ZM63.12 17.12L42.12 38.12C41.5575 38.6818 40.795 38.9974 40 38.9974C39.205 38.9974 38.4425 38.6818 37.88 38.12L28 28.24L17.12 39.12C16.551 39.6496 15.7987 39.938 15.0215 39.9246C14.2442 39.9112 13.5024 39.597 12.952 39.048C12.403 38.4976 12.0888 37.7558 12.0754 36.9785C12.062 36.2013 12.3504 35.449 12.88 34.88L25.88 21.88C26.4425 21.3182 27.205 21.0026 28 21.0026C28.795 21.0026 29.5575 21.3182 30.12 21.88L40 31.76L58.88 12.88C59.449 12.3504 60.2013 12.062 60.9785 12.0754C61.7558 12.0888 62.4976 12.403 63.048 12.952C63.597 13.5024 63.9112 14.2442 63.9246 15.0215C63.938 15.7987 63.6496 16.551 63.12 17.12Z"
/>
</svg>
Understanding collapsible sections
The summary
block dictates what will be visible, and the remainder of the details
block is the content of the collapsible section.
NOTE: When including headings within collapsible sections, remember to add a new line after the summary
tag. In general, if you’re finding that something fails to render, add a line break after the closing </summary>
tag.
Customizing the clickable summary
block
Simply add normal HTML modifications to the summary
block.
<details>
<summary><i>Wow, so fancy</i></summary>
<b>WOW, SO BOLD</b>
</details>
Expanding details by default
You can start out the collapsible section by including the open
attribute within the <details>
tag.
<details open>
<summary>Summay block</summary>
Text open by default!
</details>
Nesting collapsible sections
<details>
<summary>Section A</summary>
<details>
<summary>Section A.B</summary>
<details>
<summary>Section A.B.C</summary>
<details>
<summary>Section A.B.C.D</summary>
Done!
</details>
</details>
</details>
</details>
[Click here to go back to the “GitHub” section]
GitHub Events
Pull Request Events
synchronize
(GitHubEvent): Triggered when a pull request’s head branch is updated. For example, when the head branch is updated from the base branch, when new commits are pushed to the head branch, or when the base branch is changed.
Pull-request checklist
- Describe how to test the PR
- Screenshot the new behavior if applicable
- Add a description for context on the chosen implementation strategy
- Refer to related issues/tasks/cards
- Resolve merge conflicts: Make sure the target branch is merged into the PR branch.
Self-review
- Add code comments for lines that reviewer might not understand correctly. Consider refactoring the names of variables and functions for clarity.
- DRY: Don’t repeat yourself
- KISS: Keep it simple, sweetie
- YAGNI: You aren’t gonna need it. Check that you are not overcomplicating something for the sake of “making it future-proof”. Fowler said “Yagni only applies to capabilities built into the software to support a presumptive feature, it does not apply to effort to make the software easier to modify”.
GitHub: Cloning without Cloning
This can be accomplished with subversion’s svn export
. This command allows you to download a single folder.
svn export https://github.com/<Owner>/<Repo>/trunk/<Path to Directory>
Installing subversion:
sudo apt-get update
sudo apt-get install subversion
# on mac
# brew install svn
[Click here to go back to the “GitHub” section]
Git
Fundamental Concepts
Initial Repo Configuration
git config user.name "UserName"
git config user.email gitHubAccount@email.address
Local branch vs. remote branch
- local branch: a branch only the local user can see. It exists only on your local machine.
- Ex. Create local branch named “myNewBranch”:
git branch myNewBranch
- Ex. Create local branch named “myNewBranch”:
- remote branch: a branch on a remote location (in most cases ‘origin’). Local branches can be pushed to ‘origin’ (a remote branch), where other users can track it.
- Ex. Push local branch, “myNewBranch”, to the remote, “origin” so that a new branch named “myNewBranch” is created on the remote machine (“origin”):
git push -u origin myNewBranch
- Ex. Push local branch, “myNewBranch”, to the remote, “origin” so that a new branch named “myNewBranch” is created on the remote machine (“origin”):
- remote tracking branch: A local copy of a remote branch. When ‘myNewBranch’ is pushed to ‘origin’ using the command above, a remote tracking branch named ‘origin/myNewBranch’ is created on your local machine.
- local tracking branch: a local branch that is tracking another branch.
source(s): SNce & Brian Webster.stackoverflow.com
HEAD, master, and origin
I highly recommend the book “Pro Git” by Scott Chacon. Take time and really read it, while exploring an actual git repo as you do.
- HEAD: the current commit your repo is on. Most of the time HEAD points to the latest commit in your current branch, but that doesn’t have to be the case. HEAD really just means “what is my repo currently pointing at”.
In the event that the commit HEAD refers to is not the tip of any branch, this is called a “detached head”. - master: the name of the default branch that git creates for you when first creating a repo. In most cases, “master” means “the main branch”. Most shops have everyone pushing to master, and master is considered the definitive view of the repo. But it’s also common for release branches to be made off of master for releasing. Your local repo has its own master branch, that almost always follows the master of a remote repo.
- origin: the default name that git gives to your main remote repo. Your box has its own repo, and you most likely push out to some remote repo that you and all your coworkers push to. That remote repo is almost always called origin, but it doesn’t have to be.
HEAD
is an official notion in git.HEAD
always has a well-defined meaning.master
andorigin
are common names usually used in git, but they don’t have to be.
source: HEAD, master, and origin. Matt Greer & Jacqueline P. via stackoverflow.com
Branching
Suppose your application is stable. Later, you discover a gigantic bug that was passing silently. You want to write some tests, fix the bug, and eventually have a stable, passing application once again. To do this, you’d create a branch for the fix and push the branch to the remote so that all of the developers on your team can collaborate and make the fix.
Once all of the necessary changes have been made and the application is stable, someone from the team would commit merge the commits from the other branch into master. Since the commit history from the branch will have been saved to master, the new branch could be deleted without loss of information (if you no longer wanted to work on this branch).
- View all local branches:
git branch
- Switch branches:
git checkout [branch-name]
- Grab a file from a specific branch:
git checkout [branch_name] [paths]
. Note that if the files are on a remote branch, you’ll have to usegit checkout origin/[branch_name] [paths]
instead.
Merging
Merge the specified branch’s history into the current one. git merge [branch]
Deleting branches
Delete local branch git branch -d [branch-name]
Delete remote branch git push origin --delete [branch-name]
Git flow
When working on a new feature, branch off from the develop
branch:
git checkout -b newFeature develop
git checkout -b newBranch
: creates a new branchgit checkout -m newBranch
: Renames the current branch
Merge finished features into the development branch to add them to the upcoming release. Use the “no fast forward” flag, --no-ff
, to cause the merge to create a new commit object even if the merge could be performed with a fast-forward. This avoids losing information about the historical existence of a feature branch and groups together all commits that together added the feature.
git checkout develop
git merge --no-ff newFeature
git branch -d newFeature
git push origin develop
Git: Editting commit history
Permanently removing files from commit history
WHy do this? You may have commited a password, some other sensitive information, or a large file that you want to remove from github. If the change is only a few commits back, you can “rebase” changes out of the history. I actually need to do this for a much older set of files and accidentally uploaded a textbook that takes up almost a GB of space.
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PathToSensitiveFile" --prune-empty --tag-name-filter cat -- --all
All you need to change is the PathToSensitiveFile
item. Once you’ve used this command for all of the files you’d like to get rid of, update the origin by typing git push origin --force --all
.
How to merge a specific commit from another branch?
Ex.: git cherry-pick [commit-codename]
Making a small edit to the most recent commit
git commit --amend
This allows you to combine staged changes with the previous commit without writing a new commit. It simply edits the previous one in-place.
To amend with an updated commit message: git commit --amend -m "updated message"
To amend without changing the commit message: git commit --amend --no-edit
Commit part of a file rather than all of its changes
git add —patch [file-name]
Ref: https://stackoverflow.com/a/1085191
Git: Special Topics
Git Aliases
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.ac '!git add -A && git commit'
Changing remote after a repo name change
If you change the name of a repository, the fetch/pull commands may stop working. Git will show you an error along the lines of “error: failed to push some refs to '{repo_url}.git'
”.
To check which URL the remote references to, use git remote -v
. Then, set a new URL for remote origin:
git remote set-url origin {new_repo_url}
Large File Storage
See https://git-lfs.github.com
When the .gitignore just won’t ignore
git rm -rf --cached .
git add .
If you already have unstaged changes, you must run the following after editing the ignore patterns.
git update-index --skip-worktree <file-list>
You can reverse this with:
git update-index --no-skip-worktree <file-list>
SSH keys
An SSH key is an alternative to username/password authorization on GitHub. This will allow you to bypass entering your username and password for future GitHub commands.
SSH keys come in pairs, a public key that gets shared with services like GitHub, and a private key that is stored only on your computer. If the keys match, you’re granted access.
The cryptography behind SSH keys ensures that no one can reverse engineer your private key from the public one.
Generating a new SSH key: Follow Generating a new SSH key and adding it to the ssh-agent [article]
References:
- A successful Git branching model. [web]
Commit SHA Hashes
Secure Hash Algorithm (SHA) in git refers to a cryptographic hash algorithm. There are variants like SHA-1, SHA-256, etc. In git, “SHA” usually refers specifically to SHA-1 hashes.
A commit SHA is a 40-character hexadecimal string that uniquely identifies a git commit. It is calculated by applying the SHA-1 hash to the commit contents. This allows referring to commits by an ID that is based on the commit contents.
”SHA reference” means referring to a commit by its actual SHA hash rather than by a symbolic name such as the branch or tag name. This is unambiguous since the SHA is unique to that exact commit.
The main differences between the SHA-1 and SHA-256 hash algorithms are:
Topic | SHA-1 | SHA-256 |
---|---|---|
Digest Length | SHA-1 produces a 160-bit (20 byte) hash value. | SHA-256 produces a 256-bit (32 byte) hash value. |
Security | There are known cryptanalytic attacks against SHA-1. | Considered more secure against brute force collisions and attacks than SHA-1. |
Speed | SHA-1 is generally faster to compute than SHA-256. The simpler process results in better performance. | |
Adoption | SHA-1 is still more widely used and is the default git | |
algorithm. | SHA-256 adoption is growing due to the security weaknesses of SHA-1. |
SHA-256 trades some speed for significantly improved cryptographic strength over the now dated SHA-1 algorithm.
Git Submodules
Submodules allow you to embed a git repository as a subdirectory inside another git repository. They allow using another project while still maintaining separation between the two projects.
The outer project contains just the commit SHA of the inner project. This reference is stored in .gitmodules
. Cloning the outer project doesn’t automatically clone the submodule’s code. You need to initialize and update submodules expressly.
git submodule add
: Command for including submodules.git submodule init
: Clones the submodule contents to the proper location.git submodule update
: Syncs the submodule to the correct reference commit.
Submodules allow nested git repos with separate histories and pushing. Making changes in the submodule requires pushing from within the submodule itself. Committing in the outer project records a new SHA reference to the submodule. The parent repo controls which submodule commit is used via the SHA reference.