# How to Resolve Merge Conflicts in Scientific Research

The most likely cause of a merge conflict in a research repository is two people editing the same lines of the same analysis script, manuscript section, or configuration file on two different branches. Git, the version control system that underpins most modern collaborative research code, can merge changes automatically when they touch different parts of a file. When two changes touch the same lines, Git refuses to guess which version is correct and stops the merge, marking the file as conflicted and waiting for a human decision.

The first thing to check is always the same. Run this command from the root of your repository:

```
git status
```

The output lists every file in one of three states. Files listed under "Unmerged paths" are the ones causing the conflict. Files listed as "both modified" contain conflict markers that you must edit by hand. Files listed as "both added" were created independently on both branches. Everything else usually merged cleanly and needs no action. In most research repositories, a single `git status` followed by opening the listed files in your editor resolves ninety percent of conflicts in under fifteen minutes.

This article explains why merge conflicts happen in scientific projects, how to diagnose them in a repeatable sequence, how to fix each common type, and how to set up your lab's workflow so conflicts become rare. The commands shown are standard Git commands documented in the official Git manual and work on macOS, Linux, and Windows (with Git Bash).

## Why Merge Conflicts Happen in Research Projects

Research teams generate merge conflicts more often than software teams for structural reasons. The review describes the core problem: modern investigations in biology often require groups of specialists from different fields who generate and share data of different formats and sizes, and without work automation and data versioning, teamwork quickly devolves into unmanageable confusion [1]. Merge conflicts are the visible symptom of that coordination gap.

The common causes, ordered from most to least frequent:

1. **Simultaneous edits to shared files.** Two analysts edit the same `analysis.R` or the same methods section of a manuscript. Git merges the file automatically if the edits are on different lines and raises a conflict if they overlap.
2. **Long-lived branches.** A feature branch that drifts for weeks (a new cohort analysis, a referee-response revision) accumulates divergence from the main branch. The longer the drift, the larger the conflict surface when the branches finally meet.
3. **Merge without pulling first.** An analyst starts work in the morning without pulling changes pushed by a collaborator the previous evening. The local history and the remote history diverge, and the eventual push or pull triggers a merge that may conflict.
4. **Generated files kept under version control.** Figures, processed data tables, and rendered reports are regenerated from code. If two collaborators regenerate the same output file from slightly different inputs or package versions, Git sees two different versions of a file that neither human intentionally edited.
5. **Formatting churn.** Auto-formatters, editor whitespace settings, and line-ending differences between Windows and macOS create line-level differences that look like content changes to Git.
6. **Merges of data and metadata files.** CSV sample sheets, JSON configuration files, and YAML parameter files are single long records. Any edit on both sides conflicts, because Git merges line by line.

Understanding the mechanism matters because the fix differs by cause. Overlapping human edits need a judgment call about content. Generated files need a decision to exclude them from version control. Formatting churn needs a shared configuration file. The Git primer for surgical data science frames this around four mental models (repository, commit, branch, and remote) and a dominant daily cycle of edit, stage, and commit, with branches and pull requests used for collaboration [2]. Conflicts occur precisely at the point where two branches, each carrying its own commits, must be combined into one history.

## The Four Mental Models You Need Before You Touch a Conflict

A conflict is confusing mainly when the underlying model is fuzzy. These four concepts, described in the Git primer for surgical research, are the basis for all Git usage and therefore for all conflict resolution [2].

- **Repository.** A repository is a project folder plus the complete history of every committed snapshot. The history lives in a hidden `.git` directory. Nothing you have committed is destroyed by a merge conflict, which is why conflicts are recoverable and rarely catastrophic.
- **Commit.** A commit is a numbered snapshot of your project at a moment in time, with a message describing what changed. Conflicts arise when two commits change the same content and no common ancestor commit can arbitrate.
- **Branch.** A branch is a movable pointer to a line of commits. The main branch usually holds the accepted analysis. Side branches hold work in progress. A merge combines one branch's commits into another.
- **Remote.** A remote is a copy of the repository on a hosting service such as GitHub. Git reminders to "pull" or "push" describe syncing your local history with the remote history.

One additional concept explains most research-specific conflicts: the **staging area** (also called the index). Between editing a file and committing it, you stage the file with `git add`. During a conflicted merge, the staging area holds three versions of each conflicted file: the common ancestor, your branch's version, and the incoming branch's version. Tools read those three versions to show you exactly what differs.

## A Diagnostic Sequence You Can Follow

Run these commands in order the next time a merge stops with a conflict message. Each step narrows the problem.

**Step 1. Confirm what Git was trying to do.**

```
git status
```

If the first line says "You have unmerged paths," a merge is in progress and waiting on you. If it says you are in the middle of a rebase or a cherry-pick, the resolution procedure is the same but the finishing command differs (covered below).

**Step 2. List only the conflicted files.**

```
git diff --name-only --diff-filter=U
```

This prints a short list. In a typical research repository it is one to four files, most often a script and a generated output.

**Step 3. See what each side changed.**

```
git log --merge --oneline -- path/to/file
```

This shows the commits on both branches that touched the conflicted file since the common ancestor. Reading those commit messages usually tells you whose change is newer and what each author intended.

**Step 4. Look at the conflict markers.** Open each conflicted file. Git has inserted markers that look like this:

```
<<<<<<< HEAD
cohort <- filter(cohort, age >= 18)
=======
cohort <- filter(cohort, age >= 21)
>>>>>>> feature-new-cohort
```

The section between `<<<<<<< HEAD` and `=======` is your branch's version. The section between `=======` and `>>>>>>>` is the incoming version. Everything outside the markers merged cleanly and needs no attention.

**Step 5. Decide per file whether to resolve, skip, or abort.** Resolution is covered in the next section. Aborting is always available and always safe for committed work.

## Troubleshooting Table

| Symptom | Likely cause | How to confirm | Fix |
|--|--|--|--|
| `git pull` or `git merge` stops with "CONFLICT (content): Merge conflict in ..." | Two branches edited the same lines of a text file | `git status` lists the file under Unmerged paths | Edit the file, remove the `<<<<<<<`, `=======`, `>>>>>>>` markers, keep the correct code, then `git add` the file and `git commit` |
| "CONFLICT (add/add)" on a file | Both branches created a file with the same name independently | The file appears as "both added" in `git status` | Compare the two versions (`git show :2:path` for yours, `git show :3:path` for theirs), keep the better one, delete the markers, add and commit |
| Conflict appears in a figure, table, or rendered report neither person edited by hand | A generated file was committed and regenerated on both branches | The conflicted file is an output (`.png`, `_files/` directories, knitted HTML) rather than source | Resolve once by regenerating from code, then add the output class to `.gitignore` so it never conflicts again |
| Conflict in a `.csv` sample sheet or metadata file | Two collaborators edited different rows of a line-oriented record file | Open the file, markers surround only some rows | Manually combine both sets of rows in the marked region, verify row counts, add and commit |
| Conflict in `requirements.txt`, `environment.yml`, or a package lock file | Both branches added or upgraded packages | The marker region shows differing dependency lines | Keep the union of required packages, deduplicate, re-run your environment install, add and commit |
| Every pull produces conflicts even after resolution | Commits are landing on the remote that local branches were never synced against, or a long-lived branch never merges | `git log, oneline HEAD...origin/main` shows growing divergence | Pull before each work session, merge or rebase the feature branch frequently, and keep branches short-lived |
| `error: Your local changes ... would be overwritten by merge` | You have uncommitted edits in files the merge would touch | `git status` shows modified files before the merge attempt | Commit or stash first (`git stash` saves them safely), then merge, then `git stash pop` |
| "fatal: Not possible to fast-forward, aborting" or a rebase stops repeatedly | Divergent histories that cannot merge automatically | `git log, graph, oneline, all` shows the fork point | Resolve conflicts one commit at a time during rebase, or use a plain merge for a single resolution |
| Conflict markers (`<<<<<<<`) accidentally committed and appear in the manuscript or code | Markers were saved but not removed before committing | Search the repository: `git grep '<<<<<<<'` | Remove all markers, correct the content, commit the cleanup, and tell collaborators who may have pulled the broken version |
| Merge appears stuck with no conflicted files listed | Untracked files would be overwritten by the merge, or a merge tool is waiting | `git status` shows untracked files with names matching incoming files | Move or rename the untracked files, or delete generated duplicates, then rerun the merge |

## How to Fix a Merge Conflict Step by Step

![Five-step flow from opening the conflicted file through editing markers, staging, committing, and verifying by running the analysis.](/article-images/illustrations/resolve-merge-conflicts-scientific-research-resolution-steps.webp)

This is the core resolution procedure for a content conflict in a script, manuscript, or any plain-text file. It is the same on every operating system.

### Step 1. Do not panic and do not delete the repository

A conflict stops the merge. It does not damage anything. Both versions of every conflicted file are stored in the repository's object database, and your committed history is untouched. Deleting the folder and re-cloning is the single most destructive reflex in research Git use, because it discards uncommitted work permanently.

### Step 2. Edit each conflicted file

Open the file in any editor. Modern editors including VS Code, RStudio, and Emacs color the conflict markers and offer click-to-choose buttons (Accept Current, Accept Incoming, Accept Both). Manually, you edit the marked region to produce one correct version and delete all three marker lines.

For the earlier example, a correct resolution keeping the stricter filter and the comment from the other branch might read:

```
cohort <- filter(cohort, age >= 21)
```

You are not limited to choosing one side. A resolution can combine both changes, rewrite the passage entirely, or delete content, as long as the result is valid code or prose and the markers are gone.

### Step 3. Choose sides programmatically when one branch is clearly right

When you know one version should win for the whole file, Git can apply it without manual editing:

```
git checkout --ours path/to/file
git checkout --theirs path/to/file
```

`-ours` keeps your branch's version. `-theirs` takes the incoming branch's version. During a rebase the meaning flips (you are replaying the other branch's commits), which is a common source of wrong resolutions, so confirm which side you are on with `git status` before using these flags.

### Step 4. Mark the file as resolved

```
git add path/to/file
```

Staging the file tells Git the conflict is settled. When every conflicted file is staged, the stoppage message in `git status` disappears.

### Step 5. Finish the merge

```
git commit
```

Git pre-fills a default merge commit message. Accept it or edit it to record why the resolution went the way it did, which is valuable context for collaborators reviewing the history. If the stoppage happened during a rebase, continue instead with `git rebase, continue` after staging the resolved files.

### Step 6. Verify the result

Before pushing, run the resolved code. For an analysis script, run it end to end. For a manuscript section, recompile. A conflict resolution that parses but breaks the analysis is the most insidious failure mode in research Git use, and the only reliable check is execution. The workflowr package addresses exactly this class of problem by building automatic checks and safeguards into an R-based analysis workflow, so that reproducibility failures surface immediately rather than silently propagating into shared results [3].

### Step 7. If the resolution went wrong, abort and retry

At any point before the final commit:

```
git merge --abort
```

This returns the repository to the exact state before the merge began. You can then try again with a different strategy, a different tool, or after consulting the collaborator whose change you are merging. If you have already committed a bad resolution, `git revert <commit>` creates a new commit undoing it, which is safe on shared branches. Resetting a shared branch with `git reset, hard` rewrites history and will strand every collaborator who has pulled, so reserve it for branches only you use.

## Conflicts Specific to Scientific Workflows

Generic Git advice covers scripts. Research repositories contain file types that behave badly in merges and need targeted handling.

### Generated outputs (figures, rendered reports, processed tables)

If a figure is committed and two collaborators regenerate it after pulling each other's code changes, Git reports a conflict in a binary or large file that no human deliberately edited. The durable fix is to version the code that generates the output and ignore the output itself. A `.gitignore` file, which the surgical data science primer details as the mechanism for keeping unwanted files out of the repository, handles this [2]. A typical research `.gitignore` includes entries for rendered reports, figure directories, and cache folders:

```
output/
*.png
*.pdf
*.html
.Rhistory
__pycache__/
```

The exception is final publication figures, which you may deliberately commit at the point of manuscript submission.

### Jupyter notebooks and R Markdown documents

Notebooks store code, outputs, and metadata in a single JSON file, so any edit plus any re-execution touches many lines and almost guarantees textual conflicts. Practical resolutions:

- Clear notebook outputs before committing (many teams add a pre-commit hook or use `jupyter nbconvert, clear-output, inplace`) so conflicts involve only code cells.
- When a conflict is unavoidable, resolve the code cells by hand and regenerate outputs by re-running the notebook rather than trying to merge output JSON by hand.
- For R users, the workflowr workflow sidesteps much of this by separating source R Markdown files from the generated website, committing the sources, and rebuilding the site reproducibly on demand [3].

### Data files

Version control systems are designed for text, not large data. Two collaborators editing a sample sheet will conflict on every shared region. Practices that reduce this:

- Keep row-level data files out of Git and store them on a [data management platform](/blog/guides/data-management-platform-what-it-is-and-how-to-choose-one). The laboratory information systems review describes dedicated systems including OpenBIS and SEEK for organizing research data flows, alongside project tools such as Redmine and Trello for coordinating work, so that all participants work with relevant information and results stay reproducible [1].
- Keep small, manually curated reference files (a sample manifest of a few dozen rows) in Git, but assign a single owner per file so two people never edit it simultaneously.
- When a CSV conflict does occur, resolve it in a spreadsheet or editor rather than in a terminal, verify the row count after resolution, and record the final version with a clear commit message.

### Manuscript files (LaTeX, Markdown, Word)

LaTeX and Markdown merge well when collaborators write in different sections and merge poorly when both revise the same paragraph. For Word documents, Git cannot merge content at all and will report every simultaneous edit as a binary conflict. Teams that must version Word files should serialize access (one person revises at a time, committed promptly) rather than attempt parallel editing through Git.

**Safety note on human data.** Identifiable patient data must never enter a version-controlled repository. The surgical data science primer gives this direct attention and details the use of a `.gitignore` file to prevent inadvertent commits of protected clinical data [2]. Before any merge resolution, check that conflicted or newly added files contain no patient identifiers. If identifiers have already been committed, the file must be removed from the repository history, not just from the current snapshot, and the incident handled under your institution's data governance procedure.

### Binary analysis artifacts

Binary files (images, proprietary format outputs, compressed archives) cannot be line-merged. Git reports them as conflicted wholes. Resolution is a choice of one version:

```
git checkout --ours results/model.rds
git add results/model.rds
```

Then regenerate the artifact from the merged code to confirm it matches the resolved pipeline.

## Merge or Rebase in a Research Setting

![Comparison table of merge and rebase across conflict timing, history shape, safety on shared branches, and the recommended research use.](/article-images/illustrations/resolve-merge-conflicts-scientific-research-merge-vs-rebase.webp)

Both commands integrate two lines of history, and the choice changes how conflicts appear.

A **merge** (`git merge feature`) combines the two histories in one commit. All conflicts across all changed files appear at once, you resolve them in a single session, and the resulting history shows exactly what was combined. This transparency is why merges are the sensible default for research repositories, where the audit trail of who did what, and when, carries scientific weight.

A **rebase** (`git rebase main` on a feature branch) replays your commits one at a time on top of the other branch's latest commit. Conflicts can therefore appear repeatedly, once per replayed commit. The reward is a linear history with no merge commits. The cost is more resolution events and a rewritten history that must never be force-pushed to a branch others have pulled.

A pragmatic policy for a lab: individuals may rebase their own private feature branches to stay current, but all integration into the shared main branch happens through merge commits, ideally via pull requests on GitHub so a second pair of eyes reviews the resolution before it lands. This branch and pull request pattern for collaboration is the workflow recommended in the surgical research Git primer [2].

## How to Prevent Merge Conflicts Across a Research Team

Resolution skill matters, but prevention compounds. These practices are ordered by impact per unit of effort.

**Pull before every work session and push at the end of every session.** Most conflicts are simply unsynced work colliding. A morning `git pull` and an end-of-day push keep divergence measured in hours, not weeks.

**Keep branches short-lived.** A branch merged within days has a small conflict surface. A branch that lives a month beside an evolving main branch will conflict badly no matter how carefully it is finally merged.

**Commit small and commit often.** Small commits isolate changes to few lines, which both shrinks conflict regions and makes each resolution a local decision rather than an archaeology project.

**Assign file ownership.** In a multi-analyst project, one person owns the sample sheet, one owns the environment specification, one owns each analysis module. Ownership does not forbid contributions, it sequences them through review.

**Coordinate on the data flow, not just the code.** The information systems review emphasizes defining the purpose and the set of tasks a system should solve before adopting tools, then monitoring that the recommendations are followed [1]. Concretely, a lab meeting decision such as "processed data lives in the OpenBIS project, only scripts and small manifests live in Git, figures are regenerated, never committed" eliminates an entire class of conflicts by policy rather than by heroics.

**Adopt a structured workflow tool.** For R-based teams, workflowr integrates version control, literate programming, automatic reproducibility checks, and a browsable project website, and its interface is deliberately simple enough for novice users to adopt [3]. The checks catch the broken-resolution cases that human review misses, and the shared website gives collaborators a single current version of results, reducing the parallel-document divergence that seeds conflicts.

**Use GitHub pull requests for all shared-branch changes.** GitHub for researchers functions as more than storage. A pull request shows the proposed changes, runs any configured checks, and lets a collaborator comment before integration. Conflicts discovered at pull-request time are resolved deliberately with the author present, rather than discovered at deadline time by whoever merges last.

## Common Mistakes and Limitations

- **Deleting the repository and re-cloning at the first conflict.** This destroys uncommitted work. Committed work survives conflicts by design. Exhaust `git merge, abort` and `git stash` before considering anything destructive.
- **Resolving conflicts without running the code.** A resolution that satisfies Git can still break the pipeline. Re-execute the affected analysis before pushing.
- **Committing conflict markers.** A file pushed with `<<<<<<<` in it breaks every collaborator's code at the next run. Search for markers with `git grep '<<<<<<<'` before pushing, and fix any that slipped through immediately.
- **Using `-force` pushes on shared branches.** Force-pushing after a botched rebase rewrites history that collaborators have already built on. Recover your own branch with `git reflog` instead of forcing history onto others.
- **Treating Git as backup for data.** Git versions text efficiently and large binary data poorly. Data files belong in a [data management](/blog/guides/data-management-basics-principles-processes-and-best-practices) system or institutional storage, with metadata and provenance recorded so results remain reproducible [1].
- **Assuming resolution order is arbitrary.** When conflicts interact (a renamed function in one branch, edits to its old call sites in the other), resolving file by file in the wrong order produces code that runs but is wrong. Resolve interacting conflicts together and run the full pipeline.
- **Individual circumstances vary.** This article gives general technical guidance for research repositories. Repository policy for data governance, authorship-related code release, and journal code availability requirements is set by your institution and target journals, and specific cases should follow those local requirements.

## Frequently Asked Questions

### What does a merge conflict actually mean in a research repository?

It means Git found two commits that changed the same lines of the same file and cannot determine which version to keep. The merge stops, the affected files are marked as unmerged, and Git inserts `<<<<<<<`, `=======`, and `>>>>>>>` markers showing both versions so a human can decide. Nothing is lost or overwritten until you resolve.

### Can I lose data when I resolve a merge conflict?

Not your committed work. Every commit is stored permanently in the repository's history, and `git merge, abort` restores the pre-merge state exactly. The only real risk is discarding uncommitted edits, which is why committing or stashing work before starting a merge is the standard precaution.

### How do I resolve a conflict in a Jupyter notebook or R Markdown file?

Resolve the code cells or chunks by hand in a text editor, removing the markers, and then regenerate all outputs by re-running the notebook rather than merging the output JSON manually. To prevent recurrence, clear outputs before committing so that only code differences ever reach Git.

### Should I use merge or rebase in my analysis repository?

Use merge for integrating work into the shared main branch, because it preserves a transparent history of what was combined and resolves all conflicts in one session. Rebase is reasonable on your own private feature branch to stay current, but never force-push rebased history to a branch collaborators have pulled.

### What is git merge, abort and when should I use it?

`git merge, abort` cancels an in-progress merge and returns the repository to the exact state before it started. Use it whenever a resolution turns out to be wrong or you need to gather more information. You can always restart the merge afterward.

### How do we prevent merge conflicts in a multi-lab collaboration?

Pull before each work session, keep branches short-lived, commit small changes often, assign one owner per shared file, keep large data files in a dedicated data management platform instead of Git, and route all shared-branch changes through pull requests on GitHub so conflicts surface during review rather than at deadline.

### Can Git merge two versions of a results table or dataset?

Only if the file is plain text and the edits touch different lines. Two versions of a CSV with edits in the same rows will conflict and must be combined manually, with the row count verified afterward. Binary formats such as `.rds` or Excel files cannot be merged at all, so Git requires choosing one version and regenerating from the resolved code.

### What should I do if patient data was committed to the repository by mistake?

Remove the data from the entire repository history, not just the latest commit, add a `.gitignore` rule so the file class cannot be committed again, rotate any exposed identifiers or credentials, and report the exposure under your institution's data governance procedure. The use of `.gitignore` files to prevent inadvertent commits of identifiable patient data is the documented preventive control in the clinical research Git literature.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "What does a merge conflict actually mean in a research repository?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "It means Git found two commits that changed the same lines of the same file and cannot determine which version to keep. The merge stops, the affected files are marked as unmerged, and Git inserts conflict markers showing both versions so a human can decide. Nothing is lost or overwritten until you resolve."
      }
    },
    {
      "@type": "Question",
      "name": "Can I lose data when I resolve a merge conflict?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Not your committed work. Every commit is stored permanently in the repository history, and git merge, abort restores the pre-merge state exactly. The only real risk is discarding uncommitted edits, which is why committing or stashing work before starting a merge is the standard precaution."
      }
    },
    {
      "@type": "Question",
      "name": "How do I resolve a conflict in a Jupyter notebook or R Markdown file?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Resolve the code cells or chunks by hand in a text editor, removing the markers, and then regenerate all outputs by re-running the notebook rather than merging the output JSON manually. To prevent recurrence, clear outputs before committing so that only code differences ever reach Git."
      }
    },
    {
      "@type": "Question",
      "name": "Should I use merge or rebase in my analysis repository?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Use merge for integrating work into the shared main branch, because it preserves a transparent history of what was combined and resolves all conflicts in one session. Rebase is reasonable on your own private feature branch to stay current, but never force-push rebased history to a branch collaborators have pulled."
      }
    },
    {
      "@type": "Question",
      "name": "What is git merge, abort and when should I use it?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "git merge, abort cancels an in-progress merge and returns the repository to the exact state before it started. Use it whenever a resolution turns out to be wrong or you need to gather more information. You can always restart the merge afterward."
      }
    },
    {
      "@type": "Question",
      "name": "How do we prevent merge conflicts in a multi-lab collaboration?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Pull before each work session, keep branches short-lived, commit small changes often, assign one owner per shared file, keep large data files in a dedicated data management platform instead of Git, and route all shared-branch changes through pull requests on GitHub so conflicts surface during review rather than at deadline."
      }
    },
    {
      "@type": "Question",
      "name": "Can Git merge two versions of a results table or dataset?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Only if the file is plain text and the edits touch different lines. Two versions of a CSV with edits in the same rows will conflict and must be combined manually, with the row count verified afterward. Binary formats such as RDS or Excel files cannot be merged at all, so Git requires choosing one version and regenerating from the resolved code."
      }
    },
    {
      "@type": "Question",
      "name": "What should I do if patient data was committed to the repository by mistake?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Remove the data from the entire repository history, not just the latest commit, add a .gitignore rule so the file class cannot be committed again, rotate any exposed identifiers or credentials, and report the exposure under your institution's data governance procedure."
      }
    }
  ]
}
</script>

## Sources

1. [Laboratory information systems for research management in biology.](https://pubmed.ncbi.nlm.nih.gov/38213703/)
2. [Version Control for Surgical Data Science: A Primer on Git and GitHub.](https://pubmed.ncbi.nlm.nih.gov/42893433/)
3. [Creating and sharing reproducible research code the workflowr way.](https://pubmed.ncbi.nlm.nih.gov/31723427/)