On this page

Six months into a research project, a directory may contain analysis.py, analysis_new.py, analysis_final.py, and analysis_final2.py. The filenames suggest an order, but they do not answer the important questions: Which file produced the figure in the thesis draft? What changed after the quality filter was corrected? Can the earlier calculation be recovered?

Git and GitHub provide a more reliable way to answer those questions. Git records snapshots of selected project files on your computer, each with an identifier and message. GitHub stores a copy of that Git repository online and adds sharing, discussion, and review. Together, they let a research team connect a result to a specific state of the code instead of relying on filenames and memory.

This guide is for researchers who have scripts and data folders but have not used version control. You will create a small research repository, exclude large data and generated output, make reviewable commits, and record the exact code used for a result.

The Problem Is Not Just Losing a File

Ordinary backup protects files against a failed laptop. Research reproducibility asks a different question: can you identify the code, input data, parameters, and software environment that produced a particular result?

Copying a project folder occasionally does not show which lines changed or why. A cloud-synced folder may preserve the newest file while still leaving several ambiguous versions. Git is designed to record a sequence of project states and compare them.

Git does not understand the scientific meaning of a change. It can show that a threshold moved from 0.2 to 0.3; the researcher must record why that change was valid and which outputs it affected.

Git and GitHub Are Different Tools

The two names often appear together, but they have different jobs.

ToolPlain-language meaningResearch benefit
GitA version-control system on your computerRecords snapshots, compares changes, and restores earlier code
RepositoryA project directory whose selected files and history Git tracksKeeps code, method notes, tests, and environment definitions together
CommitA named snapshot with a short explanationIdentifies the exact code state used for a result
BranchA separate line of work inside the repositoryLets you test a method change without immediately replacing reviewed work
GitHubAn online service that hosts Git repositoriesShares the history and adds issues, Pull Requests, and review

You can use Git without GitHub, including while offline. GitHub is not Git itself, and it is not a general backup service for every file on your computer.

Decide What the Repository Should Preserve

A useful research repository records the instructions and evidence needed to reconstruct an analysis:

  • Source code and small utility scripts
  • Method descriptions and parameter files
  • Tests and small synthetic test fixtures
  • Dockerfile, compose.yaml, and dependency definitions
  • README files that explain inputs, commands, and outputs
  • Data provenance, such as provider, product, retrieval date, and checksum

It usually does not contain:

  • Large raw or downloaded datasets
  • Collections of NetCDF files
  • Regenerable intermediate data
  • Caches, virtual environments, and notebook checkpoints
  • Every generated figure and report
  • Passwords, API keys, tokens, or private keys

A small reference result or synthetic dataset may belong in Git when it is needed for review or testing. The practical question is not “is this code?” but “does versioning this file help someone understand or verify the analysis?”

Start with a Research-Friendly Directory

This layout gives code, data, and results distinct roles:

research-project/
├── .gitignore
├── README.md
├── requirements.txt
├── method/
│   └── analysis-contract.yaml
├── src/
│   └── analyze.py
├── tests/
│   ├── test_analysis.py
│   └── fixtures/
├── data/
│   ├── README.md
│   └── raw/               # Present locally, ignored by Git
└── output/
    └── README.md          # Generated contents are ignored

The repository tracks the files that explain and execute the analysis. The large contents of data/raw/ and the replaceable contents of output/ remain on the researcher’s machine or in separate storage.

If your current project mixes everything in one directory, separate it before the first commit. That step makes later mistakes less likely.

Create the Repository

Install Git using the official instructions for your operating system, then confirm that the command is available:

git --version

Set the author information that will be recorded in new commits:

git config --global user.name "Your Name"
git config --global user.email "[email protected]"

Choose an email address that is appropriate to publish in commit metadata. GitHub also provides a private noreply address if you do not want a personal address exposed.

Then open a terminal in the project directory:

git init
git branch -M main
git status

git init creates the local repository. It does not upload anything. git status reports which files are untracked, modified, or staged without changing them, so it is a good command to run frequently.

Before adding files, create the ignore rules.

Keep Data and Generated Files Out with .gitignore

Add a .gitignore at the repository root:

