Git & GitHub Workflow
A guide to version control, collaboration, and keeping a lasting computational record.
§1 Why this matters
The laboratory notebook is science's canonical record. It documents what was done, when, and why: establishing intellectual priority and enabling others to reproduce and extend your work. Computational science requires the same discipline. A script run once, saved locally, and never versioned carries no more lasting value than an experiment written on a scrap of paper. Git is a laboratory notebook for code.
The GitHub repository is also where shared infrastructure is built and maintained. Pushing your code makes it available for PI review and for collaborators to build on. It also creates the foundation for eventual public release, so that others can reproduce your results. When you leave the lab, your work remains here.
Pushing regularly with meaningful commit messages is how the team can help you. Code visible only on your local machine cannot be reviewed or assisted. Treat every commit as a scientific record entry: describe what changed and why.
§2 Prerequisites
Complete the following before working with any Raredon Lab repository. Contact the PI or a senior lab member if you are stuck at any stage.
-
1
Create a personal GitHub account
If you do not already have one, create a free account at github.com. Choose a professional username: this account will be associated with your publications and scientific identity.
-
2
Provide your username to the PI
You will be added as a collaborator on relevant Raredon Lab repositories and will receive an email invitation that must be accepted before you can fork or contribute.
-
3
Install a Git interface
New users: install GitHub Desktop, which provides a clear graphical interface for all routine Git operations. Experienced users may use the command line or manage Git through Claude and other AI tools (see §12).
-
4
Configure Git with your identity
Open a terminal and run the following. This name and email will appear in all your commits.
git config --global user.name "Your Full Name"
git config --global user.email "your.email@yale.edu"
§3 The fork model
Each lab member works from their own personal copy of a repository, called a fork, and proposes changes back to the shared lab copy via pull requests. This design keeps the shared codebase protected while maintaining full PI visibility into all active work.
Initial setup flows downward (fork, then clone). Daily work and pull requests both flow on the right side: commit/push from local to personal fork, pull request from personal fork up to origin dev. Merging dev into main is reserved for the PI.
| Tier | Naming convention | Branches | Who manages |
|---|---|---|---|
| Origin — the lab's authoritative copy | RaredonLab/repo-name |
main + dev |
PI; initialized from the RaredonLab account |
| Personal fork — your working copy | username/repo-name-AB |
dev (minimum) |
You; forked from origin, cloned to your machines |
The main branch of the origin repository may not be pushed to or targeted by pull requests without explicit PI authorization. It holds only fully functional, milestone-worthy code. All active development happens in dev.
§4 Setting up a repository
All new repositories must be created from the RaredonLab GitHub organization account, not from a personal account. Initialize the repository with both a main and a dev branch, set dev as the default, and add lab members as collaborators via Settings → Collaborators.
Forking and cloning (each lab member, one time per repository)
-
1
Navigate to the origin repository on GitHub
Go to the RaredonLab repository while signed in to your personal account.
-
2
Fork to your personal account
Click the Fork button in the top right. Append your initials to the repository name so your fork is immediately identifiable: if the origin is
LungAtlas, name your forkLungAtlas-AB. Fork thedevbranch at minimum; includemainif your role requires it. -
3
Clone to your local machine
Clone your personal fork (not the origin) to your laptop and/or HPC workspace. In GitHub Desktop: File → Clone Repository, then select your fork. On the command line:
git clone https://github.com/yourusername/repo-name-AB.git
cd repo-name-AB
You now have three connected copies: the origin on RaredonLab GitHub, your personal fork on GitHub, and your local clone on disk. All three stay in sync through the commit → push → pull request cycle described in §7.
§5 Standard repository structure
Analysis repositories routinely involve data objects in the 20–50 GB range: large R objects, spatial transcriptomics outputs, processed count matrices. None of this lives in Git. Git holds code, documentation, and lightweight HTML vignettes. Large data and outputs live on the HPC or designated shared storage, with their exact file paths clearly declared at the top of every script that uses them.
The following structure is the recommended default for analysis repositories. Keep it shallow — avoid nesting beyond what is shown here.
repo-name-AB/
│
├── functions/ # Reusable helper functions (generalized, documented)
│ ├── helpers_viz.R
│ ├── helpers_qc.R
│ └── helpers_io.R
│
├── scripts/ # Numbered, dated, initialed analysis scripts
│ ├── 01_20250301_AB_preprocessing.R
│ └── 02_20250308_AB_clustering.R
│
├── markdowns/ # Rmarkdown analysis files
│ ├── 01_20250301_AB_eda.Rmd
│ └── 02_20250308_AB_results.Rmd
│
├── docs/ # Knit HTML vignettes — committed to Git
│ └── 01_20250301_AB_eda.html
│
├── figures/ # Small figures for README / docs only
│ └── .gitkeep
│
├── output/ # Large outputs — NOT committed (gitignored)
│ └── .gitkeep
│
├── data/ # Raw data — NOT committed (gitignored)
│ └── .gitkeep
│
├── .gitignore
├── README.md
├── CLAUDE.md # AI context file — see Document 06
└── repo-name.Rproj
Git does not track empty directories. A blank file named .gitkeep inside output/ and data/ preserves the folder structure in the repository even though the contents are gitignored. Create one with touch output/.gitkeep.
Avoid creating subdirectories within the folders above. Deep nesting makes paths long and fragile, and creates confusion when scripts move between machines or collaborators. If a project feels too large for this structure, ask whether it warrants a second repository rather than adding more directories.
§6 The .gitignore
Every Raredon Lab repository must include a .gitignore that excludes large data objects, generated outputs, session files, and credentials. Copy the following into the root of every new repository on first commit.
# ── R session artifacts ─────────────────────────────────────────────
.Rhistory
.RData
.Rproj.user/
# ── Large R data objects (never commit) ─────────────────────────────
*.rds
*.rda
*.RData
# ── Genomics and spatial data files (never commit) ──────────────────
*.h5
*.h5ad
*.h5seurat
*.loom
*.mtx
*.fastq
*.fastq.gz
*.bam
*.bai
# ── Output and data directories (contents excluded) ─────────────────
output/*
!output/.gitkeep
data/*
!data/.gitkeep
# ── OS and editor noise ─────────────────────────────────────────────
.DS_Store
Thumbs.db
*.swp
*~
.vscode/
# ── Credentials — never commit ──────────────────────────────────────
.Renviron
*.env
secrets/
API keys, HPC passwords, database credentials, and access tokens must never appear in a Git repository, private or otherwise. Store credentials in .Renviron (which is gitignored) and access them in R via Sys.getenv("MY_KEY"). If you accidentally commit a credential, notify the PI immediately and rotate the key before doing anything else.
§7 Daily workflow
After initial setup, your routine has four steps: make changes locally, commit, push to your personal fork, and open a pull request when a meaningful unit of work is ready. The first two happen throughout a working day; the last two happen daily at minimum.
-
1
Make changes locally
Write and edit code in your local clone, on your laptop or HPC. All work begins here.
-
2
Stage and commit your changes
Commit at logical stopping points, and always at the end of the day. In GitHub Desktop, review your changed files, write a commit message (see §8), and click Commit to dev. On the command line:
git add -A
git commit -m "Add UMAP step to clustering pipeline; parameterize resolution in helpers_qc.R"
-
3
Push to your personal fork
Push committed changes to your fork on GitHub, not to the origin. In GitHub Desktop, click Push Origin. On the command line:
git push origin dev
-
4
Open a pull request to origin dev
When you have a meaningful unit of work ready, open a pull request from your fork's
devbranch toRaredonLab/repo-name'sdevbranch. You may self-approve and merge if there are no conflicts. Tag the PI if you want review. See §9 for details.
Committing and pushing to your personal fork at the end of every working day is required. Code that exists only on your local machine is invisible to everyone else: it cannot be reviewed or helped with, and if your machine fails, it is gone. It takes one minute and is not optional.
§8 Commit practices
Frequency
Commit whenever you complete a logical unit of work: a new function, a resolved bug, a completed analysis step. During complex or exploratory work, committing every 30–60 minutes protects against loss and creates a readable trail. During lighter work, end-of-day commits are sufficient. End-of-day commits are never optional.
Commit messages
A good commit message says what changed and why. It does not need to be long, but it must be specific. The commit history is a scientific record and should be interpretable by someone who was not present when the code was written, including yourself in six months.
Add QC filtering step with doublet removal via scDblFinder; update helpers_qc.R to accept min.cells param
Fix incorrect file path in helpers_io read_seurat(); update expected input format in docstring
Initial commit: scRNAseq preprocessing pipeline for rat lung cohort 1, n=6 samples
fixes
wip
update
asdf
If you are unsure how to describe your changes, ask Claude. Describe what changed or summarize your diff and ask for a commit message. Review and edit the result before committing. The message must be accurate, and you should stand behind what it says. See Document 06 for the full AI usage standard.
§9 Pull requests
All code moving from a personal fork into the shared origin repository travels through a pull request, including straightforward changes with no conflicts. The pull request is the formal record of what changed and why, and it creates an opportunity for comment before code enters the shared codebase.
Opening a pull request
Navigate to your personal fork on GitHub and click "Contribute" → "Open pull request." Verify that the base repository is RaredonLab/repo-name and the base branch is dev. Write a descriptive title and a brief summary. If the PR implements a specific analysis step or resolves an issue, say so.
Self-approval
You may approve and merge your own pull request if there are no merge conflicts and the changes do not touch shared infrastructure: the helper functions in functions/, the CLAUDE.md, the .gitignore, or the README.md. Changes to shared infrastructure should be flagged for PI review regardless of conflict status.
Requesting PI review
For significant changes — new analysis pipelines, refactored helpers, anything affecting how other team members use the repository — add the PI as a reviewer with a note explaining what you would like reviewed and any open questions.
All pull requests from personal forks target the dev branch of the origin. Merging dev into main is a deliberate, infrequent operation performed only by the PI or an explicitly authorized lab member, and only when the codebase has reached a stable, fully functional milestone.
§10 Branch rules
| Branch | Lives in | Purpose | Who may merge into it |
|---|---|---|---|
main |
Origin only | Fully functional, milestone-worthy code. The stable scientific record. | PI and explicitly authorized individuals only |
dev |
Origin + all personal forks | Active development. The shared team working space. | Lab members via pull request from personal fork |
For routine work, no additional branches are needed within your personal fork. If a large experimental feature warrants isolation, discuss it with the PI before creating feature branches. Keep the branching model as simple as possible.
§11 File naming conventions
Consistent file naming allows anyone to understand who created a file, when, and in what order without opening it. Every file you create should be interpretable from its name alone.
The standard pattern
NN_YYYYMMDD_AB_descriptive-name.ext
| Component | Meaning | Format |
|---|---|---|
NN |
Sequence number within the analysis | Two-digit integer: 01, 02, 03 |
YYYYMMDD |
Date of creation or last major revision | ISO 8601, no separators: 20250315 |
AB |
Author initials | 2–4 uppercase letters: NW, NK, SE, MSBR |
descriptive-name |
What the file does or contains | Lowercase words separated by hyphens; no spaces or underscores between words |
01_20250301_AB_preprocessing-qc.R
02_20250308_AB_clustering-umap.Rmd
03_20250315_CD_spatial-niche-analysis.Rmd
helpers_20250220_MSBR_visualization-utils.R
01_20250301_AB_eda-overview.html # knit vignette in docs/
The same convention applies to figures, exported tables, and any output files not committed to Git. Name a saved plot 02_20250308_NW_umap-celltype.pdf, not plot_final_v3.pdf. Date stamps on outputs make it possible to match figures to the code and data versions that produced them.
§12 Using Claude and AI tools with Git
AI tools have an explicit, encouraged role in the workflow described here. The goal is to use AI for the mechanical parts of version control so you can focus on the science.
Writing commit messages
Claude writes good commit messages. If you are uncertain what to write, describe your changes in plain language or paste a summary of your diff and ask Claude to draft a message. Review and edit it before committing: the message must be accurate, and you should understand what it says.
The CLAUDE.md file
Every repository should contain a CLAUDE.md file in the root directory. This file gives Claude essential context about the repository: what it does, how it is structured, where data lives, what conventions apply, and the current state of active work.
When you open a Claude session to work on code in a repository, load the CLAUDE.md as context first. Update it when significant structural changes occur: new analysis phases, restructured helpers, new datasets, or major shifts in direction. The CLAUDE.md is a living document and should be treated as such.
The longer-term goal is that each lab member's Claude, working from a current CLAUDE.md, can interact with and learn from the shared codebase, enabling a form of AI-assisted cross-pollination between team members' work. See Document 06 for the full standard.
Git commands via AI
Claude can help with Git syntax when you are unsure. Describe what you want to accomplish and ask for the command. Read and verify the output before running it, particularly for anything involving --force, reset, rebase, or operations that modify history.
§13 Common mistakes to avoid
Not pushing regularly
Code that exists only on your local machine is invisible to the rest of the lab. It cannot be reviewed or helped with, and if your machine fails, it is gone. Push to your personal fork at the end of every working day. During intensive work, push every hour or two. This habit takes seconds and provides considerable protection.
Deep directory nesting
Nested subdirectories make file paths long and fragile, and create confusion when scripts move between machines or collaborators. Keep repositories shallow. If a project feels too large for the recommended structure, ask whether it should be split into two repositories rather than adding more directories.
Committing large files
Git is not designed for large binary files. An accidentally committed .rds or .h5 file becomes part of the repository's permanent history and can make cloning very slow. Verify that your .gitignore is in place before your first commit. If a large file is accidentally committed, notify the PI before attempting to remove it from history.
Pushing to the origin directly
Never push changes directly to the RaredonLab origin repository, even with permission to do so. All changes flow through your personal fork and a pull request. This keeps the shared codebase protected and ensures every change has a review checkpoint.
Vague commit messages
A commit labeled update or wip is not a useful scientific record. When you are writing a methods section or trying to reproduce a figure months later, you will not know what that commit contained or why it mattered. Write a specific message every time, or ask Claude to help.
Git mistakes are recoverable in almost all cases. If you are unsure what to do, especially before running reset, rebase, or any force push, ask the PI or a senior lab member first. A few minutes of consultation can prevent hours of recovery work.