Skip to content

Add git integration for automatic commit, push, and pull - #2118

Open
alichtman wants to merge 12 commits into
mainfrom
git_autocommit_and_push_integration
Open

alichtman wants to merge 12 commits into
mainfrom
git_autocommit_and_push_integration

Conversation

@alichtman

Copy link
Copy Markdown
Contributor

Related to #921. I, like some others that use jrnl, have a git repo backing my jrnls up to a remote git repo. This allows me to sync my jrnls across multiple machines. It is currently a manual process, and this PR adds some infra to automate it + configure it.

This also unblocks the addition of jrnl mobile apps, which will rely on a remote git repo for syncing across devices.

Supersedes #2062 (moved from a fork branch to a branch on this repo now that I'm a maintainer here).

Summary

  • Automatically commit journal changes to git when git: true is set per-journal or backup_all_jrnls_with_git is set globally. Adds GitPython dependency.
  • Auto-pull from remote before reading entries with auto_pull_from_git_remote_before_edit (uses fetch + fast-forward instead of git pull to avoid unexpected merges).
  • Auto-push to remote after writing with auto_push_to_git_remote_after_edit.
  • Add --git/--no-git CLI flags to override git operations for a single invocation.

Test plan

  • Unit tests for jrnl/git.py (init, commit, pull, push, error handling)
  • Unit tests for journal write git integration (file and folder journals)
  • Unit tests for git config validation
  • BDD feature tests covering commit, push, pull, and --no-git flag scenarios
  • Manual testing
  • CI
  # 1. Lint (matches CI exactly)
  poetry run ruff check .
  poetry run black --check .

  # 2. All unit tests
  poetry run pytest tests/unit/ -x -q

  # 3. All BDD tests
  poetry run pytest tests/bdd/ -x -q

  # 4. Specifically the tests that were failing — git features
  poetry run pytest tests/unit/test_git.py tests/unit/test_journal_write_git.py tests/unit/test_parse_args.py -v

  # 5. BDD git tests (push, pull, commit, no-git)
  poetry run pytest tests/bdd/test_features.py -k "git" -v

  # 6. Upgrade tests (the square brackets flow-style bug)
  poetry run pytest tests/bdd/test_features.py -k "upgrade" -v

  # 7. Full CI-equivalent run (lint + tox)
  poetry run poe test

Checklist

  • I have read the contributing doc.
  • I have included a link to the relevant issue number.
  • I have checked to ensure there aren't other open pull requests
    for the same issue.
  • I have written new tests for these changes, as needed.

alichtman and others added 12 commits August 8, 2026 16:13
Automatically initialize a git repo and commit after every journal write
when the per-journal `git: true` or global `backup_all_jrnls_with_git`
config key is set. Optionally push to the first configured remote with
`auto_push_to_git_remote_after_edit: true`. Supports both file and
folder journals. Adds GitPython dependency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pull from the configured remote before reading journal entries so that
changes made on other machines are incorporated automatically. Controlled
by a new `auto_pull_from_git_remote_before_edit` config key (global or
per-journal, default false). On merge conflicts the pull raises a
JrnlException directing the user to resolve manually.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace git pull with fetch + fast-forward for better performance. The
common "already up to date" case now only updates remote refs without
touching the working tree. Diverged histories raise a clear error
instead of attempting a merge.

Add --git/--no-git CLI flags to enable or disable all git operations
(commit, pull, push) for a single invocation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add config reference entries for backup_all_jrnls_with_git, git,
auto_pull_from_git_remote_before_edit, and
auto_push_to_git_remote_after_edit. Document --git/--no-git CLI flags
and add a Git Integration section to advanced usage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…port)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The --git/--no-git CLI flags added git_enabled to parsed args but the
test helper was missing it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
jrnl/journals/__init__.py re-exports the Journal class as
jrnl.journals.Journal, shadowing the module of the same name.
patch("jrnl.journals.Journal.git_auto_commit") resolved to the class
on Python 3.10, causing AttributeError. Use patch.object with an
explicit module reference via sys.modules to avoid the ambiguity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Convert Path to str in repo.git.add() and repo.index.add() calls
  for compatibility with older GitPython on Python 3.10
- Use explicit refspec in push to avoid push.default issues on macOS
- Improve error assertion messages in BDD tests to show stderr/stdout

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
repo.index.add() calls os.getcwd() internally, which fails under
pytest-xdist on macOS when a parallel worker's CWD has been deleted
by another test's cleanup. repo.git.add() runs git as a subprocess
and avoids this issue.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a config is originally loaded from JSON (e.g., during v1.x
upgrade), ruamel's round-trip YAML loader marks every mapping with
flow style. This causes save_config to write the file starting with
'{', which is_config_json() mistakes for a legacy v1.x config,
triggering a re-upgrade on the next run and producing empty output.

Recursively clear flow style on all CommentedMap/CommentedSeq nodes
before dumping to ensure block-style YAML output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Git marks pack-file objects as read-only, which causes
shutil.rmtree to fail with PermissionError on Windows.
Add an onerror handler that clears the read-only flag before retry.
Also close the repo before cleanup to release file handles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@alichtman
alichtman force-pushed the git_autocommit_and_push_integration branch from e0ccc1c to d20c118 Compare August 8, 2026 23:24

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant