summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/main.yml16
-rw-r--r--.gitignore2
-rw-r--r--Documentation/Makefile1
-rw-r--r--Documentation/RelNotes/2.30.5.txt12
-rw-r--r--Documentation/RelNotes/2.31.4.txt6
-rw-r--r--Documentation/RelNotes/2.32.3.txt6
-rw-r--r--Documentation/RelNotes/2.33.4.txt6
-rw-r--r--Documentation/RelNotes/2.34.4.txt6
-rw-r--r--Documentation/RelNotes/2.35.4.txt7
-rw-r--r--Documentation/RelNotes/2.36.2.txt14
-rw-r--r--Documentation/RelNotes/2.37.0.txt35
-rw-r--r--Documentation/RelNotes/2.37.1.txt17
-rw-r--r--Documentation/RelNotes/2.37.2.txt47
-rw-r--r--Documentation/RelNotes/2.38.0.txt191
-rw-r--r--Documentation/config.txt4
-rw-r--r--Documentation/config/core.txt37
-rw-r--r--Documentation/config/fetch.txt14
-rw-r--r--Documentation/config/gpg.txt9
-rw-r--r--Documentation/config/http.txt2
-rw-r--r--Documentation/config/includeif.txt6
-rw-r--r--Documentation/config/push.txt5
-rw-r--r--Documentation/config/rebase.txt3
-rw-r--r--Documentation/config/revert.txt3
-rw-r--r--Documentation/config/safe.txt32
-rw-r--r--Documentation/config/transfer.txt38
-rw-r--r--Documentation/config/uploadpack.txt6
-rw-r--r--Documentation/diff-format.txt6
-rw-r--r--Documentation/git-archive.txt21
-rw-r--r--Documentation/git-config.txt95
-rw-r--r--Documentation/git-cvsserver.txt19
-rw-r--r--Documentation/git-daemon.txt21
-rw-r--r--Documentation/git-diff-index.txt6
-rw-r--r--Documentation/git-gc.txt3
-rw-r--r--Documentation/git-grep.txt9
-rw-r--r--Documentation/git-merge-tree.txt235
-rw-r--r--Documentation/git-rebase.txt252
-rw-r--r--Documentation/git-revert.txt9
-rw-r--r--Documentation/git.txt4
-rw-r--r--Documentation/revisions.txt17
-rw-r--r--Documentation/technical/bitmap-format.txt203
-rw-r--r--Documentation/technical/index-format.txt2
-rw-r--r--Documentation/technical/scalar.txt127
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile69
l---------RelNotes2
-rw-r--r--add-interactive.c12
-rw-r--r--archive-tar.c77
-rw-r--r--archive.h2
-rw-r--r--bloom.c10
-rw-r--r--branch.c89
-rw-r--r--branch.h7
-rw-r--r--builtin/branch.c11
-rw-r--r--builtin/cat-file.c33
-rw-r--r--builtin/check-ref-format.c11
-rw-r--r--builtin/checkout.c38
-rw-r--r--builtin/clone.c82
-rw-r--r--builtin/diff-files.c2
-rw-r--r--builtin/fast-import.c2
-rw-r--r--builtin/fetch.c49
-rw-r--r--builtin/fsck.c39
-rw-r--r--builtin/gc.c10
-rw-r--r--builtin/grep.c9
-rw-r--r--builtin/index-pack.c2
-rw-r--r--builtin/merge-file.c32
-rw-r--r--builtin/merge-tree.c187
-rw-r--r--builtin/merge.c4
-rw-r--r--builtin/mktree.c11
-rw-r--r--builtin/multi-pack-index.c8
-rw-r--r--builtin/mv.c255
-rw-r--r--builtin/name-rev.c2
-rw-r--r--builtin/pack-objects.c2
-rw-r--r--builtin/pull.c16
-rw-r--r--builtin/push.c2
-rw-r--r--builtin/rebase.c24
-rw-r--r--builtin/remote.c12
-rw-r--r--builtin/repack.c4
-rw-r--r--builtin/revert.c10
-rw-r--r--builtin/shortlog.c2
-rw-r--r--builtin/submodule--helper.c161
-rw-r--r--builtin/unpack-objects.c106
-rw-r--r--cache-tree.c27
-rw-r--r--cache-tree.h2
-rwxr-xr-xci/lib.sh13
-rwxr-xr-xci/make-test-artifacts.sh2
-rw-r--r--combine-diff.c7
-rw-r--r--commit-graph.c25
-rw-r--r--commit-graph.h22
-rw-r--r--commit.c2
-rw-r--r--compat/mingw.c5
-rw-r--r--compat/win32/syslog.c7
-rw-r--r--config.c43
-rw-r--r--config.h16
-rw-r--r--contrib/coccinelle/array.cocci82
-rw-r--r--contrib/coccinelle/object_id.cocci12
-rw-r--r--contrib/coccinelle/tests/free.c11
-rw-r--r--contrib/coccinelle/tests/free.res9
-rw-r--r--contrib/coccinelle/tests/unused.c82
-rw-r--r--contrib/coccinelle/tests/unused.res45
-rw-r--r--contrib/coccinelle/unused.cocci43
-rw-r--r--contrib/completion/git-prompt.sh32
-rw-r--r--contrib/credential/osxkeychain/git-credential-osxkeychain.c2
-rwxr-xr-xcontrib/rerere-train.sh2
-rw-r--r--contrib/scalar/README.md82
-rw-r--r--contrib/scalar/scalar.c3
-rw-r--r--contrib/scalar/scalar.txt9
-rwxr-xr-xcontrib/subtree/git-subtree.sh15
-rwxr-xr-xcontrib/vscode/init.sh8
-rw-r--r--convert.h6
-rw-r--r--daemon.c8
-rw-r--r--diff.c29
-rw-r--r--dir.c35
-rw-r--r--entry.c34
-rw-r--r--entry.h3
-rw-r--r--fsmonitor-settings.c8
-rw-r--r--fuzz-commit-graph.c12
-rw-r--r--git-compat-util.h7
-rwxr-xr-xgit-cvsserver.perl2
-rwxr-xr-xgit-instaweb.sh2
-rwxr-xr-xgit-p4.py62
-rw-r--r--git-sh-setup.sh16
-rwxr-xr-xgit-submodule.sh88
-rw-r--r--git.c2
-rw-r--r--gitweb/Makefile145
-rw-r--r--gpg-interface.c30
-rw-r--r--gpg-interface.h8
-rw-r--r--grep.c2
-rw-r--r--grep.h2
-rw-r--r--hash.h4
-rw-r--r--http.c6
-rw-r--r--http.h3
-rw-r--r--merge-ort.c548
-rw-r--r--merge-ort.h32
-rw-r--r--mergetools/vimdiff75
-rw-r--r--midx.c72
-rw-r--r--object-file.c233
-rw-r--r--object-store.h8
-rw-r--r--pack-bitmap-write.c2
-rw-r--r--pack-bitmap.c103
-rw-r--r--pack-bitmap.h2
-rw-r--r--pack-mtimes.c3
-rw-r--r--pack-objects.h10
-rw-r--r--pack-write.c17
-rw-r--r--packfile.c3
-rw-r--r--parallel-checkout.c10
-rw-r--r--parallel-checkout.h4
-rw-r--r--pkt-line.h16
-rw-r--r--po/README.md2
-rw-r--r--po/TEAMS6
-rw-r--r--po/bg.po22080
-rw-r--r--po/ca.po21698
-rw-r--r--po/de.po21069
-rw-r--r--po/es.po22660
-rw-r--r--po/fr.po21655
-rw-r--r--po/id.po25663
-rw-r--r--po/ru.po23312
-rw-r--r--po/sv.po23435
-rw-r--r--po/tr.po20641
-rw-r--r--po/vi.po20792
-rw-r--r--po/zh_CN.po25750
-rw-r--r--po/zh_TW.po26951
-rw-r--r--pretty.c18
-rw-r--r--read-cache.c8
-rw-r--r--rebase-interactive.c15
-rw-r--r--ref-filter.c5
-rw-r--r--remote-curl.c21
-rw-r--r--remote.c8
-rw-r--r--remote.h6
-rw-r--r--repo-settings.c12
-rw-r--r--repository.h1
-rw-r--r--revision.c36
-rw-r--r--send-pack.c6
-rw-r--r--send-pack.h3
-rw-r--r--sequencer.c507
-rw-r--r--sequencer.h24
-rw-r--r--setup.c132
-rw-r--r--sha256/nettle.h31
-rw-r--r--shared.mak1
-rw-r--r--submodule-config.c10
-rw-r--r--submodule.c5
-rw-r--r--t/Makefile4
-rw-r--r--t/README55
-rw-r--r--t/annotate-tests.sh3
-rw-r--r--t/helper/test-bloom.c2
-rw-r--r--t/helper/test-delta.c21
-rw-r--r--t/helper/test-dump-cache-tree.c7
-rw-r--r--t/helper/test-hash.c1
-rw-r--r--t/helper/test-json-writer.c16
-rw-r--r--t/helper/test-path-utils.c11
-rw-r--r--t/helper/test-ref-store.c1
-rw-r--r--t/helper/test-regex.c9
-rw-r--r--t/helper/test-scrap-cache-tree.c1
-rw-r--r--t/helper/test-trace2.c4
-rw-r--r--t/helper/test-urlmatch-normalization.c11
-rw-r--r--t/lib-httpd.sh2
-rw-r--r--t/lib-parallel-checkout.sh6
-rw-r--r--t/lib-proto-disable.sh6
-rw-r--r--t/lib-rebase.sh15
-rw-r--r--t/lib-submodule-update.sh7
-rw-r--r--t/perf/perf-lib.sh2
-rwxr-xr-xt/t0003-attributes.sh5
-rwxr-xr-xt/t0008-ignores.sh12
-rwxr-xr-xt/t0015-hash.sh3
-rwxr-xr-xt/t0019-json-writer.sh2
-rwxr-xr-xt/t0021-conversion.sh22
-rwxr-xr-xt/t0028-working-tree-encoding.sh3
-rwxr-xr-xt/t0033-safe-directory.sh26
-rwxr-xr-xt/t0034-root-safe-directory.sh15
-rwxr-xr-xt/t0035-safe-bare-repository.sh54
-rwxr-xr-xt/t0060-path-utils.sh1
-rwxr-xr-xt/t0090-cache-tree.sh2
-rwxr-xr-xt/t0095-bloom.sh2
-rwxr-xr-xt/t0110-urlmatch-normalization.sh2
-rw-r--r--t/t0212/parse_events.perl19
-rwxr-xr-xt/t1011-read-tree-sparse-checkout.sh2
-rwxr-xr-xt/t1051-large-conversion.sh2
-rwxr-xr-xt/t1090-sparse-checkout-scope.sh5
-rwxr-xr-xt/t1092-sparse-checkout-compatibility.sh25
-rwxr-xr-xt/t1300-config.sh5
-rwxr-xr-xt/t1301-shared-repo.sh3
-rwxr-xr-xt/t1402-check-ref-format.sh1
-rwxr-xr-xt/t2016-checkout-patch.sh2
-rwxr-xr-xt/t2018-checkout-branch.sh4
-rwxr-xr-xt/t2030-unresolve-info.sh71
-rwxr-xr-xt/t2080-parallel-checkout-basics.sh48
-rwxr-xr-xt/t2107-update-index-basic.sh31
-rwxr-xr-xt/t2205-add-worktree-config.sh265
-rwxr-xr-xt/t2400-worktree-add.sh4
-rwxr-xr-xt/t2407-worktree-heads.sh180
-rwxr-xr-xt/t3001-ls-files-others-exclude.sh42
-rwxr-xr-xt/t3002-ls-files-dashpath.sh86
-rwxr-xr-xt/t3020-ls-files-error-unmatch.sh12
-rwxr-xr-xt/t3060-ls-files-with-tree.sh8
-rwxr-xr-xt/t3304-notes-mixed.sh1
-rwxr-xr-xt/t3404-rebase-interactive.sh273
-rwxr-xr-xt/t3426-rebase-submodule.sh1
-rwxr-xr-xt/t3501-revert-cherry-pick.sh37
-rwxr-xr-xt/t3507-cherry-pick-conflict.sh2
-rwxr-xr-xt/t3700-add.sh2
-rwxr-xr-xt/t3701-add-interactive.sh21
-rwxr-xr-xt/t3903-stash.sh2
-rwxr-xr-xt/t4044-diff-index-unique-abbrev.sh2
-rwxr-xr-xt/t4140-apply-ita.sh1
-rwxr-xr-xt/t4200-rerere.sh3
-rwxr-xr-xt/t4301-merge-tree-write-tree.sh240
-rwxr-xr-xt/t5000-tar-tree.sh33
-rwxr-xr-xt/t5001-archive-attr.sh5
-rwxr-xr-xt/t5002-archive-attr-pattern.sh5
-rwxr-xr-xt/t5003-archive-zip.sh5
-rwxr-xr-xt/t5303-pack-corruption-resilience.sh2
-rwxr-xr-xt/t5308-pack-detect-duplicates.sh2
-rwxr-xr-xt/t5309-pack-delta-cycles.sh2
-rwxr-xr-xt/t5314-pack-cycle-detection.sh4
-rwxr-xr-xt/t5318-commit-graph.sh30
-rwxr-xr-xt/t5321-pack-large-objects.sh2
-rwxr-xr-xt/t5329-pack-objects-cruft.sh4
-rwxr-xr-xt/t5330-no-lazy-fetch-with-commit-graph.sh47
-rwxr-xr-xt/t5351-unpack-large-objects.sh96
-rwxr-xr-xt/t5505-remote.sh52
-rwxr-xr-xt/t5510-fetch.sh6
-rwxr-xr-xt/t5516-fetch-push.sh56
-rwxr-xr-xt/t5524-pull-msg.sh1
-rwxr-xr-xt/t5541-http-push-smart.sh19
-rwxr-xr-xt/t5544-pack-objects-hook.sh7
-rwxr-xr-xt/t5550-http-fetch-dumb.sh5
-rwxr-xr-xt/t5551-http-fetch-smart.sh10
-rwxr-xr-xt/t5601-clone.sh14
-rwxr-xr-xt/t5605-clone-local.sh16
-rwxr-xr-xt/t5702-protocol-v2.sh59
-rwxr-xr-xt/t5812-proto-disable-http.sh2
-rwxr-xr-xt/t5815-submodule-protos.sh4
-rwxr-xr-xt/t6001-rev-list-graft.sh1
-rwxr-xr-xt/t6101-rev-parse-parents.sh2
-rwxr-xr-xt/t6403-merge-file.sh2
-rwxr-xr-xt/t6417-merge-ours-theirs.sh1
-rwxr-xr-xt/t6422-merge-rename-corner-cases.sh1
-rwxr-xr-xt/t6423-merge-rename-directories.sh105
-rwxr-xr-xt/t6429-merge-sequence-rename-caching.sh2
-rwxr-xr-xt/t6435-merge-sparse.sh2
-rwxr-xr-xt/t6437-submodule-merge.sh2
-rwxr-xr-xt/t7002-mv-sparse-checkout.sh84
-rwxr-xr-xt/t7063-status-untracked-cache.sh8
-rwxr-xr-xt/t7406-submodule-update.sh64
-rwxr-xr-xt/t7418-submodule-sparse-gitmodules.sh3
-rwxr-xr-xt/t7609-mergetool--lib.sh2
-rwxr-xr-xt/t7810-grep.sh87
-rwxr-xr-xt/t7812-grep-icase-non-ascii.sh1
-rwxr-xr-xt/t7814-grep-recurse-submodules.sh8
-rwxr-xr-xt/t8001-annotate.sh1
-rwxr-xr-xt/t8002-blame.sh1
-rwxr-xr-xt/t8007-cat-file-textconv.sh2
-rwxr-xr-xt/t8010-cat-file-filters.sh2
-rwxr-xr-xt/t8012-blame-colors.sh1
-rwxr-xr-xt/t9101-git-svn-props.sh1
-rwxr-xr-xt/t9104-git-svn-follow-parent.sh1
-rwxr-xr-xt/t9132-git-svn-broken-symlink.sh1
-rwxr-xr-xt/t9301-fast-import-notes.sh1
-rwxr-xr-xt/t9400-git-cvsserver-server.sh2
-rwxr-xr-xt/t9902-completion.sh13
-rwxr-xr-xt/t9903-bash-prompt.sh2
-rw-r--r--t/test-lib-functions.sh3
-rw-r--r--t/test-lib-junit.sh10
-rw-r--r--t/test-lib.sh13
-rw-r--r--transport.c8
-rw-r--r--unpack-trees.c2
-rw-r--r--upload-pack.c27
-rw-r--r--usage.c16
-rw-r--r--wrapper.c10
-rw-r--r--xdiff/xdiff.h1
-rw-r--r--xdiff/xdiffi.c2
-rw-r--r--xdiff/xhistogram.c19
-rw-r--r--xdiff/xmacros.h18
-rw-r--r--xdiff/xpatience.c9
-rw-r--r--xdiff/xprepare.c41
-rw-r--r--xdiff/xutils.c17
-rw-r--r--xdiff/xutils.h3
315 files changed, 121312 insertions, 163284 deletions
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 3fa88b7..cd1f526 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -119,6 +119,10 @@ jobs:
- name: test
shell: bash
run: . /etc/profile && ci/run-test-slice.sh ${{matrix.nr}} 10
+ - name: print test failures
+ if: failure() && env.FAILED_TEST_ARTIFACTS != ''
+ shell: bash
+ run: ci/print-test-failures.sh
- name: Upload failed tests' directories
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
uses: actions/upload-artifact@v2
@@ -200,6 +204,10 @@ jobs:
env:
NO_SVN_TESTS: 1
run: . /etc/profile && ci/run-test-slice.sh ${{matrix.nr}} 10
+ - name: print test failures
+ if: failure() && env.FAILED_TEST_ARTIFACTS != ''
+ shell: bash
+ run: ci/print-test-failures.sh
- name: Upload failed tests' directories
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
uses: actions/upload-artifact@v2
@@ -253,6 +261,10 @@ jobs:
- uses: actions/checkout@v2
- run: ci/install-dependencies.sh
- run: ci/run-build-and-tests.sh
+ - name: print test failures
+ if: failure() && env.FAILED_TEST_ARTIFACTS != ''
+ shell: bash
+ run: ci/print-test-failures.sh
- name: Upload failed tests' directories
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
uses: actions/upload-artifact@v2
@@ -282,6 +294,10 @@ jobs:
- uses: actions/checkout@v1
- run: ci/install-docker-dependencies.sh
- run: ci/run-build-and-tests.sh
+ - name: print test failures
+ if: failure() && env.FAILED_TEST_ARTIFACTS != ''
+ shell: bash
+ run: ci/print-test-failures.sh
- name: Upload failed tests' directories
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
uses: actions/upload-artifact@v1
diff --git a/.gitignore b/.gitignore
index a452215..42fd725 100644
--- a/.gitignore
+++ b/.gitignore
@@ -185,6 +185,7 @@
/git-worktree
/git-write-tree
/git-core-*/?*
+/git.res
/gitweb/GITWEB-BUILD-OPTIONS
/gitweb/gitweb.cgi
/gitweb/static/gitweb.js
@@ -225,7 +226,6 @@
*.hcc
*.obj
*.lib
-*.res
*.sln
*.sp
*.suo
diff --git a/Documentation/Makefile b/Documentation/Makefile
index f2e7fc1..4f801f4 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -94,6 +94,7 @@ TECH_DOCS += MyFirstContribution
TECH_DOCS += MyFirstObjectWalk
TECH_DOCS += SubmittingPatches
TECH_DOCS += ToolsForGit
+TECH_DOCS += technical/bitmap-format
TECH_DOCS += technical/bundle-format
TECH_DOCS += technical/cruft-packs
TECH_DOCS += technical/hash-function-transition
diff --git a/Documentation/RelNotes/2.30.5.txt b/Documentation/RelNotes/2.30.5.txt
new file mode 100644
index 0000000..5191cab
--- /dev/null
+++ b/Documentation/RelNotes/2.30.5.txt
@@ -0,0 +1,12 @@
+Git v2.30.5 Release Notes
+=========================
+
+This release contains minor fix-ups for the changes that went into
+Git 2.30.3 and 2.30.4, addressing CVE-2022-29187.
+
+ * The safety check that verifies a safe ownership of the Git
+ worktree is now extended to also cover the ownership of the Git
+ directory (and the `.git` file, if there is any).
+
+Carlo Marcelo Arenas Belón (1):
+ setup: tighten ownership checks post CVE-2022-24765
diff --git a/Documentation/RelNotes/2.31.4.txt b/Documentation/RelNotes/2.31.4.txt
new file mode 100644
index 0000000..97a91fd
--- /dev/null
+++ b/Documentation/RelNotes/2.31.4.txt
@@ -0,0 +1,6 @@
+Git v2.31.4 Release Notes
+=========================
+
+This release merges up the fixes that appear in v2.30.5 to address
+the security issue CVE-2022-29187; see the release notes for that
+version for details.
diff --git a/Documentation/RelNotes/2.32.3.txt b/Documentation/RelNotes/2.32.3.txt
new file mode 100644
index 0000000..583fabe
--- /dev/null
+++ b/Documentation/RelNotes/2.32.3.txt
@@ -0,0 +1,6 @@
+Git v2.32.3 Release Notes
+=========================
+
+This release merges up the fixes that appear in v2.30.5 and
+v2.31.4 to address the security issue CVE-2022-29187; see the
+release notes for these versions for details.
diff --git a/Documentation/RelNotes/2.33.4.txt b/Documentation/RelNotes/2.33.4.txt
new file mode 100644
index 0000000..a145cc2
--- /dev/null
+++ b/Documentation/RelNotes/2.33.4.txt
@@ -0,0 +1,6 @@
+Git v2.33.4 Release Notes
+=========================
+
+This release merges up the fixes that appear in v2.30.5, v2.31.4
+and v2.32.3 to address the security issue CVE-2022-29187; see
+the release notes for these versions for details.
diff --git a/Documentation/RelNotes/2.34.4.txt b/Documentation/RelNotes/2.34.4.txt
new file mode 100644
index 0000000..2a6b223
--- /dev/null
+++ b/Documentation/RelNotes/2.34.4.txt
@@ -0,0 +1,6 @@
+Git v2.34.4 Release Notes
+=========================
+
+This release merges up the fixes that appear in v2.30.5, v2.31.4,
+v2.32.3 and v2.33.4 to address the security issue CVE-2022-29187;
+see the release notes for these versions for details.
diff --git a/Documentation/RelNotes/2.35.4.txt b/Documentation/RelNotes/2.35.4.txt
new file mode 100644
index 0000000..47abd5a
--- /dev/null
+++ b/Documentation/RelNotes/2.35.4.txt
@@ -0,0 +1,7 @@
+Git v2.35.4 Release Notes
+=========================
+
+This release merges up the fixes that appear in v2.30.5,
+v2.31.4, v2.32.3, v2.33.4 and v2.34.4 to address the security
+issue CVE-2022-29187; see the release notes for these versions
+for details.
diff --git a/Documentation/RelNotes/2.36.2.txt b/Documentation/RelNotes/2.36.2.txt
index ba5d5ac..958f5b4 100644
--- a/Documentation/RelNotes/2.36.2.txt
+++ b/Documentation/RelNotes/2.36.2.txt
@@ -1,10 +1,16 @@
Git v2.36.2 Release Notes
=========================
-This maintenance release is primarily to merge down updates to the
-build and CI procedures from the 'master' front, in order to ensure
-that we can cut healthy maintenance releases in the future. It also
-contains a handful of small and trivially-correct bugfixes.
+This release merges up the fixes that appear in v2.30.5, v2.31.4,
+v2.32.3, v2.33.4, v2.34.4 and v2.35.4 to address the security
+issue CVE-2022-29187; see the release notes for these versions
+for details.
+
+Apart from that, this maintenance release is primarily to merge down
+updates to the build and CI procedures from the 'master' front, in
+order to ensure that we can cut healthy maintenance releases in the
+future. It also contains a handful of small and trivially-correct
+bugfixes.
Fixes since v2.36.1
-------------------
diff --git a/Documentation/RelNotes/2.37.0.txt b/Documentation/RelNotes/2.37.0.txt
index 8f1ff3a..99dc7e3 100644
--- a/Documentation/RelNotes/2.37.0.txt
+++ b/Documentation/RelNotes/2.37.0.txt
@@ -54,8 +54,19 @@ UI, Workflows & Features
* Update the doctype written in gitweb output to xhtml5.
- * The "fetch.credentialsInUrl" configuration variable controls what
- happens when a URL with embedded login credential is used.
+ * The "transfer.credentialsInURL" configuration variable controls what
+ happens when a URL with embedded login credential is used on either
+ "fetch" or "push". Credentials are currently only detected in
+ `remote.<name>.url` config, not `remote.<name>.pushurl`.
+
+ * "git revert" learns "--reference" option to use more human-readable
+ reference to the commit it reverts in the message template it
+ prepares for the user.
+
+ * Various error messages that talk about the removal of
+ "--preserve-merges" in "rebase" have been strengthened, and "rebase
+ --abort" learned to get out of a state that was left by an earlier
+ use of the option.
Performance, Internal Implementation, Development Support etc.
@@ -80,14 +91,15 @@ Performance, Internal Implementation, Development Support etc.
* A workflow change for translators are being proposed. git.pot is
no longer version controlled and it is local responsibility of
- translaters to generate it.
+ translators to generate it.
* Plug the memory leaks from the trickiest API of all, the revision
walker.
* Rename .env_array member to .env in the child_process structure.
- * More fsmonitor--daemon.
+ * The fsmonitor--daemon handles even more corner cases when
+ watching filesystem events.
* A new bug() and BUG_if_bug() API is introduced to make it easier to
uniformly log "detect multiple bugs and abort in the end" pattern.
@@ -133,7 +145,7 @@ Fixes since v2.36
(merge 08bdd3a185 jc/cocci-xstrdup-or-null-fix later to maint).
* The path taken by "git multi-pack-index" command from the end user
- was compared with path internally prepared by the tool withut first
+ was compared with path internally prepared by the tool without first
normalizing, which lead to duplicated paths not being noticed,
which has been corrected.
(merge 11f9e8de3d ds/midx-normalize-pathname-before-comparison later to maint).
@@ -163,7 +175,7 @@ Fixes since v2.36
is given in "git status" not to use the break-rewrite heuristics.
(merge 84792322ed rs/commit-summary-wo-break-rewrite later to maint).
- * Update a few end-user facing messages around eol conversion.
+ * Update a few end-user facing messages around EOL conversion.
(merge c970d30c2c ah/convert-warning-message later to maint).
* Trace2 documentation updates.
@@ -222,9 +234,8 @@ Fixes since v2.36
* With a recent update to refuse access to repositories of other
people by default, "sudo make install" and "sudo git describe"
- stopped working. This series intends to loosen it while keeping
- the safety.
- (merge b9063afda1 cb/path-owner-check-with-sudo later to maint).
+ stopped working, which has been corrected.
+ (merge 6b11e3d52e cb/path-owner-check-with-sudo-plus later to maint).
* The tests that ensured merges stop when interfering local changes
are present did not make sure that local changes are preserved; now
@@ -256,7 +267,7 @@ Fixes since v2.36
has been corrected.
(merge b02fdbc80a jc/all-negative-pathspec later to maint).
- * With a more targetted workaround in http.c in another topic, we may
+ * With a more targeted workaround in http.c in another topic, we may
be able to lift this blanket "GCC12 dangling-pointer warning is
broken and unsalvageable" workaround.
(merge 419141e495 cb/buggy-gcc-12-workaround later to maint).
@@ -297,6 +308,9 @@ Fixes since v2.36
* Use-after-free (with another forget-to-free) fix.
(merge 323822c72b ab/remote-free-fix later to maint).
+ * Remove a coccinelle rule that is no longer relevant.
+ (merge b1299de4a1 jc/cocci-cleanup later to maint).
+
* Other code cleanup, docfix, build fix, etc.
(merge e6b2582da3 cm/reftable-0-length-memset later to maint).
(merge 0b75e5bf22 ab/misc-cleanup later to maint).
@@ -320,3 +334,4 @@ Fixes since v2.36
(merge 8c49d704ef fh/transport-push-leakfix later to maint).
(merge 1d232d38bd tl/ls-tree-oid-only later to maint).
(merge db7961e6a6 gc/document-config-worktree-scope later to maint).
+ (merge ce18a30bb7 fs/ssh-default-key-command-doc later to maint).
diff --git a/Documentation/RelNotes/2.37.1.txt b/Documentation/RelNotes/2.37.1.txt
new file mode 100644
index 0000000..8460932
--- /dev/null
+++ b/Documentation/RelNotes/2.37.1.txt
@@ -0,0 +1,17 @@
+Git 2.37.1 Release Notes
+========================
+
+This release merges up the fixes that appear in v2.30.5, v2.31.4,
+v2.32.3, v2.33.4, v2.34.4, v2.35.4, and v2.36.2 to address the
+security issue CVE-2022-29187; see the release notes for these
+versions for details.
+
+Fixes since Git 2.37
+--------------------
+
+ * Rewrite of "git add -i" in C that appeared in Git 2.25 didn't
+ correctly record a removed file to the index, which is an old
+ regression but has become widely known because the C version has
+ become the default in the latest release.
+
+ * Fix for CVS-2022-29187.
diff --git a/Documentation/RelNotes/2.37.2.txt b/Documentation/RelNotes/2.37.2.txt
new file mode 100644
index 0000000..d4acf9e
--- /dev/null
+++ b/Documentation/RelNotes/2.37.2.txt
@@ -0,0 +1,47 @@
+Git 2.37.2 Release Notes
+========================
+
+This primarily is to backport various fixes accumulated on the 'master'
+front since 2.37.1.
+
+Fixes since v2.37.1
+-------------------
+
+ * "git shortlog -n" relied on the underlying qsort() to be stable,
+ which shouldn't have. Fixed.
+
+ * Variable quoting fix in the vimdiff driver of "git mergetool".
+
+ * An earlier attempt to plug leaks placed a clean-up label to jump to
+ at a bogus place, which as been corrected.
+
+ * Fixes a long-standing corner case bug around directory renames in
+ the merge-ort strategy.
+
+ * Recent update to vimdiff layout code has been made more robust
+ against different end-user vim settings.
+
+ * In a non-bare repository, the behavior of Git when the
+ core.worktree configuration variable points at a directory that has
+ a repository as its subdirectory, regressed in Git 2.27 days.
+
+ * References to commands-to-be-typed-literally in "git rebase"
+ documentation mark-up have been corrected.
+
+ * Give _() markings to fatal/warning/usage: labels that are shown in
+ front of these messages.
+
+ * "git mktree --missing" lazily fetched objects that are missing from
+ the local object store, which was totally unnecessary for the purpose
+ of creating the tree object(s) from its input.
+
+ * Fixes for tests when the source directory has unusual characters in
+ its path, e.g. whitespaces, double-quotes, etc.
+
+ * Adjust technical/bitmap-format to be formatted by AsciiDoc, and
+ add some missing information to the documentation.
+
+ * Certain diff options are currently ignored when combined-diff is
+ shown; mark them as incompatible with the feature.
+
+Also contains minor documentation updates and code clean-ups.
diff --git a/Documentation/RelNotes/2.38.0.txt b/Documentation/RelNotes/2.38.0.txt
new file mode 100644
index 0000000..66e278b
--- /dev/null
+++ b/Documentation/RelNotes/2.38.0.txt
@@ -0,0 +1,191 @@
+Git v2.38 Release Notes
+=======================
+
+UI, Workflows & Features
+
+ * "git remote show [-n] frotz" now pays attention to negative
+ pathspec.
+
+ * "git push" sometimes perform poorly when reachability bitmaps are
+ used, even in a repository where other operations are helped by
+ bitmaps. The push.useBitmaps configuration variable is introduced
+ to allow disabling use of reachability bitmaps only for "git push".
+
+ * "git grep -m<max-hits>" is a way to limit the hits shown per file.
+
+ * "git merge-tree" learned a new mode where it takes two commits and
+ computes a tree that would result in the merge commit, if the
+ histories leading to these two commits were to be merged.
+
+ * "git mv A B" in a sparsely populated working tree can be asked to
+ move a path between directories that are "in cone" (i.e. expected
+ to be materialized in the working tree) and "out of cone"
+ (i.e. expected to be hidden). The handling of such cases has been
+ improved.
+
+ * Earlier, HTTP transport clients learned to tell the server side
+ what locale they are in by sending Accept-Language HTTP header, but
+ this was done only for some requests but not others.
+
+ * Introduce a discovery.barerepository configuration variable that
+ allows users to forbid discovery of bare repositories.
+
+ * Various messages that come from the pack-bitmap codepaths have been
+ tweaked.
+
+ * "git rebase -i" learns to update branches whose tip appear in the
+ rebased range with "--update-refs" option.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * Collection of what is referenced by objects in promisor packs have
+ been optimized to inspect these objects in the in-pack order.
+
+ * Introduce a helper to see if a branch is already being worked on
+ (hence should not be newly checked out in a working tree), which
+ performs much better than the existing find_shared_symref() to
+ replace many uses of the latter.
+
+ * Teach "git archive" to (optionally and then by default) avoid
+ spawning an external "gzip" process when creating ".tar.gz" (and
+ ".tgz") archives.
+
+ * Allow large objects read from a packstream to be streamed into a
+ loose object file straight, without having to keep it in-core as a
+ whole.
+
+ * Further preparation to turn git-submodule.sh into a builtin
+ continues.
+
+ * Apply Coccinelle rule to turn raw memmove() into MOVE_ARRAY() cpp
+ macro, which would improve maintainability and readability.
+
+ * Teach "make all" to build gitweb as well.
+
+ * Tweak tests so that they still work when the "git init" template
+ did not create .git/info directory.
+
+ * Add Coccinelle rules to detect the pattern of initializing and then
+ finalizing a structure without using it in between at all, which
+ happens after code restructuring and the compilers fail to
+ recognize as an unused variable.
+
+ * The code to convert between GPG trust level strings and internal
+ constants we use to represent them have been cleaned up.
+
+ * Support for libnettle as SHA256 implementation has been added.
+
+ * The way "git multi-pack" uses parse-options API has been improved.
+
+ * A coccinelle rule (in contrib/) to encourage use of COPY_ARRAY
+ macro has been improved.
+
+ * API tweak to make it easier to run fuzz testing on commit-graph parser.
+
+ * Omit fsync-related trace2 entries when their values are all zero.
+
+
+Fixes since v2.37
+-----------------
+
+ * Rewrite of "git add -i" in C that appeared in Git 2.25 didn't
+ correctly record a removed file to the index, which was fixed.
+
+ * Certain diff options are currently ignored when combined-diff is
+ shown; mark them as incompatible with the feature.
+
+ * Adjust technical/bitmap-format to be formatted by AsciiDoc, and
+ add some missing information to the documentation.
+
+ * Fixes for tests when the source directory has unusual characters in
+ its path, e.g. whitespaces, double-quotes, etc.
+
+ * "git mktree --missing" lazily fetched objects that are missing from
+ the local object store, which was totally unnecessary for the purpose
+ of creating the tree object(s) from its input.
+
+ * Give _() markings to fatal/warning/usage: labels that are shown in
+ front of these messages.
+
+ * References to commands-to-be-typed-literally in "git rebase"
+ documentation mark-up have been corrected.
+
+ * In a non-bare repository, the behavior of Git when the
+ core.worktree configuration variable points at a directory that has
+ a repository as its subdirectory, regressed in Git 2.27 days.
+
+ * Recent update to vimdiff layout code has been made more robust
+ against different end-user vim settings.
+
+ * Plug various memory leaks.
+ (merge ece3974ba6 ab/leakfix later to maint).
+
+ * Plug various memory leaks in test-tool commands.
+ (merge f40a693450 ab/test-tool-leakfix later to maint).
+
+ * Fixes a long-standing corner case bug around directory renames in
+ the merge-ort strategy.
+
+ * The resolve-undo information in the index was not protected against
+ GC, which has been corrected.
+ (merge e0ad13977a jc/resolve-undo later to maint).
+
+ * A corner case bug where lazily fetching objects from a promisor
+ remote resulted in infinite recursion has been corrected.
+ (merge cb88b37cb9 hx/lookup-commit-in-graph-fix later to maint).
+
+ * "git clone" from a repository with some ref whose HEAD is unborn
+ did not set the HEAD in the resulting repository correctly, which
+ has been corrected.
+ (merge daf7898abb jk/clone-unborn-confusion later to maint).
+
+ * An earlier attempt to plug leaks placed a clean-up label to jump to
+ at a bogus place, which as been corrected.
+
+ * Variable quoting fix in the vimdiff driver of "git mergetool"
+
+ * "git shortlog -n" relied on the underlying qsort() to be stable,
+ which shouldn't have. Fixed.
+
+ * A fix for a regression in test framework.
+
+ * mkstemp() emulation on Windows has been improved.
+ (merge ae25974de3 rs/mingw-tighten-mkstemp later to maint).
+
+ * Add missing documentation for "include" and "includeIf" features in
+ "git config" file format, which incidentally teaches the command
+ line completion to include them in its offerings.
+ (merge 07aed58017 mb/config-document-include later to maint).
+
+ * Avoid "white/black-list" in documentation and code comments.
+ (merge f5adaa5cc3 ds/doc-wo-whitelist later to maint).
+
+ * Workaround for a compiler warning against use of die() in
+ osx-keychain (in contrib/).
+ (merge f2fc531585 ld/osx-keychain-usage-fix later to maint).
+
+ * Workaround for a false positive compiler warning.
+ (merge b4f52f09ae ds/win-syslog-compiler-fix later to maint).
+
+ * "git p4" working on UTF-16 files on Windows did not implement
+ CRLF-to-LF conversion correctly, which has been corrected.
+ (merge 4d35f74421 mb/p4-utf16-crlf later to maint).
+
+ * "git p4" did not handle non-ASCII client name well, which has been
+ corrected.
+ (merge d205483695 kk/p4-client-name-encoding-fix later to maint).
+
+ * "rerere-train" script (in contrib/) used to honor commit.gpgSign
+ while recreating the throw-away merges.
+ (merge cc391fc886 cl/rerere-train-with-no-sign later to maint).
+
+ * "git checkout" miscounted the paths it updated, which has been
+ corrected.
+ (merge 611c7785e8 mt/checkout-count-fix later to maint).
+
+ * Other code cleanup, docfix, build fix, etc.
+ (merge a700395eaf ma/t4200-update later to maint).
+ (merge ae436f283c ma/sparse-checkout-cone-doc-fix later to maint).
+ (merge a10f6e2bda sg/index-format-doc-update later to maint).
+ (merge ce5f07983d mt/pkt-line-comment-tweak later to maint).
diff --git a/Documentation/config.txt b/Documentation/config.txt
index e284b04..5b5b976 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -445,6 +445,8 @@ include::config/i18n.txt[]
include::config/imap.txt[]
+include::config/includeif.txt[]
+
include::config/index.txt[]
include::config/init.txt[]
@@ -495,6 +497,8 @@ include::config/repack.txt[]
include::config/rerere.txt[]
+include::config/revert.txt[]
+
include::config/safe.txt[]
include::config/sendemail.txt[]
diff --git a/Documentation/config/core.txt b/Documentation/config/core.txt
index 41e330f..37afbaf 100644
--- a/Documentation/config/core.txt
+++ b/Documentation/config/core.txt
@@ -444,17 +444,32 @@ You probably do not need to adjust this value.
Common unit suffixes of 'k', 'm', or 'g' are supported.
core.bigFileThreshold::
- Files larger than this size are stored deflated, without
- attempting delta compression. Storing large files without
- delta compression avoids excessive memory usage, at the
- slight expense of increased disk usage. Additionally files
- larger than this size are always treated as binary.
+ The size of files considered "big", which as discussed below
+ changes the behavior of numerous git commands, as well as how
+ such files are stored within the repository. The default is
+ 512 MiB. Common unit suffixes of 'k', 'm', or 'g' are
+ supported.
+
-Default is 512 MiB on all platforms. This should be reasonable
-for most projects as source code and other text files can still
-be delta compressed, but larger binary media files won't be.
+Files above the configured limit will be:
+
-Common unit suffixes of 'k', 'm', or 'g' are supported.
+* Stored deflated in packfiles, without attempting delta compression.
++
+The default limit is primarily set with this use-case in mind. With it,
+most projects will have their source code and other text files delta
+compressed, but not larger binary media files.
++
+Storing large files without delta compression avoids excessive memory
+usage, at the slight expense of increased disk usage.
++
+* Will be treated as if they were labeled "binary" (see
+ linkgit:gitattributes[5]). e.g. linkgit:git-log[1] and
+ linkgit:git-diff[1] will not compute diffs for files above this limit.
++
+* Will generally be streamed when written, which avoids excessive
+memory usage, at the cost of some fixed overhead. Commands that make
+use of this include linkgit:git-archive[1],
+linkgit:git-fast-import[1], linkgit:git-index-pack[1],
+linkgit:git-unpack-objects[1] and linkgit:git-fsck[1].
core.excludesFile::
Specifies the pathname to the file that contains patterns to
@@ -707,8 +722,8 @@ core.sparseCheckout::
core.sparseCheckoutCone::
Enables the "cone mode" of the sparse checkout feature. When the
sparse-checkout file contains a limited set of patterns, this
- mode provides significant performance advantages. The "non
- cone mode" can be requested to allow specifying a more flexible
+ mode provides significant performance advantages. The "non-cone
+ mode" can be requested to allow specifying more flexible
patterns by setting this variable to 'false'. See
linkgit:git-sparse-checkout[1] for more information.
diff --git a/Documentation/config/fetch.txt b/Documentation/config/fetch.txt
index 0db7fe8..cd65d23 100644
--- a/Documentation/config/fetch.txt
+++ b/Documentation/config/fetch.txt
@@ -96,17 +96,3 @@ fetch.writeCommitGraph::
merge and the write may take longer. Having an updated commit-graph
file helps performance of many Git commands, including `git merge-base`,
`git push -f`, and `git log --graph`. Defaults to false.
-
-fetch.credentialsInUrl::
- A URL can contain plaintext credentials in the form
- `<protocol>://<user>:<password>@<domain>/<path>`. Using such URLs
- is not recommended as it exposes the password in multiple ways,
- including Git storing the URL as plaintext in the repository config.
- The `fetch.credentialsInUrl` option provides instruction for how Git
- should react to seeing such a URL, with these values:
-+
-* `allow` (default): Git will proceed with its activity without warning.
-* `warn`: Git will write a warning message to `stderr` when parsing a URL
- with a plaintext credential.
-* `die`: Git will write a failure message to `stderr` when parsing a URL
- with a plaintext credential.
diff --git a/Documentation/config/gpg.txt b/Documentation/config/gpg.txt
index 86892ad..86f6308 100644
--- a/Documentation/config/gpg.txt
+++ b/Documentation/config/gpg.txt
@@ -36,9 +36,12 @@ gpg.minTrustLevel::
gpg.ssh.defaultKeyCommand::
This command that will be run when user.signingkey is not set and a ssh
- signature is requested. On successful exit a valid ssh public key is
- expected in the first line of its output. To automatically use the first
- available key from your ssh-agent set this to "ssh-add -L".
+ signature is requested. On successful exit a valid ssh public key
+ prefixed with `key::` is expected in the first line of its output.
+ This allows for a script doing a dynamic lookup of the correct public
+ key when it is impractical to statically configure `user.signingKey`.
+ For example when keys or SSH Certificates are rotated frequently or
+ selection of the right key depends on external factors unknown to git.
gpg.ssh.allowedSignersFile::
A file containing ssh public keys which you are willing to trust.
diff --git a/Documentation/config/http.txt b/Documentation/config/http.txt
index 179d03e..afeeccf 100644
--- a/Documentation/config/http.txt
+++ b/Documentation/config/http.txt
@@ -203,7 +203,7 @@ http.schannelUseSSLCAInfo::
when the `schannel` backend was configured via `http.sslBackend`,
unless `http.schannelUseSSLCAInfo` overrides this behavior.
-http.pinnedpubkey::
+http.pinnedPubkey::
Public key of the https service. It may either be the filename of
a PEM or DER encoded public key file or a string starting with
'sha256//' followed by the base64 encoded sha256 hash of the
diff --git a/Documentation/config/includeif.txt b/Documentation/config/includeif.txt
new file mode 100644
index 0000000..82fe431
--- /dev/null
+++ b/Documentation/config/includeif.txt
@@ -0,0 +1,6 @@
+include.path::
+includeIf.<condition>.path::
+ Special variables to include other configuration files. See
+ the "CONFIGURATION FILE" section in the main
+ linkgit:git-config[1] documentation,
+ specifically the "Includes" and "Conditional Includes" subsections.
diff --git a/Documentation/config/push.txt b/Documentation/config/push.txt
index e32801e..7386fea 100644
--- a/Documentation/config/push.txt
+++ b/Documentation/config/push.txt
@@ -137,3 +137,8 @@ push.negotiate::
server attempt to find commits in common. If "false", Git will
rely solely on the server's ref advertisement to find commits
in common.
+
+push.useBitmaps::
+ If set to "false", disable use of bitmaps for "git push" even if
+ `pack.useBitmaps` is "true", without preventing other git operations
+ from using bitmaps. Default is true.
diff --git a/Documentation/config/rebase.txt b/Documentation/config/rebase.txt
index 8c979cb..f19bd0e 100644
--- a/Documentation/config/rebase.txt
+++ b/Documentation/config/rebase.txt
@@ -21,6 +21,9 @@ rebase.autoStash::
`--autostash` options of linkgit:git-rebase[1].
Defaults to false.
+rebase.updateRefs::
+ If set to true enable `--update-refs` option by default.
+
rebase.missingCommitsCheck::
If set to "warn", git rebase -i will print a warning if some
commits are removed (e.g. a line was deleted), however the
diff --git a/Documentation/config/revert.txt b/Documentation/config/revert.txt
new file mode 100644
index 0000000..802d6fa
--- /dev/null
+++ b/Documentation/config/revert.txt
@@ -0,0 +1,3 @@
+revert.reference::
+ Setting this variable to true makes `git revert` behave
+ as if the `--reference` option is given.
diff --git a/Documentation/config/safe.txt b/Documentation/config/safe.txt
index 1ee10fa..bde7f31 100644
--- a/Documentation/config/safe.txt
+++ b/Documentation/config/safe.txt
@@ -1,3 +1,22 @@
+safe.bareRepository::
+ Specifies which bare repositories Git will work with. The currently
+ supported values are:
++
+* `all`: Git works with all bare repositories. This is the default.
+* `explicit`: Git only works with bare repositories specified via
+ the top-level `--git-dir` command-line option, or the `GIT_DIR`
+ environment variable (see linkgit:git[1]).
++
+If you do not use bare repositories in your workflow, then it may be
+beneficial to set `safe.bareRepository` to `explicit` in your global
+config. This will protect you from attacks that involve cloning a
+repository that contains a bare repository and running a Git command
+within that directory.
++
+This config setting is only respected in protected configuration (see
+<<SCOPES>>). This prevents the untrusted repository from tampering with
+this value.
+
safe.directory::
These config entries specify Git-tracked directories that are
considered safe even if they are owned by someone other than the
@@ -12,9 +31,9 @@ via `git config --add`. To reset the list of safe directories (e.g. to
override any such directories specified in the system config), add a
`safe.directory` entry with an empty value.
+
-This config setting is only respected when specified in a system or global
-config, not when it is specified in a repository config, via the command
-line option `-c safe.directory=<path>`, or in environment variables.
+This config setting is only respected in protected configuration (see
+<<SCOPES>>). This prevents the untrusted repository from tampering with this
+value.
+
The value of this setting is interpolated, i.e. `~/<path>` expands to a
path relative to the home directory and `%(prefix)/<path>` expands to a
@@ -30,12 +49,13 @@ that you deem safe.
As explained, Git only allows you to access repositories owned by
yourself, i.e. the user who is running Git, by default. When Git
is running as 'root' in a non Windows platform that provides sudo,
- however, git checks the SUDO_UID environment variable that sudo creates
-and will allow access to the uid recorded as its value instead.
+however, git checks the SUDO_UID environment variable that sudo creates
+and will allow access to the uid recorded as its value in addition to
+the id from 'root'.
This is to make it easy to perform a common sequence during installation
"make && sudo make install". A git process running under 'sudo' runs as
'root' but the 'sudo' command exports the environment variable to record
which id the original user has.
If that is not what you would prefer and want git to only trust
-repositories that are owned by root instead, then you must remove
+repositories that are owned by root instead, then you can remove
the `SUDO_UID` variable from root's environment before invoking git.
diff --git a/Documentation/config/transfer.txt b/Documentation/config/transfer.txt
index b49429e..7ed917f 100644
--- a/Documentation/config/transfer.txt
+++ b/Documentation/config/transfer.txt
@@ -1,3 +1,41 @@
+transfer.credentialsInUrl::
+ A configured URL can contain plaintext credentials in the form
+ `<protocol>://<user>:<password>@<domain>/<path>`. You may want
+ to warn or forbid the use of such configuration (in favor of
+ using linkgit:git-credential[1]). This will be used on
+ linkgit:git-clone[1], linkgit:git-fetch[1], linkgit:git-push[1],
+ and any other direct use of the configured URL.
++
+Note that this is currently limited to detecting credentials in
+`remote.<name>.url` configuration, it won't detect credentials in
+`remote.<name>.pushurl` configuration.
++
+You might want to enable this to prevent inadvertent credentials
+exposure, e.g. because:
++
+* The OS or system where you're running git may not provide way way or
+ otherwise allow you to configure the permissions of the
+ configuration file where the username and/or password are stored.
+* Even if it does, having such data stored "at rest" might expose you
+ in other ways, e.g. a backup process might copy the data to another
+ system.
+* The git programs will pass the full URL to one another as arguments
+ on the command-line, meaning the credentials will be exposed to other
+ users on OS's or systems that allow other users to see the full
+ process list of other users. On linux the "hidepid" setting
+ documented in procfs(5) allows for configuring this behavior.
++
+If such concerns don't apply to you then you probably don't need to be
+concerned about credentials exposure due to storing that sensitive
+data in git's configuration files. If you do want to use this, set
+`transfer.credentialsInUrl` to one of these values:
++
+* `allow` (default): Git will proceed with its activity without warning.
+* `warn`: Git will write a warning message to `stderr` when parsing a URL
+ with a plaintext credential.
+* `die`: Git will write a failure message to `stderr` when parsing a URL
+ with a plaintext credential.
+
transfer.fsckObjects::
When `fetch.fsckObjects` or `receive.fsckObjects` are
not set, the value of this variable is used instead.
diff --git a/Documentation/config/uploadpack.txt b/Documentation/config/uploadpack.txt
index 32fad5b..16264d8 100644
--- a/Documentation/config/uploadpack.txt
+++ b/Documentation/config/uploadpack.txt
@@ -49,9 +49,9 @@ uploadpack.packObjectsHook::
`pack-objects` to the hook, and expects a completed packfile on
stdout.
+
-Note that this configuration variable is ignored if it is seen in the
-repository-level config (this is a safety measure against fetching from
-untrusted repositories).
+Note that this configuration variable is only respected when it is specified
+in protected configuration (see <<SCOPES>>). This is a safety measure
+against fetching from untrusted repositories.
uploadpack.allowFilter::
If this option is set, `upload-pack` will support partial
diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt
index 7a9c3b6..a3ae874 100644
--- a/Documentation/diff-format.txt
+++ b/Documentation/diff-format.txt
@@ -43,7 +43,7 @@ That is, from the left to the right:
. a space.
. sha1 for "src"; 0\{40\} if creation or unmerged.
. a space.
-. sha1 for "dst"; 0\{40\} if creation, unmerged or "look at work tree".
+. sha1 for "dst"; 0\{40\} if deletion, unmerged or "work tree out of sync with the index".
. a space.
. status, followed by optional "score" number.
. a tab or a NUL when `-z` option is used.
@@ -69,8 +69,8 @@ percentage of similarity between the source and target of the move or
copy). Status letter M may be followed by a score (denoting the
percentage of dissimilarity) for file rewrites.
-<sha1> is shown as all 0's if a file is new on the filesystem
-and it is out of sync with the index.
+The sha1 for "dst" is shown as all 0's if a file on the filesystem
+is out of sync with the index.
Example:
diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
index 56989a2..60c0409 100644
--- a/Documentation/git-archive.txt
+++ b/Documentation/git-archive.txt
@@ -34,10 +34,12 @@ OPTIONS
-------
--format=<fmt>::
- Format of the resulting archive: 'tar' or 'zip'. If this option
+ Format of the resulting archive. Possible values are `tar`,
+ `zip`, `tar.gz`, `tgz`, and any format defined using the
+ configuration option `tar.<format>.command`. If `--format`
is not given, and the output file is specified, the format is
- inferred from the filename if possible (e.g. writing to "foo.zip"
- makes the output to be in the zip format). Otherwise the output
+ inferred from the filename if possible (e.g. writing to `foo.zip`
+ makes the output to be in the `zip` format). Otherwise the output
format is `tar`.
-l::
@@ -143,17 +145,16 @@ tar.<format>.command::
is executed using the shell with the generated tar file on its
standard input, and should produce the final output on its
standard output. Any compression-level options will be passed
- to the command (e.g., "-9"). An output file with the same
- extension as `<format>` will be use this format if no other
- format is given.
+ to the command (e.g., `-9`).
+
-The "tar.gz" and "tgz" formats are defined automatically and default to
-`gzip -cn`. You may override them with custom commands.
+The `tar.gz` and `tgz` formats are defined automatically and use the
+magic command `git archive gzip` by default, which invokes an internal
+implementation of gzip.
tar.<format>.remote::
- If true, enable `<format>` for use by remote clients via
+ If true, enable the format for use by remote clients via
linkgit:git-upload-archive[1]. Defaults to false for
- user-defined formats, but true for the "tar.gz" and "tgz"
+ user-defined formats, but true for the `tar.gz` and `tgz`
formats.
[[ATTRIBUTES]]
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 9376e39..7a2bcb2 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -297,23 +297,20 @@ The default is to use a pager.
FILES
-----
-If not set explicitly with `--file`, there are four files where
-'git config' will search for configuration options:
+By default, 'git config' will read configuration options from multiple
+files:
$(prefix)/etc/gitconfig::
System-wide configuration file.
$XDG_CONFIG_HOME/git/config::
- Second user-specific configuration file. If $XDG_CONFIG_HOME is not set
- or empty, `$HOME/.config/git/config` will be used. Any single-valued
- variable set in this file will be overwritten by whatever is in
- `~/.gitconfig`. It is a good idea not to create this file if
- you sometimes use older versions of Git, as support for this
- file was added fairly recently.
-
~/.gitconfig::
- User-specific configuration file. Also called "global"
- configuration file.
+ User-specific configuration files. When the XDG_CONFIG_HOME environment
+ variable is not set or empty, $HOME/.config/ is used as
+ $XDG_CONFIG_HOME.
++
+These are also called "global" configuration files. If both files exist, both
+files are read in the order given above.
$GIT_DIR/config::
Repository specific configuration file.
@@ -322,28 +319,80 @@ $GIT_DIR/config.worktree::
This is optional and is only searched when
`extensions.worktreeConfig` is present in $GIT_DIR/config.
-If no further options are given, all reading options will read all of these
-files that are available. If the global or the system-wide configuration
-file are not available they will be ignored. If the repository configuration
-file is not available or readable, 'git config' will exit with a non-zero
-error code. However, in neither case will an error message be issued.
+You may also provide additional configuration parameters when running any
+git command by using the `-c` option. See linkgit:git[1] for details.
+
+Options will be read from all of these files that are available. If the
+global or the system-wide configuration files are missing or unreadable they
+will be ignored. If the repository configuration file is missing or unreadable,
+'git config' will exit with a non-zero error code. An error message is produced
+if the file is unreadable, but not if it is missing.
The files are read in the order given above, with last value found taking
precedence over values read earlier. When multiple values are taken then all
values of a key from all files will be used.
-You may override individual configuration parameters when running any git
-command by using the `-c` option. See linkgit:git[1] for details.
-
-All writing options will per default write to the repository specific
+By default, options are only written to the repository specific
configuration file. Note that this also affects options like `--replace-all`
and `--unset`. *'git config' will only ever change one file at a time*.
-You can override these rules using the `--global`, `--system`,
-`--local`, `--worktree`, and `--file` command-line options; see
-<<OPTIONS>> above.
+You can limit which configuration sources are read from or written to by
+specifying the path of a file with the `--file` option, or by specifying a
+configuration scope with `--system`, `--global`, `--local`, or `--worktree`.
+For more, see <<OPTIONS>> above.
+
+[[SCOPES]]
+SCOPES
+------
+
+Each configuration source falls within a configuration scope. The scopes
+are:
+
+system::
+ $(prefix)/etc/gitconfig
+
+global::
+ $XDG_CONFIG_HOME/git/config
++
+~/.gitconfig
+
+local::
+ $GIT_DIR/config
+
+worktree::
+ $GIT_DIR/config.worktree
+
+command::
+ GIT_CONFIG_{COUNT,KEY,VALUE} environment variables (see <<ENVIRONMENT>>
+ below)
++
+the `-c` option
+
+With the exception of 'command', each scope corresponds to a command line
+option: `--system`, `--global`, `--local`, `--worktree`.
+
+When reading options, specifying a scope will only read options from the
+files within that scope. When writing options, specifying a scope will write
+to the files within that scope (instead of the repository specific
+configuration file). See <<OPTIONS>> above for a complete description.
+
+Most configuration options are respected regardless of the scope it is
+defined in, but some options are only respected in certain scopes. See the
+respective option's documentation for the full details.
+
+Protected configuration
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Protected configuration refers to the 'system', 'global', and 'command' scopes.
+For security reasons, certain options are only respected when they are
+specified in protected configuration, and ignored otherwise.
+Git treats these scopes as if they are controlled by the user or a trusted
+administrator. This is because an attacker who controls these scopes can do
+substantial harm without using Git, so it is assumed that the user's environment
+protects these scopes against attackers.
+[[ENVIRONMENT]]
ENVIRONMENT
-----------
diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt
index 4dc57ed..53f111b 100644
--- a/Documentation/git-cvsserver.txt
+++ b/Documentation/git-cvsserver.txt
@@ -63,11 +63,10 @@ Print version information and exit
Print usage information and exit
<directory>::
-You can specify a list of allowed directories. If no directories
-are given, all are allowed. This is an additional restriction, gitcvs
-access still needs to be enabled by the `gitcvs.enabled` config option
-unless `--export-all` was given, too.
-
+The remaining arguments provide a list of directories. If no directories
+are given, then all are allowed. Repositories within these directories
+still require the `gitcvs.enabled` config option, unless `--export-all`
+is specified.
LIMITATIONS
-----------
@@ -311,11 +310,13 @@ ENVIRONMENT
These variables obviate the need for command-line options in some
circumstances, allowing easier restricted usage through git-shell.
-GIT_CVSSERVER_BASE_PATH takes the place of the argument to --base-path.
+GIT_CVSSERVER_BASE_PATH::
+ This variable replaces the argument to --base-path.
-GIT_CVSSERVER_ROOT specifies a single-directory whitelist. The
-repository must still be configured to allow access through
-git-cvsserver, as described above.
+GIT_CVSSERVER_ROOT::
+ This variable specifies a single directory, replacing the
+ `<directory>...` argument list. The repository still requires the
+ `gitcvs.enabled` config option, unless `--export-all` is specified.
When these environment variables are set, the corresponding
command-line arguments may not be used.
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index fdc28c0..236df51 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -32,8 +32,8 @@ that service if it is enabled.
It verifies that the directory has the magic file "git-daemon-export-ok", and
it will refuse to export any Git directory that hasn't explicitly been marked
for export this way (unless the `--export-all` parameter is specified). If you
-pass some directory paths as 'git daemon' arguments, you can further restrict
-the offers to a whitelist comprising of those.
+pass some directory paths as 'git daemon' arguments, the offers are limited to
+repositories within those directories.
By default, only `upload-pack` service is enabled, which serves
'git fetch-pack' and 'git ls-remote' clients, which are invoked
@@ -50,7 +50,7 @@ OPTIONS
Match paths exactly (i.e. don't allow "/foo/repo" when the real path is
"/foo/repo.git" or "/foo/repo/.git") and don't do user-relative paths.
'git daemon' will refuse to start when this option is enabled and no
- whitelist is specified.
+ directory arguments are provided.
--base-path=<path>::
Remap all the path requests as relative to the given path.
@@ -73,7 +73,7 @@ OPTIONS
%IP for the server's IP address, %P for the port number,
and %D for the absolute path of the named repository.
After interpolation, the path is validated against the directory
- whitelist.
+ list.
--export-all::
Allow pulling from all directories that look like Git repositories
@@ -218,9 +218,11 @@ standard output to be sent to the requestor as an error message when
it declines the service.
<directory>::
- A directory to add to the whitelist of allowed directories. Unless
- --strict-paths is specified this will also include subdirectories
- of each named directory.
+ The remaining arguments provide a list of directories. If any
+ directories are specified, then the `git-daemon` process will
+ serve a requested directory only if it is contained in one of
+ these directories. If `--strict-paths` is specified, then the
+ requested directory must match one of these directories exactly.
SERVICES
--------
@@ -264,9 +266,8 @@ git 9418/tcp # Git Version Control System
'git daemon' as inetd server::
To set up 'git daemon' as an inetd service that handles any
- repository under the whitelisted set of directories, /pub/foo
- and /pub/bar, place an entry like the following into
- /etc/inetd all on one line:
+ repository within `/pub/foo` or `/pub/bar`, place an entry like
+ the following into `/etc/inetd` all on one line:
+
------------------------------------------------
git stream tcp nowait nobody /usr/bin/git
diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.txt
index 679cae2..c30d8f0 100644
--- a/Documentation/git-diff-index.txt
+++ b/Documentation/git-diff-index.txt
@@ -69,8 +69,8 @@ done an `update-index` to make that effective in the index file.
matches my working directory. But doing a 'git diff-index' does:
torvalds@ppc970:~/git> git diff-index --cached HEAD
- -100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 commit.c
- +100644 blob 4161aecc6700a2eb579e842af0b7f22b98443f74 git-commit.c
+ :100644 000000 4161aecc6700a2eb579e842af0b7f22b98443f74 0000000000000000000000000000000000000000 D commit.c
+ :000000 100644 0000000000000000000000000000000000000000 4161aecc6700a2eb579e842af0b7f22b98443f74 A git-commit.c
You can see easily that the above is a rename.
@@ -103,7 +103,7 @@ have not actually done a 'git update-index' on it yet - there is no
"object" associated with the new state, and you get:
torvalds@ppc970:~/v2.6/linux> git diff-index --abbrev HEAD
- :100644 100664 7476bb... 000000... kernel/sched.c
+ :100644 100644 7476bb5ba 000000000 M kernel/sched.c
i.e., it shows that the tree has changed, and that `kernel/sched.c` is
not up to date and may contain new stuff. The all-zero sha1 means that to
diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt
index ba4e677..0af7540 100644
--- a/Documentation/git-gc.txt
+++ b/Documentation/git-gc.txt
@@ -56,8 +56,7 @@ be performed as well.
--cruft::
When expiring unreachable objects, pack them separately into a
- cruft pack instead of storing the loose objects as loose
- objects.
+ cruft pack instead of storing them as loose objects.
--prune=<date>::
Prune loose objects older than date (default is 2 weeks ago,
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index 3d393fb..58d944b 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -23,6 +23,7 @@ SYNOPSIS
[--break] [--heading] [-p | --show-function]
[-A <post-context>] [-B <pre-context>] [-C <context>]
[-W | --function-context]
+ [(-m | --max-count) <num>]
[--threads <num>]
[-f <file>] [-e] <pattern>
[--and|--or|--not|(|)|-e <pattern>...]
@@ -238,6 +239,14 @@ providing this option will cause it to die.
`git diff` works out patch hunk headers (see 'Defining a
custom hunk-header' in linkgit:gitattributes[5]).
+-m <num>::
+--max-count <num>::
+ Limit the amount of matches per file. When using the `-v` or
+ `--invert-match` option, the search stops after the specified
+ number of non-matches. A value of -1 will return unlimited
+ results (the default). A value of 0 will exit immediately with
+ a non-zero status.
+
--threads <num>::
Number of grep worker threads to use.
See `grep.threads` in 'CONFIGURATION' for more information.
diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt
index 58731c1..d6c3567 100644
--- a/Documentation/git-merge-tree.txt
+++ b/Documentation/git-merge-tree.txt
@@ -3,26 +3,237 @@ git-merge-tree(1)
NAME
----
-git-merge-tree - Show three-way merge without touching index
+git-merge-tree - Perform merge without touching index or working tree
SYNOPSIS
--------
[verse]
-'git merge-tree' <base-tree> <branch1> <branch2>
+'git merge-tree' [--write-tree] [<options>] <branch1> <branch2>
+'git merge-tree' [--trivial-merge] <base-tree> <branch1> <branch2> (deprecated)
+[[NEWMERGE]]
DESCRIPTION
-----------
-Reads three tree-ish, and output trivial merge results and
-conflicting stages to the standard output. This is similar to
-what three-way 'git read-tree -m' does, but instead of storing the
-results in the index, the command outputs the entries to the
-standard output.
-
-This is meant to be used by higher level scripts to compute
-merge results outside of the index, and stuff the results back into the
-index. For this reason, the output from the command omits
-entries that match the <branch1> tree.
+
+This command has a modern `--write-tree` mode and a deprecated
+`--trivial-merge` mode. With the exception of the
+<<DEPMERGE,DEPRECATED DESCRIPTION>> section at the end, the rest of
+this documentation describes modern `--write-tree` mode.
+
+Performs a merge, but does not make any new commits and does not read
+from or write to either the working tree or index.
+
+The performed merge will use the same feature as the "real"
+linkgit:git-merge[1], including:
+
+ * three way content merges of individual files
+ * rename detection
+ * proper directory/file conflict handling
+ * recursive ancestor consolidation (i.e. when there is more than one
+ merge base, creating a virtual merge base by merging the merge bases)
+ * etc.
+
+After the merge completes, a new toplevel tree object is created. See
+`OUTPUT` below for details.
+
+OPTIONS
+-------
+
+-z::
+ Do not quote filenames in the <Conflicted file info> section,
+ and end each filename with a NUL character rather than
+ newline. Also begin the messages section with a NUL character
+ instead of a newline. See <<OUTPUT>> below for more information.
+
+--name-only::
+ In the Conflicted file info section, instead of writing a list
+ of (mode, oid, stage, path) tuples to output for conflicted
+ files, just provide a list of filenames with conflicts (and
+ do not list filenames multiple times if they have multiple
+ conflicting stages).
+
+--[no-]messages::
+ Write any informational messages such as "Auto-merging <path>"
+ or CONFLICT notices to the end of stdout. If unspecified, the
+ default is to include these messages if there are merge
+ conflicts, and to omit them otherwise.
+
+--allow-unrelated-histories::
+ merge-tree will by default error out if the two branches specified
+ share no common history. This flag can be given to override that
+ check and make the merge proceed anyway.
+
+[[OUTPUT]]
+OUTPUT
+------
+
+For a successful merge, the output from git-merge-tree is simply one
+line:
+
+ <OID of toplevel tree>
+
+Whereas for a conflicted merge, the output is by default of the form:
+
+ <OID of toplevel tree>
+ <Conflicted file info>
+ <Informational messages>
+
+These are discussed individually below.
+
+[[OIDTLT]]
+OID of toplevel tree
+~~~~~~~~~~~~~~~~~~~~
+
+This is a tree object that represents what would be checked out in the
+working tree at the end of `git merge`. If there were conflicts, then
+files within this tree may have embedded conflict markers. This section
+is always followed by a newline (or NUL if `-z` is passed).
+
+[[CFI]]
+Conflicted file info
+~~~~~~~~~~~~~~~~~~~~
+
+This is a sequence of lines with the format
+
+ <mode> <object> <stage> <filename>
+
+The filename will be quoted as explained for the configuration
+variable `core.quotePath` (see linkgit:git-config[1]). However, if
+the `--name-only` option is passed, the mode, object, and stage will
+be omitted. If `-z` is passed, the "lines" are terminated by a NUL
+character instead of a newline character.
+
+[[IM]]
+Informational messages
+~~~~~~~~~~~~~~~~~~~~~~
+
+This always starts with a blank line (or NUL if `-z` is passed) to
+separate it from the previous sections, and then has free-form
+messages about the merge, such as:
+
+ * "Auto-merging <file>"
+ * "CONFLICT (rename/delete): <oldfile> renamed...but deleted in..."
+ * "Failed to merge submodule <submodule> (<reason>)"
+ * "Warning: cannot merge binary files: <filename>"
+
+Note that these free-form messages will never have a NUL character
+in or between them, even if -z is passed. It is simply a large block
+of text taking up the remainder of the output.
+
+EXIT STATUS
+-----------
+
+For a successful, non-conflicted merge, the exit status is 0. When the
+merge has conflicts, the exit status is 1. If the merge is not able to
+complete (or start) due to some kind of error, the exit status is
+something other than 0 or 1 (and the output is unspecified).
+
+USAGE NOTES
+-----------
+
+This command is intended as low-level plumbing, similar to
+linkgit:git-hash-object[1], linkgit:git-mktree[1],
+linkgit:git-commit-tree[1], linkgit:git-write-tree[1],
+linkgit:git-update-ref[1], and linkgit:git-mktag[1]. Thus, it can be
+used as a part of a series of steps such as:
+
+ NEWTREE=$(git merge-tree --write-tree $BRANCH1 $BRANCH2)
+ test $? -eq 0 || die "There were conflicts..."
+ NEWCOMMIT=$(git commit-tree $NEWTREE -p $BRANCH1 -p $BRANCH2)
+ git update-ref $BRANCH1 $NEWCOMMIT
+
+Note that when the exit status is non-zero, `NEWTREE` in this sequence
+will contain a lot more output than just a tree.
+
+For conflicts, the output includes the same information that you'd get
+with linkgit:git-merge[1]:
+
+ * what would be written to the working tree (the
+ <<OIDTLT,OID of toplevel tree>>)
+ * the higher order stages that would be written to the index (the
+ <<CFI,Conflicted file info>>)
+ * any messages that would have been printed to stdout (the
+ <<IM,Informational messages>>)
+
+MISTAKES TO AVOID
+-----------------
+
+Do NOT look through the resulting toplevel tree to try to find which
+files conflict; parse the <<CFI,Conflicted file info>> section instead.
+Not only would parsing an entire tree be horrendously slow in large
+repositories, there are numerous types of conflicts not representable by
+conflict markers (modify/delete, mode conflict, binary file changed on
+both sides, file/directory conflicts, various rename conflict
+permutations, etc.)
+
+Do NOT interpret an empty <<CFI,Conflicted file info>> list as a clean
+merge; check the exit status. A merge can have conflicts without having
+individual files conflict (there are a few types of directory rename
+conflicts that fall into this category, and others might also be added
+in the future).
+
+Do NOT attempt to guess or make the user guess the conflict types from
+the <<CFI,Conflicted file info>> list. The information there is
+insufficient to do so. For example: Rename/rename(1to2) conflicts (both
+sides renamed the same file differently) will result in three different
+file having higher order stages (but each only has one higher order
+stage), with no way (short of the <<IM,Informational messages>> section)
+to determine which three files are related. File/directory conflicts
+also result in a file with exactly one higher order stage.
+Possibly-involved-in-directory-rename conflicts (when
+"merge.directoryRenames" is unset or set to "conflicts") also result in
+a file with exactly one higher order stage. In all cases, the
+<<IM,Informational messages>> section has the necessary info, though it
+is not designed to be machine parseable.
+
+Do NOT assume that each paths from <<CFI,Conflicted file info>>, and
+the logical conflicts in the <<IM,Informational messages>> have a
+one-to-one mapping, nor that there is a one-to-many mapping, nor a
+many-to-one mapping. Many-to-many mappings exist, meaning that each
+path can have many logical conflict types in a single merge, and each
+logical conflict type can affect many paths.
+
+Do NOT assume all filenames listed in the <<IM,Informational messages>>
+section had conflicts. Messages can be included for files that have no
+conflicts, such as "Auto-merging <file>".
+
+AVOID taking the OIDS from the <<CFI,Conflicted file info>> and
+re-merging them to present the conflicts to the user. This will lose
+information. Instead, look up the version of the file found within the
+<<OIDTLT,OID of toplevel tree>> and show that instead. In particular,
+the latter will have conflict markers annotated with the original
+branch/commit being merged and, if renames were involved, the original
+filename. While you could include the original branch/commit in the
+conflict marker annotations when re-merging, the original filename is
+not available from the <<CFI,Conflicted file info>> and thus you would
+be losing information that might help the user resolve the conflict.
+
+[[DEPMERGE]]
+DEPRECATED DESCRIPTION
+----------------------
+
+Per the <<NEWMERGE,DESCRIPTION>> and unlike the rest of this
+documentation, this section describes the deprecated `--trivial-merge`
+mode.
+
+Other than the optional `--trivial-merge`, this mode accepts no
+options.
+
+This mode reads three tree-ish, and outputs trivial merge results and
+conflicting stages to the standard output in a semi-diff format.
+Since this was designed for higher level scripts to consume and merge
+the results back into the index, it omits entries that match
+<branch1>. The result of this second form is similar to what
+three-way 'git read-tree -m' does, but instead of storing the results
+in the index, the command outputs the entries to the standard output.
+
+This form not only has limited applicability (a trivial merge cannot
+handle content merges of individual files, rename detection, proper
+directory/file conflict handling, etc.), the output format is also
+difficult to work with, and it will generally be less performant than
+the first form even on successful merges (especially if working in
+large repositories).
GIT
---
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 262fb01..080658c 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -16,40 +16,40 @@ SYNOPSIS
DESCRIPTION
-----------
-If <branch> is specified, 'git rebase' will perform an automatic
+If `<branch>` is specified, `git rebase` will perform an automatic
`git switch <branch>` before doing anything else. Otherwise
it remains on the current branch.
-If <upstream> is not specified, the upstream configured in
-branch.<name>.remote and branch.<name>.merge options will be used (see
+If `<upstream>` is not specified, the upstream configured in
+`branch.<name>.remote` and `branch.<name>.merge` options will be used (see
linkgit:git-config[1] for details) and the `--fork-point` option is
assumed. If you are currently not on any branch or if the current
branch does not have a configured upstream, the rebase will abort.
All changes made by commits in the current branch but that are not
-in <upstream> are saved to a temporary area. This is the same set
+in `<upstream>` are saved to a temporary area. This is the same set
of commits that would be shown by `git log <upstream>..HEAD`; or by
`git log 'fork_point'..HEAD`, if `--fork-point` is active (see the
description on `--fork-point` below); or by `git log HEAD`, if the
`--root` option is specified.
-The current branch is reset to <upstream>, or <newbase> if the
---onto option was supplied. This has the exact same effect as
-`git reset --hard <upstream>` (or <newbase>). ORIG_HEAD is set
+The current branch is reset to `<upstream>` or `<newbase>` if the
+`--onto` option was supplied. This has the exact same effect as
+`git reset --hard <upstream>` (or `<newbase>`). `ORIG_HEAD` is set
to point at the tip of the branch before the reset.
The commits that were previously saved into the temporary area are
then reapplied to the current branch, one by one, in order. Note that
-any commits in HEAD which introduce the same textual changes as a commit
-in HEAD..<upstream> are omitted (i.e., a patch already accepted upstream
+any commits in `HEAD` which introduce the same textual changes as a commit
+in `HEAD..<upstream>` are omitted (i.e., a patch already accepted upstream
with a different commit message or timestamp will be skipped).
It is possible that a merge failure will prevent this process from being
completely automatic. You will have to resolve any such merge failure
and run `git rebase --continue`. Another option is to bypass the commit
that caused the merge failure with `git rebase --skip`. To check out the
-original <branch> and remove the .git/rebase-apply working files, use the
-command `git rebase --abort` instead.
+original `<branch>` and remove the `.git/rebase-apply` working files, use
+the command `git rebase --abort` instead.
Assume the following history exists and the current branch is "topic":
@@ -79,7 +79,7 @@ remain the checked-out branch.
If the upstream branch already contains a change you have made (e.g.,
because you mailed a patch which was applied upstream), then that commit
-will be skipped and warnings will be issued (if the `merge` backend is
+will be skipped and warnings will be issued (if the 'merge' backend is
used). For example, running `git rebase master` on the following
history (in which `A'` and `A` introduce the same set of changes, but
have different committer information):
@@ -176,11 +176,11 @@ would result in the removal of commits F and G:
------------
This is useful if F and G were flawed in some way, or should not be
-part of topicA. Note that the argument to --onto and the <upstream>
+part of topicA. Note that the argument to `--onto` and the `<upstream>`
parameter can be any valid commit-ish.
-In case of conflict, 'git rebase' will stop at the first problematic commit
-and leave conflict markers in the tree. You can use 'git diff' to locate
+In case of conflict, `git rebase` will stop at the first problematic commit
+and leave conflict markers in the tree. You can use `git diff` to locate
the markers (<<<<<<) and make edits to resolve the conflict. For each
file you edit, you need to tell Git that the conflict has been resolved,
typically this would be done with
@@ -205,8 +205,8 @@ OPTIONS
-------
--onto <newbase>::
Starting point at which to create the new commits. If the
- --onto option is not specified, the starting point is
- <upstream>. May be any valid commit, and not just an
+ `--onto` option is not specified, the starting point is
+ `<upstream>`. May be any valid commit, and not just an
existing branch name.
+
As a special case, you may use "A\...B" as a shortcut for the
@@ -215,19 +215,19 @@ leave out at most one of A and B, in which case it defaults to HEAD.
--keep-base::
Set the starting point at which to create the new commits to the
- merge base of <upstream> and <branch>. Running
- 'git rebase --keep-base <upstream> <branch>' is equivalent to
+ merge base of `<upstream>` and `<branch>`. Running
+ `git rebase --keep-base <upstream> <branch>` is equivalent to
running
- 'git rebase --onto <upstream>...<branch> <upstream> <branch>'.
+ `git rebase --onto <upstream>...<branch> <upstream> <branch>`.
+
This option is useful in the case where one is developing a feature on
top of an upstream branch. While the feature is being worked on, the
upstream branch may advance and it may not be the best idea to keep
rebasing on top of the upstream but to keep the base commit as-is.
+
-Although both this option and --fork-point find the merge base between
-<upstream> and <branch>, this option uses the merge base as the _starting
-point_ on which new commits will be created, whereas --fork-point uses
+Although both this option and `--fork-point` find the merge base between
+`<upstream>` and `<branch>`, this option uses the merge base as the _starting
+point_ on which new commits will be created, whereas `--fork-point` uses
the merge base to determine the _set of commits_ which will be rebased.
+
See also INCOMPATIBLE OPTIONS below.
@@ -238,23 +238,23 @@ See also INCOMPATIBLE OPTIONS below.
upstream for the current branch.
<branch>::
- Working branch; defaults to HEAD.
+ Working branch; defaults to `HEAD`.
--continue::
Restart the rebasing process after having resolved a merge conflict.
--abort::
Abort the rebase operation and reset HEAD to the original
- branch. If <branch> was provided when the rebase operation was
- started, then HEAD will be reset to <branch>. Otherwise HEAD
+ branch. If `<branch>` was provided when the rebase operation was
+ started, then `HEAD` will be reset to `<branch>`. Otherwise `HEAD`
will be reset to where it was when the rebase operation was
started.
--quit::
- Abort the rebase operation but HEAD is not reset back to the
+ Abort the rebase operation but `HEAD` is not reset back to the
original branch. The index and working tree are also left
unchanged as a result. If a temporary stash entry was created
- using --autostash, it will be saved to the stash list.
+ using `--autostash`, it will be saved to the stash list.
--apply::
Use applying strategies to rebase (calling `git-am`
@@ -269,16 +269,16 @@ See also INCOMPATIBLE OPTIONS below.
empty after rebasing (because they contain a subset of already
upstream changes). With drop (the default), commits that
become empty are dropped. With keep, such commits are kept.
- With ask (implied by --interactive), the rebase will halt when
+ With ask (implied by `--interactive`), the rebase will halt when
an empty commit is applied allowing you to choose whether to
drop it, edit files more, or just commit the empty changes.
- Other options, like --exec, will use the default of drop unless
- -i/--interactive is explicitly specified.
+ Other options, like `--exec`, will use the default of drop unless
+ `-i`/`--interactive` is explicitly specified.
+
-Note that commits which start empty are kept (unless --no-keep-empty
+Note that commits which start empty are kept (unless `--no-keep-empty`
is specified), and commits which are clean cherry-picks (as determined
by `git log --cherry-mark ...`) are detected and dropped as a
-preliminary step (unless --reapply-cherry-picks is passed).
+preliminary step (unless `--reapply-cherry-picks` is passed).
+
See also INCOMPATIBLE OPTIONS below.
@@ -287,7 +287,7 @@ See also INCOMPATIBLE OPTIONS below.
Do not keep commits that start empty before the rebase
(i.e. that do not change anything from its parent) in the
result. The default is to keep commits which start empty,
- since creating such commits requires passing the --allow-empty
+ since creating such commits requires passing the `--allow-empty`
override flag to `git commit`, signifying that a user is very
intentionally creating such a commit and thus wants to keep
it.
@@ -299,7 +299,7 @@ flag exists as a convenient shortcut, such as for cases where external
tools generate many empty commits and you want them all removed.
+
For commits which do not start empty but become empty after rebasing,
-see the --empty flag.
+see the `--empty` flag.
+
See also INCOMPATIBLE OPTIONS below.
@@ -314,7 +314,7 @@ See also INCOMPATIBLE OPTIONS below.
By default (or if `--no-reapply-cherry-picks` is given), these commits
will be automatically dropped. Because this necessitates reading all
upstream commits, this can be expensive in repos with a large number
-of upstream commits that need to be read. When using the `merge`
+of upstream commits that need to be read. When using the 'merge'
backend, warnings will be issued for each dropped commit (unless
`--quiet` is given). Advice will also be issued unless
`advice.skippedCherryPicks` is set to false (see linkgit:git-config[1]).
@@ -348,10 +348,10 @@ See also INCOMPATIBLE OPTIONS below.
Using merging strategies to rebase (default).
+
Note that a rebase merge works by replaying each commit from the working
-branch on top of the <upstream> branch. Because of this, when a merge
+branch on top of the `<upstream>` branch. Because of this, when a merge
conflict happens, the side reported as 'ours' is the so-far rebased
-series, starting with <upstream>, and 'theirs' is the working branch. In
-other words, the sides are swapped.
+series, starting with `<upstream>`, and 'theirs' is the working branch.
+In other words, the sides are swapped.
+
See also INCOMPATIBLE OPTIONS below.
@@ -360,9 +360,9 @@ See also INCOMPATIBLE OPTIONS below.
Use the given merge strategy, instead of the default `ort`.
This implies `--merge`.
+
-Because 'git rebase' replays each commit from the working branch
-on top of the <upstream> branch using the given strategy, using
-the 'ours' strategy simply empties all patches from the <branch>,
+Because `git rebase` replays each commit from the working branch
+on top of the `<upstream>` branch using the given strategy, using
+the `ours` strategy simply empties all patches from the `<branch>`,
which makes little sense.
+
See also INCOMPATIBLE OPTIONS below.
@@ -392,11 +392,11 @@ See also INCOMPATIBLE OPTIONS below.
-q::
--quiet::
- Be quiet. Implies --no-stat.
+ Be quiet. Implies `--no-stat`.
-v::
--verbose::
- Be verbose. Implies --stat.
+ Be verbose. Implies `--stat`.
--stat::
Show a diffstat of what changed upstream since the last rebase. The
@@ -411,13 +411,13 @@ See also INCOMPATIBLE OPTIONS below.
--verify::
Allows the pre-rebase hook to run, which is the default. This option can
- be used to override --no-verify. See also linkgit:githooks[5].
+ be used to override `--no-verify`. See also linkgit:githooks[5].
-C<n>::
- Ensure at least <n> lines of surrounding context match before
+ Ensure at least `<n>` lines of surrounding context match before
and after each change. When fewer lines of surrounding
context exist they all must match. By default no context is
- ever ignored. Implies --apply.
+ ever ignored. Implies `--apply`.
+
See also INCOMPATIBLE OPTIONS below.
@@ -436,21 +436,21 @@ details).
--fork-point::
--no-fork-point::
- Use reflog to find a better common ancestor between <upstream>
- and <branch> when calculating which commits have been
- introduced by <branch>.
+ Use reflog to find a better common ancestor between `<upstream>`
+ and `<branch>` when calculating which commits have been
+ introduced by `<branch>`.
+
-When --fork-point is active, 'fork_point' will be used instead of
-<upstream> to calculate the set of commits to rebase, where
+When `--fork-point` is active, 'fork_point' will be used instead of
+`<upstream>` to calculate the set of commits to rebase, where
'fork_point' is the result of `git merge-base --fork-point <upstream>
<branch>` command (see linkgit:git-merge-base[1]). If 'fork_point'
-ends up being empty, the <upstream> will be used as a fallback.
+ends up being empty, the `<upstream>` will be used as a fallback.
+
-If <upstream> is given on the command line, then the default is
+If `<upstream>` is given on the command line, then the default is
`--no-fork-point`, otherwise the default is `--fork-point`. See also
`rebase.forkpoint` in linkgit:git-config[1].
+
-If your branch was based on <upstream> but <upstream> was rewound and
+If your branch was based on `<upstream>` but `<upstream>` was rewound and
your branch contains commits which were dropped, this option can be used
with `--keep-base` in order to drop those commits from your branch.
+
@@ -458,24 +458,26 @@ See also INCOMPATIBLE OPTIONS below.
--ignore-whitespace::
Ignore whitespace differences when trying to reconcile
-differences. Currently, each backend implements an approximation of
-this behavior:
+ differences. Currently, each backend implements an approximation of
+ this behavior:
+
-apply backend: When applying a patch, ignore changes in whitespace in
-context lines. Unfortunately, this means that if the "old" lines being
-replaced by the patch differ only in whitespace from the existing
-file, you will get a merge conflict instead of a successful patch
-application.
+apply backend;;
+ When applying a patch, ignore changes in whitespace in context
+ lines. Unfortunately, this means that if the "old" lines being
+ replaced by the patch differ only in whitespace from the existing
+ file, you will get a merge conflict instead of a successful patch
+ application.
+
-merge backend: Treat lines with only whitespace changes as unchanged
-when merging. Unfortunately, this means that any patch hunks that were
-intended to modify whitespace and nothing else will be dropped, even
-if the other side had no changes that conflicted.
+merge backend;;
+ Treat lines with only whitespace changes as unchanged when merging.
+ Unfortunately, this means that any patch hunks that were intended
+ to modify whitespace and nothing else will be dropped, even if the
+ other side had no changes that conflicted.
--whitespace=<option>::
- This flag is passed to the 'git apply' program
+ This flag is passed to the `git apply` program
(see linkgit:git-apply[1]) that applies the patch.
- Implies --apply.
+ Implies `--apply`.
+
See also INCOMPATIBLE OPTIONS below.
@@ -537,7 +539,7 @@ See also REBASING MERGES and INCOMPATIBLE OPTIONS below.
-x <cmd>::
--exec <cmd>::
Append "exec <cmd>" after each line creating a commit in the
- final history. <cmd> will be interpreted as one or more shell
+ final history. `<cmd>` will be interpreted as one or more shell
commands. Any command that fails will interrupt the rebase,
with exit code 1.
+
@@ -550,7 +552,7 @@ or by giving more than one `--exec`:
+
git rebase -i --exec "cmd1" --exec "cmd2" --exec ...
+
-If `--autosquash` is used, "exec" lines will not be appended for
+If `--autosquash` is used, `exec` lines will not be appended for
the intermediate commits, and will only appear at the end of each
squash/fixup series.
+
@@ -560,11 +562,12 @@ without an explicit `--interactive`.
See also INCOMPATIBLE OPTIONS below.
--root::
- Rebase all commits reachable from <branch>, instead of
- limiting them with an <upstream>. This allows you to rebase
- the root commit(s) on a branch. When used with --onto, it
- will skip changes already contained in <newbase> (instead of
- <upstream>) whereas without --onto it will operate on every change.
+ Rebase all commits reachable from `<branch>`, instead of
+ limiting them with an `<upstream>`. This allows you to rebase
+ the root commit(s) on a branch. When used with `--onto`, it
+ will skip changes already contained in `<newbase>` (instead of
+ `<upstream>`) whereas without `--onto` it will operate on every
+ change.
+
See also INCOMPATIBLE OPTIONS below.
@@ -609,6 +612,15 @@ provided. Otherwise an explicit `--no-reschedule-failed-exec` at the
start would be overridden by the presence of
`rebase.rescheduleFailedExec=true` configuration.
+--update-refs::
+--no-update-refs::
+ Automatically force-update any branches that point to commits that
+ are being rebased. Any branches that are checked out in a worktree
+ are not updated in this way.
++
+If the configuration variable `rebase.updateRefs` is set, then this option
+can be used to override and disable this setting.
+
INCOMPATIBLE OPTIONS
--------------------
@@ -632,6 +644,7 @@ are incompatible with the following options:
* --empty=
* --reapply-cherry-picks
* --edit-todo
+ * --update-refs
* --root when used in combination with --onto
In addition, the following pairs of options are incompatible:
@@ -643,9 +656,9 @@ In addition, the following pairs of options are incompatible:
BEHAVIORAL DIFFERENCES
-----------------------
-git rebase has two primary backends: apply and merge. (The apply
+`git rebase` has two primary backends: 'apply' and 'merge'. (The 'apply'
backend used to be known as the 'am' backend, but the name led to
-confusion as it looks like a verb instead of a noun. Also, the merge
+confusion as it looks like a verb instead of a noun. Also, the 'merge'
backend used to be known as the interactive backend, but it is now
used for non-interactive cases as well. Both were renamed based on
lower-level functionality that underpinned each.) There are some
@@ -654,19 +667,19 @@ subtle differences in how these two backends behave:
Empty commits
~~~~~~~~~~~~~
-The apply backend unfortunately drops intentionally empty commits, i.e.
+The 'apply' backend unfortunately drops intentionally empty commits, i.e.
commits that started empty, though these are rare in practice. It
also drops commits that become empty and has no option for controlling
this behavior.
-The merge backend keeps intentionally empty commits by default (though
-with -i they are marked as empty in the todo list editor, or they can
-be dropped automatically with --no-keep-empty).
+The 'merge' backend keeps intentionally empty commits by default (though
+with `-i` they are marked as empty in the todo list editor, or they can
+be dropped automatically with `--no-keep-empty`).
Similar to the apply backend, by default the merge backend drops
-commits that become empty unless -i/--interactive is specified (in
+commits that become empty unless `-i`/`--interactive` is specified (in
which case it stops and asks the user what to do). The merge backend
-also has an --empty={drop,keep,ask} option for changing the behavior
+also has an `--empty={drop,keep,ask}` option for changing the behavior
of handling commits that become empty.
Directory rename detection
@@ -674,20 +687,20 @@ Directory rename detection
Due to the lack of accurate tree information (arising from
constructing fake ancestors with the limited information available in
-patches), directory rename detection is disabled in the apply backend.
+patches), directory rename detection is disabled in the 'apply' backend.
Disabled directory rename detection means that if one side of history
renames a directory and the other adds new files to the old directory,
then the new files will be left behind in the old directory without
any warning at the time of rebasing that you may want to move these
files into the new directory.
-Directory rename detection works with the merge backend to provide you
+Directory rename detection works with the 'merge' backend to provide you
warnings in such cases.
Context
~~~~~~~
-The apply backend works by creating a sequence of patches (by calling
+The 'apply' backend works by creating a sequence of patches (by calling
`format-patch` internally), and then applying the patches in sequence
(calling `am` internally). Patches are composed of multiple hunks,
each with line numbers, a context region, and the actual changes. The
@@ -698,11 +711,11 @@ order to apply the changes to the right lines. However, if multiple
areas of the code have the same surrounding lines of context, the
wrong one can be picked. There are real-world cases where this has
caused commits to be reapplied incorrectly with no conflicts reported.
-Setting diff.context to a larger value may prevent such types of
+Setting `diff.context` to a larger value may prevent such types of
problems, but increases the chance of spurious conflicts (since it
will require more lines of matching context to apply).
-The merge backend works with a full copy of each relevant file,
+The 'merge' backend works with a full copy of each relevant file,
insulating it from these types of problems.
Labelling of conflicts markers
@@ -710,30 +723,30 @@ Labelling of conflicts markers
When there are content conflicts, the merge machinery tries to
annotate each side's conflict markers with the commits where the
-content came from. Since the apply backend drops the original
+content came from. Since the 'apply' backend drops the original
information about the rebased commits and their parents (and instead
generates new fake commits based off limited information in the
generated patches), those commits cannot be identified; instead it has
-to fall back to a commit summary. Also, when merge.conflictStyle is
-set to diff3 or zdiff3, the apply backend will use "constructed merge
+to fall back to a commit summary. Also, when `merge.conflictStyle` is
+set to `diff3` or `zdiff3`, the 'apply' backend will use "constructed merge
base" to label the content from the merge base, and thus provide no
information about the merge base commit whatsoever.
-The merge backend works with the full commits on both sides of history
+The 'merge' backend works with the full commits on both sides of history
and thus has no such limitations.
Hooks
~~~~~
-The apply backend has not traditionally called the post-commit hook,
-while the merge backend has. Both have called the post-checkout hook,
-though the merge backend has squelched its output. Further, both
+The 'apply' backend has not traditionally called the post-commit hook,
+while the 'merge' backend has. Both have called the post-checkout hook,
+though the 'merge' backend has squelched its output. Further, both
backends only call the post-checkout hook with the starting point
commit of the rebase, not the intermediate commits nor the final
commit. In each case, the calling of these hooks was by accident of
implementation rather than by design (both backends were originally
implemented as shell scripts and happened to invoke other commands
-like 'git checkout' or 'git commit' that would call the hooks). Both
+like `git checkout` or `git commit` that would call the hooks). Both
backends should have the same behavior, though it is not entirely
clear which, if any, is correct. We will likely make rebase stop
calling either of these hooks in the future.
@@ -741,10 +754,10 @@ calling either of these hooks in the future.
Interruptability
~~~~~~~~~~~~~~~~
-The apply backend has safety problems with an ill-timed interrupt; if
+The 'apply' backend has safety problems with an ill-timed interrupt; if
the user presses Ctrl-C at the wrong time to try to abort the rebase,
the rebase can enter a state where it cannot be aborted with a
-subsequent `git rebase --abort`. The merge backend does not appear to
+subsequent `git rebase --abort`. The 'merge' backend does not appear to
suffer from the same shortcoming. (See
https://lore.kernel.org/git/20200207132152.GC2868@szeder.dev/ for
details.)
@@ -756,8 +769,8 @@ When a conflict occurs while rebasing, rebase stops and asks the user
to resolve. Since the user may need to make notable changes while
resolving conflicts, after conflicts are resolved and the user has run
`git rebase --continue`, the rebase should open an editor and ask the
-user to update the commit message. The merge backend does this, while
-the apply backend blindly applies the original commit message.
+user to update the commit message. The 'merge' backend does this, while
+the 'apply' backend blindly applies the original commit message.
Miscellaneous differences
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -777,23 +790,23 @@ completeness:
them to stderr.
* State directories: The two backends keep their state in different
- directories under .git/
+ directories under `.git/`
include::merge-strategies.txt[]
NOTES
-----
-You should understand the implications of using 'git rebase' on a
+You should understand the implications of using `git rebase` on a
repository that you share. See also RECOVERING FROM UPSTREAM REBASE
below.
-When the git-rebase command is run, it will first execute a "pre-rebase"
-hook if one exists. You can use this hook to do sanity checks and
-reject the rebase if it isn't appropriate. Please see the template
-pre-rebase hook script for an example.
+When the rebase is run, it will first execute a `pre-rebase` hook if one
+exists. You can use this hook to do sanity checks and reject the rebase
+if it isn't appropriate. Please see the template `pre-rebase` hook script
+for an example.
-Upon completion, <branch> will be the current branch.
+Upon completion, `<branch>` will be the current branch.
INTERACTIVE MODE
----------------
@@ -848,7 +861,7 @@ not look at them but at the commit names ("deadbee" and "fa1afe1" in this
example), so do not delete or edit the names.
By replacing the command "pick" with the command "edit", you can tell
-'git rebase' to stop after applying that commit, so that you can edit
+`git rebase` to stop after applying that commit, so that you can edit
the files and/or the commit message, amend the commit, and continue
rebasing.
@@ -876,14 +889,13 @@ commit, the message from the final one is used. You can also use
"fixup -C" to get the same behavior as "fixup -c" except without opening
an editor.
-
-'git rebase' will stop when "pick" has been replaced with "edit" or
+`git rebase` will stop when "pick" has been replaced with "edit" or
when a command fails due to merge errors. When you are done editing
and/or resolving conflicts you can continue with `git rebase --continue`.
For example, if you want to reorder the last 5 commits, such that what
-was HEAD~4 becomes the new HEAD. To achieve that, you would call
-'git rebase' like this:
+was `HEAD~4` becomes the new `HEAD`. To achieve that, you would call
+`git rebase` like this:
----------------------
$ git rebase -i HEAD~5
@@ -903,7 +915,7 @@ like this:
------------------
Suppose you want to rebase the side branch starting at "A" to "Q". Make
-sure that the current HEAD is "B", and call
+sure that the current `HEAD` is "B", and call
-----------------------------
$ git rebase -i -r --onto Q O
@@ -956,23 +968,23 @@ SPLITTING COMMITS
-----------------
In interactive mode, you can mark commits with the action "edit". However,
-this does not necessarily mean that 'git rebase' expects the result of this
+this does not necessarily mean that `git rebase` expects the result of this
edit to be exactly one commit. Indeed, you can undo the commit, or you can
add other commits. This can be used to split a commit into two:
- Start an interactive rebase with `git rebase -i <commit>^`, where
- <commit> is the commit you want to split. In fact, any commit range
+ `<commit>` is the commit you want to split. In fact, any commit range
will do, as long as it contains that commit.
- Mark the commit you want to split with the action "edit".
- When it comes to editing that commit, execute `git reset HEAD^`. The
- effect is that the HEAD is rewound by one, and the index follows suit.
+ effect is that the `HEAD` is rewound by one, and the index follows suit.
However, the working tree stays the same.
- Now add the changes to the index that you want to have in the first
commit. You can use `git add` (possibly interactively) or
- 'git gui' (or both) to do that.
+ `git gui` (or both) to do that.
- Commit the now-current index with whatever commit message is appropriate
now.
@@ -983,7 +995,7 @@ add other commits. This can be used to split a commit into two:
If you are not absolutely sure that the intermediate revisions are
consistent (they compile, pass the testsuite, etc.) you should use
-'git stash' to stash away the not-yet-committed changes
+`git stash` to stash away the not-yet-committed changes
after each commit, test, and amend the commit if fixes are necessary.
@@ -1087,12 +1099,12 @@ NOTE: While an "easy case recovery" sometimes appears to be successful
example, a commit that was removed via `git rebase
--interactive` will be **resurrected**!
-The idea is to manually tell 'git rebase' "where the old 'subsystem'
+The idea is to manually tell `git rebase` "where the old 'subsystem'
ended and your 'topic' began", that is, what the old merge base
between them was. You will have to find a way to name the last commit
of the old 'subsystem', for example:
-* With the 'subsystem' reflog: after 'git fetch', the old tip of
+* With the 'subsystem' reflog: after `git fetch`, the old tip of
'subsystem' is at `subsystem@{1}`. Subsequent fetches will
increase the number. (See linkgit:git-reflog[1].)
diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt
index bb92a4a..8463fe9 100644
--- a/Documentation/git-revert.txt
+++ b/Documentation/git-revert.txt
@@ -117,6 +117,15 @@ effect to your index in a row.
Allow the rerere mechanism to update the index with the
result of auto-conflict resolution if possible.
+--reference::
+ Instead of starting the body of the log message with "This
+ reverts <full object name of the commit being reverted>.",
+ refer to the commit using "--pretty=reference" format
+ (cf. linkgit:git-log[1]). The `revert.reference`
+ configuration variable can be used to enable this option by
+ default.
+
+
SEQUENCER SUBCOMMANDS
---------------------
include::sequencer.txt[]
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 302607a..47a6095 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -885,9 +885,7 @@ for full details.
If set to a colon-separated list of protocols, behave as if
`protocol.allow` is set to `never`, and each of the listed
protocols has `protocol.<name>.allow` set to `always`
- (overriding any existing configuration). In other words, any
- protocol not mentioned will be disallowed (i.e., this is a
- whitelist, not a blacklist). See the description of
+ (overriding any existing configuration). See the description of
`protocol.allow` in linkgit:git-config[1] for more details.
`GIT_PROTOCOL_FROM_USER`::
diff --git a/Documentation/revisions.txt b/Documentation/revisions.txt
index f5f17b6..e3e3501 100644
--- a/Documentation/revisions.txt
+++ b/Documentation/revisions.txt
@@ -96,19 +96,16 @@ some output processing may assume ref names in UTF-8.
before the current one.
'[<branchname>]@\{upstream\}', e.g. 'master@\{upstream\}', '@\{u\}'::
- The suffix '@\{upstream\}' to a branchname (short form '<branchname>@\{u\}')
- refers to the branch that the branch specified by branchname is set to build on
- top of (configured with `branch.<name>.remote` and
- `branch.<name>.merge`). A missing branchname defaults to the
- current one. These suffixes are also accepted when spelled in uppercase, and
- they mean the same thing no matter the case.
+ A branch B may be set up to build on top of a branch X (configured with
+ `branch.<name>.merge`) at a remote R (configured with
+ `branch.<name>.remote`). B@{u} refers to the remote-tracking branch for
+ the branch X taken from remote R, typically found at `refs/remotes/R/X`.
'[<branchname>]@\{push\}', e.g. 'master@\{push\}', '@\{push\}'::
The suffix '@\{push}' reports the branch "where we would push to" if
`git push` were run while `branchname` was checked out (or the current
- `HEAD` if no branchname is specified). Since our push destination is
- in a remote repository, of course, we report the local tracking branch
- that corresponds to that branch (i.e., something in `refs/remotes/`).
+ `HEAD` if no branchname is specified). Like for '@\{upstream\}', we report
+ the remote-tracking branch that corresponds to that branch at the remote.
+
Here's an example to make it more clear:
+
@@ -283,7 +280,7 @@ The '..' (two-dot) Range Notation::
for commits that are reachable from r2 excluding those that are reachable
from r1 by '{caret}r1 r2' and it can be written as 'r1..r2'.
-The '...' (three-dot) Symmetric Difference Notation::
+The '\...' (three-dot) Symmetric Difference Notation::
A similar notation 'r1\...r2' is called symmetric difference
of 'r1' and 'r2' and is defined as
'r1 r2 --not $(git merge-base --all r1 r2)'.
diff --git a/Documentation/technical/bitmap-format.txt b/Documentation/technical/bitmap-format.txt
index 04b3ec2..a85f58f 100644
--- a/Documentation/technical/bitmap-format.txt
+++ b/Documentation/technical/bitmap-format.txt
@@ -25,9 +25,9 @@ An object is uniquely described by its bit position within a bitmap:
is defined as follows:
o1 <= o2 <==> pack(o1) <= pack(o2) /\ offset(o1) <= offset(o2)
-
- The ordering between packs is done according to the MIDX's .rev file.
- Notably, the preferred pack sorts ahead of all other packs.
++
+The ordering between packs is done according to the MIDX's .rev file.
+Notably, the preferred pack sorts ahead of all other packs.
The on-disk representation (described below) of a bitmap is the same regardless
of whether or not that bitmap belongs to a packfile or a MIDX. The only
@@ -39,97 +39,108 @@ MIDXs, both the bit-cache and rev-cache extensions are required.
== On-disk format
- - A header appears at the beginning:
-
- 4-byte signature: {'B', 'I', 'T', 'M'}
-
- 2-byte version number (network byte order)
- The current implementation only supports version 1
- of the bitmap index (the same one as JGit).
-
- 2-byte flags (network byte order)
-
- The following flags are supported:
-
- - BITMAP_OPT_FULL_DAG (0x1) REQUIRED
- This flag must always be present. It implies that the
- bitmap index has been generated for a packfile or
- multi-pack index (MIDX) with full closure (i.e. where
- every single object in the packfile/MIDX can find its
- parent links inside the same packfile/MIDX). This is a
- requirement for the bitmap index format, also present in
- JGit, that greatly reduces the complexity of the
- implementation.
-
- - BITMAP_OPT_HASH_CACHE (0x4)
- If present, the end of the bitmap file contains
- `N` 32-bit name-hash values, one per object in the
- pack/MIDX. The format and meaning of the name-hash is
- described below.
-
- 4-byte entry count (network byte order)
-
- The total count of entries (bitmapped commits) in this bitmap index.
-
- 20-byte checksum
-
- The SHA1 checksum of the pack/MIDX this bitmap index
- belongs to.
-
- - 4 EWAH bitmaps that act as type indexes
-
- Type indexes are serialized after the hash cache in the shape
- of four EWAH bitmaps stored consecutively (see Appendix A for
- the serialization format of an EWAH bitmap).
-
- There is a bitmap for each Git object type, stored in the following
- order:
-
- - Commits
- - Trees
- - Blobs
- - Tags
-
- In each bitmap, the `n`th bit is set to true if the `n`th object
- in the packfile or multi-pack index is of that type.
-
- The obvious consequence is that the OR of all 4 bitmaps will result
- in a full set (all bits set), and the AND of all 4 bitmaps will
- result in an empty bitmap (no bits set).
-
- - N entries with compressed bitmaps, one for each indexed commit
-
- Where `N` is the total amount of entries in this bitmap index.
- Each entry contains the following:
-
- - 4-byte object position (network byte order)
- The position **in the index for the packfile or
- multi-pack index** where the bitmap for this commit is
- found.
-
- - 1-byte XOR-offset
- The xor offset used to compress this bitmap. For an entry
- in position `x`, a XOR offset of `y` means that the actual
- bitmap representing this commit is composed by XORing the
- bitmap for this entry with the bitmap in entry `x-y` (i.e.
- the bitmap `y` entries before this one).
-
- Note that this compression can be recursive. In order to
- XOR this entry with a previous one, the previous entry needs
- to be decompressed first, and so on.
-
- The hard-limit for this offset is 160 (an entry can only be
- xor'ed against one of the 160 entries preceding it). This
- number is always positive, and hence entries are always xor'ed
- with **previous** bitmaps, not bitmaps that will come afterwards
- in the index.
-
- - 1-byte flags for this bitmap
- At the moment the only available flag is `0x1`, which hints
- that this bitmap can be re-used when rebuilding bitmap indexes
- for the repository.
-
- - The compressed bitmap itself, see Appendix A.
+ * A header appears at the beginning:
+
+ 4-byte signature: :: {'B', 'I', 'T', 'M'}
+
+ 2-byte version number (network byte order): ::
+
+ The current implementation only supports version 1
+ of the bitmap index (the same one as JGit).
+
+ 2-byte flags (network byte order): ::
+
+ The following flags are supported:
+
+ ** {empty}
+ BITMAP_OPT_FULL_DAG (0x1) REQUIRED: :::
+
+ This flag must always be present. It implies that the
+ bitmap index has been generated for a packfile or
+ multi-pack index (MIDX) with full closure (i.e. where
+ every single object in the packfile/MIDX can find its
+ parent links inside the same packfile/MIDX). This is a
+ requirement for the bitmap index format, also present in
+ JGit, that greatly reduces the complexity of the
+ implementation.
+
+ ** {empty}
+ BITMAP_OPT_HASH_CACHE (0x4): :::
+
+ If present, the end of the bitmap file contains
+ `N` 32-bit name-hash values, one per object in the
+ pack/MIDX. The format and meaning of the name-hash is
+ described below.
+
+ 4-byte entry count (network byte order): ::
+ The total count of entries (bitmapped commits) in this bitmap index.
+
+ 20-byte checksum: ::
+ The SHA1 checksum of the pack/MIDX this bitmap index
+ belongs to.
+
+ * 4 EWAH bitmaps that act as type indexes
++
+Type indexes are serialized after the hash cache in the shape
+of four EWAH bitmaps stored consecutively (see Appendix A for
+the serialization format of an EWAH bitmap).
++
+There is a bitmap for each Git object type, stored in the following
+order:
++
+ - Commits
+ - Trees
+ - Blobs
+ - Tags
+
++
+In each bitmap, the `n`th bit is set to true if the `n`th object
+in the packfile or multi-pack index is of that type.
++
+The obvious consequence is that the OR of all 4 bitmaps will result
+in a full set (all bits set), and the AND of all 4 bitmaps will
+result in an empty bitmap (no bits set).
+
+ * N entries with compressed bitmaps, one for each indexed commit
++
+Where `N` is the total amount of entries in this bitmap index.
+Each entry contains the following:
+
+ ** {empty}
+ 4-byte object position (network byte order): ::
+ The position **in the index for the packfile or
+ multi-pack index** where the bitmap for this commit is
+ found.
+
+ ** {empty}
+ 1-byte XOR-offset: ::
+ The xor offset used to compress this bitmap. For an entry
+ in position `x`, a XOR offset of `y` means that the actual
+ bitmap representing this commit is composed by XORing the
+ bitmap for this entry with the bitmap in entry `x-y` (i.e.
+ the bitmap `y` entries before this one).
++
+NOTE: This compression can be recursive. In order to
+XOR this entry with a previous one, the previous entry needs
+to be decompressed first, and so on.
++
+The hard-limit for this offset is 160 (an entry can only be
+xor'ed against one of the 160 entries preceding it). This
+number is always positive, and hence entries are always xor'ed
+with **previous** bitmaps, not bitmaps that will come afterwards
+in the index.
+
+ ** {empty}
+ 1-byte flags for this bitmap: ::
+ At the moment the only available flag is `0x1`, which hints
+ that this bitmap can be re-used when rebuilding bitmap indexes
+ for the repository.
+
+ ** The compressed bitmap itself, see Appendix A.
+
+ * {empty}
+ TRAILER: ::
+ Trailing checksum of the preceding contents.
== Appendix A: Serialization format for an EWAH bitmap
@@ -142,8 +153,8 @@ implementation:
- 4-byte number of words of the COMPRESSED bitmap, when stored
- N x 8-byte words, as specified by the previous field
-
- This is the actual content of the compressed bitmap.
++
+This is the actual content of the compressed bitmap.
- 4-byte position of the current RLW for the compressed
bitmap
diff --git a/Documentation/technical/index-format.txt b/Documentation/technical/index-format.txt
index 65da0da..f691c20 100644
--- a/Documentation/technical/index-format.txt
+++ b/Documentation/technical/index-format.txt
@@ -26,8 +26,6 @@ Git index format
Extensions are identified by signature. Optional extensions can
be ignored if Git does not understand them.
- Git currently supports cache tree and resolve undo extensions.
-
4-byte extension signature. If the first byte is 'A'..'Z' the
extension is optional and can be ignored.
diff --git a/Documentation/technical/scalar.txt b/Documentation/technical/scalar.txt
new file mode 100644
index 0000000..08bc09c
--- /dev/null
+++ b/Documentation/technical/scalar.txt
@@ -0,0 +1,127 @@
+Scalar
+======
+
+Scalar is a repository management tool that optimizes Git for use in large
+repositories. It accomplishes this by helping users to take advantage of
+advanced performance features in Git. Unlike most other Git built-in commands,
+Scalar is not executed as a subcommand of 'git'; rather, it is built as a
+separate executable containing its own series of subcommands.
+
+Background
+----------
+
+Scalar was originally designed as an add-on to Git and implemented as a .NET
+Core application. It was created based on the learnings from the VFS for Git
+project (another application aimed at improving the experience of working with
+large repositories). As part of its initial implementation, Scalar relied on
+custom features in the Microsoft fork of Git that have since been integrated
+into core Git:
+
+* partial clone,
+* commit graphs,
+* multi-pack index,
+* sparse checkout (cone mode),
+* scheduled background maintenance,
+* etc
+
+With the requisite Git functionality in place and a desire to bring the benefits
+of Scalar to the larger Git community, the Scalar application itself was ported
+from C# to C and integrated upstream.
+
+Features
+--------
+
+Scalar is comprised of two major pieces of functionality: automatically
+configuring built-in Git performance features and managing repository
+enlistments.
+
+The Git performance features configured by Scalar (see "Background" for
+examples) confer substantial performance benefits to large repositories, but are
+either too experimental to enable for all of Git yet, or only benefit large
+repositories. As new features are introduced, Scalar should be updated
+accordingly to incorporate them. This will prevent the tool from becoming stale
+while also providing a path for more easily bringing features to the appropriate
+users.
+
+Enlistments are how Scalar knows which repositories on a user's system should
+utilize Scalar-configured features. This allows it to update performance
+settings when new ones are added to the tool, as well as centrally manage
+repository maintenance. The enlistment structure - a root directory with a
+`src/` subdirectory containing the cloned repository itself - is designed to
+encourage users to route build outputs outside of the repository to avoid the
+performance-limiting overhead of ignoring those files in Git.
+
+Design
+------
+
+Scalar is implemented in C and interacts with Git via a mix of child process
+invocations of Git and direct usage of `libgit.a`. Internally, it is structured
+much like other built-ins with subcommands (e.g., `git stash`), containing a
+`cmd_<subcommand>()` function for each subcommand, routed through a `cmd_main()`
+function. Most options are unique to each subcommand, with `scalar` respecting
+some "global" `git` options (e.g., `-c` and `-C`).
+
+Because `scalar` is not invoked as a Git subcommand (like `git scalar`), it is
+built and installed as its own executable in the `bin/` directory, alongside
+`git`, `git-gui`, etc.
+
+Roadmap
+-------
+
+NOTE: this section will be removed once the remaining tasks outlined in this
+roadmap are complete.
+
+Scalar is a large enough project that it is being upstreamed incrementally,
+living in `contrib/` until it is feature-complete. So far, the following patch
+series have been accepted:
+
+- `scalar-the-beginning`: The initial patch series which sets up
+ `contrib/scalar/` and populates it with a minimal `scalar` command that
+ demonstrates the fundamental ideas.
+
+- `scalar-c-and-C`: The `scalar` command learns about two options that can be
+ specified before the command, `-c <key>=<value>` and `-C <directory>`.
+
+- `scalar-diagnose`: The `scalar` command is taught the `diagnose` subcommand.
+
+Roughly speaking (and subject to change), the following series are needed to
+"finish" this initial version of Scalar:
+
+- Finish Scalar features: Enable the built-in FSMonitor in Scalar enlistments
+ and implement `scalar help`. At the end of this series, Scalar should be
+ feature-complete from the perspective of a user.
+
+- Generalize features not specific to Scalar: In the spirit of making Scalar
+ configure only what is needed for large repo performance, move common
+ utilities into other parts of Git. Some of this will be internal-only, but one
+ major change will be generalizing `scalar diagnose` for use with any Git
+ repository.
+
+- Move Scalar to toplevel: Move Scalar out of `contrib/` and into the root of
+ `git`, including updates to build and install it with the rest of Git. This
+ change will incorporate Scalar into the Git CI and test framework, as well as
+ expand regression and performance testing to ensure the tool is stable.
+
+Finally, there are two additional patch series that exist in Microsoft's fork of
+Git, but there is no current plan to upstream them. There are some interesting
+ideas there, but the implementation is too specific to Azure Repos and/or VFS
+for Git to be of much help in general.
+
+These still exist mainly because the GVFS protocol is what Azure Repos has
+instead of partial clone, while Git is focused on improving partial clone:
+
+- `scalar-with-gvfs`: The primary purpose of this patch series is to support
+ existing Scalar users whose repositories are hosted in Azure Repos (which does
+ not support Git's partial clones, but supports its predecessor, the GVFS
+ protocol, which is used by Scalar to emulate the partial clone).
+
+ Since the GVFS protocol will never be supported by core Git, this patch series
+ will remain in Microsoft's fork of Git.
+
+- `run-scalar-functional-tests`: The Scalar project developed a quite
+ comprehensive set of integration tests (or, "Functional Tests"). They are the
+ sole remaining part of the original C#-based Scalar project, and this patch
+ adds a GitHub workflow that runs them all.
+
+ Since the tests partially depend on features that are only provided in the
+ `scalar-with-gvfs` patch series, this patch cannot be upstreamed.
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 1d66769..6ec9e34 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.36.GIT
+DEF_VER=v2.37.GIT
LF='
'
diff --git a/Makefile b/Makefile
index 04d0fd1..1624471 100644
--- a/Makefile
+++ b/Makefile
@@ -182,6 +182,8 @@ include shared.mak
#
# Define BLK_SHA256 to use the built-in SHA-256 routines.
#
+# Define NETTLE_SHA256 to use the SHA-256 routines in libnettle.
+#
# Define GCRYPT_SHA256 to use the SHA-256 routines in libgcrypt.
#
# Define OPENSSL_SHA256 to use the SHA-256 routines in OpenSSL.
@@ -309,6 +311,11 @@ include shared.mak
# distributions that want to use their packaged versions of Perl
# modules, instead of the fallbacks shipped with Git.
#
+# Define NO_GITWEB if you do not want to build or install
+# 'gitweb'. Note that defining NO_PERL currently has the same effect
+# on not installing gitweb, but not on whether it's built in the
+# gitweb/ directory.
+#
# Define PYTHON_PATH to the path of your Python binary (often /usr/bin/python
# but /usr/bin/python2.7 or /usr/bin/python3 on some platforms).
#
@@ -544,6 +551,7 @@ gitexecdir = libexec/git-core
mergetoolsdir = $(gitexecdir)/mergetools
sharedir = $(prefix)/share
gitwebdir = $(sharedir)/gitweb
+gitwebstaticdir = $(gitwebdir)/static
perllibdir = $(sharedir)/perl5
localedir = $(sharedir)/locale
template_dir = share/git-core/templates
@@ -562,7 +570,7 @@ localedir_relative = $(patsubst $(prefix)/%,%,$(localedir))
htmldir_relative = $(patsubst $(prefix)/%,%,$(htmldir))
perllibdir_relative = $(patsubst $(prefix)/%,%,$(perllibdir))
-export prefix bindir sharedir sysconfdir gitwebdir perllibdir localedir
+export prefix bindir sharedir sysconfdir perllibdir localedir
# Set our default programs
CC = cc
@@ -1286,7 +1294,7 @@ SANITIZE_ADDRESS =
# For the 'coccicheck' target; setting SPATCH_BATCH_SIZE higher will
# usually result in less CPU usage at the cost of higher peak memory.
# Setting it to 0 will feed all files in a single spatch invocation.
-SPATCH_FLAGS = --all-includes --patch .
+SPATCH_FLAGS = --all-includes
SPATCH_BATCH_SIZE = 1
include config.mak.uname
@@ -1842,6 +1850,10 @@ ifdef OPENSSL_SHA256
EXTLIBS += $(LIB_4_CRYPTO)
BASIC_CFLAGS += -DSHA256_OPENSSL
else
+ifdef NETTLE_SHA256
+ BASIC_CFLAGS += -DSHA256_NETTLE
+ EXTLIBS += -lnettle
+else
ifdef GCRYPT_SHA256
BASIC_CFLAGS += -DSHA256_GCRYPT
EXTLIBS += -lgcrypt
@@ -1850,6 +1862,7 @@ else
BASIC_CFLAGS += -DSHA256_BLK
endif
endif
+endif
ifdef SHA1_MAX_BLOCK_SIZE
LIB_OBJS += compat/sha1-chunked.o
@@ -2089,6 +2102,7 @@ htmldir_relative_SQ = $(subst ','\'',$(htmldir_relative))
prefix_SQ = $(subst ','\'',$(prefix))
perllibdir_relative_SQ = $(subst ','\'',$(perllibdir_relative))
gitwebdir_SQ = $(subst ','\'',$(gitwebdir))
+gitwebstaticdir_SQ = $(subst ','\'',$(gitwebstaticdir))
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
TEST_SHELL_PATH_SQ = $(subst ','\'',$(TEST_SHELL_PATH))
@@ -2417,10 +2431,6 @@ GIT-PERL-HEADER: $(PERL_HEADER_TEMPLATE) GIT-PERL-DEFINES Makefile
perllibdir:
@echo '$(perllibdir_SQ)'
-.PHONY: gitweb
-gitweb:
- $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) all
-
git-instaweb: git-instaweb.sh GIT-SCRIPT-DEFINES
$(QUIET_GEN)$(cmd_munge_script) && \
chmod +x $@+ && \
@@ -3091,6 +3101,9 @@ $(SP_OBJ): %.sp: %.c %.o
sparse: $(SP_OBJ)
EXCEPT_HDRS := $(GENERATED_H) unicode-width.h compat/% xdiff/%
+ifndef NETTLE_SHA256
+ EXCEPT_HDRS += sha256/nettle.h
+endif
ifndef GCRYPT_SHA256
EXCEPT_HDRS += sha256/gcrypt.h
endif
@@ -3123,6 +3136,8 @@ check: $(GENERATED_H)
exit 1; \
fi
+COCCI_TEST_RES = $(wildcard contrib/coccinelle/tests/*.res)
+
%.cocci.patch: %.cocci $(COCCI_SOURCES)
$(QUIET_SPATCH) \
if test $(SPATCH_BATCH_SIZE) = 0; then \
@@ -3131,7 +3146,8 @@ check: $(GENERATED_H)
limit='-n $(SPATCH_BATCH_SIZE)'; \
fi; \
if ! echo $(COCCI_SOURCES) | xargs $$limit \
- $(SPATCH) --sp-file $< $(SPATCH_FLAGS) \
+ $(SPATCH) $(SPATCH_FLAGS) \
+ --sp-file $< --patch . \
>$@+ 2>$@.log; \
then \
cat $@.log; \
@@ -3142,13 +3158,43 @@ check: $(GENERATED_H)
then \
echo ' ' SPATCH result: $@; \
fi
+
+COCCI_TEST_RES_GEN = $(addprefix .build/,$(COCCI_TEST_RES))
+$(COCCI_TEST_RES_GEN): .build/%.res : %.c
+$(COCCI_TEST_RES_GEN): .build/%.res : %.res
+$(COCCI_TEST_RES_GEN): .build/contrib/coccinelle/tests/%.res : contrib/coccinelle/%.cocci
+ $(call mkdir_p_parent_template)
+ $(QUIET_SPATCH_T)$(SPATCH) $(SPATCH_FLAGS) \
+ --very-quiet --no-show-diff \
+ --sp-file $< -o $@ \
+ $(@:.build/%.res=%.c) && \
+ cmp $(@:.build/%=%) $@ || \
+ git -P diff --no-index $(@:.build/%=%) $@ 2>/dev/null; \
+
+.PHONY: coccicheck-test
+coccicheck-test: $(COCCI_TEST_RES_GEN)
+
+coccicheck: coccicheck-test
coccicheck: $(addsuffix .patch,$(filter-out %.pending.cocci,$(wildcard contrib/coccinelle/*.cocci)))
# See contrib/coccinelle/README
+coccicheck-pending: coccicheck-test
coccicheck-pending: $(addsuffix .patch,$(wildcard contrib/coccinelle/*.pending.cocci))
.PHONY: coccicheck coccicheck-pending
+# "Sub"-Makefiles, not really because they can't be run stand-alone,
+# only there to contain directory-specific rules and variables
+## gitweb/Makefile inclusion:
+MAK_DIR_GITWEB = gitweb/
+include gitweb/Makefile
+
+.PHONY: gitweb
+gitweb: $(MAK_DIR_GITWEB_ALL)
+ifndef NO_GITWEB
+all:: gitweb
+endif
+
### Installation rules
ifneq ($(filter /%,$(firstword $(template_dir))),)
@@ -3221,7 +3267,6 @@ ifndef NO_PERL
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perllibdir_SQ)'
(cd perl/build/lib && $(TAR) cf - .) | \
(cd '$(DESTDIR_SQ)$(perllibdir_SQ)' && umask 022 && $(TAR) xof -)
- $(MAKE) -C gitweb install
endif
ifndef NO_TCLTK
$(MAKE) -C gitk-git install
@@ -3276,10 +3321,8 @@ endif
cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; } \
done
-.PHONY: install-gitweb install-doc install-man install-man-perl install-html install-info install-pdf
+.PHONY: install-doc install-man install-man-perl install-html install-info install-pdf
.PHONY: quick-install-doc quick-install-man quick-install-html
-install-gitweb:
- $(MAKE) -C gitweb install
install-doc: install-man-perl
$(MAKE) -C Documentation install
@@ -3403,12 +3446,13 @@ profile-clean:
$(RM) $(addsuffix *.gcno,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
cocciclean:
+ $(RM) -r .build/contrib/coccinelle
$(RM) contrib/coccinelle/*.cocci.patch*
clean: profile-clean coverage-clean cocciclean
$(RM) -r .build
$(RM) po/git.pot po/git-core.pot
- $(RM) *.res
+ $(RM) git.res
$(RM) $(OBJECTS)
$(RM) $(LIB_FILE) $(XDIFF_LIB) $(REFTABLE_LIB) $(REFTABLE_TEST_LIB)
$(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
@@ -3425,7 +3469,6 @@ clean: profile-clean coverage-clean cocciclean
$(MAKE) -C Documentation/ clean
$(RM) Documentation/GIT-EXCLUDED-PROGRAMS
ifndef NO_PERL
- $(MAKE) -C gitweb clean
$(RM) -r perl/build/
endif
$(MAKE) -C templates/ clean
diff --git a/RelNotes b/RelNotes
index 51144b6..d505db6 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.37.0.txt \ No newline at end of file
+Documentation/RelNotes/2.38.0.txt \ No newline at end of file
diff --git a/add-interactive.c b/add-interactive.c
index 6047e8f..22fcd34 100644
--- a/add-interactive.c
+++ b/add-interactive.c
@@ -697,8 +697,16 @@ static int run_update(struct add_i_state *s, const struct pathspec *ps,
for (i = 0; i < files->items.nr; i++) {
const char *name = files->items.items[i].string;
- if (files->selected[i] &&
- add_file_to_index(s->r->index, name, 0) < 0) {
+ struct stat st;
+
+ if (!files->selected[i])
+ continue;
+ if (lstat(name, &st) && is_missing_file_error(errno)) {
+ if (remove_file_from_index(s->r->index, name) < 0) {
+ res = error(_("could not stage '%s'"), name);
+ break;
+ }
+ } else if (add_file_to_index(s->r->index, name, 0) < 0) {
res = error(_("could not stage '%s'"), name);
break;
}
diff --git a/archive-tar.c b/archive-tar.c
index 042feb6..3d77e0f 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -38,11 +38,18 @@ static int write_tar_filter_archive(const struct archiver *ar,
#define USTAR_MAX_MTIME 077777777777ULL
#endif
+static void tar_write_block(const void *buf)
+{
+ write_or_die(1, buf, BLOCKSIZE);
+}
+
+static void (*write_block)(const void *) = tar_write_block;
+
/* writes out the whole block, but only if it is full */
static void write_if_needed(void)
{
if (offset == BLOCKSIZE) {
- write_or_die(1, block, BLOCKSIZE);
+ write_block(block);
offset = 0;
}
}
@@ -66,7 +73,7 @@ static void do_write_blocked(const void *data, unsigned long size)
write_if_needed();
}
while (size >= BLOCKSIZE) {
- write_or_die(1, buf, BLOCKSIZE);
+ write_block(buf);
size -= BLOCKSIZE;
buf += BLOCKSIZE;
}
@@ -101,10 +108,10 @@ static void write_trailer(void)
{
int tail = BLOCKSIZE - offset;
memset(block + offset, 0, tail);
- write_or_die(1, block, BLOCKSIZE);
+ write_block(block);
if (tail < 2 * RECORDSIZE) {
memset(block, 0, offset);
- write_or_die(1, block, BLOCKSIZE);
+ write_block(block);
}
}
@@ -383,8 +390,8 @@ static int tar_filter_config(const char *var, const char *value, void *data)
if (!strcmp(type, "command")) {
if (!value)
return config_error_nonbool(var);
- free(ar->data);
- ar->data = xstrdup(value);
+ free(ar->filter_command);
+ ar->filter_command = xstrdup(value);
return 0;
}
if (!strcmp(type, "remote")) {
@@ -425,17 +432,65 @@ static int write_tar_archive(const struct archiver *ar,
return err;
}
+static git_zstream gzstream;
+static unsigned char outbuf[16384];
+
+static void tgz_deflate(int flush)
+{
+ while (gzstream.avail_in || flush == Z_FINISH) {
+ int status = git_deflate(&gzstream, flush);
+ if (!gzstream.avail_out || status == Z_STREAM_END) {
+ write_or_die(1, outbuf, gzstream.next_out - outbuf);
+ gzstream.next_out = outbuf;
+ gzstream.avail_out = sizeof(outbuf);
+ if (status == Z_STREAM_END)
+ break;
+ }
+ if (status != Z_OK && status != Z_BUF_ERROR)
+ die(_("deflate error (%d)"), status);
+ }
+}
+
+static void tgz_write_block(const void *data)
+{
+ gzstream.next_in = (void *)data;
+ gzstream.avail_in = BLOCKSIZE;
+ tgz_deflate(Z_NO_FLUSH);
+}
+
+static const char internal_gzip_command[] = "git archive gzip";
+
static int write_tar_filter_archive(const struct archiver *ar,
struct archiver_args *args)
{
+#if ZLIB_VERNUM >= 0x1221
+ struct gz_header_s gzhead = { .os = 3 }; /* Unix, for reproducibility */
+#endif
struct strbuf cmd = STRBUF_INIT;
struct child_process filter = CHILD_PROCESS_INIT;
int r;
- if (!ar->data)
+ if (!ar->filter_command)
BUG("tar-filter archiver called with no filter defined");
- strbuf_addstr(&cmd, ar->data);
+ if (!strcmp(ar->filter_command, internal_gzip_command)) {
+ write_block = tgz_write_block;
+ git_deflate_init_gzip(&gzstream, args->compression_level);
+#if ZLIB_VERNUM >= 0x1221
+ if (deflateSetHeader(&gzstream.z, &gzhead) != Z_OK)
+ BUG("deflateSetHeader() called too late");
+#endif
+ gzstream.next_out = outbuf;
+ gzstream.avail_out = sizeof(outbuf);
+
+ r = write_tar_archive(ar, args);
+
+ tgz_deflate(Z_FINISH);
+ git_deflate_end(&gzstream);
+ return r;
+ }
+
+ strbuf_addstr(&cmd, ar->filter_command);
if (args->compression_level >= 0)
strbuf_addf(&cmd, " -%d", args->compression_level);
@@ -471,14 +526,14 @@ void init_tar_archiver(void)
int i;
register_archiver(&tar_archiver);
- tar_filter_config("tar.tgz.command", "gzip -cn", NULL);
+ tar_filter_config("tar.tgz.command", internal_gzip_command, NULL);
tar_filter_config("tar.tgz.remote", "true", NULL);
- tar_filter_config("tar.tar.gz.command", "gzip -cn", NULL);
+ tar_filter_config("tar.tar.gz.command", internal_gzip_command, NULL);
tar_filter_config("tar.tar.gz.remote", "true", NULL);
git_config(git_tar_config, NULL);
for (i = 0; i < nr_tar_filters; i++) {
/* omit any filters that never had a command configured */
- if (tar_filters[i]->data)
+ if (tar_filters[i]->filter_command)
register_archiver(tar_filters[i]);
}
}
diff --git a/archive.h b/archive.h
index 49fab71..08bed3e 100644
--- a/archive.h
+++ b/archive.h
@@ -43,7 +43,7 @@ struct archiver {
const char *name;
int (*write_archive)(const struct archiver *, struct archiver_args *);
unsigned flags;
- void *data;
+ char *filter_command;
};
void register_archiver(struct archiver *);
diff --git a/bloom.c b/bloom.c
index 5e29703..816f063 100644
--- a/bloom.c
+++ b/bloom.c
@@ -30,10 +30,9 @@ static inline unsigned char get_bitmask(uint32_t pos)
static int load_bloom_filter_from_graph(struct commit_graph *g,
struct bloom_filter *filter,
- struct commit *c)
+ uint32_t graph_pos)
{
uint32_t lex_pos, start_index, end_index;
- uint32_t graph_pos = commit_graph_position(c);
while (graph_pos < g->num_commits_in_base)
g = g->base_graph;
@@ -203,9 +202,10 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
filter = bloom_filter_slab_at(&bloom_filters, c);
if (!filter->data) {
- load_commit_graph_info(r, c);
- if (commit_graph_position(c) != COMMIT_NOT_FROM_GRAPH)
- load_bloom_filter_from_graph(r->objects->commit_graph, filter, c);
+ uint32_t graph_pos;
+ if (repo_find_commit_pos_in_graph(r, c, &graph_pos))
+ load_bloom_filter_from_graph(r->objects->commit_graph,
+ filter, graph_pos);
}
if (filter->data && filter->len)
diff --git a/branch.c b/branch.c
index 4c8523c..d182756 100644
--- a/branch.c
+++ b/branch.c
@@ -10,6 +10,7 @@
#include "worktree.h"
#include "submodule-config.h"
#include "run-command.h"
+#include "strmap.h"
struct tracking {
struct refspec_item spec;
@@ -369,6 +370,83 @@ int validate_branchname(const char *name, struct strbuf *ref)
return ref_exists(ref->buf);
}
+static int initialized_checked_out_branches;
+static struct strmap current_checked_out_branches = STRMAP_INIT;
+
+static void prepare_checked_out_branches(void)
+{
+ int i = 0;
+ struct worktree **worktrees;
+
+ if (initialized_checked_out_branches)
+ return;
+ initialized_checked_out_branches = 1;
+
+ worktrees = get_worktrees();
+
+ while (worktrees[i]) {
+ char *old;
+ struct wt_status_state state = { 0 };
+ struct worktree *wt = worktrees[i++];
+ struct string_list update_refs = STRING_LIST_INIT_DUP;
+
+ if (wt->is_bare)
+ continue;
+
+ if (wt->head_ref) {
+ old = strmap_put(&current_checked_out_branches,
+ wt->head_ref,
+ xstrdup(wt->path));
+ free(old);
+ }
+
+ if (wt_status_check_rebase(wt, &state) &&
+ (state.rebase_in_progress || state.rebase_interactive_in_progress) &&
+ state.branch) {
+ struct strbuf ref = STRBUF_INIT;
+ strbuf_addf(&ref, "refs/heads/%s", state.branch);
+ old = strmap_put(&current_checked_out_branches,
+ ref.buf,
+ xstrdup(wt->path));
+ free(old);
+ strbuf_release(&ref);
+ }
+ wt_status_state_free_buffers(&state);
+
+ if (wt_status_check_bisect(wt, &state) &&
+ state.branch) {
+ struct strbuf ref = STRBUF_INIT;
+ strbuf_addf(&ref, "refs/heads/%s", state.branch);
+ old = strmap_put(&current_checked_out_branches,
+ ref.buf,
+ xstrdup(wt->path));
+ free(old);
+ strbuf_release(&ref);
+ }
+ wt_status_state_free_buffers(&state);
+
+ if (!sequencer_get_update_refs_state(get_worktree_git_dir(wt),
+ &update_refs)) {
+ struct string_list_item *item;
+ for_each_string_list_item(item, &update_refs) {
+ old = strmap_put(&current_checked_out_branches,
+ item->string,
+ xstrdup(wt->path));
+ free(old);
+ }
+ string_list_clear(&update_refs, 1);
+ }
+ }
+
+ free_worktrees(worktrees);
+}
+
+const char *branch_checked_out(const char *refname)
+{
+ prepare_checked_out_branches();
+ return strmap_get(&current_checked_out_branches, refname);
+}
+
/*
* Check if a branch 'name' can be created as a new branch; die otherwise.
* 'force' can be used when it is OK for the named branch already exists.
@@ -377,9 +455,7 @@ int validate_branchname(const char *name, struct strbuf *ref)
*/
int validate_new_branchname(const char *name, struct strbuf *ref, int force)
{
- struct worktree **worktrees;
- const struct worktree *wt;
-
+ const char *path;
if (!validate_branchname(name, ref))
return 0;
@@ -387,13 +463,10 @@ int validate_new_branchname(const char *name, struct strbuf *ref, int force)
die(_("a branch named '%s' already exists"),
ref->buf + strlen("refs/heads/"));
- worktrees = get_worktrees();
- wt = find_shared_symref(worktrees, "HEAD", ref->buf);
- if (wt && !wt->is_bare)
+ if ((path = branch_checked_out(ref->buf)))
die(_("cannot force update the branch '%s' "
"checked out at '%s'"),
- ref->buf + strlen("refs/heads/"), wt->path);
- free_worktrees(worktrees);
+ ref->buf + strlen("refs/heads/"), path);
return 1;
}
diff --git a/branch.h b/branch.h
index 560b6b9..ef56103 100644
--- a/branch.h
+++ b/branch.h
@@ -101,6 +101,13 @@ void create_branches_recursively(struct repository *r, const char *name,
const char *tracking_name, int force,
int reflog, int quiet, enum branch_track track,
int dry_run);
+
+/*
+ * If the branch at 'refname' is currently checked out in a worktree,
+ * then return the path to that worktree.
+ */
+const char *branch_checked_out(const char *refname);
+
/*
* Check if 'name' can be a valid name for a branch; die otherwise.
* Return 1 if the named branch already exists; return 0 otherwise.
diff --git a/builtin/branch.c b/builtin/branch.c
index 5d00d0b..55cd9a6 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -204,7 +204,6 @@ static void delete_branch_config(const char *branchname)
static int delete_branches(int argc, const char **argv, int force, int kinds,
int quiet)
{
- struct worktree **worktrees;
struct commit *head_rev = NULL;
struct object_id oid;
char *name = NULL;
@@ -242,8 +241,6 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
die(_("Couldn't look up commit object for HEAD"));
}
- worktrees = get_worktrees();
-
for (i = 0; i < argc; i++, strbuf_reset(&bname)) {
char *target = NULL;
int flags = 0;
@@ -253,12 +250,11 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
name = mkpathdup(fmt, bname.buf);
if (kinds == FILTER_REFS_BRANCHES) {
- const struct worktree *wt =
- find_shared_symref(worktrees, "HEAD", name);
- if (wt) {
+ const char *path;
+ if ((path = branch_checked_out(name))) {
error(_("Cannot delete branch '%s' "
"checked out at '%s'"),
- bname.buf, wt->path);
+ bname.buf, path);
ret = 1;
continue;
}
@@ -315,7 +311,6 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
free(name);
strbuf_release(&bname);
- free_worktrees(worktrees);
return ret;
}
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 50cf389..f42782e 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -71,6 +71,7 @@ static int stream_blob(const struct object_id *oid)
static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
int unknown_type)
{
+ int ret;
struct object_id oid;
enum object_type type;
char *buf;
@@ -106,7 +107,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
if (sb.len) {
printf("%s\n", sb.buf);
strbuf_release(&sb);
- return 0;
+ ret = 0;
+ goto cleanup;
}
break;
@@ -115,7 +117,8 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
die("git cat-file: could not get object info");
printf("%"PRIuMAX"\n", (uintmax_t)size);
- return 0;
+ ret = 0;
+ goto cleanup;
case 'e':
return !has_object_file(&oid);
@@ -123,8 +126,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
case 'w':
if (filter_object(path, obj_context.mode,
- &oid, &buf, &size))
- return -1;
+ &oid, &buf, &size)) {
+ ret = -1;
+ goto cleanup;
+ }
break;
case 'c':
@@ -143,11 +148,14 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
const char *ls_args[3] = { NULL };
ls_args[0] = "ls-tree";
ls_args[1] = obj_name;
- return cmd_ls_tree(2, ls_args, NULL);
+ ret = cmd_ls_tree(2, ls_args, NULL);
+ goto cleanup;
}
- if (type == OBJ_BLOB)
- return stream_blob(&oid);
+ if (type == OBJ_BLOB) {
+ ret = stream_blob(&oid);
+ goto cleanup;
+ }
buf = read_object_file(&oid, &type, &size);
if (!buf)
die("Cannot read object %s", obj_name);
@@ -172,8 +180,10 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
} else
oidcpy(&blob_oid, &oid);
- if (oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB)
- return stream_blob(&blob_oid);
+ if (oid_object_info(the_repository, &blob_oid, NULL) == OBJ_BLOB) {
+ ret = stream_blob(&blob_oid);
+ goto cleanup;
+ }
/*
* we attempted to dereference a tag to a blob
* and failed; there may be new dereference
@@ -193,9 +203,11 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
die("git cat-file %s: bad file", obj_name);
write_or_die(1, buf, size);
+ ret = 0;
+cleanup:
free(buf);
free(obj_context.path);
- return 0;
+ return ret;
}
struct expand_data {
@@ -655,6 +667,7 @@ static void batch_objects_command(struct batch_options *opt,
free_cmds(queued_cmd, &nr);
}
+ free_cmds(queued_cmd, &nr);
free(queued_cmd);
strbuf_release(&input);
}
diff --git a/builtin/check-ref-format.c b/builtin/check-ref-format.c
index bc67d3f..fd0e5f8 100644
--- a/builtin/check-ref-format.c
+++ b/builtin/check-ref-format.c
@@ -57,6 +57,8 @@ int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
int normalize = 0;
int flags = 0;
const char *refname;
+ char *to_free = NULL;
+ int ret = 1;
if (argc == 2 && !strcmp(argv[1], "-h"))
usage(builtin_check_ref_format_usage);
@@ -81,11 +83,14 @@ int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
refname = argv[i];
if (normalize)
- refname = collapse_slashes(refname);
+ refname = to_free = collapse_slashes(refname);
if (check_refname_format(refname, flags))
- return 1;
+ goto cleanup;
if (normalize)
printf("%s\n", refname);
- return 0;
+ ret = 0;
+cleanup:
+ free(to_free);
+ return ret;
}
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 2eefda8..29c74f8 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -417,7 +417,7 @@ static int checkout_worktree(const struct checkout_opts *opts,
mem_pool_discard(&ce_mem_pool, should_validate_cache_entries());
remove_marked_cache_entries(&the_index, 1);
remove_scheduled_dirs();
- errs |= finish_delayed_checkout(&state, &nr_checkouts, opts->show_progress);
+ errs |= finish_delayed_checkout(&state, opts->show_progress);
if (opts->count_checkout_paths) {
if (nr_unmerged)
@@ -710,6 +710,26 @@ static void setup_branch_path(struct branch_info *branch)
branch->path = strbuf_detach(&buf, NULL);
}
+static void init_topts(struct unpack_trees_options *topts, int merge,
+ int show_progress, int overwrite_ignore,
+ struct commit *old_commit)
+{
+ memset(topts, 0, sizeof(*topts));
+ topts->head_idx = -1;
+ topts->src_index = &the_index;
+ topts->dst_index = &the_index;
+
+ setup_unpack_trees_porcelain(topts, "checkout");
+
+ topts->initial_checkout = is_cache_unborn();
+ topts->update = 1;
+ topts->merge = 1;
+ topts->quiet = merge && old_commit;
+ topts->verbose_update = show_progress;
+ topts->fn = twoway_merge;
+ topts->preserve_ignored = !overwrite_ignore;
+}
+
static int merge_working_tree(const struct checkout_opts *opts,
struct branch_info *old_branch_info,
struct branch_info *new_branch_info,
@@ -740,13 +760,6 @@ static int merge_working_tree(const struct checkout_opts *opts,
struct unpack_trees_options topts;
const struct object_id *old_commit_oid;
- memset(&topts, 0, sizeof(topts));
- topts.head_idx = -1;
- topts.src_index = &the_index;
- topts.dst_index = &the_index;
-
- setup_unpack_trees_porcelain(&topts, "checkout");
-
refresh_cache(REFRESH_QUIET);
if (unmerged_cache()) {
@@ -755,17 +768,12 @@ static int merge_working_tree(const struct checkout_opts *opts,
}
/* 2-way merge to the new branch */
- topts.initial_checkout = is_cache_unborn();
- topts.update = 1;
- topts.merge = 1;
- topts.quiet = opts->merge && old_branch_info->commit;
- topts.verbose_update = opts->show_progress;
- topts.fn = twoway_merge;
+ init_topts(&topts, opts->merge, opts->show_progress,
+ opts->overwrite_ignore, old_branch_info->commit);
init_checkout_metadata(&topts.meta, new_branch_info->refname,
new_branch_info->commit ?
&new_branch_info->commit->object.oid :
&new_branch_info->oid, NULL);
- topts.preserve_ignored = !opts->overwrite_ignore;
old_commit_oid = old_branch_info->commit ?
&old_branch_info->commit->object.oid :
diff --git a/builtin/clone.c b/builtin/clone.c
index 89a91b0..c4ff464 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -494,6 +494,7 @@ static struct ref *wanted_peer_refs(const struct ref *refs,
/* if --branch=tag, pull the requested tag explicitly */
get_fetch_map(remote_head, tag_refspec, &tail, 0);
}
+ free_refs(remote_head);
} else {
int i;
for (i = 0; i < refspec->nr; i++)
@@ -606,7 +607,7 @@ static void update_remote_refs(const struct ref *refs,
}
static void update_head(const struct ref *our, const struct ref *remote,
- const char *msg)
+ const char *unborn, const char *msg)
{
const char *head;
if (our && skip_prefix(our->name, "refs/heads/", &head)) {
@@ -632,6 +633,15 @@ static void update_head(const struct ref *our, const struct ref *remote,
*/
update_ref(msg, "HEAD", &remote->old_oid, NULL, REF_NO_DEREF,
UPDATE_REFS_DIE_ON_ERR);
+ } else if (unborn && skip_prefix(unborn, "refs/heads/", &head)) {
+ /*
+ * Unborn head from remote; same as "our" case above except
+ * that we have no ref to update.
+ */
+ if (create_symref("HEAD", unborn, NULL) < 0)
+ die(_("unable to update HEAD"));
+ if (!option_bare)
+ install_branch_config(0, head, remote_name, unborn);
}
}
@@ -672,7 +682,7 @@ static int checkout(int submodule_progress, int filter_submodules)
head = resolve_refdup("HEAD", RESOLVE_REF_READING, &oid, NULL);
if (!head) {
warning(_("remote HEAD refers to nonexistent ref, "
- "unable to checkout.\n"));
+ "unable to checkout"));
return 0;
}
if (!strcmp(head, "HEAD")) {
@@ -876,6 +886,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
const struct ref *refs, *remote_head;
struct ref *remote_head_points_at = NULL;
const struct ref *our_head_points_at;
+ char *unborn_head = NULL;
struct ref *mapped_refs = NULL;
const struct ref *ref;
struct strbuf key = STRBUF_INIT;
@@ -1266,51 +1277,49 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
if (transport_fetch_refs(transport, mapped_refs))
die(_("remote transport reported error"));
}
-
- remote_head = find_ref_by_name(refs, "HEAD");
- remote_head_points_at =
- guess_remote_head(remote_head, mapped_refs, 0);
-
- if (option_branch) {
- our_head_points_at =
- find_remote_branch(mapped_refs, option_branch);
-
- if (!our_head_points_at)
- die(_("Remote branch %s not found in upstream %s"),
- option_branch, remote_name);
- }
- else
- our_head_points_at = remote_head_points_at;
}
- else {
- const char *branch;
- const char *ref;
- char *ref_free = NULL;
- if (option_branch)
- die(_("Remote branch %s not found in upstream %s"),
- option_branch, remote_name);
+ remote_head = find_ref_by_name(refs, "HEAD");
+ remote_head_points_at = guess_remote_head(remote_head, mapped_refs, 0);
- warning(_("You appear to have cloned an empty repository."));
+ if (option_branch) {
+ our_head_points_at = find_remote_branch(mapped_refs, option_branch);
+ if (!our_head_points_at)
+ die(_("Remote branch %s not found in upstream %s"),
+ option_branch, remote_name);
+ } else if (remote_head_points_at) {
+ our_head_points_at = remote_head_points_at;
+ } else if (remote_head) {
our_head_points_at = NULL;
- remote_head_points_at = NULL;
- remote_head = NULL;
- option_no_checkout = 1;
+ } else {
+ const char *branch;
+
+ if (!mapped_refs) {
+ warning(_("You appear to have cloned an empty repository."));
+ option_no_checkout = 1;
+ }
if (transport_ls_refs_options.unborn_head_target &&
skip_prefix(transport_ls_refs_options.unborn_head_target,
"refs/heads/", &branch)) {
- ref = transport_ls_refs_options.unborn_head_target;
- create_symref("HEAD", ref, reflog_msg.buf);
+ unborn_head = xstrdup(transport_ls_refs_options.unborn_head_target);
} else {
branch = git_default_branch_name(0);
- ref_free = xstrfmt("refs/heads/%s", branch);
- ref = ref_free;
+ unborn_head = xstrfmt("refs/heads/%s", branch);
}
- if (!option_bare)
- install_branch_config(0, branch, remote_name, ref);
- free(ref_free);
+ /*
+ * We may have selected a local default branch name "foo",
+ * and even though the remote's HEAD does not point there,
+ * it may still have a "foo" branch. If so, set it up so
+ * that we can follow the usual checkout code later.
+ *
+ * Note that for an empty repo we'll already have set
+ * option_no_checkout above, which would work against us here.
+ * But for an empty repo, find_remote_branch() can never find
+ * a match.
+ */
+ our_head_points_at = find_remote_branch(mapped_refs, branch);
}
write_refspec_config(src_ref_prefix, our_head_points_at,
@@ -1330,7 +1339,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
branch_top.buf, reflog_msg.buf, transport,
!is_local);
- update_head(our_head_points_at, remote_head, reflog_msg.buf);
+ update_head(our_head_points_at, remote_head, unborn_head, reflog_msg.buf);
/*
* We want to show progress for recursive submodule clones iff
@@ -1357,6 +1366,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
strbuf_release(&key);
free_refs(mapped_refs);
free_refs(remote_head_points_at);
+ free(unborn_head);
free(dir);
free(path);
UNLEAK(repo);
diff --git a/builtin/diff-files.c b/builtin/diff-files.c
index 2bfaf9b..92cf6e1 100644
--- a/builtin/diff-files.c
+++ b/builtin/diff-files.c
@@ -80,9 +80,9 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)
result = -1;
goto cleanup;
}
-cleanup:
result = run_diff_files(&rev, options);
result = diff_result_code(&rev.diffopt, result);
+cleanup:
release_revisions(&rev);
return result;
}
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index 28d3193..14113cf 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -3465,7 +3465,7 @@ static void git_pack_config(void)
pack_idx_opts.version = indexversion_value;
if (pack_idx_opts.version > 2)
git_die_config("pack.indexversion",
- "bad pack.indexversion=%"PRIu32, pack_idx_opts.version);
+ "bad pack.indexVersion=%"PRIu32, pack_idx_opts.version);
}
if (!git_config_get_ulong("pack.packsizelimit", &packsizelimit_value))
max_packsize = packsizelimit_value;
diff --git a/builtin/fetch.c b/builtin/fetch.c
index ac29c2b..fc5cecb 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -881,11 +881,9 @@ static void format_display(struct strbuf *display, char code,
static int update_local_ref(struct ref *ref,
struct ref_transaction *transaction,
const char *remote, const struct ref *remote_ref,
- struct strbuf *display, int summary_width,
- struct worktree **worktrees)
+ struct strbuf *display, int summary_width)
{
struct commit *current = NULL, *updated;
- const struct worktree *wt;
const char *pretty_ref = prettify_refname(ref->name);
int fast_forward = 0;
@@ -900,16 +898,14 @@ static int update_local_ref(struct ref *ref,
}
if (!update_head_ok &&
- (wt = find_shared_symref(worktrees, "HEAD", ref->name)) &&
- !wt->is_bare && !is_null_oid(&ref->old_oid)) {
+ !is_null_oid(&ref->old_oid) &&
+ branch_checked_out(ref->name)) {
/*
* If this is the head, and it's not okay to update
* the head, and the old value of the head isn't empty...
*/
format_display(display, '!', _("[rejected]"),
- wt->is_current ?
- _("can't fetch in current branch") :
- _("checked out in another worktree"),
+ _("can't fetch into checked-out branch"),
remote, pretty_ref, summary_width);
return 1;
}
@@ -1110,10 +1106,10 @@ N_("it took %.2f seconds to check forced updates; you can use\n"
static int store_updated_refs(const char *raw_url, const char *remote_name,
int connectivity_checked,
struct ref_transaction *transaction, struct ref *ref_map,
- struct fetch_head *fetch_head, struct worktree **worktrees)
+ struct fetch_head *fetch_head)
{
int url_len, i, rc = 0;
- struct strbuf note = STRBUF_INIT, err = STRBUF_INIT;
+ struct strbuf note = STRBUF_INIT;
const char *what, *kind;
struct ref *rm;
char *url;
@@ -1240,8 +1236,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
strbuf_reset(&note);
if (ref) {
rc |= update_local_ref(ref, transaction, what,
- rm, &note, summary_width,
- worktrees);
+ rm, &note, summary_width);
free(ref);
} else if (write_fetch_head || dry_run) {
/*
@@ -1281,7 +1276,6 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
abort:
strbuf_release(&note);
- strbuf_release(&err);
free(url);
return rc;
}
@@ -1332,8 +1326,7 @@ static int check_exist_and_connected(struct ref *ref_map)
static int fetch_and_consume_refs(struct transport *transport,
struct ref_transaction *transaction,
struct ref *ref_map,
- struct fetch_head *fetch_head,
- struct worktree **worktrees)
+ struct fetch_head *fetch_head)
{
int connectivity_checked = 1;
int ret;
@@ -1356,7 +1349,7 @@ static int fetch_and_consume_refs(struct transport *transport,
trace2_region_enter("fetch", "consume_refs", the_repository);
ret = store_updated_refs(transport->url, transport->remote->name,
connectivity_checked, transaction, ref_map,
- fetch_head, worktrees);
+ fetch_head);
trace2_region_leave("fetch", "consume_refs", the_repository);
out:
@@ -1434,19 +1427,16 @@ cleanup:
return result;
}
-static void check_not_current_branch(struct ref *ref_map,
- struct worktree **worktrees)
+static void check_not_current_branch(struct ref *ref_map)
{
- const struct worktree *wt;
+ const char *path;
for (; ref_map; ref_map = ref_map->next)
if (ref_map->peer_ref &&
starts_with(ref_map->peer_ref->name, "refs/heads/") &&
- (wt = find_shared_symref(worktrees, "HEAD",
- ref_map->peer_ref->name)) &&
- !wt->is_bare)
+ (path = branch_checked_out(ref_map->peer_ref->name)))
die(_("refusing to fetch into branch '%s' "
"checked out at '%s'"),
- ref_map->peer_ref->name, wt->path);
+ ref_map->peer_ref->name, path);
}
static int truncate_fetch_head(void)
@@ -1549,8 +1539,7 @@ static struct transport *prepare_transport(struct remote *remote, int deepen)
static int backfill_tags(struct transport *transport,
struct ref_transaction *transaction,
struct ref *ref_map,
- struct fetch_head *fetch_head,
- struct worktree **worktrees)
+ struct fetch_head *fetch_head)
{
int retcode, cannot_reuse;
@@ -1571,7 +1560,7 @@ static int backfill_tags(struct transport *transport,
transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
transport_set_option(transport, TRANS_OPT_DEPTH, "0");
transport_set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, NULL);
- retcode = fetch_and_consume_refs(transport, transaction, ref_map, fetch_head, worktrees);
+ retcode = fetch_and_consume_refs(transport, transaction, ref_map, fetch_head);
if (gsecondary) {
transport_disconnect(gsecondary);
@@ -1592,7 +1581,6 @@ static int do_fetch(struct transport *transport,
struct transport_ls_refs_options transport_ls_refs_options =
TRANSPORT_LS_REFS_OPTIONS_INIT;
int must_list_refs = 1;
- struct worktree **worktrees = get_worktrees();
struct fetch_head fetch_head = { 0 };
struct strbuf err = STRBUF_INIT;
@@ -1650,7 +1638,7 @@ static int do_fetch(struct transport *transport,
ref_map = get_ref_map(transport->remote, remote_refs, rs,
tags, &autotags);
if (!update_head_ok)
- check_not_current_branch(ref_map, worktrees);
+ check_not_current_branch(ref_map);
retcode = open_fetch_head(&fetch_head);
if (retcode)
@@ -1683,7 +1671,7 @@ static int do_fetch(struct transport *transport,
retcode = 1;
}
- if (fetch_and_consume_refs(transport, transaction, ref_map, &fetch_head, worktrees)) {
+ if (fetch_and_consume_refs(transport, transaction, ref_map, &fetch_head)) {
retcode = 1;
goto cleanup;
}
@@ -1706,7 +1694,7 @@ static int do_fetch(struct transport *transport,
* the transaction and don't commit anything.
*/
if (backfill_tags(transport, transaction, tags_ref_map,
- &fetch_head, worktrees))
+ &fetch_head))
retcode = 1;
}
@@ -1791,7 +1779,6 @@ cleanup:
close_fetch_head(&fetch_head);
strbuf_release(&err);
free_refs(ref_map);
- free_worktrees(worktrees);
return retcode;
}
diff --git a/builtin/fsck.c b/builtin/fsck.c
index 9e54892..6c73092 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -19,6 +19,7 @@
#include "decorate.h"
#include "packfile.h"
#include "object-store.h"
+#include "resolve-undo.h"
#include "run-command.h"
#include "worktree.h"
@@ -757,6 +758,43 @@ static int fsck_cache_tree(struct cache_tree *it)
return err;
}
+static int fsck_resolve_undo(struct index_state *istate)
+{
+ struct string_list_item *item;
+ struct string_list *resolve_undo = istate->resolve_undo;
+
+ if (!resolve_undo)
+ return 0;
+
+ for_each_string_list_item(item, resolve_undo) {
+ const char *path = item->string;
+ struct resolve_undo_info *ru = item->util;
+ int i;
+
+ if (!ru)
+ continue;
+ for (i = 0; i < 3; i++) {
+ struct object *obj;
+
+ if (!ru->mode[i] || !S_ISREG(ru->mode[i]))
+ continue;
+
+ obj = parse_object(the_repository, &ru->oid[i]);
+ if (!obj) {
+ error(_("%s: invalid sha1 pointer in resolve-undo"),
+ oid_to_hex(&ru->oid[i]));
+ errors_found |= ERROR_REFS;
+ continue;
+ }
+ obj->flags |= USED;
+ fsck_put_object_name(&fsck_walk_options, &ru->oid[i],
+ ":(%d):%s", i, path);
+ mark_object_reachable(obj);
+ }
+ }
+ return 0;
+}
+
static void mark_object_for_connectivity(const struct object_id *oid)
{
struct object *obj = lookup_unknown_object(the_repository, oid);
@@ -938,6 +976,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
}
if (active_cache_tree)
fsck_cache_tree(active_cache_tree);
+ fsck_resolve_undo(&the_index);
}
check_connectivity();
diff --git a/builtin/gc.c b/builtin/gc.c
index 4ea7008..eeff2b7 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -168,9 +168,15 @@ struct maintenance_run_opts;
static int maintenance_task_pack_refs(MAYBE_UNUSED struct maintenance_run_opts *opts)
{
struct strvec pack_refs_cmd = STRVEC_INIT;
+ int ret;
+
strvec_pushl(&pack_refs_cmd, "pack-refs", "--all", "--prune", NULL);
- return run_command_v_opt(pack_refs_cmd.v, RUN_GIT_CMD);
+ ret = run_command_v_opt(pack_refs_cmd.v, RUN_GIT_CMD);
+
+ strvec_clear(&pack_refs_cmd);
+
+ return ret;
}
static int too_many_loose_objects(void)
@@ -581,7 +587,7 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
/* default expiry time, overwritten in gc_config */
gc_config();
if (parse_expiry_date(gc_log_expire, &gc_log_expire_time))
- die(_("failed to parse gc.logexpiry value %s"), gc_log_expire);
+ die(_("failed to parse gc.logExpiry value %s"), gc_log_expire);
if (pack_refs < 0)
pack_refs = !is_bare_repository();
diff --git a/builtin/grep.c b/builtin/grep.c
index bcb07ea..e6bcdf8 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -961,6 +961,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
OPT_BOOL_F(0, "ext-grep", &external_grep_allowed__ignored,
N_("allow calling of grep(1) (ignored by this build)"),
PARSE_OPT_NOCOMPLETE),
+ OPT_INTEGER('m', "max-count", &opt.max_count,
+ N_("maximum number of results per file")),
OPT_END()
};
grep_prefix = prefix;
@@ -1101,6 +1103,13 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
if (recurse_submodules && untracked)
die(_("--untracked not supported with --recurse-submodules"));
+ /*
+ * Optimize out the case where the amount of matches is limited to zero.
+ * We do this to keep results consistent with GNU grep(1).
+ */
+ if (opt.max_count == 0)
+ return 1;
+
if (show_in_pager) {
if (num_threads > 1)
warning(_("invalid option combination, ignoring --threads"));
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 3e385b4..6648f2d 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1575,7 +1575,7 @@ static int git_index_pack_config(const char *k, const char *v, void *cb)
if (!strcmp(k, "pack.indexversion")) {
opts->version = git_config_int(k, v);
if (opts->version > 2)
- die(_("bad pack.indexversion=%"PRIu32), opts->version);
+ die(_("bad pack.indexVersion=%"PRIu32), opts->version);
return 0;
}
if (!strcmp(k, "pack.threads")) {
diff --git a/builtin/merge-file.c b/builtin/merge-file.c
index e695867..c923bbf 100644
--- a/builtin/merge-file.c
+++ b/builtin/merge-file.c
@@ -25,10 +25,10 @@ static int label_cb(const struct option *opt, const char *arg, int unset)
int cmd_merge_file(int argc, const char **argv, const char *prefix)
{
- const char *names[3] = { NULL, NULL, NULL };
- mmfile_t mmfs[3];
- mmbuffer_t result = {NULL, 0};
- xmparam_t xmp = {{0}};
+ const char *names[3] = { 0 };
+ mmfile_t mmfs[3] = { 0 };
+ mmbuffer_t result = { 0 };
+ xmparam_t xmp = { 0 };
int ret = 0, i = 0, to_stdout = 0;
int quiet = 0;
struct option options[] = {
@@ -71,21 +71,24 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
for (i = 0; i < 3; i++) {
char *fname;
- int ret;
+ mmfile_t *mmf = mmfs + i;
if (!names[i])
names[i] = argv[i];
fname = prefix_filename(prefix, argv[i]);
- ret = read_mmfile(mmfs + i, fname);
+
+ if (read_mmfile(mmf, fname))
+ ret = -1;
+ else if (mmf->size > MAX_XDIFF_SIZE ||
+ buffer_is_binary(mmf->ptr, mmf->size))
+ ret = error("Cannot merge binary files: %s",
+ argv[i]);
+
free(fname);
if (ret)
- return -1;
+ goto cleanup;
- if (mmfs[i].size > MAX_XDIFF_SIZE ||
- buffer_is_binary(mmfs[i].ptr, mmfs[i].size))
- return error("Cannot merge binary files: %s",
- argv[i]);
}
xmp.ancestor = names[1];
@@ -93,9 +96,6 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
xmp.file2 = names[2];
ret = xdl_merge(mmfs + 1, mmfs + 0, mmfs + 2, &xmp, &result);
- for (i = 0; i < 3; i++)
- free(mmfs[i].ptr);
-
if (ret >= 0) {
const char *filename = argv[0];
char *fpath = prefix_filename(prefix, argv[0]);
@@ -116,5 +116,9 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
if (ret > 127)
ret = 127;
+cleanup:
+ for (i = 0; i < 3; i++)
+ free(mmfs[i].ptr);
+
return ret;
}
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 5dc94d6..ae57829 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -2,13 +2,18 @@
#include "builtin.h"
#include "tree-walk.h"
#include "xdiff-interface.h"
+#include "help.h"
+#include "commit-reach.h"
+#include "merge-ort.h"
#include "object-store.h"
+#include "parse-options.h"
#include "repository.h"
#include "blob.h"
#include "exec-cmd.h"
#include "merge-blobs.h"
+#include "quote.h"
-static const char merge_tree_usage[] = "git merge-tree <base-tree> <branch1> <branch2>";
+static int line_termination = '\n';
struct merge_list {
struct merge_list *next;
@@ -28,7 +33,7 @@ static void add_merge_entry(struct merge_list *entry)
merge_result_end = &entry->next;
}
-static void merge_trees(struct tree_desc t[3], const char *base);
+static void trivial_merge_trees(struct tree_desc t[3], const char *base);
static const char *explanation(struct merge_list *entry)
{
@@ -225,7 +230,7 @@ static void unresolved_directory(const struct traverse_info *info,
buf2 = fill_tree_descriptor(r, t + 2, ENTRY_OID(n + 2));
#undef ENTRY_OID
- merge_trees(t, newbase);
+ trivial_merge_trees(t, newbase);
free(buf0);
free(buf1);
@@ -342,7 +347,7 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s
return mask;
}
-static void merge_trees(struct tree_desc t[3], const char *base)
+static void trivial_merge_trees(struct tree_desc t[3], const char *base)
{
struct traverse_info info;
@@ -366,19 +371,18 @@ static void *get_tree_descriptor(struct repository *r,
return buf;
}
-int cmd_merge_tree(int argc, const char **argv, const char *prefix)
+static int trivial_merge(const char *base,
+ const char *branch1,
+ const char *branch2)
{
struct repository *r = the_repository;
struct tree_desc t[3];
void *buf1, *buf2, *buf3;
- if (argc != 4)
- usage(merge_tree_usage);
-
- buf1 = get_tree_descriptor(r, t+0, argv[1]);
- buf2 = get_tree_descriptor(r, t+1, argv[2]);
- buf3 = get_tree_descriptor(r, t+2, argv[3]);
- merge_trees(t, "");
+ buf1 = get_tree_descriptor(r, t+0, base);
+ buf2 = get_tree_descriptor(r, t+1, branch1);
+ buf3 = get_tree_descriptor(r, t+2, branch2);
+ trivial_merge_trees(t, "");
free(buf1);
free(buf2);
free(buf3);
@@ -386,3 +390,162 @@ int cmd_merge_tree(int argc, const char **argv, const char *prefix)
show_result();
return 0;
}
+
+enum mode {
+ MODE_UNKNOWN,
+ MODE_TRIVIAL,
+ MODE_REAL,
+};
+
+struct merge_tree_options {
+ int mode;
+ int allow_unrelated_histories;
+ int show_messages;
+ int name_only;
+};
+
+static int real_merge(struct merge_tree_options *o,
+ const char *branch1, const char *branch2,
+ const char *prefix)
+{
+ struct commit *parent1, *parent2;
+ struct commit_list *merge_bases = NULL;
+ struct merge_options opt;
+ struct merge_result result = { 0 };
+
+ parent1 = get_merge_parent(branch1);
+ if (!parent1)
+ help_unknown_ref(branch1, "merge-tree",
+ _("not something we can merge"));
+
+ parent2 = get_merge_parent(branch2);
+ if (!parent2)
+ help_unknown_ref(branch2, "merge-tree",
+ _("not something we can merge"));
+
+ init_merge_options(&opt, the_repository);
+
+ opt.show_rename_progress = 0;
+
+ opt.branch1 = branch1;
+ opt.branch2 = branch2;
+
+ /*
+ * Get the merge bases, in reverse order; see comment above
+ * merge_incore_recursive in merge-ort.h
+ */
+ merge_bases = get_merge_bases(parent1, parent2);
+ if (!merge_bases && !o->allow_unrelated_histories)
+ die(_("refusing to merge unrelated histories"));
+ merge_bases = reverse_commit_list(merge_bases);
+
+ merge_incore_recursive(&opt, merge_bases, parent1, parent2, &result);
+ if (result.clean < 0)
+ die(_("failure to merge"));
+
+ if (o->show_messages == -1)
+ o->show_messages = !result.clean;
+
+ printf("%s%c", oid_to_hex(&result.tree->object.oid), line_termination);
+ if (!result.clean) {
+ struct string_list conflicted_files = STRING_LIST_INIT_NODUP;
+ const char *last = NULL;
+ int i;
+
+ merge_get_conflicted_files(&result, &conflicted_files);
+ for (i = 0; i < conflicted_files.nr; i++) {
+ const char *name = conflicted_files.items[i].string;
+ struct stage_info *c = conflicted_files.items[i].util;
+ if (!o->name_only)
+ printf("%06o %s %d\t",
+ c->mode, oid_to_hex(&c->oid), c->stage);
+ else if (last && !strcmp(last, name))
+ continue;
+ write_name_quoted_relative(
+ name, prefix, stdout, line_termination);
+ last = name;
+ }
+ string_list_clear(&conflicted_files, 1);
+ }
+ if (o->show_messages) {
+ putchar(line_termination);
+ merge_display_update_messages(&opt, line_termination == '\0',
+ &result);
+ }
+ merge_finalize(&opt, &result);
+ return !result.clean; /* result.clean < 0 handled above */
+}
+
+int cmd_merge_tree(int argc, const char **argv, const char *prefix)
+{
+ struct merge_tree_options o = { .show_messages = -1 };
+ int expected_remaining_argc;
+ int original_argc;
+
+ const char * const merge_tree_usage[] = {
+ N_("git merge-tree [--write-tree] [<options>] <branch1> <branch2>"),
+ N_("git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2>"),
+ NULL
+ };
+ struct option mt_options[] = {
+ OPT_CMDMODE(0, "write-tree", &o.mode,
+ N_("do a real merge instead of a trivial merge"),
+ MODE_REAL),
+ OPT_CMDMODE(0, "trivial-merge", &o.mode,
+ N_("do a trivial merge only"), MODE_TRIVIAL),
+ OPT_BOOL(0, "messages", &o.show_messages,
+ N_("also show informational/conflict messages")),
+ OPT_SET_INT('z', NULL, &line_termination,
+ N_("separate paths with the NUL character"), '\0'),
+ OPT_BOOL_F(0, "name-only",
+ &o.name_only,
+ N_("list filenames without modes/oids/stages"),
+ PARSE_OPT_NONEG),
+ OPT_BOOL_F(0, "allow-unrelated-histories",
+ &o.allow_unrelated_histories,
+ N_("allow merging unrelated histories"),
+ PARSE_OPT_NONEG),
+ OPT_END()
+ };
+
+ /* Parse arguments */
+ original_argc = argc - 1; /* ignoring argv[0] */
+ argc = parse_options(argc, argv, prefix, mt_options,
+ merge_tree_usage, PARSE_OPT_STOP_AT_NON_OPTION);
+ switch (o.mode) {
+ default:
+ BUG("unexpected command mode %d", o.mode);
+ case MODE_UNKNOWN:
+ switch (argc) {
+ default:
+ usage_with_options(merge_tree_usage, mt_options);
+ case 2:
+ o.mode = MODE_REAL;
+ break;
+ case 3:
+ o.mode = MODE_TRIVIAL;
+ break;
+ }
+ expected_remaining_argc = argc;
+ break;
+ case MODE_REAL:
+ expected_remaining_argc = 2;
+ break;
+ case MODE_TRIVIAL:
+ expected_remaining_argc = 3;
+ /* Removal of `--trivial-merge` is expected */
+ original_argc--;
+ break;
+ }
+ if (o.mode == MODE_TRIVIAL && argc < original_argc)
+ die(_("--trivial-merge is incompatible with all other options"));
+
+ if (argc != expected_remaining_argc)
+ usage_with_options(merge_tree_usage, mt_options);
+
+ /* Do the relevant type of merge */
+ if (o.mode == MODE_REAL)
+ return real_merge(&o, argv[0], argv[1], prefix);
+ else
+ return trivial_merge(argv[0], argv[1], argv[2]);
+}
diff --git a/builtin/merge.c b/builtin/merge.c
index d9784d4..23170f2 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -375,7 +375,6 @@ static void reset_hard(const struct object_id *oid, int verbose)
static void restore_state(const struct object_id *head,
const struct object_id *stash)
{
- struct strbuf sb = STRBUF_INIT;
const char *args[] = { "stash", "apply", NULL, NULL };
if (is_null_oid(stash))
@@ -391,7 +390,6 @@ static void restore_state(const struct object_id *head,
*/
run_command_v_opt(args, RUN_GIT_CMD);
- strbuf_release(&sb);
refresh_cache(REFRESH_QUIET);
}
@@ -502,7 +500,6 @@ static void merge_name(const char *remote, struct strbuf *msg)
{
struct commit *remote_head;
struct object_id branch_head;
- struct strbuf buf = STRBUF_INIT;
struct strbuf bname = STRBUF_INIT;
struct merge_remote_desc *desc;
const char *ptr;
@@ -590,7 +587,6 @@ static void merge_name(const char *remote, struct strbuf *msg)
oid_to_hex(&remote_head->object.oid), remote);
cleanup:
free(found_ref);
- strbuf_release(&buf);
strbuf_release(&bname);
}
diff --git a/builtin/mktree.c b/builtin/mktree.c
index 902edba..06d8140 100644
--- a/builtin/mktree.c
+++ b/builtin/mktree.c
@@ -74,6 +74,7 @@ static void mktree_line(char *buf, int nul_term_line, int allow_missing)
unsigned mode;
enum object_type mode_type; /* object type derived from mode */
enum object_type obj_type; /* object type derived from sha */
+ struct object_info oi = OBJECT_INFO_INIT;
char *path, *to_free = NULL;
struct object_id oid;
@@ -116,8 +117,14 @@ static void mktree_line(char *buf, int nul_term_line, int allow_missing)
path, ptr, type_name(mode_type));
}
- /* Check the type of object identified by sha1 */
- obj_type = oid_object_info(the_repository, &oid, NULL);
+ /* Check the type of object identified by oid without fetching objects */
+ oi.typep = &obj_type;
+ if (oid_object_info_extended(the_repository, &oid, &oi,
+ OBJECT_INFO_LOOKUP_REPLACE |
+ OBJECT_INFO_QUICK |
+ OBJECT_INFO_SKIP_FETCH_OBJECT) < 0)
+ obj_type = -1;
+
if (obj_type < 0) {
if (allow_missing) {
; /* no problem - missing objects are presumed to be of the right type */
diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c
index 5edbb7f..8f24d59 100644
--- a/builtin/multi-pack-index.c
+++ b/builtin/multi-pack-index.c
@@ -134,7 +134,7 @@ static int cmd_multi_pack_index_write(int argc, const char **argv)
opts.flags |= MIDX_PROGRESS;
argc = parse_options(argc, argv, NULL,
options, builtin_multi_pack_index_write_usage,
- PARSE_OPT_KEEP_UNKNOWN);
+ 0);
if (argc)
usage_with_options(builtin_multi_pack_index_write_usage,
options);
@@ -176,7 +176,7 @@ static int cmd_multi_pack_index_verify(int argc, const char **argv)
opts.flags |= MIDX_PROGRESS;
argc = parse_options(argc, argv, NULL,
options, builtin_multi_pack_index_verify_usage,
- PARSE_OPT_KEEP_UNKNOWN);
+ 0);
if (argc)
usage_with_options(builtin_multi_pack_index_verify_usage,
options);
@@ -202,7 +202,7 @@ static int cmd_multi_pack_index_expire(int argc, const char **argv)
opts.flags |= MIDX_PROGRESS;
argc = parse_options(argc, argv, NULL,
options, builtin_multi_pack_index_expire_usage,
- PARSE_OPT_KEEP_UNKNOWN);
+ 0);
if (argc)
usage_with_options(builtin_multi_pack_index_expire_usage,
options);
@@ -232,7 +232,7 @@ static int cmd_multi_pack_index_repack(int argc, const char **argv)
argc = parse_options(argc, argv, NULL,
options,
builtin_multi_pack_index_repack_usage,
- PARSE_OPT_KEEP_UNKNOWN);
+ 0);
if (argc)
usage_with_options(builtin_multi_pack_index_repack_usage,
options);
diff --git a/builtin/mv.c b/builtin/mv.c
index 83a465b..4729bb1 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -13,12 +13,21 @@
#include "string-list.h"
#include "parse-options.h"
#include "submodule.h"
+#include "entry.h"
static const char * const builtin_mv_usage[] = {
N_("git mv [<options>] <source>... <destination>"),
NULL
};
+enum update_mode {
+ BOTH = 0,
+ WORKING_DIRECTORY = (1 << 1),
+ INDEX = (1 << 2),
+ SPARSE = (1 << 3),
+ SKIP_WORKTREE_DIR = (1 << 4),
+};
+
#define DUP_BASENAME 1
#define KEEP_TRAILING_SLASH 2
@@ -115,6 +124,36 @@ static int index_range_of_same_dir(const char *src, int length,
return last - first;
}
+/*
+ * Check if an out-of-cone directory should be in the index. Imagine this case
+ * that all the files under a directory are marked with 'CE_SKIP_WORKTREE' bit
+ * and thus the directory is sparsified.
+ *
+ * Return 0 if such directory exist (i.e. with any of its contained files not
+ * marked with CE_SKIP_WORKTREE, the directory would be present in working tree).
+ * Return 1 otherwise.
+ */
+static int check_dir_in_index(const char *name)
+{
+ const char *with_slash = add_slash(name);
+ int length = strlen(with_slash);
+
+ int pos = cache_name_pos(with_slash, length);
+ const struct cache_entry *ce;
+
+ if (pos < 0) {
+ pos = -pos - 1;
+ if (pos >= the_index.cache_nr)
+ return 1;
+ ce = active_cache[pos];
+ if (strncmp(with_slash, ce->name, length))
+ return 1;
+ if (ce_skip_worktree(ce))
+ return 0;
+ }
+ return 1;
+}
+
int cmd_mv(int argc, const char **argv, const char *prefix)
{
int i, flags, gitmodules_modified = 0;
@@ -129,7 +168,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
OPT_END(),
};
const char **source, **destination, **dest_path, **submodule_gitfile;
- enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX, SPARSE } *modes;
+ enum update_mode *modes;
struct stat st;
struct string_list src_for_dst = STRING_LIST_INIT_NODUP;
struct lock_file lock_file = LOCK_INIT;
@@ -148,7 +187,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
die(_("index file corrupt"));
source = internal_prefix_pathspec(prefix, argv, argc, 0);
- modes = xcalloc(argc, sizeof(enum update_mode));
+ CALLOC_ARRAY(modes, argc);
+
/*
* Keep trailing slash, needed to let
* "git mv file no-such-dir/" error out, except in the case
@@ -176,7 +216,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
/* Checking */
for (i = 0; i < argc; i++) {
const char *src = source[i], *dst = destination[i];
- int length, src_is_dir;
+ int length;
const char *bad = NULL;
int skip_sparse = 0;
@@ -185,54 +225,103 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
length = strlen(src);
if (lstat(src, &st) < 0) {
- /* only error if existence is expected. */
- if (modes[i] != SPARSE)
+ int pos;
+ const struct cache_entry *ce;
+
+ pos = cache_name_pos(src, length);
+ if (pos < 0) {
+ const char *src_w_slash = add_slash(src);
+ if (!path_in_sparse_checkout(src_w_slash, &the_index) &&
+ !check_dir_in_index(src)) {
+ modes[i] |= SKIP_WORKTREE_DIR;
+ goto dir_check;
+ }
+ /* only error if existence is expected. */
+ if (!(modes[i] & SPARSE))
+ bad = _("bad source");
+ goto act_on_entry;
+ }
+ ce = active_cache[pos];
+ if (!ce_skip_worktree(ce)) {
bad = _("bad source");
- } else if (!strncmp(src, dst, length) &&
- (dst[length] == 0 || dst[length] == '/')) {
+ goto act_on_entry;
+ }
+ if (!ignore_sparse) {
+ string_list_append(&only_match_skip_worktree, src);
+ goto act_on_entry;
+ }
+ /* Check if dst exists in index */
+ if (cache_name_pos(dst, strlen(dst)) < 0) {
+ modes[i] |= SPARSE;
+ goto act_on_entry;
+ }
+ if (!force) {
+ bad = _("destination exists");
+ goto act_on_entry;
+ }
+ modes[i] |= SPARSE;
+ goto act_on_entry;
+ }
+ if (!strncmp(src, dst, length) &&
+ (dst[length] == 0 || dst[length] == '/')) {
bad = _("can not move directory into itself");
- } else if ((src_is_dir = S_ISDIR(st.st_mode))
- && lstat(dst, &st) == 0)
+ goto act_on_entry;
+ }
+ if (S_ISDIR(st.st_mode)
+ && lstat(dst, &st) == 0) {
bad = _("cannot move directory over file");
- else if (src_is_dir) {
+ goto act_on_entry;
+ }
+
+dir_check:
+ if (S_ISDIR(st.st_mode)) {
+ int j, dst_len, n;
int first = cache_name_pos(src, length), last;
- if (first >= 0)
+ if (first >= 0) {
prepare_move_submodule(src, first,
submodule_gitfile + i);
- else if (index_range_of_same_dir(src, length,
- &first, &last) < 1)
+ goto act_on_entry;
+ } else if (index_range_of_same_dir(src, length,
+ &first, &last) < 1) {
bad = _("source directory is empty");
- else { /* last - first >= 1 */
- int j, dst_len, n;
-
- modes[i] = WORKING_DIRECTORY;
- n = argc + last - first;
- REALLOC_ARRAY(source, n);
- REALLOC_ARRAY(destination, n);
- REALLOC_ARRAY(modes, n);
- REALLOC_ARRAY(submodule_gitfile, n);
-
- dst = add_slash(dst);
- dst_len = strlen(dst);
-
- for (j = 0; j < last - first; j++) {
- const struct cache_entry *ce = active_cache[first + j];
- const char *path = ce->name;
- source[argc + j] = path;
- destination[argc + j] =
- prefix_path(dst, dst_len, path + length + 1);
- modes[argc + j] = ce_skip_worktree(ce) ? SPARSE : INDEX;
- submodule_gitfile[argc + j] = NULL;
- }
- argc += last - first;
+ goto act_on_entry;
}
- } else if (!(ce = cache_file_exists(src, length, 0))) {
+
+ /* last - first >= 1 */
+ modes[i] |= WORKING_DIRECTORY;
+ n = argc + last - first;
+ REALLOC_ARRAY(source, n);
+ REALLOC_ARRAY(destination, n);
+ REALLOC_ARRAY(modes, n);
+ REALLOC_ARRAY(submodule_gitfile, n);
+
+ dst = add_slash(dst);
+ dst_len = strlen(dst);
+
+ for (j = 0; j < last - first; j++) {
+ const struct cache_entry *ce = active_cache[first + j];
+ const char *path = ce->name;
+ source[argc + j] = path;
+ destination[argc + j] =
+ prefix_path(dst, dst_len, path + length + 1);
+ memset(modes + argc + j, 0, sizeof(enum update_mode));
+ modes[argc + j] |= ce_skip_worktree(ce) ? SPARSE : INDEX;
+ submodule_gitfile[argc + j] = NULL;
+ }
+ argc += last - first;
+ goto act_on_entry;
+ }
+ if (!(ce = cache_file_exists(src, length, 0))) {
bad = _("not under version control");
- } else if (ce_stage(ce)) {
+ goto act_on_entry;
+ }
+ if (ce_stage(ce)) {
bad = _("conflicted");
- } else if (lstat(dst, &st) == 0 &&
- (!ignore_case || strcasecmp(src, dst))) {
+ goto act_on_entry;
+ }
+ if (lstat(dst, &st) == 0 &&
+ (!ignore_case || strcasecmp(src, dst))) {
bad = _("destination exists");
if (force) {
/*
@@ -246,34 +335,40 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
} else
bad = _("Cannot overwrite");
}
- } else if (string_list_has_string(&src_for_dst, dst))
+ goto act_on_entry;
+ }
+ if (string_list_has_string(&src_for_dst, dst)) {
bad = _("multiple sources for the same target");
- else if (is_dir_sep(dst[strlen(dst) - 1]))
+ goto act_on_entry;
+ }
+ if (is_dir_sep(dst[strlen(dst) - 1])) {
bad = _("destination directory does not exist");
- else {
- /*
- * We check if the paths are in the sparse-checkout
- * definition as a very final check, since that
- * allows us to point the user to the --sparse
- * option as a way to have a successful run.
- */
- if (!ignore_sparse &&
- !path_in_sparse_checkout(src, &the_index)) {
- string_list_append(&only_match_skip_worktree, src);
- skip_sparse = 1;
- }
- if (!ignore_sparse &&
- !path_in_sparse_checkout(dst, &the_index)) {
- string_list_append(&only_match_skip_worktree, dst);
- skip_sparse = 1;
- }
-
- if (skip_sparse)
- goto remove_entry;
+ goto act_on_entry;
+ }
- string_list_insert(&src_for_dst, dst);
+ /*
+ * We check if the paths are in the sparse-checkout
+ * definition as a very final check, since that
+ * allows us to point the user to the --sparse
+ * option as a way to have a successful run.
+ */
+ if (!ignore_sparse &&
+ !path_in_sparse_checkout(src, &the_index)) {
+ string_list_append(&only_match_skip_worktree, src);
+ skip_sparse = 1;
}
+ if (!ignore_sparse &&
+ !path_in_sparse_checkout(dst, &the_index)) {
+ string_list_append(&only_match_skip_worktree, dst);
+ skip_sparse = 1;
+ }
+
+ if (skip_sparse)
+ goto remove_entry;
+
+ string_list_insert(&src_for_dst, dst);
+act_on_entry:
if (!bad)
continue;
if (!ignore_errors)
@@ -282,14 +377,11 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
remove_entry:
if (--argc > 0) {
int n = argc - i;
- memmove(source + i, source + i + 1,
- n * sizeof(char *));
- memmove(destination + i, destination + i + 1,
- n * sizeof(char *));
- memmove(modes + i, modes + i + 1,
- n * sizeof(enum update_mode));
- memmove(submodule_gitfile + i, submodule_gitfile + i + 1,
- n * sizeof(char *));
+ MOVE_ARRAY(source + i, source + i + 1, n);
+ MOVE_ARRAY(destination + i, destination + i + 1, n);
+ MOVE_ARRAY(modes + i, modes + i + 1, n);
+ MOVE_ARRAY(submodule_gitfile + i,
+ submodule_gitfile + i + 1, n);
i--;
}
}
@@ -304,11 +396,17 @@ remove_entry:
const char *src = source[i], *dst = destination[i];
enum update_mode mode = modes[i];
int pos;
+ struct checkout state = CHECKOUT_INIT;
+ state.istate = &the_index;
+
+ if (force)
+ state.force = 1;
if (show_only || verbose)
printf(_("Renaming %s to %s\n"), src, dst);
if (show_only)
continue;
- if (mode != INDEX && mode != SPARSE && rename(src, dst) < 0) {
+ if (!(mode & (INDEX | SPARSE | SKIP_WORKTREE_DIR)) &&
+ rename(src, dst) < 0) {
if (ignore_errors)
continue;
die_errno(_("renaming '%s' failed"), src);
@@ -322,12 +420,23 @@ remove_entry:
1);
}
- if (mode == WORKING_DIRECTORY)
+ if (mode & (WORKING_DIRECTORY | SKIP_WORKTREE_DIR))
continue;
pos = cache_name_pos(src, strlen(src));
assert(pos >= 0);
rename_cache_entry_at(pos, dst);
+
+ if ((mode & SPARSE) &&
+ (path_in_sparse_checkout(dst, &the_index))) {
+ int dst_pos;
+
+ dst_pos = cache_name_pos(dst, strlen(dst));
+ active_cache[dst_pos]->ce_flags &= ~CE_SKIP_WORKTREE;
+
+ if (checkout_entry(active_cache[dst_pos], &state, NULL, NULL))
+ die(_("cannot checkout %s"), active_cache[dst_pos]->name);
+ }
}
if (gitmodules_modified)
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 02ea9d1..580b1eb 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -577,7 +577,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
N_("ignore refs matching <pattern>")),
OPT_GROUP(""),
OPT_BOOL(0, "all", &all, N_("list all commits reachable from all refs")),
- OPT_BOOL(0, "stdin", &transform_stdin, N_("deprecated: use annotate-stdin instead")),
+ OPT_BOOL(0, "stdin", &transform_stdin, N_("deprecated: use --annotate-stdin instead")),
OPT_BOOL(0, "annotate-stdin", &annotate_stdin, N_("annotate text from stdin")),
OPT_BOOL(0, "undefined", &allow_undefined, N_("allow to print `undefined` names (default)")),
OPT_BOOL(0, "always", &always,
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index cc5f410..39e28cf 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -3170,7 +3170,7 @@ static int git_pack_config(const char *k, const char *v, void *cb)
if (!strcmp(k, "pack.indexversion")) {
pack_idx_opts.version = git_config_int(k, v);
if (pack_idx_opts.version > 2)
- die(_("bad pack.indexversion=%"PRIu32),
+ die(_("bad pack.indexVersion=%"PRIu32),
pack_idx_opts.version);
return 0;
}
diff --git a/builtin/pull.c b/builtin/pull.c
index 01155ba..403a24d 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -990,6 +990,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
int rebase_unspecified = 0;
int can_ff;
int divergent;
+ int ret;
if (!getenv("GIT_REFLOG_ACTION"))
set_reflog_message(argc, argv);
@@ -1100,7 +1101,8 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
if (is_null_oid(&orig_head)) {
if (merge_heads.nr > 1)
die(_("Cannot merge multiple branches into empty head."));
- return pull_into_void(merge_heads.oid, &curr_head);
+ ret = pull_into_void(merge_heads.oid, &curr_head);
+ goto cleanup;
}
if (merge_heads.nr > 1) {
if (opt_rebase)
@@ -1125,8 +1127,6 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
}
if (opt_rebase) {
- int ret = 0;
-
struct object_id newbase;
struct object_id upstream;
get_rebase_newbase_and_upstream(&newbase, &upstream, &curr_head,
@@ -1149,12 +1149,16 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
ret = rebase_submodules();
- return ret;
+ goto cleanup;
} else {
- int ret = run_merge();
+ ret = run_merge();
if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON ||
recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
ret = update_submodules();
- return ret;
+ goto cleanup;
}
+
+cleanup:
+ oid_array_clear(&merge_heads);
+ return ret;
}
diff --git a/builtin/push.c b/builtin/push.c
index 86b44f8..df0d68e 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -171,7 +171,7 @@ static NORETURN void die_push_simple(struct branch *branch,
"To avoid automatically configuring "
"upstream branches when their name\n"
"doesn't match the local branch, see option "
- "'simple' of branch.autosetupmerge\n"
+ "'simple' of branch.autoSetupMerge\n"
"in 'git help config'.\n");
die(_("The upstream branch of your current branch does not match\n"
"the name of your current branch. To push to the upstream branch\n"
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 7ab50cd..56e4214 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -102,6 +102,7 @@ struct rebase_options {
int reschedule_failed_exec;
int reapply_cherry_picks;
int fork_point;
+ int update_refs;
};
#define REBASE_OPTIONS_INIT { \
@@ -298,6 +299,7 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
ret = complete_action(the_repository, &replay, flags,
shortrevisions, opts->onto_name, opts->onto,
&opts->orig_head, &commands, opts->autosquash,
+ opts->update_refs,
&todo_list);
}
@@ -800,6 +802,11 @@ static int rebase_config(const char *var, const char *value, void *data)
return 0;
}
+ if (!strcmp(var, "rebase.updaterefs")) {
+ opts->update_refs = git_config_bool(var, value);
+ return 0;
+ }
+
if (!strcmp(var, "rebase.reschedulefailedexec")) {
opts->reschedule_failed_exec = git_config_bool(var, value);
return 0;
@@ -1110,8 +1117,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
PARSE_OPT_NOARG | PARSE_OPT_NONEG,
parse_opt_interactive),
OPT_SET_INT_F('p', "preserve-merges", &preserve_merges_selected,
- N_("(DEPRECATED) try to recreate merges instead of "
- "ignoring them"),
+ N_("(REMOVED) was: try to recreate merges "
+ "instead of ignoring them"),
1, PARSE_OPT_HIDDEN),
OPT_RERERE_AUTOUPDATE(&options.allow_rerere_autoupdate),
OPT_CALLBACK_F(0, "empty", &options, "{drop,keep,ask}",
@@ -1124,6 +1131,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
OPT_BOOL(0, "autosquash", &options.autosquash,
N_("move commits that begin with "
"squash!/fixup! under -i")),
+ OPT_BOOL(0, "update-refs", &options.update_refs,
+ N_("update branches that point to commits "
+ "that are being rebased")),
{ OPTION_STRING, 'S', "gpg-sign", &gpg_sign, N_("key-id"),
N_("GPG-sign commits"),
PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
@@ -1182,8 +1192,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
} else if (is_directory(merge_dir())) {
strbuf_reset(&buf);
strbuf_addf(&buf, "%s/rewritten", merge_dir());
- if (is_directory(buf.buf)) {
- die("`rebase -p` is no longer supported");
+ if (!(action == ACTION_ABORT) && is_directory(buf.buf)) {
+ die(_("`rebase --preserve-merges` (-p) is no longer supported.\n"
+ "Use `git rebase --abort` to terminate current rebase.\n"
+ "Or downgrade to v2.33, or earlier, to complete the rebase."));
} else {
strbuf_reset(&buf);
strbuf_addf(&buf, "%s/interactive", merge_dir());
@@ -1203,7 +1215,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
builtin_rebase_usage, 0);
if (preserve_merges_selected)
- die(_("--preserve-merges was replaced by --rebase-merges"));
+ die(_("--preserve-merges was replaced by --rebase-merges\n"
+ "Note: Your `pull.rebase` configuration may also be set to 'preserve',\n"
+ "which is no longer supported; use 'merges' instead"));
if (action != ACTION_NONE && total_argc != 2) {
usage_with_options(builtin_rebase_usage,
diff --git a/builtin/remote.c b/builtin/remote.c
index d4b69fe..d9b8746 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -344,12 +344,13 @@ static void read_branches(void)
struct ref_states {
struct remote *remote;
- struct string_list new_refs, stale, tracked, heads, push;
+ struct string_list new_refs, skipped, stale, tracked, heads, push;
int queried;
};
#define REF_STATES_INIT { \
.new_refs = STRING_LIST_INIT_DUP, \
+ .skipped = STRING_LIST_INIT_DUP, \
.stale = STRING_LIST_INIT_DUP, \
.tracked = STRING_LIST_INIT_DUP, \
.heads = STRING_LIST_INIT_DUP, \
@@ -368,7 +369,9 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
states->remote->fetch.raw[i]);
for (ref = fetch_map; ref; ref = ref->next) {
- if (!ref->peer_ref || !ref_exists(ref->peer_ref->name))
+ if (omit_name_by_refspec(ref->name, &states->remote->fetch))
+ string_list_append(&states->skipped, abbrev_branch(ref->name));
+ else if (!ref->peer_ref || !ref_exists(ref->peer_ref->name))
string_list_append(&states->new_refs, abbrev_branch(ref->name));
else
string_list_append(&states->tracked, abbrev_branch(ref->name));
@@ -383,6 +386,7 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
free_refs(fetch_map);
string_list_sort(&states->new_refs);
+ string_list_sort(&states->skipped);
string_list_sort(&states->tracked);
string_list_sort(&states->stale);
@@ -941,6 +945,7 @@ static void clear_push_info(void *util, const char *string)
static void free_remote_ref_states(struct ref_states *states)
{
string_list_clear(&states->new_refs, 0);
+ string_list_clear(&states->skipped, 0);
string_list_clear(&states->stale, 1);
string_list_clear(&states->tracked, 0);
string_list_clear(&states->heads, 0);
@@ -1035,6 +1040,8 @@ static int show_remote_info_item(struct string_list_item *item, void *cb_data)
arg = states->remote->name;
} else if (string_list_has_string(&states->tracked, name))
arg = _(" tracked");
+ else if (string_list_has_string(&states->skipped, name))
+ arg = _(" skipped");
else if (string_list_has_string(&states->stale, name))
arg = _(" stale (use 'git remote prune' to remove)");
else
@@ -1308,6 +1315,7 @@ static int show(int argc, const char **argv)
/* remote branch info */
info.width = 0;
for_each_string_list(&info.states.new_refs, add_remote_to_show_info, &info);
+ for_each_string_list(&info.states.skipped, add_remote_to_show_info, &info);
for_each_string_list(&info.states.tracked, add_remote_to_show_info, &info);
for_each_string_list(&info.states.stale, add_remote_to_show_info, &info);
if (info.list.nr)
diff --git a/builtin/repack.c b/builtin/repack.c
index c957b29..482b66f 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -41,7 +41,7 @@ static const char *const git_repack_usage[] = {
static const char incremental_bitmap_conflict_error[] = N_(
"Incremental repacks are incompatible with bitmap indexes. Use\n"
-"--no-write-bitmap-index or disable the pack.writebitmaps configuration."
+"--no-write-bitmap-index or disable the pack.writeBitmaps configuration."
);
struct pack_objects_args {
@@ -727,7 +727,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
struct child_process cmd = CHILD_PROCESS_INIT;
struct string_list_item *item;
struct string_list names = STRING_LIST_INIT_DUP;
- struct string_list rollback = STRING_LIST_INIT_NODUP;
struct string_list existing_nonkept_packs = STRING_LIST_INIT_DUP;
struct string_list existing_kept_packs = STRING_LIST_INIT_DUP;
struct pack_geometry *geometry = NULL;
@@ -1117,7 +1116,6 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
}
string_list_clear(&names, 0);
- string_list_clear(&rollback, 0);
string_list_clear(&existing_nonkept_packs, 0);
string_list_clear(&existing_kept_packs, 0);
clear_pack_geometry(geometry);
diff --git a/builtin/revert.c b/builtin/revert.c
index 51776ab..2554f90 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -130,6 +130,13 @@ static int run_sequencer(int argc, const char **argv, struct replay_opts *opts)
OPT_END(),
};
options = parse_options_concat(options, cp_extra);
+ } else if (opts->action == REPLAY_REVERT) {
+ struct option cp_extra[] = {
+ OPT_BOOL(0, "reference", &opts->commit_use_reference,
+ N_("use the 'reference' format to refer to commits")),
+ OPT_END(),
+ };
+ options = parse_options_concat(options, cp_extra);
}
argc = parse_options(argc, argv, NULL, options, usage_str,
@@ -239,6 +246,9 @@ int cmd_revert(int argc, const char **argv, const char *prefix)
res = run_sequencer(argc, argv, &opts);
if (res < 0)
die(_("revert failed"));
+ if (opts.revs)
+ release_revisions(opts.revs);
+ free(opts.revs);
return res;
}
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 35825f0..086dfee 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -443,7 +443,7 @@ void shortlog_output(struct shortlog *log)
struct strbuf sb = STRBUF_INIT;
if (log->sort_by_number)
- QSORT(log->list.items, log->list.nr,
+ STABLE_QSORT(log->list.items, log->list.nr,
log->summary ? compare_by_counter : compare_by_list);
for (i = 0; i < log->list.nr; i++) {
const struct string_list_item *item = &log->list.items[i];
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index 5c77dfc..fac52ad 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -118,10 +118,11 @@ static int resolve_relative_url_test(int argc, const char **argv, const char *pr
return 0;
}
-static char *do_get_submodule_displaypath(const char *path,
- const char *prefix,
- const char *super_prefix)
+/* the result should be freed by the caller. */
+static char *get_submodule_displaypath(const char *path, const char *prefix)
{
+ const char *super_prefix = get_super_prefix();
+
if (prefix && super_prefix) {
BUG("cannot have prefix '%s' and superprefix '%s'",
prefix, super_prefix);
@@ -137,13 +138,6 @@ static char *do_get_submodule_displaypath(const char *path,
}
}
-/* the result should be freed by the caller. */
-static char *get_submodule_displaypath(const char *path, const char *prefix)
-{
- const char *super_prefix = get_super_prefix();
- return do_get_submodule_displaypath(path, prefix, super_prefix);
-}
-
static char *compute_rev_name(const char *sub_path, const char* object_id)
{
struct strbuf sb = STRBUF_INIT;
@@ -444,7 +438,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
};
const char *const git_submodule_helper_usage[] = {
- N_("git submodule--helper foreach [--quiet] [--recursive] [--] <command>"),
+ N_("git submodule foreach [--quiet] [--recursive] [--] <command>"),
NULL
};
@@ -477,22 +471,18 @@ static int starts_with_dot_dot_slash(const char *const path)
struct init_cb {
const char *prefix;
- const char *superprefix;
unsigned int flags;
};
#define INIT_CB_INIT { 0 }
static void init_submodule(const char *path, const char *prefix,
- const char *superprefix, unsigned int flags)
+ unsigned int flags)
{
const struct submodule *sub;
struct strbuf sb = STRBUF_INIT;
char *upd = NULL, *url = NULL, *displaypath;
- /* try superprefix from the environment, if it is not passed explicitly */
- if (!superprefix)
- superprefix = get_super_prefix();
- displaypath = do_get_submodule_displaypath(path, prefix, superprefix);
+ displaypath = get_submodule_displaypath(path, prefix);
sub = submodule_from_path(the_repository, null_oid(), path);
@@ -566,7 +556,7 @@ static void init_submodule(const char *path, const char *prefix,
static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data)
{
struct init_cb *info = cb_data;
- init_submodule(list_item->name, info->prefix, info->superprefix, info->flags);
+ init_submodule(list_item->name, info->prefix, info->flags);
}
static int module_init(int argc, const char **argv, const char *prefix)
@@ -582,7 +572,7 @@ static int module_init(int argc, const char **argv, const char *prefix)
};
const char *const git_submodule_helper_usage[] = {
- N_("git submodule--helper init [<options>] [<path>]"),
+ N_("git submodule init [<options>] [<path>]"),
NULL
};
@@ -1185,7 +1175,7 @@ static int module_summary(int argc, const char **argv, const char *prefix)
};
const char *const git_submodule_helper_usage[] = {
- N_("git submodule--helper summary [<options>] [<commit>] [--] [<path>]"),
+ N_("git submodule summary [<options>] [<commit>] [--] [<path>]"),
NULL
};
@@ -1349,7 +1339,7 @@ static int module_sync(int argc, const char **argv, const char *prefix)
};
const char *const git_submodule_helper_usage[] = {
- N_("git submodule--helper sync [--quiet] [--recursive] [<path>]"),
+ N_("git submodule sync [--quiet] [--recursive] [<path>]"),
NULL
};
@@ -1818,7 +1808,7 @@ static int module_clone(int argc, const char **argv, const char *prefix)
static void determine_submodule_update_strategy(struct repository *r,
int just_cloned,
const char *path,
- const char *update,
+ enum submodule_update_type update,
struct submodule_update_strategy *out)
{
const struct submodule *sub = submodule_from_path(r, null_oid(), path);
@@ -1828,9 +1818,7 @@ static void determine_submodule_update_strategy(struct repository *r,
key = xstrfmt("submodule.%s.update", sub->name);
if (update) {
- if (parse_submodule_update_strategy(update, out) < 0)
- die(_("Invalid update mode '%s' for submodule path '%s'"),
- update, path);
+ out->type = update;
} else if (!repo_config_get_string_tmp(r, key, &val)) {
if (parse_submodule_update_strategy(val, out) < 0)
die(_("Invalid update mode '%s' configured for submodule path '%s'"),
@@ -1880,9 +1868,8 @@ struct submodule_update_clone {
struct update_data {
const char *prefix;
- const char *recursive_prefix;
const char *displaypath;
- const char *update_default;
+ enum submodule_update_type update_default;
struct object_id suboid;
struct string_list references;
struct submodule_update_strategy update_strategy;
@@ -1949,30 +1936,20 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
const char *update_string;
enum submodule_update_type update_type;
char *key;
- struct strbuf displaypath_sb = STRBUF_INIT;
+ struct update_data *ud = suc->update_data;
+ char *displaypath = get_submodule_displaypath(ce->name, ud->prefix);
struct strbuf sb = STRBUF_INIT;
- const char *displaypath = NULL;
int needs_cloning = 0;
int need_free_url = 0;
if (ce_stage(ce)) {
- if (suc->update_data->recursive_prefix)
- strbuf_addf(&sb, "%s/%s", suc->update_data->recursive_prefix, ce->name);
- else
- strbuf_addstr(&sb, ce->name);
- strbuf_addf(out, _("Skipping unmerged submodule %s"), sb.buf);
+ strbuf_addf(out, _("Skipping unmerged submodule %s"), displaypath);
strbuf_addch(out, '\n');
goto cleanup;
}
sub = submodule_from_path(the_repository, null_oid(), ce->name);
- if (suc->update_data->recursive_prefix)
- displaypath = relative_path(suc->update_data->recursive_prefix,
- ce->name, &displaypath_sb);
- else
- displaypath = ce->name;
-
if (!sub) {
next_submodule_warn_missing(suc, out, displaypath);
goto cleanup;
@@ -2062,7 +2039,7 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
"--no-single-branch");
cleanup:
- strbuf_release(&displaypath_sb);
+ free(displaypath);
strbuf_release(&sb);
if (need_free_url)
free((void*)url);
@@ -2208,6 +2185,7 @@ static int fetch_in_submodule(const char *module_path, int depth, int quiet, str
char *hex = oid_to_hex(oid);
char *remote = get_default_remote();
strvec_pushl(&cp.args, remote, hex, NULL);
+ free(remote);
}
return run_command(&cp);
@@ -2404,13 +2382,33 @@ static void ensure_core_worktree(const char *path)
}
}
+static const char *submodule_update_type_to_label(enum submodule_update_type type)
+{
+ switch (type) {
+ case SM_UPDATE_CHECKOUT:
+ return "checkout";
+ case SM_UPDATE_MERGE:
+ return "merge";
+ case SM_UPDATE_REBASE:
+ return "rebase";
+ case SM_UPDATE_UNSPECIFIED:
+ case SM_UPDATE_NONE:
+ case SM_UPDATE_COMMAND:
+ break;
+ }
+ BUG("unreachable with type %d", type);
+}
+
static void update_data_to_args(struct update_data *update_data, struct strvec *args)
{
+ enum submodule_update_type update_type = update_data->update_default;
+
+ if (update_data->displaypath) {
+ strvec_push(args, "--super-prefix");
+ strvec_pushf(args, "%s/", update_data->displaypath);
+ }
strvec_pushl(args, "submodule--helper", "update", "--recursive", NULL);
strvec_pushf(args, "--jobs=%d", update_data->max_jobs);
- if (update_data->recursive_prefix)
- strvec_pushl(args, "--recursive-prefix",
- update_data->recursive_prefix, NULL);
if (update_data->quiet)
strvec_push(args, "--quiet");
if (update_data->force)
@@ -2429,8 +2427,10 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
strvec_push(args, "--require-init");
if (update_data->depth)
strvec_pushf(args, "--depth=%d", update_data->depth);
- if (update_data->update_default)
- strvec_pushl(args, "--update", update_data->update_default, NULL);
+ if (update_type != SM_UPDATE_UNSPECIFIED)
+ strvec_pushf(args, "--%s",
+ submodule_update_type_to_label(update_type));
+
if (update_data->references.nr) {
struct string_list_item *item;
for_each_string_list_item(item, &update_data->references)
@@ -2452,19 +2452,10 @@ static void update_data_to_args(struct update_data *update_data, struct strvec *
static int update_submodule(struct update_data *update_data)
{
- char *prefixed_path;
-
ensure_core_worktree(update_data->sm_path);
- if (update_data->recursive_prefix)
- prefixed_path = xstrfmt("%s%s", update_data->recursive_prefix,
- update_data->sm_path);
- else
- prefixed_path = xstrdup(update_data->sm_path);
-
- update_data->displaypath = get_submodule_displaypath(prefixed_path,
- update_data->prefix);
- free(prefixed_path);
+ update_data->displaypath = get_submodule_displaypath(
+ update_data->sm_path, update_data->prefix);
determine_submodule_update_strategy(the_repository, update_data->just_cloned,
update_data->sm_path, update_data->update_default,
@@ -2504,14 +2495,6 @@ static int update_submodule(struct update_data *update_data)
struct update_data next = *update_data;
int res;
- if (update_data->recursive_prefix)
- prefixed_path = xstrfmt("%s%s/", update_data->recursive_prefix,
- update_data->sm_path);
- else
- prefixed_path = xstrfmt("%s/", update_data->sm_path);
-
- next.recursive_prefix = get_submodule_displaypath(prefixed_path,
- update_data->prefix);
next.prefix = NULL;
oidcpy(&next.oid, null_oid());
oidcpy(&next.suboid, null_oid());
@@ -2596,13 +2579,15 @@ static int module_update(int argc, const char **argv, const char *prefix)
OPT_STRING(0, "prefix", &opt.prefix,
N_("path"),
N_("path into the working tree")),
- OPT_STRING(0, "recursive-prefix", &opt.recursive_prefix,
- N_("path"),
- N_("path into the working tree, across nested "
- "submodule boundaries")),
- OPT_STRING(0, "update", &opt.update_default,
- N_("string"),
- N_("rebase, merge, checkout or none")),
+ OPT_SET_INT(0, "checkout", &opt.update_default,
+ N_("use the 'checkout' update strategy (default)"),
+ SM_UPDATE_CHECKOUT),
+ OPT_SET_INT('m', "merge", &opt.update_default,
+ N_("use the 'merge' update strategy"),
+ SM_UPDATE_MERGE),
+ OPT_SET_INT('r', "rebase", &opt.update_default,
+ N_("use the 'rebase' update strategy"),
+ SM_UPDATE_REBASE),
OPT_STRING_LIST(0, "reference", &opt.references, N_("repo"),
N_("reference repository")),
OPT_BOOL(0, "dissociate", &opt.dissociate,
@@ -2618,7 +2603,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
OPT_BOOL(0, "progress", &opt.progress,
N_("force cloning progress")),
OPT_BOOL(0, "require-init", &opt.require_init,
- N_("disallow cloning into non-empty directory")),
+ N_("disallow cloning into non-empty directory, implies --init")),
OPT_BOOL(0, "single-branch", &opt.single_branch,
N_("clone only one branch, HEAD or --branch")),
OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
@@ -2642,6 +2627,9 @@ static int module_update(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, module_update_options,
git_submodule_helper_usage, 0);
+ if (opt.require_init)
+ opt.init = 1;
+
if (filter_options.choice && !opt.init) {
usage_with_options(git_submodule_helper_usage,
module_update_options);
@@ -2650,9 +2638,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
opt.filter_options = &filter_options;
if (opt.update_default)
- if (parse_submodule_update_strategy(opt.update_default,
- &opt.update_strategy) < 0)
- die(_("bad value for update parameter"));
+ opt.update_strategy.type = opt.update_default;
if (module_list_compute(argc, argv, prefix, &pathspec, &opt.list) < 0) {
list_objects_filter_release(&filter_options);
@@ -2678,7 +2664,6 @@ static int module_update(int argc, const char **argv, const char *prefix)
module_list_active(&list);
info.prefix = opt.prefix;
- info.superprefix = opt.recursive_prefix;
if (opt.quiet)
info.flags |= OPT_QUIET;
@@ -2784,7 +2769,7 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
};
const char *const git_submodule_helper_usage[] = {
- N_("git submodule--helper absorb-git-dirs [<options>] [<path>...]"),
+ N_("git submodule absorbgitdirs [<options>] [<path>...]"),
NULL
};
@@ -2889,7 +2874,7 @@ static int module_set_url(int argc, const char **argv, const char *prefix)
OPT_END()
};
const char *const usage[] = {
- N_("git submodule--helper set-url [--quiet] <path> <newurl>"),
+ N_("git submodule set-url [--quiet] <path> <newurl>"),
NULL
};
@@ -2928,8 +2913,8 @@ static int module_set_branch(int argc, const char **argv, const char *prefix)
OPT_END()
};
const char *const usage[] = {
- N_("git submodule--helper set-branch [-q|--quiet] (-d|--default) <path>"),
- N_("git submodule--helper set-branch [-q|--quiet] (-b|--branch) <branch> <path>"),
+ N_("git submodule set-branch [-q|--quiet] (-d|--default) <path>"),
+ N_("git submodule set-branch [-q|--quiet] (-b|--branch) <branch> <path>"),
NULL
};
@@ -3273,7 +3258,7 @@ static int module_add(int argc, const char **argv, const char *prefix)
};
const char *const usage[] = {
- N_("git submodule--helper add [<options>] [--] <repository> [<path>]"),
+ N_("git submodule add [<options>] [--] <repository> [<path>]"),
NULL
};
@@ -3375,18 +3360,18 @@ struct cmd_struct {
static struct cmd_struct commands[] = {
{"list", module_list, 0},
{"name", module_name, 0},
- {"clone", module_clone, 0},
- {"add", module_add, SUPPORT_SUPER_PREFIX},
- {"update", module_update, 0},
+ {"clone", module_clone, SUPPORT_SUPER_PREFIX},
+ {"add", module_add, 0},
+ {"update", module_update, SUPPORT_SUPER_PREFIX},
{"resolve-relative-url-test", resolve_relative_url_test, 0},
{"foreach", module_foreach, SUPPORT_SUPER_PREFIX},
- {"init", module_init, SUPPORT_SUPER_PREFIX},
+ {"init", module_init, 0},
{"status", module_status, SUPPORT_SUPER_PREFIX},
{"sync", module_sync, SUPPORT_SUPER_PREFIX},
{"deinit", module_deinit, 0},
- {"summary", module_summary, SUPPORT_SUPER_PREFIX},
+ {"summary", module_summary, 0},
{"push-check", push_check, 0},
- {"absorb-git-dirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
+ {"absorbgitdirs", absorb_git_dirs, SUPPORT_SUPER_PREFIX},
{"is-active", is_active, 0},
{"check-name", check_name, 0},
{"config", module_config, 0},
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 56d05e2..43789b8 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -97,15 +97,27 @@ static void use(int bytes)
display_throughput(progress, consumed_bytes);
}
+/*
+ * Decompress zstream from the standard input into a newly
+ * allocated buffer of specified size and return the buffer.
+ * The caller is responsible to free the returned buffer.
+ *
+ * But for dry_run mode, "get_data()" is only used to check the
+ * integrity of data, and the returned buffer is not used at all.
+ * Therefore, in dry_run mode, "get_data()" will release the small
+ * allocated buffer which is reused to hold temporary zstream output
+ * and return NULL instead of returning garbage data.
+ */
static void *get_data(unsigned long size)
{
git_zstream stream;
- void *buf = xmallocz(size);
+ unsigned long bufsize = dry_run && size > 8192 ? 8192 : size;
+ void *buf = xmallocz(bufsize);
memset(&stream, 0, sizeof(stream));
stream.next_out = buf;
- stream.avail_out = size;
+ stream.avail_out = bufsize;
stream.next_in = fill(1);
stream.avail_in = len;
git_inflate_init(&stream);
@@ -125,8 +137,17 @@ static void *get_data(unsigned long size)
}
stream.next_in = fill(1);
stream.avail_in = len;
+ if (dry_run) {
+ /* reuse the buffer in dry_run mode */
+ stream.next_out = buf;
+ stream.avail_out = bufsize > size - stream.total_out ?
+ size - stream.total_out :
+ bufsize;
+ }
}
git_inflate_end(&stream);
+ if (dry_run)
+ FREE_AND_NULL(buf);
return buf;
}
@@ -326,10 +347,70 @@ static void unpack_non_delta_entry(enum object_type type, unsigned long size,
{
void *buf = get_data(size);
- if (!dry_run && buf)
+ if (buf)
write_object(nr, type, buf, size);
- else
- free(buf);
+}
+
+struct input_zstream_data {
+ git_zstream *zstream;
+ unsigned char buf[8192];
+ int status;
+};
+
+static const void *feed_input_zstream(struct input_stream *in_stream,
+ unsigned long *readlen)
+{
+ struct input_zstream_data *data = in_stream->data;
+ git_zstream *zstream = data->zstream;
+ void *in = fill(1);
+
+ if (in_stream->is_finished) {
+ *readlen = 0;
+ return NULL;
+ }
+
+ zstream->next_out = data->buf;
+ zstream->avail_out = sizeof(data->buf);
+ zstream->next_in = in;
+ zstream->avail_in = len;
+
+ data->status = git_inflate(zstream, 0);
+
+ in_stream->is_finished = data->status != Z_OK;
+ use(len - zstream->avail_in);
+ *readlen = sizeof(data->buf) - zstream->avail_out;
+
+ return data->buf;
+}
+
+static void stream_blob(unsigned long size, unsigned nr)
+{
+ git_zstream zstream = { 0 };
+ struct input_zstream_data data = { 0 };
+ struct input_stream in_stream = {
+ .read = feed_input_zstream,
+ .data = &data,
+ };
+ struct obj_info *info = &obj_list[nr];
+
+ data.zstream = &zstream;
+ git_inflate_init(&zstream);
+
+ if (stream_loose_object(&in_stream, size, &info->oid))
+ die(_("failed to write object in stream"));
+
+ if (data.status != Z_STREAM_END)
+ die(_("inflate returned (%d)"), data.status);
+ git_inflate_end(&zstream);
+
+ if (strict) {
+ struct blob *blob = lookup_blob(the_repository, &info->oid);
+
+ if (!blob)
+ die(_("invalid blob object from stream"));
+ blob->object.flags |= FLAG_WRITTEN;
+ }
+ info->obj = NULL;
}
static int resolve_against_held(unsigned nr, const struct object_id *base,
@@ -359,10 +440,8 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
oidread(&base_oid, fill(the_hash_algo->rawsz));
use(the_hash_algo->rawsz);
delta_data = get_data(delta_size);
- if (dry_run || !delta_data) {
- free(delta_data);
+ if (!delta_data)
return;
- }
if (has_object_file(&base_oid))
; /* Ok we have this one */
else if (resolve_against_held(nr, &base_oid,
@@ -398,10 +477,8 @@ static void unpack_delta_entry(enum object_type type, unsigned long delta_size,
die("offset value out of bound for delta base object");
delta_data = get_data(delta_size);
- if (dry_run || !delta_data) {
- free(delta_data);
+ if (!delta_data)
return;
- }
lo = 0;
hi = nr;
while (lo < hi) {
@@ -468,9 +545,14 @@ static void unpack_one(unsigned nr)
}
switch (type) {
+ case OBJ_BLOB:
+ if (!dry_run && size > big_file_threshold) {
+ stream_blob(size, nr);
+ return;
+ }
+ /* fallthrough */
case OBJ_COMMIT:
case OBJ_TREE:
- case OBJ_BLOB:
case OBJ_TAG:
unpack_non_delta_entry(type, size, nr);
return;
diff --git a/cache-tree.c b/cache-tree.c
index ff794d9..56db0b5 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -101,33 +101,6 @@ struct cache_tree_sub *cache_tree_sub(struct cache_tree *it, const char *path)
return find_subtree(it, path, pathlen, 1);
}
-struct cache_tree *cache_tree_find_path(struct cache_tree *it, const char *path)
-{
- const char *slash;
- int namelen;
- struct cache_tree_sub it_sub = {
- .cache_tree = it,
- };
- struct cache_tree_sub *down = &it_sub;
-
- while (down) {
- slash = strchrnul(path, '/');
- namelen = slash - path;
- down->cache_tree->entry_count = -1;
- if (!*slash) {
- int pos;
- pos = cache_tree_subtree_pos(down->cache_tree, path, namelen);
- if (0 <= pos)
- return down->cache_tree->down[pos]->cache_tree;
- return NULL;
- }
- down = find_subtree(it, path, namelen, 0);
- path = slash + 1;
- }
-
- return NULL;
-}
-
static int do_invalidate_path(struct cache_tree *it, const char *path)
{
/* a/b/c
diff --git a/cache-tree.h b/cache-tree.h
index f75f8e7..8efecce 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -29,8 +29,6 @@ struct cache_tree_sub *cache_tree_sub(struct cache_tree *, const char *);
int cache_tree_subtree_pos(struct cache_tree *it, const char *path, int pathlen);
-struct cache_tree *cache_tree_find_path(struct cache_tree *it, const char *path);
-
void cache_tree_write(struct strbuf *, struct cache_tree *root);
struct cache_tree *cache_tree_read(const char *buffer, unsigned long size);
diff --git a/ci/lib.sh b/ci/lib.sh
index 2f6d9d2..f095519 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -29,8 +29,14 @@ else
set +x
begin_group "$1"
shift
- "$@"
- res=$?
+ # work around `dash` not supporting `set -o pipefail`
+ (
+ "$@" 2>&1
+ echo $? >exit.status
+ ) |
+ sed 's/^\(\([^ ]*\):\([0-9]*\):\([0-9]*:\) \)\(error\|warning\): /::\5 file=\2,line=\3::\1/'
+ res=$(cat exit.status)
+ rm exit.status
end_group
return $res
}
@@ -177,7 +183,8 @@ then
test_name="${test_exit%.exit}"
test_name="${test_name##*/}"
printf "\\e[33m\\e[1m=== Failed test: ${test_name} ===\\e[m\\n"
- echo "The full logs are in the artifacts attached to this run."
+ echo "The full logs are in the 'print test failures' step below."
+ echo "See also the 'failed-tests-*' artifacts attached to this run."
cat "t/test-results/$test_name.markup"
trash_dir="t/trash directory.$test_name"
diff --git a/ci/make-test-artifacts.sh b/ci/make-test-artifacts.sh
index 6469674..74141af 100755
--- a/ci/make-test-artifacts.sh
+++ b/ci/make-test-artifacts.sh
@@ -7,6 +7,6 @@ mkdir -p "$1" # in case ci/lib.sh decides to quit early
. ${0%/*}/lib.sh
-make artifacts-tar ARTIFACTS_DIRECTORY="$1"
+group Build make artifacts-tar ARTIFACTS_DIRECTORY="$1"
check_unignored_build_artifacts
diff --git a/combine-diff.c b/combine-diff.c
index b724f02..b0ece95 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -1498,6 +1498,13 @@ void diff_tree_combined(const struct object_id *oid,
int i, num_paths, needsep, show_log_first, num_parent = parents->nr;
int need_generic_pathscan;
+ if (opt->ignore_regex_nr)
+ die("combined diff and '%s' cannot be used together",
+ "--ignore-matching-lines");
+ if (opt->close_file)
+ die("combined diff and '%s' cannot be used together",
+ "--output");
+
/* nothing to do, if no parents */
if (!num_parent)
return;
diff --git a/commit-graph.c b/commit-graph.c
index 92d4503..f2a3603 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -252,7 +252,8 @@ struct commit_graph *load_commit_graph_one_fd_st(struct repository *r,
}
graph_map = xmmap(NULL, graph_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
- ret = parse_commit_graph(r, graph_map, graph_size);
+ prepare_repo_settings(r);
+ ret = parse_commit_graph(&r->settings, graph_map, graph_size);
if (ret)
ret->odb = odb;
@@ -321,7 +322,7 @@ static int graph_read_bloom_data(const unsigned char *chunk_start,
return 0;
}
-struct commit_graph *parse_commit_graph(struct repository *r,
+struct commit_graph *parse_commit_graph(struct repo_settings *s,
void *graph_map, size_t graph_size)
{
const unsigned char *data;
@@ -359,8 +360,6 @@ struct commit_graph *parse_commit_graph(struct repository *r,
return NULL;
}
- prepare_repo_settings(r);
-
graph = alloc_commit_graph();
graph->hash_len = the_hash_algo->rawsz;
@@ -390,7 +389,7 @@ struct commit_graph *parse_commit_graph(struct repository *r,
pair_chunk(cf, GRAPH_CHUNKID_EXTRAEDGES, &graph->chunk_extra_edges);
pair_chunk(cf, GRAPH_CHUNKID_BASE, &graph->chunk_base_graphs);
- if (get_configured_generation_version(r) >= 2) {
+ if (s->commit_graph_generation_version >= 2) {
pair_chunk(cf, GRAPH_CHUNKID_GENERATION_DATA,
&graph->chunk_generation_data);
pair_chunk(cf, GRAPH_CHUNKID_GENERATION_DATA_OVERFLOW,
@@ -400,7 +399,7 @@ struct commit_graph *parse_commit_graph(struct repository *r,
graph->read_generation_data = 1;
}
- if (r->settings.commit_graph_read_changed_paths) {
+ if (s->commit_graph_read_changed_paths) {
pair_chunk(cf, GRAPH_CHUNKID_BLOOMINDEXES,
&graph->chunk_bloom_indexes);
read_chunk(cf, GRAPH_CHUNKID_BLOOMDATA,
@@ -889,6 +888,14 @@ static int find_commit_pos_in_graph(struct commit *item, struct commit_graph *g,
}
}
+int repo_find_commit_pos_in_graph(struct repository *r, struct commit *c,
+ uint32_t *pos)
+{
+ if (!prepare_commit_graph(r))
+ return 0;
+ return find_commit_pos_in_graph(c, r->objects->commit_graph, pos);
+}
+
struct commit *lookup_commit_in_graph(struct repository *repo, const struct object_id *id)
{
struct commit *commit;
@@ -898,7 +905,7 @@ struct commit *lookup_commit_in_graph(struct repository *repo, const struct obje
return NULL;
if (!search_commit_pos_in_graph(id, repo->objects->commit_graph, &pos))
return NULL;
- if (!repo_has_object_file(repo, id))
+ if (!has_object(repo, id, 0))
return NULL;
commit = lookup_commit(repo, id);
@@ -946,9 +953,7 @@ int parse_commit_in_graph(struct repository *r, struct commit *item)
void load_commit_graph_info(struct repository *r, struct commit *item)
{
uint32_t pos;
- if (!prepare_commit_graph(r))
- return;
- if (find_commit_pos_in_graph(item, r->objects->commit_graph, &pos))
+ if (repo_find_commit_pos_in_graph(r, item, &pos))
fill_commit_graph_info(item, r->objects->commit_graph, pos);
}
diff --git a/commit-graph.h b/commit-graph.h
index 2e3ac35..37faee6 100644
--- a/commit-graph.h
+++ b/commit-graph.h
@@ -41,6 +41,21 @@ int open_commit_graph(const char *graph_file, int *fd, struct stat *st);
int parse_commit_in_graph(struct repository *r, struct commit *item);
/*
+ * Fills `*pos` with the graph position of `c`, and returns 1 if `c` is
+ * found in the commit-graph belonging to `r`, or 0 otherwise.
+ * Initializes the commit-graph belonging to `r` if it hasn't been
+ * already.
+ *
+ * Note: this is a low-level helper that does not alter any slab data
+ * associated with `c`. Useful in circumstances where the slab data is
+ * already being modified (e.g., writing the commit-graph itself).
+ *
+ * In most cases, callers should use `parse_commit_in_graph()` instead.
+ */
+int repo_find_commit_pos_in_graph(struct repository *r, struct commit *c,
+ uint32_t *pos);
+
+/*
* Look up the given commit ID in the commit-graph. This will only return a
* commit if the ID exists both in the graph and in the object database such
* that we don't return commits whose object has been pruned. Otherwise, this
@@ -93,7 +108,12 @@ struct commit_graph *load_commit_graph_one_fd_st(struct repository *r,
struct object_directory *odb);
struct commit_graph *read_commit_graph_one(struct repository *r,
struct object_directory *odb);
-struct commit_graph *parse_commit_graph(struct repository *r,
+
+/*
+ * Callers should initialize the repo_settings with prepare_repo_settings()
+ * prior to calling parse_commit_graph().
+ */
+struct commit_graph *parse_commit_graph(struct repo_settings *s,
void *graph_map, size_t graph_size);
/*
diff --git a/commit.c b/commit.c
index 73865fe..1fb1b2e 100644
--- a/commit.c
+++ b/commit.c
@@ -1526,7 +1526,7 @@ static int verify_utf8(struct strbuf *buf)
static const char commit_utf8_warn[] =
N_("Warning: commit message did not conform to UTF-8.\n"
"You may want to amend it after fixing the message, or set the config\n"
- "variable i18n.commitencoding to the encoding your project uses.\n");
+ "variable i18n.commitEncoding to the encoding your project uses.\n");
int commit_tree_extended(const char *msg, size_t msg_len,
const struct object_id *tree,
diff --git a/compat/mingw.c b/compat/mingw.c
index 2607de9..b550299 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -1059,10 +1059,7 @@ char *mingw_mktemp(char *template)
int mkstemp(char *template)
{
- char *filename = mktemp(template);
- if (!filename)
- return -1;
- return open(filename, O_RDWR | O_CREAT, 0600);
+ return git_mkstemp_mode(template, 0600);
}
int gettimeofday(struct timeval *tv, void *tz)
diff --git a/compat/win32/syslog.c b/compat/win32/syslog.c
index 1f8d893..0af18d8 100644
--- a/compat/win32/syslog.c
+++ b/compat/win32/syslog.c
@@ -44,6 +44,7 @@ void syslog(int priority, const char *fmt, ...)
while ((pos = strstr(str, "%1")) != NULL) {
size_t offset = pos - str;
+ char *new_pos;
char *oldstr = str;
str = realloc(str, st_add(++str_len, 1));
if (!str) {
@@ -51,9 +52,9 @@ void syslog(int priority, const char *fmt, ...)
warning_errno("realloc failed");
return;
}
- pos = str + offset;
- memmove(pos + 2, pos + 1, strlen(pos));
- pos[1] = ' ';
+ new_pos = str + offset;
+ memmove(new_pos + 2, new_pos + 1, strlen(new_pos));
+ new_pos[1] = ' ';
}
switch (priority) {
diff --git a/config.c b/config.c
index 9b0e9c9..015bec3 100644
--- a/config.c
+++ b/config.c
@@ -81,6 +81,17 @@ static enum config_scope current_parsing_scope;
static int pack_compression_seen;
static int zlib_compression_seen;
+/*
+ * Config that comes from trusted scopes, namely:
+ * - CONFIG_SCOPE_SYSTEM (e.g. /etc/gitconfig)
+ * - CONFIG_SCOPE_GLOBAL (e.g. $HOME/.gitconfig, $XDG_CONFIG_HOME/git)
+ * - CONFIG_SCOPE_COMMAND (e.g. "-c" option, environment variables)
+ *
+ * This is declared here for code cleanliness, but unlike the other
+ * static variables, this does not hold config parser state.
+ */
+static struct config_set protected_config;
+
static int config_file_fgetc(struct config_source *conf)
{
return getc_unlocked(conf->u.file);
@@ -2378,6 +2389,11 @@ int git_configset_add_file(struct config_set *cs, const char *filename)
return git_config_from_file(config_set_callback, filename, cs);
}
+int git_configset_add_parameters(struct config_set *cs)
+{
+ return git_config_from_parameters(config_set_callback, cs);
+}
+
int git_configset_get_value(struct config_set *cs, const char *key, const char **value)
{
const struct string_list *values = NULL;
@@ -2619,6 +2635,33 @@ int repo_config_get_pathname(struct repository *repo,
return ret;
}
+/* Read values into protected_config. */
+static void read_protected_config(void)
+{
+ char *xdg_config = NULL, *user_config = NULL, *system_config = NULL;
+
+ git_configset_init(&protected_config);
+
+ system_config = git_system_config();
+ git_global_config(&user_config, &xdg_config);
+
+ git_configset_add_file(&protected_config, system_config);
+ git_configset_add_file(&protected_config, xdg_config);
+ git_configset_add_file(&protected_config, user_config);
+ git_configset_add_parameters(&protected_config);
+
+ free(system_config);
+ free(xdg_config);
+ free(user_config);
+}
+
+void git_protected_config(config_fn_t fn, void *data)
+{
+ if (!protected_config.hash_initialized)
+ read_protected_config();
+ configset_iter(&protected_config, fn, data);
+}
+
/* Functions used historically to read configuration from 'the_repository' */
void git_config(config_fn_t fn, void *data)
{
diff --git a/config.h b/config.h
index 7654f61..ca994d7 100644
--- a/config.h
+++ b/config.h
@@ -447,6 +447,15 @@ void git_configset_init(struct config_set *cs);
int git_configset_add_file(struct config_set *cs, const char *filename);
/**
+ * Parses command line options and environment variables, and adds the
+ * variable-value pairs to the `config_set`. Returns 0 on success, or -1
+ * if there is an error in parsing. The caller decides whether to free
+ * the incomplete configset or continue using it when the function
+ * returns -1.
+ */
+int git_configset_add_parameters(struct config_set *cs);
+
+/**
* Finds and returns the value list, sorted in order of increasing priority
* for the configuration variable `key` and config set `cs`. When the
* configuration variable `key` is not found, returns NULL. The caller
@@ -505,6 +514,13 @@ int repo_config_get_maybe_bool(struct repository *repo,
int repo_config_get_pathname(struct repository *repo,
const char *key, const char **dest);
+/*
+ * Functions for reading protected config. By definition, protected
+ * config ignores repository config, so these do not take a `struct
+ * repository` parameter.
+ */
+void git_protected_config(config_fn_t fn, void *data);
+
/**
* Querying For Specific Variables
* -------------------------------
diff --git a/contrib/coccinelle/array.cocci b/contrib/coccinelle/array.cocci
index 9a4f00c..aa75937 100644
--- a/contrib/coccinelle/array.cocci
+++ b/contrib/coccinelle/array.cocci
@@ -1,60 +1,58 @@
@@
-expression dst, src, n, E;
+type T;
+T *dst_ptr;
+T *src_ptr;
+expression n;
@@
- memcpy(dst, src, n * sizeof(
-- E[...]
-+ *(E)
- ))
+- memcpy(dst_ptr, src_ptr, (n) * \( sizeof(T)
+- \| sizeof(*(dst_ptr))
+- \| sizeof(*(src_ptr))
+- \| sizeof(dst_ptr[...])
+- \| sizeof(src_ptr[...])
+- \) )
++ COPY_ARRAY(dst_ptr, src_ptr, n)
@@
type T;
-T *ptr;
-T[] arr;
-expression E, n;
+T *dst_ptr;
+T[] src_arr;
+expression n;
@@
-(
- memcpy(ptr, E,
-- n * sizeof(*(ptr))
-+ n * sizeof(T)
- )
-|
- memcpy(arr, E,
-- n * sizeof(*(arr))
-+ n * sizeof(T)
- )
-|
- memcpy(E, ptr,
-- n * sizeof(*(ptr))
-+ n * sizeof(T)
- )
-|
- memcpy(E, arr,
-- n * sizeof(*(arr))
-+ n * sizeof(T)
- )
-)
+- memcpy(dst_ptr, src_arr, (n) * \( sizeof(T)
+- \| sizeof(*(dst_ptr))
+- \| sizeof(*(src_arr))
+- \| sizeof(dst_ptr[...])
+- \| sizeof(src_arr[...])
+- \) )
++ COPY_ARRAY(dst_ptr, src_arr, n)
@@
type T;
-T *dst_ptr;
+T[] dst_arr;
T *src_ptr;
+expression n;
+@@
+- memcpy(dst_arr, src_ptr, (n) * \( sizeof(T)
+- \| sizeof(*(dst_arr))
+- \| sizeof(*(src_ptr))
+- \| sizeof(dst_arr[...])
+- \| sizeof(src_ptr[...])
+- \) )
++ COPY_ARRAY(dst_arr, src_ptr, n)
+
+@@
+type T;
T[] dst_arr;
T[] src_arr;
expression n;
@@
-(
-- memcpy(dst_ptr, src_ptr, (n) * sizeof(T))
-+ COPY_ARRAY(dst_ptr, src_ptr, n)
-|
-- memcpy(dst_ptr, src_arr, (n) * sizeof(T))
-+ COPY_ARRAY(dst_ptr, src_arr, n)
-|
-- memcpy(dst_arr, src_ptr, (n) * sizeof(T))
-+ COPY_ARRAY(dst_arr, src_ptr, n)
-|
-- memcpy(dst_arr, src_arr, (n) * sizeof(T))
+- memcpy(dst_arr, src_arr, (n) * \( sizeof(T)
+- \| sizeof(*(dst_arr))
+- \| sizeof(*(src_arr))
+- \| sizeof(dst_arr[...])
+- \| sizeof(src_arr[...])
+- \) )
+ COPY_ARRAY(dst_arr, src_arr, n)
-)
@@
type T;
diff --git a/contrib/coccinelle/object_id.cocci b/contrib/coccinelle/object_id.cocci
index ddf4f22..01f8d69 100644
--- a/contrib/coccinelle/object_id.cocci
+++ b/contrib/coccinelle/object_id.cocci
@@ -1,18 +1,6 @@
@@
struct object_id OID;
@@
-- is_null_sha1(OID.hash)
-+ is_null_oid(&OID)
-
-@@
-struct object_id *OIDPTR;
-@@
-- is_null_sha1(OIDPTR->hash)
-+ is_null_oid(OIDPTR)
-
-@@
-struct object_id OID;
-@@
- hashclr(OID.hash)
+ oidclr(&OID)
diff --git a/contrib/coccinelle/tests/free.c b/contrib/coccinelle/tests/free.c
new file mode 100644
index 0000000..96d4abc
--- /dev/null
+++ b/contrib/coccinelle/tests/free.c
@@ -0,0 +1,11 @@
+int use_FREE_AND_NULL(int *v)
+{
+ free(*v);
+ *v = NULL;
+}
+
+int need_no_if(int *v)
+{
+ if (v)
+ free(v);
+}
diff --git a/contrib/coccinelle/tests/free.res b/contrib/coccinelle/tests/free.res
new file mode 100644
index 0000000..f90fd9f
--- /dev/null
+++ b/contrib/coccinelle/tests/free.res
@@ -0,0 +1,9 @@
+int use_FREE_AND_NULL(int *v)
+{
+ FREE_AND_NULL(*v);
+}
+
+int need_no_if(int *v)
+{
+ free(v);
+}
diff --git a/contrib/coccinelle/tests/unused.c b/contrib/coccinelle/tests/unused.c
new file mode 100644
index 0000000..8294d73
--- /dev/null
+++ b/contrib/coccinelle/tests/unused.c
@@ -0,0 +1,82 @@
+void test_strbuf(void)
+{
+ struct strbuf sb1 = STRBUF_INIT;
+ struct strbuf sb2 = STRBUF_INIT;
+ struct strbuf sb3 = STRBUF_INIT;
+ struct strbuf sb4 = STRBUF_INIT;
+ struct strbuf sb5;
+ struct strbuf sb6 = { 0 };
+ struct strbuf sb7 = STRBUF_INIT;
+ struct strbuf sb8 = STRBUF_INIT;
+ struct strbuf *sp1;
+ struct strbuf *sp2;
+ struct strbuf *sp3;
+ struct strbuf *sp4 = xmalloc(sizeof(struct strbuf));
+ struct strbuf *sp5 = xmalloc(sizeof(struct strbuf));
+ struct strbuf *sp6 = xmalloc(sizeof(struct strbuf));
+ struct strbuf *sp7;
+
+ strbuf_init(&sb5, 0);
+ strbuf_init(sp1, 0);
+ strbuf_init(sp2, 0);
+ strbuf_init(sp3, 0);
+ strbuf_init(sp4, 0);
+ strbuf_init(sp5, 0);
+ strbuf_init(sp6, 0);
+ strbuf_init(sp7, 0);
+ sp7 = xmalloc(sizeof(struct strbuf));
+
+ use_before(&sb3);
+ use_as_str("%s", sb7.buf);
+ use_as_str("%s", sp1->buf);
+ use_as_str("%s", sp6->buf);
+ pass_pp(&sp3);
+
+ strbuf_release(&sb1);
+ strbuf_reset(&sb2);
+ strbuf_release(&sb3);
+ strbuf_release(&sb4);
+ strbuf_release(&sb5);
+ strbuf_release(&sb6);
+ strbuf_release(&sb7);
+ strbuf_release(sp1);
+ strbuf_release(sp2);
+ strbuf_release(sp3);
+ strbuf_release(sp4);
+ strbuf_release(sp5);
+ strbuf_release(sp6);
+ strbuf_release(sp7);
+
+ use_after(&sb4);
+
+ if (when_strict())
+ return;
+ strbuf_release(&sb8);
+}
+
+void test_other(void)
+{
+ struct string_list l = STRING_LIST_INIT_DUP;
+ struct strbuf sb = STRBUF_INIT;
+
+ string_list_clear(&l, 0);
+ string_list_clear(&sb, 0);
+}
+
+void test_worktrees(void)
+{
+ struct worktree **w1 = get_worktrees();
+ struct worktree **w2 = get_worktrees();
+ struct worktree **w3;
+ struct worktree **w4;
+
+ w3 = get_worktrees();
+ w4 = get_worktrees();
+
+ use_it(w4);
+
+ free_worktrees(w1);
+ free_worktrees(w2);
+ free_worktrees(w3);
+ free_worktrees(w4);
+}
diff --git a/contrib/coccinelle/tests/unused.res b/contrib/coccinelle/tests/unused.res
new file mode 100644
index 0000000..6d3e745
--- /dev/null
+++ b/contrib/coccinelle/tests/unused.res
@@ -0,0 +1,45 @@
+void test_strbuf(void)
+{
+ struct strbuf sb3 = STRBUF_INIT;
+ struct strbuf sb4 = STRBUF_INIT;
+ struct strbuf sb7 = STRBUF_INIT;
+ struct strbuf *sp1;
+ struct strbuf *sp3;
+ struct strbuf *sp6 = xmalloc(sizeof(struct strbuf));
+ strbuf_init(sp1, 0);
+ strbuf_init(sp3, 0);
+ strbuf_init(sp6, 0);
+
+ use_before(&sb3);
+ use_as_str("%s", sb7.buf);
+ use_as_str("%s", sp1->buf);
+ use_as_str("%s", sp6->buf);
+ pass_pp(&sp3);
+
+ strbuf_release(&sb3);
+ strbuf_release(&sb4);
+ strbuf_release(&sb7);
+ strbuf_release(sp1);
+ strbuf_release(sp3);
+ strbuf_release(sp6);
+
+ use_after(&sb4);
+
+ if (when_strict())
+ return;
+}
+
+void test_other(void)
+{
+}
+
+void test_worktrees(void)
+{
+ struct worktree **w4;
+
+ w4 = get_worktrees();
+
+ use_it(w4);
+
+ free_worktrees(w4);
+}
diff --git a/contrib/coccinelle/unused.cocci b/contrib/coccinelle/unused.cocci
new file mode 100644
index 0000000..d84046f
--- /dev/null
+++ b/contrib/coccinelle/unused.cocci
@@ -0,0 +1,43 @@
+// This rule finds sequences of "unused" declerations and uses of a
+// variable, where "unused" is defined to include only calling the
+// equivalent of alloc, init & free functions on the variable.
+@@
+type T;
+identifier I;
+// STRBUF_INIT, but also e.g. STRING_LIST_INIT_DUP (so no anchoring)
+constant INIT_MACRO =~ "_INIT";
+identifier MALLOC1 =~ "^x?[mc]alloc$";
+identifier INIT_ASSIGN1 =~ "^get_worktrees$";
+identifier INIT_CALL1 =~ "^[a-z_]*_init$";
+identifier REL1 =~ "^[a-z_]*_(release|reset|clear|free)$";
+identifier REL2 =~ "^(release|clear|free)_[a-z_]*$";
+@@
+
+(
+- T I;
+|
+- T I = { 0 };
+|
+- T I = INIT_MACRO;
+|
+- T I = MALLOC1(...);
+|
+- T I = INIT_ASSIGN1(...);
+)
+
+<... when != \( I \| &I \)
+(
+- \( INIT_CALL1 \)( \( I \| &I \), ...);
+|
+- I = \( INIT_ASSIGN1 \)(...);
+|
+- I = MALLOC1(...);
+)
+...>
+
+(
+- \( REL1 \| REL2 \)( \( I \| &I \), ...);
+|
+- \( REL1 \| REL2 \)( \( &I \| I \) );
+)
+ ... when != \( I \| &I \)
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 87b2b91..1435548 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -245,7 +245,8 @@ __git_ps1_show_upstream ()
# Helper function that is meant to be called from __git_ps1. It
# injects color codes into the appropriate gitstring variables used
-# to build a gitstring.
+# to build a gitstring. Colored variables are responsible for clearing
+# their own color.
__git_ps1_colorize_gitstring ()
{
if [[ -n ${ZSH_VERSION-} ]]; then
@@ -271,22 +272,23 @@ __git_ps1_colorize_gitstring ()
else
branch_color="$bad_color"
fi
- c="$branch_color$c"
+ if [ -n "$c" ]; then
+ c="$branch_color$c$c_clear"
+ fi
+ b="$branch_color$b$c_clear"
- z="$c_clear$z"
- if [ "$w" = "*" ]; then
- w="$bad_color$w"
+ if [ -n "$w" ]; then
+ w="$bad_color$w$c_clear"
fi
if [ -n "$i" ]; then
- i="$ok_color$i"
+ i="$ok_color$i$c_clear"
fi
if [ -n "$s" ]; then
- s="$flags_color$s"
+ s="$flags_color$s$c_clear"
fi
if [ -n "$u" ]; then
- u="$bad_color$u"
+ u="$bad_color$u$c_clear"
fi
- r="$c_clear$r"
}
# Helper function to read the first line of a file into a variable.
@@ -556,6 +558,12 @@ __git_ps1 ()
local z="${GIT_PS1_STATESEPARATOR-" "}"
+ b=${b##refs/heads/}
+ if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then
+ __git_ps1_branch_name=$b
+ b="\${__git_ps1_branch_name}"
+ fi
+
# NO color option unless in PROMPT_COMMAND mode or it's Zsh
if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
if [ $pcmode = yes ] || [ -n "${ZSH_VERSION-}" ]; then
@@ -563,12 +571,6 @@ __git_ps1 ()
fi
fi
- b=${b##refs/heads/}
- if [ $pcmode = yes ] && [ $ps1_expanded = yes ]; then
- __git_ps1_branch_name=$b
- b="\${__git_ps1_branch_name}"
- fi
-
local f="$h$w$i$s$u$p"
local gitstring="$c$b${f:+$z$f}${sparse}$r${upstream}"
diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
index 0b44a9b..bf77748 100644
--- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c
+++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
@@ -168,7 +168,7 @@ int main(int argc, const char **argv)
"usage: git credential-osxkeychain <get|store|erase>";
if (!argv[1])
- die(usage);
+ die("%s", usage);
read_credential();
diff --git a/contrib/rerere-train.sh b/contrib/rerere-train.sh
index 26b724c..bd01e43 100755
--- a/contrib/rerere-train.sh
+++ b/contrib/rerere-train.sh
@@ -75,7 +75,7 @@ do
continue
fi
git checkout -q "$parent1^0"
- if git merge $other_parents >/dev/null 2>&1
+ if git merge --no-gpg-sign $other_parents >/dev/null 2>&1
then
# Cleanly merges
continue
diff --git a/contrib/scalar/README.md b/contrib/scalar/README.md
deleted file mode 100644
index 634b577..0000000
--- a/contrib/scalar/README.md
+++ /dev/null
@@ -1,82 +0,0 @@
-# Scalar - an opinionated repository management tool
-
-Scalar is an add-on to Git that helps users take advantage of advanced
-performance features in Git. Originally implemented in C# using .NET Core,
-based on the learnings from the VFS for Git project, most of the techniques
-developed by the Scalar project have been integrated into core Git already:
-
-* partial clone,
-* commit graphs,
-* multi-pack index,
-* sparse checkout (cone mode),
-* scheduled background maintenance,
-* etc
-
-This directory contains the remaining parts of Scalar that are not (yet) in
-core Git.
-
-## Roadmap
-
-The idea is to populate this directory via incremental patch series and
-eventually move to a top-level directory next to `gitk-git/` and to `git-gui/`. The
-current plan involves the following patch series:
-
-- `scalar-the-beginning`: The initial patch series which sets up
- `contrib/scalar/` and populates it with a minimal `scalar` command that
- demonstrates the fundamental ideas.
-
-- `scalar-c-and-C`: The `scalar` command learns about two options that can be
- specified before the command, `-c <key>=<value>` and `-C <directory>`.
-
-- `scalar-diagnose`: The `scalar` command is taught the `diagnose` subcommand.
-
-- `scalar-and-builtin-fsmonitor`: The built-in FSMonitor is enabled in `scalar
- register` and in `scalar clone`, for an enormous performance boost when
- working in large worktrees. This patch series necessarily depends on Jeff
- Hostetler's FSMonitor patch series to be integrated into Git.
-
-- `scalar-gentler-config-locking`: Scalar enlistments are registered in the
- user's Git config. This usually does not represent any problem because it is
- rare for a user to register an enlistment. However, in Scalar's functional
- tests, Scalar enlistments are created galore, and in parallel, which can lead
- to lock contention. This patch series works around that problem by re-trying
- to lock the config file in a gentle fashion.
-
-- `scalar-extra-docs`: Add some extensive documentation that has been written
- in the original Scalar project (all subject to discussion, of course).
-
-- `optionally-install-scalar`: Now that Scalar is feature (and documentation)
- complete and is verified in CI builds, let's offer to install it.
-
-- `move-scalar-to-toplevel`: Now that Scalar is complete, let's move it next to
- `gitk-git/` and to `git-gui/`, making it a top-level command.
-
-The following two patch series exist in Microsoft's fork of Git and are
-publicly available. There is no current plan to upstream them, not because I
-want to withhold these patches, but because I don't think the Git community is
-interested in these patches.
-
-There are some interesting ideas there, but the implementation is too specific
-to Azure Repos and/or VFS for Git to be of much help in general (and also: my
-colleagues tried to upstream some patches already and the enthusiasm for
-integrating things related to Azure Repos and VFS for Git can be summarized in
-very, very few words).
-
-These still exist mainly because the GVFS protocol is what Azure Repos has
-instead of partial clone, while Git is focused on improving partial clone:
-
-- `scalar-with-gvfs`: The primary purpose of this patch series is to support
- existing Scalar users whose repositories are hosted in Azure Repos (which
- does not support Git's partial clones, but supports its predecessor, the GVFS
- protocol, which is used by Scalar to emulate the partial clone).
-
- Since the GVFS protocol will never be supported by core Git, this patch
- series will remain in Microsoft's fork of Git.
-
-- `run-scalar-functional-tests`: The Scalar project developed a quite
- comprehensive set of integration tests (or, "Functional Tests"). They are the
- sole remaining part of the original C#-based Scalar project, and this patch
- adds a GitHub workflow that runs them all.
-
- Since the tests partially depend on features that are only provided in the
- `scalar-with-gvfs` patch series, this patch cannot be upstreamed.
diff --git a/contrib/scalar/scalar.c b/contrib/scalar/scalar.c
index 2817691..97e71fe 100644
--- a/contrib/scalar/scalar.c
+++ b/contrib/scalar/scalar.c
@@ -687,7 +687,7 @@ static int cmd_diagnose(int argc, const char **argv)
int stdout_fd = -1, archiver_fd = -1;
time_t now = time(NULL);
struct tm tm;
- struct strbuf path = STRBUF_INIT, buf = STRBUF_INIT;
+ struct strbuf buf = STRBUF_INIT;
int res = 0;
argc = parse_options(argc, argv, NULL, options,
@@ -779,7 +779,6 @@ diagnose_cleanup:
free(argv_copy);
strvec_clear(&archiver_args);
strbuf_release(&zip_path);
- strbuf_release(&path);
strbuf_release(&buf);
return res;
diff --git a/contrib/scalar/scalar.txt b/contrib/scalar/scalar.txt
index c0425e0..1a12dc4 100644
--- a/contrib/scalar/scalar.txt
+++ b/contrib/scalar/scalar.txt
@@ -3,7 +3,7 @@ scalar(1)
NAME
----
-scalar - an opinionated repository management tool
+scalar - A tool for managing large Git repositories
SYNOPSIS
--------
@@ -20,10 +20,9 @@ scalar delete <enlistment>
DESCRIPTION
-----------
-Scalar is an opinionated repository management tool. By creating new
-repositories or registering existing repositories with Scalar, your Git
-experience will speed up. Scalar sets advanced Git config settings,
-maintains your repositories in the background, and helps reduce data sent
+Scalar is a repository management tool that optimizes Git for use in large
+repositories. Scalar improves performance by configuring advanced Git settings,
+maintaining repositories in the background, and helping to reduce data sent
across the network.
An important Scalar concept is the enlistment: this is the top-level directory
diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index 1af1d96..7562a39 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -50,6 +50,14 @@ m,message= use the given message as the commit message for the merge commit
indent=0
+# Usage: say [MSG...]
+say () {
+ if test -z "$arg_quiet"
+ then
+ printf '%s\n' "$*"
+ fi
+}
+
# Usage: debug [MSG...]
debug () {
if test -n "$arg_debug"
@@ -60,7 +68,7 @@ debug () {
# Usage: progress [MSG...]
progress () {
- if test -z "$GIT_QUIET"
+ if test -z "$arg_quiet"
then
if test -z "$arg_debug"
then
@@ -146,6 +154,7 @@ main () {
eval "$set_args"
# Begin "real" flag parsing.
+ arg_quiet=
arg_debug=
arg_prefix=
arg_split_branch=
@@ -161,7 +170,7 @@ main () {
case "$opt" in
-q)
- GIT_QUIET=1
+ arg_quiet=1
;;
-d)
arg_debug=1
@@ -252,7 +261,7 @@ main () {
dir="$(dirname "$arg_prefix/.")"
debug "command: {$arg_command}"
- debug "quiet: {$GIT_QUIET}"
+ debug "quiet: {$arg_quiet}"
debug "dir: {$dir}"
debug "opts: {$*}"
debug
diff --git a/contrib/vscode/init.sh b/contrib/vscode/init.sh
index f139fd8..521d303 100755
--- a/contrib/vscode/init.sh
+++ b/contrib/vscode/init.sh
@@ -25,8 +25,12 @@ cat >.vscode/settings.json.new <<\EOF ||
"editor.detectIndentation": false,
"editor.insertSpaces": false,
"editor.tabSize": 8,
- "editor.wordWrap": "wordWrapColumn",
- "editor.wordWrapColumn": 80,
+ "files.trimTrailingWhitespace": true
+ },
+ "[txt]": {
+ "editor.detectIndentation": false,
+ "editor.insertSpaces": false,
+ "editor.tabSize": 8,
"files.trimTrailingWhitespace": true
},
"files.associations": {
diff --git a/convert.h b/convert.h
index 5ee1c32..0a6e408 100644
--- a/convert.h
+++ b/convert.h
@@ -53,7 +53,11 @@ struct delayed_checkout {
enum ce_delay_state state;
/* List of filter drivers that signaled delayed blobs. */
struct string_list filters;
- /* List of delayed blobs identified by their path. */
+ /*
+ * List of delayed blobs identified by their path. The `util` member
+ * holds a counter pointer which must be incremented when/if the
+ * associated blob gets checked out.
+ */
struct string_list paths;
};
diff --git a/daemon.c b/daemon.c
index 58f1077..0ae7d12 100644
--- a/daemon.c
+++ b/daemon.c
@@ -279,7 +279,7 @@ static const char *path_ok(const char *directory, struct hostinfo *hi)
/* The validation is done on the paths after enter_repo
* appends optional {.git,.git/.git} and friends, but
* it does not use getcwd(). So if your /pub is
- * a symlink to /mnt/pub, you can whitelist /pub and
+ * a symlink to /mnt/pub, you can include /pub and
* do not have to say /mnt/pub.
* Do not say /pub/.
*/
@@ -298,7 +298,7 @@ static const char *path_ok(const char *directory, struct hostinfo *hi)
return path;
}
- logerror("'%s': not in whitelist", path);
+ logerror("'%s': not in directory list", path);
return NULL; /* Fallthrough. Deny by default */
}
@@ -403,7 +403,7 @@ static int run_service(const char *dir, struct daemon_service *service,
* a "git-daemon-export-ok" flag that says that the other side
* is ok with us doing this.
*
- * path_ok() uses enter_repo() and does whitelist checking.
+ * path_ok() uses enter_repo() and checks for included directories.
* We only need to make sure the repository is exported.
*/
@@ -1444,7 +1444,7 @@ int cmd_main(int argc, const char **argv)
cred = prepare_credentials(user_name, group_name);
if (strict_paths && (!ok_paths || !*ok_paths))
- die("option --strict-paths requires a whitelist");
+ die("option --strict-paths requires '<directory>' arguments");
if (base_path && !is_directory(base_path))
die("base-path '%s' does not exist or is not a directory",
diff --git a/diff.c b/diff.c
index e71cf75..974626a 100644
--- a/diff.c
+++ b/diff.c
@@ -1289,7 +1289,6 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
{
static const char *nneof = " No newline at end of file\n";
const char *context, *reset, *set, *set_sign, *meta, *fraginfo;
- struct strbuf sb = STRBUF_INIT;
enum diff_symbol s = eds->s;
const char *line = eds->line;
@@ -1521,7 +1520,6 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
default:
BUG("unknown diff symbol");
}
- strbuf_release(&sb);
}
static void emit_diff_symbol(struct diff_options *o, enum diff_symbol s,
@@ -3362,23 +3360,23 @@ struct userdiff_driver *get_textconv(struct repository *r,
return userdiff_get_textconv(r, one->driver);
}
-static struct strbuf *additional_headers(struct diff_options *o,
- const char *path)
+static struct string_list *additional_headers(struct diff_options *o,
+ const char *path)
{
if (!o->additional_path_headers)
return NULL;
return strmap_get(o->additional_path_headers, path);
}
-static void add_formatted_headers(struct strbuf *msg,
- struct strbuf *more_headers,
+static void add_formatted_header(struct strbuf *msg,
+ const char *header,
const char *line_prefix,
const char *meta,
const char *reset)
{
- char *next, *newline;
+ const char *next, *newline;
- for (next = more_headers->buf; *next; next = newline) {
+ for (next = header; *next; next = newline) {
newline = strchrnul(next, '\n');
strbuf_addf(msg, "%s%s%.*s%s\n", line_prefix, meta,
(int)(newline - next), next, reset);
@@ -3387,6 +3385,19 @@ static void add_formatted_headers(struct strbuf *msg,
}
}
+static void add_formatted_headers(struct strbuf *msg,
+ struct string_list *more_headers,
+ const char *line_prefix,
+ const char *meta,
+ const char *reset)
+{
+ int i;
+
+ for (i = 0; i < more_headers->nr; i++)
+ add_formatted_header(msg, more_headers->items[i].string,
+ line_prefix, meta, reset);
+}
+
static void builtin_diff(const char *name_a,
const char *name_b,
struct diff_filespec *one,
@@ -4314,7 +4325,7 @@ static void fill_metainfo(struct strbuf *msg,
const char *set = diff_get_color(use_color, DIFF_METAINFO);
const char *reset = diff_get_color(use_color, DIFF_RESET);
const char *line_prefix = diff_line_prefix(o);
- struct strbuf *more_headers = NULL;
+ struct string_list *more_headers = NULL;
*must_show_header = 1;
strbuf_init(msg, PATH_MAX * 2 + 300);
diff --git a/dir.c b/dir.c
index 6ca2ef5..d7cfb08 100644
--- a/dir.c
+++ b/dir.c
@@ -1861,7 +1861,7 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
*/
enum path_treatment state;
int matches_how = 0;
- int nested_repo = 0, check_only, stop_early;
+ int check_only, stop_early;
int old_ignored_nr, old_untracked_nr;
/* The "len-1" is to strip the final '/' */
enum exist_status status = directory_exists_in_index(istate, dirname, len-1);
@@ -1893,16 +1893,37 @@ static enum path_treatment treat_directory(struct dir_struct *dir,
if ((dir->flags & DIR_SKIP_NESTED_GIT) ||
!(dir->flags & DIR_NO_GITLINKS)) {
+ /*
+ * Determine if `dirname` is a nested repo by confirming that:
+ * 1) we are in a nonbare repository, and
+ * 2) `dirname` is not an immediate parent of `the_repository->gitdir`,
+ * which could occur if the git_dir or worktree location was
+ * manually configured by the user; see t2205 testcases 1-3 for
+ * examples where this matters
+ */
+ int nested_repo;
struct strbuf sb = STRBUF_INIT;
strbuf_addstr(&sb, dirname);
nested_repo = is_nonbare_repository_dir(&sb);
+
+ if (nested_repo) {
+ char *real_dirname, *real_gitdir;
+ strbuf_addstr(&sb, ".git");
+ real_dirname = real_pathdup(sb.buf, 1);
+ real_gitdir = real_pathdup(the_repository->gitdir, 1);
+
+ nested_repo = !!strcmp(real_dirname, real_gitdir);
+ free(real_gitdir);
+ free(real_dirname);
+ }
strbuf_release(&sb);
- }
- if (nested_repo) {
- if ((dir->flags & DIR_SKIP_NESTED_GIT) ||
- (matches_how == MATCHED_RECURSIVELY_LEADING_PATHSPEC))
- return path_none;
- return excluded ? path_excluded : path_untracked;
+
+ if (nested_repo) {
+ if ((dir->flags & DIR_SKIP_NESTED_GIT) ||
+ (matches_how == MATCHED_RECURSIVELY_LEADING_PATHSPEC))
+ return path_none;
+ return excluded ? path_excluded : path_untracked;
+ }
}
if (!(dir->flags & DIR_SHOW_OTHER_DIRECTORIES)) {
diff --git a/entry.c b/entry.c
index 1c9df62..616e4f0 100644
--- a/entry.c
+++ b/entry.c
@@ -157,12 +157,11 @@ static int remove_available_paths(struct string_list_item *item, void *cb_data)
available = string_list_lookup(available_paths, item->string);
if (available)
- available->util = (void *)item->string;
+ available->util = item->util;
return !available;
}
-int finish_delayed_checkout(struct checkout *state, int *nr_checkouts,
- int show_progress)
+int finish_delayed_checkout(struct checkout *state, int show_progress)
{
int errs = 0;
unsigned processed_paths = 0;
@@ -227,7 +226,7 @@ int finish_delayed_checkout(struct checkout *state, int *nr_checkouts,
strlen(path->string), 0);
if (ce) {
display_progress(progress, ++processed_paths);
- errs |= checkout_entry(ce, state, NULL, nr_checkouts);
+ errs |= checkout_entry(ce, state, NULL, path->util);
filtered_bytes += ce->ce_stat_data.sd_size;
display_throughput(progress, filtered_bytes);
} else
@@ -266,7 +265,8 @@ void update_ce_after_write(const struct checkout *state, struct cache_entry *ce,
/* Note: ca is used (and required) iff the entry refers to a regular file. */
static int write_entry(struct cache_entry *ce, char *path, struct conv_attrs *ca,
- const struct checkout *state, int to_tempfile)
+ const struct checkout *state, int to_tempfile,
+ int *nr_checkouts)
{
unsigned int ce_mode_s_ifmt = ce->ce_mode & S_IFMT;
struct delayed_checkout *dco = state->delayed_checkout;
@@ -279,6 +279,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct conv_attrs *ca
struct stat st;
const struct submodule *sub;
struct checkout_metadata meta;
+ static int scratch_nr_checkouts;
clone_checkout_metadata(&meta, &state->meta, &ce->oid);
@@ -333,9 +334,15 @@ static int write_entry(struct cache_entry *ce, char *path, struct conv_attrs *ca
ret = async_convert_to_working_tree_ca(ca, ce->name,
new_blob, size,
&buf, &meta, dco);
- if (ret && string_list_has_string(&dco->paths, ce->name)) {
- free(new_blob);
- goto delayed;
+ if (ret) {
+ struct string_list_item *item =
+ string_list_lookup(&dco->paths, ce->name);
+ if (item) {
+ item->util = nr_checkouts ? nr_checkouts
+ : &scratch_nr_checkouts;
+ free(new_blob);
+ goto delayed;
+ }
}
} else {
ret = convert_to_working_tree_ca(ca, ce->name, new_blob,
@@ -392,6 +399,8 @@ finish:
ce->name);
update_ce_after_write(state, ce , &st);
}
+ if (nr_checkouts)
+ (*nr_checkouts)++;
delayed:
return 0;
}
@@ -476,7 +485,7 @@ int checkout_entry_ca(struct cache_entry *ce, struct conv_attrs *ca,
convert_attrs(state->istate, &ca_buf, ce->name);
ca = &ca_buf;
}
- return write_entry(ce, topath, ca, state, 1);
+ return write_entry(ce, topath, ca, state, 1, nr_checkouts);
}
strbuf_reset(&path);
@@ -540,18 +549,15 @@ int checkout_entry_ca(struct cache_entry *ce, struct conv_attrs *ca,
create_directories(path.buf, path.len, state);
- if (nr_checkouts)
- (*nr_checkouts)++;
-
if (S_ISREG(ce->ce_mode) && !ca) {
convert_attrs(state->istate, &ca_buf, ce->name);
ca = &ca_buf;
}
- if (!enqueue_checkout(ce, ca))
+ if (!enqueue_checkout(ce, ca, nr_checkouts))
return 0;
- return write_entry(ce, path.buf, ca, state, 0);
+ return write_entry(ce, path.buf, ca, state, 0, nr_checkouts);
}
void unlink_entry(const struct cache_entry *ce)
diff --git a/entry.h b/entry.h
index 252fd24..9be4659 100644
--- a/entry.h
+++ b/entry.h
@@ -43,8 +43,7 @@ static inline int checkout_entry(struct cache_entry *ce,
}
void enable_delayed_checkout(struct checkout *state);
-int finish_delayed_checkout(struct checkout *state, int *nr_checkouts,
- int show_progress);
+int finish_delayed_checkout(struct checkout *state, int show_progress);
/*
* Unlink the last component and schedule the leading directories for
diff --git a/fsmonitor-settings.c b/fsmonitor-settings.c
index 658cb79..464424a 100644
--- a/fsmonitor-settings.c
+++ b/fsmonitor-settings.c
@@ -202,11 +202,15 @@ char *fsm_settings__get_incompatible_msg(const struct repository *r,
case FSMONITOR_REASON_OK:
goto done;
- case FSMONITOR_REASON_BARE:
+ case FSMONITOR_REASON_BARE: {
+ char *cwd = xgetcwd();
+
strbuf_addf(&msg,
_("bare repository '%s' is incompatible with fsmonitor"),
- xgetcwd());
+ cwd);
+ free(cwd);
goto done;
+ }
case FSMONITOR_REASON_ERROR:
strbuf_addf(&msg,
diff --git a/fuzz-commit-graph.c b/fuzz-commit-graph.c
index e7cf6d5..914026f 100644
--- a/fuzz-commit-graph.c
+++ b/fuzz-commit-graph.c
@@ -1,7 +1,7 @@
#include "commit-graph.h"
#include "repository.h"
-struct commit_graph *parse_commit_graph(struct repository *r,
+struct commit_graph *parse_commit_graph(struct repo_settings *s,
void *graph_map, size_t graph_size);
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
@@ -11,7 +11,15 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
struct commit_graph *g;
initialize_the_repository();
- g = parse_commit_graph(the_repository, (void *)data, size);
+ /*
+ * Initialize the_repository with commit-graph settings that would
+ * normally be read from the repository's gitdir. We want to avoid
+ * touching the disk to keep the individual fuzz-test cases as fast as
+ * possible.
+ */
+ the_repository->settings.commit_graph_generation_version = 2;
+ the_repository->settings.commit_graph_read_changed_paths = 1;
+ g = parse_commit_graph(&the_repository->settings, (void *)data, size);
repo_clear(the_repository);
free_commit_graph(g);
diff --git a/git-compat-util.h b/git-compat-util.h
index fd36d3b..58d7708 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -497,7 +497,12 @@ static inline int is_path_owned_by_current_uid(const char *path)
euid = geteuid();
if (euid == ROOT_UID)
- extract_id_from_env("SUDO_UID", &euid);
+ {
+ if (st.st_uid == ROOT_UID)
+ return 1;
+ else
+ extract_id_from_env("SUDO_UID", &euid);
+ }
return st.st_uid == euid;
}
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 4c81180..7b75736 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -152,7 +152,7 @@ $state->{allowed_roots} = [ @ARGV ];
# don't export the whole system unless the users requests it
if ($state->{'export-all'} && !@{$state->{allowed_roots}}) {
- die "--export-all can only be used together with an explicit whitelist\n";
+ die "--export-all can only be used together with an explicit '<directory>...' list\n";
}
# Environment handling for running under git-shell
diff --git a/git-instaweb.sh b/git-instaweb.sh
index 4349566..c68f494 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -102,7 +102,7 @@ resolve_full_httpd () {
start_httpd () {
if test -f "$fqgitdir/pid"; then
- say "Instance already running. Restarting..."
+ echo "Instance already running. Restarting..."
stop_httpd
fi
diff --git a/git-p4.py b/git-p4.py
index 8fbf6eb..d26a980 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -822,6 +822,42 @@ def isModeExecChanged(src_mode, dst_mode):
return isModeExec(src_mode) != isModeExec(dst_mode)
+def p4KeysContainingNonUtf8Chars():
+ """Returns all keys which may contain non UTF-8 encoded strings
+ for which a fallback strategy has to be applied.
+ """
+ return ['desc', 'client', 'FullName']
+
+
+def p4KeysContainingBinaryData():
+ """Returns all keys which may contain arbitrary binary data
+ """
+ return ['data']
+
+
+def p4KeyContainsFilePaths(key):
+ """Returns True if the key contains file paths. These are handled by decode_path().
+ Otherwise False.
+ """
+ return key.startswith('depotFile') or key in ['path', 'clientFile']
+
+
+def p4KeyWhichCanBeDirectlyDecoded(key):
+ """Returns True if the key can be directly decoded as UTF-8 string
+ Otherwise False.
+
+ Keys which can not be encoded directly:
+ - `data` which may contain arbitrary binary data
+ - `desc` or `client` or `FullName` which may contain non-UTF8 encoded text
+ - `depotFile[0-9]*`, `path`, or `clientFile` which may contain non-UTF8 encoded text, handled by decode_path()
+ """
+ if key in p4KeysContainingNonUtf8Chars() or \
+ key in p4KeysContainingBinaryData() or \
+ p4KeyContainsFilePaths(key):
+ return False
+ return True
+
+
def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False,
errors_as_exceptions=False, *k, **kw):
@@ -851,15 +887,13 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False,
try:
while True:
entry = marshal.load(p4.stdout)
+
if bytes is not str:
- # Decode unmarshalled dict to use str keys and values, except for:
- # - `data` which may contain arbitrary binary data
- # - `desc` or `FullName` which may contain non-UTF8 encoded text handled below, eagerly converted to bytes
- # - `depotFile[0-9]*`, `path`, or `clientFile` which may contain non-UTF8 encoded text, handled by decode_path()
+ # Decode unmarshalled dict to use str keys and values. Special cases are handled below.
decoded_entry = {}
for key, value in entry.items():
key = key.decode()
- if isinstance(value, bytes) and not (key in ('data', 'desc', 'FullName', 'path', 'clientFile') or key.startswith('depotFile')):
+ if isinstance(value, bytes) and p4KeyWhichCanBeDirectlyDecoded(key):
value = value.decode()
decoded_entry[key] = value
# Parse out data if it's an error response
@@ -869,10 +903,9 @@ def p4CmdList(cmd, stdin=None, stdin_mode='w+b', cb=None, skip_info=False,
if skip_info:
if 'code' in entry and entry['code'] == 'info':
continue
- if 'desc' in entry:
- entry['desc'] = metadata_stream_to_writable_bytes(entry['desc'])
- if 'FullName' in entry:
- entry['FullName'] = metadata_stream_to_writable_bytes(entry['FullName'])
+ for key in p4KeysContainingNonUtf8Chars():
+ if key in entry:
+ entry[key] = metadata_stream_to_writable_bytes(entry[key])
if cb is not None:
cb(entry)
else:
@@ -2226,7 +2259,7 @@ class P4Submit(Command, P4UserMap):
raw=True):
if regexp.search(line):
if verbose:
- print("got keyword match on %s in %s in %s" % (regex.pattern, line, file))
+ print("got keyword match on %s in %s in %s" % (regexp.pattern, line, file))
kwfiles[file] = regexp
break
@@ -3148,7 +3181,7 @@ class P4Sync(Command, P4UserMap):
raise e
else:
if p4_version_string().find('/NT') >= 0:
- text = text.replace(b'\r\n', b'\n')
+ text = text.replace(b'\x0d\x00\x0a\x00', b'\x0a\x00')
contents = [text]
if type_base == "apple":
@@ -4369,19 +4402,16 @@ class P4Unshelve(Command):
def renameBranch(self, branch_name):
"""Rename the existing branch to branch_name.N ."""
- found = True
for i in range(0, 1000):
backup_branch_name = "{0}.{1}".format(branch_name, i)
if not gitBranchExists(backup_branch_name):
# Copy ref to backup
gitUpdateRef(backup_branch_name, branch_name)
gitDeleteRef(branch_name)
- found = True
print("renamed old unshelve branch to {0}".format(backup_branch_name))
break
-
- if not found:
- sys.exit("gave up trying to rename existing branch {0}".format(sync.branch))
+ else:
+ sys.exit("gave up trying to rename existing branch {0}".format(branch_name))
def findLastP4Revision(self, starting_point):
"""Look back from starting_point for the first commit created by git-p4
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index d92df37..ce273fe 100644
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -57,15 +57,6 @@ die_with_status () {
exit "$status"
}
-GIT_QUIET=
-
-say () {
- if test -z "$GIT_QUIET"
- then
- printf '%s\n' "$*"
- fi
-}
-
if test -n "$OPTIONS_SPEC"; then
usage() {
"$0" -h
@@ -285,13 +276,6 @@ get_author_ident_from_commit () {
parse_ident_from_commit author AUTHOR
}
-# Clear repo-local GIT_* environment variables. Useful when switching to
-# another repository (e.g. when entering a submodule). See also the env
-# list in git_connect()
-clear_local_git_env() {
- unset $(git rev-parse --local-env-vars)
-}
-
# Generate a virtual base file for a two-file merge. Uses git apply to
# remove lines from $1 that are not in $2, leaving only common lines.
create_virtual_base() {
diff --git a/git-submodule.sh b/git-submodule.sh
index fd0b4a2..5e5d21c 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -30,6 +30,7 @@ GIT_PROTOCOL_FROM_USER=0
export GIT_PROTOCOL_FROM_USER
command=
+quiet=
branch=
force=
reference=
@@ -40,8 +41,9 @@ require_init=
files=
remote=
nofetch=
-update=
-prefix=
+rebase=
+merge=
+checkout=
custom_name=
depth=
progress=
@@ -56,17 +58,6 @@ isnumber()
n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
}
-# Sanitize the local git environment for use within a submodule. We
-# can't simply use clear_local_git_env since we want to preserve some
-# of the settings from GIT_CONFIG_PARAMETERS.
-sanitize_submodule_env()
-{
- save_config=$GIT_CONFIG_PARAMETERS
- clear_local_git_env
- GIT_CONFIG_PARAMETERS=$save_config
- export GIT_CONFIG_PARAMETERS
-}
-
#
# Add a new submodule to the working tree, .gitmodules and the index
#
@@ -90,7 +81,7 @@ cmd_add()
force=$1
;;
-q|--quiet)
- GIT_QUIET=1
+ quiet=1
;;
--progress)
progress=1
@@ -138,7 +129,7 @@ cmd_add()
usage
fi
- git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper add ${GIT_QUIET:+--quiet} ${force:+--force} ${progress:+"--progress"} ${branch:+--branch "$branch"} ${reference_path:+--reference "$reference_path"} ${dissociate:+--dissociate} ${custom_name:+--name "$custom_name"} ${depth:+"$depth"} -- "$@"
+ git ${wt_prefix:+-C "$wt_prefix"} submodule--helper add ${quiet:+--quiet} ${force:+--force} ${progress:+"--progress"} ${branch:+--branch "$branch"} ${reference_path:+--reference "$reference_path"} ${dissociate:+--dissociate} ${custom_name:+--name "$custom_name"} ${depth:+"$depth"} -- "$@"
}
#
@@ -154,7 +145,7 @@ cmd_foreach()
do
case "$1" in
-q|--quiet)
- GIT_QUIET=1
+ quiet=1
;;
--recursive)
recursive=1
@@ -169,7 +160,7 @@ cmd_foreach()
shift
done
- git ${wt_prefix:+-C "$wt_prefix"} submodule--helper foreach ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@"
+ git ${wt_prefix:+-C "$wt_prefix"} submodule--helper foreach ${quiet:+--quiet} ${recursive:+--recursive} -- "$@"
}
#
@@ -184,7 +175,7 @@ cmd_init()
do
case "$1" in
-q|--quiet)
- GIT_QUIET=1
+ quiet=1
;;
--)
shift
@@ -200,7 +191,7 @@ cmd_init()
shift
done
- git ${wt_prefix:+-C "$wt_prefix"} ${prefix:+--super-prefix "$prefix"} submodule--helper init ${GIT_QUIET:+--quiet} -- "$@"
+ git ${wt_prefix:+-C "$wt_prefix"} submodule--helper init ${quiet:+--quiet} -- "$@"
}
#
@@ -217,7 +208,7 @@ cmd_deinit()
force=$1
;;
-q|--quiet)
- GIT_QUIET=1
+ quiet=1
;;
--all)
deinit_all=t
@@ -236,7 +227,7 @@ cmd_deinit()
shift
done
- git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${GIT_QUIET:+--quiet} ${force:+--force} ${deinit_all:+--all} -- "$@"
+ git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit ${quiet:+--quiet} ${force:+--force} ${deinit_all:+--all} -- "$@"
}
#
@@ -251,10 +242,7 @@ cmd_update()
do
case "$1" in
-q|--quiet)
- GIT_QUIET=1
- ;;
- -v)
- unset GIT_QUIET
+ quiet=1
;;
--progress)
progress=1
@@ -263,7 +251,6 @@ cmd_update()
init=1
;;
--require-init)
- init=1
require_init=1
;;
--remote)
@@ -276,7 +263,7 @@ cmd_update()
force=$1
;;
-r|--rebase)
- update="rebase"
+ rebase=1
;;
--reference)
case "$2" in '') usage ;; esac
@@ -290,13 +277,13 @@ cmd_update()
dissociate=1
;;
-m|--merge)
- update="merge"
+ merge=1
;;
--recursive)
recursive=1
;;
--checkout)
- update="checkout"
+ checkout=1
;;
--recommend-shallow)
recommend_shallow="--recommend-shallow"
@@ -349,7 +336,7 @@ cmd_update()
done
git ${wt_prefix:+-C "$wt_prefix"} submodule--helper update \
- ${GIT_QUIET:+--quiet} \
+ ${quiet:+--quiet} \
${force:+--force} \
${progress:+"--progress"} \
${remote:+--remote} \
@@ -357,8 +344,9 @@ cmd_update()
${init:+--init} \
${nofetch:+--no-fetch} \
${wt_prefix:+--prefix "$wt_prefix"} \
- ${prefix:+--recursive-prefix "$prefix"} \
- ${update:+--update "$update"} \
+ ${rebase:+--rebase} \
+ ${merge:+--merge} \
+ ${checkout:+--checkout} \
${reference:+"$reference"} \
${dissociate:+"--dissociate"} \
${depth:+"$depth"} \
@@ -409,7 +397,7 @@ cmd_set_branch() {
shift
done
- git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-branch ${GIT_QUIET:+--quiet} ${branch:+--branch "$branch"} ${default:+--default} -- "$@"
+ git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-branch ${quiet:+--quiet} ${branch:+--branch "$branch"} ${default:+--default} -- "$@"
}
#
@@ -422,7 +410,7 @@ cmd_set_url() {
do
case "$1" in
-q|--quiet)
- GIT_QUIET=1
+ quiet=1
;;
--)
shift
@@ -438,7 +426,7 @@ cmd_set_url() {
shift
done
- git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-url ${GIT_QUIET:+--quiet} -- "$@"
+ git ${wt_prefix:+-C "$wt_prefix"} submodule--helper set-url ${quiet:+--quiet} -- "$@"
}
#
@@ -459,7 +447,7 @@ cmd_summary() {
do
case "$1" in
--cached)
- cached="$1"
+ cached=1
;;
--files)
files="$1"
@@ -509,7 +497,7 @@ cmd_status()
do
case "$1" in
-q|--quiet)
- GIT_QUIET=1
+ quiet=1
;;
--cached)
cached=1
@@ -531,7 +519,7 @@ cmd_status()
shift
done
- git ${wt_prefix:+-C "$wt_prefix"} submodule--helper status ${GIT_QUIET:+--quiet} ${cached:+--cached} ${recursive:+--recursive} -- "$@"
+ git ${wt_prefix:+-C "$wt_prefix"} submodule--helper status ${quiet:+--quiet} ${cached:+--cached} ${recursive:+--recursive} -- "$@"
}
#
# Sync remote urls for submodules
@@ -544,7 +532,7 @@ cmd_sync()
do
case "$1" in
-q|--quiet)
- GIT_QUIET=1
+ quiet=1
shift
;;
--recursive)
@@ -564,12 +552,12 @@ cmd_sync()
esac
done
- git ${wt_prefix:+-C "$wt_prefix"} submodule--helper sync ${GIT_QUIET:+--quiet} ${recursive:+--recursive} -- "$@"
+ git ${wt_prefix:+-C "$wt_prefix"} submodule--helper sync ${quiet:+--quiet} ${recursive:+--recursive} -- "$@"
}
cmd_absorbgitdirs()
{
- git submodule--helper absorb-git-dirs --prefix "$wt_prefix" "$@"
+ git submodule--helper absorbgitdirs --prefix "$wt_prefix" "$@"
}
# This loop parses the command line arguments to find the
@@ -585,18 +573,10 @@ do
command=$1
;;
-q|--quiet)
- GIT_QUIET=1
- ;;
- -b|--branch)
- case "$2" in
- '')
- usage
- ;;
- esac
- branch="$2"; shift
+ quiet=1
;;
--cached)
- cached="$1"
+ cached=1
;;
--)
break
@@ -622,12 +602,6 @@ then
fi
fi
-# "-b branch" is accepted only by "add" and "set-branch"
-if test -n "$branch" && (test "$command" != add || test "$command" != set-branch)
-then
- usage
-fi
-
# "--cached" is accepted only by "status" and "summary"
if test -n "$cached" && test "$command" != status && test "$command" != summary
then
diff --git a/git.c b/git.c
index d7a7a82..e5d62fa 100644
--- a/git.c
+++ b/git.c
@@ -565,7 +565,7 @@ static struct cmd_struct commands[] = {
{ "merge-recursive-ours", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
{ "merge-recursive-theirs", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
{ "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },
- { "merge-tree", cmd_merge_tree, RUN_SETUP | NO_PARSEOPT },
+ { "merge-tree", cmd_merge_tree, RUN_SETUP },
{ "mktag", cmd_mktag, RUN_SETUP | NO_PARSEOPT },
{ "mktree", cmd_mktree, RUN_SETUP },
{ "multi-pack-index", cmd_multi_pack_index, RUN_SETUP },
diff --git a/gitweb/Makefile b/gitweb/Makefile
index f13e23c..3b68ab2 100644
--- a/gitweb/Makefile
+++ b/gitweb/Makefile
@@ -1,8 +1,8 @@
-# The default target of this Makefile is...
-all::
+ifndef MAK_DIR_GITWEB
+$(error do not run gitweb/Makefile stand-alone anymore. The "gitweb" and \
+"install-gitweb" targets now live in the top-level Makefile)
+endif
-# Define V=1 to have a more verbose compile.
-#
# Define JSMIN to point to JavaScript minifier that functions as
# a filter to have static/gitweb.js minified.
#
@@ -10,13 +10,6 @@ all::
# version of static/gitweb.css
#
-prefix ?= $(HOME)
-bindir ?= $(prefix)/bin
-gitwebdir ?= /var/www/cgi-bin
-
-RM ?= rm -f
-INSTALL ?= install
-
# default configuration for gitweb
GITWEB_CONFIG = gitweb_config.perl
GITWEB_CONFIG_SYSTEM = /etc/gitweb.conf
@@ -30,89 +23,45 @@ GITWEB_STRICT_EXPORT =
GITWEB_BASE_URL =
GITWEB_LIST =
GITWEB_HOMETEXT = indextext.html
-GITWEB_CSS = static/gitweb.css
+GITWEB_CSS_IN = static/gitweb.css
+GITWEB_CSS = $(GITWEB_CSS_IN)
GITWEB_LOGO = static/git-logo.png
GITWEB_FAVICON = static/git-favicon.png
-GITWEB_JS = static/gitweb.js
+GITWEB_JS_IN = static/gitweb.js
+GITWEB_JS = $(GITWEB_JS_IN)
GITWEB_SITE_HTML_HEAD_STRING =
GITWEB_SITE_HEADER =
GITWEB_SITE_FOOTER =
HIGHLIGHT_BIN = highlight
-# include user config
--include ../config.mak.autogen
--include ../config.mak
--include config.mak
-
-# determine version
-../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
- $(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) GIT-VERSION-FILE
-
-ifneq ($(MAKECMDGOALS),clean)
--include ../GIT-VERSION-FILE
-endif
-
-### Build rules
-
-SHELL_PATH ?= $(SHELL)
-PERL_PATH ?= /usr/bin/perl
+# What targets we'll add to 'all' for "make gitweb"
+GITWEB_ALL =
+GITWEB_ALL += gitweb.cgi
+GITWEB_ALL += $(GITWEB_JS)
-# Shell quote;
-bindir_SQ = $(subst ','\'',$(bindir))#'
-gitwebdir_SQ = $(subst ','\'',$(gitwebdir))#'
-gitwebstaticdir_SQ = $(subst ','\'',$(gitwebdir)/static)#'
-SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))#'
-PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))#'
-DESTDIR_SQ = $(subst ','\'',$(DESTDIR))#'
-
-# Quiet generation (unless V=1)
-QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
-QUIET_SUBDIR1 =
-
-ifneq ($(findstring $(MAKEFLAGS),w),w)
-PRINT_DIR = --no-print-directory
-else # "make -w"
-NO_SUBDIR = :
-endif
-
-ifneq ($(findstring $(MAKEFLAGS),s),s)
-ifndef V
- QUIET = @
- QUIET_GEN = $(QUIET)echo ' ' GEN $@;
- QUIET_SUBDIR0 = +@subdir=
- QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \
- $(MAKE) $(PRINT_DIR) -C $$subdir
- export V
- export QUIET
- export QUIET_GEN
- export QUIET_SUBDIR0
- export QUIET_SUBDIR1
-endif
-endif
-
-all:: gitweb.cgi static/gitweb.js
+MAK_DIR_GITWEB_ALL = $(addprefix $(MAK_DIR_GITWEB),$(GITWEB_ALL))
GITWEB_PROGRAMS = gitweb.cgi
+GITWEB_JS_MIN = static/gitweb.min.js
ifdef JSMIN
-GITWEB_FILES += static/gitweb.min.js
-GITWEB_JS = static/gitweb.min.js
-all:: static/gitweb.min.js
-static/gitweb.min.js: static/gitweb.js GITWEB-BUILD-OPTIONS
+GITWEB_JS = $(GITWEB_JS_MIN)
+GITWEB_ALL += $(MAK_DIR_GITWEB)$(GITWEB_JS_MIN)
+$(MAK_DIR_GITWEB)$(GITWEB_JS_MIN): $(MAK_DIR_GITWEB)GITWEB-BUILD-OPTIONS
+$(MAK_DIR_GITWEB)$(GITWEB_JS_MIN): $(MAK_DIR_GITWEB)$(GITWEB_JS_IN)
$(QUIET_GEN)$(JSMIN) <$< >$@
-else
-GITWEB_FILES += static/gitweb.js
endif
+GITWEB_FILES += $(GITWEB_JS)
+GITWEB_CSS_MIN = static/gitweb.min.css
ifdef CSSMIN
-GITWEB_FILES += static/gitweb.min.css
-GITWEB_CSS = static/gitweb.min.css
-all:: static/gitweb.min.css
-static/gitweb.min.css: static/gitweb.css GITWEB-BUILD-OPTIONS
+GITWEB_CSS = $(GITWEB_CSS_MIN)
+GITWEB_ALL += $(MAK_DIR_GITWEB)$(GITWEB_CSS_MIN)
+$(MAK_DIR_GITWEB)$(GITWEB_CSS_MIN): $(MAK_DIR_GITWEB)GITWEB-BUILD-OPTIONS
+$(MAK_DIR_GITWEB)$(GITWEB_CSS_MIN): $(MAK_DIR_GITWEB)$(GITWEB_CSS_IN)
$(QUIET_GEN)$(CSSMIN) <$< >$@
-else
-GITWEB_FILES += static/gitweb.css
endif
+GITWEB_FILES += $(GITWEB_CSS)
GITWEB_FILES += static/git-logo.png static/git-favicon.png
@@ -120,6 +69,7 @@ GITWEB_FILES += static/git-logo.png static/git-favicon.png
#
# js/lib/common-lib.js should be always first, then js/lib/*.js,
# then the rest of files; js/gitweb.js should be last (if it exists)
+GITWEB_JSLIB_FILES =
GITWEB_JSLIB_FILES += static/js/lib/common-lib.js
GITWEB_JSLIB_FILES += static/js/lib/datetime.js
GITWEB_JSLIB_FILES += static/js/lib/cookies.js
@@ -152,46 +102,45 @@ GITWEB_REPLACE = \
-e 's|++GITWEB_SITE_FOOTER++|$(GITWEB_SITE_FOOTER)|g' \
-e 's|++HIGHLIGHT_BIN++|$(HIGHLIGHT_BIN)|g'
-GITWEB-BUILD-OPTIONS: FORCE
+.PHONY: FORCE
+$(MAK_DIR_GITWEB)GITWEB-BUILD-OPTIONS: FORCE
@rm -f $@+
@echo "x" '$(PERL_PATH_SQ)' $(GITWEB_REPLACE) "$(JSMIN)|$(CSSMIN)" >$@+
@cmp -s $@+ $@ && rm -f $@+ || mv -f $@+ $@
-gitweb.cgi: gitweb.perl GITWEB-BUILD-OPTIONS
+$(MAK_DIR_GITWEB)gitweb.cgi: $(MAK_DIR_GITWEB)GITWEB-BUILD-OPTIONS
+$(MAK_DIR_GITWEB)gitweb.cgi: $(MAK_DIR_GITWEB)gitweb.perl
$(QUIET_GEN)$(RM) $@ $@+ && \
sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \
$(GITWEB_REPLACE) $< >$@+ && \
chmod +x $@+ && \
mv $@+ $@
-static/gitweb.js: $(GITWEB_JSLIB_FILES)
+$(MAK_DIR_GITWEB)static/gitweb.js: $(addprefix $(MAK_DIR_GITWEB),$(GITWEB_JSLIB_FILES))
$(QUIET_GEN)$(RM) $@ $@+ && \
cat $^ >$@+ && \
mv $@+ $@
-### Testing rules
-
-test:
- $(MAKE) -C ../t gitweb-test
-
-test-installed:
- GITWEB_TEST_INSTALLED='$(DESTDIR_SQ)$(gitwebdir_SQ)' \
- $(MAKE) -C ../t gitweb-test
-
### Installation rules
-install: all
+.PHONY: install-gitweb
+install-gitweb: $(MAK_DIR_GITWEB_ALL)
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitwebdir_SQ)'
- $(INSTALL) -m 755 $(GITWEB_PROGRAMS) '$(DESTDIR_SQ)$(gitwebdir_SQ)'
+ $(INSTALL) -m 755 $(addprefix $(MAK_DIR_GITWEB),$(GITWEB_PROGRAMS)) '$(DESTDIR_SQ)$(gitwebdir_SQ)'
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitwebstaticdir_SQ)'
- $(INSTALL) -m 644 $(GITWEB_FILES) '$(DESTDIR_SQ)$(gitwebstaticdir_SQ)'
+ $(INSTALL) -m 644 $(addprefix $(MAK_DIR_GITWEB),$(GITWEB_FILES)) \
+ '$(DESTDIR_SQ)$(gitwebstaticdir_SQ)'
+ifndef NO_GITWEB
+ifndef NO_PERL
+install: install-gitweb
+endif
+endif
### Cleaning rules
-clean:
- $(RM) gitweb.cgi static/gitweb.js \
- static/gitweb.min.js static/gitweb.min.css \
- GITWEB-BUILD-OPTIONS
-
-.PHONY: all clean install test test-installed .FORCE-GIT-VERSION-FILE FORCE
-
+.PHONY: gitweb-clean
+gitweb-clean:
+ $(RM) $(addprefix $(MAK_DIR_GITWEB),gitweb.cgi $(GITWEB_JS_IN) \
+ $(GITWEB_JS_MIN) $(GITWEB_CSS_MIN) \
+ GITWEB-BUILD-OPTIONS)
+clean: gitweb-clean
diff --git a/gpg-interface.c b/gpg-interface.c
index 280f1fa..6dff241 100644
--- a/gpg-interface.c
+++ b/gpg-interface.c
@@ -165,15 +165,17 @@ static struct {
{ 0, "TRUST_", GPG_STATUS_TRUST_LEVEL },
};
-static struct {
+/* Keep the order same as enum signature_trust_level */
+static struct sigcheck_gpg_trust_level {
const char *key;
+ const char *display_key;
enum signature_trust_level value;
} sigcheck_gpg_trust_level[] = {
- { "UNDEFINED", TRUST_UNDEFINED },
- { "NEVER", TRUST_NEVER },
- { "MARGINAL", TRUST_MARGINAL },
- { "FULLY", TRUST_FULLY },
- { "ULTIMATE", TRUST_ULTIMATE },
+ { "UNDEFINED", "undefined", TRUST_UNDEFINED },
+ { "NEVER", "never", TRUST_NEVER },
+ { "MARGINAL", "marginal", TRUST_MARGINAL },
+ { "FULLY", "fully", TRUST_FULLY },
+ { "ULTIMATE", "ultimate", TRUST_ULTIMATE },
};
static void replace_cstring(char **field, const char *line, const char *next)
@@ -905,6 +907,20 @@ const char *get_signing_key(void)
return git_committer_info(IDENT_STRICT | IDENT_NO_DATE);
}
+const char *gpg_trust_level_to_str(enum signature_trust_level level)
+{
+ struct sigcheck_gpg_trust_level *trust;
+
+ if (level < 0 || level >= ARRAY_SIZE(sigcheck_gpg_trust_level))
+ BUG("invalid trust level requested %d", level);
+
+ trust = &sigcheck_gpg_trust_level[level];
+ if (trust->value != level)
+ BUG("sigcheck_gpg_trust_level[] unsorted");
+
+ return sigcheck_gpg_trust_level[level].display_key;
+}
+
int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key)
{
return use_format->sign_buffer(buffer, signature, signing_key);
@@ -985,7 +1001,7 @@ static int sign_buffer_ssh(struct strbuf *buffer, struct strbuf *signature,
if (!signing_key || signing_key[0] == '\0')
return error(
- _("user.signingkey needs to be set for ssh signing"));
+ _("user.signingKey needs to be set for ssh signing"));
if (is_literal_ssh_key(signing_key, &literal_key)) {
/* A literal ssh key */
diff --git a/gpg-interface.h b/gpg-interface.h
index b30cbdc..8a9ef41 100644
--- a/gpg-interface.h
+++ b/gpg-interface.h
@@ -71,6 +71,14 @@ size_t parse_signed_buffer(const char *buf, size_t size);
int sign_buffer(struct strbuf *buffer, struct strbuf *signature,
const char *signing_key);
+
+/*
+ * Returns corresponding string in lowercase for a given member of
+ * enum signature_trust_level. For example, `TRUST_ULTIMATE` will
+ * return "ultimate".
+ */
+const char *gpg_trust_level_to_str(enum signature_trust_level level);
+
int git_gpg_config(const char *, const char *, void *);
void set_signing_key(const char *);
const char *get_signing_key(void);
diff --git a/grep.c b/grep.c
index 82eb7da..52a894c 100644
--- a/grep.c
+++ b/grep.c
@@ -1615,7 +1615,7 @@ static int grep_source_1(struct grep_opt *opt, struct grep_source *gs, int colle
return 0;
goto next_line;
}
- if (hit) {
+ if (hit && (opt->max_count < 0 || count < opt->max_count)) {
count++;
if (opt->status_only)
return 1;
diff --git a/grep.h b/grep.h
index c722d25..bdcadce 100644
--- a/grep.h
+++ b/grep.h
@@ -171,6 +171,7 @@ struct grep_opt {
int show_hunk_mark;
int file_break;
int heading;
+ int max_count;
void *priv;
void (*output)(struct grep_opt *opt, const void *data, size_t size);
@@ -181,6 +182,7 @@ struct grep_opt {
.relative = 1, \
.pathname = 1, \
.max_depth = -1, \
+ .max_count = -1, \
.pattern_type_option = GREP_PATTERN_TYPE_UNSPECIFIED, \
.colors = { \
[GREP_COLOR_CONTEXT] = "", \
diff --git a/hash.h b/hash.h
index 5d40368..ea87ae9 100644
--- a/hash.h
+++ b/hash.h
@@ -16,7 +16,9 @@
#include "block-sha1/sha1.h"
#endif
-#if defined(SHA256_GCRYPT)
+#if defined(SHA256_NETTLE)
+#include "sha256/nettle.h"
+#elif defined(SHA256_GCRYPT)
#define SHA256_NEEDS_CLONE_HELPER
#include "sha256/gcrypt.h"
#elif defined(SHA256_OPENSSL)
diff --git a/http.c b/http.c
index 11c6f69..5d0502f 100644
--- a/http.c
+++ b/http.c
@@ -349,7 +349,7 @@ static int http_options(const char *var, const char *value, void *cb)
if (!strcmp("http.postbuffer", var)) {
http_post_buffer = git_config_ssize_t(var, value);
if (http_post_buffer < 0)
- warning(_("negative value for http.postbuffer; defaulting to %d"), LARGE_PACKET_MAX);
+ warning(_("negative value for http.postBuffer; defaulting to %d"), LARGE_PACKET_MAX);
if (http_post_buffer < LARGE_PACKET_MAX)
http_post_buffer = LARGE_PACKET_MAX;
return 0;
@@ -1775,7 +1775,7 @@ static void write_accept_language(struct strbuf *buf)
* LANGUAGE= LANG=en_US.UTF-8 -> "Accept-Language: en-US, *; q=0.1"
* LANGUAGE= LANG=C -> ""
*/
-static const char *get_accept_language(void)
+const char *http_get_accept_language_header(void)
{
if (!cached_accept_language) {
struct strbuf buf = STRBUF_INIT;
@@ -1829,7 +1829,7 @@ static int http_request(const char *url,
fwrite_buffer);
}
- accept_language = get_accept_language();
+ accept_language = http_get_accept_language_header();
if (accept_language)
headers = curl_slist_append(headers, accept_language);
diff --git a/http.h b/http.h
index ba303cf..3c94c47 100644
--- a/http.h
+++ b/http.h
@@ -178,6 +178,9 @@ int http_fetch_ref(const char *base, struct ref *ref);
int http_get_info_packs(const char *base_url,
struct packed_git **packs_head);
+/* Helper for getting Accept-Language header */
+const char *http_get_accept_language_header(void);
+
struct http_pack_request {
char *url;
diff --git a/merge-ort.c b/merge-ort.c
index b5015b9..8b7de0f 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -349,13 +349,15 @@ struct merge_options_internal {
struct mem_pool pool;
/*
- * output: special messages and conflict notices for various paths
+ * conflicts: logical conflicts and messages stored by _primary_ path
*
* This is a map of pathnames (a subset of the keys in "paths" above)
- * to strbufs. It gathers various warning/conflict/notice messages
- * for later processing.
+ * to struct string_list, with each item's `util` containing a
+ * `struct logical_conflict_info`. Note, though, that for each path,
+ * it only stores the logical conflicts for which that path is the
+ * primary path; the path might be part of additional conflicts.
*/
- struct strmap output;
+ struct strmap conflicts;
/*
* renames: various data relating to rename detection
@@ -481,6 +483,100 @@ struct conflict_info {
unsigned match_mask:3;
};
+enum conflict_and_info_types {
+ /* "Simple" conflicts and informational messages */
+ INFO_AUTO_MERGING = 0,
+ CONFLICT_CONTENTS, /* text file that failed to merge */
+ CONFLICT_BINARY,
+ CONFLICT_FILE_DIRECTORY,
+ CONFLICT_DISTINCT_MODES,
+ CONFLICT_MODIFY_DELETE,
+ CONFLICT_PRESENT_DESPITE_SKIPPED,
+
+ /* Regular rename */
+ CONFLICT_RENAME_RENAME, /* same file renamed differently */
+ CONFLICT_RENAME_COLLIDES, /* rename/add or two files renamed to 1 */
+ CONFLICT_RENAME_DELETE,
+
+ /* Basic directory rename */
+ CONFLICT_DIR_RENAME_SUGGESTED,
+ INFO_DIR_RENAME_APPLIED,
+
+ /* Special directory rename cases */
+ INFO_DIR_RENAME_SKIPPED_DUE_TO_RERENAME,
+ CONFLICT_DIR_RENAME_FILE_IN_WAY,
+ CONFLICT_DIR_RENAME_COLLISION,
+ CONFLICT_DIR_RENAME_SPLIT,
+
+ /* Basic submodule */
+ INFO_SUBMODULE_FAST_FORWARDING,
+ CONFLICT_SUBMODULE_FAILED_TO_MERGE,
+
+ /* Special submodule cases broken out from FAILED_TO_MERGE */
+ CONFLICT_SUBMODULE_FAILED_TO_MERGE_BUT_POSSIBLE_RESOLUTION,
+ CONFLICT_SUBMODULE_NOT_INITIALIZED,
+ CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE,
+ CONFLICT_SUBMODULE_MAY_HAVE_REWINDS,
+
+ /* Keep this entry _last_ in the list */
+ NB_CONFLICT_TYPES,
+};
+
+/*
+ * Short description of conflict type, relied upon by external tools.
+ *
+ * We can add more entries, but DO NOT change any of these strings. Also,
+ * Order MUST match conflict_info_and_types.
+ */
+static const char *type_short_descriptions[] = {
+ /*** "Simple" conflicts and informational messages ***/
+ [INFO_AUTO_MERGING] = "Auto-merging",
+ [CONFLICT_CONTENTS] = "CONFLICT (contents)",
+ [CONFLICT_BINARY] = "CONFLICT (binary)",
+ [CONFLICT_FILE_DIRECTORY] = "CONFLICT (file/directory)",
+ [CONFLICT_DISTINCT_MODES] = "CONFLICT (distinct modes)",
+ [CONFLICT_MODIFY_DELETE] = "CONFLICT (modify/delete)",
+ [CONFLICT_PRESENT_DESPITE_SKIPPED] =
+ "CONFLICT (upgrade your version of git)",
+
+ /*** Regular rename ***/
+ [CONFLICT_RENAME_RENAME] = "CONFLICT (rename/rename)",
+ [CONFLICT_RENAME_COLLIDES] = "CONFLICT (rename involved in collision)",
+ [CONFLICT_RENAME_DELETE] = "CONFLICT (rename/delete)",
+
+ /*** Basic directory rename ***/
+ [CONFLICT_DIR_RENAME_SUGGESTED] =
+ "CONFLICT (directory rename suggested)",
+ [INFO_DIR_RENAME_APPLIED] = "Path updated due to directory rename",
+
+ /*** Special directory rename cases ***/
+ [INFO_DIR_RENAME_SKIPPED_DUE_TO_RERENAME] =
+ "Directory rename skipped since directory was renamed on both sides",
+ [CONFLICT_DIR_RENAME_FILE_IN_WAY] =
+ "CONFLICT (file in way of directory rename)",
+ [CONFLICT_DIR_RENAME_COLLISION] = "CONFLICT(directory rename collision)",
+ [CONFLICT_DIR_RENAME_SPLIT] = "CONFLICT(directory rename unclear split)",
+
+ /*** Basic submodule ***/
+ [INFO_SUBMODULE_FAST_FORWARDING] = "Fast forwarding submodule",
+ [CONFLICT_SUBMODULE_FAILED_TO_MERGE] = "CONFLICT (submodule)",
+
+ /*** Special submodule cases broken out from FAILED_TO_MERGE ***/
+ [CONFLICT_SUBMODULE_FAILED_TO_MERGE_BUT_POSSIBLE_RESOLUTION] =
+ "CONFLICT (submodule with possible resolution)",
+ [CONFLICT_SUBMODULE_NOT_INITIALIZED] =
+ "CONFLICT (submodule not initialized)",
+ [CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE] =
+ "CONFLICT (submodule history not available)",
+ [CONFLICT_SUBMODULE_MAY_HAVE_REWINDS] =
+ "CONFLICT (submodule may have rewinds)",
+};
+
+struct logical_conflict_info {
+ enum conflict_and_info_types type;
+ struct strvec paths;
+};
+
/*** Function Grouping: various utility functions ***/
/*
@@ -567,20 +663,25 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
struct strmap_entry *e;
/* Release and free each strbuf found in output */
- strmap_for_each_entry(&opti->output, &iter, e) {
- struct strbuf *sb = e->value;
- strbuf_release(sb);
+ strmap_for_each_entry(&opti->conflicts, &iter, e) {
+ struct string_list *list = e->value;
+ for (int i = 0; i < list->nr; i++) {
+ struct logical_conflict_info *info =
+ list->items[i].util;
+ strvec_clear(&info->paths);
+ }
/*
- * While strictly speaking we don't need to free(sb)
- * here because we could pass free_values=1 when
- * calling strmap_clear() on opti->output, that would
- * require strmap_clear to do another
- * strmap_for_each_entry() loop, so we just free it
- * while we're iterating anyway.
+ * While strictly speaking we don't need to
+ * free(conflicts) here because we could pass
+ * free_values=1 when calling strmap_clear() on
+ * opti->conflicts, that would require strmap_clear
+ * to do another strmap_for_each_entry() loop, so we
+ * just free it while we're iterating anyway.
*/
- free(sb);
+ string_list_clear(list, 1);
+ free(list);
}
- strmap_clear(&opti->output, 0);
+ strmap_clear(&opti->conflicts, 0);
}
mem_pool_discard(&opti->pool, 0);
@@ -627,29 +728,58 @@ static void format_commit(struct strbuf *sb,
strbuf_addch(sb, '\n');
}
-__attribute__((format (printf, 4, 5)))
+__attribute__((format (printf, 8, 9)))
static void path_msg(struct merge_options *opt,
- const char *path,
+ enum conflict_and_info_types type,
int omittable_hint, /* skippable under --remerge-diff */
+ const char *primary_path,
+ const char *other_path_1, /* may be NULL */
+ const char *other_path_2, /* may be NULL */
+ struct string_list *other_paths, /* may be NULL */
const char *fmt, ...)
{
va_list ap;
- struct strbuf *sb, *dest;
+ struct string_list *path_conflicts;
+ struct logical_conflict_info *info;
+ struct strbuf buf = STRBUF_INIT;
+ struct strbuf *dest;
struct strbuf tmp = STRBUF_INIT;
+ /* Sanity checks */
+ assert(omittable_hint ==
+ !starts_with(type_short_descriptions[type], "CONFLICT") ||
+ type == CONFLICT_DIR_RENAME_SUGGESTED ||
+ type == CONFLICT_PRESENT_DESPITE_SKIPPED);
if (opt->record_conflict_msgs_as_headers && omittable_hint)
return; /* Do not record mere hints in headers */
if (opt->priv->call_depth && opt->verbosity < 5)
return; /* Ignore messages from inner merges */
- sb = strmap_get(&opt->priv->output, path);
- if (!sb) {
- sb = xmalloc(sizeof(*sb));
- strbuf_init(sb, 0);
- strmap_put(&opt->priv->output, path, sb);
+ /* Ensure path_conflicts (ptr to array of logical_conflict) allocated */
+ path_conflicts = strmap_get(&opt->priv->conflicts, primary_path);
+ if (!path_conflicts) {
+ path_conflicts = xmalloc(sizeof(*path_conflicts));
+ string_list_init_dup(path_conflicts);
+ strmap_put(&opt->priv->conflicts, primary_path, path_conflicts);
}
- dest = (opt->record_conflict_msgs_as_headers ? &tmp : sb);
+ /* Add a logical_conflict at the end to store info from this call */
+ info = xcalloc(1, sizeof(*info));
+ info->type = type;
+ strvec_init(&info->paths);
+
+ /* Handle the list of paths */
+ strvec_push(&info->paths, primary_path);
+ if (other_path_1)
+ strvec_push(&info->paths, other_path_1);
+ if (other_path_2)
+ strvec_push(&info->paths, other_path_2);
+ if (other_paths)
+ for (int i = 0; i < other_paths->nr; i++)
+ strvec_push(&info->paths, other_paths->items[i].string);
+
+ /* Handle message and its format, in normal case */
+ dest = (opt->record_conflict_msgs_as_headers ? &tmp : &buf);
va_start(ap, fmt);
if (opt->priv->call_depth) {
@@ -660,32 +790,32 @@ static void path_msg(struct merge_options *opt,
strbuf_vaddf(dest, fmt, ap);
va_end(ap);
+ /* Handle specialized formatting of message under --remerge-diff */
if (opt->record_conflict_msgs_as_headers) {
int i_sb = 0, i_tmp = 0;
/* Start with the specified prefix */
if (opt->msg_header_prefix)
- strbuf_addf(sb, "%s ", opt->msg_header_prefix);
+ strbuf_addf(&buf, "%s ", opt->msg_header_prefix);
/* Copy tmp to sb, adding spaces after newlines */
- strbuf_grow(sb, sb->len + 2*tmp.len); /* more than sufficient */
+ strbuf_grow(&buf, buf.len + 2*tmp.len); /* more than sufficient */
for (; i_tmp < tmp.len; i_tmp++, i_sb++) {
/* Copy next character from tmp to sb */
- sb->buf[sb->len + i_sb] = tmp.buf[i_tmp];
+ buf.buf[buf.len + i_sb] = tmp.buf[i_tmp];
/* If we copied a newline, add a space */
if (tmp.buf[i_tmp] == '\n')
- sb->buf[++i_sb] = ' ';
+ buf.buf[++i_sb] = ' ';
}
/* Update length and ensure it's NUL-terminated */
- sb->len += i_sb;
- sb->buf[sb->len] = '\0';
+ buf.len += i_sb;
+ buf.buf[buf.len] = '\0';
strbuf_release(&tmp);
}
-
- /* Add final newline character to sb */
- strbuf_addch(sb, '\n');
+ string_list_append_nodup(path_conflicts, strbuf_detach(&buf, NULL))
+ ->util = info;
}
static struct diff_filespec *pool_alloc_filespec(struct mem_pool *pool,
@@ -1627,16 +1757,18 @@ static int merge_submodule(struct merge_options *opt,
return 0;
if (repo_submodule_init(&subrepo, opt->repo, path, null_oid())) {
- path_msg(opt, path, 0,
- _("Failed to merge submodule %s (not checked out)"),
- path);
+ path_msg(opt, CONFLICT_SUBMODULE_NOT_INITIALIZED, 0,
+ path, NULL, NULL, NULL,
+ _("Failed to merge submodule %s (not checked out)"),
+ path);
return 0;
}
if (!(commit_o = lookup_commit_reference(&subrepo, o)) ||
!(commit_a = lookup_commit_reference(&subrepo, a)) ||
!(commit_b = lookup_commit_reference(&subrepo, b))) {
- path_msg(opt, path, 0,
+ path_msg(opt, CONFLICT_SUBMODULE_HISTORY_NOT_AVAILABLE, 0,
+ path, NULL, NULL, NULL,
_("Failed to merge submodule %s (commits not present)"),
path);
goto cleanup;
@@ -1645,7 +1777,8 @@ static int merge_submodule(struct merge_options *opt,
/* check whether both changes are forward */
if (!repo_in_merge_bases(&subrepo, commit_o, commit_a) ||
!repo_in_merge_bases(&subrepo, commit_o, commit_b)) {
- path_msg(opt, path, 0,
+ path_msg(opt, CONFLICT_SUBMODULE_MAY_HAVE_REWINDS, 0,
+ path, NULL, NULL, NULL,
_("Failed to merge submodule %s "
"(commits don't follow merge-base)"),
path);
@@ -1655,7 +1788,8 @@ static int merge_submodule(struct merge_options *opt,
/* Case #1: a is contained in b or vice versa */
if (repo_in_merge_bases(&subrepo, commit_a, commit_b)) {
oidcpy(result, b);
- path_msg(opt, path, 1,
+ path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1,
+ path, NULL, NULL, NULL,
_("Note: Fast-forwarding submodule %s to %s"),
path, oid_to_hex(b));
ret = 1;
@@ -1663,7 +1797,8 @@ static int merge_submodule(struct merge_options *opt,
}
if (repo_in_merge_bases(&subrepo, commit_b, commit_a)) {
oidcpy(result, a);
- path_msg(opt, path, 1,
+ path_msg(opt, INFO_SUBMODULE_FAST_FORWARDING, 1,
+ path, NULL, NULL, NULL,
_("Note: Fast-forwarding submodule %s to %s"),
path, oid_to_hex(a));
ret = 1;
@@ -1686,30 +1821,27 @@ static int merge_submodule(struct merge_options *opt,
&merges);
switch (parent_count) {
case 0:
- path_msg(opt, path, 0, _("Failed to merge submodule %s"), path);
+ path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE, 0,
+ path, NULL, NULL, NULL,
+ _("Failed to merge submodule %s"), path);
break;
case 1:
format_commit(&sb, 4, &subrepo,
(struct commit *)merges.objects[0].item);
- path_msg(opt, path, 0,
+ path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE_BUT_POSSIBLE_RESOLUTION, 0,
+ path, NULL, NULL, NULL,
_("Failed to merge submodule %s, but a possible merge "
- "resolution exists:\n%s\n"),
+ "resolution exists: %s"),
path, sb.buf);
- path_msg(opt, path, 1,
- _("If this is correct simply add it to the index "
- "for example\n"
- "by using:\n\n"
- " git update-index --cacheinfo 160000 %s \"%s\"\n\n"
- "which will accept this suggestion.\n"),
- oid_to_hex(&merges.objects[0].item->oid), path);
strbuf_release(&sb);
break;
default:
for (i = 0; i < merges.nr; i++)
format_commit(&sb, 4, &subrepo,
(struct commit *)merges.objects[i].item);
- path_msg(opt, path, 0,
+ path_msg(opt, CONFLICT_SUBMODULE_FAILED_TO_MERGE_BUT_POSSIBLE_RESOLUTION, 0,
+ path, NULL, NULL, NULL,
_("Failed to merge submodule %s, but multiple "
"possible merges exist:\n%s"), path, sb.buf);
strbuf_release(&sb);
@@ -1835,7 +1967,8 @@ static int merge_3way(struct merge_options *opt,
&src1, name1, &src2, name2,
&opt->priv->attr_index, &ll_opts);
if (merge_status == LL_MERGE_BINARY_CONFLICT)
- path_msg(opt, path, 0,
+ path_msg(opt, CONFLICT_BINARY, 0,
+ path, NULL, NULL, NULL,
"warning: Cannot merge binary files: %s (%s vs. %s)",
path, name1, name2);
@@ -1947,7 +2080,8 @@ static int handle_content_merge(struct merge_options *opt,
if (ret)
return -1;
clean &= (merge_status == 0);
- path_msg(opt, path, 1, _("Auto-merging %s"), path);
+ path_msg(opt, INFO_AUTO_MERGING, 1, path, NULL, NULL, NULL,
+ _("Auto-merging %s"), path);
} else if (S_ISGITLINK(a->mode)) {
int two_way = ((S_IFMT & o->mode) != (S_IFMT & a->mode));
clean = merge_submodule(opt, pathnames[0],
@@ -2085,21 +2219,24 @@ static char *handle_path_level_conflicts(struct merge_options *opt,
c_info->reported_already = 1;
strbuf_add_separated_string_list(&collision_paths, ", ",
&c_info->source_files);
- path_msg(opt, new_path, 0,
- _("CONFLICT (implicit dir rename): Existing file/dir "
- "at %s in the way of implicit directory rename(s) "
- "putting the following path(s) there: %s."),
- new_path, collision_paths.buf);
+ path_msg(opt, CONFLICT_DIR_RENAME_FILE_IN_WAY, 0,
+ new_path, NULL, NULL, &c_info->source_files,
+ _("CONFLICT (implicit dir rename): Existing "
+ "file/dir at %s in the way of implicit "
+ "directory rename(s) putting the following "
+ "path(s) there: %s."),
+ new_path, collision_paths.buf);
clean = 0;
} else if (c_info->source_files.nr > 1) {
c_info->reported_already = 1;
strbuf_add_separated_string_list(&collision_paths, ", ",
&c_info->source_files);
- path_msg(opt, new_path, 0,
- _("CONFLICT (implicit dir rename): Cannot map more "
- "than one path to %s; implicit directory renames "
- "tried to put these paths there: %s"),
- new_path, collision_paths.buf);
+ path_msg(opt, CONFLICT_DIR_RENAME_COLLISION, 0,
+ new_path, NULL, NULL, &c_info->source_files,
+ _("CONFLICT (implicit dir rename): Cannot map "
+ "more than one path to %s; implicit directory "
+ "renames tried to put these paths there: %s"),
+ new_path, collision_paths.buf);
clean = 0;
}
@@ -2153,13 +2290,14 @@ static void get_provisional_directory_renames(struct merge_options *opt,
continue;
if (bad_max == max) {
- path_msg(opt, source_dir, 0,
- _("CONFLICT (directory rename split): "
- "Unclear where to rename %s to; it was "
- "renamed to multiple other directories, with "
- "no destination getting a majority of the "
- "files."),
- source_dir);
+ path_msg(opt, CONFLICT_DIR_RENAME_SPLIT, 0,
+ source_dir, NULL, NULL, NULL,
+ _("CONFLICT (directory rename split): "
+ "Unclear where to rename %s to; it was "
+ "renamed to multiple other directories, "
+ "with no destination getting a majority of "
+ "the files."),
+ source_dir);
*clean = 0;
} else {
strmap_put(&renames->dir_renames[side],
@@ -2260,6 +2398,27 @@ static void compute_collisions(struct strmap *collisions,
}
}
+static void free_collisions(struct strmap *collisions)
+{
+ struct hashmap_iter iter;
+ struct strmap_entry *entry;
+
+ /* Free each value in the collisions map */
+ strmap_for_each_entry(collisions, &iter, entry) {
+ struct collision_info *info = entry->value;
+ string_list_clear(&info->source_files, 0);
+ }
+ /*
+ * In compute_collisions(), we set collisions.strdup_strings to 0
+ * so that we wouldn't have to make another copy of the new_path
+ * allocated by apply_dir_rename(). But now that we've used them
+ * and have no other references to these strings, it is time to
+ * deallocate them.
+ */
+ free_strmap_strings(collisions);
+ strmap_clear(collisions, 1);
+}
+
static char *check_for_directory_rename(struct merge_options *opt,
const char *path,
unsigned side_index,
@@ -2268,18 +2427,23 @@ static char *check_for_directory_rename(struct merge_options *opt,
struct strmap *collisions,
int *clean_merge)
{
- char *new_path = NULL;
+ char *new_path;
struct strmap_entry *rename_info;
- struct strmap_entry *otherinfo = NULL;
+ struct strmap_entry *otherinfo;
const char *new_dir;
+ int other_side = 3 - side_index;
+ /*
+ * Cases where we don't have or don't want a directory rename for
+ * this path.
+ */
if (strmap_empty(dir_renames))
- return new_path;
+ return NULL;
+ if (strmap_get(&collisions[other_side], path))
+ return NULL;
rename_info = check_dir_renamed(path, dir_renames);
if (!rename_info)
- return new_path;
- /* old_dir = rename_info->key; */
- new_dir = rename_info->value;
+ return NULL;
/*
* This next part is a little weird. We do not want to do an
@@ -2305,9 +2469,11 @@ static char *check_for_directory_rename(struct merge_options *opt,
* As it turns out, this also prevents N-way transient rename
* confusion; See testcases 9c and 9d of t6043.
*/
+ new_dir = rename_info->value; /* old_dir = rename_info->key; */
otherinfo = strmap_get_entry(dir_rename_exclusions, new_dir);
if (otherinfo) {
- path_msg(opt, rename_info->key, 1,
+ path_msg(opt, INFO_DIR_RENAME_SKIPPED_DUE_TO_RERENAME, 1,
+ rename_info->key, path, new_dir, NULL,
_("WARNING: Avoiding applying %s -> %s rename "
"to %s, because %s itself was renamed."),
rename_info->key, new_dir, path, new_dir);
@@ -2315,7 +2481,8 @@ static char *check_for_directory_rename(struct merge_options *opt,
}
new_path = handle_path_level_conflicts(opt, path, side_index,
- rename_info, collisions);
+ rename_info,
+ &collisions[side_index]);
*clean_merge &= (new_path != NULL);
return new_path;
@@ -2447,14 +2614,16 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
if (opt->detect_directory_renames == MERGE_DIRECTORY_RENAMES_TRUE) {
/* Notify user of updated path */
if (pair->status == 'A')
- path_msg(opt, new_path, 1,
+ path_msg(opt, INFO_DIR_RENAME_APPLIED, 1,
+ new_path, old_path, NULL, NULL,
_("Path updated: %s added in %s inside a "
"directory that was renamed in %s; moving "
"it to %s."),
old_path, branch_with_new_path,
branch_with_dir_rename, new_path);
else
- path_msg(opt, new_path, 1,
+ path_msg(opt, INFO_DIR_RENAME_APPLIED, 1,
+ new_path, old_path, NULL, NULL,
_("Path updated: %s renamed to %s in %s, "
"inside a directory that was renamed in %s; "
"moving it to %s."),
@@ -2467,7 +2636,8 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
*/
ci->path_conflict = 1;
if (pair->status == 'A')
- path_msg(opt, new_path, 1,
+ path_msg(opt, CONFLICT_DIR_RENAME_SUGGESTED, 1,
+ new_path, old_path, NULL, NULL,
_("CONFLICT (file location): %s added in %s "
"inside a directory that was renamed in %s, "
"suggesting it should perhaps be moved to "
@@ -2475,7 +2645,8 @@ static void apply_directory_rename_modifications(struct merge_options *opt,
old_path, branch_with_new_path,
branch_with_dir_rename, new_path);
else
- path_msg(opt, new_path, 1,
+ path_msg(opt, CONFLICT_DIR_RENAME_SUGGESTED, 1,
+ new_path, old_path, NULL, NULL,
_("CONFLICT (file location): %s renamed to %s "
"in %s, inside a directory that was renamed "
"in %s, suggesting it should perhaps be "
@@ -2631,7 +2802,8 @@ static int process_renames(struct merge_options *opt,
* and remove the setting of base->path_conflict to 1.
*/
base->path_conflict = 1;
- path_msg(opt, oldpath, 0,
+ path_msg(opt, CONFLICT_RENAME_RENAME, 0,
+ pathnames[0], pathnames[1], pathnames[2], NULL,
_("CONFLICT (rename/rename): %s renamed to "
"%s in %s and to %s in %s."),
pathnames[0],
@@ -2726,7 +2898,8 @@ static int process_renames(struct merge_options *opt,
memcpy(&newinfo->stages[target_index], &merged,
sizeof(merged));
if (!clean) {
- path_msg(opt, newpath, 0,
+ path_msg(opt, CONFLICT_RENAME_COLLIDES, 0,
+ newpath, oldpath, NULL, NULL,
_("CONFLICT (rename involved in "
"collision): rename of %s -> %s has "
"content conflicts AND collides "
@@ -2745,7 +2918,8 @@ static int process_renames(struct merge_options *opt,
*/
newinfo->path_conflict = 1;
- path_msg(opt, newpath, 0,
+ path_msg(opt, CONFLICT_RENAME_DELETE, 0,
+ newpath, oldpath, NULL, NULL,
_("CONFLICT (rename/delete): %s renamed "
"to %s in %s, but deleted in %s."),
oldpath, newpath, rename_branch, delete_branch);
@@ -2769,7 +2943,8 @@ static int process_renames(struct merge_options *opt,
} else if (source_deleted) {
/* rename/delete */
newinfo->path_conflict = 1;
- path_msg(opt, newpath, 0,
+ path_msg(opt, CONFLICT_RENAME_DELETE, 0,
+ newpath, oldpath, NULL, NULL,
_("CONFLICT (rename/delete): %s renamed"
" to %s in %s, but deleted in %s."),
oldpath, newpath,
@@ -3024,18 +3199,15 @@ static int detect_regular_renames(struct merge_options *opt,
static int collect_renames(struct merge_options *opt,
struct diff_queue_struct *result,
unsigned side_index,
+ struct strmap *collisions,
struct strmap *dir_renames_for_side,
struct strmap *rename_exclusions)
{
int i, clean = 1;
- struct strmap collisions;
struct diff_queue_struct *side_pairs;
- struct hashmap_iter iter;
- struct strmap_entry *entry;
struct rename_info *renames = &opt->priv->renames;
side_pairs = &renames->pairs[side_index];
- compute_collisions(&collisions, dir_renames_for_side, side_pairs);
for (i = 0; i < side_pairs->nr; ++i) {
struct diff_filepair *p = side_pairs->queue[i];
@@ -3051,7 +3223,7 @@ static int collect_renames(struct merge_options *opt,
side_index,
dir_renames_for_side,
rename_exclusions,
- &collisions,
+ collisions,
&clean);
possibly_cache_new_pair(renames, p, side_index, new_path);
@@ -3077,20 +3249,6 @@ static int collect_renames(struct merge_options *opt,
result->queue[result->nr++] = p;
}
- /* Free each value in the collisions map */
- strmap_for_each_entry(&collisions, &iter, entry) {
- struct collision_info *info = entry->value;
- string_list_clear(&info->source_files, 0);
- }
- /*
- * In compute_collisions(), we set collisions.strdup_strings to 0
- * so that we wouldn't have to make another copy of the new_path
- * allocated by apply_dir_rename(). But now that we've used them
- * and have no other references to these strings, it is time to
- * deallocate them.
- */
- free_strmap_strings(&collisions);
- strmap_clear(&collisions, 1);
return clean;
}
@@ -3101,6 +3259,7 @@ static int detect_and_process_renames(struct merge_options *opt,
{
struct diff_queue_struct combined = { 0 };
struct rename_info *renames = &opt->priv->renames;
+ struct strmap collisions[3];
int need_dir_renames, s, i, clean = 1;
unsigned detection_run = 0;
@@ -3150,12 +3309,22 @@ static int detect_and_process_renames(struct merge_options *opt,
ALLOC_GROW(combined.queue,
renames->pairs[1].nr + renames->pairs[2].nr,
combined.alloc);
+ for (i = MERGE_SIDE1; i <= MERGE_SIDE2; i++) {
+ int other_side = 3 - i;
+ compute_collisions(&collisions[i],
+ &renames->dir_renames[other_side],
+ &renames->pairs[i]);
+ }
clean &= collect_renames(opt, &combined, MERGE_SIDE1,
+ collisions,
&renames->dir_renames[2],
&renames->dir_renames[1]);
clean &= collect_renames(opt, &combined, MERGE_SIDE2,
+ collisions,
&renames->dir_renames[1],
&renames->dir_renames[2]);
+ for (i = MERGE_SIDE1; i <= MERGE_SIDE2; i++)
+ free_collisions(&collisions[i]);
STABLE_QSORT(combined.queue, combined.nr, compare_pairs);
trace2_region_leave("merge", "directory renames", opt->repo);
@@ -3690,7 +3859,8 @@ static void process_entry(struct merge_options *opt,
path = unique_path(opt, path, branch);
strmap_put(&opt->priv->paths, path, new_ci);
- path_msg(opt, path, 0,
+ path_msg(opt, CONFLICT_FILE_DIRECTORY, 0,
+ path, old_path, NULL, NULL,
_("CONFLICT (file/directory): directory in the way "
"of %s from %s; moving it to %s instead."),
old_path, branch, path);
@@ -3766,15 +3936,23 @@ static void process_entry(struct merge_options *opt,
rename_b = 1;
}
+ if (rename_a)
+ a_path = unique_path(opt, path, opt->branch1);
+ if (rename_b)
+ b_path = unique_path(opt, path, opt->branch2);
+
if (rename_a && rename_b) {
- path_msg(opt, path, 0,
+ path_msg(opt, CONFLICT_DISTINCT_MODES, 0,
+ path, a_path, b_path, NULL,
_("CONFLICT (distinct types): %s had "
"different types on each side; "
"renamed both of them so each can "
"be recorded somewhere."),
path);
} else {
- path_msg(opt, path, 0,
+ path_msg(opt, CONFLICT_DISTINCT_MODES, 0,
+ path, rename_a ? a_path : b_path,
+ NULL, NULL,
_("CONFLICT (distinct types): %s had "
"different types on each side; "
"renamed one of them so each can be "
@@ -3811,14 +3989,10 @@ static void process_entry(struct merge_options *opt,
/* Insert entries into opt->priv_paths */
assert(rename_a || rename_b);
- if (rename_a) {
- a_path = unique_path(opt, path, opt->branch1);
+ if (rename_a)
strmap_put(&opt->priv->paths, a_path, ci);
- }
- if (rename_b)
- b_path = unique_path(opt, path, opt->branch2);
- else
+ if (!rename_b)
b_path = path;
strmap_put(&opt->priv->paths, b_path, new_ci);
@@ -3869,7 +4043,8 @@ static void process_entry(struct merge_options *opt,
reason = _("add/add");
if (S_ISGITLINK(merged_file.mode))
reason = _("submodule");
- path_msg(opt, path, 0,
+ path_msg(opt, CONFLICT_CONTENTS, 0,
+ path, NULL, NULL, NULL,
_("CONFLICT (%s): Merge conflict in %s"),
reason, path);
}
@@ -3913,7 +4088,8 @@ static void process_entry(struct merge_options *opt,
* since the contents were not modified.
*/
} else {
- path_msg(opt, path, 0,
+ path_msg(opt, CONFLICT_MODIFY_DELETE, 0,
+ path, NULL, NULL, NULL,
_("CONFLICT (modify/delete): %s deleted in %s "
"and modified in %s. Version %s of %s left "
"in tree."),
@@ -4209,7 +4385,8 @@ static int record_conflicted_index_entries(struct merge_options *opt)
path,
"cruft");
- path_msg(opt, path, 1,
+ path_msg(opt, CONFLICT_PRESENT_DESPITE_SKIPPED, 1,
+ path, NULL, NULL, NULL,
_("Note: %s not up to date and in way of checking out conflicted version; old copy renamed to %s"),
path, new_name);
errs |= rename(path, new_name);
@@ -4257,6 +4434,93 @@ static int record_conflicted_index_entries(struct merge_options *opt)
return errs;
}
+void merge_display_update_messages(struct merge_options *opt,
+ int detailed,
+ struct merge_result *result)
+{
+ struct merge_options_internal *opti = result->priv;
+ struct hashmap_iter iter;
+ struct strmap_entry *e;
+ struct string_list olist = STRING_LIST_INIT_NODUP;
+
+ if (opt->record_conflict_msgs_as_headers)
+ BUG("Either display conflict messages or record them as headers, not both");
+
+ trace2_region_enter("merge", "display messages", opt->repo);
+
+ /* Hack to pre-allocate olist to the desired size */
+ ALLOC_GROW(olist.items, strmap_get_size(&opti->conflicts),
+ olist.alloc);
+
+ /* Put every entry from output into olist, then sort */
+ strmap_for_each_entry(&opti->conflicts, &iter, e) {
+ string_list_append(&olist, e->key)->util = e->value;
+ }
+ string_list_sort(&olist);
+
+ /* Iterate over the items, printing them */
+ for (int path_nr = 0; path_nr < olist.nr; ++path_nr) {
+ struct string_list *conflicts = olist.items[path_nr].util;
+ for (int i = 0; i < conflicts->nr; i++) {
+ struct logical_conflict_info *info =
+ conflicts->items[i].util;
+
+ if (detailed) {
+ printf("%lu", (unsigned long)info->paths.nr);
+ putchar('\0');
+ for (int n = 0; n < info->paths.nr; n++) {
+ fputs(info->paths.v[n], stdout);
+ putchar('\0');
+ }
+ fputs(type_short_descriptions[info->type],
+ stdout);
+ putchar('\0');
+ }
+ puts(conflicts->items[i].string);
+ if (detailed)
+ putchar('\0');
+ }
+ }
+ string_list_clear(&olist, 0);
+
+ /* Also include needed rename limit adjustment now */
+ diff_warn_rename_limit("merge.renamelimit",
+ opti->renames.needed_limit, 0);
+
+ trace2_region_leave("merge", "display messages", opt->repo);
+}
+
+void merge_get_conflicted_files(struct merge_result *result,
+ struct string_list *conflicted_files)
+{
+ struct hashmap_iter iter;
+ struct strmap_entry *e;
+ struct merge_options_internal *opti = result->priv;
+
+ strmap_for_each_entry(&opti->conflicted, &iter, e) {
+ const char *path = e->key;
+ struct conflict_info *ci = e->value;
+ int i;
+
+ VERIFY_CI(ci);
+
+ for (i = MERGE_BASE; i <= MERGE_SIDE2; i++) {
+ struct stage_info *si;
+
+ if (!(ci->filemask & (1ul << i)))
+ continue;
+
+ si = xmalloc(sizeof(*si));
+ si->stage = i+1;
+ si->mode = ci->stages[i].mode;
+ oidcpy(&si->oid, &ci->stages[i].oid);
+ string_list_append(conflicted_files, path)->util = si;
+ }
+ }
+ /* string_list_sort() uses a stable sort, so we're good */
+ string_list_sort(conflicted_files);
+}
+
void merge_switch_to_result(struct merge_options *opt,
struct tree *head,
struct merge_result *result,
@@ -4294,43 +4558,8 @@ void merge_switch_to_result(struct merge_options *opt,
fclose(fp);
trace2_region_leave("merge", "write_auto_merge", opt->repo);
}
-
- if (display_update_msgs) {
- struct merge_options_internal *opti = result->priv;
- struct hashmap_iter iter;
- struct strmap_entry *e;
- struct string_list olist = STRING_LIST_INIT_NODUP;
- int i;
-
- if (opt->record_conflict_msgs_as_headers)
- BUG("Either display conflict messages or record them as headers, not both");
-
- trace2_region_enter("merge", "display messages", opt->repo);
-
- /* Hack to pre-allocate olist to the desired size */
- ALLOC_GROW(olist.items, strmap_get_size(&opti->output),
- olist.alloc);
-
- /* Put every entry from output into olist, then sort */
- strmap_for_each_entry(&opti->output, &iter, e) {
- string_list_append(&olist, e->key)->util = e->value;
- }
- string_list_sort(&olist);
-
- /* Iterate over the items, printing them */
- for (i = 0; i < olist.nr; ++i) {
- struct strbuf *sb = olist.items[i].util;
-
- printf("%s", sb->buf);
- }
- string_list_clear(&olist, 0);
-
- /* Also include needed rename limit adjustment now */
- diff_warn_rename_limit("merge.renamelimit",
- opti->renames.needed_limit, 0);
-
- trace2_region_leave("merge", "display messages", opt->repo);
- }
+ if (display_update_msgs)
+ merge_display_update_messages(opt, /* detailed */ 0, result);
merge_finalize(opt, result);
}
@@ -4504,11 +4733,11 @@ static void merge_start(struct merge_options *opt, struct merge_result *result)
strmap_init_with_options(&opt->priv->conflicted, pool, 0);
/*
- * keys & strbufs in output will sometimes need to outlive "paths",
- * so it will have a copy of relevant keys. It's probably a small
- * subset of the overall paths that have special output.
+ * keys & string_lists in conflicts will sometimes need to outlive
+ * "paths", so it will have a copy of relevant keys. It's probably
+ * a small subset of the overall paths that have special output.
*/
- strmap_init(&opt->priv->output);
+ strmap_init(&opt->priv->conflicts);
trace2_region_leave("merge", "allocate/init", opt->repo);
}
@@ -4609,7 +4838,8 @@ redo:
trace2_region_leave("merge", "process_entries", opt->repo);
/* Set return values */
- result->path_messages = &opt->priv->output;
+ result->path_messages = &opt->priv->conflicts;
+
result->tree = parse_tree_indirect(&working_tree_oid);
/* existence of conflicted entries implies unclean */
result->clean &= strmap_empty(&opt->priv->conflicted);
diff --git a/merge-ort.h b/merge-ort.h
index fe599b8..a994c9a 100644
--- a/merge-ort.h
+++ b/merge-ort.h
@@ -2,6 +2,7 @@
#define MERGE_ORT_H
#include "merge-recursive.h"
+#include "hash.h"
struct commit;
struct tree;
@@ -27,7 +28,7 @@ struct merge_result {
/*
* Special messages and conflict notices for various paths
*
- * This is a map of pathnames to strbufs. It contains various
+ * This is a map of pathnames to a string_list. It contains various
* warning/conflict/notice messages (possibly multiple per path)
* that callers may want to use.
*/
@@ -80,6 +81,35 @@ void merge_switch_to_result(struct merge_options *opt,
int update_worktree_and_index,
int display_update_msgs);
+/*
+ * Display messages about conflicts and which files were 3-way merged.
+ * Automatically called by merge_switch_to_result() with stream == stdout,
+ * so only call this when bypassing merge_switch_to_result().
+ */
+void merge_display_update_messages(struct merge_options *opt,
+ int detailed,
+ struct merge_result *result);
+
+struct stage_info {
+ struct object_id oid;
+ int mode;
+ int stage;
+};
+
+/*
+ * Provide a list of path -> {struct stage_info*} mappings for
+ * all conflicted files. Note that each path could appear up to three
+ * times in the list, corresponding to 3 different stage entries. In short,
+ * this basically provides the info that would be printed by `ls-files -u`.
+ *
+ * result should have been populated by a call to
+ * one of the merge_incore_[non]recursive() functions.
+ *
+ * conflicted_files should be empty before calling this function.
+ */
+void merge_get_conflicted_files(struct merge_result *result,
+ struct string_list *conflicted_files);
+
/* Do needed cleanup when not calling merge_switch_to_result() */
void merge_finalize(struct merge_options *opt,
struct merge_result *result);
diff --git a/mergetools/vimdiff b/mergetools/vimdiff
index 461a89b..f770b8f 100644
--- a/mergetools/vimdiff
+++ b/mergetools/vimdiff
@@ -228,14 +228,14 @@ gen_cmd_aux () {
elif ! test -z "$index_horizontal_split"
then
- before="split"
+ before="leftabove split"
after="wincmd j"
index=$index_horizontal_split
terminate="true"
elif ! test -z "$index_vertical_split"
then
- before="vertical split"
+ before="leftabove vertical split"
after="wincmd l"
index=$index_vertical_split
terminate="true"
@@ -310,7 +310,7 @@ gen_cmd () {
#
# gen_cmd "@LOCAL , REMOTE"
# |
- # `-> FINAL_CMD == "-c \"echo | vertical split | 1b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\""
+ # `-> FINAL_CMD == "-c \"echo | leftabove vertical split | 1b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\""
# FINAL_TARGET == "LOCAL"
LAYOUT=$1
@@ -414,8 +414,8 @@ merge_cmd () {
if $base_present
then
- eval "$merge_tool_path" \
- -f "$FINAL_CMD" "$LOCAL" "$BASE" "$REMOTE" "$MERGED"
+ eval '"$merge_tool_path"' \
+ -f "$FINAL_CMD" '"$LOCAL"' '"$BASE"' '"$REMOTE"' '"$MERGED"'
else
# If there is no BASE (example: a merge conflict in a new file
# with the same name created in both braches which didn't exist
@@ -424,8 +424,8 @@ merge_cmd () {
FINAL_CMD=$(echo "$FINAL_CMD" | \
sed -e 's:2b:quit:g' -e 's:3b:2b:g' -e 's:4b:3b:g')
- eval "$merge_tool_path" \
- -f "$FINAL_CMD" "$LOCAL" "$REMOTE" "$MERGED"
+ eval '"$merge_tool_path"' \
+ -f "$FINAL_CMD" '"$LOCAL"' '"$REMOTE"' '"$MERGED"'
fi
ret="$?"
@@ -555,22 +555,22 @@ run_unit_tests () {
TEST_CASE_15=" (( (LOCAL , BASE , REMOTE) / MERGED)) +(BASE) , LOCAL+ BASE , REMOTE+ (((LOCAL / BASE / REMOTE)) , MERGED ) "
TEST_CASE_16="LOCAL,BASE,REMOTE / MERGED + BASE,LOCAL + BASE,REMOTE + (LOCAL / BASE / REMOTE),MERGED"
- EXPECTED_CMD_01="-c \"echo | split | vertical split | 1b | wincmd l | vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_02="-c \"echo | vertical split | 1b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_03="-c \"echo | vertical split | 1b | wincmd l | vertical split | 4b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_01="-c \"echo | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_02="-c \"echo | leftabove vertical split | 1b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_03="-c \"echo | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 4b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\""
EXPECTED_CMD_04="-c \"echo | 4b | bufdo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_05="-c \"echo | split | 1b | wincmd j | split | 4b | wincmd j | 3b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_06="-c \"echo | vertical split | split | 1b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_07="-c \"echo | vertical split | 4b | wincmd l | split | 1b | wincmd j | 3b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_08="-c \"echo | split | vertical split | 1b | wincmd l | 3b | wincmd j | 4b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_09="-c \"echo | split | 4b | wincmd j | vertical split | 1b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_10="-c \"echo | vertical split | split | 1b | wincmd j | split | 2b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_11="-c \"echo | -tabnew | split | vertical split | 1b | wincmd l | vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnext | -tabnew | vertical split | 2b | wincmd l | 1b | tabnext | -tabnew | vertical split | 2b | wincmd l | 3b | tabnext | vertical split | split | 1b | wincmd j | split | 2b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_12="-c \"echo | vertical split | split | vertical split | 1b | wincmd l | 3b | wincmd j | 2b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_13="-c \"echo | vertical split | split | vertical split | 1b | wincmd l | 3b | wincmd j | 2b | wincmd l | vertical split | split | 1b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_14="-c \"echo | -tabnew | vertical split | 2b | wincmd l | 3b | tabnext | vertical split | 2b | wincmd l | 1b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_15="-c \"echo | -tabnew | split | vertical split | 1b | wincmd l | vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnext | -tabnew | vertical split | 2b | wincmd l | 1b | tabnext | -tabnew | vertical split | 2b | wincmd l | 3b | tabnext | vertical split | split | 1b | wincmd j | split | 2b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
- EXPECTED_CMD_16="-c \"echo | -tabnew | split | vertical split | 1b | wincmd l | vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnext | -tabnew | vertical split | 2b | wincmd l | 1b | tabnext | -tabnew | vertical split | 2b | wincmd l | 3b | tabnext | vertical split | split | 1b | wincmd j | split | 2b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_05="-c \"echo | leftabove split | 1b | wincmd j | leftabove split | 4b | wincmd j | 3b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_06="-c \"echo | leftabove vertical split | leftabove split | 1b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_07="-c \"echo | leftabove vertical split | 4b | wincmd l | leftabove split | 1b | wincmd j | 3b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_08="-c \"echo | leftabove split | leftabove vertical split | 1b | wincmd l | 3b | wincmd j | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_09="-c \"echo | leftabove split | 4b | wincmd j | leftabove vertical split | 1b | wincmd l | 3b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_10="-c \"echo | leftabove vertical split | leftabove split | 1b | wincmd j | leftabove split | 2b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_11="-c \"echo | -tabnew | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnext | -tabnew | leftabove vertical split | 2b | wincmd l | 1b | tabnext | -tabnew | leftabove vertical split | 2b | wincmd l | 3b | tabnext | leftabove vertical split | leftabove split | 1b | wincmd j | leftabove split | 2b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_12="-c \"echo | leftabove vertical split | leftabove split | leftabove vertical split | 1b | wincmd l | 3b | wincmd j | 2b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_13="-c \"echo | leftabove vertical split | leftabove split | leftabove vertical split | 1b | wincmd l | 3b | wincmd j | 2b | wincmd l | leftabove vertical split | leftabove split | 1b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_14="-c \"echo | -tabnew | leftabove vertical split | 2b | wincmd l | 3b | tabnext | leftabove vertical split | 2b | wincmd l | 1b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_15="-c \"echo | -tabnew | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnext | -tabnew | leftabove vertical split | 2b | wincmd l | 1b | tabnext | -tabnew | leftabove vertical split | 2b | wincmd l | 3b | tabnext | leftabove vertical split | leftabove split | 1b | wincmd j | leftabove split | 2b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
+ EXPECTED_CMD_16="-c \"echo | -tabnew | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | 2b | wincmd l | 3b | wincmd j | 4b | tabnext | -tabnew | leftabove vertical split | 2b | wincmd l | 1b | tabnext | -tabnew | leftabove vertical split | 2b | wincmd l | 3b | tabnext | leftabove vertical split | leftabove split | 1b | wincmd j | leftabove split | 2b | wincmd j | 3b | wincmd l | 4b | tabdo windo diffthis\" -c \"tabfirst\""
EXPECTED_TARGET_01="MERGED"
EXPECTED_TARGET_02="LOCAL"
@@ -614,6 +614,37 @@ run_unit_tests () {
fi
done
+ # verify that `merge_cmd` handles paths with spaces
+ record_parameters () {
+ >actual
+ for arg
+ do
+ echo "$arg" >>actual
+ done
+ }
+
+ base_present=false
+ LOCAL='lo cal'
+ BASE='ba se'
+ REMOTE="' '"
+ MERGED='mer ged'
+ merge_tool_path=record_parameters
+
+ merge_cmd vimdiff || at_least_one_ko=true
+
+ cat >expect <<-\EOF
+ -f
+ -c
+ echo | leftabove split | leftabove vertical split | 1b | wincmd l | leftabove vertical split | quit | wincmd l | 2b | wincmd j | 3b | tabdo windo diffthis
+ -c
+ tabfirst
+ lo cal
+ ' '
+ mer ged
+ EOF
+
+ diff -u expect actual || at_least_one_ko=true
+
if test "$at_least_one_ko" = "true"
then
return 255
diff --git a/midx.c b/midx.c
index 5f0dd38..4e956ca 100644
--- a/midx.c
+++ b/midx.c
@@ -1053,40 +1053,34 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr
return cb.commits;
}
-static int write_midx_bitmap(char *midx_name, unsigned char *midx_hash,
- struct write_midx_context *ctx,
- const char *refs_snapshot,
+static int write_midx_bitmap(const char *midx_name,
+ const unsigned char *midx_hash,
+ struct packing_data *pdata,
+ struct commit **commits,
+ uint32_t commits_nr,
+ uint32_t *pack_order,
unsigned flags)
{
- struct packing_data pdata;
- struct pack_idx_entry **index;
- struct commit **commits = NULL;
- uint32_t i, commits_nr;
+ int ret, i;
uint16_t options = 0;
- char *bitmap_name = xstrfmt("%s-%s.bitmap", midx_name, hash_to_hex(midx_hash));
- int ret;
-
- if (!ctx->entries_nr)
- BUG("cannot write a bitmap without any objects");
+ struct pack_idx_entry **index;
+ char *bitmap_name = xstrfmt("%s-%s.bitmap", midx_name,
+ hash_to_hex(midx_hash));
if (flags & MIDX_WRITE_BITMAP_HASH_CACHE)
options |= BITMAP_OPT_HASH_CACHE;
- prepare_midx_packing_data(&pdata, ctx);
-
- commits = find_commits_for_midx_bitmap(&commits_nr, refs_snapshot, ctx);
-
/*
* Build the MIDX-order index based on pdata.objects (which is already
* in MIDX order; c.f., 'midx_pack_order_cmp()' for the definition of
* this order).
*/
- ALLOC_ARRAY(index, pdata.nr_objects);
- for (i = 0; i < pdata.nr_objects; i++)
- index[i] = &pdata.objects[i].idx;
+ ALLOC_ARRAY(index, pdata->nr_objects);
+ for (i = 0; i < pdata->nr_objects; i++)
+ index[i] = &pdata->objects[i].idx;
bitmap_writer_show_progress(flags & MIDX_PROGRESS);
- bitmap_writer_build_type_index(&pdata, index, pdata.nr_objects);
+ bitmap_writer_build_type_index(pdata, index, pdata->nr_objects);
/*
* bitmap_writer_finish expects objects in lex order, but pack_order
@@ -1101,16 +1095,16 @@ static int write_midx_bitmap(char *midx_name, unsigned char *midx_hash,
* happens between bitmap_writer_build_type_index() and
* bitmap_writer_finish().
*/
- for (i = 0; i < pdata.nr_objects; i++)
- index[ctx->pack_order[i]] = &pdata.objects[i].idx;
+ for (i = 0; i < pdata->nr_objects; i++)
+ index[pack_order[i]] = &pdata->objects[i].idx;
bitmap_writer_select_commits(commits, commits_nr, -1);
- ret = bitmap_writer_build(&pdata);
+ ret = bitmap_writer_build(pdata);
if (ret < 0)
goto cleanup;
bitmap_writer_set_checksum(midx_hash);
- bitmap_writer_finish(index, pdata.nr_objects, bitmap_name, options);
+ bitmap_writer_finish(index, pdata->nr_objects, bitmap_name, options);
cleanup:
free(index);
@@ -1443,14 +1437,40 @@ static int write_midx_internal(const char *object_dir,
if (flags & MIDX_WRITE_REV_INDEX &&
git_env_bool("GIT_TEST_MIDX_WRITE_REV", 0))
write_midx_reverse_index(midx_name.buf, midx_hash, &ctx);
+
if (flags & MIDX_WRITE_BITMAP) {
- if (write_midx_bitmap(midx_name.buf, midx_hash, &ctx,
- refs_snapshot, flags) < 0) {
+ struct packing_data pdata;
+ struct commit **commits;
+ uint32_t commits_nr;
+
+ if (!ctx.entries_nr)
+ BUG("cannot write a bitmap without any objects");
+
+ prepare_midx_packing_data(&pdata, &ctx);
+
+ commits = find_commits_for_midx_bitmap(&commits_nr, refs_snapshot, &ctx);
+
+ /*
+ * The previous steps translated the information from
+ * 'entries' into information suitable for constructing
+ * bitmaps. We no longer need that array, so clear it to
+ * reduce memory pressure.
+ */
+ FREE_AND_NULL(ctx.entries);
+ ctx.entries_nr = 0;
+
+ if (write_midx_bitmap(midx_name.buf, midx_hash, &pdata,
+ commits, commits_nr, ctx.pack_order,
+ flags) < 0) {
error(_("could not write multi-pack bitmap"));
result = 1;
goto cleanup;
}
}
+ /*
+ * NOTE: Do not use ctx.entries beyond this point, since it might
+ * have been freed in the previous if block.
+ */
if (ctx.m)
close_object_store(the_repository->objects);
diff --git a/object-file.c b/object-file.c
index 6c8e3b1..5b270f0 100644
--- a/object-file.c
+++ b/object-file.c
@@ -1951,6 +1951,96 @@ static int create_tmpfile(struct strbuf *tmp, const char *filename)
return fd;
}
+/**
+ * Common steps for loose object writers to start writing loose
+ * objects:
+ *
+ * - Create tmpfile for the loose object.
+ * - Setup zlib stream for compression.
+ * - Start to feed header to zlib stream.
+ *
+ * Returns a "fd", which should later be provided to
+ * end_loose_object_common().
+ */
+static int start_loose_object_common(struct strbuf *tmp_file,
+ const char *filename, unsigned flags,
+ git_zstream *stream,
+ unsigned char *buf, size_t buflen,
+ git_hash_ctx *c,
+ char *hdr, int hdrlen)
+{
+ int fd;
+
+ fd = create_tmpfile(tmp_file, filename);
+ if (fd < 0) {
+ if (flags & HASH_SILENT)
+ return -1;
+ else if (errno == EACCES)
+ return error(_("insufficient permission for adding "
+ "an object to repository database %s"),
+ get_object_directory());
+ else
+ return error_errno(
+ _("unable to create temporary file"));
+ }
+
+ /* Setup zlib stream for compression */
+ git_deflate_init(stream, zlib_compression_level);
+ stream->next_out = buf;
+ stream->avail_out = buflen;
+ the_hash_algo->init_fn(c);
+
+ /* Start to feed header to zlib stream */
+ stream->next_in = (unsigned char *)hdr;
+ stream->avail_in = hdrlen;
+ while (git_deflate(stream, 0) == Z_OK)
+ ; /* nothing */
+ the_hash_algo->update_fn(c, hdr, hdrlen);
+
+ return fd;
+}
+
+/**
+ * Common steps for the inner git_deflate() loop for writing loose
+ * objects. Returns what git_deflate() returns.
+ */
+static int write_loose_object_common(git_hash_ctx *c,
+ git_zstream *stream, const int flush,
+ unsigned char *in0, const int fd,
+ unsigned char *compressed,
+ const size_t compressed_len)
+{
+ int ret;
+
+ ret = git_deflate(stream, flush ? Z_FINISH : 0);
+ the_hash_algo->update_fn(c, in0, stream->next_in - in0);
+ if (write_buffer(fd, compressed, stream->next_out - compressed) < 0)
+ die(_("unable to write loose object file"));
+ stream->next_out = compressed;
+ stream->avail_out = compressed_len;
+
+ return ret;
+}
+
+/**
+ * Common steps for loose object writers to end writing loose objects:
+ *
+ * - End the compression of zlib stream.
+ * - Get the calculated oid to "oid".
+ */
+static int end_loose_object_common(git_hash_ctx *c, git_zstream *stream,
+ struct object_id *oid)
+{
+ int ret;
+
+ ret = git_deflate_end_gently(stream);
+ if (ret != Z_OK)
+ return ret;
+ the_hash_algo->final_oid_fn(oid, c);
+
+ return Z_OK;
+}
+
static int write_loose_object(const struct object_id *oid, char *hdr,
int hdrlen, const void *buf, unsigned long len,
time_t mtime, unsigned flags)
@@ -1968,50 +2058,29 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
loose_object_path(the_repository, &filename, oid);
- fd = create_tmpfile(&tmp_file, filename.buf);
- if (fd < 0) {
- if (flags & HASH_SILENT)
- return -1;
- else if (errno == EACCES)
- return error(_("insufficient permission for adding an object to repository database %s"), get_object_directory());
- else
- return error_errno(_("unable to create temporary file"));
- }
-
- /* Set it up */
- git_deflate_init(&stream, zlib_compression_level);
- stream.next_out = compressed;
- stream.avail_out = sizeof(compressed);
- the_hash_algo->init_fn(&c);
-
- /* First header.. */
- stream.next_in = (unsigned char *)hdr;
- stream.avail_in = hdrlen;
- while (git_deflate(&stream, 0) == Z_OK)
- ; /* nothing */
- the_hash_algo->update_fn(&c, hdr, hdrlen);
+ fd = start_loose_object_common(&tmp_file, filename.buf, flags,
+ &stream, compressed, sizeof(compressed),
+ &c, hdr, hdrlen);
+ if (fd < 0)
+ return -1;
/* Then the data itself.. */
stream.next_in = (void *)buf;
stream.avail_in = len;
do {
unsigned char *in0 = stream.next_in;
- ret = git_deflate(&stream, Z_FINISH);
- the_hash_algo->update_fn(&c, in0, stream.next_in - in0);
- if (write_buffer(fd, compressed, stream.next_out - compressed) < 0)
- die(_("unable to write loose object file"));
- stream.next_out = compressed;
- stream.avail_out = sizeof(compressed);
+
+ ret = write_loose_object_common(&c, &stream, 1, in0, fd,
+ compressed, sizeof(compressed));
} while (ret == Z_OK);
if (ret != Z_STREAM_END)
die(_("unable to deflate new object %s (%d)"), oid_to_hex(oid),
ret);
- ret = git_deflate_end_gently(&stream);
+ ret = end_loose_object_common(&c, &stream, &parano_oid);
if (ret != Z_OK)
die(_("deflateEnd on object %s failed (%d)"), oid_to_hex(oid),
ret);
- the_hash_algo->final_oid_fn(&parano_oid, &c);
if (!oideq(oid, &parano_oid))
die(_("confused by unstable object source data for %s"),
oid_to_hex(oid));
@@ -2050,6 +2119,110 @@ static int freshen_packed_object(const struct object_id *oid)
return 1;
}
+int stream_loose_object(struct input_stream *in_stream, size_t len,
+ struct object_id *oid)
+{
+ int fd, ret, err = 0, flush = 0;
+ unsigned char compressed[4096];
+ git_zstream stream;
+ git_hash_ctx c;
+ struct strbuf tmp_file = STRBUF_INIT;
+ struct strbuf filename = STRBUF_INIT;
+ int dirlen;
+ char hdr[MAX_HEADER_LEN];
+ int hdrlen;
+
+ if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
+ prepare_loose_object_bulk_checkin();
+
+ /* Since oid is not determined, save tmp file to odb path. */
+ strbuf_addf(&filename, "%s/", get_object_directory());
+ hdrlen = format_object_header(hdr, sizeof(hdr), OBJ_BLOB, len);
+
+ /*
+ * Common steps for write_loose_object and stream_loose_object to
+ * start writing loose objects:
+ *
+ * - Create tmpfile for the loose object.
+ * - Setup zlib stream for compression.
+ * - Start to feed header to zlib stream.
+ */
+ fd = start_loose_object_common(&tmp_file, filename.buf, 0,
+ &stream, compressed, sizeof(compressed),
+ &c, hdr, hdrlen);
+ if (fd < 0) {
+ err = -1;
+ goto cleanup;
+ }
+
+ /* Then the data itself.. */
+ do {
+ unsigned char *in0 = stream.next_in;
+
+ if (!stream.avail_in && !in_stream->is_finished) {
+ const void *in = in_stream->read(in_stream, &stream.avail_in);
+ stream.next_in = (void *)in;
+ in0 = (unsigned char *)in;
+ /* All data has been read. */
+ if (in_stream->is_finished)
+ flush = 1;
+ }
+ ret = write_loose_object_common(&c, &stream, flush, in0, fd,
+ compressed, sizeof(compressed));
+ /*
+ * Unlike write_loose_object(), we do not have the entire
+ * buffer. If we get Z_BUF_ERROR due to too few input bytes,
+ * then we'll replenish them in the next input_stream->read()
+ * call when we loop.
+ */
+ } while (ret == Z_OK || ret == Z_BUF_ERROR);
+
+ if (stream.total_in != len + hdrlen)
+ die(_("write stream object %ld != %"PRIuMAX), stream.total_in,
+ (uintmax_t)len + hdrlen);
+
+ /*
+ * Common steps for write_loose_object and stream_loose_object to
+ * end writing loose oject:
+ *
+ * - End the compression of zlib stream.
+ * - Get the calculated oid.
+ */
+ if (ret != Z_STREAM_END)
+ die(_("unable to stream deflate new object (%d)"), ret);
+ ret = end_loose_object_common(&c, &stream, oid);
+ if (ret != Z_OK)
+ die(_("deflateEnd on stream object failed (%d)"), ret);
+ close_loose_object(fd, tmp_file.buf);
+
+ if (freshen_packed_object(oid) || freshen_loose_object(oid)) {
+ unlink_or_warn(tmp_file.buf);
+ goto cleanup;
+ }
+
+ loose_object_path(the_repository, &filename, oid);
+
+ /* We finally know the object path, and create the missing dir. */
+ dirlen = directory_size(filename.buf);
+ if (dirlen) {
+ struct strbuf dir = STRBUF_INIT;
+ strbuf_add(&dir, filename.buf, dirlen);
+
+ if (mkdir_in_gitdir(dir.buf) && errno != EEXIST) {
+ err = error_errno(_("unable to create directory %s"), dir.buf);
+ strbuf_release(&dir);
+ goto cleanup;
+ }
+ strbuf_release(&dir);
+ }
+
+ err = finalize_object_file(tmp_file.buf, filename.buf);
+cleanup:
+ strbuf_release(&tmp_file);
+ strbuf_release(&filename);
+ return err;
+}
+
int write_object_file_flags(const void *buf, unsigned long len,
enum object_type type, struct object_id *oid,
unsigned flags)
diff --git a/object-store.h b/object-store.h
index 539ea43..5222ee5 100644
--- a/object-store.h
+++ b/object-store.h
@@ -46,6 +46,12 @@ struct object_directory {
char *path;
};
+struct input_stream {
+ const void *(*read)(struct input_stream *, unsigned long *len);
+ void *data;
+ int is_finished;
+};
+
KHASH_INIT(odb_path_map, const char * /* key: odb_path */,
struct object_directory *, 1, fspathhash, fspatheq)
@@ -269,6 +275,8 @@ static inline int write_object_file(const void *buf, unsigned long len,
int write_object_file_literally(const void *buf, unsigned long len,
const char *type, struct object_id *oid,
unsigned flags);
+int stream_loose_object(struct input_stream *in_stream, size_t len,
+ struct object_id *oid);
/*
* Add an object file to the in-memory object store, without writing it
diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c
index c43375b..4fcfaed 100644
--- a/pack-bitmap-write.c
+++ b/pack-bitmap-write.c
@@ -683,7 +683,7 @@ static void write_hash_cache(struct hashfile *f,
}
}
-void bitmap_writer_set_checksum(unsigned char *sha1)
+void bitmap_writer_set_checksum(const unsigned char *sha1)
{
hashcpy(writer.pack_checksum, sha1);
}
diff --git a/pack-bitmap.c b/pack-bitmap.c
index 3613422..ef580be 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -1,5 +1,6 @@
#include "cache.h"
#include "commit.h"
+#include "strbuf.h"
#include "tag.h"
#include "diff.h"
#include "revision.h"
@@ -138,7 +139,7 @@ static struct ewah_bitmap *read_bitmap_1(struct bitmap_index *index)
index->map_size - index->map_pos);
if (bitmap_size < 0) {
- error("Failed to load bitmap index (corrupted?)");
+ error(_("failed to load bitmap index (corrupted?)"));
ewah_pool_free(b);
return NULL;
}
@@ -160,14 +161,14 @@ static int load_bitmap_header(struct bitmap_index *index)
size_t header_size = sizeof(*header) - GIT_MAX_RAWSZ + the_hash_algo->rawsz;
if (index->map_size < header_size + the_hash_algo->rawsz)
- return error("Corrupted bitmap index (too small)");
+ return error(_("corrupted bitmap index (too small)"));
if (memcmp(header->magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE)) != 0)
- return error("Corrupted bitmap index file (wrong header)");
+ return error(_("corrupted bitmap index file (wrong header)"));
index->version = ntohs(header->version);
if (index->version != 1)
- return error("Unsupported version for bitmap index file (%d)", index->version);
+ return error(_("unsupported version '%d' for bitmap index file"), index->version);
/* Parse known bitmap format options */
{
@@ -176,12 +177,12 @@ static int load_bitmap_header(struct bitmap_index *index)
unsigned char *index_end = index->map + index->map_size - the_hash_algo->rawsz;
if ((flags & BITMAP_OPT_FULL_DAG) == 0)
- return error("Unsupported options for bitmap index file "
+ BUG("unsupported options for bitmap index file "
"(Git requires BITMAP_OPT_FULL_DAG)");
if (flags & BITMAP_OPT_HASH_CACHE) {
if (cache_size > index_end - index->map - header_size)
- return error("corrupted bitmap index file (too short to fit hash cache)");
+ return error(_("corrupted bitmap index file (too short to fit hash cache)"));
index->hashes = (void *)(index_end - cache_size);
index_end -= cache_size;
}
@@ -215,7 +216,7 @@ static struct stored_bitmap *store_bitmap(struct bitmap_index *index,
* because the SHA1 already existed on the map. this is bad, there
* shouldn't be duplicated commits in the index */
if (ret == 0) {
- error("Duplicate entry in bitmap index: %s", oid_to_hex(oid));
+ error(_("duplicate entry in bitmap index: '%s'"), oid_to_hex(oid));
return NULL;
}
@@ -259,14 +260,14 @@ static int load_bitmap_entries_v1(struct bitmap_index *index)
struct object_id oid;
if (index->map_size - index->map_pos < 6)
- return error("corrupt ewah bitmap: truncated header for entry %d", i);
+ return error(_("corrupt ewah bitmap: truncated header for entry %d"), i);
commit_idx_pos = read_be32(index->map, &index->map_pos);
xor_offset = read_u8(index->map, &index->map_pos);
flags = read_u8(index->map, &index->map_pos);
if (nth_bitmap_object_oid(index, &oid, commit_idx_pos) < 0)
- return error("corrupt ewah bitmap: commit index %u out of range",
+ return error(_("corrupt ewah bitmap: commit index %u out of range"),
(unsigned)commit_idx_pos);
bitmap = read_bitmap_1(index);
@@ -274,13 +275,13 @@ static int load_bitmap_entries_v1(struct bitmap_index *index)
return -1;
if (xor_offset > MAX_XOR_OFFSET || xor_offset > i)
- return error("Corrupted bitmap pack index");
+ return error(_("corrupted bitmap pack index"));
if (xor_offset > 0) {
xor_bitmap = recent_bitmaps[(i - xor_offset) % MAX_XOR_OFFSET];
if (!xor_bitmap)
- return error("Invalid XOR offset in bitmap pack index");
+ return error(_("invalid XOR offset in bitmap pack index"));
}
recent_bitmaps[i % MAX_XOR_OFFSET] = store_bitmap(
@@ -313,17 +314,21 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
struct multi_pack_index *midx)
{
struct stat st;
- char *idx_name = midx_bitmap_filename(midx);
- int fd = git_open(idx_name);
+ char *bitmap_name = midx_bitmap_filename(midx);
+ int fd = git_open(bitmap_name);
uint32_t i;
struct packed_git *preferred;
- free(idx_name);
-
- if (fd < 0)
+ if (fd < 0) {
+ if (errno != ENOENT)
+ warning_errno("cannot open '%s'", bitmap_name);
+ free(bitmap_name);
return -1;
+ }
+ free(bitmap_name);
if (fstat(fd, &st)) {
+ error_errno(_("cannot fstat bitmap file"));
close(fd);
return -1;
}
@@ -332,7 +337,7 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
struct strbuf buf = STRBUF_INIT;
get_midx_filename(&buf, midx->object_dir);
/* ignore extra bitmap file; we can only handle one */
- warning("ignoring extra bitmap file: %s", buf.buf);
+ warning(_("ignoring extra bitmap file: '%s'"), buf.buf);
close(fd);
strbuf_release(&buf);
return -1;
@@ -348,8 +353,10 @@ static int open_midx_bitmap_1(struct bitmap_index *bitmap_git,
if (load_bitmap_header(bitmap_git) < 0)
goto cleanup;
- if (!hasheq(get_midx_checksum(bitmap_git->midx), bitmap_git->checksum))
+ if (!hasheq(get_midx_checksum(bitmap_git->midx), bitmap_git->checksum)) {
+ error(_("checksum doesn't match in MIDX and bitmap"));
goto cleanup;
+ }
if (load_midx_revindex(bitmap_git->midx) < 0) {
warning(_("multi-pack bitmap is missing required reverse index"));
@@ -384,26 +391,31 @@ static int open_pack_bitmap_1(struct bitmap_index *bitmap_git, struct packed_git
{
int fd;
struct stat st;
- char *idx_name;
+ char *bitmap_name;
if (open_pack_index(packfile))
return -1;
- idx_name = pack_bitmap_filename(packfile);
- fd = git_open(idx_name);
- free(idx_name);
+ bitmap_name = pack_bitmap_filename(packfile);
+ fd = git_open(bitmap_name);
- if (fd < 0)
+ if (fd < 0) {
+ if (errno != ENOENT)
+ warning_errno("cannot open '%s'", bitmap_name);
+ free(bitmap_name);
return -1;
+ }
+ free(bitmap_name);
if (fstat(fd, &st)) {
+ error_errno(_("cannot fstat bitmap file"));
close(fd);
return -1;
}
if (bitmap_git->pack || bitmap_git->midx) {
/* ignore extra bitmap file; we can only handle one */
- warning("ignoring extra bitmap file: %s", packfile->pack_name);
+ warning(_("ignoring extra bitmap file: '%s'"), packfile->pack_name);
close(fd);
return -1;
}
@@ -508,15 +520,16 @@ static int open_pack_bitmap(struct repository *r,
static int open_midx_bitmap(struct repository *r,
struct bitmap_index *bitmap_git)
{
+ int ret = -1;
struct multi_pack_index *midx;
assert(!bitmap_git->map);
for (midx = get_multi_pack_index(r); midx; midx = midx->next) {
if (!open_midx_bitmap_1(bitmap_git, midx))
- return 0;
+ ret = 0;
}
- return -1;
+ return ret;
}
static int open_bitmap(struct repository *r,
@@ -831,7 +844,7 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
revs->include_check_data = &incdata;
if (prepare_revision_walk(revs))
- die("revision walk setup failed");
+ die(_("revision walk setup failed"));
show_data.bitmap_git = bitmap_git;
show_data.base = base;
@@ -1640,15 +1653,15 @@ static void test_bitmap_type(struct bitmap_test_data *tdata,
}
if (bitmap_type == OBJ_NONE)
- die("object %s not found in type bitmaps",
+ die(_("object '%s' not found in type bitmaps"),
oid_to_hex(&obj->oid));
if (bitmaps_nr > 1)
- die("object %s does not have a unique type",
+ die(_("object '%s' does not have a unique type"),
oid_to_hex(&obj->oid));
if (bitmap_type != obj->type)
- die("object %s: real type %s, expected: %s",
+ die(_("object '%s': real type '%s', expected: '%s'"),
oid_to_hex(&obj->oid),
type_name(obj->type),
type_name(bitmap_type));
@@ -1662,7 +1675,7 @@ static void test_show_object(struct object *object, const char *name,
bitmap_pos = bitmap_position(tdata->bitmap_git, &object->oid);
if (bitmap_pos < 0)
- die("Object not in bitmap: %s\n", oid_to_hex(&object->oid));
+ die(_("object not in bitmap: '%s'"), oid_to_hex(&object->oid));
test_bitmap_type(tdata, object, bitmap_pos);
bitmap_set(tdata->base, bitmap_pos);
@@ -1677,7 +1690,7 @@ static void test_show_commit(struct commit *commit, void *data)
bitmap_pos = bitmap_position(tdata->bitmap_git,
&commit->object.oid);
if (bitmap_pos < 0)
- die("Object not in bitmap: %s\n", oid_to_hex(&commit->object.oid));
+ die(_("object not in bitmap: '%s'"), oid_to_hex(&commit->object.oid));
test_bitmap_type(tdata, &commit->object, bitmap_pos);
bitmap_set(tdata->base, bitmap_pos);
@@ -1694,26 +1707,26 @@ void test_bitmap_walk(struct rev_info *revs)
struct ewah_bitmap *bm;
if (!(bitmap_git = prepare_bitmap_git(revs->repo)))
- die("failed to load bitmap indexes");
+ die(_("failed to load bitmap indexes"));
if (revs->pending.nr != 1)
- die("you must specify exactly one commit to test");
+ die(_("you must specify exactly one commit to test"));
- fprintf(stderr, "Bitmap v%d test (%d entries loaded)\n",
+ fprintf_ln(stderr, "Bitmap v%d test (%d entries loaded)",
bitmap_git->version, bitmap_git->entry_count);
root = revs->pending.objects[0].item;
bm = bitmap_for_commit(bitmap_git, (struct commit *)root);
if (bm) {
- fprintf(stderr, "Found bitmap for %s. %d bits / %08x checksum\n",
+ fprintf_ln(stderr, "Found bitmap for '%s'. %d bits / %08x checksum",
oid_to_hex(&root->oid), (int)bm->bit_size, ewah_checksum(bm));
result = ewah_to_bitmap(bm);
}
if (!result)
- die("Commit %s doesn't have an indexed bitmap", oid_to_hex(&root->oid));
+ die(_("commit '%s' doesn't have an indexed bitmap"), oid_to_hex(&root->oid));
revs->tag_objects = 1;
revs->tree_objects = 1;
@@ -1722,7 +1735,7 @@ void test_bitmap_walk(struct rev_info *revs)
result_popcnt = bitmap_popcount(result);
if (prepare_revision_walk(revs))
- die("revision walk setup failed");
+ die(_("revision walk setup failed"));
tdata.bitmap_git = bitmap_git;
tdata.base = bitmap_new();
@@ -1738,9 +1751,9 @@ void test_bitmap_walk(struct rev_info *revs)
stop_progress(&tdata.prg);
if (bitmap_equals(result, tdata.base))
- fprintf(stderr, "OK!\n");
+ fprintf_ln(stderr, "OK!");
else
- die("mismatch in bitmap results");
+ die(_("mismatch in bitmap results"));
bitmap_free(result);
bitmap_free(tdata.base);
@@ -1758,10 +1771,10 @@ int test_bitmap_commits(struct repository *r)
MAYBE_UNUSED void *value;
if (!bitmap_git)
- die("failed to load bitmap indexes");
+ die(_("failed to load bitmap indexes"));
kh_foreach(bitmap_git->bitmaps, oid, value, {
- printf("%s\n", oid_to_hex(&oid));
+ printf_ln("%s", oid_to_hex(&oid));
});
free_bitmap_index(bitmap_git);
@@ -1786,7 +1799,7 @@ int test_bitmap_hashes(struct repository *r)
nth_bitmap_object_oid(bitmap_git, &oid, index_pos);
- printf("%s %"PRIu32"\n",
+ printf_ln("%s %"PRIu32"",
oid_to_hex(&oid), get_be32(bitmap_git->hashes + index_pos));
}
@@ -1948,7 +1961,7 @@ static off_t get_disk_usage_for_type(struct bitmap_index *bitmap_git,
struct object_id oid;
nth_midxed_object_oid(&oid, bitmap_git->midx, midx_pos);
- die(_("could not find %s in pack %s at offset %"PRIuMAX),
+ die(_("could not find '%s' in pack '%s' at offset %"PRIuMAX),
oid_to_hex(&oid),
pack->pack_name,
(uintmax_t)offset);
@@ -1984,7 +1997,7 @@ static off_t get_disk_usage_for_extended(struct bitmap_index *bitmap_git)
continue;
if (oid_object_info_extended(the_repository, &obj->oid, &oi, 0) < 0)
- die(_("unable to get disk usage of %s"),
+ die(_("unable to get disk usage of '%s'"),
oid_to_hex(&obj->oid));
total += object_size;
diff --git a/pack-bitmap.h b/pack-bitmap.h
index 3d3ddd7..f3a57ca 100644
--- a/pack-bitmap.h
+++ b/pack-bitmap.h
@@ -75,7 +75,7 @@ int bitmap_has_oid_in_uninteresting(struct bitmap_index *, const struct object_i
off_t get_disk_usage_from_bitmap(struct bitmap_index *, struct rev_info *);
void bitmap_writer_show_progress(int show);
-void bitmap_writer_set_checksum(unsigned char *sha1);
+void bitmap_writer_set_checksum(const unsigned char *sha1);
void bitmap_writer_build_type_index(struct packing_data *to_pack,
struct pack_idx_entry **index,
uint32_t index_nr);
diff --git a/pack-mtimes.c b/pack-mtimes.c
index 0e0aafd..0f9785f 100644
--- a/pack-mtimes.c
+++ b/pack-mtimes.c
@@ -89,7 +89,8 @@ cleanup:
*data_p = data;
}
- close(fd);
+ if (fd >= 0)
+ close(fd);
return ret;
}
diff --git a/pack-objects.h b/pack-objects.h
index 393b9db..5794766 100644
--- a/pack-objects.h
+++ b/pack-objects.h
@@ -116,16 +116,6 @@ struct object_entry {
unsigned dfs_state:OE_DFS_STATE_BITS;
unsigned depth:OE_DEPTH_BITS;
unsigned ext_base:1; /* delta_idx points outside packlist */
-
- /*
- * pahole results on 64-bit linux (gcc and clang)
- *
- * size: 80, bit_padding: 9 bits
- *
- * and on 32-bit (gcc)
- *
- * size: 76, bit_padding: 9 bits
- */
};
struct packing_data {
diff --git a/pack-write.c b/pack-write.c
index 23c0342..00787e3 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -310,26 +310,21 @@ static void write_mtimes_trailer(struct hashfile *f, const unsigned char *hash)
hashwrite(f, hash, the_hash_algo->rawsz);
}
-static const char *write_mtimes_file(const char *mtimes_name,
- struct packing_data *to_pack,
+static const char *write_mtimes_file(struct packing_data *to_pack,
struct pack_idx_entry **objects,
uint32_t nr_objects,
const unsigned char *hash)
{
+ struct strbuf tmp_file = STRBUF_INIT;
+ const char *mtimes_name;
struct hashfile *f;
int fd;
if (!to_pack)
BUG("cannot call write_mtimes_file with NULL packing_data");
- if (!mtimes_name) {
- struct strbuf tmp_file = STRBUF_INIT;
- fd = odb_mkstemp(&tmp_file, "pack/tmp_mtimes_XXXXXX");
- mtimes_name = strbuf_detach(&tmp_file, NULL);
- } else {
- unlink(mtimes_name);
- fd = xopen(mtimes_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
- }
+ fd = odb_mkstemp(&tmp_file, "pack/tmp_mtimes_XXXXXX");
+ mtimes_name = strbuf_detach(&tmp_file, NULL);
f = hashfd(fd, mtimes_name);
write_mtimes_header(f);
@@ -561,7 +556,7 @@ void stage_tmp_packfiles(struct strbuf *name_buffer,
pack_idx_opts->flags);
if (pack_idx_opts->flags & WRITE_MTIMES) {
- mtimes_tmp_name = write_mtimes_file(NULL, to_pack, written_list,
+ mtimes_tmp_name = write_mtimes_file(to_pack, written_list,
nr_written,
hash);
}
diff --git a/packfile.c b/packfile.c
index 8e812a8..ed69fe4 100644
--- a/packfile.c
+++ b/packfile.c
@@ -2275,7 +2275,8 @@ int is_promisor_object(const struct object_id *oid)
if (has_promisor_remote()) {
for_each_packed_object(add_promisor_object,
&promisor_objects,
- FOR_EACH_OBJECT_PROMISOR_ONLY);
+ FOR_EACH_OBJECT_PROMISOR_ONLY |
+ FOR_EACH_OBJECT_PACK_ORDER);
}
promisor_objects_prepared = 1;
}
diff --git a/parallel-checkout.c b/parallel-checkout.c
index 31a3d0e..4f6819f 100644
--- a/parallel-checkout.c
+++ b/parallel-checkout.c
@@ -143,7 +143,8 @@ static int is_eligible_for_parallel_checkout(const struct cache_entry *ce,
}
}
-int enqueue_checkout(struct cache_entry *ce, struct conv_attrs *ca)
+int enqueue_checkout(struct cache_entry *ce, struct conv_attrs *ca,
+ int *checkout_counter)
{
struct parallel_checkout_item *pc_item;
@@ -159,6 +160,7 @@ int enqueue_checkout(struct cache_entry *ce, struct conv_attrs *ca)
memcpy(&pc_item->ca, ca, sizeof(pc_item->ca));
pc_item->status = PC_ITEM_PENDING;
pc_item->id = parallel_checkout.nr;
+ pc_item->checkout_counter = checkout_counter;
parallel_checkout.nr++;
return 0;
@@ -200,7 +202,8 @@ static int handle_results(struct checkout *state)
switch(pc_item->status) {
case PC_ITEM_WRITTEN:
- /* Already handled */
+ if (pc_item->checkout_counter)
+ (*pc_item->checkout_counter)++;
break;
case PC_ITEM_COLLIDED:
/*
@@ -225,7 +228,8 @@ static int handle_results(struct checkout *state)
* add any extra overhead.
*/
ret |= checkout_entry_ca(pc_item->ce, &pc_item->ca,
- state, NULL, NULL);
+ state, NULL,
+ pc_item->checkout_counter);
advance_progress_meter();
break;
case PC_ITEM_PENDING:
diff --git a/parallel-checkout.h b/parallel-checkout.h
index 80f539b..c575284 100644
--- a/parallel-checkout.h
+++ b/parallel-checkout.h
@@ -31,7 +31,8 @@ void init_parallel_checkout(void);
* entry is not eligible for parallel checkout. Otherwise, enqueue the entry
* for later write and return 0.
*/
-int enqueue_checkout(struct cache_entry *ce, struct conv_attrs *ca);
+int enqueue_checkout(struct cache_entry *ce, struct conv_attrs *ca,
+ int *checkout_counter);
size_t pc_queue_size(void);
/*
@@ -68,6 +69,7 @@ struct parallel_checkout_item {
struct cache_entry *ce;
struct conv_attrs ca;
size_t id; /* position in parallel_checkout.items[] of main process */
+ int *checkout_counter;
/* Output fields, sent from workers. */
enum pc_item_status status;
diff --git a/pkt-line.h b/pkt-line.h
index 6d2a63d..1f623de 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -49,14 +49,6 @@ void packet_fflush(FILE *f);
* Read a packetized line into the buffer, which must be at least size bytes
* long. The return value specifies the number of bytes read into the buffer.
*
- * If src_buffer and *src_buffer are not NULL, it should point to a buffer
- * containing the packet data to parse, of at least *src_len bytes. After the
- * function returns, src_buf will be incremented and src_len decremented by the
- * number of bytes consumed.
- *
- * If src_buffer (or *src_buffer) is NULL, then data is read from the
- * descriptor "fd".
- *
* If options does not contain PACKET_READ_GENTLE_ON_EOF, we will die under any
* of the following conditions:
*
@@ -104,6 +96,14 @@ int packet_length(const char lenbuf_hex[4]);
* returns an 'enum packet_read_status' which indicates the status of the read.
* The number of bytes read will be assigned to *pktlen if the status of the
* read was 'PACKET_READ_NORMAL'.
+ *
+ * If src_buffer and *src_buffer are not NULL, it should point to a buffer
+ * containing the packet data to parse, of at least *src_len bytes. After the
+ * function returns, src_buf will be incremented and src_len decremented by the
+ * number of bytes consumed.
+ *
+ * If src_buffer (or *src_buffer) is NULL, then data is read from the
+ * descriptor "fd".
*/
enum packet_read_status {
PACKET_READ_EOF,
diff --git a/po/README.md b/po/README.md
index 74856ca..3e4f897 100644
--- a/po/README.md
+++ b/po/README.md
@@ -5,7 +5,7 @@ describes how you can contribute to the effort of enhancing the language
coverage and maintaining the translation.
The localization (l10n) coordinator, Jiang Xin <worldhello.net@gmail.com>,
-coordinates our localization effort in the l10 coordinator repository:
+coordinates our localization effort in the l10n coordinator repository:
https://github.com/git-l10n/git-po/
diff --git a/po/TEAMS b/po/TEAMS
index 2e40726..5a63397 100644
--- a/po/TEAMS
+++ b/po/TEAMS
@@ -11,9 +11,9 @@ Leader: Jordi Mas <jmas@softcatala.org>
Members: Alex Henrie <alexhenrie24@gmail.com>
Language: de (German)
-Repository: https://github.com/ruester/git-po-de
-Leader: Matthias Rüster <matthias.ruester@gmail.com>
-Members: Ralf Thielow <ralf.thielow@gmail.com>
+Repository: https://github.com/ralfth/git
+Leader: Ralf Thielow <ralf.thielow@gmail.com>
+Members: Matthias Rüster <matthias.ruester@gmail.com>
Phillip Szelat <phillip.szelat@gmail.com>
Language: el (Greek)
diff --git a/po/bg.po b/po/bg.po
index 8328531..934784f 100644
--- a/po/bg.po
+++ b/po/bg.po
@@ -29,7 +29,7 @@
# git bundle пратка на git
# bisect двоично търсене
# am прилагам поредица от кръпки
-# working directory/tree — винаги работно дърво, git следи цялото дърво, а не директории, работна директория за cwd
+# working directory/tree/worktree — винаги работно дърво, git следи цялото дърво, а не директории, работна директория за cwd
# switch to branch преминавам към клон
# sparse entry/blob частично изтеглена директория/път/обект-BLOB
# sparse index частичен индекс
@@ -48,8 +48,8 @@
# mixed reset смесено зануляване (индекса и указателя „HEAD“, без работното дърво)
# soft reset меко зануляване (само указателя „HEAD“, без индекса и работното дърво)
# hard reset пълно зануляване (указателя „HEAD“, индекса и работното дърво)
-# merge reset слято зануляване (целия индекс и отчасти работното дърво — без файловете с промени между работното дърво и индекса)
-# keep reset запазващо зануляване (отчасти индекса и работното дърво — файловете с промени от подаването и „HEAD“)
+# merge reset слято зануляване (целия индекс и отчасти работното дърво — без файловете с промѐни между работното дърво и индекса)
+# keep reset запазващо зануляване (отчасти индекса и работното дърво — файловете с промѐни от подаването и „HEAD“)
# commit-ish указател към подаване
# sequence последователност/поредица
# whitespace symbol знаци за интервали
@@ -88,7 +88,7 @@
# nested tag - непряк етикет
# strip - премахвам (за компонент при филтриране)
# unrelated histories - независими истории
-# inexact rename detection търсене на преименувания на обекти съчетани с промени
+# inexact rename detection търсене на преименувания на обекти съчетани с промѐни
# hunk парче
# binary patch двоична кръпка
# reverse-apply прилагам в обратна посока
@@ -153,7 +153,7 @@
# end packet пакет за край
# identity самоличност, информация за
# boundary commit гранично подаване
-# integrate (changes) внасяне (на промени)
+# integrate (changes) внасяне (на промѐни)
# overflow data данни за отместването
# reverse index обратен индекс (а не обърнат, за да не се бърка с reverse key index)
# preferred предпочитан
@@ -168,6 +168,23 @@
# zealous merge засилено сливане
# unregister отчислявам
# marked counting изброяване
+# good/bad commit добро/лошо подаване
+# unreferenced object обект, към който нищо не сочи
+# reference = ref указател
+# revision = rev версия
+# specifier уточнение
+# unset изчиствам (стойност/настройка)
+# batch пакетен режим
+# skip-worktree bit флага файл само за индекса/прескачане на работното дърво
+# IPC комуникация между процеси
+# thread pool запас нишки
+# listener thread слушаща нишка
+# health thread нишка за следене на състоянието
+# cruft ненужни обекти
+# traverse обхождам
+# timestamp времево клеймо
+# bare repository голо хранилище
+#
# ------------------------
# „$var“ - може да не сработва за shell има gettext и eval_gettext - проверка - намират се лесно по „$
# ------------------------
@@ -185,10 +202,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: git 2.34\n"
+"Project-Id-Version: git 2.37\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2022-01-17 08:34+0800\n"
-"PO-Revision-Date: 2022-01-16 10:50+0100\n"
+"POT-Creation-Date: 2022-06-22 15:43+0200\n"
+"PO-Revision-Date: 2022-06-22 15:44+0200\n"
"Last-Translator: Alexander Shopov <ash@kambanaria.org>\n"
"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
"Language: bg\n"
@@ -197,239 +214,176 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: add-interactive.c:380
#, c-format
msgid "Huh (%s)?"
msgstr "Неуспешен анализ — „%s“."
-#: add-interactive.c:533 add-interactive.c:834 reset.c:65 sequencer.c:3509
-#: sequencer.c:3974 sequencer.c:4136 builtin/rebase.c:1233
-#: builtin/rebase.c:1642
msgid "could not read index"
msgstr "индексът не може да бъде прочетен"
-#: add-interactive.c:588 git-add--interactive.perl:269
-#: git-add--interactive.perl:294
msgid "binary"
msgstr "двоично"
-#: add-interactive.c:646 git-add--interactive.perl:278
-#: git-add--interactive.perl:332
msgid "nothing"
msgstr "нищо"
-#: add-interactive.c:647 git-add--interactive.perl:314
-#: git-add--interactive.perl:329
msgid "unchanged"
-msgstr "няма промени"
+msgstr "няма промѐни"
-#: add-interactive.c:684 git-add--interactive.perl:641
msgid "Update"
msgstr "Обновяване"
-#: add-interactive.c:701 add-interactive.c:889
#, c-format
msgid "could not stage '%s'"
msgstr "неуспешно добавяне в индекса на „%s“"
-#: add-interactive.c:707 add-interactive.c:896 reset.c:89 sequencer.c:3713
msgid "could not write index"
msgstr "индексът не може да бъде записан"
-#: add-interactive.c:710 git-add--interactive.perl:626
#, c-format, perl-format
msgid "updated %d path\n"
msgid_plural "updated %d paths\n"
msgstr[0] "%d файл обновен\n"
msgstr[1] "%d файла обновени\n"
-#: add-interactive.c:728 git-add--interactive.perl:676
#, c-format, perl-format
msgid "note: %s is untracked now.\n"
msgstr "БЕЛЕЖКА: „%s“ вече не се следи.\n"
-#: add-interactive.c:733 apply.c:4151 builtin/checkout.c:306
-#: builtin/reset.c:167
#, c-format
msgid "make_cache_entry failed for path '%s'"
msgstr "неуспешно създаване на запис в кеша чрез „make_cache_entry“ за „%s“"
-#: add-interactive.c:763 git-add--interactive.perl:653
msgid "Revert"
msgstr "Отмяна"
-#: add-interactive.c:779
msgid "Could not parse HEAD^{tree}"
msgstr "Указателят „HEAD^{tree}“ не може да бъде анализиран"
-#: add-interactive.c:817 git-add--interactive.perl:629
#, c-format, perl-format
msgid "reverted %d path\n"
msgid_plural "reverted %d paths\n"
-msgstr[0] "%d файл с отменени промени\n"
-msgstr[1] "%d файла с отменени промени\n"
+msgstr[0] "%d файл с отменени промѐни\n"
+msgstr[1] "%d файла с отменени промѐни\n"
-#: add-interactive.c:868 git-add--interactive.perl:693
#, c-format
msgid "No untracked files.\n"
msgstr "Няма неследени файлове.\n"
-#: add-interactive.c:872 git-add--interactive.perl:687
msgid "Add untracked"
msgstr "Добавяне на неследени"
-#: add-interactive.c:899 git-add--interactive.perl:623
#, c-format, perl-format
msgid "added %d path\n"
msgid_plural "added %d paths\n"
msgstr[0] "%d файл добавен\n"
msgstr[1] "%d файла добавени\n"
-#: add-interactive.c:929
#, c-format
msgid "ignoring unmerged: %s"
msgstr "пренебрегване на неслятото: „%s“"
-#: add-interactive.c:941 add-patch.c:1752 git-add--interactive.perl:1371
#, c-format
msgid "Only binary files changed.\n"
msgstr "Само двоични файлове са променени.\n"
-#: add-interactive.c:943 add-patch.c:1750 git-add--interactive.perl:1373
#, c-format
msgid "No changes.\n"
-msgstr "Няма промени.\n"
+msgstr "Няма промѐни.\n"
-#: add-interactive.c:947 git-add--interactive.perl:1381
msgid "Patch update"
msgstr "Обновяване на кръпка"
-#: add-interactive.c:986 git-add--interactive.perl:1794
msgid "Review diff"
msgstr "Преглед на разликата"
-#: add-interactive.c:1014
msgid "show paths with changes"
-msgstr "извеждане на пътищата с промени"
+msgstr "извеждане на пътищата с промѐни"
-#: add-interactive.c:1016
msgid "add working tree state to the staged set of changes"
-msgstr "добавяне на състоянието на работното дърво към промените в индекса"
+msgstr "добавяне на състоянието на работното дърво към промѐните в индекса"
-#: add-interactive.c:1018
msgid "revert staged set of changes back to the HEAD version"
msgstr "връщане на състоянието на индекса към соченото от „HEAD“"
-#: add-interactive.c:1020
msgid "pick hunks and update selectively"
msgstr "интерактивни избор и промяна на парчета код"
-#: add-interactive.c:1022
msgid "view diff between HEAD and index"
msgstr "разлика между соченото от „HEAD“ и индекса"
-#: add-interactive.c:1024
msgid "add contents of untracked files to the staged set of changes"
msgstr "добавяне на съдържанието на неследените файлове към индекса"
-#: add-interactive.c:1032 add-interactive.c:1081
msgid "Prompt help:"
msgstr "Помощ:"
-#: add-interactive.c:1034
msgid "select a single item"
msgstr "избор на eдин елемент"
-#: add-interactive.c:1036
msgid "select a range of items"
msgstr "избор на поредица от елементи"
-#: add-interactive.c:1038
msgid "select multiple ranges"
msgstr "избор на няколко поредици от елементи"
-#: add-interactive.c:1040 add-interactive.c:1085
msgid "select item based on unique prefix"
msgstr "избор на базата на уникален префикс"
-#: add-interactive.c:1042
msgid "unselect specified items"
msgstr "изваждане на указаното от избора"
-#: add-interactive.c:1044
msgid "choose all items"
msgstr "избор на всички елементи"
-#: add-interactive.c:1046
msgid "(empty) finish selecting"
msgstr "(празно) приключване на избирането"
-#: add-interactive.c:1083
msgid "select a numbered item"
msgstr "избор на номериран елемент"
-#: add-interactive.c:1087
msgid "(empty) select nothing"
msgstr "(празно) без избор на нищо"
-#: add-interactive.c:1095 builtin/clean.c:839 git-add--interactive.perl:1898
msgid "*** Commands ***"
msgstr "●●● Команди ●●●"
-#: add-interactive.c:1096 builtin/clean.c:840 git-add--interactive.perl:1895
msgid "What now"
msgstr "Избор на следващо действие"
-#: add-interactive.c:1148 git-add--interactive.perl:213
msgid "staged"
msgstr "в индекса"
-#: add-interactive.c:1148 git-add--interactive.perl:213
msgid "unstaged"
msgstr "извън индекса"
-#: add-interactive.c:1148 apply.c:5020 apply.c:5023 builtin/am.c:2367
-#: builtin/am.c:2370 builtin/bugreport.c:107 builtin/clone.c:128
-#: builtin/fetch.c:153 builtin/merge.c:287 builtin/pull.c:194
-#: builtin/submodule--helper.c:404 builtin/submodule--helper.c:1858
-#: builtin/submodule--helper.c:1861 builtin/submodule--helper.c:2504
-#: builtin/submodule--helper.c:2507 builtin/submodule--helper.c:2574
-#: builtin/submodule--helper.c:2579 builtin/submodule--helper.c:2812
-#: git-add--interactive.perl:213
msgid "path"
msgstr "път"
-#: add-interactive.c:1155
msgid "could not refresh index"
msgstr "индексът не може да бъде обновен"
#
-#: add-interactive.c:1169 builtin/clean.c:804 git-add--interactive.perl:1805
#, c-format
msgid "Bye.\n"
msgstr "Изход.\n"
-#: add-patch.c:34 git-add--interactive.perl:1433
#, c-format, perl-format
msgid "Stage mode change [y,n,q,a,d%s,?]? "
msgstr "Добавяне на промяната на правата за достъп [y,n,q,a,d%s,?]? "
-#: add-patch.c:35 git-add--interactive.perl:1434
#, c-format, perl-format
msgid "Stage deletion [y,n,q,a,d%s,?]? "
msgstr "Добавяне на изтриването [y,n,q,a,d%s,?]? "
-#: add-patch.c:36 git-add--interactive.perl:1435
#, c-format, perl-format
msgid "Stage addition [y,n,q,a,d%s,?]? "
msgstr "Добавяне на добавянето [y,n,q,a,d%s,?]? "
-#: add-patch.c:37 git-add--interactive.perl:1436
#, c-format, perl-format
msgid "Stage this hunk [y,n,q,a,d%s,?]? "
msgstr "Добавяне на това парче [y,n,q,a,d%s,?]? "
-#: add-patch.c:39
msgid ""
"If the patch applies cleanly, the edited hunk will immediately be marked for "
"staging."
@@ -437,7 +391,6 @@ msgstr ""
"Ако кръпката може да се приложи чисто, редактираното парче ще бъде незабавно "
"добавено към индекса."
-#: add-patch.c:42
msgid ""
"y - stage this hunk\n"
"n - do not stage this hunk\n"
@@ -451,27 +404,22 @@ msgstr ""
"a — добавяне на това и всички следващи парчета от файла в индекса\n"
"d — без добавяне на това и всички следващи парчета от файла в индекса\n"
-#: add-patch.c:56 git-add--interactive.perl:1439
#, c-format, perl-format
msgid "Stash mode change [y,n,q,a,d%s,?]? "
msgstr "Скатаване на промяната на правата за достъп [y,n,q,a,d%s,?]? "
-#: add-patch.c:57 git-add--interactive.perl:1440
#, c-format, perl-format
msgid "Stash deletion [y,n,q,a,d%s,?]? "
msgstr "Скатаване на изтриването [y,n,q,a,d%s,?]? "
-#: add-patch.c:58 git-add--interactive.perl:1441
#, c-format, perl-format
msgid "Stash addition [y,n,q,a,d%s,?]? "
msgstr "Скатаване на добавянето [y,n,q,a,d%s,?]? "
-#: add-patch.c:59 git-add--interactive.perl:1442
#, c-format, perl-format
msgid "Stash this hunk [y,n,q,a,d%s,?]? "
msgstr "Скатаване на това парче [y,n,q,a,d%s,?]? "
-#: add-patch.c:61
msgid ""
"If the patch applies cleanly, the edited hunk will immediately be marked for "
"stashing."
@@ -479,7 +427,6 @@ msgstr ""
"Ако кръпката може да се приложи чисто, редактираното парче ще бъде незабавно "
"скътано."
-#: add-patch.c:64
msgid ""
"y - stash this hunk\n"
"n - do not stash this hunk\n"
@@ -493,27 +440,22 @@ msgstr ""
"a — скатаване на това и всички следващи парчета от файла\n"
"d — без скатаване на това и всички следващи парчета от файла\n"
-#: add-patch.c:80 git-add--interactive.perl:1445
#, c-format, perl-format
msgid "Unstage mode change [y,n,q,a,d%s,?]? "
msgstr "Изваждане на промяната на правата за достъп [y,n,q,a,d%s,?]? "
-#: add-patch.c:81 git-add--interactive.perl:1446
#, c-format, perl-format
msgid "Unstage deletion [y,n,q,a,d%s,?]? "
msgstr "Изваждане на изтриването [y,n,q,a,d%s,?]? "
-#: add-patch.c:82 git-add--interactive.perl:1447
#, c-format, perl-format
msgid "Unstage addition [y,n,q,a,d%s,?]? "
msgstr "Изваждане на добавянето [y,n,q,a,d%s,?]? "
-#: add-patch.c:83 git-add--interactive.perl:1448
#, c-format, perl-format
msgid "Unstage this hunk [y,n,q,a,d%s,?]? "
msgstr "Изваждане на това парче [y,n,q,a,d%s,?]? "
-#: add-patch.c:85
msgid ""
"If the patch applies cleanly, the edited hunk will immediately be marked for "
"unstaging."
@@ -521,7 +463,6 @@ msgstr ""
"Ако кръпката може да се приложи чисто, редактираното парче ще бъде незабавно "
"извадено от индекса."
-#: add-patch.c:88
msgid ""
"y - unstage this hunk\n"
"n - do not unstage this hunk\n"
@@ -535,28 +476,23 @@ msgstr ""
"a — изваждане на това и всички следващи парчета от файла от индекса\n"
"d — без изваждане на това и всички следващи парчета от файла от индекса\n"
-#: add-patch.c:103 git-add--interactive.perl:1451
#, c-format, perl-format
msgid "Apply mode change to index [y,n,q,a,d%s,?]? "
msgstr ""
"Прилагане на промяната на правата за достъп към индекса [y,n,q,a,d%s,?]? "
-#: add-patch.c:104 git-add--interactive.perl:1452
#, c-format, perl-format
msgid "Apply deletion to index [y,n,q,a,d%s,?]? "
msgstr "Прилагане на изтриването към индекса [y,n,q,a,d%s,?]? "
-#: add-patch.c:105 git-add--interactive.perl:1453
#, c-format, perl-format
msgid "Apply addition to index [y,n,q,a,d%s,?]? "
msgstr "Прилагане на добавянето към индекса [y,n,q,a,d%s,?]? "
-#: add-patch.c:106 git-add--interactive.perl:1454
#, c-format, perl-format
msgid "Apply this hunk to index [y,n,q,a,d%s,?]? "
msgstr "Прилагане на това парче към индекса [y,n,q,a,d%s,?]? "
-#: add-patch.c:108 add-patch.c:176 add-patch.c:221
msgid ""
"If the patch applies cleanly, the edited hunk will immediately be marked for "
"applying."
@@ -564,7 +500,6 @@ msgstr ""
"Ако кръпката може да се приложи чисто, редактираното парче ще бъде незабавно "
"набелязано за прилагане."
-#: add-patch.c:111
msgid ""
"y - apply this hunk to index\n"
"n - do not apply this hunk to index\n"
@@ -578,33 +513,24 @@ msgstr ""
"a — прилагане на това и всички следващи парчета от файла към индекса\n"
"d — без прилагане на това и всички следващи парчета от файла към индекса\n"
-#: add-patch.c:126 git-add--interactive.perl:1457
-#: git-add--interactive.perl:1475
#, c-format, perl-format
msgid "Discard mode change from worktree [y,n,q,a,d%s,?]? "
msgstr ""
"Премахване на промяната в правата за достъп от работното дърво [y,n,q,a,d"
"%s,?]? "
-#: add-patch.c:127 git-add--interactive.perl:1458
-#: git-add--interactive.perl:1476
#, c-format, perl-format
msgid "Discard deletion from worktree [y,n,q,a,d%s,?]? "
msgstr "Премахване на изтриването от работното дърво [y,n,q,a,d%s,?]? "
-#: add-patch.c:128 git-add--interactive.perl:1459
-#: git-add--interactive.perl:1477
#, c-format, perl-format
msgid "Discard addition from worktree [y,n,q,a,d%s,?]? "
msgstr "Премахване на добавянето от работното дърво [y,n,q,a,d%s,?]? "
-#: add-patch.c:129 git-add--interactive.perl:1460
-#: git-add--interactive.perl:1478
#, c-format, perl-format
msgid "Discard this hunk from worktree [y,n,q,a,d%s,?]? "
msgstr "Премахване на парчето от работното дърво [y,n,q,a,d%s,?]? "
-#: add-patch.c:131 add-patch.c:154 add-patch.c:199
msgid ""
"If the patch applies cleanly, the edited hunk will immediately be marked for "
"discarding."
@@ -612,7 +538,6 @@ msgstr ""
"Ако кръпката може да се приложи чисто, редактираното парче ще бъде незабавно "
"набелязано за зануляване."
-#: add-patch.c:134 add-patch.c:202
msgid ""
"y - discard this hunk from worktree\n"
"n - do not discard this hunk from worktree\n"
@@ -629,31 +554,26 @@ msgstr ""
"d — без премахване на това и всички следващи парчета от файла от работното "
"дърво\n"
-#: add-patch.c:149 add-patch.c:194 git-add--interactive.perl:1463
#, c-format, perl-format
msgid "Discard mode change from index and worktree [y,n,q,a,d%s,?]? "
msgstr ""
"Премахване на промяната в правата за достъп от индекса и работното дърво [y,"
"n,q,a,d%s,?]? "
-#: add-patch.c:150 add-patch.c:195 git-add--interactive.perl:1464
#, c-format, perl-format
msgid "Discard deletion from index and worktree [y,n,q,a,d%s,?]? "
msgstr ""
"Премахване на изтриването от индекса и работното дърво [y,n,q,a,d%s,?]? "
-#: add-patch.c:151 add-patch.c:196 git-add--interactive.perl:1465
#, c-format, perl-format
msgid "Discard addition from index and worktree [y,n,q,a,d%s,?]? "
msgstr ""
"Премахване на добавянето от индекса и работното дърво [y,n,q,a,d%s,?]? "
-#: add-patch.c:152 add-patch.c:197 git-add--interactive.perl:1466
#, c-format, perl-format
msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? "
msgstr "Премахване на парчето от индекса и работното дърво [y,n,q,a,d%s,?]? "
-#: add-patch.c:157
msgid ""
"y - discard this hunk from index and worktree\n"
"n - do not discard this hunk from index and worktree\n"
@@ -670,30 +590,25 @@ msgstr ""
"d — без премахване на това и всички следващи парчета от файла от индекса и "
"работното дърво\n"
-#: add-patch.c:171 add-patch.c:216 git-add--interactive.perl:1469
#, c-format, perl-format
msgid "Apply mode change to index and worktree [y,n,q,a,d%s,?]? "
msgstr ""
"Прилагане на промяната в правата за достъп от индекса и работното дърво [y,n,"
"q,a,d%s,?]? "
-#: add-patch.c:172 add-patch.c:217 git-add--interactive.perl:1470
#, c-format, perl-format
msgid "Apply deletion to index and worktree [y,n,q,a,d%s,?]? "
msgstr ""
"Прилагане на изтриването от индекса и работното дърво [y,n,q,a,d%s,?]? "
-#: add-patch.c:173 add-patch.c:218 git-add--interactive.perl:1471
#, c-format, perl-format
msgid "Apply addition to index and worktree [y,n,q,a,d%s,?]? "
msgstr "Прилагане на добавянето от индекса и работното дърво [y,n,q,a,d%s,?]? "
-#: add-patch.c:174 add-patch.c:219 git-add--interactive.perl:1472
#, c-format, perl-format
msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? "
msgstr "Прилагане на парчето от индекса и работното дърво [y,n,q,a,d%s,?]? "
-#: add-patch.c:179
msgid ""
"y - apply this hunk to index and worktree\n"
"n - do not apply this hunk to index and worktree\n"
@@ -710,7 +625,6 @@ msgstr ""
"d — без прилагане на това и всички следващи парчета от файла от индекса и "
"работното дърво\n"
-#: add-patch.c:224
msgid ""
"y - apply this hunk to worktree\n"
"n - do not apply this hunk to worktree\n"
@@ -724,34 +638,27 @@ msgstr ""
"a — прилагане на това и всички следващи парчета от файла\n"
"d — без прилагане на това и всички следващи парчета от файла\n"
-#: add-patch.c:343
#, c-format
msgid "could not parse hunk header '%.*s'"
msgstr "заглавната част на парчето „%.*s“ не може да се анализира"
-#: add-patch.c:362 add-patch.c:366
#, c-format
msgid "could not parse colored hunk header '%.*s'"
msgstr "заглавната част на оцветеното парче „%.*s“ не може да се анализира"
-#: add-patch.c:420
msgid "could not parse diff"
msgstr "разликата не може да се анализира"
-#: add-patch.c:439
msgid "could not parse colored diff"
msgstr "оцветената разлика не може да се анализира"
-#: add-patch.c:453
#, c-format
msgid "failed to run '%s'"
msgstr "неуспешно изпълнение на „%s“"
-#: add-patch.c:612
msgid "mismatched output from interactive.diffFilter"
msgstr "изходът от „interactive.diffFilter“ не напасва"
-#: add-patch.c:613
msgid ""
"Your filter must maintain a one-to-one correspondence\n"
"between its input and output lines."
@@ -759,7 +666,6 @@ msgstr ""
"Обработените редове на изхода на ползвания филтър, трябва\n"
"да се отнасят едно към едно спрямо редовете на входа."
-#: add-patch.c:791
#, c-format
msgid ""
"expected context line #%d in\n"
@@ -768,7 +674,6 @@ msgstr ""
"очаква се ред №%d от контекста в\n"
"%.*s"
-#: add-patch.c:806
#, c-format
msgid ""
"hunks do not overlap:\n"
@@ -781,11 +686,9 @@ msgstr ""
" не завършва с:\n"
"%.*s"
-#: add-patch.c:1082 git-add--interactive.perl:1115
msgid "Manual hunk edit mode -- see bottom for a quick guide.\n"
msgstr "Ръчно редактиране на парчета код — отдолу има подсказка.\n"
-#: add-patch.c:1086
#, c-format
msgid ""
"---\n"
@@ -799,8 +702,8 @@ msgstr ""
"За да пропуснете редовете, започващи с „%c“: изтрийте ги.\n"
"Редовете, които започват с „%c“ ще бъдат пропуснати.\n"
+#. #-#-#-#-# git-add--interactive.perl.po #-#-#-#-#
#. TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.
-#: add-patch.c:1100 git-add--interactive.perl:1129
msgid ""
"If it does not apply cleanly, you will be given an opportunity to\n"
"edit again. If all lines of the hunk are removed, then the edit is\n"
@@ -810,27 +713,26 @@ msgstr ""
"изтриете всички редове от парчето код, то ще бъде оставено непроменено, а\n"
"редактирането — отказано.\n"
-#: add-patch.c:1133
msgid "could not parse hunk header"
msgstr "заглавната част парчето не може да се анализира"
-#: add-patch.c:1178
msgid "'git apply --cached' failed"
msgstr "неуспешно изпълнение на „git apply --cached“"
+#. #-#-#-#-# add-patch.c.po #-#-#-#-#
#. TRANSLATORS: do not translate [y/n]
#. The program will only accept that input at this point.
#. Consider translating (saying "no" discards!) as
#. (saying "n" for "no" discards!) if the translation
#. of the word "no" does not start with n.
#.
+#. #-#-#-#-# git-add--interactive.perl.po #-#-#-#-#
#. TRANSLATORS: do not translate [y/n]
#. The program will only accept that input
#. at this point.
#. Consider translating (saying "no" discards!) as
#. (saying "n" for "no" discards!) if the translation
#. of the word "no" does not start with n.
-#: add-patch.c:1247 git-add--interactive.perl:1244
msgid ""
"Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? "
msgstr ""
@@ -838,19 +740,15 @@ msgstr ""
"редактирането? (текущите редакции ще се отменят при отказ!): „y“ (да)/ "
"„n“ (не)? "
-#: add-patch.c:1290
msgid "The selected hunks do not apply to the index!"
msgstr "Избраните парчета не може да се добавят в индекса!"
-#: add-patch.c:1291 git-add--interactive.perl:1348
msgid "Apply them to the worktree anyway? "
msgstr "Да се приложат ли към работното дърво? "
-#: add-patch.c:1298 git-add--interactive.perl:1351
msgid "Nothing was applied.\n"
msgstr "Нищо не е приложено.\n"
-#: add-patch.c:1355
msgid ""
"j - leave this hunk undecided, see next undecided hunk\n"
"J - leave this hunk undecided, see next hunk\n"
@@ -872,73 +770,57 @@ msgstr ""
"e — ръчно редактиране на текущото парче\n"
"? — извеждане не помощта\n"
-#: add-patch.c:1517 add-patch.c:1527
msgid "No previous hunk"
msgstr "Няма друго парче преди това"
-#: add-patch.c:1522 add-patch.c:1532
msgid "No next hunk"
msgstr "Няма друго парче след това"
-#: add-patch.c:1538
msgid "No other hunks to goto"
msgstr "Няма други парчета"
-#: add-patch.c:1549 git-add--interactive.perl:1608
msgid "go to which hunk (<ret> to see more)? "
msgstr "към кое парче да се придвижи (за повече варианти натиснете „enter“)? "
-#: add-patch.c:1550 git-add--interactive.perl:1610
msgid "go to which hunk? "
msgstr "към кое парче да се придвижи? "
-#: add-patch.c:1561
#, c-format
msgid "Invalid number: '%s'"
msgstr "Неправилен номер: „%s“"
-#: add-patch.c:1566
#, c-format
msgid "Sorry, only %d hunk available."
msgid_plural "Sorry, only %d hunks available."
msgstr[0] "Има само %d парче."
msgstr[1] "Има само %d парчета."
-#: add-patch.c:1575
msgid "No other hunks to search"
msgstr "Няма други парчета за търсене"
-#: add-patch.c:1581 git-add--interactive.perl:1663
msgid "search for regex? "
msgstr "да се търси с регулярен израз? "
-#: add-patch.c:1596
#, c-format
msgid "Malformed search regexp %s: %s"
msgstr "Сгрешен регулярен израз „%s“: %s"
-#: add-patch.c:1613
msgid "No hunk matches the given pattern"
msgstr "Никое парче не напасва на регулярния израз"
-#: add-patch.c:1620
msgid "Sorry, cannot split this hunk"
msgstr "Това парче не може да бъде разделено"
-#: add-patch.c:1624
#, c-format
msgid "Split into %d hunks."
msgstr "Разделяне на %d парчета."
-#: add-patch.c:1628
msgid "Sorry, cannot edit this hunk"
msgstr "Това парче не може да бъде редактирано"
-#: add-patch.c:1680
msgid "'git apply' failed"
msgstr "неуспешно изпълнение на „git apply“"
-#: advice.c:78
#, c-format
msgid ""
"\n"
@@ -946,39 +828,32 @@ msgid ""
msgstr ""
"\n"
"За да изключите това предупреждение, изпълнете:\n"
+"\n"
" git config advice.%s false"
-#: advice.c:94
#, c-format
msgid "%shint: %.*s%s\n"
msgstr "%sподсказка: %.*s%s\n"
-#: advice.c:178
msgid "Cherry-picking is not possible because you have unmerged files."
msgstr "Отбирането на подавания е блокирано от неслети файлове."
-#: advice.c:180
msgid "Committing is not possible because you have unmerged files."
msgstr "Подаването е блокирано от неслети файлове."
-#: advice.c:182
msgid "Merging is not possible because you have unmerged files."
msgstr "Сливането е блокирано от неслети файлове."
-#: advice.c:184
msgid "Pulling is not possible because you have unmerged files."
msgstr "Издърпването е блокирано от неслети файлове."
-#: advice.c:186
msgid "Reverting is not possible because you have unmerged files."
msgstr "Отмяната е блокирана от неслети файлове."
-#: advice.c:188
#, c-format
msgid "It is not possible to %s because you have unmerged files."
msgstr "Действието „%s“ е блокирано от неслети файлове."
-#: advice.c:196
msgid ""
"Fix them up in the work tree, and then use 'git add/rm <file>'\n"
"as appropriate to mark resolution and make a commit."
@@ -986,27 +861,21 @@ msgstr ""
"Редактирайте ги в работното дърво, и тогава ползвайте „git add/rm ФАЙЛ“,\n"
"за да отбележите коригирането им. След това извършете подаването."
-#: advice.c:204
msgid "Exiting because of an unresolved conflict."
msgstr "Изход от програмата заради некоригиран конфликт."
-#: advice.c:209 builtin/merge.c:1382
msgid "You have not concluded your merge (MERGE_HEAD exists)."
msgstr "Не сте завършили сливане. (Указателят „MERGE_HEAD“ съществува)."
-#: advice.c:211
msgid "Please, commit your changes before merging."
-msgstr "Промените трябва да се подадат преди сливане."
+msgstr "Промѐните трябва да се подадат преди сливане."
-#: advice.c:212
msgid "Exiting because of unfinished merge."
msgstr "Изход от програмата заради незавършено сливане."
-#: advice.c:217
msgid "Not possible to fast-forward, aborting."
msgstr "Не може да се извърши превъртане, преустановяване на действието."
-#: advice.c:227
#, c-format
msgid ""
"The following paths and/or pathspecs matched paths that exist\n"
@@ -1016,7 +885,6 @@ msgstr ""
"Следните пътища напасват с пътища извън дефиницията за частично\n"
"изтегляне и няма да се обновят в индекса:\n"
-#: advice.c:234
msgid ""
"If you intend to update such entries, try one of the following:\n"
"* Use the --sparse option.\n"
@@ -1026,7 +894,6 @@ msgstr ""
" ⁃ ползвайте опцията „--sparse“\n"
" ⁃ изключете или променете правилата за частичност."
-#: advice.c:242
#, c-format
msgid ""
"Note: switching to '%s'.\n"
@@ -1051,9 +918,9 @@ msgstr ""
"Бележка: преминаване към „%s“.\n"
"\n"
"Указателят „HEAD“ не е свързан. Може да разглеждате, да правите произволни\n"
-"промени и да ги подавате. Ако изтеглите нещо друго, всички промени ще "
+"промѐни и да ги подавате. Ако изтеглите нещо друго, всички промѐни ще "
"бъдат\n"
-"забравени и никой клон няма да се промени.\n"
+"забравени и никой клон няма да се промѐни.\n"
"\n"
"Ако искате да създадете нов клон, за да запазите подаванията си, може да\n"
"направите това като зададете име на клон към опцията „-c“ на командата\n"
@@ -1069,106 +936,72 @@ msgstr ""
"detachedHead“\n"
"да е „false“ (лъжа̀).\n"
-#: alias.c:50
msgid "cmdline ends with \\"
msgstr "командният ред завършва с „/“"
-#: alias.c:51
msgid "unclosed quote"
msgstr "кавичка без еш"
-#: apply.c:70
#, c-format
msgid "unrecognized whitespace option '%s'"
msgstr "непозната опция за знаците за интервали „%s“"
-#: apply.c:86
#, c-format
msgid "unrecognized whitespace ignore option '%s'"
msgstr "непозната опция за игнориране на знаците за интервали „%s“"
-#: apply.c:136 archive.c:584 range-diff.c:559 revision.c:2303 revision.c:2307
-#: revision.c:2316 revision.c:2321 revision.c:2527 revision.c:2870
-#: revision.c:2874 revision.c:2880 revision.c:2883 revision.c:2885
-#: builtin/add.c:510 builtin/add.c:512 builtin/add.c:529 builtin/add.c:541
-#: builtin/branch.c:727 builtin/checkout.c:467 builtin/checkout.c:470
-#: builtin/checkout.c:1644 builtin/checkout.c:1754 builtin/checkout.c:1757
-#: builtin/clone.c:906 builtin/commit.c:358 builtin/commit.c:361
-#: builtin/commit.c:1196 builtin/describe.c:593 builtin/diff-tree.c:155
-#: builtin/difftool.c:733 builtin/fast-export.c:1245 builtin/fetch.c:2038
-#: builtin/fetch.c:2043 builtin/index-pack.c:1852 builtin/init-db.c:560
-#: builtin/log.c:1946 builtin/log.c:1948 builtin/ls-files.c:778
-#: builtin/merge.c:1403 builtin/merge.c:1405 builtin/pack-objects.c:4073
-#: builtin/push.c:592 builtin/push.c:630 builtin/push.c:636 builtin/push.c:641
-#: builtin/rebase.c:1193 builtin/rebase.c:1195 builtin/rebase.c:1199
-#: builtin/repack.c:684 builtin/repack.c:715 builtin/reset.c:426
-#: builtin/reset.c:462 builtin/rev-list.c:541 builtin/show-branch.c:710
-#: builtin/stash.c:1707 builtin/stash.c:1710 builtin/submodule--helper.c:1316
-#: builtin/submodule--helper.c:2975 builtin/tag.c:526 builtin/tag.c:572
-#: builtin/worktree.c:702
#, c-format
msgid "options '%s' and '%s' cannot be used together"
msgstr "опциите „%s“ и „%s“ са несъвместими"
-#: apply.c:139 apply.c:150 apply.c:153
#, c-format
msgid "'%s' outside a repository"
msgstr "„%s“ извън хранилище"
-#: apply.c:800
#, c-format
msgid "Cannot prepare timestamp regexp %s"
-msgstr "Регулярният израз за времето „%s“ не може за бъде компилиран"
+msgstr "Регулярният израз за времевото клеймо „%s“ не може за бъде компилиран"
-#: apply.c:809
#, c-format
msgid "regexec returned %d for input: %s"
msgstr "Регулярният израз върна %d при подадена последователност „%s“ на входа"
-#: apply.c:883
#, c-format
msgid "unable to find filename in patch at line %d"
msgstr "Липсва име на файл на ред %d от кръпката"
-#: apply.c:921
#, c-format
msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d"
msgstr ""
"git apply: лош изход от командата „git-diff“ — на ред %2$d се очакваше „/dev/"
"null“, а бе получен „%1$s“"
-#: apply.c:927
#, c-format
msgid "git apply: bad git-diff - inconsistent new filename on line %d"
msgstr ""
"git apply: лош изход от командата „git-diff“ — на ред %d бе получено "
"неправилно име на нов файл"
-#: apply.c:928
#, c-format
msgid "git apply: bad git-diff - inconsistent old filename on line %d"
msgstr ""
"git apply: лош изход от командата „git-diff“ — на ред %d бе получено "
"неправилно име на стар файл"
-#: apply.c:933
#, c-format
msgid "git apply: bad git-diff - expected /dev/null on line %d"
msgstr ""
"git apply: лош изход от командата „git-diff“ — на ред %d се очакваше „/dev/"
"null“"
-#: apply.c:962
#, c-format
msgid "invalid mode on line %d: %s"
msgstr "грешен режим на ред №%d: %s"
-#: apply.c:1281
#, c-format
msgid "inconsistent header lines %d and %d"
msgstr "несъвместими заглавни части на редове №%d и №%d"
-#: apply.c:1371
#, c-format
msgid ""
"git diff header lacks filename information when removing %d leading pathname "
@@ -1183,81 +1016,65 @@ msgstr[1] ""
"След съкращаването на първите %d части от компонентите на пътя, в заглавната "
"част на „git diff“ липсва информация за име на файл (ред: %d)"
-#: apply.c:1384
#, c-format
msgid "git diff header lacks filename information (line %d)"
msgstr ""
"в заглавната част на „git diff“ липсва информация за име на файл (ред: %d)"
-#: apply.c:1480
#, c-format
msgid "recount: unexpected line: %.*s"
msgstr "при повторното преброяване бе получен неочакван ред: „%.*s“"
-#: apply.c:1549
#, c-format
msgid "patch fragment without header at line %d: %.*s"
msgstr "част от кръпка без заглавна част на ред %d: %.*s"
-#: apply.c:1752
msgid "new file depends on old contents"
msgstr "новият файл зависи от старото съдържание на файла"
-#: apply.c:1754
msgid "deleted file still has contents"
msgstr "изтритият файл не е празен"
-#: apply.c:1788
#, c-format
msgid "corrupt patch at line %d"
msgstr "грешка в кръпката на ред %d"
-#: apply.c:1825
#, c-format
msgid "new file %s depends on old contents"
msgstr "новият файл „%s“ зависи от старото съдържание на файла"
-#: apply.c:1827
#, c-format
msgid "deleted file %s still has contents"
msgstr "изтритият файл „%s“ не е празен"
-#: apply.c:1830
#, c-format
msgid "** warning: file %s becomes empty but is not deleted"
msgstr "● предупреждение: файлът „%s“ вече е празен, но не е изтрит"
-#: apply.c:1978
#, c-format
msgid "corrupt binary patch at line %d: %.*s"
msgstr "грешка в двоичната кръпка на ред %d: %.*s"
-#: apply.c:2015
#, c-format
msgid "unrecognized binary patch at line %d"
msgstr "неразпозната двоичната кръпка на ред %d"
-#: apply.c:2177
#, c-format
msgid "patch with only garbage at line %d"
msgstr "кръпката е с изцяло повредени данни на ред %d"
-#: apply.c:2263
#, c-format
msgid "unable to read symlink %s"
msgstr "символната връзка „%s“ не може да бъде прочетена"
-#: apply.c:2267
#, c-format
msgid "unable to open or read %s"
msgstr "файлът „%s“ не може да бъде отворен или прочетен"
-#: apply.c:2936
#, c-format
msgid "invalid start of line: '%c'"
msgstr "неправилно начало на ред: „%c“"
-#: apply.c:3057
#, c-format
msgid "Hunk #%d succeeded at %d (offset %d line)."
msgid_plural "Hunk #%d succeeded at %d (offset %d lines)."
@@ -1266,13 +1083,11 @@ msgstr[0] ""
msgstr[1] ""
"%d-то парче код бе успешно приложено на ред %d (отместване от %d реда)."
-#: apply.c:3069
#, c-format
msgid "Context reduced to (%ld/%ld) to apply fragment at %d"
msgstr ""
"Контекстът е намален на (%ld/%ld) за прилагането на парчето код на ред %d"
-#: apply.c:3075
#, c-format
msgid ""
"while searching for:\n"
@@ -1281,318 +1096,255 @@ msgstr ""
"при търсене за:\n"
"%.*s"
-#: apply.c:3097
#, c-format
msgid "missing binary patch data for '%s'"
msgstr "липсват данните за двоичната кръпка за „%s“"
-#: apply.c:3105
#, c-format
msgid "cannot reverse-apply a binary patch without the reverse hunk to '%s'"
msgstr ""
"двоичната кръпка не може да се приложи в обратна посока, когато обратното "
"парче за „%s“ липсва"
-#: apply.c:3152
#, c-format
msgid "cannot apply binary patch to '%s' without full index line"
msgstr "към „%s“ не може да се приложи двоична кръпка без пълен индекс"
-#: apply.c:3163
#, c-format
msgid ""
"the patch applies to '%s' (%s), which does not match the current contents."
msgstr "кръпката съответства на „%s“ (%s), който не съвпада по съдържание."
-#: apply.c:3171
#, c-format
msgid "the patch applies to an empty '%s' but it is not empty"
msgstr "кръпката съответства на „%s“, който трябва да е празен, но не е"
-#: apply.c:3189
#, c-format
msgid "the necessary postimage %s for '%s' cannot be read"
msgstr ""
"необходимият резултат след операцията — „%s“ за „%s“ не може да бъде "
"прочетен"
-#: apply.c:3202
#, c-format
msgid "binary patch does not apply to '%s'"
msgstr "двоичната кръпка не може да бъде приложена върху „%s“"
-#: apply.c:3209
#, c-format
msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)"
msgstr ""
"двоичната кръпка за „%s“ води до неправилни резултати (очакваше се: „%s“, а "
"бе получено: „%s“)"
-#: apply.c:3230
#, c-format
msgid "patch failed: %s:%ld"
msgstr "неуспешно прилагане на кръпка: „%s:%ld“"
-#: apply.c:3353
#, c-format
msgid "cannot checkout %s"
msgstr "„%s“ не може да се изтегли"
-#: apply.c:3405 apply.c:3416 apply.c:3462 midx.c:104 pack-revindex.c:214
-#: setup.c:309
#, c-format
msgid "failed to read %s"
msgstr "файлът „%s“ не може да бъде прочетен"
-#: apply.c:3413
#, c-format
msgid "reading from '%s' beyond a symbolic link"
msgstr "изчитане на „%s“ след проследяване на символна връзка"
-#: apply.c:3442 apply.c:3711
#, c-format
msgid "path %s has been renamed/deleted"
msgstr "обектът с път „%s“ е преименуван или изтрит"
-#: apply.c:3549 apply.c:3726
#, c-format
msgid "%s: does not exist in index"
msgstr "„%s“ не съществува в индекса"
-#: apply.c:3558 apply.c:3734 apply.c:3978
#, c-format
msgid "%s: does not match index"
msgstr "„%s“ не съответства на индекса"
-#: apply.c:3595
msgid "repository lacks the necessary blob to perform 3-way merge."
msgstr "в хранилището липсват необходимите обекти-BLOB, за тройно сливане."
-#: apply.c:3598
#, c-format
msgid "Performing three-way merge...\n"
msgstr "Тройно сливане…\n"
-#: apply.c:3614 apply.c:3618
#, c-format
msgid "cannot read the current contents of '%s'"
msgstr "текущото съдържание на „%s“ не може да бъде прочетено"
-#: apply.c:3630
#, c-format
msgid "Failed to perform three-way merge...\n"
msgstr "Неуспешно тройно сливане…\n"
-#: apply.c:3644
#, c-format
msgid "Applied patch to '%s' with conflicts.\n"
msgstr "Конфликти при прилагането на кръпката към „%s“.\n"
-#: apply.c:3649
#, c-format
msgid "Applied patch to '%s' cleanly.\n"
msgstr "Кръпката бе приложена чисто към „%s“.\n"
-#: apply.c:3666
#, c-format
msgid "Falling back to direct application...\n"
msgstr "Преминаване към пряко прилагане…\n"
-#: apply.c:3678
msgid "removal patch leaves file contents"
msgstr "изтриващата кръпка оставя файла непразен"
-#: apply.c:3751
#, c-format
msgid "%s: wrong type"
msgstr "„%s“: неправилен вид"
-#: apply.c:3753
#, c-format
msgid "%s has type %o, expected %o"
msgstr "„%s“ е от вид „%o“, а се очакваше „%o“"
-#: apply.c:3918 apply.c:3920 read-cache.c:889 read-cache.c:918
-#: read-cache.c:1381
#, c-format
msgid "invalid path '%s'"
msgstr "неправилен път: „%s“"
-#: apply.c:3976
#, c-format
msgid "%s: already exists in index"
msgstr "„%s“: вече съществува в индекса"
-#: apply.c:3980
#, c-format
msgid "%s: already exists in working directory"
msgstr "„%s“: вече съществува в работното дърво"
-#: apply.c:4000
#, c-format
msgid "new mode (%o) of %s does not match old mode (%o)"
msgstr "новите права за достъп (%o) на „%s“ не съвпадат със старите (%o)"
-#: apply.c:4005
#, c-format
msgid "new mode (%o) of %s does not match old mode (%o) of %s"
msgstr ""
"новите права за достъп (%o) на „%s“ не съвпадат със старите (%o) на „%s“"
-#: apply.c:4025
#, c-format
msgid "affected file '%s' is beyond a symbolic link"
msgstr "засегнатият файл „%s“ е след символна връзка"
-#: apply.c:4029
#, c-format
msgid "%s: patch does not apply"
msgstr "Кръпката „%s“ не може да бъде приложена"
-#: apply.c:4044
#, c-format
msgid "Checking patch %s..."
msgstr "Проверяване на кръпката „%s“…"
-#: apply.c:4136
#, c-format
msgid "sha1 information is lacking or useless for submodule %s"
msgstr ""
"информацията за сумата по SHA1 за подмодула липсва или не е достатъчна (%s)."
-#: apply.c:4143
#, c-format
msgid "mode change for %s, which is not in current HEAD"
msgstr "смяна на режима на достъпа на „%s“, който не е в текущия връх „HEAD“"
-#: apply.c:4146
#, c-format
msgid "sha1 information is lacking or useless (%s)."
msgstr "информацията за сумата по SHA1 липсва или не е достатъчна (%s)."
-#: apply.c:4155
#, c-format
msgid "could not add %s to temporary index"
msgstr "„%s“ не може да се добави към временния индекс"
-#: apply.c:4165
#, c-format
msgid "could not write temporary index to %s"
msgstr "временният индекс не може да се запази в „%s“"
-#: apply.c:4303
#, c-format
msgid "unable to remove %s from index"
msgstr "„%s“ не може да се извади от индекса"
-#: apply.c:4337
#, c-format
msgid "corrupt patch for submodule %s"
msgstr "повредена кръпка за модула „%s“"
-#: apply.c:4343
#, c-format
msgid "unable to stat newly created file '%s'"
msgstr ""
"не може да се получи информация чрез „stat“ за новосъздадения файл „%s“"
-#: apply.c:4351
#, c-format
msgid "unable to create backing store for newly created file %s"
msgstr ""
"не може да се за създаде мястото за съхранение на новосъздадения файл „%s“"
-#: apply.c:4357 apply.c:4502
#, c-format
msgid "unable to add cache entry for %s"
msgstr "не може да се добави запис в кеша за „%s“"
-#: apply.c:4400 builtin/bisect--helper.c:540 builtin/gc.c:2258
-#: builtin/gc.c:2293
#, c-format
msgid "failed to write to '%s'"
msgstr "в „%s“ не може да се пише"
-#: apply.c:4404
#, c-format
msgid "closing file '%s'"
msgstr "затваряне на файла „%s“"
-#: apply.c:4474
#, c-format
msgid "unable to write file '%s' mode %o"
msgstr "файлът „%s“ не може да се запише с режим на достъп „%o“"
-#: apply.c:4572
#, c-format
msgid "Applied patch %s cleanly."
msgstr "Кръпката „%s“ бе приложена чисто."
-#: apply.c:4580
msgid "internal error"
msgstr "вътрешна грешка"
-#: apply.c:4583
#, c-format
msgid "Applying patch %%s with %d reject..."
msgid_plural "Applying patch %%s with %d rejects..."
msgstr[0] "Прилагане на кръпката „%%s“ с %d отхвърлено парче…"
msgstr[1] "Прилагане на кръпката „%%s“ с %d отхвърлени парчета…"
-#: apply.c:4594
#, c-format
msgid "truncating .rej filename to %.*s.rej"
msgstr "съкращаване на името на файла с отхвърлените парчета на „%.*s.rej“"
-#: apply.c:4602
#, c-format
msgid "cannot open %s"
msgstr "„%s“ не може да бъде отворен"
-#: apply.c:4616
#, c-format
msgid "Hunk #%d applied cleanly."
msgstr "%d-то парче бе успешно приложено."
-#: apply.c:4620
#, c-format
msgid "Rejected hunk #%d."
msgstr "%d-то парче бе отхвърлено."
-#: apply.c:4749
#, c-format
msgid "Skipped patch '%s'."
msgstr "Пропусната кръпка: „%s“"
-#: apply.c:4758
msgid "No valid patches in input (allow with \"--allow-empty\")"
msgstr ""
"На входа няма непразни кръпки (те се приемат при опция „--allow-empty“)"
-#: apply.c:4779
msgid "unable to read index file"
msgstr "индексът не може да бъде записан"
-#: apply.c:4936
#, c-format
msgid "can't open patch '%s': %s"
msgstr "кръпката „%s“ не може да бъде отворена: %s"
-#: apply.c:4963
#, c-format
msgid "squelched %d whitespace error"
msgid_plural "squelched %d whitespace errors"
msgstr[0] "пренебрегната е %d грешка в знаците за интервали"
msgstr[1] "пренебрегнати са %d грешки в знаците за интервали"
-#: apply.c:4969 apply.c:4984
#, c-format
msgid "%d line adds whitespace errors."
msgid_plural "%d lines add whitespace errors."
msgstr[0] "%d ред добавя грешки в знаците за интервали."
msgstr[1] "%d реда добавят грешки в знаците за интервали."
-#: apply.c:4977
#, c-format
msgid "%d line applied after fixing whitespace errors."
msgid_plural "%d lines applied after fixing whitespace errors."
@@ -1601,348 +1353,269 @@ msgstr[0] ""
msgstr[1] ""
"Добавени са %d реда след корекцията на грешките в знаците за интервали."
-#: apply.c:4993 builtin/add.c:704 builtin/mv.c:338 builtin/rm.c:430
msgid "Unable to write new index file"
msgstr "Новият индекс не може да бъде записан"
-#: apply.c:5021
msgid "don't apply changes matching the given path"
-msgstr "без прилагане на промените напасващи на дадения път"
+msgstr "без прилагане на промѐните напасващи на дадения път"
-#: apply.c:5024
msgid "apply changes matching the given path"
-msgstr "прилагане на промените напасващи на дадения път"
+msgstr "прилагане на промѐните напасващи на дадения път"
-#: apply.c:5026 builtin/am.c:2376
msgid "num"
msgstr "БРОЙ"
-#: apply.c:5027
msgid "remove <num> leading slashes from traditional diff paths"
msgstr "премахване на този БРОЙ водещи елементи от пътищата в разликата"
-#: apply.c:5030
msgid "ignore additions made by the patch"
msgstr "игнориране на редовете добавени от тази кръпка"
-#: apply.c:5032
msgid "instead of applying the patch, output diffstat for the input"
-msgstr "извеждане на статистика на промените без прилагане на кръпката"
+msgstr "извеждане на статистика на промѐните без прилагане на кръпката"
-#: apply.c:5036
msgid "show number of added and deleted lines in decimal notation"
msgstr "извеждане на броя на добавените и изтритите редове"
-#: apply.c:5038
msgid "instead of applying the patch, output a summary for the input"
msgstr "извеждане на статистика на входните данни без прилагане на кръпката"
-#: apply.c:5040
msgid "instead of applying the patch, see if the patch is applicable"
msgstr "проверка дали кръпката може да се приложи, без действително прилагане"
-#: apply.c:5042
msgid "make sure the patch is applicable to the current index"
msgstr "проверка дали кръпката може да бъде приложена към текущия индекс"
-#: apply.c:5044
msgid "mark new files with `git add --intent-to-add`"
msgstr "отбелязване на новите файлове с „git add --intent-to-add“"
-#: apply.c:5046
msgid "apply a patch without touching the working tree"
msgstr "прилагане на кръпката без промяна на работното дърво"
-#: apply.c:5048
msgid "accept a patch that touches outside the working area"
msgstr "прилагане на кръпка, която променя и файлове извън работното дърво"
-#: apply.c:5051
msgid "also apply the patch (use with --stat/--summary/--check)"
msgstr ""
"кръпката да бъде приложена. Опцията се комбинира с „--check“/„--stat“/„--"
"summary“"
-#: apply.c:5053
msgid "attempt three-way merge, fall back on normal patch if that fails"
msgstr ""
"пробване с тройно сливане, ако това не сработи — стандартно прилагане на "
"кръпка"
-#: apply.c:5055
msgid "build a temporary index based on embedded index information"
msgstr ""
"създаване на временен индекс на база на включената информация за индекса"
-#: apply.c:5058 builtin/checkout-index.c:196
msgid "paths are separated with NUL character"
msgstr "разделяне на пътищата с нулевия знак „NUL“"
-#: apply.c:5060
msgid "ensure at least <n> lines of context match"
msgstr "да се осигури контекст от поне такъв БРОЙ съвпадащи редове"
-#: apply.c:5061 builtin/am.c:2352 builtin/am.c:2355
-#: builtin/interpret-trailers.c:98 builtin/interpret-trailers.c:100
-#: builtin/interpret-trailers.c:102 builtin/pack-objects.c:3960
-#: builtin/rebase.c:1051
msgid "action"
msgstr "действие"
-#: apply.c:5062
msgid "detect new or modified lines that have whitespace errors"
msgstr "засичане на нови или променени редове с грешки в знаците за интервали"
-#: apply.c:5065 apply.c:5068
msgid "ignore changes in whitespace when finding context"
msgstr ""
-"игнориране на промените в знаците за интервали при откриване на контекста"
+"игнориране на промѐните в знаците за интервали при откриване на контекста"
-#: apply.c:5071
msgid "apply the patch in reverse"
msgstr "прилагане на кръпката в обратна посока"
-#: apply.c:5073
msgid "don't expect at least one line of context"
msgstr "без изискване на дори и един ред контекст"
-#: apply.c:5075
msgid "leave the rejected hunks in corresponding *.rej files"
msgstr "оставяне на отхвърлените парчета във файлове с разширение „.rej“"
-#: apply.c:5077
msgid "allow overlapping hunks"
msgstr "позволяване на застъпващи се парчета"
-#: apply.c:5080
msgid "tolerate incorrectly detected missing new-line at the end of file"
msgstr "пренебрегване на неправилно липсващ знак за нов ред в края на файл"
-#: apply.c:5083
msgid "do not trust the line counts in the hunk headers"
msgstr "без доверяване на номерата на редовете в заглавните части на парчетата"
-#: apply.c:5085 builtin/am.c:2364
msgid "root"
msgstr "НАЧАЛНА_ДИРЕКТОРИЯ"
-#: apply.c:5086
msgid "prepend <root> to all filenames"
msgstr "добавяне на тази НАЧАЛНА_ДИРЕКТОРИЯ към имената на всички файлове"
-#: apply.c:5089
msgid "don't return error for empty patches"
msgstr "да не се връща грешка при празни кръпки"
-#: archive-tar.c:125 archive-zip.c:345
#, c-format
msgid "cannot stream blob %s"
msgstr "обектът-BLOB „%s“ не може да бъде обработен"
-#: archive-tar.c:265 archive-zip.c:358
#, c-format
msgid "unsupported file mode: 0%o (SHA1: %s)"
msgstr "неподдържани права за достъп до файл: 0%o (SHA1: %s)"
-#: archive-tar.c:447
#, c-format
msgid "unable to start '%s' filter"
msgstr "филтърът „%s“ не може да бъде стартиран"
-#: archive-tar.c:450
msgid "unable to redirect descriptor"
msgstr "дескрипторът не може да бъде пренасочен"
-#: archive-tar.c:457
#, c-format
msgid "'%s' filter reported error"
msgstr "филтърът „%s“ върна грешка"
-#: archive-zip.c:318
#, c-format
msgid "path is not valid UTF-8: %s"
msgstr "пътят не е правилно кодиран в UTF-8: %s"
-#: archive-zip.c:322
#, c-format
msgid "path too long (%d chars, SHA1: %s): %s"
msgstr "твърде дълъг път (%d знака, SHA1: %s): %s"
-#: archive-zip.c:469 builtin/pack-objects.c:365 builtin/pack-objects.c:368
#, c-format
msgid "deflate error (%d)"
msgstr "грешка при декомпресиране с „deflate“ (%d)"
-#: archive-zip.c:603
#, c-format
msgid "timestamp too large for this system: %<PRIuMAX>"
-msgstr "времевата стойност е твърде голяма за тази система: %<PRIuMAX>"
+msgstr "времевото клеймо е твърде голямо за тази система: %<PRIuMAX>"
-#: archive.c:14
msgid "git archive [<options>] <tree-ish> [<path>...]"
msgstr "git archive [ОПЦИЯ…] УКАЗАТЕЛ_КЪМ_ДЪРВО [ПЪТ…]"
-#: archive.c:15
-msgid "git archive --list"
-msgstr "git archive --list"
-
-#: archive.c:16
msgid ""
"git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]"
msgstr ""
"git archive --remote ХРАНИЛИЩЕ [--exec КОМАНДА] [ОПЦИЯ…] УКАЗАТЕЛ_КЪМ_ДЪРВО "
"[ПЪТ…]"
-#: archive.c:17
msgid "git archive --remote <repo> [--exec <cmd>] --list"
msgstr "git archive --remote ХРАНИЛИЩЕ [--exec КОМАНДА] --list"
-#: archive.c:188 archive.c:341 builtin/gc.c:497 builtin/notes.c:238
-#: builtin/tag.c:578
#, c-format
msgid "cannot read '%s'"
msgstr "файлът „%s“ не може да бъде прочетен"
-#: archive.c:426 builtin/add.c:215 builtin/add.c:671 builtin/rm.c:334
#, c-format
msgid "pathspec '%s' did not match any files"
msgstr "пътят „%s“ не съвпада с никой файл"
-#: archive.c:450
#, c-format
msgid "no such ref: %.*s"
msgstr "такъв указател няма: %.*s"
-#: archive.c:456
#, c-format
msgid "not a valid object name: %s"
msgstr "неправилно име на обект: „%s“"
-#: archive.c:469
#, c-format
msgid "not a tree object: %s"
msgstr "не е обект-дърво: %s"
-#: archive.c:481
msgid "current working directory is untracked"
msgstr "текущата работна директория не е следена"
-#: archive.c:522
#, c-format
msgid "File not found: %s"
msgstr "Файлът „%s“ липсва"
-#: archive.c:524
#, c-format
msgid "Not a regular file: %s"
msgstr "„%s“ не е обикновен файл"
-#: archive.c:551
+#, c-format
+msgid "unclosed quote: '%s'"
+msgstr "кавичка без еш: „%s“"
+
+#, c-format
+msgid "missing colon: '%s'"
+msgstr "липсва двоеточие: „%s“"
+
+#, c-format
+msgid "empty file name: '%s'"
+msgstr "празно име на файл: „%s“"
+
msgid "fmt"
msgstr "ФОРМАТ"
-#: archive.c:551
msgid "archive format"
msgstr "ФОРМАТ на архива"
-#: archive.c:552 builtin/log.c:1790
msgid "prefix"
msgstr "ПРЕФИКС"
-#: archive.c:553
msgid "prepend prefix to each pathname in the archive"
msgstr "добавяне на този ПРЕФИКС към всеки път в архива"
-#: archive.c:554 archive.c:557 builtin/blame.c:880 builtin/blame.c:884
-#: builtin/blame.c:885 builtin/commit-tree.c:115 builtin/config.c:135
-#: builtin/fast-export.c:1181 builtin/fast-export.c:1183
-#: builtin/fast-export.c:1187 builtin/grep.c:935 builtin/hash-object.c:103
-#: builtin/ls-files.c:654 builtin/ls-files.c:657 builtin/notes.c:410
-#: builtin/notes.c:576 builtin/read-tree.c:115 parse-options.h:190
msgid "file"
msgstr "ФАЙЛ"
-#: archive.c:555
msgid "add untracked file to archive"
msgstr "добавяне на неследените файлове към архива"
-#: archive.c:558 builtin/archive.c:88
+msgid "path:content"
+msgstr "път:съдържание"
+
msgid "write the archive to this file"
msgstr "запазване на архива в този ФАЙЛ"
-#: archive.c:560
msgid "read .gitattributes in working directory"
msgstr "изчитане на „.gitattributes“ в работната директория"
-#: archive.c:561
msgid "report archived files on stderr"
msgstr "извеждане на архивираните файлове на стандартната грешка"
-#: archive.c:563
msgid "set compression level"
msgstr "задаване на нивото на компресиране"
-#: archive.c:566
msgid "list supported archive formats"
msgstr "извеждане на списъка с поддържаните формати"
-#: archive.c:568 builtin/archive.c:89 builtin/clone.c:118 builtin/clone.c:121
-#: builtin/submodule--helper.c:1870 builtin/submodule--helper.c:2513
msgid "repo"
msgstr "хранилище"
-#: archive.c:569 builtin/archive.c:90
msgid "retrieve the archive from remote repository <repo>"
msgstr "получаване на архива от отдалеченото ХРАНИЛИЩЕ"
-#: archive.c:570 builtin/archive.c:91 builtin/difftool.c:708
-#: builtin/notes.c:496
msgid "command"
msgstr "команда"
-#: archive.c:571 builtin/archive.c:92
msgid "path to the remote git-upload-archive command"
msgstr "път към отдалечената команда „git-upload-archive“"
-#: archive.c:578
msgid "Unexpected option --remote"
msgstr "Неочаквана опция „--remote“"
-#: archive.c:580 fetch-pack.c:300 revision.c:2887 builtin/add.c:544
-#: builtin/add.c:576 builtin/checkout.c:1763 builtin/commit.c:370
-#: builtin/fast-export.c:1230 builtin/index-pack.c:1848 builtin/log.c:2115
-#: builtin/reset.c:435 builtin/reset.c:493 builtin/rm.c:281
-#: builtin/stash.c:1719 builtin/worktree.c:508 http-fetch.c:144
-#: http-fetch.c:153
#, c-format
msgid "the option '%s' requires '%s'"
msgstr "опцията „%s“ изисква „%s“"
-#: archive.c:582
msgid "Unexpected option --output"
msgstr "Неочаквана опция „--output“"
-#: archive.c:606
#, c-format
msgid "Unknown archive format '%s'"
msgstr "Непознат формат на архив: „%s“"
-#: archive.c:615
#, c-format
msgid "Argument not supported for format '%s': -%d"
msgstr "Аргументът не се поддържа за форма̀та „%s“: -%d"
-#: attr.c:203
#, c-format
msgid "%.*s is not a valid attribute name"
msgstr "„%.*s“ е неправилно име за атрибут"
-#: attr.c:364
#, c-format
msgid "%s not allowed: %s:%d"
msgstr "%s: командата не е позволена: „%s:%d“"
-#: attr.c:404
msgid ""
"Negative patterns are ignored in git attributes\n"
"Use '\\!' for literal leading exclamation."
@@ -1950,22 +1623,18 @@ msgstr ""
"Отрицателните шаблони се игнорират в атрибутите на git.\n"
"Ако ви трябва начална удивителна, ползвайте „\\!“."
-#: bisect.c:488
#, c-format
msgid "Badly quoted content in file '%s': %s"
msgstr "Неправилно цитирано съдържание във файла „%s“: %s"
-#: bisect.c:698
#, c-format
msgid "We cannot bisect more!\n"
msgstr "Повече не може да се търси двоично!\n"
-#: bisect.c:764
#, c-format
msgid "Not a valid commit name %s"
msgstr "Неправилно име на подаване „%s“"
-#: bisect.c:789
#, c-format
msgid ""
"The merge base %s is bad.\n"
@@ -1974,7 +1643,6 @@ msgstr ""
"Неправилна база за сливане: %s.\n"
"Следователно грешката е коригирана между „%s“ и [%s].\n"
-#: bisect.c:794
#, c-format
msgid ""
"The merge base %s is new.\n"
@@ -1983,7 +1651,6 @@ msgstr ""
"Нова база за сливане: %s.\n"
"Свойството е променено между „%s“ и [%s].\n"
-#: bisect.c:799
#, c-format
msgid ""
"The merge base %s is %s.\n"
@@ -1992,7 +1659,6 @@ msgstr ""
"Базата за сливане „%s“ е %s.\n"
"Следователно първото %s подаване е между „%s“ и [%s].\n"
-#: bisect.c:807
#, c-format
msgid ""
"Some %s revs are not ancestors of the %s rev.\n"
@@ -2003,7 +1669,6 @@ msgstr ""
"Двоичното търсене с git bisect няма да работи правилно.\n"
"Дали не сте объркали указателите „%s“ и „%s“?\n"
-#: bisect.c:820
#, c-format
msgid ""
"the merge base between %s and [%s] must be skipped.\n"
@@ -2014,36 +1679,29 @@ msgstr ""
"Не може да сме сигурни, че първото %s подаване е между „%s“ и „%s“.\n"
"Двоичното търсене продължава."
-#: bisect.c:859
#, c-format
msgid "Bisecting: a merge base must be tested\n"
msgstr "Двоично търсене: трябва да се провери база за сливане\n"
-#: bisect.c:909
#, c-format
msgid "a %s revision is needed"
msgstr "необходима е версия „%s“"
-#: bisect.c:939
#, c-format
msgid "could not create file '%s'"
msgstr "файлът „%s“ не може да бъде създаден"
-#: bisect.c:985 builtin/merge.c:155
#, c-format
msgid "could not read file '%s'"
msgstr "файлът „%s“ не може да бъде прочетен"
-#: bisect.c:1025
msgid "reading bisect refs failed"
msgstr "неуспешно прочитане на указателите за двоично търсене"
-#: bisect.c:1055
#, c-format
msgid "%s was both %s and %s\n"
msgstr "„%s“ e както „%s“, така и „%s“\n"
-#: bisect.c:1064
#, c-format
msgid ""
"No testable commit found.\n"
@@ -2052,7 +1710,6 @@ msgstr ""
"Липсва подходящо за тестване подаване.\n"
"Проверете параметрите за пътищата.\n"
-#: bisect.c:1093
#, c-format
msgid "(roughly %d step)"
msgid_plural "(roughly %d steps)"
@@ -2062,54 +1719,40 @@ msgstr[1] "(приблизително %d стъпки)"
#. TRANSLATORS: the last %s will be replaced with "(roughly %d
#. steps)" translation.
#.
-#: bisect.c:1099
#, c-format
msgid "Bisecting: %d revision left to test after this %s\n"
msgid_plural "Bisecting: %d revisions left to test after this %s\n"
msgstr[0] "Двоично търсене: остава %d версия след тази %s\n"
msgstr[1] "Двоично търсене: остават %d версии след тази %s\n"
-#: blame.c:2776
msgid "--contents and --reverse do not blend well."
msgstr "опциите „--contents“ и „--reverse“ са несъвместими"
-#: blame.c:2790
msgid "cannot use --contents with final commit object name"
msgstr "опцията „--contents“ е несъвместима с име на обект от крайно подаване"
-#: blame.c:2811
msgid "--reverse and --first-parent together require specified latest commit"
msgstr ""
"Едновременното задаване на опциите „--reverse“ и „--first-parent“ изисква "
"указването на крайно подаване"
-#: blame.c:2820 bundle.c:224 midx.c:1042 ref-filter.c:2370 remote.c:2158
-#: sequencer.c:2352 sequencer.c:4899 submodule.c:883 builtin/commit.c:1114
-#: builtin/log.c:429 builtin/log.c:1036 builtin/log.c:1644 builtin/log.c:2071
-#: builtin/log.c:2362 builtin/merge.c:431 builtin/pack-objects.c:3373
-#: builtin/pack-objects.c:3775 builtin/pack-objects.c:3790
-#: builtin/shortlog.c:255
msgid "revision walk setup failed"
msgstr "неуспешно настройване на обхождането на версиите"
-#: blame.c:2838
msgid ""
"--reverse --first-parent together require range along first-parent chain"
msgstr ""
"Едновременното задаване на опциите „--reverse“ и „--first-parent“ изисква "
"указването на диапазон по веригата на първите наследници"
-#: blame.c:2849
#, c-format
msgid "no such path %s in %s"
msgstr "няма път на име „%s“ в „%s“"
-#: blame.c:2860
#, c-format
msgid "cannot read blob %s for path %s"
msgstr "обектът-BLOB „%s“ в пътя %s не може да бъде прочетен"
-#: branch.c:77
msgid ""
"cannot inherit upstream tracking configuration of multiple refs when "
"rebasing is requested"
@@ -2117,32 +1760,26 @@ msgstr ""
"настроените множество указатели, които да се следят, не може да се наследят "
"при пребазиране"
-#: branch.c:88
#, c-format
msgid "not setting branch '%s' as its own upstream"
msgstr ""
"клонът „%s“ не може да служи като източник за собствената си синхронизация"
-#: branch.c:144
#, c-format
msgid "branch '%s' set up to track '%s' by rebasing."
msgstr "клонът „%s“ ще следи „%s“ чрез пребазиране."
-#: branch.c:145
#, c-format
msgid "branch '%s' set up to track '%s'."
msgstr "клонът „%s“ ще следи „%s“."
-#: branch.c:148
#, c-format
msgid "branch '%s' set up to track:"
msgstr "клонът „%s“ ще следи:"
-#: branch.c:160
msgid "unable to write upstream branch configuration"
msgstr "настройките за следения клон не може да бъдат записани"
-#: branch.c:162
msgid ""
"\n"
"After fixing the error cause you may try to fix up\n"
@@ -2152,54 +1789,83 @@ msgstr ""
"След корекция на грешката, може да обновите\n"
"информацията за следения клон чрез:"
-#: branch.c:203
#, c-format
msgid "asked to inherit tracking from '%s', but no remote is set"
msgstr ""
"заявка за наследяване на следенето от „%s“, но не е зададено отдалечено "
"хранилище"
-#: branch.c:209
#, c-format
msgid "asked to inherit tracking from '%s', but no merge configuration is set"
msgstr ""
"заявка за наследяване на следенето от „%s“, но не е настроен режим за "
"пребазиране"
-#: branch.c:252
#, c-format
-msgid "not tracking: ambiguous information for ref %s"
-msgstr "няма следене: информацията за указателя „%s“ не е еднозначна"
+msgid "not tracking: ambiguous information for ref '%s'"
+msgstr "не се следени: информацията за указателя „%s“ не е еднозначна"
+
+#. #-#-#-#-# branch.c.po #-#-#-#-#
+#. TRANSLATORS: This is a line listing a remote with duplicate
+#. refspecs in the advice message below. For RTL languages you'll
+#. probably want to swap the "%s" and leading " " space around.
+#.
+#. #-#-#-#-# object-name.c.po #-#-#-#-#
+#. TRANSLATORS: This is line item of ambiguous object output
+#. from describe_ambiguous_object() above. For RTL languages
+#. you'll probably want to swap the "%s" and leading " " space
+#. around.
+#.
+#, c-format
+msgid " %s\n"
+msgstr " %s\n"
+
+#. TRANSLATORS: The second argument is a \n-delimited list of
+#. duplicate refspecs, composed above.
+#.
+#, c-format
+msgid ""
+"There are multiple remotes whose fetch refspecs map to the remote\n"
+"tracking ref '%s':\n"
+"%s\n"
+"This is typically a configuration error.\n"
+"\n"
+"To support setting up tracking branches, ensure that\n"
+"different remotes' fetch refspecs map into different\n"
+"tracking namespaces."
+msgstr ""
+"Има повече от едно отдалечено хранилище, чийто указател за изтегляне "
+"отговаря на „%s“:\n"
+"%s\n"
+"Най-често това е грешка в настройките.\n"
+"\n"
+"За конфигурирането на следящи клони трябва указателите за изтегляне да "
+"съответстват\n"
+"на различни пространства от имена."
-#: branch.c:287
#, c-format
msgid "'%s' is not a valid branch name"
msgstr "„%s“ не е позволено име за клон"
-#: branch.c:307
#, c-format
msgid "a branch named '%s' already exists"
msgstr "вече съществува клон с име „%s“."
# FIXME
-#: branch.c:313
#, c-format
msgid "cannot force update the branch '%s' checked out at '%s'"
msgstr ""
"не може принудително да обновите клона „%s“, който е изтеглен в пътя „%s“"
-#: branch.c:336
#, c-format
msgid "cannot set up tracking information; starting point '%s' is not a branch"
msgstr ""
"настройките за следенето не може да се зададат — началото „%s“ не е клон"
-#: branch.c:338
#, c-format
msgid "the requested upstream branch '%s' does not exist"
msgstr "заявеният отдалечен клон „%s“ не съществува"
-#: branch.c:340
msgid ""
"\n"
"If you are planning on basing your work on an upstream\n"
@@ -2218,8698 +1884,144 @@ msgstr ""
"може да използвате „git push -u“, за да настроите към кой клон да се "
"изтласква."
-#: branch.c:384 builtin/replace.c:321 builtin/replace.c:377
-#: builtin/replace.c:423 builtin/replace.c:453
#, c-format
msgid "not a valid object name: '%s'"
msgstr "неправилно име на обект: „%s“"
-#: branch.c:404
#, c-format
msgid "ambiguous object name: '%s'"
msgstr "името на обект не е еднозначно: „%s“"
-#: branch.c:409
#, c-format
msgid "not a valid branch point: '%s'"
msgstr "неправилно място за начало на клон: „%s“"
-#: branch.c:469
-#, c-format
-msgid "'%s' is already checked out at '%s'"
-msgstr "„%s“ вече е изтеглен в „%s“"
-
-#: branch.c:494
-#, c-format
-msgid "HEAD of working tree %s is not updated"
-msgstr "Указателят „HEAD“ на работното дърво „%s“ не е обновен"
-
-#: bundle.c:44
-#, c-format
-msgid "unrecognized bundle hash algorithm: %s"
-msgstr "непознат алгоритъм за контролни суми за пратки „%s“"
-
-#: bundle.c:48
-#, c-format
-msgid "unknown capability '%s'"
-msgstr "непозната възможност „%s“"
-
-#: bundle.c:74
-#, c-format
-msgid "'%s' does not look like a v2 or v3 bundle file"
-msgstr "Файлът „%s“ не изглежда да е пратка на git версия 2 или 3"
-
-#: bundle.c:113
-#, c-format
-msgid "unrecognized header: %s%s (%d)"
-msgstr "непозната заглавна част: %s%s (%d)"
-
-#: bundle.c:140 rerere.c:464 rerere.c:674 sequencer.c:2620 sequencer.c:3406
-#: builtin/commit.c:862
-#, c-format
-msgid "could not open '%s'"
-msgstr "„%s“ не може да се отвори"
-
-#: bundle.c:198
-msgid "Repository lacks these prerequisite commits:"
-msgstr "В хранилището липсват следните необходими подавания:"
-
-#: bundle.c:201
-msgid "need a repository to verify a bundle"
-msgstr "за проверката на пратка е необходимо хранилище"
-
-#: bundle.c:257
-#, c-format
-msgid "The bundle contains this ref:"
-msgid_plural "The bundle contains these %d refs:"
-msgstr[0] "Пратката съдържа следния указател:"
-msgstr[1] "Пратката съдържа следните %d указатели:"
-
-#: bundle.c:264
-msgid "The bundle records a complete history."
-msgstr "Пратката съдържа пълна история."
-
-#: bundle.c:266
-#, c-format
-msgid "The bundle requires this ref:"
-msgid_plural "The bundle requires these %d refs:"
-msgstr[0] "Пратката изисква следния указател:"
-msgstr[1] "Пратката изисква следните %d указатели:"
-
-#: bundle.c:333
-msgid "unable to dup bundle descriptor"
-msgstr "неуспешно дублиране на дескриптора на пратката с „dup“"
-
-#: bundle.c:340
-msgid "Could not spawn pack-objects"
-msgstr "Командата „git pack-objects“ не може да бъде стартирана"
-
-#: bundle.c:351
-msgid "pack-objects died"
-msgstr "Командата „git pack-objects“ не завърши успешно"
-
-#: bundle.c:400
-#, c-format
-msgid "ref '%s' is excluded by the rev-list options"
-msgstr ""
-"указателят „%s“ не е бил включен поради опциите зададени на „git rev-list“"
-
-#: bundle.c:504
-#, c-format
-msgid "unsupported bundle version %d"
-msgstr "неподдържана версия на индекса %d"
-
-#: bundle.c:506
-#, c-format
-msgid "cannot write bundle version %d with algorithm %s"
-msgstr "пратка %d не може да се запише с алгоритъм %s"
-
-#: bundle.c:524 builtin/log.c:210 builtin/log.c:1953 builtin/shortlog.c:399
-#, c-format
-msgid "unrecognized argument: %s"
-msgstr "непознат аргумент: %s"
-
-#: bundle.c:553
-msgid "Refusing to create empty bundle."
-msgstr "Създаването на празна пратка е невъзможно."
-
-#: bundle.c:563
-#, c-format
-msgid "cannot create '%s'"
-msgstr "файлът „%s“ не може да бъде създаден"
-
-#: bundle.c:588
-msgid "index-pack died"
-msgstr "командата „git index-pack“ не завърши успешно"
-
-#: chunk-format.c:117
-msgid "terminating chunk id appears earlier than expected"
-msgstr "идентификаторът за краен откъс се явява по-рано от очакваното"
-
-#: chunk-format.c:126
-#, c-format
-msgid "improper chunk offset(s) %<PRIx64> and %<PRIx64>"
-msgstr "неправилно отместване на откъс/и %<PRIx64> и %<PRIx64>"
-
-#: chunk-format.c:133
-#, c-format
-msgid "duplicate chunk ID %<PRIx32> found"
-msgstr "повтарящ се идентификатор на откъс %<PRIx32>"
-
-#: chunk-format.c:147
-#, c-format
-msgid "final chunk has non-zero id %<PRIx32>"
-msgstr "ненулев идентификатор за краен откъс %<PRIx32>"
-
-#: color.c:354
-#, c-format
-msgid "invalid color value: %.*s"
-msgstr "неправилна стойност за цвят: %.*s"
-
-#: commit-graph.c:204 midx.c:51
-msgid "invalid hash version"
-msgstr "неправилна версия на контролна сума"
-
-#: commit-graph.c:262
-msgid "commit-graph file is too small"
-msgstr "файлът за гра̀фа с подаванията е твърде малък"
-
-#: commit-graph.c:355
-#, c-format
-msgid "commit-graph signature %X does not match signature %X"
-msgstr "отпечатъкът на гра̀фа с подаванията %X не съвпада с %X"
-
-#: commit-graph.c:362
-#, c-format
-msgid "commit-graph version %X does not match version %X"
-msgstr "версията на гра̀фа с подаванията %X не съвпада с %X"
-
-#: commit-graph.c:369
-#, c-format
-msgid "commit-graph hash version %X does not match version %X"
-msgstr "версията на контролната сума на гра̀фа с подаванията %X не съвпада с %X"
-
-#: commit-graph.c:386
-#, c-format
-msgid "commit-graph file is too small to hold %u chunks"
-msgstr "файлът с гра̀фа на подаванията е твърде малък, за да съдържа %u откъси"
-
-#: commit-graph.c:482
-msgid "commit-graph has no base graphs chunk"
-msgstr "базовият откъс липсва в гра̀фа с подаванията"
-
-#: commit-graph.c:492
-msgid "commit-graph chain does not match"
-msgstr "веригата на гра̀фа с подаванията не съвпада"
-
-#: commit-graph.c:540
-#, c-format
-msgid "invalid commit-graph chain: line '%s' not a hash"
-msgstr ""
-"грешка във веригата на гра̀фа с подаванията: ред „%s“ не е контролна сума"
-
-#: commit-graph.c:564
-msgid "unable to find all commit-graph files"
-msgstr "някои файлове на гра̀фа с подаванията не може да бъдат открити"
-
-#: commit-graph.c:749 commit-graph.c:786
-msgid "invalid commit position. commit-graph is likely corrupt"
-msgstr ""
-"неправилна позиция на подаването. Вероятно графът с подаванията е повреден"
-
-#: commit-graph.c:770
-#, c-format
-msgid "could not find commit %s"
-msgstr "подаването „%s“ не може да бъде открито"
-
-#: commit-graph.c:803
-msgid "commit-graph requires overflow generation data but has none"
-msgstr ""
-"графът с подаванията изисква генериране на данни за отместването, но такива "
-"липсват"
-
-#: commit-graph.c:1108 builtin/am.c:1369
-#, c-format
-msgid "unable to parse commit %s"
-msgstr "подаването не може да бъде анализирано: %s"
-
-#: commit-graph.c:1370 builtin/pack-objects.c:3070
-#, c-format
-msgid "unable to get type of object %s"
-msgstr "видът на обекта „%s“ не може да бъде определен"
-
-#: commit-graph.c:1401
-msgid "Loading known commits in commit graph"
-msgstr "Зареждане на познатите подавания в гра̀фа с подаванията"
-
-#: commit-graph.c:1418
-msgid "Expanding reachable commits in commit graph"
-msgstr "Разширяване на достижимите подавания в гра̀фа"
-
-#: commit-graph.c:1438
-msgid "Clearing commit marks in commit graph"
-msgstr "Изчистване на отбелязванията на подаванията в гра̀фа с подаванията"
-
-#: commit-graph.c:1457
-msgid "Computing commit graph topological levels"
-msgstr "Изчисляване на топологичните нива в гра̀фа с подаванията"
-
-#: commit-graph.c:1510
-msgid "Computing commit graph generation numbers"
-msgstr "Изчисляване на номерата на поколенията в гра̀фа с подаванията"
-
-#: commit-graph.c:1591
-msgid "Computing commit changed paths Bloom filters"
-msgstr "Изчисляване на филтрите на Блум на пътищата с промяна при подаването"
-
-#: commit-graph.c:1668
-msgid "Collecting referenced commits"
-msgstr "Събиране на свързаните подавания"
-
-#: commit-graph.c:1693
-#, c-format
-msgid "Finding commits for commit graph in %d pack"
-msgid_plural "Finding commits for commit graph in %d packs"
-msgstr[0] "Откриване на подаванията в гра̀фа в %d пакетен файл"
-msgstr[1] "Откриване на подаванията в гра̀фа в %d пакетни файла"
-
-#: commit-graph.c:1706
-#, c-format
-msgid "error adding pack %s"
-msgstr "грешка при добавяне на пакетен файл „%s“"
-
-#: commit-graph.c:1710
-#, c-format
-msgid "error opening index for %s"
-msgstr "грешка при отваряне на индекса на „%s“"
-
-#: commit-graph.c:1747
-msgid "Finding commits for commit graph among packed objects"
-msgstr "Откриване на подаванията в гра̀фа измежду пакетираните обекти"
-
-#: commit-graph.c:1765
-msgid "Finding extra edges in commit graph"
-msgstr "Откриване на още върхове в гра̀фа с подаванията"
-
-#: commit-graph.c:1814
-msgid "failed to write correct number of base graph ids"
-msgstr "правилният брой на базовите идентификатори не може да се запише"
-
-#: commit-graph.c:1845 midx.c:1149
-#, c-format
-msgid "unable to create leading directories of %s"
-msgstr "родителските директории на „%s“ не може да бъдат създадени"
-
-#: commit-graph.c:1858
-msgid "unable to create temporary graph layer"
-msgstr "не може да бъде създаден временен слой за гра̀фа с подаванията"
-
-#: commit-graph.c:1863
-#, c-format
-msgid "unable to adjust shared permissions for '%s'"
-msgstr "правата за споделен достъп до „%s“ не може да бъдат зададени"
-
-#: commit-graph.c:1920
-#, c-format
-msgid "Writing out commit graph in %d pass"
-msgid_plural "Writing out commit graph in %d passes"
-msgstr[0] "Запазване на гра̀фа с подаванията в %d пас"
-msgstr[1] "Запазване на гра̀фа с подаванията в %d паса"
-
-#: commit-graph.c:1956
-msgid "unable to open commit-graph chain file"
-msgstr "файлът с веригата на гра̀фа с подаванията не може да се отвори"
-
-#: commit-graph.c:1972
-msgid "failed to rename base commit-graph file"
-msgstr "основният файл на гра̀фа с подаванията не може да бъде преименуван"
-
-#: commit-graph.c:1992
-msgid "failed to rename temporary commit-graph file"
-msgstr "временният файл на гра̀фа с подаванията не може да бъде преименуван"
-
-#: commit-graph.c:2125
-msgid "Scanning merged commits"
-msgstr "Търсене на подаванията със сливания"
-
-#: commit-graph.c:2169
-msgid "Merging commit-graph"
-msgstr "Сливане на гра̀фа с подаванията"
-
-#: commit-graph.c:2277
-msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled"
-msgstr ""
-"опит за запис на гра̀фа с подаванията, но настройката „core.commitGraph“ е "
-"изключена"
-
-#: commit-graph.c:2384
-msgid "too many commits to write graph"
-msgstr "прекалено много подавания за записване на гра̀фа"
-
-#: commit-graph.c:2482
-msgid "the commit-graph file has incorrect checksum and is likely corrupt"
-msgstr "графът с подаванията е с грешна сума за проверка — вероятно е повреден"
-
-#: commit-graph.c:2492
-#, c-format
-msgid "commit-graph has incorrect OID order: %s then %s"
-msgstr ""
-"неправилна подредба на обектите по идентификатор в гра̀фа с подаванията: „%s“ "
-"е преди „%s“, а не трябва"
-
-#: commit-graph.c:2502 commit-graph.c:2517
-#, c-format
-msgid "commit-graph has incorrect fanout value: fanout[%d] = %u != %u"
-msgstr ""
-"неправилна стойност за откъс в гра̀фа с подаванията: fanout[%d] = %u, а "
-"трябва да е %u"
-
-#: commit-graph.c:2509
-#, c-format
-msgid "failed to parse commit %s from commit-graph"
-msgstr "подаване „%s“ в гра̀фа с подаванията не може да се анализира"
-
-#: commit-graph.c:2527
-msgid "Verifying commits in commit graph"
-msgstr "Проверка на подаванията в гра̀фа"
-
-#: commit-graph.c:2542
-#, c-format
-msgid "failed to parse commit %s from object database for commit-graph"
-msgstr ""
-"подаване „%s“ в базата от данни към гра̀фа с подаванията не може да се "
-"анализира"
-
-#: commit-graph.c:2549
-#, c-format
-msgid "root tree OID for commit %s in commit-graph is %s != %s"
-msgstr ""
-"идентификаторът на обект за кореновото дърво за подаване „%s“ в гра̀фа с "
-"подаванията е „%s“, а трябва да е „%s“"
-
-#: commit-graph.c:2559
-#, c-format
-msgid "commit-graph parent list for commit %s is too long"
-msgstr "списъкът с родители на „%s“ в гра̀фа с подаванията е прекалено дълъг"
-
-#: commit-graph.c:2568
-#, c-format
-msgid "commit-graph parent for %s is %s != %s"
-msgstr "родителят на „%s“ в гра̀фа с подаванията е „%s“, а трябва да е „%s“"
-
-#: commit-graph.c:2582
-#, c-format
-msgid "commit-graph parent list for commit %s terminates early"
-msgstr "списъкът с родители на „%s“ в гра̀фа с подаванията е прекалено къс"
-
-#: commit-graph.c:2587
-#, c-format
-msgid ""
-"commit-graph has generation number zero for commit %s, but non-zero elsewhere"
-msgstr ""
-"номерът на поколението на подаване „%s“ в гра̀фа с подаванията е 0, а другаде "
-"не е"
-
-#: commit-graph.c:2591
-#, c-format
-msgid ""
-"commit-graph has non-zero generation number for commit %s, but zero elsewhere"
-msgstr ""
-"номерът на поколението на подаване „%s“ в гра̀фа с подаванията не е 0, а "
-"другаде е"
-
-#: commit-graph.c:2608
-#, c-format
-msgid "commit-graph generation for commit %s is %<PRIuMAX> < %<PRIuMAX>"
-msgstr ""
-"номерът на поколението на подаване „%s“ в гра̀фа с подаванията е %<PRIuMAX> < "
-"%<PRIuMAX>"
-
-#: commit-graph.c:2614
-#, c-format
-msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>"
-msgstr ""
-"датата на подаване на „%s“ в гра̀фа с подаванията е %<PRIuMAX>, а трябва да е "
-"%<PRIuMAX>"
-
-#: commit.c:53 sequencer.c:3109 builtin/am.c:399 builtin/am.c:444
-#: builtin/am.c:449 builtin/am.c:1448 builtin/am.c:2123 builtin/replace.c:456
-#, c-format
-msgid "could not parse %s"
-msgstr "„%s“ не може да се анализира"
-
-#: commit.c:55
-#, c-format
-msgid "%s %s is not a commit!"
-msgstr "%s %s не е подаване!"
-
-#: commit.c:196
-msgid ""
-"Support for <GIT_DIR>/info/grafts is deprecated\n"
-"and will be removed in a future Git version.\n"
-"\n"
-"Please use \"git replace --convert-graft-file\"\n"
-"to convert the grafts into replace refs.\n"
-"\n"
-"Turn this message off by running\n"
-"\"git config advice.graftFileDeprecated false\""
-msgstr ""
-"Поддръжката на „<GIT_DIR>/info/grafts“ е остаряла.\n"
-"В бъдеща версия на Git ще бъде премахната.\n"
-"\n"
-"Може да преобразувате присадките в заместващи\n"
-"указатели с командата:\n"
-"\n"
-" git replace --convert-graft-file\n"
-"\n"
-"За да изключите това съобщение, изпълнете:\n"
-"\n"
-" git config advice.graftFileDeprecated false"
-
-#: commit.c:1241
-#, c-format
-msgid "Commit %s has an untrusted GPG signature, allegedly by %s."
-msgstr ""
-"Подаването „%s“ е с недоверен подпис от GPG, който твърди, че е на „%s“."
-
-#: commit.c:1245
-#, c-format
-msgid "Commit %s has a bad GPG signature allegedly by %s."
-msgstr ""
-"Подаването „%s“ е с неправилен подпис от GPG, който твърди, че е на „%s“."
-
-#: commit.c:1248
-#, c-format
-msgid "Commit %s does not have a GPG signature."
-msgstr "Подаването „%s“ е без подпис от GPG."
-
-#: commit.c:1251
-#, c-format
-msgid "Commit %s has a good GPG signature by %s\n"
-msgstr "Подаването „%s“ е с коректен подпис от GPG на „%s“.\n"
-
-#: commit.c:1505
-msgid ""
-"Warning: commit message did not conform to UTF-8.\n"
-"You may want to amend it after fixing the message, or set the config\n"
-"variable i18n.commitencoding to the encoding your project uses.\n"
-msgstr ""
-"ПРЕДУПРЕЖДЕНИЕ: съобщението при подаване не е кодирано с UTF-8.\n"
-"Може да поправите подаването заедно със съобщението или може да\n"
-"зададете ползваното кодиране в настройката „i18n.commitencoding“.\n"
-
-#: compat/obstack.c:406 compat/obstack.c:408
-msgid "memory exhausted"
-msgstr "паметта свърши"
-
-#: config.c:125
-#, c-format
-msgid ""
-"exceeded maximum include depth (%d) while including\n"
-"\t%s\n"
-"from\n"
-"\t%s\n"
-"This might be due to circular includes."
-msgstr ""
-"максималната дълбочина на влагане (%d) е надвишена при вмъкването на:\n"
-" %s\n"
-"от\n"
-" %s\n"
-"Това може да се дължи на зацикляне при вмъкването."
-
-#: config.c:141
-#, c-format
-msgid "could not expand include path '%s'"
-msgstr "пътят за вмъкване „%s“не може да бъде разширен"
-
-#: config.c:152
-msgid "relative config includes must come from files"
-msgstr "относителните вмъквания на конфигурации трябва да идват от файлове"
-
-#: config.c:201
-msgid "relative config include conditionals must come from files"
-msgstr "относителните условни изрази за вмъкване трябва да идват от файлове"
-
-#: config.c:398
-#, c-format
-msgid "invalid config format: %s"
-msgstr "неправилен формат на настройка: %s"
-
-#: config.c:402
-#, c-format
-msgid "missing environment variable name for configuration '%.*s'"
-msgstr "липсва име на променлива на средата за настройката „%.*s“"
-
-#: config.c:407
-#, c-format
-msgid "missing environment variable '%s' for configuration '%.*s'"
-msgstr "липсва променлива на средата „%s“ за настройката „%.*s“"
-
-#: config.c:443
-#, c-format
-msgid "key does not contain a section: %s"
-msgstr "ключът не съдържа раздел: „%s“"
-
-#: config.c:448
-#, c-format
-msgid "key does not contain variable name: %s"
-msgstr "ключът не съдържа име на променлива: „%s“"
-
-#: config.c:470 sequencer.c:2806
-#, c-format
-msgid "invalid key: %s"
-msgstr "неправилен ключ: „%s“"
-
-#: config.c:475
-#, c-format
-msgid "invalid key (newline): %s"
-msgstr "неправилен ключ (нов ред): „%s“"
-
-#: config.c:495
-msgid "empty config key"
-msgstr "празен ключ за настройка"
-
-#: config.c:513 config.c:525
-#, c-format
-msgid "bogus config parameter: %s"
-msgstr "неправилен конфигурационен параметър: „%s“"
-
-#: config.c:539 config.c:556 config.c:563 config.c:572
-#, c-format
-msgid "bogus format in %s"
-msgstr "неправилен формат в „%s“"
-
-#: config.c:606
-#, c-format
-msgid "bogus count in %s"
-msgstr "неправилен брой в „%s“"
-
-#: config.c:610
-#, c-format
-msgid "too many entries in %s"
-msgstr "прекалено много записи в „%s“"
-
-#: config.c:620
-#, c-format
-msgid "missing config key %s"
-msgstr "ключът за настройка „%s“ липсва"
-
-#: config.c:628
-#, c-format
-msgid "missing config value %s"
-msgstr "стойността за настройка „%s“ липсва"
-
-#: config.c:979
-#, c-format
-msgid "bad config line %d in blob %s"
-msgstr "неправилен ред за настройки %d в BLOB „%s“"
-
-#: config.c:983
-#, c-format
-msgid "bad config line %d in file %s"
-msgstr "неправилен ред за настройки %d във файла „%s“"
-
-#: config.c:987
-#, c-format
-msgid "bad config line %d in standard input"
-msgstr "неправилен ред за настройки %d на стандартния вход"
-
-#: config.c:991
-#, c-format
-msgid "bad config line %d in submodule-blob %s"
-msgstr "неправилен ред за настройки %d в BLOB за подмодул „%s“"
-
-#: config.c:995
-#, c-format
-msgid "bad config line %d in command line %s"
-msgstr "неправилен ред за настройки %d на командния ред „%s“"
-
-#: config.c:999
-#, c-format
-msgid "bad config line %d in %s"
-msgstr "неправилен ред за настройки %d в „%s“"
-
-#: config.c:1136
-msgid "out of range"
-msgstr "извън диапазона"
-
-#: config.c:1136
-msgid "invalid unit"
-msgstr "неправилна мерна единица"
-
-#: config.c:1137
-#, c-format
-msgid "bad numeric config value '%s' for '%s': %s"
-msgstr "неправилна числова стойност „%s“ за „%s“: %s"
-
-#: config.c:1147
-#, c-format
-msgid "bad numeric config value '%s' for '%s' in blob %s: %s"
-msgstr "неправилна числова стойност „%s“ за „%s“ в BLOB „%s“: %s"
-
-#: config.c:1150
-#, c-format
-msgid "bad numeric config value '%s' for '%s' in file %s: %s"
-msgstr "неправилна числова стойност „%s“ за „%s“ във файла „%s“: %s"
-
-#: config.c:1153
-#, c-format
-msgid "bad numeric config value '%s' for '%s' in standard input: %s"
-msgstr "неправилна числова стойност „%s“ за „%s“ на стандартния вход: %s"
-
-#: config.c:1156
-#, c-format
-msgid "bad numeric config value '%s' for '%s' in submodule-blob %s: %s"
-msgstr "неправилна числова стойност „%s“ за „%s“ в BLOB от подмодул „%s“: %s"
-
-#: config.c:1159
-#, c-format
-msgid "bad numeric config value '%s' for '%s' in command line %s: %s"
-msgstr "неправилна числова стойност „%s“ за „%s“ на командния ред „%s“: %s"
-
-#: config.c:1162
-#, c-format
-msgid "bad numeric config value '%s' for '%s' in %s: %s"
-msgstr "неправилна числова стойност „%s“ за „%s“ в %s: %s"
-
-#: config.c:1241
-#, c-format
-msgid "bad boolean config value '%s' for '%s'"
-msgstr "неправилна булева стойност „%s“ за „%s“"
-
-#: config.c:1259
-#, c-format
-msgid "failed to expand user dir in: '%s'"
-msgstr "домашната папка на потребителя не може да бъде открита: „%s“"
-
-#: config.c:1268
-#, c-format
-msgid "'%s' for '%s' is not a valid timestamp"
-msgstr "„%s“ не е правилна стойност за време за „%s“"
-
-#: config.c:1361
-#, c-format
-msgid "abbrev length out of range: %d"
-msgstr "дължината на съкращаване е извън интервала ([4; 40]): %d"
-
-#: config.c:1375 config.c:1386
-#, c-format
-msgid "bad zlib compression level %d"
-msgstr "неправилно ниво на компресиране: %d"
-
-#: config.c:1476
-msgid "core.commentChar should only be one character"
-msgstr "настройката „core.commentChar“ трябва да е само един знак"
-
-#: config.c:1509
-#, c-format
-msgid "invalid mode for object creation: %s"
-msgstr "неправилен режим за създаването на обекти: %s"
-
-#: config.c:1584
-#, c-format
-msgid "malformed value for %s"
-msgstr "неправилна стойност за „%s“"
-
-#: config.c:1610
-#, c-format
-msgid "malformed value for %s: %s"
-msgstr "неправилна стойност за „%s“: „%s“"
-
-#: config.c:1611
-msgid "must be one of nothing, matching, simple, upstream or current"
-msgstr ""
-"трябва да е една от следните стойности: „nothing“ (без изтласкване при липса "
-"на указател), „matching“ (всички клони със съвпадащи имена), "
-"„simple“ (клонът със същото име, от който се издърпва), „upstream“ (клонът, "
-"от който се издърпва) или „current“ (клонът със същото име)"
-
-#: config.c:1672 builtin/pack-objects.c:4053
-#, c-format
-msgid "bad pack compression level %d"
-msgstr "неправилно ниво на компресиране при пакетиране: %d"
-
-#: config.c:1795
-#, c-format
-msgid "unable to load config blob object '%s'"
-msgstr "обектът-BLOB „%s“ с конфигурации не може да се зареди"
-
-#: config.c:1798
-#, c-format
-msgid "reference '%s' does not point to a blob"
-msgstr "указателят „%s“ не сочи към обект-BLOB"
-
-#: config.c:1816
-#, c-format
-msgid "unable to resolve config blob '%s'"
-msgstr "обектът-BLOB „%s“ с конфигурации не може да бъде открит"
-
-#: config.c:1861
-#, c-format
-msgid "failed to parse %s"
-msgstr "„%s“ не може да бъде анализиран"
-
-#: config.c:1917
-msgid "unable to parse command-line config"
-msgstr "неправилни настройки от командния ред"
-
-#: config.c:2285
-msgid "unknown error occurred while reading the configuration files"
-msgstr "неочаквана грешка при изчитането на конфигурационните файлове"
-
-#: config.c:2459
-#, c-format
-msgid "Invalid %s: '%s'"
-msgstr "Неправилен %s: „%s“"
-
-#: config.c:2504
-#, c-format
-msgid "splitIndex.maxPercentChange value '%d' should be between 0 and 100"
-msgstr ""
-"стойността на „splitIndex.maxPercentChange“ трябва да е между 1 и 100, а не "
-"%d"
-
-#: config.c:2550
-#, c-format
-msgid "unable to parse '%s' from command-line config"
-msgstr "неразпозната стойност „%s“ от командния ред"
-
-#: config.c:2552
-#, c-format
-msgid "bad config variable '%s' in file '%s' at line %d"
-msgstr "неправилна настройка „%s“ във файла „%s“ на ред №%d"
-
-#: config.c:2637
-#, c-format
-msgid "invalid section name '%s'"
-msgstr "неправилно име на раздел: „%s“"
-
-#: config.c:2669
-#, c-format
-msgid "%s has multiple values"
-msgstr "зададени са няколко стойности за „%s“"
-
-#: config.c:2698
-#, c-format
-msgid "failed to write new configuration file %s"
-msgstr "новият конфигурационен файл „%s“ не може да бъде запазен"
-
-#: config.c:2950 config.c:3277
-#, c-format
-msgid "could not lock config file %s"
-msgstr "конфигурационният файл „%s“ не може да бъде заключен"
-
-#: config.c:2961
-#, c-format
-msgid "opening %s"
-msgstr "отваряне на „%s“"
-
-#: config.c:2998 builtin/config.c:361
-#, c-format
-msgid "invalid pattern: %s"
-msgstr "неправилен шаблон: %s"
-
-#: config.c:3023
-#, c-format
-msgid "invalid config file %s"
-msgstr "неправилен конфигурационен файл: „%s“"
-
-#: config.c:3036 config.c:3290
-#, c-format
-msgid "fstat on %s failed"
-msgstr "неуспешно изпълнение на „fstat“ върху „%s“"
-
-#: config.c:3047
-#, c-format
-msgid "unable to mmap '%s'%s"
-msgstr "неуспешно изпълнение на „mmap“ върху „%s“%s"
-
-#: config.c:3057 config.c:3295
-#, c-format
-msgid "chmod on %s failed"
-msgstr "неуспешна смяна на права с „chmod“ върху „%s“"
-
-#: config.c:3142 config.c:3392
-#, c-format
-msgid "could not write config file %s"
-msgstr "конфигурационният файл „%s“ не може да бъде записан"
-
-#: config.c:3176
-#, c-format
-msgid "could not set '%s' to '%s'"
-msgstr "„%s“ не може да се зададе да е „%s“"
-
-#: config.c:3178 builtin/remote.c:662 builtin/remote.c:860 builtin/remote.c:868
-#, c-format
-msgid "could not unset '%s'"
-msgstr "„%s“ не може да се премахне"
-
-#: config.c:3268
-#, c-format
-msgid "invalid section name: %s"
-msgstr "неправилно име на раздел: %s"
-
-#: config.c:3435
-#, c-format
-msgid "missing value for '%s'"
-msgstr "липсва стойност за „%s“"
-
-#: connect.c:61
-msgid "the remote end hung up upon initial contact"
-msgstr "отдалеченото хранилище прекъсна връзката веднага след отварянето ѝ"
-
-#: connect.c:63
-msgid ""
-"Could not read from remote repository.\n"
-"\n"
-"Please make sure you have the correct access rights\n"
-"and the repository exists."
-msgstr ""
-"Не може да се чете от отдалеченото хранилище.\n"
-"\n"
-"Проверете дали то съществува и дали имате права\n"
-"за достъп."
-
-#: connect.c:81
-#, c-format
-msgid "server doesn't support '%s'"
-msgstr "сървърът не поддържа „%s“"
-
-#: connect.c:118
-#, c-format
-msgid "server doesn't support feature '%s'"
-msgstr "сървърът не поддържа „%s“"
-
-#: connect.c:129
-msgid "expected flush after capabilities"
-msgstr ""
-"след първоначалната обява на възможностите се очаква изчистване на буферите"
-
-#: connect.c:265
-#, c-format
-msgid "ignoring capabilities after first line '%s'"
-msgstr "пропускане на възможностите след първия ред „%s“"
-
-#: connect.c:286
-msgid "protocol error: unexpected capabilities^{}"
-msgstr "протоколна грешка: неочаквани възможности^{}"
-
-#: connect.c:308
-#, c-format
-msgid "protocol error: expected shallow sha-1, got '%s'"
-msgstr "протоколна грешка: очаква се SHA1 на плитък обект, а бе получено: „%s“"
-
-#: connect.c:310
-msgid "repository on the other end cannot be shallow"
-msgstr "отсрещното хранилище не може да е плитко"
-
-#: connect.c:349
-msgid "invalid packet"
-msgstr "неправилен пакет"
-
-#: connect.c:369
-#, c-format
-msgid "protocol error: unexpected '%s'"
-msgstr "протоколна грешка: неочаквано „%s“"
-
-#: connect.c:499
-#, c-format
-msgid "unknown object format '%s' specified by server"
-msgstr "сървърът указа непознат формат на обект: „%s“"
-
-#: connect.c:528
-#, c-format
-msgid "invalid ls-refs response: %s"
-msgstr "неправилен отговор на „ls-refs“: „%s“"
-
-#: connect.c:532
-msgid "expected flush after ref listing"
-msgstr "след изброяването на указателите се очаква изчистване на буферите"
-
-#: connect.c:535
-msgid "expected response end packet after ref listing"
-msgstr "след изброяването на указателите се очаква пакет за край"
-
-#: connect.c:670
-#, c-format
-msgid "protocol '%s' is not supported"
-msgstr "протокол „%s“ не се поддържа"
-
-#: connect.c:721
-msgid "unable to set SO_KEEPALIVE on socket"
-msgstr "неуспешно задаване на „SO_KEEPALIVE“ на гнездо"
-
-#: connect.c:761 connect.c:824
-#, c-format
-msgid "Looking up %s ... "
-msgstr "Търсене на „%s“… "
-
-#: connect.c:765
-#, c-format
-msgid "unable to look up %s (port %s) (%s)"
-msgstr "„%s“ (порт %s) не може да се открие („%s“)"
-
-#. TRANSLATORS: this is the end of "Looking up %s ... "
-#: connect.c:769 connect.c:840
-#, c-format
-msgid ""
-"done.\n"
-"Connecting to %s (port %s) ... "
-msgstr ""
-"готово.\n"
-"Свързване към „%s“ (порт %s)…"
-
-#: connect.c:791 connect.c:868
-#, c-format
-msgid ""
-"unable to connect to %s:\n"
-"%s"
-msgstr ""
-"неуспешно свързване към „%s“:\n"
-"%s"
-
-#. TRANSLATORS: this is the end of "Connecting to %s (port %s) ... "
-#: connect.c:797 connect.c:874
-msgid "done."
-msgstr "действието завърши."
-
-#: connect.c:828
-#, c-format
-msgid "unable to look up %s (%s)"
-msgstr "„%s“ не може да се открие (%s)"
-
-#: connect.c:834
-#, c-format
-msgid "unknown port %s"
-msgstr "непознат порт „%s“"
-
-#: connect.c:971 connect.c:1303
-#, c-format
-msgid "strange hostname '%s' blocked"
-msgstr "необичайното име на хост „%s“ е блокирано"
-
-#: connect.c:973
-#, c-format
-msgid "strange port '%s' blocked"
-msgstr "необичайният порт „%s“ е блокиран"
-
-#: connect.c:983
-#, c-format
-msgid "cannot start proxy %s"
-msgstr "посредникът „%s“ не може да се стартира"
-
-#: connect.c:1054
-msgid "no path specified; see 'git help pull' for valid url syntax"
-msgstr ""
-"не е указан път. Проверете синтаксиса с командата:\n"
-"\n"
-" git help pull"
-
-#: connect.c:1194
-msgid "newline is forbidden in git:// hosts and repo paths"
-msgstr ""
-"знакът за нов ред не е позволен в адресите и в пътищата до хранилищата "
-"„git://“"
-
-#: connect.c:1251
-msgid "ssh variant 'simple' does not support -4"
-msgstr "вариантът за „ssh“ — „simple“ (опростен), не поддържа опцията „-4“"
-
-#: connect.c:1263
-msgid "ssh variant 'simple' does not support -6"
-msgstr "вариантът за „ssh“ — „simple“ (опростен), не поддържа опцията „-6“"
-
-#: connect.c:1280
-msgid "ssh variant 'simple' does not support setting port"
-msgstr ""
-"вариантът за „ssh“ — „simple“ (опростен), не поддържа задаването на порт"
-
-#: connect.c:1392
-#, c-format
-msgid "strange pathname '%s' blocked"
-msgstr "необичайният път „%s“ е блокиран"
-
-#: connect.c:1440
-msgid "unable to fork"
-msgstr "неуспешно създаване на процес"
-
-#: connected.c:109 builtin/fsck.c:189 builtin/prune.c:57
-msgid "Checking connectivity"
-msgstr "Проверка на свързаността"
-
-#: connected.c:122
-msgid "Could not run 'git rev-list'"
-msgstr "Командата „git rev-list“ не може да бъде изпълнена."
-
-#: connected.c:146
-msgid "failed write to rev-list"
-msgstr "неуспешен запис на списъка с версиите"
-
-#: connected.c:151
-msgid "failed to close rev-list's stdin"
-msgstr "стандартният вход на списъка с версиите не може да бъде затворен"
-
-#: convert.c:183
-#, c-format
-msgid "illegal crlf_action %d"
-msgstr "неправилно действие за край на ред (crlf_action): %d"
-
-#: convert.c:196
-#, c-format
-msgid "CRLF would be replaced by LF in %s"
-msgstr "Всяка последователност от знаци „CRLF“ ще бъдe заменена с „LF“ в „%s“."
-
-#: convert.c:198
-#, c-format
-msgid ""
-"CRLF will be replaced by LF in %s.\n"
-"The file will have its original line endings in your working directory"
-msgstr ""
-"Всяка последователност от знаци „CRLF“ ще бъдe заменена с „LF“ в „%s“.\n"
-"Файлът ще остане с първоначалните знаци за край на ред в работната ви "
-"директория."
-
-#: convert.c:206
-#, c-format
-msgid "LF would be replaced by CRLF in %s"
-msgstr ""
-"Всеки знак „LF“ ще бъдe заменен с последователността от знаци „CRLF“ в „%s“."
-
-#: convert.c:208
-#, c-format
-msgid ""
-"LF will be replaced by CRLF in %s.\n"
-"The file will have its original line endings in your working directory"
-msgstr ""
-"Всеки знак „LF“ ще бъдe заменен с последователността от знаци „CRLF“ в "
-"„%s“.\n"
-"Файлът ще остане с първоначалните знаци за край на ред в работната ви "
-"директория."
-
-#: convert.c:273
-#, c-format
-msgid "BOM is prohibited in '%s' if encoded as %s"
-msgstr ""
-"„%s“ не трябва да съдържа маркер за поредността на байтовете (BOM) при "
-"кодиране „%s“"
-
-#: convert.c:280
-#, c-format
-msgid ""
-"The file '%s' contains a byte order mark (BOM). Please use UTF-%.*s as "
-"working-tree-encoding."
-msgstr ""
-"Файлът „%s“ съдържа маркер за поредността на байтовете (BOM). Използвайте "
-"„UTF-%.*s“ като кодиране за работното дърво."
-
-#: convert.c:293
-#, c-format
-msgid "BOM is required in '%s' if encoded as %s"
-msgstr ""
-"„%s“ трябва да съдържа маркер за поредността на байтовете (BOM) при кодиране "
-"„%s“"
-
-#: convert.c:295
-#, c-format
-msgid ""
-"The file '%s' is missing a byte order mark (BOM). Please use UTF-%sBE or UTF-"
-"%sLE (depending on the byte order) as working-tree-encoding."
-msgstr ""
-"Във файла „%s“ липсва маркер за поредността на байтовете (BOM). За кодиране "
-"на работното дърво използвайте UTF-%sBE или UTF-%sLE (в зависимост от "
-"поредността на байтовете)."
-
-#: convert.c:408 convert.c:479
-#, c-format
-msgid "failed to encode '%s' from %s to %s"
-msgstr "неуспешно прекодиране на „%s“ от „%s“ към „%s“"
-
-#: convert.c:451
-#, c-format
-msgid "encoding '%s' from %s to %s and back is not the same"
-msgstr "Прекодирането на „%s“ от „%s“ към „%s“ и обратно променя файла"
-
-#: convert.c:654
-#, c-format
-msgid "cannot fork to run external filter '%s'"
-msgstr "неуспешно създаване на процес за външен филтър „%s“"
-
-#: convert.c:674
-#, c-format
-msgid "cannot feed the input to external filter '%s'"
-msgstr "входът не може да бъде подаден на външния филтър „%s“"
-
-#: convert.c:681
-#, c-format
-msgid "external filter '%s' failed %d"
-msgstr "неуспешно изпълнение на външния филтър „%s“: %d"
-
-#: convert.c:716 convert.c:719
-#, c-format
-msgid "read from external filter '%s' failed"
-msgstr "неуспешно четене от външния филтър „%s“"
-
-#: convert.c:722 convert.c:777
-#, c-format
-msgid "external filter '%s' failed"
-msgstr "неуспешно изпълнение на външния филтър „%s“"
-
-#: convert.c:826
-msgid "unexpected filter type"
-msgstr "неочакван вид филтър"
-
-#: convert.c:837
-msgid "path name too long for external filter"
-msgstr "пътят е прекалено дълъг за външен филтър"
-
-#: convert.c:935
-#, c-format
-msgid ""
-"external filter '%s' is not available anymore although not all paths have "
-"been filtered"
-msgstr ""
-"външният филтър „%s“ вече не е наличен, въпреки че не всички пътища са "
-"филтрирани"
-
-#: convert.c:1236
-msgid "true/false are no valid working-tree-encodings"
-msgstr ""
-"„true“/„false“ (истина/лъжа̀) не може да са кодирания на работното дърво"
-
-#: convert.c:1416 convert.c:1449
-#, c-format
-msgid "%s: clean filter '%s' failed"
-msgstr "%s: неуспешно изпълнение на декодиращ филтър „%s“"
-
-#: convert.c:1492
-#, c-format
-msgid "%s: smudge filter %s failed"
-msgstr "%s: неуспешно изпълнение на кодиращ филтър „%s“"
-
-#: credential.c:96
-#, c-format
-msgid "skipping credential lookup for key: credential.%s"
-msgstr "прескачане на търсенето на идентификация според ключа: „credential.%s“"
-
-#: credential.c:112
-msgid "refusing to work with credential missing host field"
-msgstr "адресът трябва задължително да съдържа хост"
-
-#: credential.c:114
-msgid "refusing to work with credential missing protocol field"
-msgstr "адресът трябва задължително да съдържа протокол"
-
-#: credential.c:395
-#, c-format
-msgid "url contains a newline in its %s component: %s"
-msgstr "адресът съдържа нов ред в частта за %s: %s"
-
-#: credential.c:439
-#, c-format
-msgid "url has no scheme: %s"
-msgstr "адресът е без схема: %s"
-
-#: credential.c:512
-#, c-format
-msgid "credential url cannot be parsed: %s"
-msgstr "адресът за идентификация не може да се анализира: „%s“"
-
-#: date.c:138
-msgid "in the future"
-msgstr "в бъдещето"
-
-#: date.c:144
-#, c-format
-msgid "%<PRIuMAX> second ago"
-msgid_plural "%<PRIuMAX> seconds ago"
-msgstr[0] "преди %<PRIuMAX> секунда"
-msgstr[1] "преди %<PRIuMAX> секунди"
-
-#: date.c:151
-#, c-format
-msgid "%<PRIuMAX> minute ago"
-msgid_plural "%<PRIuMAX> minutes ago"
-msgstr[0] "преди %<PRIuMAX> минута"
-msgstr[1] "преди %<PRIuMAX> минути"
-
-#: date.c:158
-#, c-format
-msgid "%<PRIuMAX> hour ago"
-msgid_plural "%<PRIuMAX> hours ago"
-msgstr[0] "преди %<PRIuMAX> час"
-msgstr[1] "преди %<PRIuMAX> часа"
-
-#: date.c:165
-#, c-format
-msgid "%<PRIuMAX> day ago"
-msgid_plural "%<PRIuMAX> days ago"
-msgstr[0] "преди %<PRIuMAX> ден"
-msgstr[1] "преди %<PRIuMAX> дена"
-
-#: date.c:171
-#, c-format
-msgid "%<PRIuMAX> week ago"
-msgid_plural "%<PRIuMAX> weeks ago"
-msgstr[0] "преди %<PRIuMAX> седмица"
-msgstr[1] "преди %<PRIuMAX> седмици"
-
-#: date.c:178
-#, c-format
-msgid "%<PRIuMAX> month ago"
-msgid_plural "%<PRIuMAX> months ago"
-msgstr[0] "преди %<PRIuMAX> месец"
-msgstr[1] "преди %<PRIuMAX> месеца"
-
-#: date.c:189
-#, c-format
-msgid "%<PRIuMAX> year"
-msgid_plural "%<PRIuMAX> years"
-msgstr[0] "%<PRIuMAX> година"
-msgstr[1] "%<PRIuMAX> години"
-
-#. TRANSLATORS: "%s" is "<n> years"
-#: date.c:192
-#, c-format
-msgid "%s, %<PRIuMAX> month ago"
-msgid_plural "%s, %<PRIuMAX> months ago"
-msgstr[0] "преди %s и %<PRIuMAX> месец"
-msgstr[1] "преди %s и %<PRIuMAX> месеца"
-
-#: date.c:197 date.c:202
-#, c-format
-msgid "%<PRIuMAX> year ago"
-msgid_plural "%<PRIuMAX> years ago"
-msgstr[0] "преди %<PRIuMAX> година"
-msgstr[1] "преди %<PRIuMAX> години"
-
-#: delta-islands.c:272
-msgid "Propagating island marks"
-msgstr "Разпространяване на границите на групите"
-
-#: delta-islands.c:290
-#, c-format
-msgid "bad tree object %s"
-msgstr "неправилен обект-дърво: %s"
-
-#: delta-islands.c:334
-#, c-format
-msgid "failed to load island regex for '%s': %s"
-msgstr "регулярният израз на групата за „%s“, не може да бъде зареден: „%s“"
-
-#: delta-islands.c:390
-#, c-format
-msgid "island regex from config has too many capture groups (max=%d)"
-msgstr ""
-"регулярният израз на групата в конфигурационния файл съдържа повече от "
-"максимално поддържаните (%d) прихващащи групи"
-
-#: delta-islands.c:467
-#, c-format
-msgid "Marked %d islands, done.\n"
-msgstr "Отбелязани са %d групи, работата приключи.\n"
-
-#: diff-merges.c:70
-#, c-format
-msgid "unknown value for --diff-merges: %s"
-msgstr "непозната стойност за опцията „--diff-merges“: „%s“"
-
-#: diff-lib.c:561
-msgid "--merge-base does not work with ranges"
-msgstr "опцията „--merge-base“ не работи с диапазони"
-
-#: diff-lib.c:563
-msgid "--merge-base only works with commits"
-msgstr "опцията „--merge-base“ работи само с подавания"
-
-#: diff-lib.c:580
-msgid "unable to get HEAD"
-msgstr "Указателят „HEAD“ не може да бъде получен"
-
-#: diff-lib.c:587
-msgid "no merge base found"
-msgstr "липсва база за сливане"
-
-#: diff-lib.c:589
-msgid "multiple merge bases found"
-msgstr "много бази за сливане"
-
-#: diff-no-index.c:237
-msgid "git diff --no-index [<options>] <path> <path>"
-msgstr "git diff --no-index [ОПЦИЯ…] ПЪТ ПЪТ"
-
-#: diff-no-index.c:262
-msgid ""
-"Not a git repository. Use --no-index to compare two paths outside a working "
-"tree"
-msgstr ""
-"Не е хранилище на git. Ползвайте опцията „--no-index“, за да сравните "
-"пътища извън работно дърво"
-
-#: diff.c:158
-#, c-format
-msgid " Failed to parse dirstat cut-off percentage '%s'\n"
-msgstr ""
-" Неуспешно разпознаване на „%s“ като процент-праг за статистиката по "
-"директории\n"
-
-#: diff.c:163
-#, c-format
-msgid " Unknown dirstat parameter '%s'\n"
-msgstr " Непознат параметър „%s“ за статистиката по директории'\n"
-
-#: diff.c:299
-msgid ""
-"color moved setting must be one of 'no', 'default', 'blocks', 'zebra', "
-"'dimmed-zebra', 'plain'"
-msgstr ""
-"настройката за цвят за преместване трябва да е една от: „no“ (без), "
-"„default“ (стандартно), „blocks“ (парчета), „zebra“ (райе), „dimmed-"
-"zebra“ (тъмно райе), „plain“ (обикновено)"
-
-#: diff.c:327
-#, c-format
-msgid ""
-"unknown color-moved-ws mode '%s', possible values are 'ignore-space-change', "
-"'ignore-space-at-eol', 'ignore-all-space', 'allow-indentation-change'"
-msgstr ""
-"неподдържан режим за настройката „color-moved-ws mode“ — „%s“, възможните "
-"стойности са „ignore-space-change“ (пренебрегване на промените на празните "
-"знаци), „ignore-space-at-eol“ (пренебрегване на промените на празните знаци "
-"в края на реда), „ignore-all-space“ (пренебрегване на всички празни знаци), "
-"„allow-indentation-change“ (позволяване на промените в празните знаци за "
-"форматиране)"
-
-#: diff.c:335
-msgid ""
-"color-moved-ws: allow-indentation-change cannot be combined with other "
-"whitespace modes"
-msgstr ""
-"„color-moved-ws“: „allow-indentation-change“ е несъвместима с другите режими "
-"за празни знаци"
-
-#: diff.c:412
-#, c-format
-msgid "Unknown value for 'diff.submodule' config variable: '%s'"
-msgstr "Непозната стойност „%s“ за настройката „diff.submodule“"
-
-#: diff.c:472
-#, c-format
-msgid ""
-"Found errors in 'diff.dirstat' config variable:\n"
-"%s"
-msgstr ""
-"Грешки в настройката „diff.dirstat“:\n"
-"%s"
-
-#: diff.c:4237
-#, c-format
-msgid "external diff died, stopping at %s"
-msgstr ""
-"външната програма за разлики завърши неуспешно. Спиране на работата при „%s“"
-
-#: diff.c:4589
-#, c-format
-msgid "options '%s', '%s', '%s', and '%s' cannot be used together"
-msgstr "опциите „%s“, „%s“, „%s“ и „%s“ са несъвместими"
-
-#: diff.c:4593 builtin/difftool.c:736 builtin/log.c:1982 builtin/worktree.c:506
-#, c-format
-msgid "options '%s', '%s', and '%s' cannot be used together"
-msgstr "опциите „%s“, „%s“ и „%s“ са несъвместими"
-
-#: diff.c:4597
-#, c-format
-msgid "options '%s' and '%s' cannot be used together, use '%s' with '%s'"
-msgstr "опциите „%s“ и „%s“ са несъвместими, използвайте „%s“ с „%s“"
-
-#: diff.c:4601
-#, c-format
-msgid ""
-"options '%s' and '%s' cannot be used together, use '%s' with '%s' and '%s'"
-msgstr "опциите „%s“ и „%s“ са несъвместими, използвайте „%s“ с „%s“ и „%s“"
-
-#: diff.c:4681
-msgid "--follow requires exactly one pathspec"
-msgstr "опцията „--follow“ изисква точно един път"
-
-#: diff.c:4729
-#, c-format
-msgid "invalid --stat value: %s"
-msgstr "неправилна стойност за „--stat“: %s"
-
-#: diff.c:4734 diff.c:4739 diff.c:4744 diff.c:4749 diff.c:5277
-#: parse-options.c:217 parse-options.c:221
-#, c-format
-msgid "%s expects a numerical value"
-msgstr "опцията „%s“ очаква число за аргумент"
-
-#: diff.c:4766
-#, c-format
-msgid ""
-"Failed to parse --dirstat/-X option parameter:\n"
-"%s"
-msgstr ""
-"Неразпознат параметър към опцията „--dirstat/-X“:\n"
-"%s"
-
-#: diff.c:4851
-#, c-format
-msgid "unknown change class '%c' in --diff-filter=%s"
-msgstr "непознат вид промяна: „%c“ в „--diff-filter=%s“"
-
-#: diff.c:4875
-#, c-format
-msgid "unknown value after ws-error-highlight=%.*s"
-msgstr "непозната стойност след „ws-error-highlight=%.*s“"
-
-#: diff.c:4889
-#, c-format
-msgid "unable to resolve '%s'"
-msgstr "„%s“ не може да се открие"
-
-#: diff.c:4939 diff.c:4945
-#, c-format
-msgid "%s expects <n>/<m> form"
-msgstr ""
-"опцията „%s“ изисква стойности за МИНИМАЛЕН_%%_ПРОМЯНА_ЗА_ИЗТОЧНИК_/"
-"МАКСИМАЛЕН_%%_ПРОМЯНА_ЗА_ЗАМЯНА от"
-
-#: diff.c:4957
-#, c-format
-msgid "%s expects a character, got '%s'"
-msgstr "опцията „%s“ изисква знак, а не: „%s“"
-
-#: diff.c:4978
-#, c-format
-msgid "bad --color-moved argument: %s"
-msgstr "неправилен аргумент за „--color-moved“: „%s“"
-
-#: diff.c:4997
-#, c-format
-msgid "invalid mode '%s' in --color-moved-ws"
-msgstr "неправилен режим „%s“ за „ --color-moved-ws“"
-
-#: diff.c:5037
-msgid ""
-"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-msgstr ""
-"опцията приема следните варианти за алгоритъм за разлики: „myers“ (по "
-"Майерс), „minimal“ (минимизиране на разликите), „patience“ (пасианс) и "
-"„histogram“ (хистограмен)"
-
-#: diff.c:5073 diff.c:5093
-#, c-format
-msgid "invalid argument to %s"
-msgstr "неправилен аргумент към „%s“"
-
-#: diff.c:5197
-#, c-format
-msgid "invalid regex given to -I: '%s'"
-msgstr "неправилен регулярен израз подаден към „-I“: „%s“"
-
-#: diff.c:5246
-#, c-format
-msgid "failed to parse --submodule option parameter: '%s'"
-msgstr "неразпознат параметър към опцията „--submodule“: „%s“"
-
-#: diff.c:5302
-#, c-format
-msgid "bad --word-diff argument: %s"
-msgstr "неправилен аргумент към „--word-diff“: „%s“"
-
-#: diff.c:5338
-msgid "Diff output format options"
-msgstr "Формат на изхода за разликите"
-
-#: diff.c:5340 diff.c:5346
-msgid "generate patch"
-msgstr "създаване на кръпки"
-
-#: diff.c:5343 builtin/log.c:179
-msgid "suppress diff output"
-msgstr "без извеждане на разликите"
-
-#: diff.c:5348 diff.c:5462 diff.c:5469
-msgid "<n>"
-msgstr "БРОЙ"
-
-#: diff.c:5349 diff.c:5352
-msgid "generate diffs with <n> lines context"
-msgstr "файловете с разлики да са с контекст с такъв БРОЙ редове"
-
-#: diff.c:5354
-msgid "generate the diff in raw format"
-msgstr "файловете с разлики да са в суров формат"
-
-#: diff.c:5357
-msgid "synonym for '-p --raw'"
-msgstr "псевдоним на „-p --raw“"
-
-#: diff.c:5361
-msgid "synonym for '-p --stat'"
-msgstr "псевдоним на „-p --stat“"
-
-#: diff.c:5365
-msgid "machine friendly --stat"
-msgstr "„--stat“ във формат за четене от програма"
-
-#: diff.c:5368
-msgid "output only the last line of --stat"
-msgstr "извеждане само на последния ред на „--stat“"
-
-#: diff.c:5370 diff.c:5378
-msgid "<param1,param2>..."
-msgstr "ПАРАМЕТЪР_1, ПАРАМЕТЪР_2, …"
-
-#: diff.c:5371
-msgid ""
-"output the distribution of relative amount of changes for each sub-directory"
-msgstr "извеждане на разпределението на промените за всяка поддиректория"
-
-#: diff.c:5375
-msgid "synonym for --dirstat=cumulative"
-msgstr "псевдоним на „--dirstat=cumulative“"
-
-#: diff.c:5379
-msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "псевдоним на „--dirstat=ФАЙЛ…,ПАРАМЕТЪР_1,ПАРАМЕТЪР_2,…“"
-
-#: diff.c:5383
-msgid "warn if changes introduce conflict markers or whitespace errors"
-msgstr ""
-"предупреждаване, ако промените водят до маркери за конфликт или грешки в "
-"празните знаци"
-
-#: diff.c:5386
-msgid "condensed summary such as creations, renames and mode changes"
-msgstr ""
-"съкратено резюме на създадените, преименуваните и файловете с промяна на "
-"режима на достъп"
-
-#: diff.c:5389
-msgid "show only names of changed files"
-msgstr "извеждане само на имената на променените файлове"
-
-#: diff.c:5392
-msgid "show only names and status of changed files"
-msgstr "извеждане само на имената и статистиката за променените файлове"
-
-#: diff.c:5394
-msgid "<width>[,<name-width>[,<count>]]"
-msgstr "ШИРОЧИНА[,ИМЕ-ШИРОЧИНА[,БРОЙ]]"
-
-#: diff.c:5395
-msgid "generate diffstat"
-msgstr "извеждане на статистика за промените"
-
-#: diff.c:5397 diff.c:5400 diff.c:5403
-msgid "<width>"
-msgstr "ШИРОЧИНА"
-
-#: diff.c:5398
-msgid "generate diffstat with a given width"
-msgstr "статистика с такава ШИРОЧИНА за промените"
-
-#: diff.c:5401
-msgid "generate diffstat with a given name width"
-msgstr "статистика за промените с такава ШИРОЧИНА на имената"
-
-#: diff.c:5404
-msgid "generate diffstat with a given graph width"
-msgstr "статистика за промените с такава ШИРОЧИНА на гра̀фа"
-
-#: diff.c:5406
-msgid "<count>"
-msgstr "БРОЙ"
-
-#: diff.c:5407
-msgid "generate diffstat with limited lines"
-msgstr "ограничаване на БРОя на редовете в статистиката за промените"
-
-#: diff.c:5410
-msgid "generate compact summary in diffstat"
-msgstr "кратко резюме в статистиката за промените"
-
-#: diff.c:5413
-msgid "output a binary diff that can be applied"
-msgstr "извеждане на двоична разлика във вид за прилагане"
-
-#: diff.c:5416
-msgid "show full pre- and post-image object names on the \"index\" lines"
-msgstr ""
-"показване на пълните имена на обекти в редовете за индекса при вариантите "
-"преди и след промяната"
-
-#: diff.c:5418
-msgid "show colored diff"
-msgstr "разлики в цвят"
-
-#: diff.c:5419
-msgid "<kind>"
-msgstr "ВИД"
-
-#: diff.c:5420
-msgid ""
-"highlight whitespace errors in the 'context', 'old' or 'new' lines in the "
-"diff"
-msgstr ""
-"грешките в празните знаци да се указват в редовете за контекста, вариантите "
-"преди и след разликата,"
-
-#: diff.c:5423
-msgid ""
-"do not munge pathnames and use NULs as output field terminators in --raw or "
-"--numstat"
-msgstr ""
-"без преименуване на пътищата. Да се използват нулеви байтове за разделители "
-"на полета в изхода при ползване на опцията „--raw“ или „--numstat“"
-
-#: diff.c:5426 diff.c:5429 diff.c:5432 diff.c:5541
-msgid "<prefix>"
-msgstr "ПРЕФИКС"
-
-#: diff.c:5427
-msgid "show the given source prefix instead of \"a/\""
-msgstr "префикс вместо „a/“ за източник"
-
-#: diff.c:5430
-msgid "show the given destination prefix instead of \"b/\""
-msgstr "префикс вместо „b/“ за цел"
-
-#: diff.c:5433
-msgid "prepend an additional prefix to every line of output"
-msgstr "добавяне на допълнителен префикс за всеки ред на изхода"
-
-#: diff.c:5436
-msgid "do not show any source or destination prefix"
-msgstr "без префикс за източника и целта"
-
-#: diff.c:5439
-msgid "show context between diff hunks up to the specified number of lines"
-msgstr ""
-"извеждане на контекст между последователните парчета с разлики от указания "
-"БРОЙ редове"
-
-#: diff.c:5443 diff.c:5448 diff.c:5453
-msgid "<char>"
-msgstr "ЗНАК"
-
-#: diff.c:5444
-msgid "specify the character to indicate a new line instead of '+'"
-msgstr "знак вместо „+“ за нов вариант на ред"
-
-#: diff.c:5449
-msgid "specify the character to indicate an old line instead of '-'"
-msgstr "знак вместо „-“ за стар вариант на ред"
-
-#: diff.c:5454
-msgid "specify the character to indicate a context instead of ' '"
-msgstr "знак вместо „ “ за контекст"
-
-#: diff.c:5457
-msgid "Diff rename options"
-msgstr "Настройки за разлики с преименуване"
-
-#: diff.c:5458
-msgid "<n>[/<m>]"
-msgstr "МИНИМАЛЕН_%_ПРОМЯНА_ЗА_ИЗТОЧНИК[/МАКСИМАЛEН_%_ПРОМЯНА_ЗА_ЗАМЯНА]"
-
-#: diff.c:5459
-msgid "break complete rewrite changes into pairs of delete and create"
-msgstr ""
-"заместване на пълните промени с последователност от изтриване и създаване"
-
-#: diff.c:5463
-msgid "detect renames"
-msgstr "засичане на преименуванията"
-
-#: diff.c:5467
-msgid "omit the preimage for deletes"
-msgstr "без предварителен вариант при изтриване"
-
-#: diff.c:5470
-msgid "detect copies"
-msgstr "засичане на копиранията"
-
-#: diff.c:5474
-msgid "use unmodified files as source to find copies"
-msgstr "търсене на копирано и от непроменените файлове"
-
-#: diff.c:5476
-msgid "disable rename detection"
-msgstr "без търсене на преименувания"
-
-#: diff.c:5479
-msgid "use empty blobs as rename source"
-msgstr "празни обекти като източник при преименувания"
-
-#: diff.c:5481
-msgid "continue listing the history of a file beyond renames"
-msgstr ""
-"продължаване на извеждането на историята — без отрязването при преименувания "
-"на файл"
-
-#: diff.c:5484
-msgid ""
-"prevent rename/copy detection if the number of rename/copy targets exceeds "
-"given limit"
-msgstr ""
-"без засичане на преименувания/копирания, ако броят им надвишава тази стойност"
-
-#: diff.c:5486
-msgid "Diff algorithm options"
-msgstr "Опции към алгоритъма за разлики"
-
-#: diff.c:5488
-msgid "produce the smallest possible diff"
-msgstr "търсене на възможно най-малка разлика"
-
-#: diff.c:5491
-msgid "ignore whitespace when comparing lines"
-msgstr "без промени в празните знаци при сравняване на редове"
-
-#: diff.c:5494
-msgid "ignore changes in amount of whitespace"
-msgstr "без промени в празните знаци"
-
-#: diff.c:5497
-msgid "ignore changes in whitespace at EOL"
-msgstr "без промени в празните знаци в края на редовете"
-
-#: diff.c:5500
-msgid "ignore carrier-return at the end of line"
-msgstr "без промени в знаците за край на ред"
-
-#: diff.c:5503
-msgid "ignore changes whose lines are all blank"
-msgstr "без промени в редовете, които са изцяло от празни знаци"
-
-#: diff.c:5505 diff.c:5527 diff.c:5530 diff.c:5575
-msgid "<regex>"
-msgstr "РЕГУЛЯРЕН_ИЗРАЗ"
-
-#: diff.c:5506
-msgid "ignore changes whose all lines match <regex>"
-msgstr "без промени в редовете, които напасват РЕГУЛЯРНия_ИЗРАЗ"
-
-#: diff.c:5509
-msgid "heuristic to shift diff hunk boundaries for easy reading"
-msgstr ""
-"евристика за преместване на границите на парчетата за улесняване на четенето"
-
-#: diff.c:5512
-msgid "generate diff using the \"patience diff\" algorithm"
-msgstr "разлика чрез алгоритъм за подредба като пасианс"
-
-#: diff.c:5516
-msgid "generate diff using the \"histogram diff\" algorithm"
-msgstr "разлика по хистограмния алгоритъм"
-
-#: diff.c:5518
-msgid "<algorithm>"
-msgstr "АЛГОРИТЪМ"
-
-#: diff.c:5519
-msgid "choose a diff algorithm"
-msgstr "избор на АЛГОРИТЪМа за разлики"
-
-#: diff.c:5521
-msgid "<text>"
-msgstr "ТЕКСТ"
-
-#: diff.c:5522
-msgid "generate diff using the \"anchored diff\" algorithm"
-msgstr "разлика чрез алгоритъма със закотвяне"
-
-#: diff.c:5524 diff.c:5533 diff.c:5536
-msgid "<mode>"
-msgstr "РЕЖИМ"
-
-#: diff.c:5525
-msgid "show word diff, using <mode> to delimit changed words"
-msgstr ""
-"разлика по думи, като се ползва този РЕЖИМ за отделянето на променените думи"
-
-#: diff.c:5528
-msgid "use <regex> to decide what a word is"
-msgstr "РЕГУЛЯРЕН_ИЗРАЗ за разделяне по думи"
-
-#: diff.c:5531
-msgid "equivalent to --word-diff=color --word-diff-regex=<regex>"
-msgstr "псевдоним на „--word-diff=color --word-diff-regex=РЕГУЛЯРЕН_ИЗРАЗ“"
-
-#: diff.c:5534
-msgid "moved lines of code are colored differently"
-msgstr "различен цвят за извеждане на преместените редове"
-
-#: diff.c:5537
-msgid "how white spaces are ignored in --color-moved"
-msgstr ""
-"режим за прескачането на празните знаци при задаването на „--color-moved“"
-
-#: diff.c:5540
-msgid "Other diff options"
-msgstr "Други опции за разлики"
-
-#: diff.c:5542
-msgid "when run from subdir, exclude changes outside and show relative paths"
-msgstr ""
-"при изпълнение от поддиректория да се пренебрегват разликите извън нея и да "
-"се ползват относителни пътища"
-
-#: diff.c:5546
-msgid "treat all files as text"
-msgstr "обработка на всички файлове като текстови"
-
-#: diff.c:5548
-msgid "swap two inputs, reverse the diff"
-msgstr "размяна на двата входа — обръщане на разликата"
-
-#: diff.c:5550
-msgid "exit with 1 if there were differences, 0 otherwise"
-msgstr ""
-"завършване с код за състояние 1 при наличието на разлики, а в противен "
-"случай — с 0"
-
-#: diff.c:5552
-msgid "disable all output of the program"
-msgstr "без всякакъв изход от програмата"
-
-#: diff.c:5554
-msgid "allow an external diff helper to be executed"
-msgstr "позволяване на изпълнение на външна помощна програма за разлики"
-
-#: diff.c:5556
-msgid "run external text conversion filters when comparing binary files"
-msgstr ""
-"изпълнение на външни програми-филтри при сравнението на двоични файлове"
-
-#: diff.c:5558
-msgid "<when>"
-msgstr "КОГА"
-
-#: diff.c:5559
-msgid "ignore changes to submodules in the diff generation"
-msgstr "игнориране на промените в подмодулите при извеждането на разликите"
-
-#: diff.c:5562
-msgid "<format>"
-msgstr "ФОРМАТ"
-
-#: diff.c:5563
-msgid "specify how differences in submodules are shown"
-msgstr "начин за извеждане на промените в подмодулите"
-
-#: diff.c:5567
-msgid "hide 'git add -N' entries from the index"
-msgstr "без включване в индекса на записите, добавени с „git add -N“"
-
-#: diff.c:5570
-msgid "treat 'git add -N' entries as real in the index"
-msgstr "включване в индекса на записите, добавени с „git add -N“"
-
-#: diff.c:5572
-msgid "<string>"
-msgstr "НИЗ"
-
-#: diff.c:5573
-msgid ""
-"look for differences that change the number of occurrences of the specified "
-"string"
-msgstr "търсене на разлики, които променят броя на поява на указаните низове"
-
-#: diff.c:5576
-msgid ""
-"look for differences that change the number of occurrences of the specified "
-"regex"
-msgstr ""
-"търсене на разлики, които променят броя на поява на низовете, които напасват "
-"на регулярния израз"
-
-#: diff.c:5579
-msgid "show all changes in the changeset with -S or -G"
-msgstr "извеждане на всички промени с „-G“/„-S“"
-
-#: diff.c:5582
-msgid "treat <string> in -S as extended POSIX regular expression"
-msgstr "НИЗът към „-S“ да се тълкува като разширен регулярен израз по POSIX"
-
-#: diff.c:5585
-msgid "control the order in which files appear in the output"
-msgstr "управление на подредбата на файловете в изхода"
-
-#: diff.c:5586 diff.c:5589
-msgid "<path>"
-msgstr "ПЪТ"
-
-#: diff.c:5587
-msgid "show the change in the specified path first"
-msgstr "първо извеждане на промяната в указания път"
-
-#: diff.c:5590
-msgid "skip the output to the specified path"
-msgstr "прескачане на изхода към указания път"
-
-#: diff.c:5592
-msgid "<object-id>"
-msgstr "ИДЕНТИФИКАТОР_НА_ОБЕКТ"
-
-#: diff.c:5593
-msgid ""
-"look for differences that change the number of occurrences of the specified "
-"object"
-msgstr "търсене на разлики, които променят броя на поява на указания обект"
-
-#: diff.c:5595
-msgid "[(A|C|D|M|R|T|U|X|B)...[*]]"
-msgstr "[(A|C|D|M|R|T|U|X|B)…[*]]"
-
-#: diff.c:5596
-msgid "select files by diff type"
-msgstr "избор на файловете по вид разлика"
-
-#: diff.c:5598
-msgid "<file>"
-msgstr "ФАЙЛ"
-
-#: diff.c:5599
-msgid "Output to a specific file"
-msgstr "Изход към указания файл"
-
-#: diff.c:6257
-msgid "exhaustive rename detection was skipped due to too many files."
-msgstr ""
-"пълното търсене на преименувания на обекти се прескача поради многото "
-"файлове."
-
-#: diff.c:6260
-msgid "only found copies from modified paths due to too many files."
-msgstr ""
-"установени са само точните копия на променените пътища поради многото "
-"файлове."
-
-#: diff.c:6263
-#, c-format
-msgid ""
-"you may want to set your %s variable to at least %d and retry the command."
-msgstr "задайте променливата „%s“ да е поне %d и отново изпълнете командата."
-
-#: diffcore-order.c:24
-#, c-format
-msgid "failed to read orderfile '%s'"
-msgstr "файлът с подредбата на съответствията „%s“ не може да бъде прочетен"
-
-#: diffcore-rename.c:1564
-msgid "Performing inexact rename detection"
-msgstr "Търсене на преименувания на обекти съчетани с промени"
-
-#: diffcore-rotate.c:29
-#, c-format
-msgid "No such path '%s' in the diff"
-msgstr "Няма път на име „%s“ в разликата"
-
-#: dir.c:593
-#, c-format
-msgid "pathspec '%s' did not match any file(s) known to git"
-msgstr "пътят „%s“ не съвпада с никой файл в git"
-
-#: dir.c:733 dir.c:762 dir.c:775
-#, c-format
-msgid "unrecognized pattern: '%s'"
-msgstr "непознат шаблон: „%s“"
-
-#: dir.c:790 dir.c:804
-#, c-format
-msgid "unrecognized negative pattern: '%s'"
-msgstr "непознат отрицателен шаблон: „%s“"
-
-#: dir.c:820
-#, c-format
-msgid "your sparse-checkout file may have issues: pattern '%s' is repeated"
-msgstr ""
-"файлът определящ частичността на изтегленото хранилище може да има проблем: "
-"шаблонът „%s“ се повтаря"
-
-#: dir.c:828
-msgid "disabling cone pattern matching"
-msgstr "изключване на пътеводното напасване"
-
-#: dir.c:1212
-#, c-format
-msgid "cannot use %s as an exclude file"
-msgstr "„%s“ не може да се ползва за игнорираните файлове (като gitignore)"
-
-#: dir.c:2418
-#, c-format
-msgid "could not open directory '%s'"
-msgstr "директорията „%s“ не може да бъде отворена"
-
-#: dir.c:2720
-msgid "failed to get kernel name and information"
-msgstr "името и версията на ядрото не бяха получени"
-
-#: dir.c:2844
-msgid "untracked cache is disabled on this system or location"
-msgstr ""
-"кешът за неследените файлове е изключен на тази система или местоположение"
-
-#: dir.c:3112
-msgid ""
-"No directory name could be guessed.\n"
-"Please specify a directory on the command line"
-msgstr ""
-"Името на директорията не може да бъде отгатнато.\n"
-"Задайте директорията изрично на командния ред"
-
-#: dir.c:3800
-#, c-format
-msgid "index file corrupt in repo %s"
-msgstr "файлът с индекса е повреден в хранилището „%s“"
-
-#: dir.c:3847 dir.c:3852
-#, c-format
-msgid "could not create directories for %s"
-msgstr "директориите за „%s“ не може да бъдат създадени"
-
-#: dir.c:3881
-#, c-format
-msgid "could not migrate git directory from '%s' to '%s'"
-msgstr "директорията на git не може да се мигрира от „%s“ до „%s“"
-
-#: editor.c:74
-#, c-format
-msgid "hint: Waiting for your editor to close the file...%c"
-msgstr "Подсказка: чака се редакторът ви да затвори файла …%c"
-
-#: entry.c:179
-msgid "Filtering content"
-msgstr "Филтриране на съдържанието"
-
-#: entry.c:500
-#, c-format
-msgid "could not stat file '%s'"
-msgstr "неуспешно изпълнение на „stat“ върху файла „%s“"
-
-#: environment.c:145
-#, c-format
-msgid "bad git namespace path \"%s\""
-msgstr "неправилен път към пространства от имена „%s“"
-
-#: exec-cmd.c:363
-#, c-format
-msgid "too many args to run %s"
-msgstr "прекалено много аргументи за изпълнение „%s“"
-
-#: fetch-pack.c:194
-msgid "git fetch-pack: expected shallow list"
-msgstr "git fetch-pack: очаква се плитък списък"
-
-#: fetch-pack.c:197
-msgid "git fetch-pack: expected a flush packet after shallow list"
-msgstr "git fetch-pack: след плитък списък се очаква изчистващ пакет „flush“"
-
-#: fetch-pack.c:208
-msgid "git fetch-pack: expected ACK/NAK, got a flush packet"
-msgstr ""
-"git fetch-pack: очаква се „ACK“/„NAK“, а бе получен изчистващ пакет „flush“"
-
-#: fetch-pack.c:228
-#, c-format
-msgid "git fetch-pack: expected ACK/NAK, got '%s'"
-msgstr "git fetch-pack: очаква се „ACK“/„NAK“, а бе получено „%s“"
-
-#: fetch-pack.c:239
-msgid "unable to write to remote"
-msgstr "невъзможно писане към отдалечено хранилище"
-
-#: fetch-pack.c:395 fetch-pack.c:1439
-#, c-format
-msgid "invalid shallow line: %s"
-msgstr "неправилен плитък ред: „%s“"
-
-#: fetch-pack.c:401 fetch-pack.c:1445
-#, c-format
-msgid "invalid unshallow line: %s"
-msgstr "неправилен неплитък ред: „%s“"
-
-#: fetch-pack.c:403 fetch-pack.c:1447
-#, c-format
-msgid "object not found: %s"
-msgstr "обектът „%s“ липсва"
-
-#: fetch-pack.c:406 fetch-pack.c:1450
-#, c-format
-msgid "error in object: %s"
-msgstr "грешка в обекта: „%s“"
-
-#: fetch-pack.c:408 fetch-pack.c:1452
-#, c-format
-msgid "no shallow found: %s"
-msgstr "не е открит плитък обект: %s"
-
-#: fetch-pack.c:411 fetch-pack.c:1456
-#, c-format
-msgid "expected shallow/unshallow, got %s"
-msgstr "очаква се плитък или не обект, а бе получено: „%s“"
-
-#: fetch-pack.c:451
-#, c-format
-msgid "got %s %d %s"
-msgstr "получено бе %s %d %s"
-
-#: fetch-pack.c:468
-#, c-format
-msgid "invalid commit %s"
-msgstr "неправилно подаване: „%s“"
-
-#: fetch-pack.c:499
-msgid "giving up"
-msgstr "преустановяване"
-
-#: fetch-pack.c:512 progress.c:339
-msgid "done"
-msgstr "действието завърши"
-
-#: fetch-pack.c:524
-#, c-format
-msgid "got %s (%d) %s"
-msgstr "получено бе %s (%d) %s"
-
-#: fetch-pack.c:560
-#, c-format
-msgid "Marking %s as complete"
-msgstr "Отбелязване на „%s“ като пълно"
-
-#: fetch-pack.c:775
-#, c-format
-msgid "already have %s (%s)"
-msgstr "вече има „%s“ (%s)"
-
-#: fetch-pack.c:861
-msgid "fetch-pack: unable to fork off sideband demultiplexer"
-msgstr "fetch-pack: не може да се създаде процес за демултиплексора"
-
-#: fetch-pack.c:869
-msgid "protocol error: bad pack header"
-msgstr "протоколна грешка: неправилна заглавна част на пакет"
-
-#: fetch-pack.c:965
-#, c-format
-msgid "fetch-pack: unable to fork off %s"
-msgstr "fetch-pack: не може да се създаде процес за „%s“"
-
-#: fetch-pack.c:971
-msgid "fetch-pack: invalid index-pack output"
-msgstr "fetch-pack: неправилен изход от командата „index-pack“"
-
-#: fetch-pack.c:988
-#, c-format
-msgid "%s failed"
-msgstr "неуспешно изпълнение на „%s“"
-
-#: fetch-pack.c:990
-msgid "error in sideband demultiplexer"
-msgstr "грешка в демултиплексора"
-
-#: fetch-pack.c:1035
-#, c-format
-msgid "Server version is %.*s"
-msgstr "Версията на сървъра е: %.*s"
-
-#: fetch-pack.c:1043 fetch-pack.c:1049 fetch-pack.c:1052 fetch-pack.c:1058
-#: fetch-pack.c:1062 fetch-pack.c:1066 fetch-pack.c:1070 fetch-pack.c:1074
-#: fetch-pack.c:1078 fetch-pack.c:1082 fetch-pack.c:1086 fetch-pack.c:1090
-#: fetch-pack.c:1096 fetch-pack.c:1102 fetch-pack.c:1107 fetch-pack.c:1112
-#, c-format
-msgid "Server supports %s"
-msgstr "Сървърът поддържа „%s“"
-
-#: fetch-pack.c:1045
-msgid "Server does not support shallow clients"
-msgstr "Сървърът не поддържа плитки клиенти"
-
-#: fetch-pack.c:1105
-msgid "Server does not support --shallow-since"
-msgstr "Сървърът не поддържа опцията „--shallow-since“"
-
-#: fetch-pack.c:1110
-msgid "Server does not support --shallow-exclude"
-msgstr "Сървърът не поддържа опцията „--shallow-exclude“"
-
-#: fetch-pack.c:1114
-msgid "Server does not support --deepen"
-msgstr "Сървърът не поддържа опцията „--deepen“"
-
-#: fetch-pack.c:1116
-msgid "Server does not support this repository's object format"
-msgstr "Сървърът не поддържа форма̀та на обектите на това хранилище"
-
-#: fetch-pack.c:1129
-msgid "no common commits"
-msgstr "няма общи подавания"
-
-#: fetch-pack.c:1138 fetch-pack.c:1485 builtin/clone.c:1130
-msgid "source repository is shallow, reject to clone."
-msgstr "клонираното хранилище е плитко, затова няма да се клонира."
-
-#: fetch-pack.c:1144 fetch-pack.c:1681
-msgid "git fetch-pack: fetch failed."
-msgstr "git fetch-pack: неуспешно доставяне."
-
-#: fetch-pack.c:1258
-#, c-format
-msgid "mismatched algorithms: client %s; server %s"
-msgstr "различни алгоритми — на клиента: „%s“, на сървъра: „%s“"
-
-#: fetch-pack.c:1262
-#, c-format
-msgid "the server does not support algorithm '%s'"
-msgstr "сървърът не поддържа алгоритъм „%s“"
-
-#: fetch-pack.c:1295
-msgid "Server does not support shallow requests"
-msgstr "Сървърът не поддържа плитки заявки"
-
-#: fetch-pack.c:1302
-msgid "Server supports filter"
-msgstr "Сървърът поддържа филтри"
-
-#: fetch-pack.c:1345 fetch-pack.c:2063
-msgid "unable to write request to remote"
-msgstr "невъзможно писане към отдалечено хранилище"
-
-#: fetch-pack.c:1363
-#, c-format
-msgid "error reading section header '%s'"
-msgstr "грешка при прочитане на заглавната част на раздел „%s“"
-
-#: fetch-pack.c:1369
-#, c-format
-msgid "expected '%s', received '%s'"
-msgstr "очаква се „%s“, а бе получено „%s“"
-
-#: fetch-pack.c:1403
-#, c-format
-msgid "unexpected acknowledgment line: '%s'"
-msgstr "неочакван ред за потвърждение: „%s“"
-
-#: fetch-pack.c:1408
-#, c-format
-msgid "error processing acks: %d"
-msgstr "грешка при обработка на потвържденията: %d"
-
-#: fetch-pack.c:1418
-msgid "expected packfile to be sent after 'ready'"
-msgstr ""
-"очакваше се пакетният файл да бъде изпратен след отговор за готовност (ready)"
-
-#: fetch-pack.c:1420
-msgid "expected no other sections to be sent after no 'ready'"
-msgstr ""
-"очакваше се след липса на отговор за готовност (ready) да не се се пращат "
-"други раздели"
-
-#: fetch-pack.c:1461
-#, c-format
-msgid "error processing shallow info: %d"
-msgstr "грешка при обработка на информация за дълбочината/плиткостта: %d"
-
-#: fetch-pack.c:1510
-#, c-format
-msgid "expected wanted-ref, got '%s'"
-msgstr "очаква се искан указател, а бе получено: „%s“"
-
-#: fetch-pack.c:1515
-#, c-format
-msgid "unexpected wanted-ref: '%s'"
-msgstr "неочакван искан указател: „%s“"
-
-#: fetch-pack.c:1520
-#, c-format
-msgid "error processing wanted refs: %d"
-msgstr "грешка при обработката на исканите указатели: %d"
-
-#: fetch-pack.c:1550
-msgid "git fetch-pack: expected response end packet"
-msgstr "git fetch-pack: очаква се пакет за край на отговора"
-
-#: fetch-pack.c:1959
-msgid "no matching remote head"
-msgstr "не може да бъде открит подходящ връх от отдалеченото хранилище"
-
-#: fetch-pack.c:1982 builtin/clone.c:581
-msgid "remote did not send all necessary objects"
-msgstr "отдалеченото хранилище не изпрати всички необходими обекти."
-
-#: fetch-pack.c:2085
-msgid "unexpected 'ready' from remote"
-msgstr "неочаквано състояние за готовност от отдалечено хранилище"
-
-#: fetch-pack.c:2108
-#, c-format
-msgid "no such remote ref %s"
-msgstr "такъв отдалечен указател няма: %s"
-
-#: fetch-pack.c:2111
-#, c-format
-msgid "Server does not allow request for unadvertised object %s"
-msgstr "Сървърът не позволява заявка за необявен обект „%s“"
-
-#: gpg-interface.c:329 gpg-interface.c:457 gpg-interface.c:974
-#: gpg-interface.c:990
-msgid "could not create temporary file"
-msgstr "не може да се създаде временен файл"
-
-#: gpg-interface.c:332 gpg-interface.c:460
-#, c-format
-msgid "failed writing detached signature to '%s'"
-msgstr "Програмата не успя да запише самостоятелния подпис в „%s“"
-
-#: gpg-interface.c:451
-msgid ""
-"gpg.ssh.allowedSignersFile needs to be configured and exist for ssh "
-"signature verification"
-msgstr ""
-"настройката „gpg.ssh.allowedSignersFile“ трябва да е зададена за проверка на "
-"подписите на ssh"
-
-#: gpg-interface.c:480
-msgid ""
-"ssh-keygen -Y find-principals/verify is needed for ssh signature "
-"verification (available in openssh version 8.2p1+)"
-msgstr ""
-"За проверка на подписите е необходима командата (достъпна от openssh ≥ "
-"8.2p1+):\n"
-"\n"
-" ssh-keygen -Y find-principals/verify"
-
-#: gpg-interface.c:536
-#, c-format
-msgid "ssh signing revocation file configured but not found: %s"
-msgstr ""
-"файлът за отхвърляне на подписи на ssh е настроен, но не може да се открие: "
-"%s"
-
-#: gpg-interface.c:624
-#, c-format
-msgid "bad/incompatible signature '%s'"
-msgstr "лош/несъвместим подпис „%s“"
-
-#: gpg-interface.c:801 gpg-interface.c:806
-#, c-format
-msgid "failed to get the ssh fingerprint for key '%s'"
-msgstr "отпечатъкът по ssh на ключа „%s“ не може да бъде получен"
-
-#: gpg-interface.c:829
-msgid ""
-"either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"
-msgstr ""
-"Поне една от настройките „user.signingkey“ или „gpg.ssh.defaultKeyCommand“ "
-"трябва да е зададена"
-
-#: gpg-interface.c:851
-#, c-format
-msgid "gpg.ssh.defaultKeyCommand succeeded but returned no keys: %s %s"
-msgstr ""
-"командата „gpg.ssh.defaultKeyCommand“ завърши успешно, но не върна никакви "
-"ключове: %s %s"
-
-#: gpg-interface.c:857
-#, c-format
-msgid "gpg.ssh.defaultKeyCommand failed: %s %s"
-msgstr "неуспешно изпълнение на „gpg.ssh.defaultKeyCommand“: %s %s"
-
-#: gpg-interface.c:945
-msgid "gpg failed to sign the data"
-msgstr "Програмата „gpg“ не подписа данните"
-
-#: gpg-interface.c:967
-msgid "user.signingkey needs to be set for ssh signing"
-msgstr ""
-"за подписване със ssh е необходимо да зададете настройката „user.signingkey“"
-
-#: gpg-interface.c:978
-#, c-format
-msgid "failed writing ssh signing key to '%s'"
-msgstr "неуспешно запазване на ключа за подписване на ssh в „%s“"
-
-#: gpg-interface.c:996
-#, c-format
-msgid "failed writing ssh signing key buffer to '%s'"
-msgstr "неуспешно запазване на буфера за подписване на ssh в „%s“"
-
-#: gpg-interface.c:1014
-msgid ""
-"ssh-keygen -Y sign is needed for ssh signing (available in openssh version "
-"8.2p1+)"
-msgstr ""
-"За подписване със ssh е необходима командата (достъпна от openssh ≥ "
-"8.2p1+):\n"
-"\n"
-" ssh-keygen -Y"
-
-#: gpg-interface.c:1026
-#, c-format
-msgid "failed reading ssh signing data buffer from '%s'"
-msgstr "неуспешно прочитане на буфера за подписване на ssh от „%s“"
-
-#: graph.c:98
-#, c-format
-msgid "ignored invalid color '%.*s' in log.graphColors"
-msgstr "прескачане на неправилния цвят „%.*s“ в „log.graphColors“"
-
-#: grep.c:531
-msgid ""
-"given pattern contains NULL byte (via -f <file>). This is only supported "
-"with -P under PCRE v2"
-msgstr ""
-"зададеният шаблон съдържа нулев знак (идва от -f „ФАЙЛ“). Това се поддържа "
-"в комбинация с „-P“ само при ползването на „PCRE v2“"
-
-#: grep.c:1942
-#, c-format
-msgid "'%s': unable to read %s"
-msgstr "„%s“: файлът сочен от „%s“ не може да бъде прочетен"
-
-#: grep.c:1959 setup.c:177 builtin/clone.c:302 builtin/diff.c:90
-#: builtin/rm.c:136
-#, c-format
-msgid "failed to stat '%s'"
-msgstr "не може да бъде получена информация чрез „stat“ за „%s“"
-
-#: grep.c:1970
-#, c-format
-msgid "'%s': short read"
-msgstr "„%s“: изчитането върна по-малко байтове от очакваното"
-
-#: help.c:24
-msgid "start a working area (see also: git help tutorial)"
-msgstr "създаване на работно дърво (погледнете: „git help tutorial“)"
-
-#: help.c:25
-msgid "work on the current change (see also: git help everyday)"
-msgstr "работа по текущата промяна (погледнете: „git help everyday“)"
-
-#: help.c:26
-msgid "examine the history and state (see also: git help revisions)"
-msgstr "преглед на историята и състоянието (погледнете: „git help revisions“)"
-
-#: help.c:27
-msgid "grow, mark and tweak your common history"
-msgstr "увеличаване, отбелязване и промяна на общата история"
-
-#: help.c:28
-msgid "collaborate (see also: git help workflows)"
-msgstr "съвместна работа (погледнете: „git help workflows“)"
-
-#: help.c:32
-msgid "Main Porcelain Commands"
-msgstr "Основни команди от потребителско ниво"
-
-#: help.c:33
-msgid "Ancillary Commands / Manipulators"
-msgstr "Помощни команди / Променящи"
-
-#: help.c:34
-msgid "Ancillary Commands / Interrogators"
-msgstr "Помощни команди / Запитващи"
-
-#: help.c:35
-msgid "Interacting with Others"
-msgstr "Съвместна работа с други хора"
-
-#: help.c:36
-msgid "Low-level Commands / Manipulators"
-msgstr "Команди от ниско ниво / Променящи"
-
-#: help.c:37
-msgid "Low-level Commands / Interrogators"
-msgstr "Команди от ниско ниво / Запитващи"
-
-#: help.c:38
-msgid "Low-level Commands / Syncing Repositories"
-msgstr "Команди от ниско ниво / Синхронизация на хранилища"
-
-#: help.c:39
-msgid "Low-level Commands / Internal Helpers"
-msgstr "Команди от ниско ниво / Допълнителни инструменти"
-
-#: help.c:313
-#, c-format
-msgid "available git commands in '%s'"
-msgstr "налични команди на git от „%s“"
-
-#: help.c:320
-msgid "git commands available from elsewhere on your $PATH"
-msgstr "команди на git от други директории от „$PATH“"
-
-#: help.c:329
-msgid "These are common Git commands used in various situations:"
-msgstr "Това са най-често използваните команди на Git:"
-
-#: help.c:378 git.c:100
-#, c-format
-msgid "unsupported command listing type '%s'"
-msgstr "неподдържан списък от команди „%s“"
-
-#: help.c:418
-msgid "The Git concept guides are:"
-msgstr "Ръководствата за концепциите в Git са:"
-
-#: help.c:442
-msgid "See 'git help <command>' to read about a specific subcommand"
-msgstr "За повече информация за КОМАНДА изпълнете „git help КОМАНДА“"
-
-#: help.c:447
-msgid "External commands"
-msgstr "Външни команди"
-
-#: help.c:462
-msgid "Command aliases"
-msgstr "Псевдоними на командите"
-
-#: help.c:543
-#, c-format
-msgid ""
-"'%s' appears to be a git command, but we were not\n"
-"able to execute it. Maybe git-%s is broken?"
-msgstr ""
-"Изглежда, че „%s“ е команда на git, но тя не може да\n"
-"бъде изпълнена. Вероятно пакетът „git-%s“ е повреден."
-
-#: help.c:565 help.c:662
-#, c-format
-msgid "git: '%s' is not a git command. See 'git --help'."
-msgstr "git: „%s“ не е команда на git. Погледнете изхода от „git --help“."
-
-#: help.c:613
-msgid "Uh oh. Your system reports no Git commands at all."
-msgstr "Странно, изглежда, че на системата ви няма нито една команда на git."
-
-#: help.c:635
-#, c-format
-msgid "WARNING: You called a Git command named '%s', which does not exist."
-msgstr ""
-"ПРЕДУПРЕЖДЕНИЕ: Пробвахте да изпълните команда на Git на име „%s“, а такава "
-"не съществува."
-
-#: help.c:640
-#, c-format
-msgid "Continuing under the assumption that you meant '%s'."
-msgstr ""
-"Изпълнението автоматично продължава, като се счита, че имате предвид „%s“."
-
-#: help.c:646
-#, c-format
-msgid "Run '%s' instead [y/N]? "
-msgstr "Да се изпълни „%s“ вместо това [y/N]? "
-
-#: help.c:654
-#, c-format
-msgid "Continuing in %0.1f seconds, assuming that you meant '%s'."
-msgstr ""
-"Изпълнението автоматично ще продължи след %0.1f сек., като се счита, че "
-"имате предвид „%s“."
-
-#: help.c:666
-msgid ""
-"\n"
-"The most similar command is"
-msgid_plural ""
-"\n"
-"The most similar commands are"
-msgstr[0] ""
-"\n"
-"Най-близката команда е"
-msgstr[1] ""
-"\n"
-"Най-близките команди са"
-
-#: help.c:706
-msgid "git version [<options>]"
-msgstr "git version [ОПЦИЯ…]"
-
-#: help.c:761
-#, c-format
-msgid "%s: %s - %s"
-msgstr "%s: %s — %s"
-
-#: help.c:765
-msgid ""
-"\n"
-"Did you mean this?"
-msgid_plural ""
-"\n"
-"Did you mean one of these?"
-msgstr[0] ""
-"\n"
-"Команда с подобно име е:"
-msgstr[1] ""
-"\n"
-"Команди с подобно име са:"
-
-#: hook.c:27
-#, c-format
-msgid ""
-"The '%s' hook was ignored because it's not set as executable.\n"
-"You can disable this warning with `git config advice.ignoredHook false`."
-msgstr ""
-"Куката „%s“ се прескача, защото липсват права за изпълнение.\n"
-"За да изключите това предупреждение, изпълнете:\n"
-" git config advice.ignoredHook false"
-
-#: ident.c:353
-msgid "Author identity unknown\n"
-msgstr "Липсва информация за автора\n"
-
-#: ident.c:356
-msgid "Committer identity unknown\n"
-msgstr "Липсва информация за подалия\n"
-
-#: ident.c:362
-msgid ""
-"\n"
-"*** Please tell me who you are.\n"
-"\n"
-"Run\n"
-"\n"
-" git config --global user.email \"you@example.com\"\n"
-" git config --global user.name \"Your Name\"\n"
-"\n"
-"to set your account's default identity.\n"
-"Omit --global to set the identity only in this repository.\n"
-"\n"
-msgstr ""
-"\n"
-"●●● Въведете самоличност.\n"
-"\n"
-"Изпълнете:\n"
-"\n"
-" git config --global user.email \"ИМЕ@example.com\"\n"
-" git config --global user.name \"ВАШЕТО ИМЕ\"\n"
-"\n"
-"и въведете данни за себе си.\n"
-"Ако пропуснете опцията „--global“, самоличността е само за текущото "
-"хранилище.\n"
-"\n"
-
-#: ident.c:397
-msgid "no email was given and auto-detection is disabled"
-msgstr "липсва адрес за е-поща, а автоматичното отгатване е изключено"
-
-#: ident.c:402
-#, c-format
-msgid "unable to auto-detect email address (got '%s')"
-msgstr ""
-"адресът за е-поща не може да бъде отгатнат (най-доброто предположение бе "
-"„%s“)"
-
-#: ident.c:419
-msgid "no name was given and auto-detection is disabled"
-msgstr "липсва име, а автоматичното отгатване е изключено"
-
-#: ident.c:425
-#, c-format
-msgid "unable to auto-detect name (got '%s')"
-msgstr "името не може да бъде отгатнато (най-доброто предположение бе „%s“)"
-
-#: ident.c:433
-#, c-format
-msgid "empty ident name (for <%s>) not allowed"
-msgstr "не може да се ползва празно име като идентификатор (за <%s>)"
-
-#: ident.c:439
-#, c-format
-msgid "name consists only of disallowed characters: %s"
-msgstr "името съдържа само непозволени знаци: „%s“"
-
-#: ident.c:454 builtin/commit.c:648
-#, c-format
-msgid "invalid date format: %s"
-msgstr "неправилен формат на дата: %s"
-
-#: list-objects-filter-options.c:83
-msgid "expected 'tree:<depth>'"
-msgstr "очаква се „tree:ДЪЛБОЧИНА“"
-
-#: list-objects-filter-options.c:98
-msgid "sparse:path filters support has been dropped"
-msgstr "поддръжката на филтри със „sparse:path“ е премахната"
-
-#: list-objects-filter-options.c:105
-#, c-format
-msgid "'%s' for 'object:type=<type>' is not a valid object type"
-msgstr "„%s“ не е правилна стойност за вид на обект в „object:type=ВИД“"
-
-#: list-objects-filter-options.c:124
-#, c-format
-msgid "invalid filter-spec '%s'"
-msgstr "неправилен филтър: „%s“"
-
-#: list-objects-filter-options.c:140
-#, c-format
-msgid "must escape char in sub-filter-spec: '%c'"
-msgstr "знак за екраниране в подфилтър: „%c“"
-
-#: list-objects-filter-options.c:182
-msgid "expected something after combine:"
-msgstr "добавете нещо след комбинирането:"
-
-#: list-objects-filter-options.c:264
-msgid "multiple filter-specs cannot be combined"
-msgstr "не може да комбинирате множество филтри"
-
-#: list-objects-filter-options.c:376
-msgid "unable to upgrade repository format to support partial clone"
-msgstr ""
-"не може да се извърши частично клониране, защото форматът на хранилището не "
-"може да се обнови"
-
-#: list-objects-filter.c:532
-#, c-format
-msgid "unable to access sparse blob in '%s'"
-msgstr "няма достъп до частично изтегления обект-BLOB в „%s“"
-
-#: list-objects-filter.c:535
-#, c-format
-msgid "unable to parse sparse filter data in %s"
-msgstr ""
-"данните от филтъра за частични изтегляния в „%s“ не може да бъдат анализирани"
-
-#: list-objects.c:127
-#, c-format
-msgid "entry '%s' in tree %s has tree mode, but is not a tree"
-msgstr "обект „%s“ в дървото „%s“ е отбелязан като дърво, но не е"
-
-#: list-objects.c:140
-#, c-format
-msgid "entry '%s' in tree %s has blob mode, but is not a blob"
-msgstr "обект „%s“ в дървото „%s“ е отбелязан като BLOB, но не е"
-
-#: list-objects.c:398
-#, c-format
-msgid "unable to load root tree for commit %s"
-msgstr "кореновото дърво за подаване „%s“ не може да се зареди"
-
-#: lockfile.c:152
-#, c-format
-msgid ""
-"Unable to create '%s.lock': %s.\n"
-"\n"
-"Another git process seems to be running in this repository, e.g.\n"
-"an editor opened by 'git commit'. Please make sure all processes\n"
-"are terminated then try again. If it still fails, a git process\n"
-"may have crashed in this repository earlier:\n"
-"remove the file manually to continue."
-msgstr ""
-"Файлът-ключалка „%s.lock“ не може да бъде създаден: %s\n"
-"\n"
-"Изглежда, че и друг процес на git е пуснат в това хранилище, напр.\n"
-"редактор, стартиран с „git commit“. Уверете се, че всички подобни\n"
-"процеси са спрени и опитайте отново. Ако това не помогне, вероятната\n"
-"причина е, че някой процес на git в това хранилище е забил. За да\n"
-"продължите работа, ще трябва ръчно да изтриете файла:"
-
-#: lockfile.c:160
-#, c-format
-msgid "Unable to create '%s.lock': %s"
-msgstr "Файлът-ключалка „%s.lock“ не може да бъде създаден: %s"
-
-#: ls-refs.c:37
-#, c-format
-msgid "invalid value '%s' for lsrefs.unborn"
-msgstr "неправилна стойност „%s“ за „lsrefs.unborn“"
-
-#: ls-refs.c:174
-#, c-format
-msgid "unexpected line: '%s'"
-msgstr "неочакван ред: „%s“"
-
-#: ls-refs.c:178
-msgid "expected flush after ls-refs arguments"
-msgstr "след аргументите към „ls-refs“ се очаква изчистване на буферите"
-
-#: mailinfo.c:1050
-msgid "quoted CRLF detected"
-msgstr "цитирани знаци CRLF"
-
-#: mailinfo.c:1254 builtin/am.c:184 builtin/mailinfo.c:46
-#, c-format
-msgid "bad action '%s' for '%s'"
-msgstr "неправилно действие „%s“ за „%s“"
-
-#: merge-ort.c:1584 merge-recursive.c:1211
-#, c-format
-msgid "Failed to merge submodule %s (not checked out)"