# Raw and downloaded data
data/*
!data/README.md
!data/sample/
!data/sample/**

# Generated analysis output
output/*
!output/README.md

# Local configuration and credentials
.env
.env.*
!.env.example
secrets/

# Python and notebook caches
__pycache__/
*.py[cod]
.pytest_cache/
.ipynb_checkpoints/

# Local environments and editor files
.venv/
.DS_Store

The exception rules keep the explanatory README files and an optional small sample while excluding the large contents.

.gitignore only applies to files that Git is not already tracking. Adding a filename after it has been committed does not remove it from earlier history.

Document Data Instead of Uploading It

An ignored dataset still needs a tracked description. Add data/README.md:

# Input data

## Dataset

- Provider: [official provider and URL]
- Product or collection: [identifier]
- Retrieval or snapshot date: YYYY-MM-DD
- Spatial and temporal subset: [selection]
- License or access terms: [reference]

## Local layout

- `raw/`: files obtained from the provider; do not edit in place
- `derived/`: recreated with the preprocessing command below

## Obtain the data

Run:

`bash scripts/download-data.sh`

Expected SHA-256:

`filename.nc  expected-digest`

A stable dataset identifier, version, DOI, object version, or checksum is stronger than a download URL alone. The same URL may return updated data later.

For restricted data, document how an authorized researcher obtains access. Do not place credentials or redistributable copies in the repository.

Make the First Commit Deliberately

Stage named paths, then inspect exactly what will enter the history:

git add .gitignore README.md requirements.txt
git add method src tests data/README.md output/README.md
git status
git diff --cached
git commit -m "Initialize reproducible analysis project"

Staging is a review area for the next commit. git diff --cached shows the proposed snapshot before it is recorded.

A commit message should describe one coherent change. Examples include:

  • Add adjusted-temperature quality filter
  • Correct pressure-unit validation
  • Record parameters for North Pacific comparison

Avoid combining a scientific method change with unrelated renaming or formatting. Smaller commits make it easier to identify when a calculation changed.

Put the Repository on GitHub

Create an empty repository in the appropriate GitHub account or organization. Choose public or private access based on licenses, collaboration rules, unpublished work, and institutional policy.

GitHub displays a remote URL. Add it locally and push the reviewed history:

git remote add origin https://github.com/ACCOUNT/REPOSITORY.git
git remote -v
git push -u origin main

Replace the example account and repository. Use an approved browser login, credential manager, SSH key, or GitHub CLI for authentication. Never embed a personal access token in the remote URL, a script, or a README.

A private repository limits who can browse it, but it is not a reason to upload secrets or data you are not permitted to redistribute.

Use a Small Daily Workflow

You do not need an advanced branching strategy for a first research repository. Start with this loop:

git status
git diff

git add src/analyze.py tests/test_analysis.py method/analysis-contract.yaml
git diff --cached
git commit -m "Apply reviewed salinity filter"

git push

The important habits are:

  1. Inspect the unstaged changes.
  2. Stage only the files that belong to one decision.
  3. Inspect the staged changes.
  4. Commit with a message that explains the decision.
  5. Push so the shared repository contains the reviewed history.

Git records what changed. The method document and commit message should explain why.

Review Scientific Changes on a Branch

For a change that may alter results, create a branch:

git switch -c revise-qc-filter

Change the method description, code, and tests together. Run the analysis in the declared environment, inspect representative intermediate values and outputs, and push the branch.

A useful GitHub Pull Request explains:

  • Which scientific question or defect the change addresses
  • Whether variables, units, quality control, or equations changed
  • Which tests and analysis commands were run
  • Which outputs changed and why
  • Which decisions still need domain review

Review makes a change visible. An approval button alone does not prove the calculation is scientifically correct.

Connect a Result to Exact Code

When a reviewed result is used in a thesis chapter, report, or manuscript, record the commit identifier:

git rev-parse HEAD
git show --stat HEAD

You can also add a descriptive tag:

git tag -a analysis-v1 -m "Code used for the reviewed analysis"
git show analysis-v1
git push origin analysis-v1

Record that commit or tag together with:

  • The input-data snapshot or checksums
  • The parameter file
  • The software environment
  • The command used to produce the result

The Git identifier specifies code, not separately stored data or uncommitted parameters.

Where Large Research Files Belong

Choose storage based on the file’s role.

File typeSuitable location
Code, text configuration, method notesNormal Git
Small synthetic test fixtureNormal Git
A limited set of large files that must follow Git versionsConsider Git LFS
Large raw datasets and frequently regenerated binariesData repository or object storage
Publication dataset intended for citationRepository that provides a stable identifier or DOI
CredentialsPassword manager or secret-management system

Git LFS keeps a pointer in Git and stores the large object separately. It can be useful for a limited set of binaries, but storage, bandwidth, and per-file limits still apply. It is not automatically the right home for a changing multi-terabyte archive.

If a large file was staged but not committed, unstage it and add an ignore rule. To stop tracking a file while keeping the local copy:

git rm --cached data/raw/filename.nc

This does not erase the file from earlier commits. If a large or sensitive file was already pushed, follow GitHub’s documented cleanup procedure and coordinate with collaborators before rewriting shared history.

Never Treat Deleting a Secret as Remediation

Before each commit, inspect git status and git diff --cached. Keep .env files, API keys, access tokens, cloud credentials, private keys, and passwords outside Git.

If a credential enters a commit, assume it has been exposed. Revoke or rotate it first. Deleting the working file or adding it to .gitignore does not remove the value from repository history.

Git Is One Part of Reproducibility

Git and GitHub preserve code history and review. They do not preserve the Python interpreter, system libraries, or installed package versions. How to Make a Research Analysis Reproducible with Docker explains how to record that environment.

They also do not verify generated calculations. If you use an agent to modify analysis code, Codex and Claude Code for Research: Preventing Wrong Results provides a layered review process.

For Argo projects, OceanGraph can help identify profiles before a scripted study begins. Record downloaded profiles as input data: keep routine downloads outside Git, and write down the WMO ID, cycle, retrieval date, and reason for selection. The relevant product workflows are Search and Bookmark and Analysis Lab: Vertical Profiles.

A Practical Definition of Done

A research repository is useful when another authorized researcher can determine:

  • Which code produced a reported result
  • What changed between two versions
  • Where the input data came from
  • How to obtain or identify the same input
  • Which command and environment to use
  • Which tests and scientific checks were performed

Git supplies the history. GitHub supplies a shared place for that history and its review. The research team must still supply the method, provenance, validation, and interpretation.

If setting up this repository and review workflow inside your own team would be difficult, the inquiry link below can also be used to ask about setup and implementation support.

Contact

Implementation support and annotation services

Ask about setup, design, and implementation support, or annotation services.

Go to the contact form

Continue with:

Official references: