Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions en/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
* [OpenOffice/LibreOffice integration](cite/openofficeintegration.md)
* [Share](collaborative-work/README.md)
* [Sharing a Bib(la)TeX Library](collaborative-work/sharedbibfile.md)
* [Merging a Bib(la)TeX Library with Git](collaborative-work/git-merge-driver.md)
* [Shared SQL Database](collaborative-work/sqldatabase/README.md)
* [Migration of pre-3.6 SQL databases into a shared SQL database](collaborative-work/sqldatabase/sqldatabasemigration.md)
* [Export](collaborative-work/export/README.md)
Expand Down
61 changes: 61 additions & 0 deletions en/collaborative-work/git-merge-driver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Merging a Bib(la)TeX Library with Git

When two people edit different entries of a `bib` file in a Git repository, Git often reports a merge conflict, because Git compares the file line by line and JabRef writes entries in a fixed field order.

[JabKit](../jabkit.md) offers a merge driver that compares the two versions entry by entry instead. Git then merges changes to different entries — and to different fields of the same entry — on its own, and reports a conflict only where both sides changed the same field.

## Setup

Register the driver once for your user account:

```bash
git config --global merge.jabref.name "JabRef semantic .bib merge"
git config --global merge.jabref.driver "jabkit git merge-driver --porcelain %O %A %B"
Comment thread
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.
```

If you run JabKit through `jbang`, replace `jabkit` by `jbang jabkit@jabref`.

Enable the driver in each repository holding a library, by adding this line to the repository's `.gitattributes` file:

```text
*.bib merge=jabref
```

## What the driver merges

The driver receives the common ancestor of both sides, your version, and the other version.
It writes your version plus the changes of the other side back into your file: for every entry, identified by its citation key, a field that only the other side changed takes the other side's value, and an entry that only the other side added or deleted is added or deleted.

Check warning on line 27 in en/collaborative-work/git-merge-driver.md

View workflow job for this annotation

GitHub Actions / vale-lint

[vale] reported by reviewdog 🐶 [write-good.Passive] 'is added' may be passive voice. Use active voice if you can. Raw Output: {"message": "[write-good.Passive] 'is added' may be passive voice. Use active voice if you can.", "location": {"path": "en/collaborative-work/git-merge-driver.md", "range": {"start": {"line": 27, "column": 255}}}, "severity": "WARNING"}
The entry type and the comment written above an entry are merged the same way.

Check warning on line 28 in en/collaborative-work/git-merge-driver.md

View workflow job for this annotation

GitHub Actions / vale-lint

[vale] reported by reviewdog 🐶 [write-good.Passive] 'are merged' may be passive voice. Use active voice if you can. Raw Output: {"message": "[write-good.Passive] 'are merged' may be passive voice. Use active voice if you can.", "location": {"path": "en/collaborative-work/git-merge-driver.md", "range": {"start": {"line": 28, "column": 55}}}, "severity": "WARNING"}

An entry is a conflict when both sides changed the same field to different values, changed the entry type or the comment differently, or when one side deleted the entry while the other side changed it.
Conflicting entries keep your version.
Everything outside entries with a citation key - `@String` definitions, the preamble, entries without a citation key, custom entry types, and the library properties - is taken from your version as it is.

Check warning on line 32 in en/collaborative-work/git-merge-driver.md

View workflow job for this annotation

GitHub Actions / vale-lint

[vale] reported by reviewdog 🐶 [write-good.TooWordy] 'it is' is too wordy. Raw Output: {"message": "[write-good.TooWordy] 'it is' is too wordy.", "location": {"path": "en/collaborative-work/git-merge-driver.md", "range": {"start": {"line": 32, "column": 198}}}, "severity": "WARNING"}

Check warning on line 32 in en/collaborative-work/git-merge-driver.md

View workflow job for this annotation

GitHub Actions / vale-lint

[vale] reported by reviewdog 🐶 [write-good.Passive] 'is taken' may be passive voice. Use active voice if you can. Raw Output: {"message": "[write-good.Passive] 'is taken' may be passive voice. Use active voice if you can.", "location": {"path": "en/collaborative-work/git-merge-driver.md", "range": {"start": {"line": 32, "column": 168}}}, "severity": "WARNING"}

The driver exits with `0` when it merged everything, which makes Git continue with the merge.
Any other exit code makes Git mark the file as conflicted.

## Resolving the remaining conflicts

`git pull` and `git merge` now apply all changes that JabRef can merge safely and keep your own version of everything else. Git marks the file as conflicted and JabKit lists the citation keys it could not merge, for example:

```text
1 entries could not be merged automatically:
Smith2020: changed on both sides with different content
```

Open the library in JabRef and give those entries their final content, then `git add` the file and commit the merge.

## When the driver refuses to merge

The driver writes the result the way JabRef saves a library.
Whenever that would lose content of one of the three versions, it leaves your file untouched, reports the reason, and exits with `1`, so that Git marks the file as conflicted.
Merge those libraries by hand.

| Message | Reason |
| --- | --- |
| `citation keys must be unique` | The library contains an entry twice under the same citation key. |
| `the file was not parsed without warnings` | JabRef could not read all of the file, for example because of a duplicate `@String` name or a malformed entry. |

Check warning on line 57 in en/collaborative-work/git-merge-driver.md

View workflow job for this annotation

GitHub Actions / vale-lint

[vale] reported by reviewdog 🐶 [write-good.TooWordy] 'all of' is too wordy. Raw Output: {"message": "[write-good.TooWordy] 'all of' is too wordy.", "location": {"path": "en/collaborative-work/git-merge-driver.md", "range": {"start": {"line": 57, "column": 70}}}, "severity": "WARNING"}
| `an entry without fields is not preserved` | The library contains an entry without fields, which JabRef drops when saving. |
| `a custom entry type without entries is not preserved` | The library defines a custom entry type that no entry uses; JabRef saves only the types in use. |
| `a comment in front of @Comment or @Preamble is not preserved` | A comment line precedes an `@Comment` block (library properties, custom entry types) or the `@Preamble`; JabRef keeps comments in front of entries and `@String` definitions only. |
| `content outside of entries with a citation key changed in OTHER` | The other side changed `@String` definitions, the preamble, an entry without a citation key, custom entry types, or the library properties, which the driver does not merge. |
26 changes: 14 additions & 12 deletions en/jabkit.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ jabkit --help
```bash
Usage: jabkit [-dhpv] [COMMAND]
-d, --debug Enable debug output
-h, --help display this help message
-h, --help Display this help message
-p, --porcelain Enable script-friendly output
-v, --version display version info
```
Expand All @@ -72,17 +72,19 @@ Usage: jabkit [-dhpv] [COMMAND]

```pre
Commands:
generate-citation-keys Generate citation keys for entries in a .bib file.
check-consistency Check consistency of the library.
check-integrity Check integrity of the database.
fetch Fetch entries from a provider.
search Search in a library.
convert Convert between bibliography formats.
generate-bib-from-aux Generate small bib from aux file.
preferences Manage JabKit preferences.
pdf Manage PDF metadata.
get-cited-works Get the cited works (bibliography).
get-citing-works Get the works citing the work at hand.
check Check the integrity and consistency of a library.
citationkeys Manage citation keys.
convert Convert between bibliography formats.
doi-to-bibtex Converts a DOI to BibTeX
fetch Fetch entries from a provider.
generate-bib-from-aux Generate small bib from aux file.
get-cited-works Outputs a list of works cited ("bibliography")
get-citing-works Outputs a list of works citing the work at hand
git Git integration for .bib files.
pdf Manage PDF metadata.
preferences Manage JabKit preferences.
pseudonymize Perform pseudonymization of the library
search Search in a library.
```

Hint: Using `jabkit <COMMAND> --help` will show the supported options for each command.
Expand Down
Loading