github-backup 0.61.5__tar.gz → 0.62.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. {github_backup-0.61.5 → github_backup-0.62.1}/CHANGES.rst +211 -1
  2. {github_backup-0.61.5/github_backup.egg-info → github_backup-0.62.1}/PKG-INFO +62 -28
  3. {github_backup-0.61.5 → github_backup-0.62.1}/README +61 -27
  4. {github_backup-0.61.5 → github_backup-0.62.1}/README.rst +61 -27
  5. github_backup-0.62.1/github_backup/__init__.py +1 -0
  6. {github_backup-0.61.5 → github_backup-0.62.1}/github_backup/github_backup.py +842 -100
  7. github_backup-0.62.1/github_backup/graphql_queries.py +292 -0
  8. {github_backup-0.61.5 → github_backup-0.62.1/github_backup.egg-info}/PKG-INFO +62 -28
  9. {github_backup-0.61.5 → github_backup-0.62.1}/github_backup.egg-info/SOURCES.txt +7 -0
  10. {github_backup-0.61.5 → github_backup-0.62.1}/release-requirements.txt +3 -3
  11. github_backup-0.62.1/tests/test_auth.py +75 -0
  12. github_backup-0.62.1/tests/test_discussions.py +257 -0
  13. github_backup-0.62.1/tests/test_incremental_per_repository.py +189 -0
  14. github_backup-0.62.1/tests/test_pull_incremental_pagination.py +131 -0
  15. github_backup-0.62.1/tests/test_pull_reviews.py +237 -0
  16. github_backup-0.62.1/tests/test_releases.py +95 -0
  17. {github_backup-0.61.5 → github_backup-0.62.1}/tests/test_retrieve_data.py +28 -0
  18. github_backup-0.61.5/github_backup/__init__.py +0 -1
  19. {github_backup-0.61.5 → github_backup-0.62.1}/LICENSE.txt +0 -0
  20. {github_backup-0.61.5 → github_backup-0.62.1}/MANIFEST.in +0 -0
  21. {github_backup-0.61.5 → github_backup-0.62.1}/github_backup/__main__.py +0 -0
  22. {github_backup-0.61.5 → github_backup-0.62.1}/github_backup/cli.py +0 -0
  23. {github_backup-0.61.5 → github_backup-0.62.1}/github_backup.egg-info/dependency_links.txt +0 -0
  24. {github_backup-0.61.5 → github_backup-0.62.1}/github_backup.egg-info/entry_points.txt +0 -0
  25. {github_backup-0.61.5 → github_backup-0.62.1}/github_backup.egg-info/top_level.txt +0 -0
  26. {github_backup-0.61.5 → github_backup-0.62.1}/github_backup.egg-info/zip-safe +0 -0
  27. {github_backup-0.61.5 → github_backup-0.62.1}/requirements.txt +0 -0
  28. {github_backup-0.61.5 → github_backup-0.62.1}/setup.cfg +0 -0
  29. {github_backup-0.61.5 → github_backup-0.62.1}/setup.py +0 -0
  30. {github_backup-0.61.5 → github_backup-0.62.1}/tests/test_all_starred.py +0 -0
  31. {github_backup-0.61.5 → github_backup-0.62.1}/tests/test_attachments.py +0 -0
  32. {github_backup-0.61.5 → github_backup-0.62.1}/tests/test_case_sensitivity.py +0 -0
  33. {github_backup-0.61.5 → github_backup-0.62.1}/tests/test_http_451.py +0 -0
  34. {github_backup-0.61.5 → github_backup-0.62.1}/tests/test_json_dump_if_changed.py +0 -0
  35. {github_backup-0.61.5 → github_backup-0.62.1}/tests/test_pagination.py +0 -0
  36. {github_backup-0.61.5 → github_backup-0.62.1}/tests/test_skip_assets_on.py +0 -0
  37. {github_backup-0.61.5 → github_backup-0.62.1}/tests/test_starred_skip_size_over.py +0 -0
@@ -1,9 +1,219 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
- 0.61.5 (2026-02-18)
4
+ 0.62.1 (2026-04-30)
5
5
  -------------------
6
6
  ------------------------
7
+ - Document that nothing is saved by default. [Changaco]
8
+ - Eliminate trailing spaces. [Changaco]
9
+ - Remove pointless and unsafe `export`s in examples. [Changaco]
10
+ - Try to clarify what `--incremental` actually does. [Changaco]
11
+ - Fix a typo in the README. [Changaco]
12
+ - Document that `--all` doesn't imply `--attachments` [Changaco]
13
+ - Rename a function to match what it actually does. [Changaco]
14
+ - Don't leave files open. [Changaco]
15
+ - Remove legacy code in `mkdir_p` function. [Changaco]
16
+ - Don't pass stdin when doing so can't do any good. [Changaco]
17
+
18
+ When the child process doesn't inherit stderr, it can't ask the user for input, so it shouldn't inherit stdin either.
19
+ - Use `subprocess.DEVNULL` instead of emulating it. [Changaco]
20
+ - Remove bad invocation of the system shell. [Changaco]
21
+ - Add missing `context` argument to `urlopen` call. [Changaco]
22
+ - Suppress output of call to `git lfs version` [Changaco]
23
+ - Handle more network errors. [Changaco]
24
+
25
+ ```python-traceback
26
+ Traceback (most recent call last):
27
+ File ".local/bin/github-backup", line 6, in <module>
28
+ sys.exit(main())
29
+ ~~~~^^
30
+ File ".local/share/pipx/venvs/github-backup/lib/python3.14/site-packages/github_backup/cli.py", line 83, in main
31
+ backup_repositories(args, output_directory, repositories)
32
+ ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
33
+ File ".local/share/pipx/venvs/github-backup/lib/python3.14/site-packages/github_backup/github_backup.py", line 1845, in backup_repositories
34
+ backup_pulls(args, repo_cwd, repository, repos_template)
35
+ ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36
+ File ".local/share/pipx/venvs/github-backup/lib/python3.14/site-packages/github_backup/github_backup.py", line 2019, in backup_pulls
37
+ pulls[number]["commit_data"] = retrieve_data(args, template)
38
+ ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
39
+ File ".local/share/pipx/venvs/github-backup/lib/python3.14/site-packages/github_backup/github_backup.py", line 766, in retrieve_data
40
+ return list(fetch_all())
41
+ File ".local/share/pipx/venvs/github-backup/lib/python3.14/site-packages/github_backup/github_backup.py", line 717, in fetch_all
42
+ response = json.loads(http_response.read().decode("utf-8"))
43
+ ~~~~~~~~~~~~~~~~~~^^
44
+ File "/usr/lib/python3.14/http/client.py", line 500, in read
45
+ s = self._safe_read(self.length)
46
+ File "/usr/lib/python3.14/http/client.py", line 648, in _safe_read
47
+ data = self.fp.read(cursize)
48
+ File "/usr/lib/python3.14/socket.py", line 725, in readinto
49
+ return self._sock.recv_into(b)
50
+ ~~~~~~~~~~~~~~~~~~~~^^^
51
+ File "/usr/lib/python3.14/ssl.py", line 1304, in recv_into
52
+ return self.read(nbytes, buffer)
53
+ ~~~~~~~~~^^^^^^^^^^^^^^^^
54
+ File "/usr/lib/python3.14/ssl.py", line 1138, in read
55
+ return self._sslobj.read(len, buffer)
56
+ ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
57
+ ConnectionResetError: [Errno 104] Connection reset by peer
58
+ ```
59
+
60
+
61
+ 0.62.0 (2026-04-29)
62
+ -------------------
63
+ - Skip checkpoint-equal incremental items. [Duncan Ogilvie]
64
+ - Avoid redundant release asset list requests. [Duncan Ogilvie]
65
+ - Reduce unnecessary pull requests with incremental fetching. [Duncan
66
+ Ogilvie]
67
+ - Implement per-resource last_update timestamps. [Duncan Ogilvie]
68
+
69
+ Closes #62
70
+ - Add support for pull request reviews. [Duncan Ogilvie]
71
+
72
+ Closes #124
73
+ - Add support for discussions. [Duncan Ogilvie]
74
+
75
+ Closes #290
76
+ - Add --token-from-gh authentication option. [Duncan Ogilvie]
77
+ - Chore(deps): bump pytest in the python-packages group.
78
+ [dependabot[bot]]
79
+
80
+ Bumps the python-packages group with 1 update: [pytest](https://github.com/pytest-dev/pytest).
81
+
82
+
83
+ Updates `pytest` from 9.0.2 to 9.0.3
84
+ - [Release notes](https://github.com/pytest-dev/pytest/releases)
85
+ - [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
86
+ - [Commits](https://github.com/pytest-dev/pytest/compare/9.0.2...9.0.3)
87
+
88
+ ---
89
+ updated-dependencies:
90
+ - dependency-name: pytest
91
+ dependency-version: 9.0.3
92
+ dependency-type: direct:production
93
+ update-type: version-update:semver-patch
94
+ dependency-group: python-packages
95
+ ...
96
+ - Chore(deps): bump black in the python-packages group.
97
+ [dependabot[bot]]
98
+
99
+ Bumps the python-packages group with 1 update: [black](https://github.com/psf/black).
100
+
101
+
102
+ Updates `black` from 26.3.0 to 26.3.1
103
+ - [Release notes](https://github.com/psf/black/releases)
104
+ - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
105
+ - [Commits](https://github.com/psf/black/compare/26.3.0...26.3.1)
106
+
107
+ ---
108
+ updated-dependencies:
109
+ - dependency-name: black
110
+ dependency-version: 26.3.1
111
+ dependency-type: direct:production
112
+ update-type: version-update:semver-patch
113
+ dependency-group: python-packages
114
+ ...
115
+ - Chore(deps): bump docker/login-action from 3 to 4. [dependabot[bot]]
116
+
117
+ Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4.
118
+ - [Release notes](https://github.com/docker/login-action/releases)
119
+ - [Commits](https://github.com/docker/login-action/compare/v3...v4)
120
+
121
+ ---
122
+ updated-dependencies:
123
+ - dependency-name: docker/login-action
124
+ dependency-version: '4'
125
+ dependency-type: direct:production
126
+ update-type: version-update:semver-major
127
+ ...
128
+ - Chore(deps): bump docker/setup-qemu-action from 3 to 4.
129
+ [dependabot[bot]]
130
+
131
+ Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3 to 4.
132
+ - [Release notes](https://github.com/docker/setup-qemu-action/releases)
133
+ - [Commits](https://github.com/docker/setup-qemu-action/compare/v3...v4)
134
+
135
+ ---
136
+ updated-dependencies:
137
+ - dependency-name: docker/setup-qemu-action
138
+ dependency-version: '4'
139
+ dependency-type: direct:production
140
+ update-type: version-update:semver-major
141
+ ...
142
+ - Chore(deps): bump docker/build-push-action from 6 to 7.
143
+ [dependabot[bot]]
144
+
145
+ Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6 to 7.
146
+ - [Release notes](https://github.com/docker/build-push-action/releases)
147
+ - [Commits](https://github.com/docker/build-push-action/compare/v6...v7)
148
+
149
+ ---
150
+ updated-dependencies:
151
+ - dependency-name: docker/build-push-action
152
+ dependency-version: '7'
153
+ dependency-type: direct:production
154
+ update-type: version-update:semver-major
155
+ ...
156
+ - Chore(deps): bump docker/setup-buildx-action from 3 to 4.
157
+ [dependabot[bot]]
158
+
159
+ Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4.
160
+ - [Release notes](https://github.com/docker/setup-buildx-action/releases)
161
+ - [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4)
162
+
163
+ ---
164
+ updated-dependencies:
165
+ - dependency-name: docker/setup-buildx-action
166
+ dependency-version: '4'
167
+ dependency-type: direct:production
168
+ update-type: version-update:semver-major
169
+ ...
170
+ - Chore(deps): bump docker/metadata-action from 5 to 6.
171
+ [dependabot[bot]]
172
+
173
+ Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5 to 6.
174
+ - [Release notes](https://github.com/docker/metadata-action/releases)
175
+ - [Commits](https://github.com/docker/metadata-action/compare/v5...v6)
176
+
177
+ ---
178
+ updated-dependencies:
179
+ - dependency-name: docker/metadata-action
180
+ dependency-version: '6'
181
+ dependency-type: direct:production
182
+ update-type: version-update:semver-major
183
+ ...
184
+ - Chore(deps): bump the python-packages group with 2 updates.
185
+ [dependabot[bot]]
186
+
187
+ Bumps the python-packages group with 2 updates: [black](https://github.com/psf/black) and [setuptools](https://github.com/pypa/setuptools).
188
+
189
+
190
+ Updates `black` from 26.1.0 to 26.3.0
191
+ - [Release notes](https://github.com/psf/black/releases)
192
+ - [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
193
+ - [Commits](https://github.com/psf/black/compare/26.1.0...26.3.0)
194
+
195
+ Updates `setuptools` from 82.0.0 to 82.0.1
196
+ - [Release notes](https://github.com/pypa/setuptools/releases)
197
+ - [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
198
+ - [Commits](https://github.com/pypa/setuptools/compare/v82.0.0...v82.0.1)
199
+
200
+ ---
201
+ updated-dependencies:
202
+ - dependency-name: black
203
+ dependency-version: 26.3.0
204
+ dependency-type: direct:production
205
+ update-type: version-update:semver-minor
206
+ dependency-group: python-packages
207
+ - dependency-name: setuptools
208
+ dependency-version: 82.0.1
209
+ dependency-type: direct:production
210
+ update-type: version-update:semver-patch
211
+ dependency-group: python-packages
212
+ ...
213
+
214
+
215
+ 0.61.5 (2026-02-18)
216
+ -------------------
7
217
  - Fix empty repository crash due to None timestamp comparison (#489)
8
218
  [Rodos]
9
219
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-backup
3
- Version: 0.61.5
3
+ Version: 0.62.1
4
4
  Summary: backup a github user or organization
5
5
  Home-page: http://github.com/josegonzalez/python-github-backup
6
6
  Author: Jose Diaz-Gonzalez
@@ -34,7 +34,7 @@ github-backup
34
34
 
35
35
  |PyPI| |Python Versions|
36
36
 
37
- The package can be used to backup an *entire* `Github <https://github.com/>`_ organization, repository or user account, including starred repos, issues and wikis in the most appropriate format (clones for wikis, json files for issues).
37
+ The package can be used to backup an *entire* `Github <https://github.com/>`_ organization, repository or user account, including starred repos, issues, discussions and wikis in the most appropriate format (clones for wikis, json files for issues and discussions).
38
38
 
39
39
  Requirements
40
40
  ============
@@ -52,7 +52,7 @@ Using PIP via PyPI::
52
52
  Using PIP via Github (more likely the latest version)::
53
53
 
54
54
  pip install git+https://github.com/josegonzalez/python-github-backup.git#egg=github-backup
55
-
55
+
56
56
  *Install note for python newcomers:*
57
57
 
58
58
  Python scripts are unlikely to be included in your ``$PATH`` by default, this means it cannot be run directly in terminal with ``$ github-backup ...``, you can either add python's install path to your environments ``$PATH`` or call the script directly e.g. using ``$ ~/.local/bin/github-backup``.*
@@ -66,16 +66,18 @@ Show the CLI help output::
66
66
 
67
67
  CLI Help output::
68
68
 
69
- github-backup [-h] [-t TOKEN_CLASSIC] [-f TOKEN_FINE] [-q] [--as-app]
70
- [-o OUTPUT_DIRECTORY] [-l LOG_LEVEL] [-i]
69
+ github-backup [-h] [-t TOKEN_CLASSIC] [-f TOKEN_FINE] [--token-from-gh]
70
+ [-q] [--as-app] [-o OUTPUT_DIRECTORY] [-l LOG_LEVEL] [-i]
71
71
  [--incremental-by-files]
72
72
  [--starred] [--all-starred] [--starred-skip-size-over MB]
73
73
  [--watched] [--followers] [--following] [--all]
74
74
  [--issues] [--issue-comments] [--issue-events] [--pulls]
75
- [--pull-comments] [--pull-commits] [--pull-details]
75
+ [--pull-comments] [--pull-reviews] [--pull-commits]
76
+ [--pull-details]
76
77
  [--labels] [--hooks] [--milestones] [--security-advisories]
77
- [--repositories] [--bare] [--no-prune] [--lfs] [--wikis]
78
- [--gists] [--starred-gists] [--skip-archived] [--skip-existing]
78
+ [--discussions] [--repositories] [--bare] [--no-prune]
79
+ [--lfs] [--wikis] [--gists] [--starred-gists]
80
+ [--skip-archived] [--skip-existing]
79
81
  [-L [LANGUAGES ...]] [-N NAME_REGEX] [-H GITHUB_HOST]
80
82
  [-O] [-R REPOSITORY] [-P] [-F] [--prefer-ssh] [-v]
81
83
  [--keychain-name OSX_KEYCHAIN_ITEM_NAME]
@@ -101,6 +103,7 @@ CLI Help output::
101
103
  -f, --token-fine TOKEN_FINE
102
104
  fine-grained personal access token (github_pat_....),
103
105
  or path to token (file://...)
106
+ --token-from-gh read token from GitHub CLI (gh auth token)
104
107
  -q, --quiet supress log messages less severe than warning, e.g.
105
108
  info
106
109
  --as-app authenticate as github app instead of as a user.
@@ -125,6 +128,7 @@ CLI Help output::
125
128
  --issue-events include issue events in backup
126
129
  --pulls include pull requests in backup
127
130
  --pull-comments include pull request review comments in backup
131
+ --pull-reviews include pull request reviews in backup
128
132
  --pull-commits include pull request commits in backup
129
133
  --pull-details include more pull request details in backup [*]
130
134
  --labels include labels in backup
@@ -133,6 +137,7 @@ CLI Help output::
133
137
  --milestones include milestones in backup
134
138
  --security-advisories
135
139
  include security advisories in backup
140
+ --discussions include discussions in backup
136
141
  --repositories include repository clone in backup
137
142
  --bare clone bare repositories
138
143
  --no-prune disable prune option for git fetch
@@ -173,8 +178,8 @@ CLI Help output::
173
178
  applies if including releases
174
179
  --skip-assets-on [SKIP_ASSETS_ON ...]
175
180
  skip asset downloads for these repositories
176
- --attachments download user-attachments from issues and pull
177
- requests
181
+ --attachments download user-attachments from issues, pull requests,
182
+ and discussions
178
183
  --throttle-limit THROTTLE_LIMIT
179
184
  start throttling of GitHub API requests after this
180
185
  amount of API requests remain
@@ -201,6 +206,8 @@ The positional argument ``USER`` specifies the user or organization account you
201
206
 
202
207
  **Classic tokens** (``-t TOKEN``) are `slightly less secure <https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#personal-access-tokens-classic>`_ as they provide very coarse-grained permissions.
203
208
 
209
+ If you already authenticate with the `GitHub CLI <https://cli.github.com/>`_, you can use ``--token-from-gh`` to read the token with ``gh auth token`` instead of passing a token directly. This avoids placing the token in shell history or process arguments. When ``--github-host`` is set, the token is read with ``gh auth token --hostname HOST``.
210
+
204
211
 
205
212
  Fine Tokens
206
213
  ~~~~~~~~~~~
@@ -211,7 +218,7 @@ Customise the permissions for your use case, but for a personal account full bac
211
218
 
212
219
  **User permissions**: Read access to followers, starring, and watching.
213
220
 
214
- **Repository permissions**: Read access to contents, issues, metadata, pull requests, and webhooks.
221
+ **Repository permissions**: Read access to contents, discussions, issues, metadata, pull requests, and webhooks.
215
222
 
216
223
 
217
224
  GitHub Apps
@@ -272,7 +279,7 @@ Note: When you run github-backup, you will be asked whether you want to allow "
272
279
  Github Rate-limit and Throttling
273
280
  --------------------------------
274
281
 
275
- "github-backup" will automatically throttle itself based on feedback from the Github API.
282
+ "github-backup" will automatically throttle itself based on feedback from the Github API.
276
283
 
277
284
  Their API is usually rate-limited to 5000 calls per hour. The API will ask github-backup to pause until a specific time when the limit is reset again (at the start of the next hour). This continues until the backup is complete.
278
285
 
@@ -292,9 +299,9 @@ LFS objects are fetched for all refs, not just the current checkout, ensuring a
292
299
  About Attachments
293
300
  -----------------
294
301
 
295
- When you use the ``--attachments`` option with ``--issues`` or ``--pulls``, the tool will download user-uploaded attachments (images, videos, documents, etc.) from issue and pull request descriptions and comments. In some circumstances attachments contain valuable data related to the topic, and without their backup important information or context might be lost inadvertently.
302
+ When you use the ``--attachments`` option with ``--issues``, ``--pulls`` or ``--discussions``, the tool will download user-uploaded attachments (images, videos, documents, etc.) from issue, pull request and discussion descriptions and comments. In some circumstances attachments contain valuable data related to the topic, and without their backup important information or context might be lost inadvertently.
296
303
 
297
- Attachments are saved to ``issues/attachments/{issue_number}/`` and ``pulls/attachments/{pull_number}/`` directories, where ``{issue_number}`` is the GitHub issue number (e.g., issue #123 saves to ``issues/attachments/123/``). Each attachment directory contains:
304
+ Attachments are saved to ``issues/attachments/{issue_number}/``, ``pulls/attachments/{pull_number}/`` and ``discussions/attachments/{discussion_number}/`` directories, where ``{issue_number}`` is the GitHub issue number (e.g., issue #123 saves to ``issues/attachments/123/``). Each attachment directory contains:
298
305
 
299
306
  - The downloaded attachment files (named by their GitHub identifier with appropriate file extensions)
300
307
  - If multiple attachments have the same filename, conflicts are resolved with numeric suffixes (e.g., ``report.pdf``, ``report_1.pdf``, ``report_2.pdf``)
@@ -314,6 +321,16 @@ The tool automatically extracts file extensions from HTTP headers to ensure file
314
321
  **Fine-grained token limitation:** Due to a GitHub platform limitation, fine-grained personal access tokens (``github_pat_...``) cannot download attachments from private repositories directly. This affects both ``/assets/`` (images) and ``/files/`` (documents) URLs. The tool implements a workaround for image attachments using GitHub's Markdown API, which converts URLs to temporary JWT-signed URLs that can be downloaded. However, this workaround only works for images - document attachments (PDFs, text files, etc.) will fail with 404 errors when using fine-grained tokens on private repos. For full attachment support on private repositories, use a classic token (``-t``) instead of a fine-grained token (``-f``). See `#477 <https://github.com/josegonzalez/python-github-backup/issues/477>`_ for details.
315
322
 
316
323
 
324
+ About Discussions
325
+ -----------------
326
+
327
+ GitHub Discussions are backed up with GitHub's GraphQL API because the REST API does not expose discussions. Use ``--discussions`` to save each discussion as JSON under ``repositories/{repo}/discussions/{number}.json``. Discussion backups include the discussion body and metadata, category information, comments, and comment replies.
328
+
329
+ ``--discussions`` is included in ``--all``. Unlike most REST API-backed resources, discussions require authentication because GitHub's GraphQL API requires a token. Fine-grained personal access tokens and GitHub Apps need read access to the repository's Discussions permission.
330
+
331
+ Incremental backups use a per-repository checkpoint at ``repositories/{repo}/discussions/last_update`` based on discussion ``updatedAt`` timestamps. This is separate from the repository-level ``last_update`` file so discussion activity is not missed if the repository's own update timestamp does not change. If you enable ``--discussions`` on an existing incremental backup, the first run performs a full discussions backup for each repository and creates the discussions checkpoint for future runs.
332
+
333
+
317
334
  About security advisories
318
335
  -------------------------
319
336
 
@@ -338,7 +355,12 @@ Gotchas / Known-issues
338
355
  All is not everything
339
356
  ---------------------
340
357
 
341
- The ``--all`` argument does not include: cloning private repos (``-P, --private``), cloning forks (``-F, --fork``), cloning starred repositories (``--all-starred``), ``--pull-details``, cloning LFS repositories (``--lfs``), cloning gists (``--gists``) or cloning starred gist repos (``--starred-gists``). See examples for more.
358
+ The ``--all`` argument does not include: downloading attachments from issue and pull request comments (``--attachments``), cloning private repos (``-P, --private``), cloning forks (``-F, --fork``), cloning starred repositories (``--all-starred``), ``--pull-details``, cloning LFS repositories (``--lfs``), cloning gists (``--gists``) or cloning starred gist repos (``--starred-gists``). See examples for more.
359
+
360
+ Saves nothing if no arguments are passed
361
+ ----------------------------------------
362
+
363
+ At least one argument like ``--all`` or ``--repositories`` is needed for github-backup to actually save data. Without relevant arguments, github-backup fetches some data from GitHub but doesn't put any of it into files.
342
364
 
343
365
  Starred repository size
344
366
  -----------------------
@@ -355,25 +377,37 @@ For finer control, avoid using ``--assets`` with starred repos, or use ``--skip-
355
377
 
356
378
  Alternatively, consider just storing links to starred repos in JSON format with ``--starred``.
357
379
 
380
+ About pull request reviews
381
+ --------------------------
382
+
383
+ Use ``--pull-reviews`` with ``--pulls`` to include GitHub pull request review metadata under each pull request's ``review_data`` key. Reviews are separate from review comments: ``--pull-comments`` backs up inline review comments via ``comment_data`` and regular PR conversation comments via ``comment_regular_data``, while ``--pull-reviews`` backs up review state, submitted time, commit ID, and the top-level review body.
384
+
385
+ ``--pull-reviews`` is included in ``--all``. Incremental backups use a per-repository checkpoint at ``repositories/{repo}/pulls/reviews_last_update``. If ``--pull-reviews`` is enabled on an existing incremental backup, the first run performs a one-time backfill for pull request reviews so older PRs are not skipped by the existing pull request checkpoint. Existing ``comment_data``, ``comment_regular_data`` and ``commit_data`` fields are preserved when only review data is being added.
386
+
387
+
358
388
  Incremental Backup
359
389
  ------------------
360
390
 
361
- Using (``-i, --incremental``) will only request new data from the API **since the last run (successful or not)**. e.g. only request issues from the API since the last run.
391
+ Using (``-i, --incremental``) will only request new data from the API **since the last successful resource backup**. e.g. only request issues from the API since the last issue backup for that repository.
392
+
393
+ Incremental checkpoints for issue and pull request API backups are stored per resource in that repository's backup directory (for example ``repositories/{repo}/issues/last_update``, ``repositories/{repo}/pulls/last_update`` or ``starred/{owner}/{repo}/pulls/last_update``). Older versions stored a single global ``last_update`` file in the output directory root. During migration, the legacy global checkpoint is used as a fallback only for resource directories that already contain backup data but do not yet have their own checkpoint. New repositories or newly enabled resources with no existing data get a full backup instead of inheriting an unrelated global checkpoint.
362
394
 
363
- This means any blocking errors on previous runs can cause a large amount of missing data in backups.
395
+ After all existing issue and pull request resource directories have per-resource checkpoints, the legacy global ``last_update`` file is removed automatically.
396
+
397
+ This means any blocking errors on previous runs can cause missing data in backups for the affected repository resource.
364
398
 
365
399
  Using (``--incremental-by-files``) will request new data from the API **based on when the file was modified on filesystem**. e.g. if you modify the file yourself you may miss something.
366
400
 
367
- Still saver than the previous version.
401
+ Still safer than the previous version.
368
402
 
369
- Specifically, issues and pull requests are handled like this.
403
+ Incremental backup only changes how issue and pull request data is fetched.
370
404
 
371
405
  Known blocking errors
372
406
  ---------------------
373
407
 
374
408
  Some errors will block the backup run by exiting the script. e.g. receiving a 403 Forbidden error from the Github API.
375
409
 
376
- If the incremental argument is used, this will result in the next backup only requesting API data since the last blocked/failed run. Potentially causing unexpected large amounts of missing data.
410
+ If the incremental argument is used, per-resource checkpoints are only advanced after that resource's backup work completes. A blocking error can still abort the overall run, but repositories and resources that were not processed will keep their previous checkpoints.
377
411
 
378
412
  It's therefore recommended to only use the incremental argument if the output/result is being actively monitored, or complimented with periodic full non-incremental runs, to avoid unexpected missing data in a regular backup runs.
379
413
 
@@ -430,12 +464,12 @@ Github Backup Examples
430
464
 
431
465
  Backup all repositories, including private ones using a classic token::
432
466
 
433
- export ACCESS_TOKEN=SOME-GITHUB-TOKEN
467
+ ACCESS_TOKEN=SOME-GITHUB-TOKEN
434
468
  github-backup WhiteHouse --token $ACCESS_TOKEN --organization --output-directory /tmp/white-house --repositories --private
435
469
 
436
470
  Use a fine-grained access token to backup a single organization repository with everything else (wiki, pull requests, comments, issues etc)::
437
471
 
438
- export FINE_ACCESS_TOKEN=SOME-GITHUB-TOKEN
472
+ FINE_ACCESS_TOKEN=SOME-GITHUB-TOKEN
439
473
  ORGANIZATION=docker
440
474
  REPO=cli
441
475
  # e.g. git@github.com:docker/cli.git
@@ -443,17 +477,17 @@ Use a fine-grained access token to backup a single organization repository with
443
477
 
444
478
  Quietly and incrementally backup useful Github user data (public and private repos with SSH) including; all issues, pulls, all public starred repos and gists (omitting "hooks", "releases" and therefore "assets" to prevent blocking). *Great for a cron job.* ::
445
479
 
446
- export FINE_ACCESS_TOKEN=SOME-GITHUB-TOKEN
480
+ FINE_ACCESS_TOKEN=SOME-GITHUB-TOKEN
447
481
  GH_USER=YOUR-GITHUB-USER
448
482
 
449
- github-backup -f $FINE_ACCESS_TOKEN --prefer-ssh -o ~/github-backup/ -l error -P -i --all-starred --starred --watched --followers --following --issues --issue-comments --issue-events --pulls --pull-comments --pull-commits --labels --milestones --security-advisories --repositories --wikis --releases --assets --attachments --pull-details --gists --starred-gists $GH_USER
450
-
483
+ github-backup -f $FINE_ACCESS_TOKEN --prefer-ssh -o ~/github-backup/ -l error -P -i --all-starred --starred --watched --followers --following --issues --issue-comments --issue-events --pulls --pull-comments --pull-reviews --pull-commits --labels --milestones --security-advisories --discussions --repositories --wikis --releases --assets --attachments --pull-details --gists --starred-gists $GH_USER
484
+
451
485
  Debug an error/block or incomplete backup into a temporary directory. Omit "incremental" to fill a previous incomplete backup. ::
452
486
 
453
- export FINE_ACCESS_TOKEN=SOME-GITHUB-TOKEN
487
+ FINE_ACCESS_TOKEN=SOME-GITHUB-TOKEN
454
488
  GH_USER=YOUR-GITHUB-USER
455
489
 
456
- github-backup -f $FINE_ACCESS_TOKEN -o /tmp/github-backup/ -l debug -P --all-starred --starred --watched --followers --following --issues --issue-comments --issue-events --pulls --pull-comments --pull-commits --labels --milestones --repositories --wikis --releases --assets --pull-details --gists --starred-gists $GH_USER
490
+ github-backup -f $FINE_ACCESS_TOKEN -o /tmp/github-backup/ -l debug -P --all-starred --starred --watched --followers --following --issues --issue-comments --issue-events --pulls --pull-comments --pull-reviews --pull-commits --labels --milestones --discussions --repositories --wikis --releases --assets --pull-details --gists --starred-gists $GH_USER
457
491
 
458
492
  Pipe a token from stdin to avoid storing it in environment variables or command history (Unix-like systems only)::
459
493
 
@@ -469,7 +503,7 @@ This tool creates backups only, there is no inbuilt restore command.
469
503
  cd /tmp/white-house/repositories/petitions/repository
470
504
  git push --mirror git@github.com:WhiteHouse/petitions.git
471
505
 
472
- **Issues, pull requests, comments, and other metadata** are saved as JSON files for archival purposes. The GitHub API does not support recreating this data faithfully, creating issues via the API has limitations:
506
+ **Issues, pull requests, discussions, comments, and other metadata** are saved as JSON files for archival purposes. The GitHub API does not support recreating this data faithfully, creating issues via the API has limitations:
473
507
 
474
508
  - New issue/PR numbers are assigned (original numbers cannot be set)
475
509
  - Timestamps reflect creation time (original dates cannot be set)