aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/check-whitespace.yml67
-rw-r--r--.github/workflows/coverity.yml2
-rw-r--r--.github/workflows/main.yml11
-rw-r--r--.gitlab-ci.yml24
-rw-r--r--Documentation/MyFirstContribution.txt9
-rw-r--r--Documentation/RelNotes/2.39.4.txt79
-rw-r--r--Documentation/RelNotes/2.40.2.txt7
-rw-r--r--Documentation/RelNotes/2.41.1.txt7
-rw-r--r--Documentation/RelNotes/2.42.2.txt7
-rw-r--r--Documentation/RelNotes/2.43.4.txt7
-rw-r--r--Documentation/RelNotes/2.44.1.txt8
-rw-r--r--Documentation/RelNotes/2.45.0.txt2
-rw-r--r--Documentation/RelNotes/2.45.1.txt8
-rw-r--r--Documentation/RelNotes/2.46.0.txt117
-rw-r--r--Documentation/SubmittingPatches208
-rw-r--r--Documentation/config.txt35
-rw-r--r--Documentation/config/bitmap-pseudo-merge.txt75
-rw-r--r--Documentation/config/commitgraph.txt29
-rw-r--r--Documentation/config/reftable.txt48
-rw-r--r--Documentation/fsck-msgids.txt12
-rw-r--r--Documentation/git-config.txt219
-rw-r--r--Documentation/git-credential.txt104
-rw-r--r--Documentation/git-for-each-repo.txt9
-rw-r--r--Documentation/git-format-patch.txt26
-rw-r--r--Documentation/git-gui.txt2
-rw-r--r--Documentation/git-merge-tree.txt5
-rw-r--r--Documentation/git-rev-parse.txt15
-rw-r--r--Documentation/git-tag.txt16
-rw-r--r--Documentation/git-update-index.txt1
-rw-r--r--Documentation/git-upload-pack.txt31
-rw-r--r--Documentation/git.txt49
-rw-r--r--Documentation/gitformat-commit-graph.txt9
-rw-r--r--Documentation/githooks.txt14
-rw-r--r--Documentation/glossary-content.txt75
-rw-r--r--Documentation/technical/bitmap-format.txt205
-rwxr-xr-xGIT-VERSION-GEN2
-rw-r--r--Makefile66
l---------RelNotes2
-rw-r--r--add-interactive.c18
-rw-r--r--add-patch.c19
-rw-r--r--advice.c7
-rw-r--r--apply.c4
-rw-r--r--attr.c55
-rw-r--r--bisect.c25
-rw-r--r--blame.c4
-rw-r--r--bloom.c208
-rw-r--r--bloom.h38
-rw-r--r--branch.c7
-rw-r--r--builtin/add.c57
-rw-r--r--builtin/am.c74
-rw-r--r--builtin/apply.c4
-rw-r--r--builtin/bisect.c44
-rw-r--r--builtin/blame.c9
-rw-r--r--builtin/branch.c51
-rw-r--r--builtin/bundle.c5
-rw-r--r--builtin/cat-file.c4
-rw-r--r--builtin/check-attr.c5
-rw-r--r--builtin/check-ignore.c7
-rw-r--r--builtin/checkout-index.c22
-rw-r--r--builtin/checkout.c122
-rw-r--r--builtin/clean.c7
-rw-r--r--builtin/clone.c94
-rw-r--r--builtin/commit.c101
-rw-r--r--builtin/config.c1166
-rw-r--r--builtin/credential-cache--daemon.c22
-rw-r--r--builtin/credential-cache.c10
-rw-r--r--builtin/credential-store.c2
-rw-r--r--builtin/credential.c15
-rw-r--r--builtin/describe.c6
-rw-r--r--builtin/diff-tree.c3
-rw-r--r--builtin/diff.c15
-rw-r--r--builtin/difftool.c4
-rw-r--r--builtin/fast-import.c18
-rw-r--r--builtin/fetch.c22
-rw-r--r--builtin/for-each-ref.c2
-rw-r--r--builtin/for-each-repo.c13
-rw-r--r--builtin/fsck.c11
-rw-r--r--builtin/fsmonitor--daemon.c4
-rw-r--r--builtin/gc.c10
-rw-r--r--builtin/hash-object.c3
-rw-r--r--builtin/interpret-trailers.c12
-rw-r--r--builtin/log.c36
-rw-r--r--builtin/merge-index.c17
-rw-r--r--builtin/merge-tree.c3
-rw-r--r--builtin/merge.c65
-rw-r--r--builtin/multi-pack-index.c3
-rw-r--r--builtin/mv.c68
-rw-r--r--builtin/name-rev.c5
-rw-r--r--builtin/notes.c26
-rw-r--r--builtin/pack-objects.c13
-rw-r--r--builtin/patch-id.c13
-rw-r--r--builtin/pull.c6
-rw-r--r--builtin/read-tree.c15
-rw-r--r--builtin/rebase.c38
-rw-r--r--builtin/receive-pack.c16
-rw-r--r--builtin/reflog.c25
-rw-r--r--builtin/remote.c37
-rw-r--r--builtin/repack.c7
-rw-r--r--builtin/replace.c11
-rw-r--r--builtin/replay.c1
-rw-r--r--builtin/reset.c45
-rw-r--r--builtin/rev-parse.c36
-rw-r--r--builtin/rm.c40
-rw-r--r--builtin/shortlog.c2
-rw-r--r--builtin/show-branch.c22
-rw-r--r--builtin/show-ref.c19
-rw-r--r--builtin/stash.c72
-rw-r--r--builtin/submodule--helper.c114
-rw-r--r--builtin/symbolic-ref.c13
-rw-r--r--builtin/tag.c50
-rw-r--r--builtin/update-index.c124
-rw-r--r--builtin/update-ref.c22
-rw-r--r--builtin/upload-pack.c2
-rw-r--r--builtin/worktree.c21
-rw-r--r--builtin/write-tree.c6
-rw-r--r--bundle-uri.c12
-rw-r--r--bundle.c2
-rwxr-xr-xci/check-whitespace.sh95
-rwxr-xr-xci/install-dependencies.sh103
-rwxr-xr-xci/install-docker-dependencies.sh46
-rwxr-xr-xci/lib.sh24
-rwxr-xr-xci/run-build-and-minimal-fuzzers.sh2
-rwxr-xr-xci/run-build-and-tests.sh2
-rwxr-xr-xci/run-test-slice.sh2
-rw-r--r--color.c21
-rw-r--r--color.h3
-rw-r--r--commit-graph.c67
-rw-r--r--commit.c3
-rw-r--r--common-main.c2
-rw-r--r--compat/mingw.c2
-rw-r--r--compat/precompose_utf8.c10
-rw-r--r--compat/precompose_utf8.h1
-rw-r--r--compat/regex/regcomp.c12
-rw-r--r--compat/regex/regex_internal.c4
-rw-r--r--compat/regex/regexec.c10
-rw-r--r--config.c53
-rw-r--r--config.h4
-rw-r--r--config.mak.uname1
-rw-r--r--contrib/buildsystems/CMakeLists.txt3
-rw-r--r--contrib/coccinelle/refs.cocci103
-rw-r--r--contrib/completion/git-completion.bash74
-rw-r--r--contrib/completion/git-completion.zsh1
-rw-r--r--copy.c61
-rw-r--r--copy.h14
-rw-r--r--credential.c138
-rw-r--r--credential.h92
-rw-r--r--delta-islands.c7
-rw-r--r--diff-lib.c1
-rw-r--r--diff.c34
-rw-r--r--dir.c12
-rw-r--r--dir.h7
-rw-r--r--entry.c16
-rw-r--r--environment.h8
-rw-r--r--ewah/bitmap.c76
-rw-r--r--ewah/ewok.h8
-rw-r--r--fetch-pack.c11
-rw-r--r--fmt-merge-msg.c4
-rw-r--r--fsck.c56
-rw-r--r--fsck.h12
-rw-r--r--git-compat-util.h1
-rwxr-xr-xgit-p4.py24
-rwxr-xr-xgit-send-email.perl19
-rw-r--r--git.c11
-rw-r--r--help.c5
-rw-r--r--hook.c53
-rw-r--r--http-backend.c13
-rw-r--r--http.c127
-rw-r--r--http.h5
-rw-r--r--imap-send.c2
-rw-r--r--khash.h338
-rw-r--r--khashl.h522
-rw-r--r--list-objects-filter.c2
-rw-r--r--log-tree.c9
-rw-r--r--loose.h2
-rw-r--r--ls-refs.c10
-rw-r--r--mem-pool.c3
-rw-r--r--midx-write.c6
-rw-r--r--negotiator/default.c3
-rw-r--r--negotiator/skipping.c3
-rw-r--r--notes-cache.c6
-rw-r--r--notes-merge.c2
-rw-r--r--notes-utils.c7
-rw-r--r--notes.c5
-rw-r--r--object-store-ll.h2
-rw-r--r--object-store.h7
-rw-r--r--object.h3
-rw-r--r--oidset.h2
-rw-r--r--oss-fuzz/fuzz-commit-graph.c6
-rw-r--r--pack-bitmap-write.c275
-rw-r--r--pack-bitmap.c359
-rw-r--r--pack-bitmap.h18
-rw-r--r--parse-options-cb.c3
-rw-r--r--path.c55
-rw-r--r--path.h1
-rw-r--r--po/TEAMS23
-rw-r--r--po/bg.po731
-rw-r--r--po/de.po670
-rw-r--r--po/fr.po681
-rw-r--r--po/id.po812
-rw-r--r--po/sv.po941
-rw-r--r--po/tr.po661
-rw-r--r--po/uk.po663
-rw-r--r--po/vi.po9749
-rw-r--r--po/zh_CN.po798
-rw-r--r--po/zh_TW.po910
-rw-r--r--promisor-remote.c10
-rw-r--r--pseudo-merge.c740
-rw-r--r--pseudo-merge.h218
-rw-r--r--range-diff.h6
-rw-r--r--reachable.c5
-rw-r--r--read-cache.c72
-rw-r--r--rebase-interactive.c21
-rw-r--r--rebase-interactive.h9
-rw-r--r--ref-filter.c51
-rw-r--r--ref-filter.h4
-rw-r--r--reflog-walk.c27
-rw-r--r--reflog.c20
-rw-r--r--refs.c417
-rw-r--r--refs.h359
-rw-r--r--refs/debug.c13
-rw-r--r--refs/files-backend.c215
-rw-r--r--refs/packed-backend.c1
-rw-r--r--refs/refs-internal.h40
-rw-r--r--refs/reftable-backend.c329
-rw-r--r--reftable/block.c84
-rw-r--r--reftable/block.h6
-rw-r--r--reftable/constants.h1
-rw-r--r--reftable/dump.c12
-rw-r--r--reftable/error.c2
-rw-r--r--reftable/generic.c94
-rw-r--r--reftable/generic.h9
-rw-r--r--reftable/iter.c23
-rw-r--r--reftable/merged.c148
-rw-r--r--reftable/merged.h6
-rw-r--r--reftable/merged_test.c19
-rw-r--r--reftable/reader.c283
-rw-r--r--reftable/readwrite_test.c35
-rw-r--r--reftable/refname.c206
-rw-r--r--reftable/refname.h29
-rw-r--r--reftable/refname_test.c101
-rw-r--r--reftable/reftable-error.h3
-rw-r--r--reftable/reftable-generic.h8
-rw-r--r--reftable/reftable-iterator.h21
-rw-r--r--reftable/reftable-merged.h15
-rw-r--r--reftable/reftable-reader.h47
-rw-r--r--reftable/reftable-stack.h20
-rw-r--r--reftable/reftable-tests.h1
-rw-r--r--reftable/reftable-writer.h14
-rw-r--r--reftable/stack.c153
-rw-r--r--reftable/stack.h5
-rw-r--r--reftable/stack_test.c157
-rw-r--r--reftable/writer.c160
-rw-r--r--remote-curl.c33
-rw-r--r--remote.c38
-rw-r--r--repo-settings.c6
-rw-r--r--repository.c68
-rw-r--r--repository.h7
-rw-r--r--rerere.c46
-rw-r--r--reset.c29
-rw-r--r--revision.c53
-rw-r--r--scalar.c10
-rw-r--r--sequencer.c404
-rw-r--r--sequencer.h15
-rw-r--r--server-info.c3
-rw-r--r--setup.c148
-rw-r--r--setup.h14
-rw-r--r--shallow.c16
-rw-r--r--strbuf.c5
-rw-r--r--submodule.c95
-rw-r--r--submodule.h5
-rw-r--r--t/Makefile14
-rw-r--r--t/helper/test-bitmap.c34
-rw-r--r--t/helper/test-bloom.c9
-rw-r--r--t/helper/test-cache-tree.c17
-rw-r--r--t/helper/test-dump-cache-tree.c5
-rw-r--r--t/helper/test-dump-split-index.c11
-rw-r--r--t/helper/test-dump-untracked-cache.c3
-rw-r--r--t/helper/test-example-tap.c (renamed from t/unit-tests/t-basic.c)5
-rw-r--r--t/helper/test-lazy-init-name-hash.c39
-rw-r--r--t/helper/test-path-utils.c11
-rw-r--r--t/helper/test-read-cache.c11
-rw-r--r--t/helper/test-read-graph.c65
-rw-r--r--t/helper/test-ref-store.c2
-rw-r--r--t/helper/test-reftable.c1
-rw-r--r--t/helper/test-run-command.c28
-rw-r--r--t/helper/test-scrap-cache-tree.c7
-rw-r--r--t/helper/test-tool.c2
-rw-r--r--t/helper/test-tool.h2
-rw-r--r--t/helper/test-write-cache.c3
-rw-r--r--t/helper/test-xgethostname.c12
-rw-r--r--t/lib-chunk.sh3
-rw-r--r--t/lib-credential.sh123
-rw-r--r--t/lib-httpd/nph-custom-auth.sh17
-rwxr-xr-xt/perf/p5333-pseudo-merge-bitmaps.sh32
-rwxr-xr-xt/run-test.sh18
-rwxr-xr-xt/t0000-basic.sh28
-rwxr-xr-xt/t0003-attributes.sh35
-rwxr-xr-xt/t0018-advice.sh71
-rwxr-xr-xt/t0033-safe-directory.sh24
-rwxr-xr-xt/t0040-parse-options.sh17
-rwxr-xr-xt/t0050-filesystem.sh11
-rwxr-xr-xt/t0060-path-utils.sh41
-rwxr-xr-xt/t0068-for-each-repo.sh16
-rwxr-xr-xt/t0080-unit-test-output.sh24
-rwxr-xr-xt/t0095-bloom.sh8
-rwxr-xr-xt/t0300-credentials.sh165
-rwxr-xr-xt/t0301-credential-cache.sh1
-rwxr-xr-xt/t0411-clone-from-partial.sh78
-rw-r--r--t/t0450/txt-help-mismatches1
-rwxr-xr-xt/t0600-reffiles-backend.sh8
-rwxr-xr-xt/t0601-reffiles-pack-refs.sh9
-rwxr-xr-xt/t0610-reftable-basics.sh48
-rwxr-xr-xt/t0612-reftable-jgit-compatibility.sh132
-rwxr-xr-xt/t0613-reftable-write-options.sh286
-rwxr-xr-xt/t1007-hash-object.sh6
-rwxr-xr-xt/t1300-config.sh441
-rwxr-xr-xt/t1305-config-include.sh42
-rwxr-xr-xt/t1416-ref-transaction-hooks.sh23
-rwxr-xr-xt/t1450-fsck.sh37
-rwxr-xr-xt/t1500-rev-parse.sh6
-rwxr-xr-xt/t1517-outside-repo.sh61
-rwxr-xr-xt/t1800-hook.sh15
-rwxr-xr-xt/t2016-checkout-patch.sh1
-rwxr-xr-xt/t3404-rebase-interactive.sh33
-rwxr-xr-xt/t3428-rebase-signoff.sh90
-rwxr-xr-xt/t3434-rebase-i18n.sh2
-rwxr-xr-xt/t3701-add-interactive.sh29
-rwxr-xr-xt/t3903-stash.sh9
-rwxr-xr-xt/t4014-format-patch.sh49
-rwxr-xr-xt/t4020-diff-external.sh8
-rwxr-xr-xt/t4026-color.sh26
-rwxr-xr-xt/t4046-diff-unmerged.sh8
-rwxr-xr-xt/t4103-apply-binary.sh1
-rwxr-xr-xt/t4104-apply-boundary.sh1
-rwxr-xr-xt/t4113-apply-ending.sh1
-rwxr-xr-xt/t4117-apply-reject.sh1
-rwxr-xr-xt/t4123-apply-shrink.sh1
-rwxr-xr-xt/t4204-patch-id.sh34
-rwxr-xr-xt/t4216-log-bloom.sh310
-rwxr-xr-xt/t4252-am-options.sh2
-rwxr-xr-xt/t4258-am-quoted-cr.sh1
-rwxr-xr-xt/t5001-archive-attr.sh3
-rwxr-xr-xt/t5326-multi-pack-bitmaps.sh21
-rwxr-xr-xt/t5333-pseudo-merge-bitmaps.sh389
-rwxr-xr-xt/t5510-fetch.sh46
-rwxr-xr-xt/t5550-http-fetch-dumb.sh15
-rwxr-xr-xt/t5563-simple-http-auth.sh308
-rwxr-xr-xt/t5601-clone.sh66
-rwxr-xr-xt/t6302-for-each-ref-filter.sh34
-rwxr-xr-xt/t6500-gc.sh3
-rwxr-xr-xt/t7004-tag.sh114
-rwxr-xr-xt/t7400-submodule-basic.sh31
-rwxr-xr-xt/t7406-submodule-update.sh48
-rwxr-xr-xt/t7423-submodule-symlinks.sh67
-rwxr-xr-xt/t7450-bad-git-dotfiles.sh34
-rwxr-xr-xt/t7514-commit-patch.sh2
-rwxr-xr-xt/t7900-maintenance.sh6
-rwxr-xr-xt/t9001-send-email.sh10
-rwxr-xr-xt/t9210-scalar.sh38
-rwxr-xr-xt/t9902-completion.sh23
-rw-r--r--t/test-lib-functions.sh12
-rw-r--r--t/unit-tests/t-trailer.c315
-rw-r--r--trailer.c179
-rw-r--r--trailer.h102
-rw-r--r--transport-helper.c29
-rw-r--r--transport.c16
-rw-r--r--upload-pack.c20
-rw-r--r--walker.c8
-rw-r--r--wrapper.c2
-rw-r--r--wt-status.c22
370 files changed, 22762 insertions, 11831 deletions
diff --git a/.github/workflows/check-whitespace.yml b/.github/workflows/check-whitespace.yml
index a241a63428..d0a78fc426 100644
--- a/.github/workflows/check-whitespace.yml
+++ b/.github/workflows/check-whitespace.yml
@@ -26,66 +26,7 @@ jobs:
- name: git log --check
id: check_out
run: |
- baseSha=${{github.event.pull_request.base.sha}}
- problems=()
- commit=
- commitText=
- commitTextmd=
- goodparent=
- while read dash sha etc
- do
- case "${dash}" in
- "---")
- if test -z "${commit}"
- then
- goodparent=${sha}
- fi
- commit="${sha}"
- commitText="${sha} ${etc}"
- commitTextmd="[${sha}](https://github.com/${{ github.repository }}/commit/${sha}) ${etc}"
- ;;
- "")
- ;;
- *)
- if test -n "${commit}"
- then
- problems+=("1) --- ${commitTextmd}")
- echo ""
- echo "--- ${commitText}"
- commit=
- fi
- case "${dash}" in
- *:[1-9]*:) # contains file and line number information
- dashend=${dash#*:}
- problems+=("[${dash}](https://github.com/${{ github.repository }}/blob/${{github.event.pull_request.head.ref}}/${dash%%:*}#L${dashend%:}) ${sha} ${etc}")
- ;;
- *)
- problems+=("\`${dash} ${sha} ${etc}\`")
- ;;
- esac
- echo "${dash} ${sha} ${etc}"
- ;;
- esac
- done <<< $(git log --check --pretty=format:"---% h% s" ${baseSha}..)
-
- if test ${#problems[*]} -gt 0
- then
- if test -z "${commit}"
- then
- goodparent=${baseSha: 0:7}
- fi
- echo "🛑 Please review the Summary output for further information."
- echo "### :x: A whitespace issue was found in one or more of the commits." >$GITHUB_STEP_SUMMARY
- echo "" >>$GITHUB_STEP_SUMMARY
- echo "Run these commands to correct the problem:" >>$GITHUB_STEP_SUMMARY
- echo "1. \`git rebase --whitespace=fix ${goodparent}\`" >>$GITHUB_STEP_SUMMARY
- echo "1. \`git push --force\`" >>$GITHUB_STEP_SUMMARY
- echo " " >>$GITHUB_STEP_SUMMARY
- echo "Errors:" >>$GITHUB_STEP_SUMMARY
- for i in "${problems[@]}"
- do
- echo "${i}" >>$GITHUB_STEP_SUMMARY
- done
-
- exit 2
- fi
+ ./ci/check-whitespace.sh \
+ "${{github.event.pull_request.base.sha}}" \
+ "$GITHUB_STEP_SUMMARY" \
+ "https://github.com/${{github.repository}}"
diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml
index 53cf12fe04..48341e81f4 100644
--- a/.github/workflows/coverity.yml
+++ b/.github/workflows/coverity.yml
@@ -45,7 +45,7 @@ jobs:
- run: ci/install-dependencies.sh
if: contains(matrix.os, 'ubuntu') || contains(matrix.os, 'macos')
env:
- runs_on_pool: ${{ matrix.os }}
+ distro: ${{ matrix.os }}
# The Coverity site says the tool is usually updated twice yearly, so the
# MD5 of download can be used to determine whether there's been an update.
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 3428773b09..13cc0fe807 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -284,8 +284,7 @@ jobs:
cc: clang
pool: macos-13
- jobname: osx-gcc
- cc: gcc
- cc_package: gcc-13
+ cc: gcc-13
pool: macos-13
- jobname: linux-gcc-default
cc: gcc
@@ -303,7 +302,7 @@ jobs:
CC: ${{matrix.vector.cc}}
CC_PACKAGE: ${{matrix.vector.cc_package}}
jobname: ${{matrix.vector.jobname}}
- runs_on_pool: ${{matrix.vector.pool}}
+ distro: ${{matrix.vector.pool}}
runs-on: ${{matrix.vector.pool}}
steps:
- uses: actions/checkout@v4
@@ -342,12 +341,16 @@ jobs:
vector:
- jobname: linux-musl
image: alpine
+ distro: alpine-latest
- jobname: linux32
image: daald/ubuntu32:xenial
+ distro: ubuntu32-16.04
- jobname: pedantic
image: fedora
+ distro: fedora-latest
env:
jobname: ${{matrix.vector.jobname}}
+ distro: ${{matrix.vector.distro}}
runs-on: ubuntu-latest
container: ${{matrix.vector.image}}
steps:
@@ -355,7 +358,7 @@ jobs:
if: matrix.vector.jobname != 'linux32'
- uses: actions/checkout@v1 # cannot be upgraded because Node.js Actions aren't supported in this container
if: matrix.vector.jobname == 'linux32'
- - run: ci/install-docker-dependencies.sh
+ - run: ci/install-dependencies.sh
- run: ci/run-build-and-tests.sh
- name: print test failures
if: failure() && env.FAILED_TEST_ARTIFACTS != ''
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index c0fa2fe90b..f676959ca0 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -9,8 +9,10 @@ workflow:
test:linux:
image: $image
+ variables:
+ CUSTOM_PATH: "/custom"
before_script:
- - ./ci/install-docker-dependencies.sh
+ - ./ci/install-dependencies.sh
script:
- useradd builder --create-home
- chown -R builder "${CI_PROJECT_DIR}"
@@ -93,12 +95,30 @@ test:osx:
- t/failed-test-artifacts
when: on_failure
+test:fuzz-smoke-tests:
+ image: ubuntu:latest
+ variables:
+ CC: clang
+ before_script:
+ - ./ci/install-dependencies.sh
+ script:
+ - ./ci/run-build-and-minimal-fuzzers.sh
+
static-analysis:
image: ubuntu:22.04
variables:
jobname: StaticAnalysis
before_script:
- - ./ci/install-docker-dependencies.sh
+ - ./ci/install-dependencies.sh
script:
- ./ci/run-static-analysis.sh
- ./ci/check-directional-formatting.bash
+
+check-whitespace:
+ image: ubuntu:latest
+ before_script:
+ - ./ci/install-dependencies.sh
+ script:
+ - ./ci/check-whitespace.sh "$CI_MERGE_REQUEST_TARGET_BRANCH_SHA"
+ rules:
+ - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
diff --git a/Documentation/MyFirstContribution.txt b/Documentation/MyFirstContribution.txt
index f06563e981..e41654c00a 100644
--- a/Documentation/MyFirstContribution.txt
+++ b/Documentation/MyFirstContribution.txt
@@ -1116,6 +1116,15 @@ $ git send-email --to=target@example.com psuh/*.patch
NOTE: Check `git help send-email` for some other options which you may find
valuable, such as changing the Reply-to address or adding more CC and BCC lines.
+:contrib-scripts: footnoteref:[contrib-scripts,Scripts under `contrib/` are +
+not part of the core `git` binary and must be called directly. Clone the Git +
+codebase and run `perl contrib/contacts/git-contacts`.]
+
+NOTE: If you're not sure whom to CC, running `contrib/contacts/git-contacts` can
+list potential reviewers. In addition, you can do `git send-email
+--cc-cmd='perl contrib/contacts/git-contacts' feature/*.patch`{contrib-scripts} to
+automatically pass this list of emails to `send-email`.
+
NOTE: When you are sending a real patch, it will go to git@vger.kernel.org - but
please don't send your patchset from the tutorial to the real mailing list! For
now, you can send it to yourself, to make sure you understand how it will look.
diff --git a/Documentation/RelNotes/2.39.4.txt b/Documentation/RelNotes/2.39.4.txt
new file mode 100644
index 0000000000..7f54521fea
--- /dev/null
+++ b/Documentation/RelNotes/2.39.4.txt
@@ -0,0 +1,79 @@
+Git v2.39.4 Release Notes
+=========================
+
+This addresses the security issues CVE-2024-32002, CVE-2024-32004,
+CVE-2024-32020 and CVE-2024-32021.
+
+This release also backports fixes necessary to let the CI builds pass
+successfully.
+
+Fixes since v2.39.3
+-------------------
+
+ * CVE-2024-32002:
+
+ Recursive clones on case-insensitive filesystems that support symbolic
+ links are susceptible to case confusion that can be exploited to
+ execute just-cloned code during the clone operation.
+
+ * CVE-2024-32004:
+
+ Repositories can be configured to execute arbitrary code during local
+ clones. To address this, the ownership checks introduced in v2.30.3
+ are now extended to cover cloning local repositories.
+
+ * CVE-2024-32020:
+
+ Local clones may end up hardlinking files into the target repository's
+ object database when source and target repository reside on the same
+ disk. If the source repository is owned by a different user, then
+ those hardlinked files may be rewritten at any point in time by the
+ untrusted user.
+
+ * CVE-2024-32021:
+
+ When cloning a local source repository that contains symlinks via the
+ filesystem, Git may create hardlinks to arbitrary user-readable files
+ on the same filesystem as the target repository in the objects/
+ directory.
+
+ * CVE-2024-32465:
+
+ It is supposed to be safe to clone untrusted repositories, even those
+ unpacked from zip archives or tarballs originating from untrusted
+ sources, but Git can be tricked to run arbitrary code as part of the
+ clone.
+
+ * Defense-in-depth: submodule: require the submodule path to contain
+ directories only.
+
+ * Defense-in-depth: clone: when symbolic links collide with directories, keep
+ the latter.
+
+ * Defense-in-depth: clone: prevent hooks from running during a clone.
+
+ * Defense-in-depth: core.hooksPath: add some protection while cloning.
+
+ * Defense-in-depth: fsck: warn about symlink pointing inside a gitdir.
+
+ * Various fix-ups on HTTP tests.
+
+ * Test update.
+
+ * HTTP Header redaction code has been adjusted for a newer version of
+ cURL library that shows its traces differently from earlier
+ versions.
+
+ * Fix was added to work around a regression in libcURL 8.7.0 (which has
+ already been fixed in their tip of the tree).
+
+ * Replace macos-12 used at GitHub CI with macos-13.
+
+ * ci(linux-asan/linux-ubsan): let's save some time
+
+ * Tests with LSan from time to time seem to emit harmless message that makes
+ our tests unnecessarily flakey; we work it around by filtering the
+ uninteresting output.
+
+ * Update GitHub Actions jobs to avoid warnings against using deprecated
+ version of Node.js.
diff --git a/Documentation/RelNotes/2.40.2.txt b/Documentation/RelNotes/2.40.2.txt
new file mode 100644
index 0000000000..646a2cc3eb
--- /dev/null
+++ b/Documentation/RelNotes/2.40.2.txt
@@ -0,0 +1,7 @@
+Git v2.40.2 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.39.4 to address
+the security issues CVE-2024-32002, CVE-2024-32004, CVE-2024-32020,
+CVE-2024-32021 and CVE-2024-32465; see the release notes for that
+version for details.
diff --git a/Documentation/RelNotes/2.41.1.txt b/Documentation/RelNotes/2.41.1.txt
new file mode 100644
index 0000000000..9fb4c218b2
--- /dev/null
+++ b/Documentation/RelNotes/2.41.1.txt
@@ -0,0 +1,7 @@
+Git v2.41.1 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.39.4 and v2.40.2
+to address the security issues CVE-2024-32002, CVE-2024-32004,
+CVE-2024-32020, CVE-2024-32021 and CVE-2024-32465; see the release
+notes for these versions for details.
diff --git a/Documentation/RelNotes/2.42.2.txt b/Documentation/RelNotes/2.42.2.txt
new file mode 100644
index 0000000000..dbf761a01d
--- /dev/null
+++ b/Documentation/RelNotes/2.42.2.txt
@@ -0,0 +1,7 @@
+Git v2.42.2 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.39.4, v2.40.2
+and v2.41.1 to address the security issues CVE-2024-32002,
+CVE-2024-32004, CVE-2024-32020, CVE-2024-32021 and CVE-2024-32465;
+see the release notes for these versions for details.
diff --git a/Documentation/RelNotes/2.43.4.txt b/Documentation/RelNotes/2.43.4.txt
new file mode 100644
index 0000000000..0a842515ff
--- /dev/null
+++ b/Documentation/RelNotes/2.43.4.txt
@@ -0,0 +1,7 @@
+Git v2.43.4 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.39.4, v2.40.2,
+v2.41.1 and v2.42.2 to address the security issues CVE-2024-32002,
+CVE-2024-32004, CVE-2024-32020, CVE-2024-32021 and CVE-2024-32465;
+see the release notes for these versions for details.
diff --git a/Documentation/RelNotes/2.44.1.txt b/Documentation/RelNotes/2.44.1.txt
new file mode 100644
index 0000000000..b5135c3281
--- /dev/null
+++ b/Documentation/RelNotes/2.44.1.txt
@@ -0,0 +1,8 @@
+Git v2.44.1 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.39.4, v2.40.2,
+v2.41.1, v2.42.2 and v2.43.4 to address the security issues
+CVE-2024-32002, CVE-2024-32004, CVE-2024-32020, CVE-2024-32021
+and CVE-2024-32465; see the release notes for these versions
+for details.
diff --git a/Documentation/RelNotes/2.45.0.txt b/Documentation/RelNotes/2.45.0.txt
index e31bb70d15..fec193679f 100644
--- a/Documentation/RelNotes/2.45.0.txt
+++ b/Documentation/RelNotes/2.45.0.txt
@@ -256,7 +256,7 @@ Fixes since v2.44
(merge 5edd126720 jk/reflog-special-cases-fix later to maint).
* An error message from "git upload-pack", which responds to "git
- fetch" requests, had a trialing NUL in it, which has been
+ fetch" requests, had a trailing NUL in it, which has been
corrected.
(merge 3f4c7a0805 sg/upload-pack-error-message-fix later to maint).
diff --git a/Documentation/RelNotes/2.45.1.txt b/Documentation/RelNotes/2.45.1.txt
new file mode 100644
index 0000000000..3b0d60cfa3
--- /dev/null
+++ b/Documentation/RelNotes/2.45.1.txt
@@ -0,0 +1,8 @@
+Git v2.45.1 Release Notes
+=========================
+
+This release merges up the fix that appears in v2.39.4,
+v2.40.2, v2.41.1, v2.42.2, v2.43.4 and v2.44.1 to address the
+security issues CVE-2024-32002, CVE-2024-32004, CVE-2024-32020,
+CVE-2024-32021 and CVE-2024-32465; see the release notes for
+these versions for details.
diff --git a/Documentation/RelNotes/2.46.0.txt b/Documentation/RelNotes/2.46.0.txt
new file mode 100644
index 0000000000..966ad69a5d
--- /dev/null
+++ b/Documentation/RelNotes/2.46.0.txt
@@ -0,0 +1,117 @@
+Git v2.46 Release Notes
+=======================
+
+Backward Compatibility Notes
+
+ (None at this moment)
+
+UI, Workflows & Features
+
+ * The "--rfc" option of "git format-patch" learned to take an
+ optional string value to be used in place of "RFC" to tweak the
+ "[PATCH]" on the subject header.
+
+ * The credential helper protocol, together with the HTTP layer, have
+ been enhanced to support authentication schemes different from
+ username & password pair, like Bearer and NTLM.
+
+ * Command line completion script (in contrib/) learned to complete
+ "git symbolic-ref" a bit better (you need to enable plumbing
+ commands to be completed with GIT_COMPLETION_SHOW_ALL_COMMANDS).
+
+ * When the user responds to a prompt given by "git add -p" with an
+ unsupported command, list of available commands were given, which
+ was too much if the user knew what they wanted to type but merely
+ made a typo. Now the user gets a much shorter error message.
+
+ * The color parsing code learned to handle 12-bit RGB colors, spelled
+ as "#RGB" (in addition to "#RRGGBB" that is already supported).
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * Advertise "git contacts", a tool for newcomers to find people to
+ ask review for their patches, a bit more in our developer
+ documentation.
+
+ * In addition to building the objects needed, try to link the objects
+ that are used in fuzzer tests, to make sure at least they build
+ without bitrot, in Linux CI runs.
+
+ * Code to write out reftable has seen some optimization and
+ simplification.
+
+ * Tests to ensure interoperability between reftable written by jgit
+ and our code have been added and enabled in CI.
+
+ * The singleton index_state instance "the_index" has been eliminated
+ by always instantiating "the_repository" and replacing references
+ to "the_index" with references to its .index member.
+
+
+ * Git-GUI has a new maintainer, Johannes Sixt.
+ (merge e18ad8eb26 jc/git-gui-maintainer-update later to maint).
+
+
+Fixes since v2.45
+-----------------
+
+ * "git rebase --signoff" used to forget that it needs to add a
+ sign-off to the resulting commit when told to continue after a
+ conflict stops its operation.
+ (merge a6c2654f83 pw/rebase-m-signoff-fix later to maint).
+
+ * The procedure to build multi-pack-index got confused by the
+ replace-refs mechanism, which has been corrected by disabling the
+ latter.
+ (merge 93e2ae1c95 xx/disable-replace-when-building-midx later to maint).
+
+ * The "-k" and "--rfc" options of "format-patch" will now error out
+ when used together, as one tells us not to add anything to the
+ title of the commit, and the other one tells us to add "RFC" in
+ addition to "PATCH".
+ (merge cadcf58085 ds/format-patch-rfc-and-k later to maint).
+
+ * "git stash -S" did not handle binary files correctly, which has
+ been corrected.
+ (merge 5fb7686409 aj/stash-staged-fix later to maint).
+
+ * A scheduled "git maintenance" job is expected to work on all
+ repositories it knows about, but it stopped at the first one that
+ errored out. Now it keeps going.
+ (merge c75662bfc9 js/for-each-repo-keep-going later to maint).
+
+ * zsh can pretend to be a normal shell pretty well except for some
+ glitches that we tickle in some of our scripts. Work them around
+ so that "vimdiff" and our test suite works well enough with it.
+ (merge fedd5c79ff bc/zsh-compatibility later to maint).
+
+ * Command line completion support for zsh (in contrib/) has been
+ updated to stop exposing internal state to end-user shell
+ interaction.
+ (merge 3c20acdf46 dk/zsh-git-repo-path-fix later to maint).
+
+ * Tests that try to corrupt in-repository files in chunked format did
+ not work well on macOS due to its broken "mv", which has been
+ worked around.
+ (merge 861dc19ba8 jc/test-workaround-broken-mv later to maint).
+
+ * The maximum size of attribute files is enforced more consistently.
+ (merge c793f9cb08 tb/attr-limits later to maint).
+
+ * Unbreak CI jobs so that we do not attempt to use Python 2 that has
+ been removed from the platform.
+ (merge 5ca0c455f1 ps/ci-python-2-deprecation later to maint).
+
+ * Git 2.43 started using the tree of HEAD as the source of attributes
+ in a bare repository, which has severe performance implications.
+ For now, revert the change, without ripping out a more explicit
+ support for the attr.tree configuration variable.
+ (merge 51441e6460 jc/no-default-attr-tree-in-bare later to maint).
+
+ * Other code cleanup, docfix, build fix, etc.
+ (merge 4cf6e7bf5e jt/doc-submitting-rerolled-series later to maint).
+ (merge a5a4cb7b27 rs/diff-parseopts-cleanup later to maint).
+ (merge 395c130fd8 ma/win32-unix-domain-socket later to maint).
+ (merge 7df2405b38 jk/ci-macos-gcc13-fix later to maint).
+ (merge 55702c543e fa/p4-error later to maint).
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index c647c7e1b4..7cc8b15f85 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -7,6 +7,73 @@ Here are some guidelines for contributing back to this
project. There is also a link:MyFirstContribution.html[step-by-step tutorial]
available which covers many of these same guidelines.
+[[patch-flow]]
+=== A typical life cycle of a patch series
+
+To help us understand the reason behind various guidelines given later
+in the document, first let's understand how the life cycle of a
+typical patch series for this project goes.
+
+. You come up with an itch. You code it up. You do not need any
+ pre-authorization from the project to do so.
++
+Your patches will be reviewed by other contributors on the mailing
+list, and the reviews will be done to assess the merit of various
+things, like the general idea behind your patch (including "is it
+solving a problem worth solving in the first place?"), the reason
+behind the design of the solution, and the actual implementation.
+The guidelines given here are there to help your patches by making
+them easier to understand by the reviewers.
+
+. You send the patches to the list and cc people who may need to know
+ about the change. Your goal is *not* necessarily to convince others
+ that what you are building is good. Your goal is to get help in
+ coming up with a solution for the "itch" that is better than what
+ you can build alone.
++
+The people who may need to know are the ones who worked on the code
+you are touching. These people happen to be the ones who are
+most likely to be knowledgeable enough to help you, but
+they have no obligation to help you (i.e. you ask them for help,
+you don't demand). +git log -p {litdd} _$area_you_are_modifying_+ would
+help you find out who they are.
+
+. You get comments and suggestions for improvements. You may even get
+ them in an "on top of your change" patch form. You are expected to
+ respond to them with "Reply-All" on the mailing list, while taking
+ them into account while preparing an updated set of patches.
+
+. Polish, refine, and re-send your patches to the list and to the people
+ who spent their time to improve your patch. Go back to step (2).
+
+. While the above iterations improve your patches, the maintainer may
+ pick the patches up from the list and queue them to the `seen`
+ branch, in order to make it easier for people to play with it
+ without having to pick up and apply the patches to their trees
+ themselves. Being in `seen` has no other meaning. Specifically, it
+ does not mean the patch was "accepted" in any way.
+
+. When the discussion reaches a consensus that the latest iteration of
+ the patches are in good enough shape, the maintainer includes the
+ topic in the "What's cooking" report that are sent out a few times a
+ week to the mailing list, marked as "Will merge to 'next'." This
+ decision is primarily made by the maintainer with help from those
+ who participated in the review discussion.
+
+. After the patches are merged to the 'next' branch, the discussion
+ can still continue to further improve them by adding more patches on
+ top, but by the time a topic gets merged to 'next', it is expected
+ that everybody agrees that the scope and the basic direction of the
+ topic are appropriate, so such an incremental updates are limited to
+ small corrections and polishing. After a topic cooks for some time
+ (like 7 calendar days) in 'next' without needing further tweaks on
+ top, it gets merged to the 'master' branch and wait to become part
+ of the next major release.
+
+In the following sections, many techniques and conventions are listed
+to help your patches get reviewed effectively in such a life cycle.
+
+
[[choose-starting-point]]
=== Choose a starting point.
@@ -192,8 +259,9 @@ reasons:
which case, they can explain why they extend your code to cover
files, too).
-The goal of your log message is to convey the _why_ behind your
-change to help future developers.
+The goal of your log message is to convey the _why_ behind your change
+to help future developers. The reviewers will also make sure that
+your proposed log message will serve this purpose well.
The first line of the commit message should be a short description (50
characters is the soft limit, see DISCUSSION in linkgit:git-commit[1]),
@@ -397,17 +465,57 @@ letter.
[[send-patches]]
=== Sending your patches.
+==== Choosing your reviewers
+
:security-ml: footnoteref:[security-ml,The Git Security mailing list: git-security@googlegroups.com]
-Before sending any patches, please note that patches that may be
+NOTE: Patches that may be
security relevant should be submitted privately to the Git Security
mailing list{security-ml}, instead of the public mailing list.
-Learn to use format-patch and send-email if possible. These commands
+:contrib-scripts: footnoteref:[contrib-scripts,Scripts under `contrib/` are +
+not part of the core `git` binary and must be called directly. Clone the Git +
+codebase and run `perl contrib/contacts/git-contacts`.]
+
+Send your patch with "To:" set to the mailing list, with "cc:" listing
+people who are involved in the area you are touching (the `git-contacts`
+script in `contrib/contacts/`{contrib-scripts} can help to
+identify them), to solicit comments and reviews. Also, when you made
+trial merges of your topic to `next` and `seen`, you may have noticed
+work by others conflicting with your changes. There is a good possibility
+that these people may know the area you are touching well.
+
+If you are using `send-email`, you can feed it the output of `git-contacts` like
+this:
+
+....
+ git send-email --cc-cmd='perl contrib/contacts/git-contacts' feature/*.patch
+....
+
+:current-maintainer: footnote:[The current maintainer: gitster@pobox.com]
+:git-ml: footnote:[The mailing list: git@vger.kernel.org]
+
+After the list reached a consensus that it is a good idea to apply the
+patch, re-send it with "To:" set to the maintainer{current-maintainer}
+and "cc:" the list{git-ml} for inclusion. This is especially relevant
+when the maintainer did not heavily participate in the discussion and
+instead left the review to trusted others.
+
+Do not forget to add trailers such as `Acked-by:`, `Reviewed-by:` and
+`Tested-by:` lines as necessary to credit people who helped your
+patch, and "cc:" them when sending such a final version for inclusion.
+
+==== `format-patch` and `send-email`
+
+Learn to use `format-patch` and `send-email` if possible. These commands
are optimized for the workflow of sending patches, avoiding many ways
your existing e-mail client (often optimized for "multipart/*" MIME
type e-mails) might render your patches unusable.
+NOTE: Here we outline the procedure using `format-patch` and
+`send-email`, but you can instead use GitGitGadget to send in your
+patches (see link:MyFirstContribution.html[MyFirstContribution]).
+
People on the Git mailing list need to be able to read and
comment on the changes you are submitting. It is important for
a developer to be able to "quote" your changes, using standard
@@ -415,10 +523,12 @@ e-mail tools, so that they may comment on specific portions of
your code. For this reason, each patch should be submitted
"inline" in a separate message.
-Multiple related patches should be grouped into their own e-mail
-thread to help readers find all parts of the series. To that end,
-send them as replies to either an additional "cover letter" message
-(see below), the first patch, or the respective preceding patch.
+All subsequent versions of a patch series and other related patches should be
+grouped into their own e-mail thread to help readers find all parts of the
+series. To that end, send them as replies to either an additional "cover
+letter" message (see below), the first patch, or the respective preceding patch.
+Here is a link:MyFirstContribution.html#v2-git-send-email[step-by-step guide] on
+how to submit updated versions of a patch series.
If your log message (including your name on the
`Signed-off-by` trailer) is not writable in ASCII, make sure that
@@ -498,42 +608,14 @@ patch, format it as "multipart/signed", not a text/plain message
that starts with `-----BEGIN PGP SIGNED MESSAGE-----`. That is
not a text/plain, it's something else.
-:security-ml-ref: footnoteref:[security-ml]
-
-As mentioned at the beginning of the section, patches that may be
-security relevant should not be submitted to the public mailing list
-mentioned below, but should instead be sent privately to the Git
-Security mailing list{security-ml-ref}.
-
-Send your patch with "To:" set to the mailing list, with "cc:" listing
-people who are involved in the area you are touching (the `git
-contacts` command in `contrib/contacts/` can help to
-identify them), to solicit comments and reviews. Also, when you made
-trial merges of your topic to `next` and `seen`, you may have noticed
-work by others conflicting with your changes. There is a good possibility
-that these people may know the area you are touching well.
-
-:current-maintainer: footnote:[The current maintainer: gitster@pobox.com]
-:git-ml: footnote:[The mailing list: git@vger.kernel.org]
-
-After the list reached a consensus that it is a good idea to apply the
-patch, re-send it with "To:" set to the maintainer{current-maintainer}
-and "cc:" the list{git-ml} for inclusion. This is especially relevant
-when the maintainer did not heavily participate in the discussion and
-instead left the review to trusted others.
-
-Do not forget to add trailers such as `Acked-by:`, `Reviewed-by:` and
-`Tested-by:` lines as necessary to credit people who helped your
-patch, and "cc:" them when sending such a final version for inclusion.
-
== Subsystems with dedicated maintainers
Some parts of the system have dedicated maintainers with their own
repositories.
-- `git-gui/` comes from git-gui project, maintained by Pratyush Yadav:
+- `git-gui/` comes from git-gui project, maintained by Johannes Sixt:
- https://github.com/prati0100/git-gui.git
+ https://github.com/j6t/git-gui
- `gitk-git/` comes from Paul Mackerras's gitk project:
@@ -548,54 +630,12 @@ repositories.
Patches to these parts should be based on their trees.
-[[patch-flow]]
-== An ideal patch flow
-
-Here is an ideal patch flow for this project the current maintainer
-suggests to the contributors:
-
-. You come up with an itch. You code it up.
-
-. Send it to the list and cc people who may need to know about
- the change.
-+
-The people who may need to know are the ones whose code you
-are butchering. These people happen to be the ones who are
-most likely to be knowledgeable enough to help you, but
-they have no obligation to help you (i.e. you ask for help,
-don't demand). +git log -p {litdd} _$area_you_are_modifying_+ would
-help you find out who they are.
-
-. You get comments and suggestions for improvements. You may
- even get them in an "on top of your change" patch form.
-
-. Polish, refine, and re-send to the list and the people who
- spend their time to improve your patch. Go back to step (2).
-
-. The list forms consensus that the last round of your patch is
- good. Send it to the maintainer and cc the list.
-
-. A topic branch is created with the patch and is merged to `next`,
- and cooked further and eventually graduates to `master`.
-
-In any time between the (2)-(3) cycle, the maintainer may pick it up
-from the list and queue it to `seen`, in order to make it easier for
-people to play with it without having to pick up and apply the patch to
-their trees themselves.
-
-[[patch-status]]
-== Know the status of your patch after submission
+- The "Git documentation translations" project, led by Jean-Noël
+ Avila, translates our documentation pages. Their work products are
+ maintained separately from this project, not as part of our tree:
-* You can use Git itself to find out when your patch is merged in
- master. `git pull --rebase` will automatically skip already-applied
- patches, and will let you know. This works only if you rebase on top
- of the branch in which your patch has been merged (i.e. it will not
- tell you if your patch is merged in `seen` if you rebase on top of
- master).
+ https://github.com/jnavila/git-manpages-l10n/
-* Read the Git mailing list, the maintainer regularly posts messages
- entitled "What's cooking in git.git" giving
- the status of various proposed changes.
== GitHub CI[[GHCI]]
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 70b448b132..dc34e7aeae 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -58,11 +58,11 @@ compared case sensitively. These subsection names follow the same
restrictions as section names.
All the other lines (and the remainder of the line after the section
-header) are recognized as setting variables, in the form
-'name = value' (or just 'name', which is a short-hand to say that
-the variable is the boolean "true").
-The variable names are case-insensitive, allow only alphanumeric characters
-and `-`, and must start with an alphabetic character.
+header) are recognized as setting variables, in the form 'name = value'
+(or just 'name', which is a short-hand to say that the variable is the
+boolean "true"). The variable names are case-insensitive, allow only
+alphanumeric characters and `-`, and must start with an alphabetic
+character.
Whitespace characters surrounding `name`, `=` and `value` are discarded.
Internal whitespace characters within 'value' are retained verbatim.
@@ -97,10 +97,10 @@ to be included. The variable takes a pathname as its value, and is
subject to tilde expansion. These variables can be given multiple times.
The contents of the included file are inserted immediately, as if they
-had been found at the location of the include directive. If the value of the
-variable is a relative path, the path is considered to
-be relative to the configuration file in which the include directive
-was found. See below for examples.
+had been found at the location of the include directive. If the value of
+the variable is a relative path, the path is considered to be relative to
+the configuration file in which the include directive was found. See
+below for examples.
Conditional includes
~~~~~~~~~~~~~~~~~~~~
@@ -188,6 +188,12 @@ As for the naming of this keyword, it is for forwards compatibility with
a naming scheme that supports more variable-based include conditions,
but currently Git only supports the exact keyword described above.
+`hostname`::
+ The data that follows the keyword `hostname:` is taken to be a
+ pattern with standard globbing wildcards. If the current
+ hostname (output of gethostname(2)) matches the
+ pattern, the include condition is met.
+
A few more notes on matching via `gitdir` and `gitdir/i`:
* Symlinks in `$GIT_DIR` are not resolved before matching.
@@ -263,6 +269,10 @@ Example
path = foo.inc
[remote "origin"]
url = https://example.com/git
+
+; include only if the hostname of the machine matches some-hostname
+[includeIf "hostname:some-hostname"]
+ path = foo.inc
----
Values
@@ -316,7 +326,8 @@ terminals, this is usually not the same as setting to "white black".
Colors may also be given as numbers between 0 and 255; these use ANSI
256-color mode (but note that not all terminals may support this). If
your terminal supports it, you may also specify 24-bit RGB values as
-hex, like `#ff0ab3`.
+hex, like `#ff0ab3`, or 12-bit RGB values like `#f1b`, which is
+equivalent to the 24-bit color `#ff11bb`.
+
The accepted attributes are `bold`, `dim`, `ul`, `blink`, `reverse`,
`italic`, and `strike` (for crossed-out or "strikethrough" letters).
@@ -383,6 +394,8 @@ include::config/apply.txt[]
include::config/attr.txt[]
+include::config/bitmap-pseudo-merge.txt[]
+
include::config/blame.txt[]
include::config/branch.txt[]
@@ -497,6 +510,8 @@ include::config/rebase.txt[]
include::config/receive.txt[]
+include::config/reftable.txt[]
+
include::config/remote.txt[]
include::config/remotes.txt[]
diff --git a/Documentation/config/bitmap-pseudo-merge.txt b/Documentation/config/bitmap-pseudo-merge.txt
new file mode 100644
index 0000000000..90b7252204
--- /dev/null
+++ b/Documentation/config/bitmap-pseudo-merge.txt
@@ -0,0 +1,75 @@
+bitmapPseudoMerge.<name>.pattern::
+ Regular expression used to match reference names. Commits
+ pointed to by references matching this pattern (and meeting
+ the below criteria, like `bitmapPseudoMerge.<name>.sampleRate`
+ and `bitmapPseudoMerge.<name>.threshold`) will be considered
+ for inclusion in a pseudo-merge bitmap.
++
+Commits are grouped into pseudo-merge groups based on whether or not
+any reference(s) that point at a given commit match the pattern, which
+is an extended regular expression.
++
+Within a pseudo-merge group, commits may be further grouped into
+sub-groups based on the capture groups in the pattern. These
+sub-groupings are formed from the regular expressions by concatenating
+any capture groups from the regular expression, with a '-' dash in
+between.
++
+For example, if the pattern is `refs/tags/`, then all tags (provided
+they meet the below criteria) will be considered candidates for the
+same pseudo-merge group. However, if the pattern is instead
+`refs/remotes/([0-9])+/tags/`, then tags from different remotes will
+be grouped into separate pseudo-merge groups, based on the remote
+number.
+
+bitmapPseudoMerge.<name>.decay::
+ Determines the rate at which consecutive pseudo-merge bitmap
+ groups decrease in size. Must be non-negative. This parameter
+ can be thought of as `k` in the function `f(n) = C *
+ n^(-k/100)`, where `f(n)` is the size of the `n`th group.
++
+Setting the decay rate equal to `0` will cause all groups to be the
+same size. Setting the decay rate equal to `100` will cause the `n`th
+group to be `1/n` the size of the initial group. Higher values of the
+decay rate cause consecutive groups to shrink at an increasing rate.
+The default is `100`.
+
+bitmapPseudoMerge.<name>.sampleRate::
+ Determines the proportion of non-bitmapped commits (among
+ reference tips) which are selected for inclusion in an
+ unstable pseudo-merge bitmap. Must be between `0` and `100`
+ (inclusive). The default is `100`.
+
+bitmapPseudoMerge.<name>.threshold::
+ Determines the minimum age of non-bitmapped commits (among
+ reference tips, as above) which are candidates for inclusion
+ in an unstable pseudo-merge bitmap. The default is
+ `1.week.ago`.
+
+bitmapPseudoMerge.<name>.maxMerges::
+ Determines the maximum number of pseudo-merge commits among
+ which commits may be distributed.
++
+For pseudo-merge groups whose pattern does not contain any capture
+groups, this setting is applied for all commits matching the regular
+expression. For patterns that have one or more capture groups, this
+setting is applied for each distinct capture group.
++
+For example, if your capture group is `refs/tags/`, then this setting
+will distribute all tags into a maximum of `maxMerges` pseudo-merge
+commits. However, if your capture group is, say,
+`refs/remotes/([0-9]+)/tags/`, then this setting will be applied to
+each remote's set of tags individually.
++
+Must be non-negative. The default value is 64.
+
+bitmapPseudoMerge.<name>.stableThreshold::
+ Determines the minimum age of commits (among reference tips,
+ as above, however stable commits are still considered
+ candidates even when they have been covered by a bitmap) which
+ are candidates for a stable a pseudo-merge bitmap. The default
+ is `1.month.ago`.
+
+bitmapPseudoMerge.<name>.stableSize::
+ Determines the size (in number of commits) of a stable
+ psuedo-merge bitmap. The default is `512`.
diff --git a/Documentation/config/commitgraph.txt b/Documentation/config/commitgraph.txt
index 30604e4a4c..7f8c9d6638 100644
--- a/Documentation/config/commitgraph.txt
+++ b/Documentation/config/commitgraph.txt
@@ -9,6 +9,29 @@ commitGraph.maxNewFilters::
commit-graph write` (c.f., linkgit:git-commit-graph[1]).
commitGraph.readChangedPaths::
- If true, then git will use the changed-path Bloom filters in the
- commit-graph file (if it exists, and they are present). Defaults to
- true. See linkgit:git-commit-graph[1] for more information.
+ Deprecated. Equivalent to commitGraph.changedPathsVersion=-1 if true, and
+ commitGraph.changedPathsVersion=0 if false. (If commitGraph.changedPathVersion
+ is also set, commitGraph.changedPathsVersion takes precedence.)
+
+commitGraph.changedPathsVersion::
+ Specifies the version of the changed-path Bloom filters that Git will read and
+ write. May be -1, 0, 1, or 2. Note that values greater than 1 may be
+ incompatible with older versions of Git which do not yet understand
+ those versions. Use caution when operating in a mixed-version
+ environment.
++
+Defaults to -1.
++
+If -1, Git will use the version of the changed-path Bloom filters in the
+repository, defaulting to 1 if there are none.
++
+If 0, Git will not read any Bloom filters, and will write version 1 Bloom
+filters when instructed to write.
++
+If 1, Git will only read version 1 Bloom filters, and will write version 1
+Bloom filters.
++
+If 2, Git will only read version 2 Bloom filters, and will write version 2
+Bloom filters.
++
+See linkgit:git-commit-graph[1] for more information.
diff --git a/Documentation/config/reftable.txt b/Documentation/config/reftable.txt
new file mode 100644
index 0000000000..0515727977
--- /dev/null
+++ b/Documentation/config/reftable.txt
@@ -0,0 +1,48 @@
+reftable.blockSize::
+ The size in bytes used by the reftable backend when writing blocks.
+ The block size is determined by the writer, and does not have to be a
+ power of 2. The block size must be larger than the longest reference
+ name or log entry used in the repository, as references cannot span
+ blocks.
++
+Powers of two that are friendly to the virtual memory system or
+filesystem (such as 4kB or 8kB) are recommended. Larger sizes (64kB) can
+yield better compression, with a possible increased cost incurred by
+readers during access.
++
+The largest block size is `16777215` bytes (15.99 MiB). The default value is
+`4096` bytes (4kB). A value of `0` will use the default value.
+
+reftable.restartInterval::
+ The interval at which to create restart points. The reftable backend
+ determines the restart points at file creation. Every 16 may be
+ more suitable for smaller block sizes (4k or 8k), every 64 for larger
+ block sizes (64k).
++
+More frequent restart points reduces prefix compression and increases
+space consumed by the restart table, both of which increase file size.
++
+Less frequent restart points makes prefix compression more effective,
+decreasing overall file size, with increased penalties for readers
+walking through more records after the binary search step.
++
+A maximum of `65535` restart points per block is supported.
++
+The default value is to create restart points every 16 records. A value of `0`
+will use the default value.
+
+reftable.indexObjects::
+ Whether the reftable backend shall write object blocks. Object blocks
+ are a reverse mapping of object ID to the references pointing to them.
++
+The default value is `true`.
+
+reftable.geometricFactor::
+ Whenever the reftable backend appends a new table to the stack, it
+ performs auto compaction to ensure that there is only a handful of
+ tables. The backend does this by ensuring that tables form a geometric
+ sequence regarding the respective sizes of each table.
++
+By default, the geometric sequence uses a factor of 2, meaning that for any
+table, the next-biggest table must at least be twice as big. A maximum factor
+of 256 is supported.
diff --git a/Documentation/fsck-msgids.txt b/Documentation/fsck-msgids.txt
index f643585a34..5edc06c658 100644
--- a/Documentation/fsck-msgids.txt
+++ b/Documentation/fsck-msgids.txt
@@ -164,6 +164,18 @@
`nullSha1`::
(WARN) Tree contains entries pointing to a null sha1.
+`symlinkPointsToGitDir`::
+ (WARN) Symbolic link points inside a gitdir.
+
+`symlinkTargetBlob`::
+ (ERROR) A non-blob found instead of a symbolic link's target.
+
+`symlinkTargetLength`::
+ (WARN) Symbolic link target longer than maximum path length.
+
+`symlinkTargetMissing`::
+ (ERROR) Unable to read symbolic link target's blob.
+
`treeNotSorted`::
(ERROR) A tree is not properly sorted.
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index ac61113fcc..65c645d461 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -9,21 +9,14 @@ git-config - Get and set repository or global options
SYNOPSIS
--------
[verse]
-'git config' [<file-option>] [--type=<type>] [--comment=<message>] [--fixed-value] [--show-origin] [--show-scope] [-z|--null] <name> [<value> [<value-pattern>]]
-'git config' [<file-option>] [--type=<type>] [--comment=<message>] --add <name> <value>
-'git config' [<file-option>] [--type=<type>] [--comment=<message>] [--fixed-value] --replace-all <name> <value> [<value-pattern>]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--fixed-value] --get <name> [<value-pattern>]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--fixed-value] --get-all <name> [<value-pattern>]
-'git config' [<file-option>] [--type=<type>] [--show-origin] [--show-scope] [-z|--null] [--fixed-value] [--name-only] --get-regexp <name-regex> [<value-pattern>]
-'git config' [<file-option>] [--type=<type>] [-z|--null] --get-urlmatch <name> <URL>
-'git config' [<file-option>] [--fixed-value] --unset <name> [<value-pattern>]
-'git config' [<file-option>] [--fixed-value] --unset-all <name> [<value-pattern>]
-'git config' [<file-option>] --rename-section <old-name> <new-name>
-'git config' [<file-option>] --remove-section <name>
-'git config' [<file-option>] [--show-origin] [--show-scope] [-z|--null] [--name-only] -l | --list
-'git config' [<file-option>] --get-color <name> [<default>]
+'git config list' [<file-option>] [<display-option>] [--includes]
+'git config get' [<file-option>] [<display-option>] [--includes] [--all] [--regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] <name>
+'git config set' [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value>
+'git config unset' [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>
+'git config rename-section' [<file-option>] <old-name> <new-name>
+'git config remove-section' [<file-option>] <name>
+'git config edit' [<file-option>]
'git config' [<file-option>] --get-colorbool <name> [<stdout-is-tty>]
-'git config' [<file-option>] -e | --edit
DESCRIPTION
-----------
@@ -31,7 +24,7 @@ You can query/set/replace/unset options with this command. The name is
actually the section and the key separated by a dot, and the value will be
escaped.
-Multiple lines can be added to an option by using the `--add` option.
+Multiple lines can be added to an option by using the `--append` option.
If you want to update or unset an option which can occur on multiple
lines, a `value-pattern` (which is an extended regular expression,
unless the `--fixed-value` option is given) needs to be given. Only the
@@ -74,6 +67,42 @@ On success, the command returns the exit code 0.
A list of all available configuration variables can be obtained using the
`git help --config` command.
+COMMANDS
+--------
+
+list::
+ List all variables set in config file, along with their values.
+
+get::
+ Emits the value of the specified key. If key is present multiple times
+ in the configuration, emits the last value. If `--all` is specified,
+ emits all values associated with key. Returns error code 1 if key is
+ not present.
+
+set::
+ Set value for one or more config options. By default, this command
+ refuses to write multi-valued config options. Passing `--all` will
+ replace all multi-valued config options with the new value, whereas
+ `--value=` will replace all config options whose values match the given
+ pattern.
+
+unset::
+ Unset value for one or more config options. By default, this command
+ refuses to unset multi-valued keys. Passing `--all` will unset all
+ multi-valued config options, whereas `--value` will unset all config
+ options whose values match the given pattern.
+
+rename-section::
+ Rename the given section to a new name.
+
+remove-section::
+ Remove the given section from the configuration file.
+
+edit::
+ Opens an editor to modify the specified config file; either
+ `--system`, `--global`, `--local` (default), `--worktree`, or
+ `--file <config-file>`.
+
[[OPTIONS]]
OPTIONS
-------
@@ -82,10 +111,9 @@ OPTIONS
Default behavior is to replace at most one line. This replaces
all lines matching the key (and optionally the `value-pattern`).
---add::
+--append::
Adds a new line to the option without altering any existing
- values. This is the same as providing '^$' as the `value-pattern`
- in `--replace-all`.
+ values. This is the same as providing '--value=^$' in `set`.
--comment <message>::
Append a comment at the end of new or modified lines.
@@ -99,22 +127,16 @@ OPTIONS
not contain linefeed characters (no multi-line comments are
permitted).
---get::
- Get the value for a given key (optionally filtered by a regex
- matching the value). Returns error code 1 if the key was not
- found and the last value if multiple key values were found.
+--all::
+ With `get`, return all values for a multi-valued key.
---get-all::
- Like get, but returns all values for a multi-valued key.
+---regexp::
+ With `get`, interpret the name as a regular expression. Regular
+ expression matching is currently case-sensitive and done against a
+ canonicalized version of the key in which section and variable names
+ are lowercased, but subsection names are not.
---get-regexp::
- Like --get-all, but interprets the name as a regular expression and
- writes out the key names. Regular expression matching is currently
- case-sensitive and done against a canonicalized version of the key
- in which section and variable names are lowercased, but subsection
- names are not.
-
---get-urlmatch <name> <URL>::
+--url=<URL>::
When given a two-part <name> as <section>.<key>, the value for
<section>.<URL>.<key> whose <URL> part matches the best to the
given URL is returned (if no such key exists, the value for
@@ -178,22 +200,6 @@ See also <<FILES>>.
section in linkgit:gitrevisions[7] for a more complete list of
ways to spell blob names.
---remove-section::
- Remove the given section from the configuration file.
-
---rename-section::
- Rename the given section to a new name.
-
---unset::
- Remove the line matching the key from config file.
-
---unset-all::
- Remove all lines matching the key from config file.
-
--l::
---list::
- List all variables set in config file, along with their values.
-
--fixed-value::
When used with the `value-pattern` argument, treat `value-pattern` as
an exact string instead of a regular expression. This will restrict
@@ -248,8 +254,8 @@ Valid `<type>`'s include:
contain line breaks.
--name-only::
- Output only the names of config variables for `--list` or
- `--get-regexp`.
+ Output only the names of config variables for `list` or
+ `get`.
--show-origin::
Augment the output of all queried config options with the
@@ -273,23 +279,6 @@ Valid `<type>`'s include:
When the color setting for `name` is undefined, the command uses
`color.ui` as fallback.
---get-color <name> [<default>]::
-
- Find the color configured for `name` (e.g. `color.diff.new`) and
- output it as the ANSI color escape sequence to the standard
- output. The optional `default` parameter is used instead, if
- there is no color configured for `name`.
-+
-`--type=color [--default=<default>]` is preferred over `--get-color`
-(but note that `--get-color` will omit the trailing newline printed by
-`--type=color`).
-
--e::
---edit::
- Opens an editor to modify the specified config file; either
- `--system`, `--global`, `--local` (default), `--worktree`, or
- `--file <config-file>`.
-
--[no-]includes::
Respect `include.*` directives in config files when looking up
values. Defaults to `off` when a specific file is given (e.g.,
@@ -297,14 +286,64 @@ Valid `<type>`'s include:
config files.
--default <value>::
- When using `--get`, and the requested variable is not found, behave as if
+ When using `get`, and the requested variable is not found, behave as if
<value> were the value assigned to that variable.
+DEPRECATED MODES
+----------------
+
+The following modes have been deprecated in favor of subcommands. It is
+recommended to migrate to the new syntax.
+
+'git config <name>'::
+ Replaced by `git config get <name>`.
+
+'git config <name> <value> [<value-pattern>]'::
+ Replaced by `git config set [--value=<pattern>] <name> <value>`.
+
+-l::
+--list::
+ Replaced by `git config list`.
+
+--get <name> [<value-pattern>]::
+ Replaced by `git config get [--value=<pattern>] <name>`.
+
+--get-all <name> [<value-pattern>]::
+ Replaced by `git config get [--value=<pattern>] --all --show-names <name>`.
+
+--get-regexp <name-regexp>::
+ Replaced by `git config get --all --show-names --regexp <name-regexp>`.
+
+--get-urlmatch <name> <URL>::
+ Replaced by `git config get --all --show-names --url=<URL> <name>`.
+
+--get-color <name> [<default>]::
+ Replaced by `git config get --type=color [--default=<default>] <name>`.
+
+--add <name> <value>::
+ Replaced by `git config set --append <name> <value>`.
+
+--unset <name> [<value-pattern>]::
+ Replaced by `git config unset [--value=<pattern>] <name>`.
+
+--unset-all <name> [<value-pattern>]::
+ Replaced by `git config unset [--value=<pattern>] --all <name>`.
+
+--rename-section <old-name> <new-name>::
+ Replaced by `git config rename-section <old-name> <new-name>`.
+
+--remove-section <name>::
+ Replaced by `git config remove-section <name>`.
+
+-e::
+--edit::
+ Replaced by `git config edit`.
+
CONFIGURATION
-------------
`pager.config` is only respected when listing configuration, i.e., when
-using `--list` or any of the `--get-*` which may return multiple results.
-The default is to use a pager.
+using `list` or `get` which may return multiple results. The default is to use
+a pager.
[[FILES]]
FILES
@@ -346,8 +385,8 @@ precedence over values read earlier. When multiple values are taken then all
values of a key from all files will be used.
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*.
+configuration file. Note that this also affects options like `set`
+and `unset`. *'git config' will only ever change one file at a time*.
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
@@ -482,7 +521,7 @@ Given a .git/config like this:
you can set the filemode to true with
------------
-% git config core.filemode true
+% git config set core.filemode true
------------
The hypothetical proxy command entries actually have a postfix to discern
@@ -490,7 +529,7 @@ what URL they apply to. Here is how to change the entry for kernel.org
to "ssh".
------------
-% git config core.gitproxy '"ssh" for kernel.org' 'for kernel.org$'
+% git config set --value='for kernel.org$' core.gitproxy '"ssh" for kernel.org'
------------
This makes sure that only the key/value pair for kernel.org is replaced.
@@ -498,7 +537,7 @@ This makes sure that only the key/value pair for kernel.org is replaced.
To delete the entry for renames, do
------------
-% git config --unset diff.renames
+% git config unset diff.renames
------------
If you want to delete an entry for a multivar (like core.gitproxy above),
@@ -507,51 +546,45 @@ you have to provide a regex matching the value of exactly one line.
To query the value for a given key, do
------------
-% git config --get core.filemode
-------------
-
-or
-
-------------
-% git config core.filemode
+% git config get core.filemode
------------
or, to query a multivar:
------------
-% git config --get core.gitproxy "for kernel.org$"
+% git config get --value="for kernel.org$" core.gitproxy
------------
If you want to know all the values for a multivar, do:
------------
-% git config --get-all core.gitproxy
+% git config get --all --show-names core.gitproxy
------------
If you like to live dangerously, you can replace *all* core.gitproxy by a
new one with
------------
-% git config --replace-all core.gitproxy ssh
+% git config set --all core.gitproxy ssh
------------
However, if you really only want to replace the line for the default proxy,
i.e. the one without a "for ..." postfix, do something like this:
------------
-% git config core.gitproxy ssh '! for '
+% git config set --value='! for ' core.gitproxy ssh
------------
To actually match only values with an exclamation mark, you have to
------------
-% git config section.key value '[!]'
+% git config set --value='[!]' section.key value
------------
To add a new proxy, without altering any of the existing ones, use
------------
-% git config --add core.gitproxy '"proxy-command" for example.com'
+% git config set --append core.gitproxy '"proxy-command" for example.com'
------------
An example to use customized color from the configuration in your
@@ -559,8 +592,8 @@ script:
------------
#!/bin/sh
-WS=$(git config --get-color color.diff.whitespace "blue reverse")
-RESET=$(git config --get-color "" "reset")
+WS=$(git config get --type=color --default="blue reverse" color.diff.whitespace)
+RESET=$(git config get --type=color --default="reset" "")
echo "${WS}your whitespace color or blue reverse${RESET}"
------------
@@ -568,11 +601,11 @@ For URLs in `https://weak.example.com`, `http.sslVerify` is set to
false, while it is set to `true` for all others:
------------
-% git config --type=bool --get-urlmatch http.sslverify https://good.example.com
+% git config get --type=bool --url=https://good.example.com http.sslverify
true
-% git config --type=bool --get-urlmatch http.sslverify https://weak.example.com
+% git config get --type=bool --url=https://weak.example.com http.sslverify
false
-% git config --get-urlmatch http https://weak.example.com
+% git config get --url=https://weak.example.com http
http.cookieFile /tmp/cookie.txt
http.sslverify false
------------
diff --git a/Documentation/git-credential.txt b/Documentation/git-credential.txt
index 918a0aa42b..e41493292f 100644
--- a/Documentation/git-credential.txt
+++ b/Documentation/git-credential.txt
@@ -8,7 +8,7 @@ git-credential - Retrieve and store user credentials
SYNOPSIS
--------
------------------
-'git credential' (fill|approve|reject)
+'git credential' (fill|approve|reject|capability)
------------------
DESCRIPTION
@@ -41,6 +41,9 @@ If the action is `reject`, git-credential will send the description to
any configured credential helpers, which may erase any stored
credentials matching the description.
+If the action is `capability`, git-credential will announce any capabilities
+it supports to standard output.
+
If the action is `approve` or `reject`, no output should be emitted.
TYPICAL USE OF GIT CREDENTIAL
@@ -111,7 +114,9 @@ attribute per line. Each attribute is specified by a key-value pair,
separated by an `=` (equals) sign, followed by a newline.
The key may contain any bytes except `=`, newline, or NUL. The value may
-contain any bytes except newline or NUL.
+contain any bytes except newline or NUL. A line, including the trailing
+newline, may not exceed 65535 bytes in order to allow implementations to
+parse efficiently.
Attributes with keys that end with C-style array brackets `[]` can have
multiple values. Each instance of a multi-valued attribute forms an
@@ -178,6 +183,61 @@ empty string.
Components which are missing from the URL (e.g., there is no
username in the example above) will be left unset.
+`authtype`::
+ This indicates that the authentication scheme in question should be used.
+ Common values for HTTP and HTTPS include `basic`, `bearer`, and `digest`,
+ although the latter is insecure and should not be used. If `credential`
+ is used, this may be set to an arbitrary string suitable for the protocol in
+ question (usually HTTP).
++
+This value should not be sent unless the appropriate capability (see below) is
+provided on input.
+
+`credential`::
+ The pre-encoded credential, suitable for the protocol in question (usually
+ HTTP). If this key is sent, `authtype` is mandatory, and `username` and
+ `password` are not used. For HTTP, Git concatenates the `authtype` value and
+ this value with a single space to determine the `Authorization` header.
++
+This value should not be sent unless the appropriate capability (see below) is
+provided on input.
+
+`ephemeral`::
+ This boolean value indicates, if true, that the value in the `credential`
+ field should not be saved by the credential helper because its usefulness is
+ limited in time. For example, an HTTP Digest `credential` value is computed
+ using a nonce and reusing it will not result in successful authentication.
+ This may also be used for situations with short duration (e.g., 24-hour)
+ credentials. The default value is false.
++
+The credential helper will still be invoked with `store` or `erase` so that it
+can determine whether the operation was successful.
++
+This value should not be sent unless the appropriate capability (see below) is
+provided on input.
+
+`state[]`::
+ This value provides an opaque state that will be passed back to this helper
+ if it is called again. Each different credential helper may specify this
+ once. The value should include a prefix unique to the credential helper and
+ should ignore values that don't match its prefix.
++
+This value should not be sent unless the appropriate capability (see below) is
+provided on input.
+
+`continue`::
+ This is a boolean value, which, if enabled, indicates that this
+ authentication is a non-final part of a multistage authentication step. This
+ is common in protocols such as NTLM and Kerberos, where two rounds of client
+ authentication are required, and setting this flag allows the credential
+ helper to implement the multistage authentication step. This flag should
+ only be sent if a further stage is required; that is, if another round of
+ authentication is expected.
++
+This value should not be sent unless the appropriate capability (see below) is
+provided on input. This attribute is 'one-way' from a credential helper to
+pass information to Git (or other programs invoking `git credential`).
+
`wwwauth[]`::
When an HTTP response is received by Git that includes one or more
@@ -189,7 +249,45 @@ attribute 'wwwauth[]', where the order of the attributes is the same as
they appear in the HTTP response. This attribute is 'one-way' from Git
to pass additional information to credential helpers.
-Unrecognised attributes are silently discarded.
+`capability[]`::
+ This signals that Git, or the helper, as appropriate, supports the capability
+ in question. This can be used to provide better, more specific data as part
+ of the protocol. A `capability[]` directive must precede any value depending
+ on it and these directives _should_ be the first item announced in the
+ protocol.
++
+There are two currently supported capabilities. The first is `authtype`, which
+indicates that the `authtype`, `credential`, and `ephemeral` values are
+understood. The second is `state`, which indicates that the `state[]` and
+`continue` values are understood.
++
+It is not obligatory to use the additional features just because the capability
+is supported, but they should not be provided without the capability.
+
+Unrecognised attributes and capabilities are silently discarded.
+
+[[CAPA-IOFMT]]
+CAPABILITY INPUT/OUTPUT FORMAT
+------------------------------
+
+For `git credential capability`, the format is slightly different. First, a
+`version 0` announcement is made to indicate the current version of the
+protocol, and then each capability is announced with a line like `capability
+authtype`. Credential helpers may also implement this format, again with the
+`capability` argument. Additional lines may be added in the future; callers
+should ignore lines which they don't understand.
+
+Because this is a new part of the credential helper protocol, older versions of
+Git, as well as some credential helpers, may not support it. If a non-zero
+exit status is received, or if the first line doesn't start with the word
+`version` and a space, callers should assume that no capabilities are supported.
+
+The intention of this format is to differentiate it from the credential output
+in an unambiguous way. It is possible to use very simple credential helpers
+(e.g., inline shell scripts) which always produce identical output. Using a
+distinct format allows users to continue to use this syntax without having to
+worry about correctly implementing capability advertisements or accidentally
+confusing callers querying for capabilities.
GIT
---
diff --git a/Documentation/git-for-each-repo.txt b/Documentation/git-for-each-repo.txt
index 94bd19da26..abe3527aac 100644
--- a/Documentation/git-for-each-repo.txt
+++ b/Documentation/git-for-each-repo.txt
@@ -42,6 +42,15 @@ These config values are loaded from system, global, and local Git config,
as available. If `git for-each-repo` is run in a directory that is not a
Git repository, then only the system and global config is used.
+--keep-going::
+ Continue with the remaining repositories if the command failed
+ on a repository. The exit code will still indicate that the
+ overall operation was not successful.
++
+Note that the exact exit code of the failing command is not passed
+through as the exit code of the `for-each-repo` command: If the command
+failed in any of the specified repositories, the overall exit code will
+be 1.
SUBPROCESS BEHAVIOR
-------------------
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 728bb3821c..8708b31593 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -20,7 +20,7 @@ SYNOPSIS
[--in-reply-to=<message-id>] [--suffix=.<sfx>]
[--ignore-if-in-upstream] [--always]
[--cover-from-description=<mode>]
- [--rfc] [--subject-prefix=<subject-prefix>]
+ [--rfc[=<rfc>]] [--subject-prefix=<subject-prefix>]
[(--reroll-count|-v) <n>]
[--to=<email>] [--cc=<email>]
[--[no-]cover-letter] [--quiet]
@@ -238,10 +238,21 @@ the patches (with a value of e.g. "PATCH my-project").
value of the `format.filenameMaxLength` configuration
variable, or 64 if unconfigured.
---rfc::
- Prepends "RFC" to the subject prefix (producing "RFC PATCH" by
- default). RFC means "Request For Comments"; use this when sending
- an experimental patch for discussion rather than application.
+--rfc[=<rfc>]::
+ Prepends the string _<rfc>_ (defaults to "RFC") to
+ the subject prefix. As the subject prefix defaults to
+ "PATCH", you'll get "RFC PATCH" by default.
++
+RFC means "Request For Comments"; use this when sending
+an experimental patch for discussion rather than application.
+"--rfc=WIP" may also be a useful way to indicate that a patch
+is not complete yet ("WIP" stands for "Work In Progress").
++
+If the convention of the receiving community for a particular extra
+string is to have it _after_ the subject prefix, the string _<rfc>_
+can be prefixed with a dash ("`-`") to signal that the the rest of
+the _<rfc>_ string should be appended to the subject prefix instead,
+e.g., `--rfc='-(WIP)'` results in "PATCH (WIP)".
-v <n>::
--reroll-count=<n>::
@@ -346,6 +357,11 @@ material (this may change in the future).
between the previous and current series of patches by adjusting the
creation/deletion cost fudge factor. See linkgit:git-range-diff[1])
for details.
++
+Defaults to 999 (the linkgit:git-range-diff[1] uses 60), as the use
+case is to show comparison with an older iteration of the same
+topic and the tool should find more correspondence between the two
+sets of patches.
--notes[=<ref>]::
--no-notes::
diff --git a/Documentation/git-gui.txt b/Documentation/git-gui.txt
index e8f3ccb433..f5b02ef114 100644
--- a/Documentation/git-gui.txt
+++ b/Documentation/git-gui.txt
@@ -114,7 +114,7 @@ of end users.
The official repository of the 'git gui' project can be found at:
- https://github.com/prati0100/git-gui.git/
+ https://github.com/j6t/git-gui
GIT
---
diff --git a/Documentation/git-merge-tree.txt b/Documentation/git-merge-tree.txt
index dd388fa21d..84cb2edf6d 100644
--- a/Documentation/git-merge-tree.txt
+++ b/Documentation/git-merge-tree.txt
@@ -72,6 +72,11 @@ OPTIONS
As the merge-base is provided directly, <branch1> and <branch2> do not need
to specify commits; trees are enough.
+-X<option>::
+--strategy-option=<option>::
+ Pass the merge strategy-specific option through to the merge strategy.
+ See linkgit:git-merge[1] for details.
+
[[OUTPUT]]
OUTPUT
------
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index f9d5a35fa0..dc12d38534 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -18,8 +18,15 @@ Many Git porcelainish commands take a mixture of flags
(i.e. parameters that begin with a dash '-') and parameters
meant for the underlying 'git rev-list' command they use internally
and flags and parameters for the other commands they use
-downstream of 'git rev-list'. This command is used to
-distinguish between them.
+downstream of 'git rev-list'. The primary purpose of this command
+is to allow calling programs to distinguish between them. There are
+a few other operation modes that have nothing to do with the above
+"help parse command line options".
+
+Unless otherwise specified, most of the options and operation modes
+require you to run this command inside a git repository or a working
+tree that is under the control of a git repository, and will give you
+a fatal error otherwise.
OPTIONS
@@ -32,11 +39,15 @@ Each of these options must appear first on the command line.
--parseopt::
Use 'git rev-parse' in option parsing mode (see PARSEOPT section below).
+ The command in this mode can be used outside a repository or
+ a working tree controlled by a repository.
--sq-quote::
Use 'git rev-parse' in shell quoting mode (see SQ-QUOTE
section below). In contrast to the `--sq` option below, this
mode only does quoting. Nothing else is done to command input.
+ The command in this mode can be used outside a repository or
+ a working tree controlled by a repository.
Options for --parseopt
~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 5fe519c31e..4494729f5e 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -10,6 +10,7 @@ SYNOPSIS
--------
[verse]
'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]
+ [(--trailer <token>[(=|:)<value>])...]
<tagname> [<commit> | <object>]
'git tag' -d <tagname>...
'git tag' [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]
@@ -31,8 +32,8 @@ creates a 'tag' object, and requires a tag message. Unless
`-m <msg>` or `-F <file>` is given, an editor is started for the user to type
in the tag message.
-If `-m <msg>` or `-F <file>` is given and `-a`, `-s`, and `-u <key-id>`
-are absent, `-a` is implied.
+If `-m <msg>` or `-F <file>` or `--trailer <token>[=<value>]` is given
+and `-a`, `-s`, and `-u <key-id>` are absent, `-a` is implied.
Otherwise, a tag reference that points directly at the given object
(i.e., a lightweight tag) is created.
@@ -178,6 +179,17 @@ This option is only applicable when listing tags without annotation lines.
Implies `-a` if none of `-a`, `-s`, or `-u <key-id>`
is given.
+--trailer <token>[(=|:)<value>]::
+ Specify a (<token>, <value>) pair that should be applied as a
+ trailer. (e.g. `git tag --trailer "Custom-Key: value"`
+ will add a "Custom-Key" trailer to the tag message.)
+ The `trailer.*` configuration variables
+ (linkgit:git-interpret-trailers[1]) can be used to define if
+ a duplicated trailer is omitted, where in the run of trailers
+ each trailer would appear, and other details.
+ The trailers can be extracted in `git tag --list`, using
+ `--format="%(trailers)"` placeholder.
+
-e::
--edit::
The message taken from file with `-F` and command line with
diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
index 8c47890a6a..7128aed540 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -25,6 +25,7 @@ SYNOPSIS
[--really-refresh] [--unresolve] [--again | -g]
[--info-only] [--index-info]
[-z] [--stdin] [--index-version <n>]
+ [--show-index-version]
[--verbose]
[--] [<file>...]
diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt
index 7ad60bc348..516d1639d9 100644
--- a/Documentation/git-upload-pack.txt
+++ b/Documentation/git-upload-pack.txt
@@ -55,6 +55,37 @@ ENVIRONMENT
admins may need to configure some transports to allow this
variable to be passed. See the discussion in linkgit:git[1].
+`GIT_NO_LAZY_FETCH`::
+ When cloning or fetching from a partial repository (i.e., one
+ itself cloned with `--filter`), the server-side `upload-pack`
+ may need to fetch extra objects from its upstream in order to
+ complete the request. By default, `upload-pack` will refuse to
+ perform such a lazy fetch, because `git fetch` may run arbitrary
+ commands specified in configuration and hooks of the source
+ repository (and `upload-pack` tries to be safe to run even in
+ untrusted `.git` directories).
++
+This is implemented by having `upload-pack` internally set the
+`GIT_NO_LAZY_FETCH` variable to `1`. If you want to override it
+(because you are fetching from a partial clone, and you are sure
+you trust it), you can explicitly set `GIT_NO_LAZY_FETCH` to
+`0`.
+
+SECURITY
+--------
+
+Most Git commands should not be run in an untrusted `.git` directory
+(see the section `SECURITY` in linkgit:git[1]). `upload-pack` tries to
+avoid any dangerous configuration options or hooks from the repository
+it's serving, making it safe to clone an untrusted directory and run
+commands on the resulting clone.
+
+For an extra level of safety, you may be able to run `upload-pack` as an
+alternate user. The details will be platform dependent, but on many
+systems you can run:
+
+ git clone --no-local --upload-pack='sudo -u nobody git-upload-pack' ...
+
SEE ALSO
--------
linkgit:gitnamespaces[7]
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 7a1b112a3e..a31a70acca 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -11,9 +11,10 @@ SYNOPSIS
[verse]
'git' [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
- [-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]
- [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
- [--config-env=<name>=<envvar>] <command> [<args>]
+ [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-lazy-fetch]
+ [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]
+ [--work-tree=<path>] [--namespace=<name>] [--config-env=<name>=<envvar>]
+ <command> [<args>]
DESCRIPTION
-----------
@@ -186,6 +187,13 @@ If you just want to run git as if it was started in `<path>` then use
This is equivalent to setting the `GIT_NO_LAZY_FETCH`
environment variable to `1`.
+--no-optional-locks::
+ Do not perform optional operations that require locks. This is
+ equivalent to setting the `GIT_OPTIONAL_LOCKS` to `0`.
+
+--no-advice::
+ Disable all advice hints from being printed.
+
--literal-pathspecs::
Treat pathspecs literally (i.e. no globbing, no pathspec magic).
This is equivalent to setting the `GIT_LITERAL_PATHSPECS` environment
@@ -207,10 +215,6 @@ If you just want to run git as if it was started in `<path>` then use
Add "icase" magic to all pathspec. This is equivalent to setting
the `GIT_ICASE_PATHSPECS` environment variable to `1`.
---no-optional-locks::
- Do not perform optional operations that require locks. This is
- equivalent to setting the `GIT_OPTIONAL_LOCKS` to `0`.
-
--list-cmds=<group>[,<group>...]::
List commands by group. This is an internal/experimental
option and may change or be removed in the future. Supported
@@ -1067,6 +1071,37 @@ The index is also capable of storing multiple entries (called "stages")
for a given pathname. These stages are used to hold the various
unmerged version of a file when a merge is in progress.
+SECURITY
+--------
+
+Some configuration options and hook files may cause Git to run arbitrary
+shell commands. Because configuration and hooks are not copied using
+`git clone`, it is generally safe to clone remote repositories with
+untrusted content, inspect them with `git log`, and so on.
+
+However, it is not safe to run Git commands in a `.git` directory (or
+the working tree that surrounds it) when that `.git` directory itself
+comes from an untrusted source. The commands in its config and hooks
+are executed in the usual way.
+
+By default, Git will refuse to run when the repository is owned by
+someone other than the user running the command. See the entry for
+`safe.directory` in linkgit:git-config[1]. While this can help protect
+you in a multi-user environment, note that you can also acquire
+untrusted repositories that are owned by you (for example, if you
+extract a zip file or tarball from an untrusted source). In such cases,
+you'd need to "sanitize" the untrusted repository first.
+
+If you have an untrusted `.git` directory, you should first clone it
+with `git clone --no-local` to obtain a clean copy. Git does restrict
+the set of options and hooks that will be run by `upload-pack`, which
+handles the server side of a clone or fetch, but beware that the
+surface area for attack against `upload-pack` is large, so this does
+carry some risk. The safest thing is to serve the repository as an
+unprivileged user (either via linkgit:git-daemon[1], ssh, or using
+other tools to change user ids). See the discussion in the `SECURITY`
+section of linkgit:git-upload-pack[1].
+
FURTHER DOCUMENTATION
---------------------
diff --git a/Documentation/gitformat-commit-graph.txt b/Documentation/gitformat-commit-graph.txt
index 31cad585e2..3e906e8030 100644
--- a/Documentation/gitformat-commit-graph.txt
+++ b/Documentation/gitformat-commit-graph.txt
@@ -142,13 +142,16 @@ All multi-byte numbers are in network byte order.
==== Bloom Filter Data (ID: {'B', 'D', 'A', 'T'}) [Optional]
* It starts with header consisting of three unsigned 32-bit integers:
- - Version of the hash algorithm being used. We currently only support
- value 1 which corresponds to the 32-bit version of the murmur3 hash
+ - Version of the hash algorithm being used. We currently support
+ value 2 which corresponds to the 32-bit version of the murmur3 hash
implemented exactly as described in
https://en.wikipedia.org/wiki/MurmurHash#Algorithm and the double
hashing technique using seed values 0x293ae76f and 0x7e646e2 as
described in https://doi.org/10.1007/978-3-540-30494-4_26 "Bloom Filters
- in Probabilistic Verification"
+ in Probabilistic Verification". Version 1 Bloom filters have a bug that appears
+ when char is signed and the repository has path names that have characters >=
+ 0x80; Git supports reading and writing them, but this ability will be removed
+ in a future version of Git.
- The number of times a path is hashed and hence the number of bit positions
that cumulatively determine whether a file is present in the commit.
- The minimum number of bits 'b' per entry in the Bloom filter. If the filter
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index ee9b92c90d..06e997131b 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -486,7 +486,7 @@ reference-transaction
This hook is invoked by any Git command that performs reference
updates. It executes whenever a reference transaction is prepared,
committed or aborted and may thus get called multiple times. The hook
-does not cover symbolic references (but that may change in the future).
+also supports symbolic reference updates.
The hook takes exactly one argument, which is the current state the
given reference transaction is in:
@@ -503,16 +503,20 @@ given reference transaction is in:
For each reference update that was added to the transaction, the hook
receives on standard input a line of the format:
- <old-oid> SP <new-oid> SP <ref-name> LF
+ <old-value> SP <new-value> SP <ref-name> LF
-where `<old-oid>` is the old object name passed into the reference
-transaction, `<new-oid>` is the new object name to be stored in the
+where `<old-value>` is the old object name passed into the reference
+transaction, `<new-value>` is the new object name to be stored in the
ref and `<ref-name>` is the full name of the ref. When force updating
the reference regardless of its current value or when the reference is
-to be created anew, `<old-oid>` is the all-zeroes object name. To
+to be created anew, `<old-value>` is the all-zeroes object name. To
distinguish these cases, you can inspect the current value of
`<ref-name>` via `git rev-parse`.
+For symbolic reference updates the `<old_value>` and `<new-value>`
+fields could denote references instead of objects. A reference will be
+denoted with a 'ref:' prefix, like `ref:<ref-target>`.
+
The exit status of the hook is ignored for any state except for the
"prepared" state. In the "prepared" state, a non-zero exit status will
cause the transaction to be aborted. The hook will not be called with
diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
index d71b199955..30b394ab47 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt
@@ -497,20 +497,18 @@ exclude;;
unusual refs.
[[def_pseudoref]]pseudoref::
- Pseudorefs are a class of files under `$GIT_DIR` which behave
- like refs for the purposes of rev-parse, but which are treated
- specially by git. Pseudorefs both have names that are all-caps,
- and always start with a line consisting of a
- <<def_SHA1,SHA-1>> followed by whitespace. So, HEAD is not a
- pseudoref, because it is sometimes a symbolic ref. They might
- optionally contain some additional data. `MERGE_HEAD` and
- `CHERRY_PICK_HEAD` are examples. Unlike
- <<def_per_worktree_ref,per-worktree refs>>, these files cannot
- be symbolic refs, and never have reflogs. They also cannot be
- updated through the normal ref update machinery. Instead,
- they are updated by directly writing to the files. However,
- they can be read as if they were refs, so `git rev-parse
- MERGE_HEAD` will work.
+ A ref that has different semantics than normal refs. These refs can be
+ read via normal Git commands, but cannot be written to by commands like
+ linkgit:git-update-ref[1].
++
+The following pseudorefs are known to Git:
+
+ - `FETCH_HEAD` is written by linkgit:git-fetch[1] or linkgit:git-pull[1]. It
+ may refer to multiple object IDs. Each object ID is annotated with metadata
+ indicating where it was fetched from and its fetch status.
+
+ - `MERGE_HEAD` is written by linkgit:git-merge[1] when resolving merge
+ conflicts. It contains all commit IDs which are being merged.
[[def_pull]]pull::
Pulling a <<def_branch,branch>> means to <<def_fetch,fetch>> it and
@@ -552,20 +550,38 @@ exclude;;
to the result.
[[def_ref]]ref::
- A name that begins with `refs/` (e.g. `refs/heads/master`)
- that points to an <<def_object_name,object name>> or another
- ref (the latter is called a <<def_symref,symbolic ref>>).
+ A name that that points to an <<def_object_name,object name>> or
+ another ref (the latter is called a <<def_symref,symbolic ref>>).
For convenience, a ref can sometimes be abbreviated when used
as an argument to a Git command; see linkgit:gitrevisions[7]
for details.
Refs are stored in the <<def_repository,repository>>.
+
The ref namespace is hierarchical.
-Different subhierarchies are used for different purposes (e.g. the
-`refs/heads/` hierarchy is used to represent local branches).
+Ref names must either start with `refs/` or be located in the root of
+the hierarchy. For the latter, their name must follow these rules:
++
+ - The name consists of only upper-case characters or underscores.
+
+ - The name ends with "`_HEAD`" or is equal to "`HEAD`".
+
-There are a few special-purpose refs that do not begin with `refs/`.
-The most notable example is `HEAD`.
+There are some irregular refs in the root of the hierarchy that do not
+match these rules. The following list is exhaustive and shall not be
+extended in the future:
++
+ - `AUTO_MERGE`
+
+ - `BISECT_EXPECTED_REV`
+
+ - `NOTES_MERGE_PARTIAL`
+
+ - `NOTES_MERGE_REF`
+
+ - `MERGE_AUTOSTASH`
++
+Different subhierarchies are used for different purposes. For example,
+the `refs/heads/` hierarchy is used to represent local branches whereas
+the `refs/tags/` hierarchy is used to represent local tags..
[[def_reflog]]reflog::
A reflog shows the local "history" of a ref. In other words,
@@ -576,7 +592,8 @@ The most notable example is `HEAD`.
[[def_refspec]]refspec::
A "refspec" is used by <<def_fetch,fetch>> and
<<def_push,push>> to describe the mapping between remote
- <<def_ref,ref>> and local ref.
+ <<def_ref,ref>> and local ref. See linkgit:git-fetch[1] or
+ linkgit:git-push[1] for details.
[[def_remote]]remote repository::
A <<def_repository,repository>> which is used to track the same
@@ -638,20 +655,6 @@ The most notable example is `HEAD`.
An <<def_object,object>> used to temporarily store the contents of a
<<def_dirty,dirty>> working directory and the index for future reuse.
-[[def_special_ref]]special ref::
- A ref that has different semantics than normal refs. These refs can be
- accessed via normal Git commands but may not behave the same as a
- normal ref in some cases.
-+
-The following special refs are known to Git:
-
- - "`FETCH_HEAD`" is written by linkgit:git-fetch[1] or linkgit:git-pull[1]. It
- may refer to multiple object IDs. Each object ID is annotated with metadata
- indicating where it was fetched from and its fetch status.
-
- - "`MERGE_HEAD`" is written by linkgit:git-merge[1] when resolving merge
- conflicts. It contains all commit IDs which are being merged.
-
[[def_submodule]]submodule::
A <<def_repository,repository>> that holds the history of a
separate project inside another repository (the latter of
diff --git a/Documentation/technical/bitmap-format.txt b/Documentation/technical/bitmap-format.txt
index f5d200939b..ed7edf9803 100644
--- a/Documentation/technical/bitmap-format.txt
+++ b/Documentation/technical/bitmap-format.txt
@@ -255,3 +255,208 @@ triplet is -
xor_row (4 byte integer, network byte order): ::
The position of the triplet whose bitmap is used to compress
this one, or `0xffffffff` if no such bitmap exists.
+
+Pseudo-merge bitmaps
+--------------------
+
+If the `BITMAP_OPT_PSEUDO_MERGES` flag is set, a variable number of
+bytes (preceding the name-hash cache, commit lookup table, and trailing
+checksum) of the `.bitmap` file is used to store pseudo-merge bitmaps.
+
+A "pseudo-merge bitmap" is used to refer to a pair of bitmaps, as
+follows:
+
+Commit bitmap::
+
+ A bitmap whose set bits describe the set of commits included in the
+ pseudo-merge's "merge" bitmap (as below).
+
+Merge bitmap::
+
+ A bitmap whose set bits describe the reachability closure over the set
+ of commits in the pseudo-merge's "commits" bitmap (as above). An
+ identical bitmap would be generated for an octopus merge with the same
+ set of parents as described in the commits bitmap.
+
+Pseudo-merge bitmaps can accelerate bitmap traversals when all commits
+for a given pseudo-merge are listed on either side of the traversal,
+either directly (by explicitly asking for them as part of the `HAVES`
+or `WANTS`) or indirectly (by encountering them during a fill-in
+traversal).
+
+=== Use-cases
+
+For example, suppose there exists a pseudo-merge bitmap with a large
+number of commits, all of which are listed in the `WANTS` section of
+some bitmap traversal query. When pseudo-merge bitmaps are enabled, the
+bitmap machinery can quickly determine there is a pseudo-merge which
+satisfies some subset of the wanted objects on either side of the query.
+Then, we can inflate the EWAH-compressed bitmap, and `OR` it in to the
+resulting bitmap. By contrast, without pseudo-merge bitmaps, we would
+have to repeat the decompression and `OR`-ing step over a potentially
+large number of individual bitmaps, which can take proportionally more
+time.
+
+Another benefit of pseudo-merges arises when there is some combination
+of (a) a large number of references, with (b) poor bitmap coverage, and
+(c) deep, nested trees, making fill-in traversal relatively expensive.
+For example, suppose that there are a large enough number of tags where
+bitmapping each of the tags individually is infeasible. Without
+pseudo-merge bitmaps, computing the result of, say, `git rev-list
+--use-bitmap-index --count --objects --tags` would likely require a
+large amount of fill-in traversal. But when a large quantity of those
+tags are stored together in a pseudo-merge bitmap, the bitmap machinery
+can take advantage of the fact that we only care about the union of
+objects reachable from all of those tags, and answer the query much
+faster.
+
+=== File format
+
+If enabled, pseudo-merge bitmaps are stored in an optional section at
+the end of a `.bitmap` file. The format is as follows:
+
+....
++-------------------------------------------+
+| .bitmap File |
++-------------------------------------------+
+| |
+| Pseudo-merge bitmaps (Variable Length) |
+| +---------------------------+ |
+| | commits_bitmap (EWAH) | |
+| +---------------------------+ |
+| | merge_bitmap (EWAH) | |
+| +---------------------------+ |
+| |
++-------------------------------------------+
+| |
+| Lookup Table |
+| +------------+--------------+ |
+| | commit_pos | offset | |
+| +------------+--------------+ |
+| | 4 bytes | 8 bytes | |
+| +------------+--------------+ |
+| |
+| Offset Cases: |
+| ------------- |
+| |
+| 1. MSB Unset: single pseudo-merge bitmap |
+| + offset to pseudo-merge bitmap |
+| |
+| 2. MSB Set: multiple pseudo-merges |
+| + offset to extended lookup table |
+| |
++-------------------------------------------+
+| |
+| Extended Lookup Table (Optional) |
+| |
+| +----+----------+----------+----------+ |
+| | N | Offset 1 | .... | Offset N | |
+| +----+----------+----------+----------+ |
+| | | 8 bytes | .... | 8 bytes | |
+| +----+----------+----------+----------+ |
+| |
++-------------------------------------------+
+| |
+| Pseudo-merge Metadata |
+| +------------------+----------------+ |
+| | # pseudo-merges | # Commits | |
+| +------------------+----------------+ |
+| | 4 bytes | 4 bytes | |
+| +------------------+----------------+ |
+| |
+| +------------------+----------------+ |
+| | Lookup offset | Extension size | |
+| +------------------+----------------+ |
+| | 8 bytes | 8 bytes | |
+| +------------------+----------------+ |
+| |
++-------------------------------------------+
+....
+
+* One or more pseudo-merge bitmaps, each containing:
+
+ ** `commits_bitmap`, an EWAH-compressed bitmap describing the set of
+ commits included in the this psuedo-merge.
+
+ ** `merge_bitmap`, an EWAH-compressed bitmap describing the union of
+ the set of objects reachable from all commits listed in the
+ `commits_bitmap`.
+
+* A lookup table, mapping pseudo-merged commits to the pseudo-merges
+ they belong to. Entries appear in increasing order of each commit's
+ bit position. Each entry is 12 bytes wide, and is comprised of the
+ following:
+
+ ** `commit_pos`, a 4-byte unsigned value (in network byte-order)
+ containing the bit position for this commit.
+
+ ** `offset`, an 8-byte unsigned value (also in network byte-order)
+ containing either one of two possible offsets, depending on whether or
+ not the most-significant bit is set.
+
+ *** If unset (i.e. `offset & ((uint64_t)1<<63) == 0`), the offset
+ (relative to the beginning of the `.bitmap` file) at which the
+ pseudo-merge bitmap for this commit can be read. This indicates
+ only a single pseudo-merge bitmap contains this commit.
+
+ *** If set (i.e. `offset & ((uint64_t)1<<63) != 0`), the offset
+ (again relative to the beginning of the `.bitmap` file) at which
+ the extended offset table can be located describing the set of
+ pseudo-merge bitmaps which contain this commit. This indicates
+ that multiple pseudo-merge bitmaps contain this commit.
+
+* An (optional) extended lookup table (written if and only if there is
+ at least one commit which appears in more than one pseudo-merge).
+ There are as many entries as commits which appear in multiple
+ pseudo-merges. Each entry contains the following:
+
+ ** `N`, a 4-byte unsigned value equal to the number of pseudo-merges
+ which contain a given commit.
+
+ ** An array of `N` 8-byte unsigned values, each of which is
+ interpreted as an offset (relative to the beginning of the
+ `.bitmap` file) at which a pseudo-merge bitmap for this commit can
+ be read. These values occur in no particular order.
+
+* Positions for all pseudo-merges, each stored as an 8-byte unsigned
+ value (in network byte-order) containing the offset (relative to the
+ beginnign of the `.bitmap` file) of each consecutive pseudo-merge.
+
+* A 4-byte unsigned value (in network byte-order) equal to the number of
+ pseudo-merges.
+
+* A 4-byte unsigned value (in network byte-order) equal to the number of
+ unique commits which appear in any pseudo-merge.
+
+* An 8-byte unsigned value (in network byte-order) equal to the number
+ of bytes between the start of the pseudo-merge section and the
+ beginning of the lookup table.
+
+* An 8-byte unsigned value (in network byte-order) equal to the number
+ of bytes in the pseudo-merge section (including this field).
+
+=== Pseudo-merge selection
+
+Pseudo-merge commits are selected among non-bitmapped commits at the
+tip of one or more reference(s). In addition, there are a handful of
+constraints to further refine this selection:
+
+`pack.bitmapPseudoMergeDecay`:: Defines the "decay rate", which
+corresponds to how quickly (or not) consecutive pseudo-merges decrease
+in size relative to one another.
+
+`pack.bitmapPseudoMergeGroups`:: Defines the maximum number of
+pseudo-merge groups.
+
+`pack.bitmapPseudoMergeSampleRate`:: Defines the percentage of commits
+(matching the above criteria) which are selected.
+
+`pack.bitmapPseudoMergeThreshold`:: Defines the minimum age of a commit
+in order to be considered for inclusion within one or more pseudo-merge
+bitmaps.
+
+The size of consecutive pseudo-merge groups decays according to a
+power-law decay function, where the size of the `n`-th group is `f(n) =
+C*n^-k`. The value of `C` is chosen accordingly to match the number of
+desired groups, and `k` is 1/100th of the value of
+`pack.bitmapPseudoMergeDecay`.
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index c92f98b3db..814cdcf95d 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.45.0-rc1
+DEF_VER=v2.45.GIT
LF='
'
diff --git a/Makefile b/Makefile
index 1e31acc72e..39c88225fc 100644
--- a/Makefile
+++ b/Makefile
@@ -409,6 +409,9 @@ include shared.mak
# to the "<name>" of the corresponding `compat/fsmonitor/fsm-settings-<name>.c`
# that implements the `fsm_os_settings__*()` routines.
#
+# Define LINK_FUZZ_PROGRAMS if you want `make all` to also build the fuzz test
+# programs in oss-fuzz/.
+#
# === Optional library: libintl ===
#
# Define NO_GETTEXT if you don't want Git output to be translated.
@@ -752,23 +755,6 @@ SCRIPTS = $(SCRIPT_SH_GEN) \
ETAGS_TARGET = TAGS
-# If you add a new fuzzer, please also make sure to run it in
-# ci/run-build-and-minimal-fuzzers.sh so that we make sure it still links and
-# runs in the future.
-FUZZ_OBJS += oss-fuzz/dummy-cmd-main.o
-FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o
-FUZZ_OBJS += oss-fuzz/fuzz-config.o
-FUZZ_OBJS += oss-fuzz/fuzz-date.o
-FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o
-FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o
-.PHONY: fuzz-objs
-fuzz-objs: $(FUZZ_OBJS)
-
-# Always build fuzz objects even if not testing, to prevent bit-rot.
-all:: $(FUZZ_OBJS)
-
-FUZZ_PROGRAMS += $(patsubst %.o,%,$(filter-out %dummy-cmd-main.o,$(FUZZ_OBJS)))
-
# Empty...
EXTRA_PROGRAMS =
@@ -808,6 +794,7 @@ TEST_BUILTINS_OBJS += test-dump-split-index.o
TEST_BUILTINS_OBJS += test-dump-untracked-cache.o
TEST_BUILTINS_OBJS += test-env-helper.o
TEST_BUILTINS_OBJS += test-example-decorate.o
+TEST_BUILTINS_OBJS += test-example-tap.o
TEST_BUILTINS_OBJS += test-find-pack.o
TEST_BUILTINS_OBJS += test-fsmonitor-client.o
TEST_BUILTINS_OBJS += test-genrandom.o
@@ -865,6 +852,7 @@ TEST_BUILTINS_OBJS += test-userdiff.o
TEST_BUILTINS_OBJS += test-wildmatch.o
TEST_BUILTINS_OBJS += test-windows-named-pipe.o
TEST_BUILTINS_OBJS += test-write-cache.o
+TEST_BUILTINS_OBJS += test-xgethostname.o
TEST_BUILTINS_OBJS += test-xml-encode.o
# Do not add more tests here unless they have extra dependencies. Add
@@ -1119,6 +1107,7 @@ LIB_OBJS += prompt.o
LIB_OBJS += protocol.o
LIB_OBJS += protocol-caps.o
LIB_OBJS += prune-packed.o
+LIB_OBJS += pseudo-merge.o
LIB_OBJS += quote.o
LIB_OBJS += range-diff.o
LIB_OBJS += reachable.o
@@ -1347,11 +1336,11 @@ THIRD_PARTY_SOURCES += compat/regex/%
THIRD_PARTY_SOURCES += sha1collisiondetection/%
THIRD_PARTY_SOURCES += sha1dc/%
-UNIT_TEST_PROGRAMS += t-basic
-UNIT_TEST_PROGRAMS += t-mem-pool
-UNIT_TEST_PROGRAMS += t-strbuf
UNIT_TEST_PROGRAMS += t-ctype
+UNIT_TEST_PROGRAMS += t-mem-pool
UNIT_TEST_PROGRAMS += t-prio-queue
+UNIT_TEST_PROGRAMS += t-strbuf
+UNIT_TEST_PROGRAMS += t-trailer
UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))
UNIT_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TEST_PROGRAMS))
UNIT_TEST_OBJS += $(UNIT_TEST_DIR)/test-lib.o
@@ -2373,6 +2362,29 @@ ifndef NO_TCLTK
endif
$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) SHELL_PATH='$(SHELL_PATH_SQ)' PERL_PATH='$(PERL_PATH_SQ)'
+# If you add a new fuzzer, please also make sure to run it in
+# ci/run-build-and-minimal-fuzzers.sh so that we make sure it still links and
+# runs in the future.
+FUZZ_OBJS += oss-fuzz/dummy-cmd-main.o
+FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o
+FUZZ_OBJS += oss-fuzz/fuzz-config.o
+FUZZ_OBJS += oss-fuzz/fuzz-date.o
+FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o
+FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o
+.PHONY: fuzz-objs
+fuzz-objs: $(FUZZ_OBJS)
+
+# Always build fuzz objects even if not testing, to prevent bit-rot.
+all:: $(FUZZ_OBJS)
+
+FUZZ_PROGRAMS += $(patsubst %.o,%,$(filter-out %dummy-cmd-main.o,$(FUZZ_OBJS)))
+
+# Build fuzz programs when possible, even without the necessary fuzzing support,
+# to prevent bit-rot.
+ifdef LINK_FUZZ_PROGRAMS
+all:: $(FUZZ_PROGRAMS)
+endif
+
please_set_SHELL_PATH_to_a_more_modern_shell:
@$$(:)
@@ -2656,7 +2668,6 @@ REFTABLE_OBJS += reftable/merged.o
REFTABLE_OBJS += reftable/pq.o
REFTABLE_OBJS += reftable/reader.o
REFTABLE_OBJS += reftable/record.o
-REFTABLE_OBJS += reftable/refname.o
REFTABLE_OBJS += reftable/generic.o
REFTABLE_OBJS += reftable/stack.o
REFTABLE_OBJS += reftable/tree.o
@@ -2669,7 +2680,6 @@ REFTABLE_TEST_OBJS += reftable/merged_test.o
REFTABLE_TEST_OBJS += reftable/pq_test.o
REFTABLE_TEST_OBJS += reftable/record_test.o
REFTABLE_TEST_OBJS += reftable/readwrite_test.o
-REFTABLE_TEST_OBJS += reftable/refname_test.o
REFTABLE_TEST_OBJS += reftable/stack_test.o
REFTABLE_TEST_OBJS += reftable/test_framework.o
REFTABLE_TEST_OBJS += reftable/tree_test.o
@@ -3228,7 +3238,7 @@ perf: all
.PRECIOUS: $(TEST_OBJS)
-t/helper/test-tool$X: $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
+t/helper/test-tool$X: $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS)) $(UNIT_TEST_DIR)/test-lib.o
t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS) $(REFTABLE_TEST_LIB)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS)
@@ -3858,22 +3868,22 @@ cover_db_html: cover_db
#
# An example command to build against libFuzzer from LLVM 11.0.0:
#
-# make CC=clang CXX=clang++ \
+# make CC=clang FUZZ_CXX=clang++ \
# CFLAGS="-fsanitize=fuzzer-no-link,address" \
# LIB_FUZZING_ENGINE="-fsanitize=fuzzer,address" \
# fuzz-all
#
+FUZZ_CXX ?= $(CC)
FUZZ_CXXFLAGS ?= $(ALL_CFLAGS)
.PHONY: fuzz-all
+fuzz-all: $(FUZZ_PROGRAMS)
$(FUZZ_PROGRAMS): %: %.o oss-fuzz/dummy-cmd-main.o $(GITLIBS) GIT-LDFLAGS
- $(QUIET_LINK)$(CXX) $(FUZZ_CXXFLAGS) -o $@ $(ALL_LDFLAGS) \
+ $(QUIET_LINK)$(FUZZ_CXX) $(FUZZ_CXXFLAGS) -o $@ $(ALL_LDFLAGS) \
-Wl,--allow-multiple-definition \
$(filter %.o,$^) $(filter %.a,$^) $(LIBS) $(LIB_FUZZING_ENGINE)
-fuzz-all: $(FUZZ_PROGRAMS)
-
$(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o $(UNIT_TEST_DIR)/test-lib.o $(GITLIBS) GIT-LDFLAGS
$(call mkdir_p_parent_template)
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
@@ -3881,5 +3891,5 @@ $(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o $(UNIT_TEST_DIR)/
.PHONY: build-unit-tests unit-tests
build-unit-tests: $(UNIT_TEST_PROGS)
-unit-tests: $(UNIT_TEST_PROGS)
+unit-tests: $(UNIT_TEST_PROGS) t/helper/test-tool$X
$(MAKE) -C t/ unit-tests
diff --git a/RelNotes b/RelNotes
index ae70277109..cc696fc869 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.45.0.txt \ No newline at end of file
+Documentation/RelNotes/2.46.0.txt \ No newline at end of file
diff --git a/add-interactive.c b/add-interactive.c
index 6bf87e7ae7..b5d6cd689a 100644
--- a/add-interactive.c
+++ b/add-interactive.c
@@ -532,8 +532,9 @@ static int get_modified_files(struct repository *r,
size_t *binary_count)
{
struct object_id head_oid;
- int is_initial = !resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
- &head_oid, NULL);
+ int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ "HEAD", RESOLVE_REF_READING,
+ &head_oid, NULL);
struct collection_status s = { 0 };
int i;
@@ -761,8 +762,10 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps,
size_t count, i, j;
struct object_id oid;
- int is_initial = !resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &oid,
- NULL);
+ int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ "HEAD", RESOLVE_REF_READING,
+ &oid,
+ NULL);
struct lock_file index_lock;
const char **paths;
struct tree *tree;
@@ -865,6 +868,7 @@ static int get_untracked_files(struct repository *r,
}
strbuf_release(&buf);
+ dir_clear(&dir);
return 0;
}
@@ -989,8 +993,10 @@ static int run_diff(struct add_i_state *s, const struct pathspec *ps,
ssize_t count, i;
struct object_id oid;
- int is_initial = !resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &oid,
- NULL);
+ int is_initial = !refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ "HEAD", RESOLVE_REF_READING,
+ &oid,
+ NULL);
if (get_modified_files(s->r, INDEX_ONLY, files, ps, NULL, NULL) < 0)
return -1;
diff --git a/add-patch.c b/add-patch.c
index a06dd18985..2252895c28 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -293,10 +293,9 @@ static void err(struct add_p_state *s, const char *fmt, ...)
va_list args;
va_start(args, fmt);
- fputs(s->s.error_color, stderr);
- vfprintf(stderr, fmt, args);
- fputs(s->s.reset_color, stderr);
- fputc('\n', stderr);
+ fputs(s->s.error_color, stdout);
+ vprintf(fmt, args);
+ puts(s->s.reset_color);
va_end(args);
}
@@ -1326,7 +1325,7 @@ static int apply_for_checkout(struct add_p_state *s, struct strbuf *diff,
err(s, _("Nothing was applied.\n"));
} else
/* As a last resort, show the diff to the user */
- fwrite(diff->buf, diff->len, 1, stderr);
+ fwrite(diff->buf, diff->len, 1, stdout);
return 0;
}
@@ -1646,6 +1645,7 @@ soft_increment:
err(s, _("No hunk matches the given pattern"));
break;
}
+ regfree(&regex);
hunk_index = i;
} else if (s->answer.buf[0] == 's') {
size_t splittable_into = hunk->splittable_into;
@@ -1667,7 +1667,7 @@ soft_increment:
}
} else if (s->answer.buf[0] == 'p') {
rendered_hunk_index = -1;
- } else {
+ } else if (s->answer.buf[0] == '?') {
const char *p = _(help_patch_remainder), *eol = p;
color_fprintf(stdout, s->s.help_color, "%s",
@@ -1691,6 +1691,9 @@ soft_increment:
color_fprintf_ln(stdout, s->s.help_color,
"%.*s", (int)(eol - p), p);
}
+ } else {
+ err(s, _("Unknown command '%s' (use '?' for help)"),
+ s->answer.buf);
}
}
@@ -1777,9 +1780,9 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
break;
if (s.file_diff_nr == 0)
- fprintf(stderr, _("No changes.\n"));
+ err(&s, _("No changes."));
else if (binary_count == s.file_diff_nr)
- fprintf(stderr, _("Only binary files changed.\n"));
+ err(&s, _("Only binary files changed."));
add_p_state_clear(&s);
return 0;
diff --git a/advice.c b/advice.c
index 75111191ad..0a122c2020 100644
--- a/advice.c
+++ b/advice.c
@@ -2,6 +2,7 @@
#include "advice.h"
#include "config.h"
#include "color.h"
+#include "environment.h"
#include "gettext.h"
#include "help.h"
#include "string-list.h"
@@ -127,6 +128,12 @@ void advise(const char *advice, ...)
int advice_enabled(enum advice_type type)
{
int enabled = advice_setting[type].level != ADVICE_LEVEL_DISABLED;
+ static int globally_enabled = -1;
+
+ if (globally_enabled < 0)
+ globally_enabled = git_env_bool(GIT_ADVICE_ENVIRONMENT, 1);
+ if (!globally_enabled)
+ return 0;
if (type == ADVICE_PUSH_UPDATE_REJECTED)
return enabled &&
diff --git a/apply.c b/apply.c
index 757009a39e..901b67e625 100644
--- a/apply.c
+++ b/apply.c
@@ -3712,8 +3712,10 @@ static int apply_data(struct apply_state *state, struct patch *patch,
fprintf(stderr, _("Falling back to direct application...\n"));
/* Note: with --reject, apply_fragments() returns 0 */
- if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0)
+ if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0) {
+ clear_image(&image);
return -1;
+ }
}
patch->result = image.buf;
patch->resultsize = image.len;
diff --git a/attr.c b/attr.c
index 679e42258c..f3dd2de12d 100644
--- a/attr.c
+++ b/attr.c
@@ -765,8 +765,8 @@ static struct attr_stack *read_attr_from_file(const char *path, unsigned flags)
return res;
}
-static struct attr_stack *read_attr_from_buf(char *buf, const char *path,
- unsigned flags)
+static struct attr_stack *read_attr_from_buf(char *buf, size_t length,
+ const char *path, unsigned flags)
{
struct attr_stack *res;
char *sp;
@@ -774,6 +774,11 @@ static struct attr_stack *read_attr_from_buf(char *buf, const char *path,
if (!buf)
return NULL;
+ if (length >= ATTR_MAX_FILE_SIZE) {
+ warning(_("ignoring overly large gitattributes blob '%s'"), path);
+ free(buf);
+ return NULL;
+ }
CALLOC_ARRAY(res, 1);
for (sp = buf; *sp;) {
@@ -813,7 +818,7 @@ static struct attr_stack *read_attr_from_blob(struct index_state *istate,
return NULL;
}
- return read_attr_from_buf(buf, path, flags);
+ return read_attr_from_buf(buf, sz, path, flags);
}
static struct attr_stack *read_attr_from_index(struct index_state *istate,
@@ -860,13 +865,7 @@ static struct attr_stack *read_attr_from_index(struct index_state *istate,
stack = read_attr_from_blob(istate, &istate->cache[sparse_dir_pos]->oid, relative_path, flags);
} else {
buf = read_blob_data_from_index(istate, path, &size);
- if (!buf)
- return NULL;
- if (size >= ATTR_MAX_FILE_SIZE) {
- warning(_("ignoring overly large gitattributes blob '%s'"), path);
- return NULL;
- }
- stack = read_attr_from_buf(buf, path, flags);
+ stack = read_attr_from_buf(buf, size, path, flags);
}
return stack;
}
@@ -1206,15 +1205,16 @@ static void collect_some_attrs(struct index_state *istate,
}
static const char *default_attr_source_tree_object_name;
-static int ignore_bad_attr_tree;
void set_git_attr_source(const char *tree_object_name)
{
default_attr_source_tree_object_name = xstrdup(tree_object_name);
}
-static void compute_default_attr_source(struct object_id *attr_source)
+static int compute_default_attr_source(struct object_id *attr_source)
{
+ int ignore_bad_attr_tree = 0;
+
if (!default_attr_source_tree_object_name)
default_attr_source_tree_object_name = getenv(GIT_ATTR_SOURCE_ENVIRONMENT);
@@ -1223,29 +1223,34 @@ static void compute_default_attr_source(struct object_id *attr_source)
ignore_bad_attr_tree = 1;
}
- if (!default_attr_source_tree_object_name &&
- startup_info->have_repository &&
- is_bare_repository()) {
- default_attr_source_tree_object_name = "HEAD";
- ignore_bad_attr_tree = 1;
- }
+ if (!default_attr_source_tree_object_name)
+ return 0;
- if (!default_attr_source_tree_object_name || !is_null_oid(attr_source))
- return;
+ if (!startup_info->have_repository) {
+ if (!ignore_bad_attr_tree)
+ die(_("cannot use --attr-source or GIT_ATTR_SOURCE without repo"));
+ return 0;
+ }
if (repo_get_oid_treeish(the_repository,
default_attr_source_tree_object_name,
- attr_source) && !ignore_bad_attr_tree)
- die(_("bad --attr-source or GIT_ATTR_SOURCE"));
+ attr_source)) {
+ if (!ignore_bad_attr_tree)
+ die(_("bad --attr-source or GIT_ATTR_SOURCE"));
+ return 0;
+ }
+
+ return 1;
}
static struct object_id *default_attr_source(void)
{
static struct object_id attr_source;
+ static int has_attr_source = -1;
- if (is_null_oid(&attr_source))
- compute_default_attr_source(&attr_source);
- if (is_null_oid(&attr_source))
+ if (has_attr_source < 0)
+ has_attr_source = compute_default_attr_source(&attr_source);
+ if (!has_attr_source)
return NULL;
return &attr_source;
}
diff --git a/bisect.c b/bisect.c
index 29aae879b8..4ea703bec1 100644
--- a/bisect.c
+++ b/bisect.c
@@ -469,7 +469,8 @@ static int register_ref(const char *refname, const struct object_id *oid,
static int read_bisect_refs(void)
{
- return for_each_ref_in("refs/bisect/", register_ref, NULL);
+ return refs_for_each_ref_in(get_main_ref_store(the_repository),
+ "refs/bisect/", register_ref, NULL);
}
static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
@@ -709,7 +710,7 @@ static enum bisect_error error_if_skipped_commits(struct commit_list *tried,
static int is_expected_rev(const struct object_id *oid)
{
struct object_id expected_oid;
- if (read_ref("BISECT_EXPECTED_REV", &expected_oid))
+ if (refs_read_ref(get_main_ref_store(the_repository), "BISECT_EXPECTED_REV", &expected_oid))
return 0;
return oideq(oid, &expected_oid);
}
@@ -721,11 +722,14 @@ enum bisect_error bisect_checkout(const struct object_id *bisect_rev,
struct pretty_print_context pp = {0};
struct strbuf commit_msg = STRBUF_INIT;
- update_ref(NULL, "BISECT_EXPECTED_REV", bisect_rev, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), NULL,
+ "BISECT_EXPECTED_REV", bisect_rev, NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
if (no_checkout) {
- update_ref(NULL, "BISECT_HEAD", bisect_rev, NULL, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), NULL,
+ "BISECT_HEAD", bisect_rev, NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
} else {
struct child_process cmd = CHILD_PROCESS_INIT;
@@ -1027,7 +1031,8 @@ enum bisect_error bisect_next_all(struct repository *r, const char *prefix)
* If no_checkout is non-zero, the bisection process does not
* checkout the trial commit but instead simply updates BISECT_HEAD.
*/
- int no_checkout = ref_exists("BISECT_HEAD");
+ int no_checkout = refs_ref_exists(get_main_ref_store(the_repository),
+ "BISECT_HEAD");
unsigned bisect_flags = 0;
read_bisect_terms(&term_bad, &term_good);
@@ -1178,10 +1183,14 @@ int bisect_clean_state(void)
/* There may be some refs packed during bisection */
struct string_list refs_for_removal = STRING_LIST_INIT_NODUP;
- for_each_ref_in("refs/bisect", mark_for_removal, (void *) &refs_for_removal);
+ refs_for_each_ref_in(get_main_ref_store(the_repository),
+ "refs/bisect", mark_for_removal,
+ (void *) &refs_for_removal);
string_list_append(&refs_for_removal, xstrdup("BISECT_HEAD"));
string_list_append(&refs_for_removal, xstrdup("BISECT_EXPECTED_REV"));
- result = delete_refs("bisect: remove", &refs_for_removal, REF_NO_DEREF);
+ result = refs_delete_refs(get_main_ref_store(the_repository),
+ "bisect: remove", &refs_for_removal,
+ REF_NO_DEREF);
refs_for_removal.strdup_strings = 1;
string_list_clear(&refs_for_removal, 0);
unlink_or_warn(git_path_bisect_ancestors_ok());
diff --git a/blame.c b/blame.c
index 1a16d4eb6a..33586b9777 100644
--- a/blame.c
+++ b/blame.c
@@ -2700,7 +2700,7 @@ static struct commit *dwim_reverse_initial(struct rev_info *revs,
return NULL;
/* Do we have HEAD? */
- if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL))
+ if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", RESOLVE_REF_READING, &head_oid, NULL))
return NULL;
head_commit = lookup_commit_reference_gently(revs->repo,
&head_oid, 1);
@@ -2803,7 +2803,7 @@ void setup_scoreboard(struct blame_scoreboard *sb,
if (sb->final) {
parent_oid = &sb->final->object.oid;
} else {
- if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL))
+ if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", RESOLVE_REF_READING, &head_oid, NULL))
die("no such ref: HEAD");
parent_oid = &head_oid;
}
diff --git a/bloom.c b/bloom.c
index e529f7605c..d080a1b616 100644
--- a/bloom.c
+++ b/bloom.c
@@ -6,6 +6,9 @@
#include "commit-graph.h"
#include "commit.h"
#include "commit-slab.h"
+#include "tree.h"
+#include "tree-walk.h"
+#include "config.h"
define_commit_slab(bloom_filter_slab, struct bloom_filter);
@@ -48,9 +51,9 @@ static int check_bloom_offset(struct commit_graph *g, uint32_t pos,
return -1;
}
-static int load_bloom_filter_from_graph(struct commit_graph *g,
- struct bloom_filter *filter,
- uint32_t graph_pos)
+int load_bloom_filter_from_graph(struct commit_graph *g,
+ struct bloom_filter *filter,
+ uint32_t graph_pos)
{
uint32_t lex_pos, start_index, end_index;
@@ -88,6 +91,8 @@ static int load_bloom_filter_from_graph(struct commit_graph *g,
filter->data = (unsigned char *)(g->chunk_bloom_data +
sizeof(unsigned char) * start_index +
BLOOMDATA_CHUNK_HEADER_SIZE);
+ filter->version = g->bloom_filter_settings->hash_version;
+ filter->to_free = NULL;
return 1;
}
@@ -99,7 +104,64 @@ static int load_bloom_filter_from_graph(struct commit_graph *g,
* Not considered to be cryptographically secure.
* Implemented as described in https://en.wikipedia.org/wiki/MurmurHash#Algorithm
*/
-uint32_t murmur3_seeded(uint32_t seed, const char *data, size_t len)
+uint32_t murmur3_seeded_v2(uint32_t seed, const char *data, size_t len)
+{
+ const uint32_t c1 = 0xcc9e2d51;
+ const uint32_t c2 = 0x1b873593;
+ const uint32_t r1 = 15;
+ const uint32_t r2 = 13;
+ const uint32_t m = 5;
+ const uint32_t n = 0xe6546b64;
+ int i;
+ uint32_t k1 = 0;
+ const char *tail;
+
+ int len4 = len / sizeof(uint32_t);
+
+ uint32_t k;
+ for (i = 0; i < len4; i++) {
+ uint32_t byte1 = (uint32_t)(unsigned char)data[4*i];
+ uint32_t byte2 = ((uint32_t)(unsigned char)data[4*i + 1]) << 8;
+ uint32_t byte3 = ((uint32_t)(unsigned char)data[4*i + 2]) << 16;
+ uint32_t byte4 = ((uint32_t)(unsigned char)data[4*i + 3]) << 24;
+ k = byte1 | byte2 | byte3 | byte4;
+ k *= c1;
+ k = rotate_left(k, r1);
+ k *= c2;
+
+ seed ^= k;
+ seed = rotate_left(seed, r2) * m + n;
+ }
+
+ tail = (data + len4 * sizeof(uint32_t));
+
+ switch (len & (sizeof(uint32_t) - 1)) {
+ case 3:
+ k1 ^= ((uint32_t)(unsigned char)tail[2]) << 16;
+ /*-fallthrough*/
+ case 2:
+ k1 ^= ((uint32_t)(unsigned char)tail[1]) << 8;
+ /*-fallthrough*/
+ case 1:
+ k1 ^= ((uint32_t)(unsigned char)tail[0]) << 0;
+ k1 *= c1;
+ k1 = rotate_left(k1, r1);
+ k1 *= c2;
+ seed ^= k1;
+ break;
+ }
+
+ seed ^= (uint32_t)len;
+ seed ^= (seed >> 16);
+ seed *= 0x85ebca6b;
+ seed ^= (seed >> 13);
+ seed *= 0xc2b2ae35;
+ seed ^= (seed >> 16);
+
+ return seed;
+}
+
+static uint32_t murmur3_seeded_v1(uint32_t seed, const char *data, size_t len)
{
const uint32_t c1 = 0xcc9e2d51;
const uint32_t c2 = 0x1b873593;
@@ -164,8 +226,14 @@ void fill_bloom_key(const char *data,
int i;
const uint32_t seed0 = 0x293ae76f;
const uint32_t seed1 = 0x7e646e2c;
- const uint32_t hash0 = murmur3_seeded(seed0, data, len);
- const uint32_t hash1 = murmur3_seeded(seed1, data, len);
+ uint32_t hash0, hash1;
+ if (settings->hash_version == 2) {
+ hash0 = murmur3_seeded_v2(seed0, data, len);
+ hash1 = murmur3_seeded_v2(seed1, data, len);
+ } else {
+ hash0 = murmur3_seeded_v1(seed0, data, len);
+ hash1 = murmur3_seeded_v1(seed1, data, len);
+ }
key->hashes = (uint32_t *)xcalloc(settings->num_hashes, sizeof(uint32_t));
for (i = 0; i < settings->num_hashes; i++)
@@ -197,6 +265,18 @@ void init_bloom_filters(void)
init_bloom_filter_slab(&bloom_filters);
}
+static void free_one_bloom_filter(struct bloom_filter *filter)
+{
+ if (!filter)
+ return;
+ free(filter->to_free);
+}
+
+void deinit_bloom_filters(void)
+{
+ deep_clear_bloom_filter_slab(&bloom_filters, free_one_bloom_filter);
+}
+
static int pathmap_cmp(const void *hashmap_cmp_fn_data UNUSED,
const struct hashmap_entry *eptr,
const struct hashmap_entry *entry_or_key,
@@ -210,11 +290,97 @@ static int pathmap_cmp(const void *hashmap_cmp_fn_data UNUSED,
return strcmp(e1->path, e2->path);
}
-static void init_truncated_large_filter(struct bloom_filter *filter)
+static void init_truncated_large_filter(struct bloom_filter *filter,
+ int version)
{
- filter->data = xmalloc(1);
+ filter->data = filter->to_free = xmalloc(1);
filter->data[0] = 0xFF;
filter->len = 1;
+ filter->version = version;
+}
+
+#define VISITED (1u<<21)
+#define HIGH_BITS (1u<<22)
+
+static int has_entries_with_high_bit(struct repository *r, struct tree *t)
+{
+ if (parse_tree(t))
+ return 1;
+
+ if (!(t->object.flags & VISITED)) {
+ struct tree_desc desc;
+ struct name_entry entry;
+
+ init_tree_desc(&desc, &t->object.oid, t->buffer, t->size);
+ while (tree_entry(&desc, &entry)) {
+ size_t i;
+ for (i = 0; i < entry.pathlen; i++) {
+ if (entry.path[i] & 0x80) {
+ t->object.flags |= HIGH_BITS;
+ goto done;
+ }
+ }
+
+ if (S_ISDIR(entry.mode)) {
+ struct tree *sub = lookup_tree(r, &entry.oid);
+ if (sub && has_entries_with_high_bit(r, sub)) {
+ t->object.flags |= HIGH_BITS;
+ goto done;
+ }
+ }
+
+ }
+
+done:
+ t->object.flags |= VISITED;
+ }
+
+ return !!(t->object.flags & HIGH_BITS);
+}
+
+static int commit_tree_has_high_bit_paths(struct repository *r,
+ struct commit *c)
+{
+ struct tree *t;
+ if (repo_parse_commit(r, c))
+ return 1;
+ t = repo_get_commit_tree(r, c);
+ if (!t)
+ return 1;
+ return has_entries_with_high_bit(r, t);
+}
+
+static struct bloom_filter *upgrade_filter(struct repository *r, struct commit *c,
+ struct bloom_filter *filter,
+ int hash_version)
+{
+ struct commit_list *p = c->parents;
+ if (commit_tree_has_high_bit_paths(r, c))
+ return NULL;
+
+ if (p && commit_tree_has_high_bit_paths(r, p->item))
+ return NULL;
+
+ filter->version = hash_version;
+
+ return filter;
+}
+
+struct bloom_filter *get_bloom_filter(struct repository *r, struct commit *c)
+{
+ struct bloom_filter *filter;
+ int hash_version;
+
+ filter = get_or_compute_bloom_filter(r, c, 0, NULL, NULL);
+ if (!filter)
+ return NULL;
+
+ prepare_repo_settings(r);
+ hash_version = r->settings.commit_graph_changed_paths_version;
+
+ if (!(hash_version == -1 || hash_version == filter->version))
+ return NULL; /* unusable filter */
+ return filter;
}
struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
@@ -242,8 +408,23 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
filter, graph_pos);
}
- if (filter->data && filter->len)
- return filter;
+ if (filter->data && filter->len) {
+ struct bloom_filter *upgrade;
+ if (!settings || settings->hash_version == filter->version)
+ return filter;
+
+ /* version mismatch, see if we can upgrade */
+ if (compute_if_not_present &&
+ git_env_bool("GIT_TEST_UPGRADE_BLOOM_FILTERS", 1)) {
+ upgrade = upgrade_filter(r, c, filter,
+ settings->hash_version);
+ if (upgrade) {
+ if (computed)
+ *computed |= BLOOM_UPGRADED;
+ return upgrade;
+ }
+ }
+ }
if (!compute_if_not_present)
return NULL;
@@ -299,19 +480,22 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
}
if (hashmap_get_size(&pathmap) > settings->max_changed_paths) {
- init_truncated_large_filter(filter);
+ init_truncated_large_filter(filter,
+ settings->hash_version);
if (computed)
*computed |= BLOOM_TRUNC_LARGE;
goto cleanup;
}
filter->len = (hashmap_get_size(&pathmap) * settings->bits_per_entry + BITS_PER_WORD - 1) / BITS_PER_WORD;
+ filter->version = settings->hash_version;
if (!filter->len) {
if (computed)
*computed |= BLOOM_TRUNC_EMPTY;
filter->len = 1;
}
CALLOC_ARRAY(filter->data, filter->len);
+ filter->to_free = filter->data;
hashmap_for_each_entry(&pathmap, &iter, e, entry) {
struct bloom_key key;
@@ -325,7 +509,7 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
} else {
for (i = 0; i < diff_queued_diff.nr; i++)
diff_free_filepair(diff_queued_diff.queue[i]);
- init_truncated_large_filter(filter);
+ init_truncated_large_filter(filter, settings->hash_version);
if (computed)
*computed |= BLOOM_TRUNC_LARGE;
diff --git a/bloom.h b/bloom.h
index adde6dfe21..d20e64bfbb 100644
--- a/bloom.h
+++ b/bloom.h
@@ -3,13 +3,16 @@
struct commit;
struct repository;
+struct commit_graph;
struct bloom_filter_settings {
/*
* The version of the hashing technique being used.
- * We currently only support version = 1 which is
+ * The newest version is 2, which is
* the seeded murmur3 hashing technique implemented
- * in bloom.c.
+ * in bloom.c. Bloom filters of version 1 were created
+ * with prior versions of Git, which had a bug in the
+ * implementation of the hash function.
*/
uint32_t hash_version;
@@ -52,6 +55,9 @@ struct bloom_filter_settings {
struct bloom_filter {
unsigned char *data;
size_t len;
+ int version;
+
+ void *to_free;
};
/*
@@ -68,6 +74,10 @@ struct bloom_key {
uint32_t *hashes;
};
+int load_bloom_filter_from_graph(struct commit_graph *g,
+ struct bloom_filter *filter,
+ uint32_t graph_pos);
+
/*
* Calculate the murmur3 32-bit hash value for the given data
* using the given seed.
@@ -75,7 +85,7 @@ struct bloom_key {
* Not considered to be cryptographically secure.
* Implemented as described in https://en.wikipedia.org/wiki/MurmurHash#Algorithm
*/
-uint32_t murmur3_seeded(uint32_t seed, const char *data, size_t len);
+uint32_t murmur3_seeded_v2(uint32_t seed, const char *data, size_t len);
void fill_bloom_key(const char *data,
size_t len,
@@ -88,12 +98,14 @@ void add_key_to_filter(const struct bloom_key *key,
const struct bloom_filter_settings *settings);
void init_bloom_filters(void);
+void deinit_bloom_filters(void);
enum bloom_filter_computed {
BLOOM_NOT_COMPUTED = (1 << 0),
BLOOM_COMPUTED = (1 << 1),
BLOOM_TRUNC_LARGE = (1 << 2),
BLOOM_TRUNC_EMPTY = (1 << 3),
+ BLOOM_UPGRADED = (1 << 4),
};
struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
@@ -102,8 +114,24 @@ struct bloom_filter *get_or_compute_bloom_filter(struct repository *r,
const struct bloom_filter_settings *settings,
enum bloom_filter_computed *computed);
-#define get_bloom_filter(r, c) get_or_compute_bloom_filter( \
- (r), (c), 0, NULL, NULL)
+/*
+ * Find the Bloom filter associated with the given commit "c".
+ *
+ * If any of the following are true
+ *
+ * - the repository does not have a commit-graph, or
+ * - the repository disables reading from the commit-graph, or
+ * - the given commit does not have a Bloom filter computed, or
+ * - there is a Bloom filter for commit "c", but it cannot be read
+ * because the filter uses an incompatible version of murmur3
+ *
+ * , then `get_bloom_filter()` will return NULL. Otherwise, the corresponding
+ * Bloom filter will be returned.
+ *
+ * For callers who wish to inspect Bloom filters with incompatible hash
+ * versions, use get_or_compute_bloom_filter().
+ */
+struct bloom_filter *get_bloom_filter(struct repository *r, struct commit *c);
int bloom_filter_contains(const struct bloom_filter *filter,
const struct bloom_key *key,
diff --git a/branch.c b/branch.c
index e4a738fc7b..df5d24fec6 100644
--- a/branch.c
+++ b/branch.c
@@ -377,7 +377,7 @@ int validate_branchname(const char *name, struct strbuf *ref)
exit(code);
}
- return ref_exists(ref->buf);
+ return refs_ref_exists(get_main_ref_store(the_repository), ref->buf);
}
static int initialized_checked_out_branches;
@@ -623,11 +623,12 @@ void create_branch(struct repository *r,
msg = xstrfmt("branch: Reset to %s", start_name);
else
msg = xstrfmt("branch: Created from %s", start_name);
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction ||
ref_transaction_update(transaction, ref.buf,
&oid, forcing ? NULL : null_oid(),
- 0, msg, &err) ||
+ NULL, NULL, 0, msg, &err) ||
ref_transaction_commit(transaction, &err))
die("%s", err.buf);
ref_transaction_free(transaction);
diff --git a/builtin/add.c b/builtin/add.c
index ae723bc85e..3dfcfc5fba 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2006 Linus Torvalds
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "advice.h"
#include "config.h"
@@ -40,20 +40,20 @@ static int chmod_pathspec(struct pathspec *pathspec, char flip, int show_only)
{
int i, ret = 0;
- for (i = 0; i < the_index.cache_nr; i++) {
- struct cache_entry *ce = the_index.cache[i];
+ for (i = 0; i < the_repository->index->cache_nr; i++) {
+ struct cache_entry *ce = the_repository->index->cache[i];
int err;
if (!include_sparse &&
(ce_skip_worktree(ce) ||
- !path_in_sparse_checkout(ce->name, &the_index)))
+ !path_in_sparse_checkout(ce->name, the_repository->index)))
continue;
- if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
+ if (pathspec && !ce_path_match(the_repository->index, ce, pathspec, NULL))
continue;
if (!show_only)
- err = chmod_index_entry(&the_index, ce, flip);
+ err = chmod_index_entry(the_repository->index, ce, flip);
else
err = S_ISREG(ce->ce_mode) ? 0 : -1;
@@ -68,20 +68,20 @@ static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
{
int i, retval = 0;
- for (i = 0; i < the_index.cache_nr; i++) {
- struct cache_entry *ce = the_index.cache[i];
+ for (i = 0; i < the_repository->index->cache_nr; i++) {
+ struct cache_entry *ce = the_repository->index->cache[i];
if (!include_sparse &&
(ce_skip_worktree(ce) ||
- !path_in_sparse_checkout(ce->name, &the_index)))
+ !path_in_sparse_checkout(ce->name, the_repository->index)))
continue;
if (ce_stage(ce))
continue; /* do not touch unmerged paths */
if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
continue; /* do not touch non blobs */
- if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
+ if (pathspec && !ce_path_match(the_repository->index, ce, pathspec, NULL))
continue;
- retval |= add_file_to_index(&the_index, ce->name,
+ retval |= add_file_to_index(the_repository->index, ce->name,
flags | ADD_CACHE_RENORMALIZE);
}
@@ -100,11 +100,11 @@ static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec,
i = dir->nr;
while (--i >= 0) {
struct dir_entry *entry = *src++;
- if (dir_path_match(&the_index, entry, pathspec, prefix, seen))
+ if (dir_path_match(the_repository->index, entry, pathspec, prefix, seen))
*dst++ = entry;
}
dir->nr = dst - dir->entries;
- add_pathspec_matches_against_index(pathspec, &the_index, seen,
+ add_pathspec_matches_against_index(pathspec, the_repository->index, seen,
PS_IGNORE_SKIP_WORKTREE);
return seen;
}
@@ -119,14 +119,14 @@ static int refresh(int verbose, const struct pathspec *pathspec)
(verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET);
seen = xcalloc(pathspec->nr, 1);
- refresh_index(&the_index, flags, pathspec, seen,
+ refresh_index(the_repository->index, flags, pathspec, seen,
_("Unstaged changes after refreshing the index:"));
for (i = 0; i < pathspec->nr; i++) {
if (!seen[i]) {
const char *path = pathspec->items[i].original;
if (matches_skip_worktree(pathspec, i, &skip_worktree_seen) ||
- !path_in_sparse_checkout(path, &the_index)) {
+ !path_in_sparse_checkout(path, the_repository->index)) {
string_list_append(&only_match_skip_worktree,
pathspec->items[i].original);
} else {
@@ -150,7 +150,7 @@ static int refresh(int verbose, const struct pathspec *pathspec)
int interactive_add(const char **argv, const char *prefix, int patch)
{
struct pathspec pathspec;
- int unused;
+ int unused, ret;
if (!git_config_get_bool("add.interactive.usebuiltin", &unused))
warning(_("the add.interactive.useBuiltin setting has been removed!\n"
@@ -163,9 +163,12 @@ int interactive_add(const char **argv, const char *prefix, int patch)
prefix, argv);
if (patch)
- return !!run_add_p(the_repository, ADD_P_ADD, NULL, &pathspec);
+ ret = !!run_add_p(the_repository, ADD_P_ADD, NULL, &pathspec);
else
- return !!run_add_i(the_repository, &pathspec);
+ ret = !!run_add_i(the_repository, &pathspec);
+
+ clear_pathspec(&pathspec);
+ return ret;
}
static int edit_patch(int argc, const char **argv, const char *prefix)
@@ -335,12 +338,12 @@ static int add_files(struct dir_struct *dir, int flags)
for (i = 0; i < dir->nr; i++) {
if (!include_sparse &&
- !path_in_sparse_checkout(dir->entries[i]->name, &the_index)) {
+ !path_in_sparse_checkout(dir->entries[i]->name, the_repository->index)) {
string_list_append(&matched_sparse_paths,
dir->entries[i]->name);
continue;
}
- if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
+ if (add_file_to_index(the_repository->index, dir->entries[i]->name, flags)) {
if (!ignore_add_errors)
die(_("adding files failed"));
exit_status = 1;
@@ -458,8 +461,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
if (repo_read_index_preload(the_repository, &pathspec, 0) < 0)
die(_("index file corrupt"));
- die_in_unpopulated_submodule(&the_index, prefix);
- die_path_inside_submodule(&the_index, &pathspec);
+ die_in_unpopulated_submodule(the_repository->index, prefix);
+ die_path_inside_submodule(the_repository->index, &pathspec);
if (add_new_files) {
int baselen;
@@ -471,7 +474,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
}
/* This picks up the paths that are not tracked */
- baselen = fill_directory(&dir, &the_index, &pathspec);
+ baselen = fill_directory(&dir, the_repository->index, &pathspec);
if (pathspec.nr)
seen = prune_directory(&dir, &pathspec, baselen);
}
@@ -488,7 +491,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
if (!seen)
seen = find_pathspecs_matching_against_index(&pathspec,
- &the_index, PS_IGNORE_SKIP_WORKTREE);
+ the_repository->index, PS_IGNORE_SKIP_WORKTREE);
/*
* file_exists() assumes exact match
@@ -524,8 +527,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
!file_exists(path)) {
if (ignore_missing) {
int dtype = DT_UNKNOWN;
- if (is_excluded(&dir, &the_index, path, &dtype))
- dir_add_ignored(&dir, &the_index,
+ if (is_excluded(&dir, the_repository->index, path, &dtype))
+ dir_add_ignored(&dir, the_repository->index,
path, pathspec.items[i].len);
} else
die(_("pathspec '%s' did not match any files"),
@@ -566,7 +569,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
end_odb_transaction();
finish:
- if (write_locked_index(&the_index, &lock_file,
+ if (write_locked_index(the_repository->index, &lock_file,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
die(_("unable to write new index file"));
diff --git a/builtin/am.c b/builtin/am.c
index 022cae2e8d..36839029d2 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -3,7 +3,7 @@
*
* Based on git-am.sh by Junio C Hamano.
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "abspath.h"
#include "advice.h"
@@ -1001,7 +1001,8 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
if (mkdir(state->dir, 0777) < 0 && errno != EEXIST)
die_errno(_("failed to create directory '%s'"), state->dir);
- delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
+ refs_delete_ref(get_main_ref_store(the_repository), NULL,
+ "REBASE_HEAD", NULL, REF_NO_DEREF);
if (split_mail(state, patch_format, paths, keep_cr) < 0) {
am_destroy(state);
@@ -1081,12 +1082,15 @@ static void am_setup(struct am_state *state, enum patch_format patch_format,
if (!repo_get_oid(the_repository, "HEAD", &curr_head)) {
write_state_text(state, "abort-safety", oid_to_hex(&curr_head));
if (!state->rebasing)
- update_ref("am", "ORIG_HEAD", &curr_head, NULL, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository),
+ "am", "ORIG_HEAD", &curr_head, NULL,
+ 0,
+ UPDATE_REFS_DIE_ON_ERR);
} else {
write_state_text(state, "abort-safety", "");
if (!state->rebasing)
- delete_ref(NULL, "ORIG_HEAD", NULL, 0);
+ refs_delete_ref(get_main_ref_store(the_repository),
+ NULL, "ORIG_HEAD", NULL, 0);
}
/*
@@ -1119,7 +1123,8 @@ static void am_next(struct am_state *state)
oidclr(&state->orig_commit);
unlink(am_path(state, "original-commit"));
- delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
+ refs_delete_ref(get_main_ref_store(the_repository), NULL,
+ "REBASE_HEAD", NULL, REF_NO_DEREF);
if (!repo_get_oid(the_repository, "HEAD", &head))
write_state_text(state, "abort-safety", oid_to_hex(&head));
@@ -1466,8 +1471,9 @@ static int parse_mail_rebase(struct am_state *state, const char *mail)
oidcpy(&state->orig_commit, &commit_oid);
write_state_text(state, "original-commit", oid_to_hex(&commit_oid));
- update_ref("am", "REBASE_HEAD", &commit_oid,
- NULL, REF_NO_DEREF, UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), "am",
+ "REBASE_HEAD", &commit_oid,
+ NULL, REF_NO_DEREF, UPDATE_REFS_DIE_ON_ERR);
return 0;
}
@@ -1536,8 +1542,8 @@ static int run_apply(const struct am_state *state, const char *index_file)
if (index_file) {
/* Reload index as apply_all_patches() will have modified it. */
- discard_index(&the_index);
- read_index_from(&the_index, index_file, get_git_dir());
+ discard_index(the_repository->index);
+ read_index_from(the_repository->index, index_file, get_git_dir());
}
return 0;
@@ -1579,10 +1585,10 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
if (build_fake_ancestor(state, index_path))
return error("could not build fake ancestor");
- discard_index(&the_index);
- read_index_from(&the_index, index_path, get_git_dir());
+ discard_index(the_repository->index);
+ read_index_from(the_repository->index, index_path, get_git_dir());
- if (write_index_as_tree(&orig_tree, &the_index, index_path, 0, NULL))
+ if (write_index_as_tree(&orig_tree, the_repository->index, index_path, 0, NULL))
return error(_("Repository lacks necessary blobs to fall back on 3-way merge."));
say(state, stdout, _("Using index info to reconstruct a base tree..."));
@@ -1608,12 +1614,12 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
return error(_("Did you hand edit your patch?\n"
"It does not apply to blobs recorded in its index."));
- if (write_index_as_tree(&their_tree, &the_index, index_path, 0, NULL))
+ if (write_index_as_tree(&their_tree, the_repository->index, index_path, 0, NULL))
return error("could not write tree");
say(state, stdout, _("Falling back to patching base and 3-way merge..."));
- discard_index(&the_index);
+ discard_index(the_repository->index);
repo_read_index(the_repository);
/*
@@ -1660,7 +1666,7 @@ static void do_commit(const struct am_state *state)
if (!state->no_verify && run_hooks("pre-applypatch"))
exit(1);
- if (write_index_as_tree(&tree, &the_index, get_index_file(), 0, NULL))
+ if (write_index_as_tree(&tree, the_repository->index, get_index_file(), 0, NULL))
die(_("git write-tree failed to write a tree"));
if (!repo_get_oid_commit(the_repository, "HEAD", &parent)) {
@@ -1697,8 +1703,9 @@ static void do_commit(const struct am_state *state)
strbuf_addf(&sb, "%s: %.*s", reflog_msg, linelen(state->msg),
state->msg);
- update_ref(sb.buf, "HEAD", &commit, old_oid, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), sb.buf, "HEAD",
+ &commit, old_oid, 0,
+ UPDATE_REFS_DIE_ON_ERR);
if (state->rebasing) {
FILE *fp = xfopen(am_path(state, "rewritten"), "a");
@@ -1948,7 +1955,7 @@ static void am_resolve(struct am_state *state, int allow_empty)
}
}
- if (unmerged_index(&the_index)) {
+ if (unmerged_index(the_repository->index)) {
printf_ln(_("You still have unmerged paths in your index.\n"
"You should 'git add' each file with resolved conflicts to mark them as such.\n"
"You might run `git rm` on a file to accept \"deleted by them\" for it."));
@@ -1987,12 +1994,12 @@ static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
- refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL);
+ refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL, NULL);
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
- opts.src_index = &the_index;
- opts.dst_index = &the_index;
+ opts.src_index = the_repository->index;
+ opts.dst_index = the_repository->index;
opts.update = 1;
opts.merge = 1;
opts.reset = reset ? UNPACK_RESET_PROTECT_UNTRACKED : 0;
@@ -2006,7 +2013,7 @@ static int fast_forward_to(struct tree *head, struct tree *remote, int reset)
return -1;
}
- if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
+ if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
return 0;
@@ -2029,8 +2036,8 @@ static int merge_tree(struct tree *tree)
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
- opts.src_index = &the_index;
- opts.dst_index = &the_index;
+ opts.src_index = the_repository->index;
+ opts.dst_index = the_repository->index;
opts.merge = 1;
opts.fn = oneway_merge;
init_tree_desc(&t[0], &tree->object.oid, tree->buffer, tree->size);
@@ -2040,7 +2047,7 @@ static int merge_tree(struct tree *tree)
return -1;
}
- if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
+ if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
return 0;
@@ -2068,7 +2075,7 @@ static int clean_index(const struct object_id *head, const struct object_id *rem
if (fast_forward_to(head_tree, head_tree, 1))
return -1;
- if (write_index_as_tree(&index, &the_index, get_index_file(), 0, NULL))
+ if (write_index_as_tree(&index, the_repository->index, get_index_file(), 0, NULL))
return -1;
index_tree = parse_tree_indirect(&index);
@@ -2175,7 +2182,8 @@ static void am_abort(struct am_state *state)
am_rerere_clear();
- curr_branch = resolve_refdup("HEAD", 0, &curr_head, NULL);
+ curr_branch = refs_resolve_refdup(get_main_ref_store(the_repository),
+ "HEAD", 0, &curr_head, NULL);
has_curr_head = curr_branch && !is_null_oid(&curr_head);
if (!has_curr_head)
oidcpy(&curr_head, the_hash_algo->empty_tree);
@@ -2188,11 +2196,13 @@ static void am_abort(struct am_state *state)
die(_("failed to clean index"));
if (has_orig_head)
- update_ref("am --abort", "HEAD", &orig_head,
- has_curr_head ? &curr_head : NULL, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository),
+ "am --abort", "HEAD", &orig_head,
+ has_curr_head ? &curr_head : NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
else if (curr_branch)
- delete_ref(NULL, curr_branch, NULL, REF_NO_DEREF);
+ refs_delete_ref(get_main_ref_store(the_repository), NULL,
+ curr_branch, NULL, REF_NO_DEREF);
free(curr_branch);
am_destroy(state);
diff --git a/builtin/apply.c b/builtin/apply.c
index 861a01910c..e9175f820f 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -1,6 +1,7 @@
#include "builtin.h"
#include "gettext.h"
#include "repository.h"
+#include "hash.h"
#include "apply.h"
static const char * const apply_usage[] = {
@@ -18,6 +19,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix)
if (init_apply_state(&state, the_repository, prefix))
exit(128);
+ if (!the_hash_algo)
+ repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
+
argc = apply_parse_options(argc, argv,
&state, &force_apply, &options,
apply_usage);
diff --git a/builtin/bisect.c b/builtin/bisect.c
index f69c3f7e43..a58432b9d9 100644
--- a/builtin/bisect.c
+++ b/builtin/bisect.c
@@ -243,7 +243,7 @@ static int bisect_reset(const char *commit)
strbuf_addstr(&branch, commit);
}
- if (branch.len && !ref_exists("BISECT_HEAD")) {
+ if (branch.len && !refs_ref_exists(get_main_ref_store(the_repository), "BISECT_HEAD")) {
struct child_process cmd = CHILD_PROCESS_INIT;
cmd.git_cmd = 1;
@@ -302,8 +302,8 @@ static int bisect_write(const char *state, const char *rev,
goto finish;
}
- if (update_ref(NULL, tag.buf, &oid, NULL, 0,
- UPDATE_REFS_MSG_ON_ERR)) {
+ if (refs_update_ref(get_main_ref_store(the_repository), NULL, tag.buf, &oid, NULL, 0,
+ UPDATE_REFS_MSG_ON_ERR)) {
res = -1;
goto finish;
}
@@ -416,11 +416,12 @@ static void bisect_status(struct bisect_state *state,
char *bad_ref = xstrfmt("refs/bisect/%s", terms->term_bad);
char *good_glob = xstrfmt("%s-*", terms->term_good);
- if (ref_exists(bad_ref))
+ if (refs_ref_exists(get_main_ref_store(the_repository), bad_ref))
state->nr_bad = 1;
- for_each_glob_ref_in(inc_nr, good_glob, "refs/bisect/",
- (void *) &state->nr_good);
+ refs_for_each_glob_ref_in(get_main_ref_store(the_repository), inc_nr,
+ good_glob, "refs/bisect/",
+ (void *) &state->nr_good);
free(good_glob);
free(bad_ref);
@@ -574,9 +575,11 @@ static int prepare_revs(struct bisect_terms *terms, struct rev_info *revs)
reset_revision_walk();
repo_init_revisions(the_repository, revs, NULL);
setup_revisions(0, NULL, revs, NULL);
- for_each_glob_ref_in(add_bisect_ref, bad, "refs/bisect/", &cb);
+ refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
+ add_bisect_ref, bad, "refs/bisect/", &cb);
cb.object_flags = UNINTERESTING;
- for_each_glob_ref_in(add_bisect_ref, good, "refs/bisect/", &cb);
+ refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
+ add_bisect_ref, good, "refs/bisect/", &cb);
if (prepare_revision_walk(revs))
res = error(_("revision walk setup failed\n"));
@@ -636,7 +639,7 @@ static int bisect_successful(struct bisect_terms *terms)
char *bad_ref = xstrfmt("refs/bisect/%s",terms->term_bad);
int res;
- read_ref(bad_ref, &oid);
+ refs_read_ref(get_main_ref_store(the_repository), bad_ref, &oid);
commit = lookup_commit_reference_by_name(bad_ref);
repo_format_commit_message(the_repository, commit, "%s", &commit_name,
&pp);
@@ -779,7 +782,8 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
/*
* Verify HEAD
*/
- head = resolve_ref_unsafe("HEAD", 0, &head_oid, &flags);
+ head = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ "HEAD", 0, &head_oid, &flags);
if (!head)
if (repo_get_oid(the_repository, "HEAD", &head_oid))
return error(_("bad HEAD - I need a HEAD"));
@@ -838,8 +842,8 @@ static enum bisect_error bisect_start(struct bisect_terms *terms, int argc,
res = error(_("invalid ref: '%s'"), start_head.buf);
goto finish;
}
- if (update_ref(NULL, "BISECT_HEAD", &oid, NULL, 0,
- UPDATE_REFS_MSG_ON_ERR)) {
+ if (refs_update_ref(get_main_ref_store(the_repository), NULL, "BISECT_HEAD", &oid, NULL, 0,
+ UPDATE_REFS_MSG_ON_ERR)) {
res = BISECT_FAILED;
goto finish;
}
@@ -972,7 +976,7 @@ static enum bisect_error bisect_state(struct bisect_terms *terms, int argc,
oid_array_append(&revs, &commit->object.oid);
}
- if (read_ref("BISECT_EXPECTED_REV", &expected))
+ if (refs_read_ref(get_main_ref_store(the_repository), "BISECT_EXPECTED_REV", &expected))
verify_expected = 0; /* Ignore invalid file contents */
for (i = 0; i < revs.nr; i++) {
@@ -982,7 +986,9 @@ static enum bisect_error bisect_state(struct bisect_terms *terms, int argc,
}
if (verify_expected && !oideq(&revs.oid[i], &expected)) {
unlink_or_warn(git_path_bisect_ancestors_ok());
- delete_ref(NULL, "BISECT_EXPECTED_REV", NULL, REF_NO_DEREF);
+ refs_delete_ref(get_main_ref_store(the_repository),
+ NULL, "BISECT_EXPECTED_REV", NULL,
+ REF_NO_DEREF);
verify_expected = 0;
}
}
@@ -1179,13 +1185,15 @@ static int verify_good(const struct bisect_terms *terms, const char *command)
struct object_id good_rev;
struct object_id current_rev;
char *good_glob = xstrfmt("%s-*", terms->term_good);
- int no_checkout = ref_exists("BISECT_HEAD");
+ int no_checkout = refs_ref_exists(get_main_ref_store(the_repository),
+ "BISECT_HEAD");
- for_each_glob_ref_in(get_first_good, good_glob, "refs/bisect/",
- &good_rev);
+ refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
+ get_first_good, good_glob, "refs/bisect/",
+ &good_rev);
free(good_glob);
- if (read_ref(no_checkout ? "BISECT_HEAD" : "HEAD", &current_rev))
+ if (refs_read_ref(get_main_ref_store(the_repository), no_checkout ? "BISECT_HEAD" : "HEAD", &current_rev))
return -1;
res = bisect_checkout(&good_rev, no_checkout);
diff --git a/builtin/blame.c b/builtin/blame.c
index 9aa74680a3..fadba1a530 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -915,7 +915,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
struct range_set ranges;
unsigned int range_i;
long anchor;
- const int hexsz = the_hash_algo->hexsz;
long num_lines = 0;
const char *str_usage = cmd_is_annotate ? annotate_usage : blame_usage;
const char **opt_usage = cmd_is_annotate ? annotate_opt_usage : blame_opt_usage;
@@ -973,11 +972,11 @@ parse_done:
} else if (show_progress < 0)
show_progress = isatty(2);
- if (0 < abbrev && abbrev < hexsz)
+ if (0 < abbrev && abbrev < (int)the_hash_algo->hexsz)
/* one more abbrev length is needed for the boundary commit */
abbrev++;
else if (!abbrev)
- abbrev = hexsz;
+ abbrev = the_hash_algo->hexsz;
if (revs_file && read_ancestry(revs_file))
die_errno("reading graft file '%s' failed", revs_file);
@@ -1093,8 +1092,8 @@ parse_done:
struct commit *head_commit;
struct object_id head_oid;
- if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
- &head_oid, NULL) ||
+ if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", RESOLVE_REF_READING,
+ &head_oid, NULL) ||
!(head_commit = lookup_commit_reference_gently(revs.repo,
&head_oid, 1)))
die("no such ref: HEAD");
diff --git a/builtin/branch.c b/builtin/branch.c
index dd3e3a7dc0..48cac74f97 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -148,8 +148,8 @@ static int branch_merged(int kind, const char *name,
if (upstream &&
(reference_name = reference_name_to_free =
- resolve_refdup(upstream, RESOLVE_REF_READING,
- &oid, NULL)) != NULL)
+ refs_resolve_refdup(get_main_ref_store(the_repository), upstream, RESOLVE_REF_READING,
+ &oid, NULL)) != NULL)
reference_rev = lookup_commit_reference(the_repository,
&oid);
}
@@ -272,21 +272,24 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
}
}
- target = resolve_refdup(name,
- RESOLVE_REF_READING
- | RESOLVE_REF_NO_RECURSE
- | RESOLVE_REF_ALLOW_BAD_NAME,
- &oid, &flags);
+ target = refs_resolve_refdup(get_main_ref_store(the_repository),
+ name,
+ RESOLVE_REF_READING
+ | RESOLVE_REF_NO_RECURSE
+ | RESOLVE_REF_ALLOW_BAD_NAME,
+ &oid, &flags);
if (!target) {
if (remote_branch) {
error(_("remote-tracking branch '%s' not found"), bname.buf);
} else {
char *virtual_name = mkpathdup(fmt_remotes, bname.buf);
- char *virtual_target = resolve_refdup(virtual_name,
- RESOLVE_REF_READING
- | RESOLVE_REF_NO_RECURSE
- | RESOLVE_REF_ALLOW_BAD_NAME,
- &oid, &flags);
+ char *virtual_target = refs_resolve_refdup(get_main_ref_store(the_repository),
+ virtual_name,
+ RESOLVE_REF_READING
+ | RESOLVE_REF_NO_RECURSE
+ | RESOLVE_REF_ALLOW_BAD_NAME,
+ &oid,
+ &flags);
FREE_AND_NULL(virtual_name);
if (virtual_target)
@@ -317,13 +320,13 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
free(target);
}
- if (delete_refs(NULL, &refs_to_delete, REF_NO_DEREF))
+ if (refs_delete_refs(get_main_ref_store(the_repository), NULL, &refs_to_delete, REF_NO_DEREF))
ret = 1;
for_each_string_list_item(item, &refs_to_delete) {
char *describe_ref = item->util;
char *name = item->string;
- if (!ref_exists(name)) {
+ if (!refs_ref_exists(get_main_ref_store(the_repository), name)) {
char *refname = name + branch_name_pos;
if (!quiet)
printf(remote_branch
@@ -499,7 +502,8 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
static void print_current_branch_name(void)
{
int flags;
- const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, &flags);
+ const char *refname = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ "HEAD", 0, NULL, &flags);
const char *shortname;
if (!refname)
die(_("could not resolve HEAD"));
@@ -555,7 +559,7 @@ static int replace_each_worktree_head_symref(struct worktree **worktrees,
continue;
refs = get_worktree_ref_store(worktrees[i]);
- if (refs_create_symref(refs, "HEAD", newref, logmsg))
+ if (refs_update_symref(refs, "HEAD", newref, logmsg))
ret = error(_("HEAD of working tree %s is not updated"),
worktrees[i]->path);
}
@@ -580,7 +584,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
* Bad name --- this could be an attempt to rename a
* ref that we used to allow to be created by accident.
*/
- if (ref_exists(oldref.buf))
+ if (refs_ref_exists(get_main_ref_store(the_repository), oldref.buf))
recovery = 1;
else {
int code = die_message(_("invalid branch name: '%s'"), oldname);
@@ -601,7 +605,7 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
}
}
- if ((copy || !(oldref_usage & IS_HEAD)) && !ref_exists(oldref.buf)) {
+ if ((copy || !(oldref_usage & IS_HEAD)) && !refs_ref_exists(get_main_ref_store(the_repository), oldref.buf)) {
if (oldref_usage & IS_HEAD)
die(_("no commit on branch '%s' yet"), oldname);
else
@@ -632,9 +636,9 @@ static void copy_or_rename_branch(const char *oldname, const char *newname, int
oldref.buf, newref.buf);
if (!copy && !(oldref_usage & IS_ORPHAN) &&
- rename_ref(oldref.buf, newref.buf, logmsg.buf))
+ refs_rename_ref(get_main_ref_store(the_repository), oldref.buf, newref.buf, logmsg.buf))
die(_("branch rename failed"));
- if (copy && copy_existing_ref(oldref.buf, newref.buf, logmsg.buf))
+ if (copy && refs_copy_existing_ref(get_main_ref_store(the_repository), oldref.buf, newref.buf, logmsg.buf))
die(_("branch copy failed"));
if (recovery) {
@@ -786,7 +790,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
track = git_branch_track;
- head = resolve_refdup("HEAD", 0, &head_oid, NULL);
+ head = refs_resolve_refdup(get_main_ref_store(the_repository), "HEAD",
+ 0, &head_oid, NULL);
if (!head)
die(_("failed to resolve HEAD as a valid ref"));
if (!strcmp(head, "HEAD"))
@@ -891,7 +896,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
}
strbuf_addf(&branch_ref, "refs/heads/%s", branch_name);
- if (!ref_exists(branch_ref.buf))
+ if (!refs_ref_exists(get_main_ref_store(the_repository), branch_ref.buf))
error((!argc || branch_checked_out(branch_ref.buf))
? _("no commit on branch '%s' yet")
: _("no branch named '%s'"),
@@ -936,7 +941,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
die(_("no such branch '%s'"), argv[0]);
}
- if (!ref_exists(branch->refname)) {
+ if (!refs_ref_exists(get_main_ref_store(the_repository), branch->refname)) {
if (!argc || branch_checked_out(branch->refname))
die(_("no commit on branch '%s' yet"), branch->name);
die(_("branch '%s' does not exist"), branch->name);
diff --git a/builtin/bundle.c b/builtin/bundle.c
index 3ad11dc5d0..d5d41a8f67 100644
--- a/builtin/bundle.c
+++ b/builtin/bundle.c
@@ -140,6 +140,11 @@ static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
builtin_bundle_verify_usage, options, &bundle_file);
/* bundle internals use argv[1] as further parameters */
+ if (!startup_info->have_repository) {
+ ret = error(_("need a repository to verify a bundle"));
+ goto cleanup;
+ }
+
if ((bundle_fd = open_bundle(bundle_file, &header, &name)) < 0) {
ret = 1;
goto cleanup;
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 0c948f40fb..43a1d7ac49 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -3,7 +3,7 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "config.h"
#include "convert.h"
@@ -77,7 +77,7 @@ static int filter_object(const char *path, unsigned mode,
struct checkout_metadata meta;
init_checkout_metadata(&meta, NULL, NULL, oid);
- if (convert_to_working_tree(&the_index, path, *buf, *size, &strbuf, &meta)) {
+ if (convert_to_working_tree(the_repository->index, path, *buf, *size, &strbuf, &meta)) {
free(*buf);
*size = strbuf.len;
*buf = strbuf_detach(&strbuf, NULL);
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index c1da1d184e..9376810710 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "config.h"
#include "attr.h"
@@ -71,9 +70,9 @@ static void check_attr(const char *prefix, struct attr_check *check,
prefix_path(prefix, prefix ? strlen(prefix) : 0, file);
if (collect_all) {
- git_all_attrs(&the_index, full_path, check);
+ git_all_attrs(the_repository->index, full_path, check);
} else {
- git_check_attr(&the_index, full_path, check);
+ git_check_attr(the_repository->index, full_path, check);
}
output_attr(check, file);
diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c
index 906cd96753..6c43430ec4 100644
--- a/builtin/check-ignore.c
+++ b/builtin/check-ignore.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "config.h"
#include "dir.h"
@@ -95,21 +94,21 @@ static int check_ignore(struct dir_struct *dir,
PATHSPEC_KEEP_ORDER,
prefix, argv);
- die_path_inside_submodule(&the_index, &pathspec);
+ die_path_inside_submodule(the_repository->index, &pathspec);
/*
* look for pathspecs matching entries in the index, since these
* should not be ignored, in order to be consistent with
* 'git status', 'git add' etc.
*/
- seen = find_pathspecs_matching_against_index(&pathspec, &the_index,
+ seen = find_pathspecs_matching_against_index(&pathspec, the_repository->index,
PS_HEED_SKIP_WORKTREE);
for (i = 0; i < pathspec.nr; i++) {
full_path = pathspec.items[i].match;
pattern = NULL;
if (!seen[i]) {
int dtype = DT_UNKNOWN;
- pattern = last_matching_pattern(dir, &the_index,
+ pattern = last_matching_pattern(dir, the_repository->index,
full_path, &dtype);
if (!verbose && pattern &&
pattern->flags & PATTERN_FLAG_NEGATIVE)
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index 2e086a204d..29e744d11b 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -4,7 +4,7 @@
* Copyright (C) 2005 Linus Torvalds
*
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -69,7 +69,7 @@ static void write_tempfile_record(const char *name, const char *prefix)
static int checkout_file(const char *name, const char *prefix)
{
int namelen = strlen(name);
- int pos = index_name_pos(&the_index, name, namelen);
+ int pos = index_name_pos(the_repository->index, name, namelen);
int has_same_name = 0;
int is_file = 0;
int is_skipped = 1;
@@ -79,8 +79,8 @@ static int checkout_file(const char *name, const char *prefix)
if (pos < 0)
pos = -pos - 1;
- while (pos < the_index.cache_nr) {
- struct cache_entry *ce = the_index.cache[pos];
+ while (pos <the_repository->index->cache_nr) {
+ struct cache_entry *ce =the_repository->index->cache[pos];
if (ce_namelen(ce) != namelen ||
memcmp(ce->name, name, namelen))
break;
@@ -140,8 +140,8 @@ static int checkout_all(const char *prefix, int prefix_length)
int i, errs = 0;
struct cache_entry *last_ce = NULL;
- for (i = 0; i < the_index.cache_nr ; i++) {
- struct cache_entry *ce = the_index.cache[i];
+ for (i = 0; i < the_repository->index->cache_nr ; i++) {
+ struct cache_entry *ce = the_repository->index->cache[i];
if (S_ISSPARSEDIR(ce->ce_mode)) {
if (!ce_skip_worktree(ce))
@@ -154,8 +154,8 @@ static int checkout_all(const char *prefix, int prefix_length)
* first entry inside the expanded sparse directory).
*/
if (ignore_skip_worktree) {
- ensure_full_index(&the_index);
- ce = the_index.cache[i];
+ ensure_full_index(the_repository->index);
+ ce = the_repository->index->cache[i];
}
}
@@ -260,7 +260,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, builtin_checkout_index_options,
builtin_checkout_index_usage, 0);
- state.istate = &the_index;
+ state.istate = the_repository->index;
state.force = force;
state.quiet = quiet;
state.not_new = not_new;
@@ -280,7 +280,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
*/
if (index_opt && !state.base_dir_len && !to_tempfile) {
state.refresh_cache = 1;
- state.istate = &the_index;
+ state.istate = the_repository->index;
repo_hold_locked_index(the_repository, &lock_file,
LOCK_DIE_ON_ERROR);
}
@@ -339,7 +339,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
return 1;
if (is_lock_file_locked(&lock_file) &&
- write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
+ write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
die("Unable to write new index file");
return 0;
}
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 71e6036aab..f90a4ca4b7 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "advice.h"
#include "branch.h"
@@ -146,7 +145,7 @@ static int update_some(const struct object_id *oid, struct strbuf *base,
return READ_TREE_RECURSIVE;
len = base->len + strlen(pathname);
- ce = make_empty_cache_entry(&the_index, len);
+ ce = make_empty_cache_entry(the_repository->index, len);
oidcpy(&ce->oid, oid);
memcpy(ce->name, base->buf, base->len);
memcpy(ce->name + base->len, pathname, len - base->len);
@@ -159,9 +158,9 @@ static int update_some(const struct object_id *oid, struct strbuf *base,
* entry in place. Whether it is UPTODATE or not, checkout_entry will
* do the right thing.
*/
- pos = index_name_pos(&the_index, ce->name, ce->ce_namelen);
+ pos = index_name_pos(the_repository->index, ce->name, ce->ce_namelen);
if (pos >= 0) {
- struct cache_entry *old = the_index.cache[pos];
+ struct cache_entry *old = the_repository->index->cache[pos];
if (ce->ce_mode == old->ce_mode &&
!ce_intent_to_add(old) &&
oideq(&ce->oid, &old->oid)) {
@@ -171,7 +170,7 @@ static int update_some(const struct object_id *oid, struct strbuf *base,
}
}
- add_index_entry(&the_index, ce,
+ add_index_entry(the_repository->index, ce,
ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
return 0;
}
@@ -190,8 +189,8 @@ static int read_tree_some(struct tree *tree, const struct pathspec *pathspec)
static int skip_same_name(const struct cache_entry *ce, int pos)
{
- while (++pos < the_index.cache_nr &&
- !strcmp(the_index.cache[pos]->name, ce->name))
+ while (++pos < the_repository->index->cache_nr &&
+ !strcmp(the_repository->index->cache[pos]->name, ce->name))
; /* skip */
return pos;
}
@@ -199,9 +198,9 @@ static int skip_same_name(const struct cache_entry *ce, int pos)
static int check_stage(int stage, const struct cache_entry *ce, int pos,
int overlay_mode)
{
- while (pos < the_index.cache_nr &&
- !strcmp(the_index.cache[pos]->name, ce->name)) {
- if (ce_stage(the_index.cache[pos]) == stage)
+ while (pos < the_repository->index->cache_nr &&
+ !strcmp(the_repository->index->cache[pos]->name, ce->name)) {
+ if (ce_stage(the_repository->index->cache[pos]) == stage)
return 0;
pos++;
}
@@ -218,8 +217,8 @@ static int check_stages(unsigned stages, const struct cache_entry *ce, int pos)
unsigned seen = 0;
const char *name = ce->name;
- while (pos < the_index.cache_nr) {
- ce = the_index.cache[pos];
+ while (pos < the_repository->index->cache_nr) {
+ ce = the_repository->index->cache[pos];
if (strcmp(name, ce->name))
break;
seen |= (1 << ce_stage(ce));
@@ -235,10 +234,10 @@ static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
const struct checkout *state, int *nr_checkouts,
int overlay_mode)
{
- while (pos < the_index.cache_nr &&
- !strcmp(the_index.cache[pos]->name, ce->name)) {
- if (ce_stage(the_index.cache[pos]) == stage)
- return checkout_entry(the_index.cache[pos], state,
+ while (pos < the_repository->index->cache_nr &&
+ !strcmp(the_repository->index->cache[pos]->name, ce->name)) {
+ if (ce_stage(the_repository->index->cache[pos]) == stage)
+ return checkout_entry(the_repository->index->cache[pos], state,
NULL, nr_checkouts);
pos++;
}
@@ -256,7 +255,7 @@ static int checkout_merged(int pos, const struct checkout *state,
int *nr_checkouts, struct mem_pool *ce_mem_pool,
int conflict_style)
{
- struct cache_entry *ce = the_index.cache[pos];
+ struct cache_entry *ce = the_repository->index->cache[pos];
const char *path = ce->name;
mmfile_t ancestor, ours, theirs;
enum ll_merge_result merge_status;
@@ -269,7 +268,7 @@ static int checkout_merged(int pos, const struct checkout *state,
int renormalize = 0;
memset(threeway, 0, sizeof(threeway));
- while (pos < the_index.cache_nr) {
+ while (pos < the_repository->index->cache_nr) {
int stage;
stage = ce_stage(ce);
if (!stage || strcmp(path, ce->name))
@@ -278,7 +277,7 @@ static int checkout_merged(int pos, const struct checkout *state,
if (stage == 2)
mode = create_ce_mode(ce->ce_mode);
pos++;
- ce = the_index.cache[pos];
+ ce = the_repository->index->cache[pos];
}
if (is_null_oid(&threeway[1]) || is_null_oid(&threeway[2]))
return error(_("path '%s' does not have necessary versions"), path);
@@ -356,7 +355,7 @@ static void mark_ce_for_checkout_overlay(struct cache_entry *ce,
* match_pathspec() for _all_ entries when
* opts->source_tree != NULL.
*/
- if (ce_path_match(&the_index, ce, &opts->pathspec, ps_matched))
+ if (ce_path_match(the_repository->index, ce, &opts->pathspec, ps_matched))
ce->ce_flags |= CE_MATCHED;
}
@@ -367,7 +366,7 @@ static void mark_ce_for_checkout_no_overlay(struct cache_entry *ce,
ce->ce_flags &= ~CE_MATCHED;
if (!opts->ignore_skipworktree && ce_skip_worktree(ce))
return;
- if (ce_path_match(&the_index, ce, &opts->pathspec, ps_matched)) {
+ if (ce_path_match(the_repository->index, ce, &opts->pathspec, ps_matched)) {
ce->ce_flags |= CE_MATCHED;
if (opts->source_tree && !(ce->ce_flags & CE_UPDATE))
/*
@@ -391,7 +390,7 @@ static int checkout_worktree(const struct checkout_opts *opts,
state.force = 1;
state.refresh_cache = 1;
- state.istate = &the_index;
+ state.istate = the_repository->index;
mem_pool_init(&ce_mem_pool, 0);
get_parallel_checkout_configs(&pc_workers, &pc_threshold);
@@ -404,8 +403,8 @@ static int checkout_worktree(const struct checkout_opts *opts,
if (pc_workers > 1)
init_parallel_checkout();
- for (pos = 0; pos < the_index.cache_nr; pos++) {
- struct cache_entry *ce = the_index.cache[pos];
+ for (pos = 0; pos < the_repository->index->cache_nr; pos++) {
+ struct cache_entry *ce = the_repository->index->cache[pos];
if (ce->ce_flags & CE_MATCHED) {
if (!ce_stage(ce)) {
errs |= checkout_entry(ce, &state,
@@ -429,7 +428,7 @@ static int checkout_worktree(const struct checkout_opts *opts,
errs |= run_parallel_checkout(&state, pc_workers, pc_threshold,
NULL, NULL);
mem_pool_discard(&ce_mem_pool, should_validate_cache_entries());
- remove_marked_cache_entries(&the_index, 1);
+ remove_marked_cache_entries(the_repository->index, 1);
remove_scheduled_dirs();
errs |= finish_delayed_checkout(&state, opts->show_progress);
@@ -571,7 +570,7 @@ static int checkout_paths(const struct checkout_opts *opts,
if (opts->source_tree)
read_tree_some(opts->source_tree, &opts->pathspec);
if (opts->merge)
- unmerge_index(&the_index, &opts->pathspec, CE_MATCHED);
+ unmerge_index(the_repository->index, &opts->pathspec, CE_MATCHED);
ps_matched = xcalloc(opts->pathspec.nr, 1);
@@ -579,13 +578,13 @@ static int checkout_paths(const struct checkout_opts *opts,
* Make sure all pathspecs participated in locating the paths
* to be checked out.
*/
- for (pos = 0; pos < the_index.cache_nr; pos++)
+ for (pos = 0; pos < the_repository->index->cache_nr; pos++)
if (opts->overlay_mode)
- mark_ce_for_checkout_overlay(the_index.cache[pos],
+ mark_ce_for_checkout_overlay(the_repository->index->cache[pos],
ps_matched,
opts);
else
- mark_ce_for_checkout_no_overlay(the_index.cache[pos],
+ mark_ce_for_checkout_no_overlay(the_repository->index->cache[pos],
ps_matched,
opts);
@@ -596,8 +595,8 @@ static int checkout_paths(const struct checkout_opts *opts,
free(ps_matched);
/* Any unmerged paths? */
- for (pos = 0; pos < the_index.cache_nr; pos++) {
- const struct cache_entry *ce = the_index.cache[pos];
+ for (pos = 0; pos < the_repository->index->cache_nr; pos++) {
+ const struct cache_entry *ce = the_repository->index->cache[pos];
if (ce->ce_flags & CE_MATCHED) {
if (!ce_stage(ce))
continue;
@@ -622,7 +621,7 @@ static int checkout_paths(const struct checkout_opts *opts,
if (opts->checkout_worktree)
errs |= checkout_worktree(opts, new_branch_info);
else
- remove_marked_cache_entries(&the_index, 1);
+ remove_marked_cache_entries(the_repository->index, 1);
/*
* Allow updating the index when checking out from the index.
@@ -634,7 +633,7 @@ static int checkout_paths(const struct checkout_opts *opts,
checkout_index = opts->checkout_index;
if (checkout_index) {
- if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
+ if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
} else {
/*
@@ -646,7 +645,8 @@ static int checkout_paths(const struct checkout_opts *opts,
rollback_lock_file(&lock_file);
}
- read_ref_full("HEAD", 0, &rev, NULL);
+ refs_read_ref_full(get_main_ref_store(the_repository), "HEAD", 0,
+ &rev, NULL);
head = lookup_commit_reference_gently(the_repository, &rev, 1);
errs |= post_checkout_hook(head, head, 0);
@@ -703,8 +703,8 @@ static int reset_tree(struct tree *tree, const struct checkout_opts *o,
opts.merge = 1;
opts.fn = oneway_merge;
opts.verbose_update = o->show_progress;
- opts.src_index = &the_index;
- opts.dst_index = &the_index;
+ opts.src_index = the_repository->index;
+ opts.dst_index = the_repository->index;
init_checkout_metadata(&opts.meta, info->refname,
info->commit ? &info->commit->object.oid : null_oid(),
NULL);
@@ -756,12 +756,12 @@ static void init_topts(struct unpack_trees_options *topts, int merge,
{
memset(topts, 0, sizeof(*topts));
topts->head_idx = -1;
- topts->src_index = &the_index;
- topts->dst_index = &the_index;
+ topts->src_index = the_repository->index;
+ topts->dst_index = the_repository->index;
setup_unpack_trees_porcelain(topts, "checkout");
- topts->initial_checkout = is_index_unborn(&the_index);
+ topts->initial_checkout = is_index_unborn(the_repository->index);
topts->update = 1;
topts->merge = 1;
topts->quiet = merge && old_commit;
@@ -783,7 +783,7 @@ static int merge_working_tree(const struct checkout_opts *opts,
if (repo_read_index_preload(the_repository, NULL, 0) < 0)
return error(_("index file corrupt"));
- resolve_undo_clear_index(&the_index);
+ resolve_undo_clear_index(the_repository->index);
if (opts->new_orphan_branch && opts->orphan_from_empty_tree) {
if (new_branch_info->commit)
BUG("'switch --orphan' should never accept a commit as starting point");
@@ -807,9 +807,9 @@ static int merge_working_tree(const struct checkout_opts *opts,
struct unpack_trees_options topts;
const struct object_id *old_commit_oid;
- refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL);
+ refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL, NULL);
- if (unmerged_index(&the_index)) {
+ if (unmerged_index(the_repository->index)) {
error(_("you need to resolve your current index first"));
return 1;
}
@@ -919,10 +919,10 @@ static int merge_working_tree(const struct checkout_opts *opts,
}
}
- if (!cache_tree_fully_valid(the_index.cache_tree))
- cache_tree_update(&the_index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
+ if (!cache_tree_fully_valid(the_repository->index->cache_tree))
+ cache_tree_update(the_repository->index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
- if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
+ if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
if (!opts->discard_changes && !opts->quiet && new_branch_info->commit)
@@ -958,7 +958,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
int ret;
struct strbuf err = STRBUF_INIT;
- ret = safe_create_reflog(refname, &err);
+ ret = refs_create_reflog(get_main_ref_store(the_repository),
+ refname, &err);
if (ret) {
fprintf(stderr, _("Can not do reflog for '%s': %s\n"),
opts->new_orphan_branch, err.buf);
@@ -999,8 +1000,10 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
if (!strcmp(new_branch_info->name, "HEAD") && !new_branch_info->path && !opts->force_detach) {
/* Nothing to do. */
} else if (opts->force_detach || !new_branch_info->path) { /* No longer on any branch. */
- update_ref(msg.buf, "HEAD", &new_branch_info->commit->object.oid, NULL,
- REF_NO_DEREF, UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), msg.buf,
+ "HEAD", &new_branch_info->commit->object.oid,
+ NULL,
+ REF_NO_DEREF, UPDATE_REFS_DIE_ON_ERR);
if (!opts->quiet) {
if (old_branch_info->path &&
advice_enabled(ADVICE_DETACHED_HEAD) && !opts->force_detach)
@@ -1008,7 +1011,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
describe_detached_head(_("HEAD is now at"), new_branch_info->commit);
}
} else if (new_branch_info->path) { /* Switch branches. */
- if (create_symref("HEAD", new_branch_info->path, msg.buf) < 0)
+ if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", new_branch_info->path, msg.buf) < 0)
die(_("unable to update HEAD"));
if (!opts->quiet) {
if (old_branch_info->path && !strcmp(new_branch_info->path, old_branch_info->path)) {
@@ -1029,8 +1032,9 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
}
}
if (old_branch_info->path && old_branch_info->name) {
- if (!ref_exists(old_branch_info->path) && reflog_exists(old_branch_info->path))
- delete_reflog(old_branch_info->path);
+ if (!refs_ref_exists(get_main_ref_store(the_repository), old_branch_info->path) && refs_reflog_exists(get_main_ref_store(the_repository), old_branch_info->path))
+ refs_delete_reflog(get_main_ref_store(the_repository),
+ old_branch_info->path);
}
}
remove_branch_state(the_repository, !opts->quiet);
@@ -1129,7 +1133,8 @@ static void orphaned_commit_warning(struct commit *old_commit, struct commit *ne
object->flags &= ~UNINTERESTING;
add_pending_object(&revs, object, oid_to_hex(&object->oid));
- for_each_ref(add_pending_uninteresting_ref, &revs);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ add_pending_uninteresting_ref, &revs);
if (new_commit)
add_pending_oid(&revs, "HEAD",
&new_commit->object.oid,
@@ -1159,7 +1164,8 @@ static int switch_branches(const struct checkout_opts *opts,
trace2_cmd_mode("branch");
memset(&old_branch_info, 0, sizeof(old_branch_info));
- old_branch_info.path = resolve_refdup("HEAD", 0, &rev, &flag);
+ old_branch_info.path = refs_resolve_refdup(get_main_ref_store(the_repository),
+ "HEAD", 0, &rev, &flag);
if (old_branch_info.path)
old_branch_info.commit = lookup_commit_reference_gently(the_repository, &rev, 1);
if (!(flag & REF_ISSYMREF))
@@ -1247,7 +1253,7 @@ static void setup_new_branch_info_and_source_tree(
setup_branch_path(new_branch_info);
if (!check_refname_format(new_branch_info->path, 0) &&
- !read_ref(new_branch_info->path, &branch_rev))
+ !refs_read_ref(get_main_ref_store(the_repository), new_branch_info->path, &branch_rev))
oidcpy(rev, &branch_rev);
else
/* not an existing branch */
@@ -1466,7 +1472,8 @@ static int switch_unborn_to_new_branch(const struct checkout_opts *opts)
if (!opts->new_branch)
die(_("You are on a branch yet to be born"));
strbuf_addf(&branch_ref, "refs/heads/%s", opts->new_branch);
- status = create_symref("HEAD", branch_ref.buf, "checkout -b");
+ status = refs_update_symref(get_main_ref_store(the_repository),
+ "HEAD", branch_ref.buf, "checkout -b");
strbuf_release(&branch_ref);
if (!opts->quiet)
fprintf(stderr, _("Switched to a new branch '%s'\n"),
@@ -1553,7 +1560,8 @@ static void die_if_switching_to_a_branch_in_use(struct checkout_opts *opts,
if (opts->ignore_other_worktrees)
return;
- head_ref = resolve_refdup("HEAD", 0, NULL, &flags);
+ head_ref = refs_resolve_refdup(get_main_ref_store(the_repository),
+ "HEAD", 0, NULL, &flags);
if (head_ref && (!(flags & REF_ISSYMREF) || strcmp(head_ref, full_ref)))
die_if_checked_out(full_ref, 1);
free(head_ref);
@@ -1634,7 +1642,7 @@ static int checkout_branch(struct checkout_opts *opts,
struct object_id rev;
int flag;
- if (!read_ref_full("HEAD", 0, &rev, &flag) &&
+ if (!refs_read_ref_full(get_main_ref_store(the_repository), "HEAD", 0, &rev, &flag) &&
(flag & REF_ISSYMREF) && is_null_oid(&rev))
return switch_unborn_to_new_branch(opts);
}
diff --git a/builtin/clean.c b/builtin/clean.c
index 29efe84153..ded5a91534 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -6,7 +6,6 @@
* Based on git-clean.sh by Pavel Roskin
*/
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "config.h"
@@ -714,7 +713,7 @@ static int filter_by_patterns_cmd(void)
for_each_string_list_item(item, &del_list) {
int dtype = DT_UNKNOWN;
- if (is_excluded(&dir, &the_index, item->string, &dtype)) {
+ if (is_excluded(&dir, the_repository->index, item->string, &dtype)) {
*item->string = '\0';
changed++;
}
@@ -1021,7 +1020,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
PATHSPEC_PREFER_CWD,
prefix, argv);
- fill_directory(&dir, &the_index, &pathspec);
+ fill_directory(&dir, the_repository->index, &pathspec);
correct_untracked_entries(&dir);
for (i = 0; i < dir.nr; i++) {
@@ -1029,7 +1028,7 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
struct stat st;
const char *rel;
- if (!index_name_is_other(&the_index, ent->name, ent->len))
+ if (!index_name_is_other(the_repository->index, ent->name, ent->len))
continue;
if (lstat(ent->name, &st))
diff --git a/builtin/clone.c b/builtin/clone.c
index 74ec14542e..23993b905b 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -8,7 +8,6 @@
* Clone a repository into a different directory that does not yet exist.
*/
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "advice.h"
@@ -329,7 +328,20 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
int src_len, dest_len;
struct dir_iterator *iter;
int iter_status;
- struct strbuf realpath = STRBUF_INIT;
+
+ /*
+ * Refuse copying directories by default which aren't owned by us. The
+ * code that performs either the copying or hardlinking is not prepared
+ * to handle various edge cases where an adversary may for example
+ * racily swap out files for symlinks. This can cause us to
+ * inadvertently use the wrong source file.
+ *
+ * Furthermore, even if we were prepared to handle such races safely,
+ * creating hardlinks across user boundaries is an inherently unsafe
+ * operation as the hardlinked files can be rewritten at will by the
+ * potentially-untrusted user. We thus refuse to do so by default.
+ */
+ die_upon_dubious_ownership(NULL, NULL, src_repo);
mkdir_if_missing(dest->buf, 0777);
@@ -377,9 +389,27 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
if (unlink(dest->buf) && errno != ENOENT)
die_errno(_("failed to unlink '%s'"), dest->buf);
if (!option_no_hardlinks) {
- strbuf_realpath(&realpath, src->buf, 1);
- if (!link(realpath.buf, dest->buf))
+ if (!link(src->buf, dest->buf)) {
+ struct stat st;
+
+ /*
+ * Sanity-check whether the created hardlink
+ * actually links to the expected file now. This
+ * catches time-of-check-time-of-use bugs in
+ * case the source file was meanwhile swapped.
+ */
+ if (lstat(dest->buf, &st))
+ die(_("hardlink cannot be checked at '%s'"), dest->buf);
+ if (st.st_mode != iter->st.st_mode ||
+ st.st_ino != iter->st.st_ino ||
+ st.st_dev != iter->st.st_dev ||
+ st.st_size != iter->st.st_size ||
+ st.st_uid != iter->st.st_uid ||
+ st.st_gid != iter->st.st_gid)
+ die(_("hardlink different from source at '%s'"), dest->buf);
+
continue;
+ }
if (option_local > 0)
die_errno(_("failed to create link '%s'"), dest->buf);
option_no_hardlinks = 1;
@@ -392,8 +422,6 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
strbuf_setlen(src, src_len);
die(_("failed to iterate over '%s'"), src->buf);
}
-
- strbuf_release(&realpath);
}
static void clone_local(const char *src_repo, const char *dest_repo)
@@ -539,7 +567,8 @@ static void write_remote_refs(const struct ref *local_refs)
struct ref_transaction *t;
struct strbuf err = STRBUF_INIT;
- t = ref_transaction_begin(&err);
+ t = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!t)
die("%s", err.buf);
@@ -570,8 +599,9 @@ static void write_followtags(const struct ref *refs, const char *msg)
OBJECT_INFO_QUICK |
OBJECT_INFO_SKIP_FETCH_OBJECT))
continue;
- update_ref(msg, ref->name, &ref->old_oid, NULL, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), msg,
+ ref->name, &ref->old_oid, NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
}
}
@@ -623,9 +653,9 @@ static void update_remote_refs(const struct ref *refs,
struct strbuf head_ref = STRBUF_INIT;
strbuf_addstr(&head_ref, branch_top);
strbuf_addstr(&head_ref, "HEAD");
- if (create_symref(head_ref.buf,
- remote_head_points_at->peer_ref->name,
- msg) < 0)
+ if (refs_update_symref(get_main_ref_store(the_repository), head_ref.buf,
+ remote_head_points_at->peer_ref->name,
+ msg) < 0)
die(_("unable to update %s"), head_ref.buf);
strbuf_release(&head_ref);
}
@@ -637,33 +667,36 @@ static void update_head(const struct ref *our, const struct ref *remote,
const char *head;
if (our && skip_prefix(our->name, "refs/heads/", &head)) {
/* Local default branch link */
- if (create_symref("HEAD", our->name, NULL) < 0)
+ if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", our->name, NULL) < 0)
die(_("unable to update HEAD"));
if (!option_bare) {
- update_ref(msg, "HEAD", &our->old_oid, NULL, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository),
+ msg, "HEAD", &our->old_oid, NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
install_branch_config(0, head, remote_name, our->name);
}
} else if (our) {
struct commit *c = lookup_commit_reference(the_repository,
&our->old_oid);
/* --branch specifies a non-branch (i.e. tags), detach HEAD */
- update_ref(msg, "HEAD", &c->object.oid, NULL, REF_NO_DEREF,
- UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), msg,
+ "HEAD", &c->object.oid, NULL, REF_NO_DEREF,
+ UPDATE_REFS_DIE_ON_ERR);
} else if (remote) {
/*
* We know remote HEAD points to a non-branch, or
* HEAD points to a branch but we don't know which one.
* Detach HEAD in all these cases.
*/
- update_ref(msg, "HEAD", &remote->old_oid, NULL, REF_NO_DEREF,
- UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), 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)
+ if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", unborn, NULL) < 0)
die(_("unable to update HEAD"));
if (!option_bare)
install_branch_config(0, head, remote_name, unborn);
@@ -704,7 +737,8 @@ static int checkout(int submodule_progress, int filter_submodules)
if (option_no_checkout)
return 0;
- head = resolve_refdup("HEAD", RESOLVE_REF_READING, &oid, NULL);
+ head = refs_resolve_refdup(get_main_ref_store(the_repository), "HEAD",
+ RESOLVE_REF_READING, &oid, NULL);
if (!head) {
warning(_("remote HEAD refers to nonexistent ref, "
"unable to checkout"));
@@ -731,8 +765,8 @@ static int checkout(int submodule_progress, int filter_submodules)
opts.preserve_ignored = 0;
opts.fn = oneway_merge;
opts.verbose_update = (option_verbosity >= 0);
- opts.src_index = &the_index;
- opts.dst_index = &the_index;
+ opts.src_index = the_repository->index;
+ opts.dst_index = the_repository->index;
init_checkout_metadata(&opts.meta, head, &oid, NULL);
tree = parse_tree_indirect(&oid);
@@ -746,7 +780,7 @@ static int checkout(int submodule_progress, int filter_submodules)
free(head);
- if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
+ if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
die(_("unable to write new index file"));
err |= run_hooks_l("post-checkout", oid_to_hex(null_oid()),
@@ -938,6 +972,8 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
int hash_algo;
unsigned int ref_storage_format = REF_STORAGE_FORMAT_UNKNOWN;
const int do_not_override_repo_unix_permissions = -1;
+ const char *template_dir;
+ char *template_dir_dup = NULL;
struct transport_ls_refs_options transport_ls_refs_options =
TRANSPORT_LS_REFS_OPTIONS_INIT;
@@ -957,6 +993,13 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
usage_msg_opt(_("You must specify a repository to clone."),
builtin_clone_usage, builtin_clone_options);
+ xsetenv("GIT_CLONE_PROTECTION_ACTIVE", "true", 0 /* allow user override */);
+ template_dir = get_template_dir(option_template);
+ if (*template_dir && !is_absolute_path(template_dir))
+ template_dir = template_dir_dup =
+ absolute_pathdup(template_dir);
+ xsetenv("GIT_CLONE_TEMPLATE_DIR", template_dir, 1);
+
if (option_depth || option_since || option_not.nr)
deepen = 1;
if (option_single_branch == -1)
@@ -1118,7 +1161,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
* repository, and reference backends may persist that information into
* their on-disk data structures.
*/
- init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN,
+ init_db(git_dir, real_git_dir, template_dir, GIT_HASH_UNKNOWN,
ref_storage_format, NULL,
do_not_override_repo_unix_permissions, INIT_DB_QUIET | INIT_DB_SKIP_REFDB);
@@ -1507,6 +1550,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
free(dir);
free(path);
free(repo_to_free);
+ free(template_dir_dup);
junk_mode = JUNK_LEAVE_ALL;
transport_ls_refs_options_release(&transport_ls_refs_options);
diff --git a/builtin/commit.c b/builtin/commit.c
index 6e1484446b..78bfae2164 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -5,7 +5,6 @@
* Based on git-commit.sh by Junio C Hamano and Linus Torvalds
*/
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "advice.h"
#include "config.h"
@@ -38,6 +37,7 @@
#include "commit-reach.h"
#include "commit-graph.h"
#include "pretty.h"
+#include "trailer.h"
static const char * const builtin_commit_usage[] = {
N_("git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n"
@@ -142,14 +142,6 @@ static struct strbuf message = STRBUF_INIT;
static enum wt_status_format status_format = STATUS_FORMAT_UNSPECIFIED;
-static int opt_pass_trailer(const struct option *opt, const char *arg, int unset)
-{
- BUG_ON_OPT_NEG(unset);
-
- strvec_pushl(opt->value, "--trailer", arg, NULL);
- return 0;
-}
-
static int opt_parse_porcelain(const struct option *opt, const char *arg, int unset)
{
enum wt_status_format *value = (enum wt_status_format *)opt->value;
@@ -266,19 +258,19 @@ static int list_paths(struct string_list *list, const char *with_tree,
if (with_tree) {
char *max_prefix = common_prefix(pattern);
- overlay_tree_on_index(&the_index, with_tree, max_prefix);
+ overlay_tree_on_index(the_repository->index, with_tree, max_prefix);
free(max_prefix);
}
/* TODO: audit for interaction with sparse-index. */
- ensure_full_index(&the_index);
- for (i = 0; i < the_index.cache_nr; i++) {
- const struct cache_entry *ce = the_index.cache[i];
+ ensure_full_index(the_repository->index);
+ for (i = 0; i < the_repository->index->cache_nr; i++) {
+ const struct cache_entry *ce = the_repository->index->cache[i];
struct string_list_item *item;
if (ce->ce_flags & CE_UPDATE)
continue;
- if (!ce_path_match(&the_index, ce, pattern, m))
+ if (!ce_path_match(the_repository->index, ce, pattern, m))
continue;
item = string_list_insert(list, ce->name);
if (ce_skip_worktree(ce))
@@ -302,10 +294,10 @@ static void add_remove_files(struct string_list *list)
continue;
if (!lstat(p->string, &st)) {
- if (add_to_index(&the_index, p->string, &st, 0))
+ if (add_to_index(the_repository->index, p->string, &st, 0))
die(_("updating files failed"));
} else
- remove_file_from_index(&the_index, p->string);
+ remove_file_from_index(the_repository->index, p->string);
}
}
@@ -316,7 +308,7 @@ static void create_base_index(const struct commit *current_head)
struct tree_desc t;
if (!current_head) {
- discard_index(&the_index);
+ discard_index(the_repository->index);
return;
}
@@ -324,8 +316,8 @@ static void create_base_index(const struct commit *current_head)
opts.head_idx = 1;
opts.index_only = 1;
opts.merge = 1;
- opts.src_index = &the_index;
- opts.dst_index = &the_index;
+ opts.src_index = the_repository->index;
+ opts.dst_index = the_repository->index;
opts.fn = oneway_merge;
tree = parse_tree_indirect(&current_head->object.oid);
@@ -344,7 +336,7 @@ static void refresh_cache_or_die(int refresh_flags)
* refresh_flags contains REFRESH_QUIET, so the only errors
* are for unmerged entries.
*/
- if (refresh_index(&the_index, refresh_flags | REFRESH_IN_PORCELAIN, NULL, NULL, NULL))
+ if (refresh_index(the_repository->index, refresh_flags | REFRESH_IN_PORCELAIN, NULL, NULL, NULL))
die_resolve_conflict("commit");
}
@@ -393,7 +385,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
refresh_cache_or_die(refresh_flags);
- if (write_locked_index(&the_index, &index_lock, 0))
+ if (write_locked_index(the_repository->index, &index_lock, 0))
die(_("unable to create temporary index"));
old_repo_index_file = the_repository->index_file;
@@ -412,13 +404,13 @@ static const char *prepare_index(const char **argv, const char *prefix,
unsetenv(INDEX_ENVIRONMENT);
FREE_AND_NULL(old_index_env);
- discard_index(&the_index);
- read_index_from(&the_index, get_lock_file_path(&index_lock),
+ discard_index(the_repository->index);
+ read_index_from(the_repository->index, get_lock_file_path(&index_lock),
get_git_dir());
- if (cache_tree_update(&the_index, WRITE_TREE_SILENT) == 0) {
+ if (cache_tree_update(the_repository->index, WRITE_TREE_SILENT) == 0) {
if (reopen_lock_file(&index_lock) < 0)
die(_("unable to write index file"));
- if (write_locked_index(&the_index, &index_lock, 0))
+ if (write_locked_index(the_repository->index, &index_lock, 0))
die(_("unable to update temporary index"));
} else
warning(_("Failed to update main cache tree"));
@@ -450,8 +442,8 @@ static const char *prepare_index(const char **argv, const char *prefix,
exit(128);
refresh_cache_or_die(refresh_flags);
- cache_tree_update(&the_index, WRITE_TREE_SILENT);
- if (write_locked_index(&the_index, &index_lock, 0))
+ cache_tree_update(the_repository->index, WRITE_TREE_SILENT);
+ if (write_locked_index(the_repository->index, &index_lock, 0))
die(_("unable to write new index file"));
commit_style = COMMIT_NORMAL;
ret = get_lock_file_path(&index_lock);
@@ -472,10 +464,10 @@ static const char *prepare_index(const char **argv, const char *prefix,
repo_hold_locked_index(the_repository, &index_lock,
LOCK_DIE_ON_ERROR);
refresh_cache_or_die(refresh_flags);
- if (the_index.cache_changed
- || !cache_tree_fully_valid(the_index.cache_tree))
- cache_tree_update(&the_index, WRITE_TREE_SILENT);
- if (write_locked_index(&the_index, &index_lock,
+ if (the_repository->index->cache_changed
+ || !cache_tree_fully_valid(the_repository->index->cache_tree))
+ cache_tree_update(the_repository->index, WRITE_TREE_SILENT);
+ if (write_locked_index(the_repository->index, &index_lock,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
die(_("unable to write new index file"));
commit_style = COMMIT_AS_IS;
@@ -516,15 +508,15 @@ static const char *prepare_index(const char **argv, const char *prefix,
if (list_paths(&partial, !current_head ? NULL : "HEAD", &pathspec))
exit(1);
- discard_index(&the_index);
+ discard_index(the_repository->index);
if (repo_read_index(the_repository) < 0)
die(_("cannot read the index"));
repo_hold_locked_index(the_repository, &index_lock, LOCK_DIE_ON_ERROR);
add_remove_files(&partial);
- refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL);
- cache_tree_update(&the_index, WRITE_TREE_SILENT);
- if (write_locked_index(&the_index, &index_lock, 0))
+ refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL, NULL);
+ cache_tree_update(the_repository->index, WRITE_TREE_SILENT);
+ if (write_locked_index(the_repository->index, &index_lock, 0))
die(_("unable to write new index file"));
hold_lock_file_for_update(&false_lock,
@@ -534,14 +526,14 @@ static const char *prepare_index(const char **argv, const char *prefix,
create_base_index(current_head);
add_remove_files(&partial);
- refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL);
+ refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL, NULL);
- if (write_locked_index(&the_index, &false_lock, 0))
+ if (write_locked_index(the_repository->index, &false_lock, 0))
die(_("unable to write temporary index file"));
- discard_index(&the_index);
+ discard_index(the_repository->index);
ret = get_lock_file_path(&false_lock);
- read_index_from(&the_index, ret, get_git_dir());
+ read_index_from(the_repository->index, ret, get_git_dir());
out:
string_list_clear(&partial, 0);
clear_pathspec(&pathspec);
@@ -999,7 +991,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
struct object_id oid;
const char *parent = "HEAD";
- if (!the_index.initialized && repo_read_index(the_repository) < 0)
+ if (!the_repository->index->initialized && repo_read_index(the_repository) < 0)
die(_("Cannot read index"));
if (amend)
@@ -1009,11 +1001,11 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
int i, ita_nr = 0;
/* TODO: audit for interaction with sparse-index. */
- ensure_full_index(&the_index);
- for (i = 0; i < the_index.cache_nr; i++)
- if (ce_intent_to_add(the_index.cache[i]))
+ ensure_full_index(the_repository->index);
+ for (i = 0; i < the_repository->index->cache_nr; i++)
+ if (ce_intent_to_add(the_repository->index->cache[i]))
ita_nr++;
- committable = the_index.cache_nr - ita_nr > 0;
+ committable = the_repository->index->cache_nr - ita_nr > 0;
} else {
/*
* Unless the user did explicitly request a submodule
@@ -1038,14 +1030,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
fclose(s->fp);
if (trailer_args.nr) {
- struct child_process run_trailer = CHILD_PROCESS_INIT;
-
- strvec_pushl(&run_trailer.args, "interpret-trailers",
- "--in-place", "--no-divider",
- git_path_commit_editmsg(), NULL);
- strvec_pushv(&run_trailer.args, trailer_args.v);
- run_trailer.git_cmd = 1;
- if (run_command(&run_trailer))
+ if (amend_file_with_trailers(git_path_commit_editmsg(), &trailer_args))
die(_("unable to pass trailers to --trailers"));
strvec_clear(&trailer_args);
}
@@ -1081,11 +1066,11 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
* and could have updated it. We must do this before we invoke
* the editor and after we invoke run_status above.
*/
- discard_index(&the_index);
+ discard_index(the_repository->index);
}
- read_index_from(&the_index, index_file, get_git_dir());
+ read_index_from(the_repository->index, index_file, get_git_dir());
- if (cache_tree_update(&the_index, 0)) {
+ if (cache_tree_update(the_repository->index, 0)) {
error(_("Error building trees"));
return 0;
}
@@ -1586,7 +1571,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
status_format != STATUS_FORMAT_PORCELAIN_V2)
progress_flag = REFRESH_PROGRESS;
repo_read_index(the_repository);
- refresh_index(&the_index,
+ refresh_index(the_repository->index,
REFRESH_QUIET|REFRESH_UNMERGED|progress_flag,
&s.pathspec, NULL, NULL);
@@ -1673,7 +1658,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
OPT_STRING(0, "fixup", &fixup_message, N_("[(amend|reword):]commit"), N_("use autosquash formatted message to fixup or amend/reword specified commit")),
OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
- OPT_CALLBACK_F(0, "trailer", &trailer_args, N_("trailer"), N_("add custom trailer(s)"), PARSE_OPT_NONEG, opt_pass_trailer),
+ OPT_PASSTHRU_ARGV(0, "trailer", &trailer_args, N_("trailer"), N_("add custom trailer(s)"), PARSE_OPT_NONEG),
OPT_BOOL('s', "signoff", &signoff, N_("add a Signed-off-by trailer")),
OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
@@ -1856,7 +1841,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
append_merge_tag_headers(parents, &tail);
}
- if (commit_tree_extended(sb.buf, sb.len, &the_index.cache_tree->oid,
+ if (commit_tree_extended(sb.buf, sb.len, &the_repository->index->cache_tree->oid,
parents, &oid, author_ident.buf, NULL,
sign_commit, extra)) {
rollback_index_files();
diff --git a/builtin/config.c b/builtin/config.c
index 0015620dde..945a1fd82d 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -16,59 +16,111 @@
#include "worktree.h"
static const char *const builtin_config_usage[] = {
- N_("git config [<options>]"),
+ N_("git config list [<file-option>] [<display-option>] [--includes]"),
+ N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] <name>"),
+ N_("git config set [<file-option>] [--type=<type>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
+ N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
+ N_("git config rename-section [<file-option>] <old-name> <new-name>"),
+ N_("git config remove-section [<file-option>] <name>"),
+ N_("git config edit [<file-option>]"),
+ N_("git config [<file-option>] --get-colorbool <name> [<stdout-is-tty>]"),
NULL
};
-static char *key;
-static regex_t *key_regexp;
-static const char *value_pattern;
-static regex_t *regexp;
-static int show_keys;
-static int omit_values;
-static int use_key_regexp;
-static int do_all;
-static int do_not_match;
-static char delim = '=';
-static char key_delim = ' ';
-static char term = '\n';
-
-static int use_global_config, use_system_config, use_local_config;
-static int use_worktree_config;
-static struct git_config_source given_config_source;
-static int actions, type;
-static char *default_value;
-static int end_nul;
-static int respect_includes_opt = -1;
-static struct config_options config_options;
-static int show_origin;
-static int show_scope;
-static int fixed_value;
-static const char *comment;
-
-#define ACTION_GET (1<<0)
-#define ACTION_GET_ALL (1<<1)
-#define ACTION_GET_REGEXP (1<<2)
-#define ACTION_REPLACE_ALL (1<<3)
-#define ACTION_ADD (1<<4)
-#define ACTION_UNSET (1<<5)
-#define ACTION_UNSET_ALL (1<<6)
-#define ACTION_RENAME_SECTION (1<<7)
-#define ACTION_REMOVE_SECTION (1<<8)
-#define ACTION_LIST (1<<9)
-#define ACTION_EDIT (1<<10)
-#define ACTION_SET (1<<11)
-#define ACTION_SET_ALL (1<<12)
-#define ACTION_GET_COLOR (1<<13)
-#define ACTION_GET_COLORBOOL (1<<14)
-#define ACTION_GET_URLMATCH (1<<15)
-
-/*
- * The actions "ACTION_LIST | ACTION_GET_*" which may produce more than
- * one line of output and which should therefore be paged.
- */
-#define PAGING_ACTIONS (ACTION_LIST | ACTION_GET_ALL | \
- ACTION_GET_REGEXP | ACTION_GET_URLMATCH)
+static const char *const builtin_config_list_usage[] = {
+ N_("git config list [<file-option>] [<display-option>] [--includes]"),
+ NULL
+};
+
+static const char *const builtin_config_get_usage[] = {
+ N_("git config get [<file-option>] [<display-option>] [--includes] [--all] [--regexp=<regexp>] [--value=<value>] [--fixed-value] [--default=<default>] <name>"),
+ NULL
+};
+
+static const char *const builtin_config_set_usage[] = {
+ N_("git config set [<file-option>] [--type=<type>] [--comment=<message>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
+ NULL
+};
+
+static const char *const builtin_config_unset_usage[] = {
+ N_("git config unset [<file-option>] [--all] [--value=<value>] [--fixed-value] <name> <value>"),
+ NULL
+};
+
+static const char *const builtin_config_rename_section_usage[] = {
+ N_("git config rename-section [<file-option>] <old-name> <new-name>"),
+ NULL
+};
+
+static const char *const builtin_config_remove_section_usage[] = {
+ N_("git config remove-section [<file-option>] <name>"),
+ NULL
+};
+
+static const char *const builtin_config_edit_usage[] = {
+ N_("git config edit [<file-option>]"),
+ NULL
+};
+
+#define CONFIG_LOCATION_OPTIONS(opts) \
+ OPT_GROUP(N_("Config file location")), \
+ OPT_BOOL(0, "global", &opts.use_global_config, N_("use global config file")), \
+ OPT_BOOL(0, "system", &opts.use_system_config, N_("use system config file")), \
+ OPT_BOOL(0, "local", &opts.use_local_config, N_("use repository config file")), \
+ OPT_BOOL(0, "worktree", &opts.use_worktree_config, N_("use per-worktree config file")), \
+ OPT_STRING('f', "file", &opts.source.file, N_("file"), N_("use given config file")), \
+ OPT_STRING(0, "blob", &opts.source.blob, N_("blob-id"), N_("read config from given blob object"))
+
+struct config_location_options {
+ struct git_config_source source;
+ struct config_options options;
+ int use_global_config;
+ int use_system_config;
+ int use_local_config;
+ int use_worktree_config;
+ int respect_includes_opt;
+};
+#define CONFIG_LOCATION_OPTIONS_INIT { \
+ .respect_includes_opt = -1, \
+}
+
+#define CONFIG_TYPE_OPTIONS(type) \
+ OPT_GROUP(N_("Type")), \
+ OPT_CALLBACK('t', "type", &type, N_("type"), N_("value is given this type"), option_parse_type), \
+ OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL), \
+ OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT), \
+ OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT), \
+ OPT_CALLBACK_VALUE(0, "bool-or-str", &type, N_("value is --bool or string"), TYPE_BOOL_OR_STR), \
+ OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH), \
+ OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE)
+
+#define CONFIG_DISPLAY_OPTIONS(opts) \
+ OPT_GROUP(N_("Display options")), \
+ OPT_BOOL('z', "null", &opts.end_nul, N_("terminate values with NUL byte")), \
+ OPT_BOOL(0, "name-only", &opts.omit_values, N_("show variable names only")), \
+ OPT_BOOL(0, "show-origin", &opts.show_origin, N_("show origin of config (file, standard input, blob, command line)")), \
+ OPT_BOOL(0, "show-scope", &opts.show_scope, N_("show scope of config (worktree, local, global, system, command)")), \
+ OPT_BOOL(0, "show-names", &opts.show_keys, N_("show config keys in addition to their values")), \
+ CONFIG_TYPE_OPTIONS(opts.type)
+
+struct config_display_options {
+ int end_nul;
+ int omit_values;
+ int show_origin;
+ int show_scope;
+ int show_keys;
+ int type;
+ char *default_value;
+ /* Populated via `display_options_init()`. */
+ int term;
+ int delim;
+ int key_delim;
+};
+#define CONFIG_DISPLAY_OPTIONS_INIT { \
+ .term = '\n', \
+ .delim = '=', \
+ .key_delim = ' ', \
+}
#define TYPE_BOOL 1
#define TYPE_INT 2
@@ -82,8 +134,6 @@ static const char *comment;
{ OPTION_CALLBACK, (s), (l), (v), NULL, (h), PARSE_OPT_NOARG | \
PARSE_OPT_NONEG, option_parse_type, (i) }
-static NORETURN void usage_builtin_config(void);
-
static int option_parse_type(const struct option *opt, const char *arg,
int unset)
{
@@ -128,61 +178,13 @@ static int option_parse_type(const struct option *opt, const char *arg,
* --type=int'.
*/
error(_("only one type at a time"));
- usage_builtin_config();
+ exit(129);
}
*to_type = new_type;
return 0;
}
-static struct option builtin_config_options[] = {
- OPT_GROUP(N_("Config file location")),
- OPT_BOOL(0, "global", &use_global_config, N_("use global config file")),
- OPT_BOOL(0, "system", &use_system_config, N_("use system config file")),
- OPT_BOOL(0, "local", &use_local_config, N_("use repository config file")),
- OPT_BOOL(0, "worktree", &use_worktree_config, N_("use per-worktree config file")),
- OPT_STRING('f', "file", &given_config_source.file, N_("file"), N_("use given config file")),
- OPT_STRING(0, "blob", &given_config_source.blob, N_("blob-id"), N_("read config from given blob object")),
- OPT_GROUP(N_("Action")),
- OPT_BIT(0, "get", &actions, N_("get value: name [value-pattern]"), ACTION_GET),
- OPT_BIT(0, "get-all", &actions, N_("get all values: key [value-pattern]"), ACTION_GET_ALL),
- OPT_BIT(0, "get-regexp", &actions, N_("get values for regexp: name-regex [value-pattern]"), ACTION_GET_REGEXP),
- OPT_BIT(0, "get-urlmatch", &actions, N_("get value specific for the URL: section[.var] URL"), ACTION_GET_URLMATCH),
- OPT_BIT(0, "replace-all", &actions, N_("replace all matching variables: name value [value-pattern]"), ACTION_REPLACE_ALL),
- OPT_BIT(0, "add", &actions, N_("add a new variable: name value"), ACTION_ADD),
- OPT_BIT(0, "unset", &actions, N_("remove a variable: name [value-pattern]"), ACTION_UNSET),
- OPT_BIT(0, "unset-all", &actions, N_("remove all matches: name [value-pattern]"), ACTION_UNSET_ALL),
- OPT_BIT(0, "rename-section", &actions, N_("rename section: old-name new-name"), ACTION_RENAME_SECTION),
- OPT_BIT(0, "remove-section", &actions, N_("remove a section: name"), ACTION_REMOVE_SECTION),
- OPT_BIT('l', "list", &actions, N_("list all"), ACTION_LIST),
- OPT_BOOL(0, "fixed-value", &fixed_value, N_("use string equality when comparing values to 'value-pattern'")),
- OPT_BIT('e', "edit", &actions, N_("open an editor"), ACTION_EDIT),
- OPT_BIT(0, "get-color", &actions, N_("find the color configured: slot [default]"), ACTION_GET_COLOR),
- OPT_BIT(0, "get-colorbool", &actions, N_("find the color setting: slot [stdout-is-tty]"), ACTION_GET_COLORBOOL),
- OPT_GROUP(N_("Type")),
- OPT_CALLBACK('t', "type", &type, N_("type"), N_("value is given this type"), option_parse_type),
- OPT_CALLBACK_VALUE(0, "bool", &type, N_("value is \"true\" or \"false\""), TYPE_BOOL),
- OPT_CALLBACK_VALUE(0, "int", &type, N_("value is decimal number"), TYPE_INT),
- OPT_CALLBACK_VALUE(0, "bool-or-int", &type, N_("value is --bool or --int"), TYPE_BOOL_OR_INT),
- OPT_CALLBACK_VALUE(0, "bool-or-str", &type, N_("value is --bool or string"), TYPE_BOOL_OR_STR),
- OPT_CALLBACK_VALUE(0, "path", &type, N_("value is a path (file or directory name)"), TYPE_PATH),
- OPT_CALLBACK_VALUE(0, "expiry-date", &type, N_("value is an expiry date"), TYPE_EXPIRY_DATE),
- OPT_GROUP(N_("Other")),
- OPT_BOOL('z', "null", &end_nul, N_("terminate values with NUL byte")),
- OPT_BOOL(0, "name-only", &omit_values, N_("show variable names only")),
- OPT_BOOL(0, "includes", &respect_includes_opt, N_("respect include directives on lookup")),
- OPT_BOOL(0, "show-origin", &show_origin, N_("show origin of config (file, standard input, blob, command line)")),
- OPT_BOOL(0, "show-scope", &show_scope, N_("show scope of config (worktree, local, global, system, command)")),
- OPT_STRING(0, "default", &default_value, N_("value"), N_("with --get, use default value when missing entry")),
- OPT_STRING(0, "comment", &comment, N_("value"), N_("human-readable comment string (# will be prepended as needed)")),
- OPT_END(),
-};
-
-static NORETURN void usage_builtin_config(void)
-{
- usage_with_options(builtin_config_usage, builtin_config_options);
-}
-
static void check_argc(int argc, int min, int max)
{
if (argc >= min && argc <= max)
@@ -192,27 +194,29 @@ static void check_argc(int argc, int min, int max)
else
error(_("wrong number of arguments, should be from %d to %d"),
min, max);
- usage_builtin_config();
+ exit(129);
}
-static void show_config_origin(const struct key_value_info *kvi,
+static void show_config_origin(const struct config_display_options *opts,
+ const struct key_value_info *kvi,
struct strbuf *buf)
{
- const char term = end_nul ? '\0' : '\t';
+ const char term = opts->end_nul ? '\0' : '\t';
strbuf_addstr(buf, config_origin_type_name(kvi->origin_type));
strbuf_addch(buf, ':');
- if (end_nul)
+ if (opts->end_nul)
strbuf_addstr(buf, kvi->filename ? kvi->filename : "");
else
quote_c_style(kvi->filename ? kvi->filename : "", buf, NULL, 0);
strbuf_addch(buf, term);
}
-static void show_config_scope(const struct key_value_info *kvi,
+static void show_config_scope(const struct config_display_options *opts,
+ const struct key_value_info *kvi,
struct strbuf *buf)
{
- const char term = end_nul ? '\0' : '\t';
+ const char term = opts->end_nul ? '\0' : '\t';
const char *scope = config_scope_name(kvi->scope);
strbuf_addstr(buf, N_(scope));
@@ -221,24 +225,25 @@ static void show_config_scope(const struct key_value_info *kvi,
static int show_all_config(const char *key_, const char *value_,
const struct config_context *ctx,
- void *cb UNUSED)
+ void *cb)
{
+ const struct config_display_options *opts = cb;
const struct key_value_info *kvi = ctx->kvi;
- if (show_origin || show_scope) {
+ if (opts->show_origin || opts->show_scope) {
struct strbuf buf = STRBUF_INIT;
- if (show_scope)
- show_config_scope(kvi, &buf);
- if (show_origin)
- show_config_origin(kvi, &buf);
+ if (opts->show_scope)
+ show_config_scope(opts, kvi, &buf);
+ if (opts->show_origin)
+ show_config_origin(opts, kvi, &buf);
/* Use fwrite as "buf" can contain \0's if "end_null" is set. */
fwrite(buf.buf, 1, buf.len, stdout);
strbuf_release(&buf);
}
- if (!omit_values && value_)
- printf("%s%c%s%c", key_, delim, value_, term);
+ if (!opts->omit_values && value_)
+ printf("%s%c%s%c", key_, opts->delim, value_, opts->term);
else
- printf("%s%c", key_, term);
+ printf("%s%c", key_, opts->term);
return 0;
}
@@ -248,26 +253,27 @@ struct strbuf_list {
int alloc;
};
-static int format_config(struct strbuf *buf, const char *key_,
+static int format_config(const struct config_display_options *opts,
+ struct strbuf *buf, const char *key_,
const char *value_, const struct key_value_info *kvi)
{
- if (show_scope)
- show_config_scope(kvi, buf);
- if (show_origin)
- show_config_origin(kvi, buf);
- if (show_keys)
+ if (opts->show_scope)
+ show_config_scope(opts, kvi, buf);
+ if (opts->show_origin)
+ show_config_origin(opts, kvi, buf);
+ if (opts->show_keys)
strbuf_addstr(buf, key_);
- if (!omit_values) {
- if (show_keys)
- strbuf_addch(buf, key_delim);
+ if (!opts->omit_values) {
+ if (opts->show_keys)
+ strbuf_addch(buf, opts->key_delim);
- if (type == TYPE_INT)
+ if (opts->type == TYPE_INT)
strbuf_addf(buf, "%"PRId64,
git_config_int64(key_, value_ ? value_ : "", kvi));
- else if (type == TYPE_BOOL)
+ else if (opts->type == TYPE_BOOL)
strbuf_addstr(buf, git_config_bool(key_, value_) ?
"true" : "false");
- else if (type == TYPE_BOOL_OR_INT) {
+ else if (opts->type == TYPE_BOOL_OR_INT) {
int is_bool, v;
v = git_config_bool_or_int(key_, value_, kvi,
&is_bool);
@@ -275,24 +281,24 @@ static int format_config(struct strbuf *buf, const char *key_,
strbuf_addstr(buf, v ? "true" : "false");
else
strbuf_addf(buf, "%d", v);
- } else if (type == TYPE_BOOL_OR_STR) {
+ } else if (opts->type == TYPE_BOOL_OR_STR) {
int v = git_parse_maybe_bool(value_);
if (v < 0)
strbuf_addstr(buf, value_);
else
strbuf_addstr(buf, v ? "true" : "false");
- } else if (type == TYPE_PATH) {
+ } else if (opts->type == TYPE_PATH) {
const char *v;
if (git_config_pathname(&v, key_, value_) < 0)
return -1;
strbuf_addstr(buf, v);
free((char *)v);
- } else if (type == TYPE_EXPIRY_DATE) {
+ } else if (opts->type == TYPE_EXPIRY_DATE) {
timestamp_t t;
if (git_config_expiry_date(&t, key_, value_) < 0)
return -1;
strbuf_addf(buf, "%"PRItime, t);
- } else if (type == TYPE_COLOR) {
+ } else if (opts->type == TYPE_COLOR) {
char v[COLOR_MAXLEN];
if (git_config_color(v, key_, value_) < 0)
return -1;
@@ -301,43 +307,73 @@ static int format_config(struct strbuf *buf, const char *key_,
strbuf_addstr(buf, value_);
} else {
/* Just show the key name; back out delimiter */
- if (show_keys)
+ if (opts->show_keys)
strbuf_setlen(buf, buf->len - 1);
}
}
- strbuf_addch(buf, term);
+ strbuf_addch(buf, opts->term);
return 0;
}
+#define GET_VALUE_ALL (1 << 0)
+#define GET_VALUE_KEY_REGEXP (1 << 1)
+
+struct collect_config_data {
+ const struct config_display_options *display_opts;
+ struct strbuf_list *values;
+ const char *value_pattern;
+ const char *key;
+ regex_t *regexp;
+ regex_t *key_regexp;
+ int do_not_match;
+ unsigned get_value_flags;
+ unsigned flags;
+};
+
static int collect_config(const char *key_, const char *value_,
const struct config_context *ctx, void *cb)
{
- struct strbuf_list *values = cb;
+ struct collect_config_data *data = cb;
+ struct strbuf_list *values = data->values;
const struct key_value_info *kvi = ctx->kvi;
- if (!use_key_regexp && strcmp(key_, key))
+ if (!(data->get_value_flags & GET_VALUE_KEY_REGEXP) &&
+ strcmp(key_, data->key))
return 0;
- if (use_key_regexp && regexec(key_regexp, key_, 0, NULL, 0))
+ if ((data->get_value_flags & GET_VALUE_KEY_REGEXP) &&
+ regexec(data->key_regexp, key_, 0, NULL, 0))
return 0;
- if (fixed_value && strcmp(value_pattern, (value_?value_:"")))
+ if ((data->flags & CONFIG_FLAGS_FIXED_VALUE) &&
+ strcmp(data->value_pattern, (value_?value_:"")))
return 0;
- if (regexp != NULL &&
- (do_not_match ^ !!regexec(regexp, (value_?value_:""), 0, NULL, 0)))
+ if (data->regexp &&
+ (data->do_not_match ^ !!regexec(data->regexp, (value_?value_:""), 0, NULL, 0)))
return 0;
ALLOC_GROW(values->items, values->nr + 1, values->alloc);
strbuf_init(&values->items[values->nr], 0);
- return format_config(&values->items[values->nr++], key_, value_, kvi);
+ return format_config(data->display_opts, &values->items[values->nr++],
+ key_, value_, kvi);
}
-static int get_value(const char *key_, const char *regex_, unsigned flags)
+static int get_value(const struct config_location_options *opts,
+ const struct config_display_options *display_opts,
+ const char *key_, const char *regex_,
+ unsigned get_value_flags, unsigned flags)
{
int ret = CONFIG_GENERIC_ERROR;
struct strbuf_list values = {NULL};
+ struct collect_config_data data = {
+ .display_opts = display_opts,
+ .values = &values,
+ .get_value_flags = get_value_flags,
+ .flags = flags,
+ };
+ char *key = NULL;
int i;
- if (use_key_regexp) {
+ if (get_value_flags & GET_VALUE_KEY_REGEXP) {
char *tl;
/*
@@ -354,10 +390,10 @@ static int get_value(const char *key_, const char *regex_, unsigned flags)
for (tl = key; *tl && *tl != '.'; tl++)
*tl = tolower(*tl);
- key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
- if (regcomp(key_regexp, key, REG_EXTENDED)) {
+ data.key_regexp = (regex_t*)xmalloc(sizeof(regex_t));
+ if (regcomp(data.key_regexp, key, REG_EXTENDED)) {
error(_("invalid key pattern: %s"), key_);
- FREE_AND_NULL(key_regexp);
+ FREE_AND_NULL(data.key_regexp);
ret = CONFIG_INVALID_PATTERN;
goto free_strings;
}
@@ -366,30 +402,32 @@ static int get_value(const char *key_, const char *regex_, unsigned flags)
ret = CONFIG_INVALID_KEY;
goto free_strings;
}
+
+ data.key = key;
}
if (regex_ && (flags & CONFIG_FLAGS_FIXED_VALUE))
- value_pattern = regex_;
+ data.value_pattern = regex_;
else if (regex_) {
if (regex_[0] == '!') {
- do_not_match = 1;
+ data.do_not_match = 1;
regex_++;
}
- regexp = (regex_t*)xmalloc(sizeof(regex_t));
- if (regcomp(regexp, regex_, REG_EXTENDED)) {
+ data.regexp = (regex_t*)xmalloc(sizeof(regex_t));
+ if (regcomp(data.regexp, regex_, REG_EXTENDED)) {
error(_("invalid pattern: %s"), regex_);
- FREE_AND_NULL(regexp);
+ FREE_AND_NULL(data.regexp);
ret = CONFIG_INVALID_PATTERN;
goto free_strings;
}
}
- config_with_options(collect_config, &values,
- &given_config_source, the_repository,
- &config_options);
+ config_with_options(collect_config, &data,
+ &opts->source, the_repository,
+ &opts->options);
- if (!values.nr && default_value) {
+ if (!values.nr && display_opts->default_value) {
struct key_value_info kvi = KVI_INIT;
struct strbuf *item;
@@ -397,16 +435,17 @@ static int get_value(const char *key_, const char *regex_, unsigned flags)
ALLOC_GROW(values.items, values.nr + 1, values.alloc);
item = &values.items[values.nr++];
strbuf_init(item, 0);
- if (format_config(item, key_, default_value, &kvi) < 0)
+ if (format_config(display_opts, item, key_,
+ display_opts->default_value, &kvi) < 0)
die(_("failed to format default config value: %s"),
- default_value);
+ display_opts->default_value);
}
ret = !values.nr;
for (i = 0; i < values.nr; i++) {
struct strbuf *buf = values.items + i;
- if (do_all || i == values.nr - 1)
+ if ((get_value_flags & GET_VALUE_ALL) || i == values.nr - 1)
fwrite(buf->buf, 1, buf->len, stdout);
strbuf_release(buf);
}
@@ -414,20 +453,20 @@ static int get_value(const char *key_, const char *regex_, unsigned flags)
free_strings:
free(key);
- if (key_regexp) {
- regfree(key_regexp);
- free(key_regexp);
+ if (data.key_regexp) {
+ regfree(data.key_regexp);
+ free(data.key_regexp);
}
- if (regexp) {
- regfree(regexp);
- free(regexp);
+ if (data.regexp) {
+ regfree(data.regexp);
+ free(data.regexp);
}
return ret;
}
static char *normalize_value(const char *key, const char *value,
- struct key_value_info *kvi)
+ int type, struct key_value_info *kvi)
{
if (!value)
return NULL;
@@ -478,97 +517,113 @@ static char *normalize_value(const char *key, const char *value,
BUG("cannot normalize type %d", type);
}
-static int get_color_found;
-static const char *get_color_slot;
-static const char *get_colorbool_slot;
-static char parsed_color[COLOR_MAXLEN];
+struct get_color_config_data {
+ int get_color_found;
+ const char *get_color_slot;
+ char parsed_color[COLOR_MAXLEN];
+};
static int git_get_color_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
- void *cb UNUSED)
+ void *cb)
{
- if (!strcmp(var, get_color_slot)) {
+ struct get_color_config_data *data = cb;
+
+ if (!strcmp(var, data->get_color_slot)) {
if (!value)
config_error_nonbool(var);
- if (color_parse(value, parsed_color) < 0)
+ if (color_parse(value, data->parsed_color) < 0)
return -1;
- get_color_found = 1;
+ data->get_color_found = 1;
}
return 0;
}
-static void get_color(const char *var, const char *def_color)
+static void get_color(const struct config_location_options *opts,
+ const char *var, const char *def_color)
{
- get_color_slot = var;
- get_color_found = 0;
- parsed_color[0] = '\0';
- config_with_options(git_get_color_config, NULL,
- &given_config_source, the_repository,
- &config_options);
-
- if (!get_color_found && def_color) {
- if (color_parse(def_color, parsed_color) < 0)
+ struct get_color_config_data data = {
+ .get_color_slot = var,
+ .parsed_color[0] = '\0',
+ };
+
+ config_with_options(git_get_color_config, &data,
+ &opts->source, the_repository,
+ &opts->options);
+
+ if (!data.get_color_found && def_color) {
+ if (color_parse(def_color, data.parsed_color) < 0)
die(_("unable to parse default color value"));
}
- fputs(parsed_color, stdout);
+ fputs(data.parsed_color, stdout);
}
-static int get_colorbool_found;
-static int get_diff_color_found;
-static int get_color_ui_found;
+struct get_colorbool_config_data {
+ int get_colorbool_found;
+ int get_diff_color_found;
+ int get_color_ui_found;
+ const char *get_colorbool_slot;
+};
+
static int git_get_colorbool_config(const char *var, const char *value,
const struct config_context *ctx UNUSED,
- void *data UNUSED)
+ void *cb)
{
- if (!strcmp(var, get_colorbool_slot))
- get_colorbool_found = git_config_colorbool(var, value);
+ struct get_colorbool_config_data *data = cb;
+
+ if (!strcmp(var, data->get_colorbool_slot))
+ data->get_colorbool_found = git_config_colorbool(var, value);
else if (!strcmp(var, "diff.color"))
- get_diff_color_found = git_config_colorbool(var, value);
+ data->get_diff_color_found = git_config_colorbool(var, value);
else if (!strcmp(var, "color.ui"))
- get_color_ui_found = git_config_colorbool(var, value);
+ data->get_color_ui_found = git_config_colorbool(var, value);
return 0;
}
-static int get_colorbool(const char *var, int print)
+static int get_colorbool(const struct config_location_options *opts,
+ const char *var, int print)
{
- get_colorbool_slot = var;
- get_colorbool_found = -1;
- get_diff_color_found = -1;
- get_color_ui_found = -1;
- config_with_options(git_get_colorbool_config, NULL,
- &given_config_source, the_repository,
- &config_options);
-
- if (get_colorbool_found < 0) {
- if (!strcmp(get_colorbool_slot, "color.diff"))
- get_colorbool_found = get_diff_color_found;
- if (get_colorbool_found < 0)
- get_colorbool_found = get_color_ui_found;
- }
-
- if (get_colorbool_found < 0)
+ struct get_colorbool_config_data data = {
+ .get_colorbool_slot = var,
+ .get_colorbool_found = -1,
+ .get_diff_color_found = -1,
+ .get_color_ui_found = -1,
+ };
+
+ config_with_options(git_get_colorbool_config, &data,
+ &opts->source, the_repository,
+ &opts->options);
+
+ if (data.get_colorbool_found < 0) {
+ if (!strcmp(data.get_colorbool_slot, "color.diff"))
+ data.get_colorbool_found = data.get_diff_color_found;
+ if (data.get_colorbool_found < 0)
+ data.get_colorbool_found = data.get_color_ui_found;
+ }
+
+ if (data.get_colorbool_found < 0)
/* default value if none found in config */
- get_colorbool_found = GIT_COLOR_AUTO;
+ data.get_colorbool_found = GIT_COLOR_AUTO;
- get_colorbool_found = want_color(get_colorbool_found);
+ data.get_colorbool_found = want_color(data.get_colorbool_found);
if (print) {
- printf("%s\n", get_colorbool_found ? "true" : "false");
+ printf("%s\n", data.get_colorbool_found ? "true" : "false");
return 0;
} else
- return get_colorbool_found ? 0 : 1;
+ return data.get_colorbool_found ? 0 : 1;
}
-static void check_write(void)
+static void check_write(const struct git_config_source *source)
{
- if (!given_config_source.file && !startup_info->have_repository)
+ if (!source->file && !startup_info->have_repository)
die(_("not in a git directory"));
- if (given_config_source.use_stdin)
+ if (source->use_stdin)
die(_("writing to stdin is not supported"));
- if (given_config_source.blob)
+ if (source->blob)
die(_("writing config blobs is not supported"));
}
@@ -605,10 +660,13 @@ static int urlmatch_collect_fn(const char *var, const char *value,
return 0;
}
-static int get_urlmatch(const char *var, const char *url)
+static int get_urlmatch(const struct config_location_options *opts,
+ const struct config_display_options *_display_opts,
+ const char *var, const char *url)
{
int ret;
char *section_tail;
+ struct config_display_options display_opts = *_display_opts;
struct string_list_item *item;
struct urlmatch_config config = URLMATCH_CONFIG_INIT;
struct string_list values = STRING_LIST_INIT_DUP;
@@ -625,15 +683,15 @@ static int get_urlmatch(const char *var, const char *url)
if (section_tail) {
*section_tail = '\0';
config.key = section_tail + 1;
- show_keys = 0;
+ display_opts.show_keys = 0;
} else {
config.key = NULL;
- show_keys = 1;
+ display_opts.show_keys = 1;
}
config_with_options(urlmatch_config_entry, &config,
- &given_config_source, the_repository,
- &config_options);
+ &opts->source, the_repository,
+ &opts->options);
ret = !values.nr;
@@ -641,7 +699,7 @@ static int get_urlmatch(const char *var, const char *url)
struct urlmatch_current_candidate_value *matched = item->util;
struct strbuf buf = STRBUF_INIT;
- format_config(&buf, item->string,
+ format_config(&display_opts, &buf, item->string,
matched->value_is_null ? NULL : matched->value.buf,
&matched->kvi);
fwrite(buf.buf, 1, buf.len, stdout);
@@ -671,47 +729,40 @@ static char *default_user_config(void)
return strbuf_detach(&buf, NULL);
}
-int cmd_config(int argc, const char **argv, const char *prefix)
+static void location_options_init(struct config_location_options *opts,
+ const char *prefix)
{
- int nongit = !startup_info->have_repository;
- char *value = NULL;
- int flags = 0;
- int ret = 0;
- struct key_value_info default_kvi = KVI_INIT;
-
- given_config_source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
-
- argc = parse_options(argc, argv, prefix, builtin_config_options,
- builtin_config_usage,
- PARSE_OPT_STOP_AT_NON_OPTION);
+ if (!opts->source.file)
+ opts->source.file = xstrdup_or_null(getenv(CONFIG_ENVIRONMENT));
+ else
+ opts->source.file = xstrdup(opts->source.file);
- if (use_global_config + use_system_config + use_local_config +
- use_worktree_config +
- !!given_config_source.file + !!given_config_source.blob > 1) {
+ if (opts->use_global_config + opts->use_system_config +
+ opts->use_local_config + opts->use_worktree_config +
+ !!opts->source.file + !!opts->source.blob > 1) {
error(_("only one config file at a time"));
- usage_builtin_config();
+ exit(129);
}
- if (nongit) {
- if (use_local_config)
+ if (!startup_info->have_repository) {
+ if (opts->use_local_config)
die(_("--local can only be used inside a git repository"));
- if (given_config_source.blob)
+ if (opts->source.blob)
die(_("--blob can only be used inside a git repository"));
- if (use_worktree_config)
+ if (opts->use_worktree_config)
die(_("--worktree can only be used inside a git repository"));
-
}
- if (given_config_source.file &&
- !strcmp(given_config_source.file, "-")) {
- given_config_source.file = NULL;
- given_config_source.use_stdin = 1;
- given_config_source.scope = CONFIG_SCOPE_COMMAND;
+ if (opts->source.file &&
+ !strcmp(opts->source.file, "-")) {
+ opts->source.file = NULL;
+ opts->source.use_stdin = 1;
+ opts->source.scope = CONFIG_SCOPE_COMMAND;
}
- if (use_global_config) {
- given_config_source.file = git_global_config();
- if (!given_config_source.file)
+ if (opts->use_global_config) {
+ opts->source.file = git_global_config();
+ if (!opts->source.file)
/*
* It is unknown if HOME/.gitconfig exists, so
* we do not know if we should write to XDG
@@ -719,17 +770,17 @@ int cmd_config(int argc, const char **argv, const char *prefix)
* is set and points at a sane location.
*/
die(_("$HOME not set"));
- given_config_source.scope = CONFIG_SCOPE_GLOBAL;
- } else if (use_system_config) {
- given_config_source.file = git_system_config();
- given_config_source.scope = CONFIG_SCOPE_SYSTEM;
- } else if (use_local_config) {
- given_config_source.file = git_pathdup("config");
- given_config_source.scope = CONFIG_SCOPE_LOCAL;
- } else if (use_worktree_config) {
+ opts->source.scope = CONFIG_SCOPE_GLOBAL;
+ } else if (opts->use_system_config) {
+ opts->source.file = xstrdup_or_null(git_system_config());
+ opts->source.scope = CONFIG_SCOPE_SYSTEM;
+ } else if (opts->use_local_config) {
+ opts->source.file = xstrdup_or_null(git_pathdup("config"));
+ opts->source.scope = CONFIG_SCOPE_LOCAL;
+ } else if (opts->use_worktree_config) {
struct worktree **worktrees = get_worktrees();
if (the_repository->repository_format_worktree_config)
- given_config_source.file = git_pathdup("config.worktree");
+ opts->source.file = git_pathdup("config.worktree");
else if (worktrees[0] && worktrees[1])
die(_("--worktree cannot be used with multiple "
"working trees unless the config\n"
@@ -737,76 +788,438 @@ int cmd_config(int argc, const char **argv, const char *prefix)
"Please read \"CONFIGURATION FILE\"\n"
"section in \"git help worktree\" for details"));
else
- given_config_source.file = git_pathdup("config");
- given_config_source.scope = CONFIG_SCOPE_LOCAL;
+ opts->source.file = git_pathdup("config");
+ opts->source.scope = CONFIG_SCOPE_LOCAL;
free_worktrees(worktrees);
- } else if (given_config_source.file) {
- if (!is_absolute_path(given_config_source.file) && prefix)
- given_config_source.file =
- prefix_filename(prefix, given_config_source.file);
- given_config_source.scope = CONFIG_SCOPE_COMMAND;
- } else if (given_config_source.blob) {
- given_config_source.scope = CONFIG_SCOPE_COMMAND;
+ } else if (opts->source.file) {
+ if (!is_absolute_path(opts->source.file) && prefix)
+ opts->source.file =
+ prefix_filename(prefix, opts->source.file);
+ opts->source.scope = CONFIG_SCOPE_COMMAND;
+ } else if (opts->source.blob) {
+ opts->source.scope = CONFIG_SCOPE_COMMAND;
}
- if (respect_includes_opt == -1)
- config_options.respect_includes = !given_config_source.file;
+ if (opts->respect_includes_opt == -1)
+ opts->options.respect_includes = !opts->source.file;
else
- config_options.respect_includes = respect_includes_opt;
- if (!nongit) {
- config_options.commondir = get_git_common_dir();
- config_options.git_dir = get_git_dir();
+ opts->options.respect_includes = opts->respect_includes_opt;
+ if (startup_info->have_repository) {
+ opts->options.commondir = get_git_common_dir();
+ opts->options.git_dir = get_git_dir();
}
+}
- if (end_nul) {
- term = '\0';
- delim = '\n';
- key_delim = '\n';
+static void location_options_release(struct config_location_options *opts)
+{
+ free((char *) opts->source.file);
+}
+
+static void display_options_init(struct config_display_options *opts)
+{
+ if (opts->end_nul) {
+ opts->term = '\0';
+ opts->delim = '\n';
+ opts->key_delim = '\n';
}
+}
- if ((actions & (ACTION_GET_COLOR|ACTION_GET_COLORBOOL)) && type) {
- error(_("--get-color and variable type are incoherent"));
- usage_builtin_config();
+static int cmd_config_list(int argc, const char **argv, const char *prefix)
+{
+ struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT;
+ struct config_display_options display_opts = CONFIG_DISPLAY_OPTIONS_INIT;
+ struct option opts[] = {
+ CONFIG_LOCATION_OPTIONS(location_opts),
+ CONFIG_DISPLAY_OPTIONS(display_opts),
+ OPT_GROUP(N_("Other")),
+ OPT_BOOL(0, "includes", &location_opts.respect_includes_opt,
+ N_("respect include directives on lookup")),
+ OPT_END(),
+ };
+
+ argc = parse_options(argc, argv, prefix, opts, builtin_config_list_usage, 0);
+ check_argc(argc, 0, 0);
+
+ location_options_init(&location_opts, prefix);
+ display_options_init(&display_opts);
+
+ setup_auto_pager("config", 1);
+
+ if (config_with_options(show_all_config, &display_opts,
+ &location_opts.source, the_repository,
+ &location_opts.options) < 0) {
+ if (location_opts.source.file)
+ die_errno(_("unable to read config file '%s'"),
+ location_opts.source.file);
+ else
+ die(_("error processing config file(s)"));
}
- if (HAS_MULTI_BITS(actions)) {
- error(_("only one action at a time"));
- usage_builtin_config();
+ location_options_release(&location_opts);
+ return 0;
+}
+
+static int cmd_config_get(int argc, const char **argv, const char *prefix)
+{
+ struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT;
+ struct config_display_options display_opts = CONFIG_DISPLAY_OPTIONS_INIT;
+ const char *value_pattern = NULL, *url = NULL;
+ int flags = 0;
+ unsigned get_value_flags = 0;
+ struct option opts[] = {
+ CONFIG_LOCATION_OPTIONS(location_opts),
+ OPT_GROUP(N_("Filter options")),
+ OPT_BIT(0, "all", &get_value_flags, N_("return all values for multi-valued config options"), GET_VALUE_ALL),
+ OPT_BIT(0, "regexp", &get_value_flags, N_("interpret the name as a regular expression"), GET_VALUE_KEY_REGEXP),
+ OPT_STRING(0, "value", &value_pattern, N_("pattern"), N_("show config with values matching the pattern")),
+ OPT_BIT(0, "fixed-value", &flags, N_("use string equality when comparing values to value pattern"), CONFIG_FLAGS_FIXED_VALUE),
+ OPT_STRING(0, "url", &url, N_("URL"), N_("show config matching the given URL")),
+ CONFIG_DISPLAY_OPTIONS(display_opts),
+ OPT_GROUP(N_("Other")),
+ OPT_BOOL(0, "includes", &location_opts.respect_includes_opt,
+ N_("respect include directives on lookup")),
+ OPT_STRING(0, "default", &display_opts.default_value,
+ N_("value"), N_("use default value when missing entry")),
+ OPT_END(),
+ };
+ int ret;
+
+ argc = parse_options(argc, argv, prefix, opts, builtin_config_get_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+ check_argc(argc, 1, 1);
+
+ if ((flags & CONFIG_FLAGS_FIXED_VALUE) && !value_pattern)
+ die(_("--fixed-value only applies with 'value-pattern'"));
+ if (display_opts.default_value &&
+ ((get_value_flags & GET_VALUE_ALL) || url))
+ die(_("--default= cannot be used with --all or --url="));
+ if (url && ((get_value_flags & GET_VALUE_ALL) ||
+ (get_value_flags & GET_VALUE_KEY_REGEXP) ||
+ value_pattern))
+ die(_("--url= cannot be used with --all, --regexp or --value"));
+
+ location_options_init(&location_opts, prefix);
+ display_options_init(&display_opts);
+
+ setup_auto_pager("config", 1);
+
+ if (url)
+ ret = get_urlmatch(&location_opts, &display_opts, argv[0], url);
+ else
+ ret = get_value(&location_opts, &display_opts, argv[0], value_pattern,
+ get_value_flags, flags);
+
+ location_options_release(&location_opts);
+ return ret;
+}
+
+static int cmd_config_set(int argc, const char **argv, const char *prefix)
+{
+ struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT;
+ const char *value_pattern = NULL, *comment_arg = NULL;
+ char *comment = NULL;
+ int flags = 0, append = 0, type = 0;
+ struct option opts[] = {
+ CONFIG_LOCATION_OPTIONS(location_opts),
+ CONFIG_TYPE_OPTIONS(type),
+ OPT_GROUP(N_("Filter")),
+ OPT_BIT(0, "all", &flags, N_("replace multi-valued config option with new value"), CONFIG_FLAGS_MULTI_REPLACE),
+ OPT_STRING(0, "value", &value_pattern, N_("pattern"), N_("show config with values matching the pattern")),
+ OPT_BIT(0, "fixed-value", &flags, N_("use string equality when comparing values to value pattern"), CONFIG_FLAGS_FIXED_VALUE),
+ OPT_GROUP(N_("Other")),
+ OPT_STRING(0, "comment", &comment_arg, N_("value"), N_("human-readable comment string (# will be prepended as needed)")),
+ OPT_BOOL(0, "append", &append, N_("add a new line without altering any existing values")),
+ OPT_END(),
+ };
+ struct key_value_info default_kvi = KVI_INIT;
+ char *value;
+ int ret;
+
+ argc = parse_options(argc, argv, prefix, opts, builtin_config_set_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+ check_argc(argc, 2, 2);
+
+ if ((flags & CONFIG_FLAGS_FIXED_VALUE) && !value_pattern)
+ die(_("--fixed-value only applies with --value=<pattern>"));
+ if (append && value_pattern)
+ die(_("--append cannot be used with --value=<pattern>"));
+ if (append)
+ value_pattern = CONFIG_REGEX_NONE;
+
+ comment = git_config_prepare_comment_string(comment_arg);
+
+ location_options_init(&location_opts, prefix);
+ check_write(&location_opts.source);
+
+ value = normalize_value(argv[0], argv[1], type, &default_kvi);
+
+ if ((flags & CONFIG_FLAGS_MULTI_REPLACE) || value_pattern) {
+ ret = git_config_set_multivar_in_file_gently(location_opts.source.file,
+ argv[0], value, value_pattern,
+ comment, flags);
+ } else {
+ ret = git_config_set_in_file_gently(location_opts.source.file,
+ argv[0], comment, value);
+ if (ret == CONFIG_NOTHING_SET)
+ error(_("cannot overwrite multiple values with a single value\n"
+ " Use a regexp, --add or --replace-all to change %s."), argv[0]);
+ }
+
+ location_options_release(&location_opts);
+ free(comment);
+ free(value);
+ return ret;
+}
+
+static int cmd_config_unset(int argc, const char **argv, const char *prefix)
+{
+ struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT;
+ const char *value_pattern = NULL;
+ int flags = 0;
+ struct option opts[] = {
+ CONFIG_LOCATION_OPTIONS(location_opts),
+ OPT_GROUP(N_("Filter")),
+ OPT_BIT(0, "all", &flags, N_("replace multi-valued config option with new value"), CONFIG_FLAGS_MULTI_REPLACE),
+ OPT_STRING(0, "value", &value_pattern, N_("pattern"), N_("show config with values matching the pattern")),
+ OPT_BIT(0, "fixed-value", &flags, N_("use string equality when comparing values to value pattern"), CONFIG_FLAGS_FIXED_VALUE),
+ OPT_END(),
+ };
+ int ret;
+
+ argc = parse_options(argc, argv, prefix, opts, builtin_config_unset_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+ check_argc(argc, 1, 1);
+
+ if ((flags & CONFIG_FLAGS_FIXED_VALUE) && !value_pattern)
+ die(_("--fixed-value only applies with 'value-pattern'"));
+
+ location_options_init(&location_opts, prefix);
+ check_write(&location_opts.source);
+
+ if ((flags & CONFIG_FLAGS_MULTI_REPLACE) || value_pattern)
+ ret = git_config_set_multivar_in_file_gently(location_opts.source.file,
+ argv[0], NULL, value_pattern,
+ NULL, flags);
+ else
+ ret = git_config_set_in_file_gently(location_opts.source.file, argv[0],
+ NULL, NULL);
+
+ location_options_release(&location_opts);
+ return ret;
+}
+
+static int cmd_config_rename_section(int argc, const char **argv, const char *prefix)
+{
+ struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT;
+ struct option opts[] = {
+ CONFIG_LOCATION_OPTIONS(location_opts),
+ OPT_END(),
+ };
+ int ret;
+
+ argc = parse_options(argc, argv, prefix, opts, builtin_config_rename_section_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+ check_argc(argc, 2, 2);
+
+ location_options_init(&location_opts, prefix);
+ check_write(&location_opts.source);
+
+ ret = git_config_rename_section_in_file(location_opts.source.file,
+ argv[0], argv[1]);
+ if (ret < 0)
+ goto out;
+ else if (!ret)
+ die(_("no such section: %s"), argv[0]);
+ ret = 0;
+
+out:
+ location_options_release(&location_opts);
+ return ret;
+}
+
+static int cmd_config_remove_section(int argc, const char **argv, const char *prefix)
+{
+ struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT;
+ struct option opts[] = {
+ CONFIG_LOCATION_OPTIONS(location_opts),
+ OPT_END(),
+ };
+ int ret;
+
+ argc = parse_options(argc, argv, prefix, opts, builtin_config_remove_section_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+ check_argc(argc, 1, 1);
+
+ location_options_init(&location_opts, prefix);
+ check_write(&location_opts.source);
+
+ ret = git_config_rename_section_in_file(location_opts.source.file,
+ argv[0], NULL);
+ if (ret < 0)
+ goto out;
+ else if (!ret)
+ die(_("no such section: %s"), argv[0]);
+ ret = 0;
+
+out:
+ location_options_release(&location_opts);
+ return ret;
+}
+
+static int show_editor(struct config_location_options *opts)
+{
+ char *config_file;
+
+ if (!opts->source.file && !startup_info->have_repository)
+ die(_("not in a git directory"));
+ if (opts->source.use_stdin)
+ die(_("editing stdin is not supported"));
+ if (opts->source.blob)
+ die(_("editing blobs is not supported"));
+ git_config(git_default_config, NULL);
+ config_file = opts->source.file ?
+ xstrdup(opts->source.file) :
+ git_pathdup("config");
+ if (opts->use_global_config) {
+ int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
+ if (fd >= 0) {
+ char *content = default_user_config();
+ write_str_in_full(fd, content);
+ free(content);
+ close(fd);
+ }
+ else if (errno != EEXIST)
+ die_errno(_("cannot create configuration file %s"), config_file);
+ }
+ launch_editor(config_file, NULL, NULL);
+ free(config_file);
+
+ return 0;
+}
+
+static int cmd_config_edit(int argc, const char **argv, const char *prefix)
+{
+ struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT;
+ struct option opts[] = {
+ CONFIG_LOCATION_OPTIONS(location_opts),
+ OPT_END(),
+ };
+ int ret;
+
+ argc = parse_options(argc, argv, prefix, opts, builtin_config_edit_usage, 0);
+ check_argc(argc, 0, 0);
+
+ location_options_init(&location_opts, prefix);
+ check_write(&location_opts.source);
+
+ ret = show_editor(&location_opts);
+ location_options_release(&location_opts);
+ return ret;
+}
+
+static int cmd_config_actions(int argc, const char **argv, const char *prefix)
+{
+ enum {
+ ACTION_GET = (1<<0),
+ ACTION_GET_ALL = (1<<1),
+ ACTION_GET_REGEXP = (1<<2),
+ ACTION_REPLACE_ALL = (1<<3),
+ ACTION_ADD = (1<<4),
+ ACTION_UNSET = (1<<5),
+ ACTION_UNSET_ALL = (1<<6),
+ ACTION_RENAME_SECTION = (1<<7),
+ ACTION_REMOVE_SECTION = (1<<8),
+ ACTION_LIST = (1<<9),
+ ACTION_EDIT = (1<<10),
+ ACTION_SET = (1<<11),
+ ACTION_SET_ALL = (1<<12),
+ ACTION_GET_COLOR = (1<<13),
+ ACTION_GET_COLORBOOL = (1<<14),
+ ACTION_GET_URLMATCH = (1<<15),
+ };
+ struct config_location_options location_opts = CONFIG_LOCATION_OPTIONS_INIT;
+ struct config_display_options display_opts = CONFIG_DISPLAY_OPTIONS_INIT;
+ const char *comment_arg = NULL;
+ int actions = 0;
+ unsigned flags = 0;
+ struct option opts[] = {
+ CONFIG_LOCATION_OPTIONS(location_opts),
+ OPT_GROUP(N_("Action")),
+ OPT_CMDMODE(0, "get", &actions, N_("get value: name [<value-pattern>]"), ACTION_GET),
+ OPT_CMDMODE(0, "get-all", &actions, N_("get all values: key [<value-pattern>]"), ACTION_GET_ALL),
+ OPT_CMDMODE(0, "get-regexp", &actions, N_("get values for regexp: name-regex [<value-pattern>]"), ACTION_GET_REGEXP),
+ OPT_CMDMODE(0, "get-urlmatch", &actions, N_("get value specific for the URL: section[.var] URL"), ACTION_GET_URLMATCH),
+ OPT_CMDMODE(0, "replace-all", &actions, N_("replace all matching variables: name value [<value-pattern>]"), ACTION_REPLACE_ALL),
+ OPT_CMDMODE(0, "add", &actions, N_("add a new variable: name value"), ACTION_ADD),
+ OPT_CMDMODE(0, "unset", &actions, N_("remove a variable: name [<value-pattern>]"), ACTION_UNSET),
+ OPT_CMDMODE(0, "unset-all", &actions, N_("remove all matches: name [<value-pattern>]"), ACTION_UNSET_ALL),
+ OPT_CMDMODE(0, "rename-section", &actions, N_("rename section: old-name new-name"), ACTION_RENAME_SECTION),
+ OPT_CMDMODE(0, "remove-section", &actions, N_("remove a section: name"), ACTION_REMOVE_SECTION),
+ OPT_CMDMODE('l', "list", &actions, N_("list all"), ACTION_LIST),
+ OPT_CMDMODE('e', "edit", &actions, N_("open an editor"), ACTION_EDIT),
+ OPT_CMDMODE(0, "get-color", &actions, N_("find the color configured: slot [<default>]"), ACTION_GET_COLOR),
+ OPT_CMDMODE(0, "get-colorbool", &actions, N_("find the color setting: slot [<stdout-is-tty>]"), ACTION_GET_COLORBOOL),
+ CONFIG_DISPLAY_OPTIONS(display_opts),
+ OPT_GROUP(N_("Other")),
+ OPT_STRING(0, "default", &display_opts.default_value,
+ N_("value"), N_("with --get, use default value when missing entry")),
+ OPT_STRING(0, "comment", &comment_arg, N_("value"), N_("human-readable comment string (# will be prepended as needed)")),
+ OPT_BIT(0, "fixed-value", &flags, N_("use string equality when comparing values to value pattern"), CONFIG_FLAGS_FIXED_VALUE),
+ OPT_BOOL(0, "includes", &location_opts.respect_includes_opt,
+ N_("respect include directives on lookup")),
+ OPT_END(),
+ };
+ char *value = NULL, *comment = NULL;
+ int ret = 0;
+ struct key_value_info default_kvi = KVI_INIT;
+
+ argc = parse_options(argc, argv, prefix, opts,
+ builtin_config_usage,
+ PARSE_OPT_STOP_AT_NON_OPTION);
+
+ location_options_init(&location_opts, prefix);
+ display_options_init(&display_opts);
+
+ if ((actions & (ACTION_GET_COLOR|ACTION_GET_COLORBOOL)) && display_opts.type) {
+ error(_("--get-color and variable type are incoherent"));
+ exit(129);
}
+
if (actions == 0)
switch (argc) {
case 1: actions = ACTION_GET; break;
case 2: actions = ACTION_SET; break;
case 3: actions = ACTION_SET_ALL; break;
default:
- usage_builtin_config();
+ error(_("no action specified"));
+ exit(129);
}
- if (omit_values &&
+ if (display_opts.omit_values &&
!(actions == ACTION_LIST || actions == ACTION_GET_REGEXP)) {
error(_("--name-only is only applicable to --list or --get-regexp"));
- usage_builtin_config();
+ exit(129);
}
- if (show_origin && !(actions &
+ if (display_opts.show_origin && !(actions &
(ACTION_GET|ACTION_GET_ALL|ACTION_GET_REGEXP|ACTION_LIST))) {
error(_("--show-origin is only applicable to --get, --get-all, "
"--get-regexp, and --list"));
- usage_builtin_config();
+ exit(129);
}
- if (default_value && !(actions & ACTION_GET)) {
+ if (display_opts.default_value && !(actions & ACTION_GET)) {
error(_("--default is only applicable to --get"));
- usage_builtin_config();
+ exit(129);
}
- if (comment &&
+ if (comment_arg &&
!(actions & (ACTION_ADD|ACTION_SET|ACTION_SET_ALL|ACTION_REPLACE_ALL))) {
error(_("--comment is only applicable to add/set/replace operations"));
- usage_builtin_config();
+ exit(129);
}
/* check usage of --fixed-value */
- if (fixed_value) {
+ if (flags & CONFIG_FLAGS_FIXED_VALUE) {
int allowed_usage = 0;
switch (actions) {
@@ -835,148 +1248,125 @@ int cmd_config(int argc, const char **argv, const char *prefix)
if (!allowed_usage) {
error(_("--fixed-value only applies with 'value-pattern'"));
- usage_builtin_config();
+ exit(129);
}
-
- flags |= CONFIG_FLAGS_FIXED_VALUE;
}
- comment = git_config_prepare_comment_string(comment);
+ comment = git_config_prepare_comment_string(comment_arg);
- if (actions & PAGING_ACTIONS)
+ /*
+ * The following actions may produce more than one line of output and
+ * should therefore be paged.
+ */
+ if (actions & (ACTION_LIST | ACTION_GET_ALL | ACTION_GET_REGEXP | ACTION_GET_URLMATCH))
setup_auto_pager("config", 1);
if (actions == ACTION_LIST) {
check_argc(argc, 0, 0);
- if (config_with_options(show_all_config, NULL,
- &given_config_source, the_repository,
- &config_options) < 0) {
- if (given_config_source.file)
+ if (config_with_options(show_all_config, &display_opts,
+ &location_opts.source, the_repository,
+ &location_opts.options) < 0) {
+ if (location_opts.source.file)
die_errno(_("unable to read config file '%s'"),
- given_config_source.file);
+ location_opts.source.file);
else
die(_("error processing config file(s)"));
}
}
else if (actions == ACTION_EDIT) {
- char *config_file;
-
- check_argc(argc, 0, 0);
- if (!given_config_source.file && nongit)
- die(_("not in a git directory"));
- if (given_config_source.use_stdin)
- die(_("editing stdin is not supported"));
- if (given_config_source.blob)
- die(_("editing blobs is not supported"));
- git_config(git_default_config, NULL);
- config_file = given_config_source.file ?
- xstrdup(given_config_source.file) :
- git_pathdup("config");
- if (use_global_config) {
- int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 0666);
- if (fd >= 0) {
- char *content = default_user_config();
- write_str_in_full(fd, content);
- free(content);
- close(fd);
- }
- else if (errno != EEXIST)
- die_errno(_("cannot create configuration file %s"), config_file);
- }
- launch_editor(config_file, NULL, NULL);
- free(config_file);
+ ret = show_editor(&location_opts);
}
else if (actions == ACTION_SET) {
- check_write();
+ check_write(&location_opts.source);
check_argc(argc, 2, 2);
- value = normalize_value(argv[0], argv[1], &default_kvi);
- ret = git_config_set_in_file_gently(given_config_source.file, argv[0], comment, value);
+ value = normalize_value(argv[0], argv[1], display_opts.type, &default_kvi);
+ ret = git_config_set_in_file_gently(location_opts.source.file, argv[0], comment, value);
if (ret == CONFIG_NOTHING_SET)
error(_("cannot overwrite multiple values with a single value\n"
" Use a regexp, --add or --replace-all to change %s."), argv[0]);
}
else if (actions == ACTION_SET_ALL) {
- check_write();
+ check_write(&location_opts.source);
check_argc(argc, 2, 3);
- value = normalize_value(argv[0], argv[1], &default_kvi);
- ret = git_config_set_multivar_in_file_gently(given_config_source.file,
+ value = normalize_value(argv[0], argv[1], display_opts.type, &default_kvi);
+ ret = git_config_set_multivar_in_file_gently(location_opts.source.file,
argv[0], value, argv[2],
comment, flags);
}
else if (actions == ACTION_ADD) {
- check_write();
+ check_write(&location_opts.source);
check_argc(argc, 2, 2);
- value = normalize_value(argv[0], argv[1], &default_kvi);
- ret = git_config_set_multivar_in_file_gently(given_config_source.file,
+ value = normalize_value(argv[0], argv[1], display_opts.type, &default_kvi);
+ ret = git_config_set_multivar_in_file_gently(location_opts.source.file,
argv[0], value,
CONFIG_REGEX_NONE,
comment, flags);
}
else if (actions == ACTION_REPLACE_ALL) {
- check_write();
+ check_write(&location_opts.source);
check_argc(argc, 2, 3);
- value = normalize_value(argv[0], argv[1], &default_kvi);
- ret = git_config_set_multivar_in_file_gently(given_config_source.file,
+ value = normalize_value(argv[0], argv[1], display_opts.type, &default_kvi);
+ ret = git_config_set_multivar_in_file_gently(location_opts.source.file,
argv[0], value, argv[2],
comment, flags | CONFIG_FLAGS_MULTI_REPLACE);
}
else if (actions == ACTION_GET) {
check_argc(argc, 1, 2);
- return get_value(argv[0], argv[1], flags);
+ ret = get_value(&location_opts, &display_opts, argv[0], argv[1],
+ 0, flags);
}
else if (actions == ACTION_GET_ALL) {
- do_all = 1;
check_argc(argc, 1, 2);
- return get_value(argv[0], argv[1], flags);
+ ret = get_value(&location_opts, &display_opts, argv[0], argv[1],
+ GET_VALUE_ALL, flags);
}
else if (actions == ACTION_GET_REGEXP) {
- show_keys = 1;
- use_key_regexp = 1;
- do_all = 1;
+ display_opts.show_keys = 1;
check_argc(argc, 1, 2);
- return get_value(argv[0], argv[1], flags);
+ ret = get_value(&location_opts, &display_opts, argv[0], argv[1],
+ GET_VALUE_ALL|GET_VALUE_KEY_REGEXP, flags);
}
else if (actions == ACTION_GET_URLMATCH) {
check_argc(argc, 2, 2);
- return get_urlmatch(argv[0], argv[1]);
+ ret = get_urlmatch(&location_opts, &display_opts, argv[0], argv[1]);
}
else if (actions == ACTION_UNSET) {
- check_write();
+ check_write(&location_opts.source);
check_argc(argc, 1, 2);
if (argc == 2)
- return git_config_set_multivar_in_file_gently(given_config_source.file,
- argv[0], NULL, argv[1],
- NULL, flags);
+ ret = git_config_set_multivar_in_file_gently(location_opts.source.file,
+ argv[0], NULL, argv[1],
+ NULL, flags);
else
- return git_config_set_in_file_gently(given_config_source.file,
- argv[0], NULL, NULL);
+ ret = git_config_set_in_file_gently(location_opts.source.file,
+ argv[0], NULL, NULL);
}
else if (actions == ACTION_UNSET_ALL) {
- check_write();
+ check_write(&location_opts.source);
check_argc(argc, 1, 2);
- return git_config_set_multivar_in_file_gently(given_config_source.file,
- argv[0], NULL, argv[1],
- NULL, flags | CONFIG_FLAGS_MULTI_REPLACE);
+ ret = git_config_set_multivar_in_file_gently(location_opts.source.file,
+ argv[0], NULL, argv[1],
+ NULL, flags | CONFIG_FLAGS_MULTI_REPLACE);
}
else if (actions == ACTION_RENAME_SECTION) {
- check_write();
+ check_write(&location_opts.source);
check_argc(argc, 2, 2);
- ret = git_config_rename_section_in_file(given_config_source.file,
+ ret = git_config_rename_section_in_file(location_opts.source.file,
argv[0], argv[1]);
if (ret < 0)
- return ret;
+ goto out;
else if (!ret)
die(_("no such section: %s"), argv[0]);
else
ret = 0;
}
else if (actions == ACTION_REMOVE_SECTION) {
- check_write();
+ check_write(&location_opts.source);
check_argc(argc, 1, 1);
- ret = git_config_rename_section_in_file(given_config_source.file,
+ ret = git_config_rename_section_in_file(location_opts.source.file,
argv[0], NULL);
if (ret < 0)
- return ret;
+ goto out;
else if (!ret)
die(_("no such section: %s"), argv[0]);
else
@@ -984,15 +1374,51 @@ int cmd_config(int argc, const char **argv, const char *prefix)
}
else if (actions == ACTION_GET_COLOR) {
check_argc(argc, 1, 2);
- get_color(argv[0], argv[1]);
+ get_color(&location_opts, argv[0], argv[1]);
}
else if (actions == ACTION_GET_COLORBOOL) {
check_argc(argc, 1, 2);
if (argc == 2)
color_stdout_is_tty = git_config_bool("command line", argv[1]);
- return get_colorbool(argv[0], argc == 2);
+ ret = get_colorbool(&location_opts, argv[0], argc == 2);
}
+out:
+ location_options_release(&location_opts);
+ free(comment);
free(value);
return ret;
}
+
+int cmd_config(int argc, const char **argv, const char *prefix)
+{
+ parse_opt_subcommand_fn *subcommand = NULL;
+ struct option subcommand_opts[] = {
+ OPT_SUBCOMMAND("list", &subcommand, cmd_config_list),
+ OPT_SUBCOMMAND("get", &subcommand, cmd_config_get),
+ OPT_SUBCOMMAND("set", &subcommand, cmd_config_set),
+ OPT_SUBCOMMAND("unset", &subcommand, cmd_config_unset),
+ OPT_SUBCOMMAND("rename-section", &subcommand, cmd_config_rename_section),
+ OPT_SUBCOMMAND("remove-section", &subcommand, cmd_config_remove_section),
+ OPT_SUBCOMMAND("edit", &subcommand, cmd_config_edit),
+ OPT_END(),
+ };
+
+ /*
+ * This is somewhat hacky: we first parse the command line while
+ * keeping all args intact in order to determine whether a subcommand
+ * has been specified. If so, we re-parse it a second time, but this
+ * time we drop KEEP_ARGV0. This is so that we don't munge the command
+ * line in case no subcommand was given, which would otherwise confuse
+ * us when parsing the legacy-style modes that don't use subcommands.
+ */
+ argc = parse_options(argc, argv, prefix, subcommand_opts, builtin_config_usage,
+ PARSE_OPT_SUBCOMMAND_OPTIONAL|PARSE_OPT_KEEP_ARGV0|PARSE_OPT_KEEP_UNKNOWN_OPT);
+ if (subcommand) {
+ argc = parse_options(argc, argv, prefix, subcommand_opts, builtin_config_usage,
+ PARSE_OPT_SUBCOMMAND_OPTIONAL|PARSE_OPT_KEEP_UNKNOWN_OPT);
+ return subcommand(argc, argv, prefix);
+ }
+
+ return cmd_config_actions(argc, argv, prefix);
+}
diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c
index 17f929dede..4952b22547 100644
--- a/builtin/credential-cache--daemon.c
+++ b/builtin/credential-cache--daemon.c
@@ -115,7 +115,9 @@ static int read_request(FILE *fh, struct credential *c,
return error("client sent bogus timeout line: %s", item.buf);
*timeout = atoi(p);
- if (credential_read(c, fh) < 0)
+ credential_set_all_capabilities(c, CREDENTIAL_OP_INITIAL);
+
+ if (credential_read(c, fh, CREDENTIAL_OP_HELPER) < 0)
return -1;
return 0;
}
@@ -131,8 +133,18 @@ static void serve_one_client(FILE *in, FILE *out)
else if (!strcmp(action.buf, "get")) {
struct credential_cache_entry *e = lookup_credential(&c);
if (e) {
- fprintf(out, "username=%s\n", e->item.username);
- fprintf(out, "password=%s\n", e->item.password);
+ e->item.capa_authtype.request_initial = 1;
+ e->item.capa_authtype.request_helper = 1;
+
+ fprintf(out, "capability[]=authtype\n");
+ if (e->item.username)
+ fprintf(out, "username=%s\n", e->item.username);
+ if (e->item.password)
+ fprintf(out, "password=%s\n", e->item.password);
+ if (credential_has_capability(&c.capa_authtype, CREDENTIAL_OP_HELPER) && e->item.authtype)
+ fprintf(out, "authtype=%s\n", e->item.authtype);
+ if (credential_has_capability(&c.capa_authtype, CREDENTIAL_OP_HELPER) && e->item.credential)
+ fprintf(out, "credential=%s\n", e->item.credential);
if (e->item.password_expiry_utc != TIME_MAX)
fprintf(out, "password_expiry_utc=%"PRItime"\n",
e->item.password_expiry_utc);
@@ -157,8 +169,10 @@ static void serve_one_client(FILE *in, FILE *out)
else if (!strcmp(action.buf, "store")) {
if (timeout < 0)
warning("cache client didn't specify a timeout");
- else if (!c.username || !c.password)
+ else if ((!c.username || !c.password) && (!c.authtype && !c.credential))
warning("cache client gave us a partial credential");
+ else if (c.ephemeral)
+ warning("not storing ephemeral credential");
else {
remove_credential(&c, 0);
cache_credential(&c, timeout);
diff --git a/builtin/credential-cache.c b/builtin/credential-cache.c
index bef120b537..3db8df70a9 100644
--- a/builtin/credential-cache.c
+++ b/builtin/credential-cache.c
@@ -1,4 +1,5 @@
#include "builtin.h"
+#include "credential.h"
#include "gettext.h"
#include "parse-options.h"
#include "path.h"
@@ -127,6 +128,13 @@ static char *get_socket_path(void)
return socket;
}
+static void announce_capabilities(void)
+{
+ struct credential c = CREDENTIAL_INIT;
+ c.capa_authtype.request_initial = 1;
+ credential_announce_capabilities(&c, stdout);
+}
+
int cmd_credential_cache(int argc, const char **argv, const char *prefix)
{
char *socket_path = NULL;
@@ -163,6 +171,8 @@ int cmd_credential_cache(int argc, const char **argv, const char *prefix)
do_cache(socket_path, op, timeout, FLAG_RELAY);
else if (!strcmp(op, "store"))
do_cache(socket_path, op, timeout, FLAG_RELAY|FLAG_SPAWN);
+ else if (!strcmp(op, "capability"))
+ announce_capabilities();
else
; /* ignore unknown operation */
diff --git a/builtin/credential-store.c b/builtin/credential-store.c
index 4a492411bb..494c809332 100644
--- a/builtin/credential-store.c
+++ b/builtin/credential-store.c
@@ -205,7 +205,7 @@ int cmd_credential_store(int argc, const char **argv, const char *prefix)
if (!fns.nr)
die("unable to set up default path; use --file");
- if (credential_read(&c, stdin) < 0)
+ if (credential_read(&c, stdin, CREDENTIAL_OP_HELPER) < 0)
die("unable to read credential");
if (!strcmp(op, "get"))
diff --git a/builtin/credential.c b/builtin/credential.c
index 7010752987..5100d441f2 100644
--- a/builtin/credential.c
+++ b/builtin/credential.c
@@ -17,15 +17,24 @@ int cmd_credential(int argc, const char **argv, const char *prefix UNUSED)
usage(usage_msg);
op = argv[1];
- if (credential_read(&c, stdin) < 0)
+ if (!strcmp(op, "capability")) {
+ credential_set_all_capabilities(&c, CREDENTIAL_OP_INITIAL);
+ credential_announce_capabilities(&c, stdout);
+ return 0;
+ }
+
+ if (credential_read(&c, stdin, CREDENTIAL_OP_INITIAL) < 0)
die("unable to read credential from stdin");
if (!strcmp(op, "fill")) {
- credential_fill(&c);
- credential_write(&c, stdout);
+ credential_fill(&c, 0);
+ credential_next_state(&c);
+ credential_write(&c, stdout, CREDENTIAL_OP_RESPONSE);
} else if (!strcmp(op, "approve")) {
+ credential_set_all_capabilities(&c, CREDENTIAL_OP_HELPER);
credential_approve(&c);
} else if (!strcmp(op, "reject")) {
+ credential_set_all_capabilities(&c, CREDENTIAL_OP_HELPER);
credential_reject(&c);
} else {
usage(usage_msg);
diff --git a/builtin/describe.c b/builtin/describe.c
index d6c77a714f..82aca00c80 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "config.h"
#include "environment.h"
@@ -638,7 +637,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
}
hashmap_init(&names, commit_name_neq, NULL, 0);
- for_each_rawref(get_name, NULL);
+ refs_for_each_rawref(get_main_ref_store(the_repository), get_name,
+ NULL);
if (!hashmap_get_size(&names) && !always)
die(_("No names found, cannot describe anything."));
@@ -674,7 +674,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
repo_read_index(the_repository);
- refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED,
+ refresh_index(the_repository->index, REFRESH_QUIET|REFRESH_UNMERGED,
NULL, NULL, NULL);
fd = repo_hold_locked_index(the_repository,
&index_lock, 0);
diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c
index a8e68ce8ef..0d3c611aac 100644
--- a/builtin/diff-tree.c
+++ b/builtin/diff-tree.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "config.h"
#include "diff.h"
@@ -206,7 +205,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)
opt->diffopt.rotate_to_strict = 0;
opt->diffopt.no_free = 1;
if (opt->diffopt.detect_rename) {
- if (!the_index.cache)
+ if (the_repository->index->cache)
repo_read_index(the_repository);
opt->diffopt.setup |= DIFF_SETUP_USE_SIZE_CACHE;
}
diff --git a/builtin/diff.c b/builtin/diff.c
index 6e196e0c7d..9b6cdabe15 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 2006 Junio C Hamano
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "config.h"
#include "ewah/ewok.h"
@@ -239,9 +239,9 @@ static void refresh_index_quietly(void)
fd = repo_hold_locked_index(the_repository, &lock_file, 0);
if (fd < 0)
return;
- discard_index(&the_index);
+ discard_index(the_repository->index);
repo_read_index(the_repository);
- refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL,
+ refresh_index(the_repository->index, REFRESH_QUIET|REFRESH_UNMERGED, NULL, NULL,
NULL);
repo_update_index_if_able(the_repository, &lock_file);
}
@@ -465,6 +465,15 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
no_index = DIFF_NO_INDEX_IMPLICIT;
}
+ /*
+ * When operating outside of a Git repository we need to have a hash
+ * algorithm at hand so that we can generate the blob hashes. We
+ * default to SHA1 here, but may eventually want to change this to be
+ * configurable via a command line option.
+ */
+ if (nongit)
+ repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
+
init_diff_ui_defaults();
git_config(git_diff_ui_config, NULL);
prefix = precompose_argv_prefix(argc, argv, prefix);
diff --git a/builtin/difftool.c b/builtin/difftool.c
index a3c72b8258..a130faae4f 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -11,7 +11,7 @@
*
* Copyright (C) 2016 Johannes Schindelin
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "abspath.h"
#include "config.h"
@@ -117,7 +117,7 @@ static int use_wt_file(const char *workdir, const char *name,
int fd = open(buf.buf, O_RDONLY);
if (fd >= 0 &&
- !index_fd(&the_index, &wt_oid, fd, &st, OBJ_BLOB, name, 0)) {
+ !index_fd(the_repository->index, &wt_oid, fd, &st, OBJ_BLOB, name, 0)) {
if (is_null_oid(oid)) {
oidcpy(oid, &wt_oid);
use = 1;
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index dc5a9d32dd..ea5ae5196d 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -24,7 +24,7 @@
#include "object-store-ll.h"
#include "mem-pool.h"
#include "commit-reach.h"
-#include "khash.h"
+#include "khashl.h"
#include "date.h"
#define PACK_ID_BITS 16
@@ -1604,10 +1604,11 @@ static int update_branch(struct branch *b)
if (is_null_oid(&b->oid)) {
if (b->delete)
- delete_ref(NULL, b->name, NULL, 0);
+ refs_delete_ref(get_main_ref_store(the_repository),
+ NULL, b->name, NULL, 0);
return 0;
}
- if (read_ref(b->name, &old_oid))
+ if (refs_read_ref(get_main_ref_store(the_repository), b->name, &old_oid))
oidclr(&old_oid);
if (!force_update && !is_null_oid(&old_oid)) {
struct commit *old_cmit, *new_cmit;
@@ -1631,10 +1632,11 @@ static int update_branch(struct branch *b)
return -1;
}
}
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction ||
ref_transaction_update(transaction, b->name, &b->oid, &old_oid,
- 0, msg, &err) ||
+ NULL, NULL, 0, msg, &err) ||
ref_transaction_commit(transaction, &err)) {
ref_transaction_free(transaction);
error("%s", err.buf);
@@ -1665,7 +1667,8 @@ static void dump_tags(void)
struct strbuf err = STRBUF_INIT;
struct ref_transaction *transaction;
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction) {
failure |= error("%s", err.buf);
goto cleanup;
@@ -1675,7 +1678,8 @@ static void dump_tags(void)
strbuf_addf(&ref_name, "refs/tags/%s", t->name);
if (ref_transaction_update(transaction, ref_name.buf,
- &t->oid, NULL, 0, msg, &err)) {
+ &t->oid, NULL, NULL, NULL,
+ 0, msg, &err)) {
failure |= error("%s", err.buf);
goto cleanup;
}
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 5857d860db..75255dc600 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -340,7 +340,8 @@ static void find_non_local_tags(const struct ref *refs,
refname_hash_init(&remote_refs);
create_fetch_oidset(head, &fetch_oids);
- for_each_ref(add_one_refname, &existing_refs);
+ refs_for_each_ref(get_main_ref_store(the_repository), add_one_refname,
+ &existing_refs);
/*
* If we already have a transaction, then we need to filter out all
@@ -614,7 +615,9 @@ static struct ref *get_ref_map(struct remote *remote,
if (!existing_refs_populated) {
refname_hash_init(&existing_refs);
- for_each_ref(add_one_refname, &existing_refs);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ add_one_refname,
+ &existing_refs);
existing_refs_populated = 1;
}
@@ -659,7 +662,8 @@ static int s_update_ref(const char *action,
* lifecycle.
*/
if (!transaction) {
- transaction = our_transaction = ref_transaction_begin(&err);
+ transaction = our_transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction) {
ret = STORE_REF_ERROR_OTHER;
goto out;
@@ -668,7 +672,7 @@ static int s_update_ref(const char *action,
ret = ref_transaction_update(transaction, ref->name, &ref->new_oid,
check_old ? &ref->old_oid : NULL,
- 0, msg, &err);
+ NULL, NULL, 0, msg, &err);
if (ret) {
ret = STORE_REF_ERROR_OTHER;
goto out;
@@ -1393,7 +1397,9 @@ static int prune_refs(struct display_state *display_state,
for (ref = stale_refs; ref; ref = ref->next)
string_list_append(&refnames, ref->name);
- result = delete_refs("fetch: prune", &refnames, 0);
+ result = refs_delete_refs(get_main_ref_store(the_repository),
+ "fetch: prune", &refnames,
+ 0);
string_list_clear(&refnames, 0);
}
}
@@ -1479,7 +1485,8 @@ static void add_negotiation_tips(struct git_transport_options *smart_options)
continue;
}
old_nr = oids->nr;
- for_each_glob_ref(add_oid, s, oids);
+ refs_for_each_glob_ref(get_main_ref_store(the_repository),
+ add_oid, s, oids);
if (old_nr == oids->nr)
warning("ignoring --negotiation-tip=%s because it does not match any refs",
s);
@@ -1655,7 +1662,8 @@ static int do_fetch(struct transport *transport,
config->display_format);
if (atomic_fetch) {
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction) {
retcode = -1;
goto cleanup;
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index 919282e12a..5517a4a1c0 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -98,7 +98,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
}
if (include_root_refs)
- flags |= FILTER_REFS_ROOT_REFS;
+ flags |= FILTER_REFS_ROOT_REFS | FILTER_REFS_DETACHED_HEAD;
filter.match_as_path = 1;
filter_and_format_refs(&filter, flags, sorting, &format);
diff --git a/builtin/for-each-repo.c b/builtin/for-each-repo.c
index 28186b30f5..c4fa41fda9 100644
--- a/builtin/for-each-repo.c
+++ b/builtin/for-each-repo.c
@@ -32,6 +32,7 @@ static int run_command_on_repo(const char *path, int argc, const char ** argv)
int cmd_for_each_repo(int argc, const char **argv, const char *prefix)
{
static const char *config_key = NULL;
+ int keep_going = 0;
int i, result = 0;
const struct string_list *values;
int err;
@@ -39,6 +40,8 @@ int cmd_for_each_repo(int argc, const char **argv, const char *prefix)
const struct option options[] = {
OPT_STRING(0, "config", &config_key, N_("config"),
N_("config key storing a list of repository paths")),
+ OPT_BOOL(0, "keep-going", &keep_going,
+ N_("keep going even if command fails in a repository")),
OPT_END()
};
@@ -55,8 +58,14 @@ int cmd_for_each_repo(int argc, const char **argv, const char *prefix)
else if (err)
return 0;
- for (i = 0; !result && i < values->nr; i++)
- result = run_command_on_repo(values->items[i].string, argc, argv);
+ for (i = 0; i < values->nr; i++) {
+ int ret = run_command_on_repo(values->items[i].string, argc, argv);
+ if (ret) {
+ if (!keep_going)
+ return ret;
+ result = 1;
+ }
+ }
return result;
}
diff --git a/builtin/fsck.c b/builtin/fsck.c
index f892487c9b..d13a226c2e 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -514,7 +514,9 @@ static int fsck_handle_reflog(const char *logname, void *cb_data)
struct strbuf refname = STRBUF_INIT;
strbuf_worktree_ref(cb_data, &refname, logname);
- for_each_reflog_ent(refname.buf, fsck_handle_reflog_ent, refname.buf);
+ refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+ refname.buf, fsck_handle_reflog_ent,
+ refname.buf);
strbuf_release(&refname);
return 0;
}
@@ -563,7 +565,8 @@ static void get_default_heads(void)
const char *head_points_at;
struct object_id head_oid;
- for_each_rawref(fsck_handle_ref, NULL);
+ refs_for_each_rawref(get_main_ref_store(the_repository),
+ fsck_handle_ref, NULL);
worktrees = get_worktrees();
for (p = worktrees; *p; p++) {
@@ -712,7 +715,9 @@ static int fsck_head_link(const char *head_ref_name,
if (verbose)
fprintf_ln(stderr, _("Checking %s link"), head_ref_name);
- *head_points_at = resolve_ref_unsafe(head_ref_name, 0, head_oid, NULL);
+ *head_points_at = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ head_ref_name, 0, head_oid,
+ NULL);
if (!*head_points_at) {
errors_found |= ERROR_REFS;
return error(_("invalid %s"), head_ref_name);
diff --git a/builtin/fsmonitor--daemon.c b/builtin/fsmonitor--daemon.c
index 1593713f4c..1c71d96c6d 100644
--- a/builtin/fsmonitor--daemon.c
+++ b/builtin/fsmonitor--daemon.c
@@ -13,7 +13,7 @@
#include "fsmonitor--daemon.h"
#include "repository.h"
#include "simple-ipc.h"
-#include "khash.h"
+#include "khashl.h"
#include "run-command.h"
#include "trace.h"
#include "trace2.h"
@@ -650,7 +650,7 @@ static int fsmonitor_parse_client_token(const char *buf_token,
return 0;
}
-KHASH_INIT(str, const char *, int, 0, kh_str_hash_func, kh_str_hash_equal)
+KHASHL_SET_INIT(KH_LOCAL, kh_str, str, const char *, kh_hash_str, kh_eq_str)
static int do_handle_client(struct fsmonitor_daemon_state *state,
const char *command,
diff --git a/builtin/gc.c b/builtin/gc.c
index d187cec1ea..054fca7835 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -907,7 +907,8 @@ static int should_write_commit_graph(void)
if (data.limit < 0)
return 1;
- result = for_each_ref(dfs_on_ref, &data);
+ result = refs_for_each_ref(get_main_ref_store(the_repository),
+ dfs_on_ref, &data);
repo_clear_commit_marks(the_repository, SEEN);
@@ -1870,6 +1871,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
"<string>%s/git</string>\n"
"<string>--exec-path=%s</string>\n"
"<string>for-each-repo</string>\n"
+ "<string>--keep-going</string>\n"
"<string>--config=maintenance.repo</string>\n"
"<string>maintenance</string>\n"
"<string>run</string>\n"
@@ -2112,7 +2114,7 @@ static int schtasks_schedule_task(const char *exec_path, enum schedule_priority
"<Actions Context=\"Author\">\n"
"<Exec>\n"
"<Command>\"%s\\headless-git.exe\"</Command>\n"
- "<Arguments>--exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n"
+ "<Arguments>--exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%s</Arguments>\n"
"</Exec>\n"
"</Actions>\n"
"</Task>\n";
@@ -2257,7 +2259,7 @@ static int crontab_update_schedule(int run_maintenance, int fd)
"# replaced in the future by a Git command.\n\n");
strbuf_addf(&line_format,
- "%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%%s\n",
+ "%%d %%s * * %%s \"%s/git\" --exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%s\n",
exec_path, exec_path);
fprintf(cron_in, line_format.buf, minute, "1-23", "*", "hourly");
fprintf(cron_in, line_format.buf, minute, "0", "1-6", "daily");
@@ -2458,7 +2460,7 @@ static int systemd_timer_write_service_template(const char *exec_path)
"\n"
"[Service]\n"
"Type=oneshot\n"
- "ExecStart=\"%s/git\" --exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%%i\n"
+ "ExecStart=\"%s/git\" --exec-path=\"%s\" for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=%%i\n"
"LockPersonality=yes\n"
"MemoryDenyWriteExecute=yes\n"
"NoNewPrivileges=yes\n"
diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index 82ca6d2bfd..c767414a0c 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -123,6 +123,9 @@ int cmd_hash_object(int argc, const char **argv, const char *prefix)
else
prefix = setup_git_directory_gently(&nongit);
+ if (nongit && !the_hash_algo)
+ repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
+
if (vpath && prefix) {
vpath_free = prefix_filename(prefix, vpath);
vpath = vpath_free;
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
index 8768bfea3c..1d969494cf 100644
--- a/builtin/interpret-trailers.c
+++ b/builtin/interpret-trailers.c
@@ -141,7 +141,7 @@ static void interpret_trailers(const struct process_trailer_options *opts,
LIST_HEAD(head);
struct strbuf sb = STRBUF_INIT;
struct strbuf trailer_block = STRBUF_INIT;
- struct trailer_info info;
+ struct trailer_info *info;
FILE *outfile = stdout;
trailer_config_init();
@@ -151,13 +151,13 @@ static void interpret_trailers(const struct process_trailer_options *opts,
if (opts->in_place)
outfile = create_in_place_tempfile(file);
- parse_trailers(opts, &info, sb.buf, &head);
+ info = parse_trailers(opts, sb.buf, &head);
/* Print the lines before the trailers */
if (!opts->only_trailers)
- fwrite(sb.buf, 1, info.trailer_block_start, outfile);
+ fwrite(sb.buf, 1, trailer_block_start(info), outfile);
- if (!opts->only_trailers && !info.blank_line_before_trailer)
+ if (!opts->only_trailers && !blank_line_before_trailer_block(info))
fprintf(outfile, "\n");
@@ -178,8 +178,8 @@ static void interpret_trailers(const struct process_trailer_options *opts,
/* Print the lines after the trailers as is */
if (!opts->only_trailers)
- fwrite(sb.buf + info.trailer_block_end, 1, sb.len - info.trailer_block_end, outfile);
- trailer_info_release(&info);
+ fwrite(sb.buf + trailer_block_end(info), 1, sb.len - trailer_block_end(info), outfile);
+ trailer_info_release(info);
if (opts->in_place)
if (rename_tempfile(&trailers_tempfile, file))
diff --git a/builtin/log.c b/builtin/log.c
index c0a8bb95e9..c8ce0c0d88 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1494,6 +1494,19 @@ static int subject_prefix_callback(const struct option *opt, const char *arg,
return 0;
}
+static int rfc_callback(const struct option *opt, const char *arg,
+ int unset)
+{
+ const char **rfc = opt->value;
+
+ *rfc = opt->value;
+ if (unset)
+ *rfc = NULL;
+ else
+ *rfc = arg ? arg : "RFC";
+ return 0;
+}
+
static int numbered_cmdline_opt = 0;
static int numbered_callback(const struct option *opt, const char *arg,
@@ -1907,8 +1920,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
struct strbuf rdiff2 = STRBUF_INIT;
struct strbuf rdiff_title = STRBUF_INIT;
struct strbuf sprefix = STRBUF_INIT;
+ const char *rfc = NULL;
int creation_factor = -1;
- int rfc = 0;
const struct option builtin_format_patch_options[] = {
OPT_CALLBACK_F('n', "numbered", &numbered, NULL,
@@ -1932,7 +1945,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
N_("mark the series as Nth re-roll")),
OPT_INTEGER(0, "filename-max-length", &fmt_patch_name_max,
N_("max length of output filename")),
- OPT_BOOL(0, "rfc", &rfc, N_("use [RFC PATCH] instead of [PATCH]")),
+ OPT_CALLBACK_F(0, "rfc", &rfc, N_("rfc"),
+ N_("add <rfc> (default 'RFC') before 'PATCH'"),
+ PARSE_OPT_OPTARG, rfc_callback),
OPT_STRING(0, "cover-from-description", &cover_from_description_arg,
N_("cover-from-description-mode"),
N_("generate parts of a cover letter based on a branch's description")),
@@ -2050,8 +2065,13 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
if (cover_from_description_arg)
cover_from_description_mode = parse_cover_from_description(cover_from_description_arg);
- if (rfc)
- strbuf_insertstr(&sprefix, 0, "RFC ");
+ if (rfc && rfc[0]) {
+ subject_prefix = 1;
+ if (rfc[0] == '-')
+ strbuf_addf(&sprefix, " %s", rfc + 1);
+ else
+ strbuf_insertf(&sprefix, 0, "%s ", rfc);
+ }
if (reroll_count) {
strbuf_addf(&sprefix, " v%s", reroll_count);
@@ -2206,8 +2226,10 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
if (check_head) {
const char *ref, *v;
- ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
- NULL, NULL);
+ ref = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ "HEAD",
+ RESOLVE_REF_READING,
+ NULL, NULL);
if (ref && skip_prefix(ref, "refs/heads/", &v))
branch_name = xstrdup(v);
else
@@ -2274,7 +2296,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
}
if (creation_factor < 0)
- creation_factor = RANGE_DIFF_CREATION_FACTOR_DEFAULT;
+ creation_factor = CREATION_FACTOR_FOR_THE_SAME_SERIES;
else if (!rdiff_prev)
die(_("the option '%s' requires '%s'"), "--creation-factor", "--range-diff");
diff --git a/builtin/merge-index.c b/builtin/merge-index.c
index 270d5f644a..0fabe3f6bb 100644
--- a/builtin/merge-index.c
+++ b/builtin/merge-index.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "hex.h"
#include "read-cache-ll.h"
@@ -18,11 +17,11 @@ static int merge_entry(int pos, const char *path)
char ownbuf[4][60];
struct child_process cmd = CHILD_PROCESS_INIT;
- if (pos >= the_index.cache_nr)
+ if (pos >= the_repository->index->cache_nr)
die("git merge-index: %s not in the cache", path);
found = 0;
do {
- const struct cache_entry *ce = the_index.cache[pos];
+ const struct cache_entry *ce = the_repository->index->cache[pos];
int stage = ce_stage(ce);
if (strcmp(ce->name, path))
@@ -32,7 +31,7 @@ static int merge_entry(int pos, const char *path)
xsnprintf(ownbuf[stage], sizeof(ownbuf[stage]), "%o", ce->ce_mode);
arguments[stage] = hexbuf[stage];
arguments[stage + 4] = ownbuf[stage];
- } while (++pos < the_index.cache_nr);
+ } while (++pos < the_repository->index->cache_nr);
if (!found)
die("git merge-index: %s not in the cache", path);
@@ -51,7 +50,7 @@ static int merge_entry(int pos, const char *path)
static void merge_one_path(const char *path)
{
- int pos = index_name_pos(&the_index, path, strlen(path));
+ int pos = index_name_pos(the_repository->index, path, strlen(path));
/*
* If it already exists in the cache as stage0, it's
@@ -65,9 +64,9 @@ static void merge_all(void)
{
int i;
/* TODO: audit for interaction with sparse-index. */
- ensure_full_index(&the_index);
- for (i = 0; i < the_index.cache_nr; i++) {
- const struct cache_entry *ce = the_index.cache[i];
+ ensure_full_index(the_repository->index);
+ for (i = 0; i < the_repository->index->cache_nr; i++) {
+ const struct cache_entry *ce = the_repository->index->cache[i];
if (!ce_stage(ce))
continue;
i += merge_entry(i, ce->name)-1;
@@ -89,7 +88,7 @@ int cmd_merge_index(int argc, const char **argv, const char *prefix UNUSED)
repo_read_index(the_repository);
/* TODO: audit for interaction with sparse-index. */
- ensure_full_index(&the_index);
+ ensure_full_index(the_repository->index);
i = 1;
if (!strcmp(argv[i], "-o")) {
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index 8bdb439131..1082d919fd 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "tree-walk.h"
#include "xdiff-interface.h"
@@ -364,7 +363,7 @@ static void trivial_merge_trees(struct tree_desc t[3], const char *base)
setup_traverse_info(&info, base);
info.fn = threeway_callback;
- traverse_trees(&the_index, 3, t, &info);
+ traverse_trees(the_repository->index, 3, t, &info);
}
static void *get_tree_descriptor(struct repository *r,
diff --git a/builtin/merge.c b/builtin/merge.c
index 6f4fec87fc..e4bd65eeba 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -6,7 +6,6 @@
* Based on git-merge.sh by Junio C Hamano.
*/
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "advice.h"
@@ -300,7 +299,7 @@ static int save_state(struct object_id *stash)
int rc = -1;
fd = repo_hold_locked_index(the_repository, &lock_file, 0);
- refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL);
+ refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL, NULL);
if (0 <= fd)
repo_update_index_if_able(the_repository, &lock_file);
rollback_lock_file(&lock_file);
@@ -372,7 +371,7 @@ static void restore_state(const struct object_id *head,
run_command(&cmd);
refresh_cache:
- discard_index(&the_index);
+ discard_index(the_repository->index);
if (repo_read_index(the_repository) < 0)
die(_("could not read index"));
}
@@ -449,8 +448,10 @@ static void finish(struct commit *head_commit,
if (verbosity >= 0 && !merge_msg.len)
printf(_("No merge message -- not updating HEAD\n"));
else {
- update_ref(reflog_message.buf, "HEAD", new_head, head,
- 0, UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository),
+ reflog_message.buf, "HEAD", new_head,
+ head,
+ 0, UPDATE_REFS_DIE_ON_ERR);
/*
* We ignore errors in 'gc --auto', since the
* user should see them.
@@ -547,7 +548,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
struct strbuf truname = STRBUF_INIT;
strbuf_addf(&truname, "refs/heads/%s", remote);
strbuf_setlen(&truname, truname.len - len);
- if (ref_exists(truname.buf)) {
+ if (refs_ref_exists(get_main_ref_store(the_repository), truname.buf)) {
strbuf_addf(msg,
"%s\t\tbranch '%s'%s of .\n",
oid_to_hex(&remote_head->object.oid),
@@ -657,8 +658,8 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,
memset(&opts, 0, sizeof(opts));
opts.head_idx = 2;
- opts.src_index = &the_index;
- opts.dst_index = &the_index;
+ opts.src_index = the_repository->index;
+ opts.dst_index = the_repository->index;
opts.update = 1;
opts.verbose_update = 1;
opts.trivial_merges_only = 1;
@@ -674,7 +675,7 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,
if (!trees[nr_trees++])
return -1;
opts.fn = threeway_merge;
- cache_tree_free(&the_index.cache_tree);
+ cache_tree_free(&the_repository->index->cache_tree);
for (i = 0; i < nr_trees; i++) {
parse_tree(trees[i]);
init_tree_desc(t+i, &trees[i]->object.oid,
@@ -687,7 +688,7 @@ static int read_tree_trivial(struct object_id *common, struct object_id *head,
static void write_tree_trivial(struct object_id *oid)
{
- if (write_index_as_tree(oid, &the_index, get_index_file(), 0, NULL))
+ if (write_index_as_tree(oid, the_repository->index, get_index_file(), 0, NULL))
die(_("git write-tree failed to write a tree"));
}
@@ -745,7 +746,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
rollback_lock_file(&lock);
return 2;
}
- if (write_locked_index(&the_index, &lock,
+ if (write_locked_index(the_repository->index, &lock,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
die(_("unable to write %s"), get_index_file());
return clean ? 0 : 1;
@@ -768,8 +769,8 @@ static int count_unmerged_entries(void)
{
int i, ret = 0;
- for (i = 0; i < the_index.cache_nr; i++)
- if (ce_stage(the_index.cache[i]))
+ for (i = 0; i < the_repository->index->cache_nr; i++)
+ if (ce_stage(the_repository->index->cache[i]))
ret++;
return ret;
@@ -843,9 +844,9 @@ static void prepare_to_commit(struct commit_list *remoteheads)
* the editor and after we invoke run_status above.
*/
if (invoked_hook)
- discard_index(&the_index);
+ discard_index(the_repository->index);
}
- read_index_from(&the_index, index_file, get_git_dir());
+ read_index_from(the_repository->index, index_file, get_git_dir());
strbuf_addbuf(&msg, &merge_msg);
if (squash)
BUG("the control must not reach here under --squash");
@@ -957,7 +958,7 @@ static int suggest_conflicts(void)
* Thus, we will get the cleanup mode which is returned when we _are_
* using an editor.
*/
- append_conflicts_hint(&the_index, &msgbuf,
+ append_conflicts_hint(the_repository->index, &msgbuf,
get_cleanup_mode(cleanup_arg, 1));
fputs(msgbuf.buf, fp);
strbuf_release(&msgbuf);
@@ -1252,7 +1253,7 @@ static int merging_a_throwaway_tag(struct commit *commit)
*/
tag_ref = xstrfmt("refs/tags/%s",
((struct tag *)merge_remote_util(commit)->obj)->tag);
- if (!read_ref(tag_ref, &oid) &&
+ if (!refs_read_ref(get_main_ref_store(the_repository), tag_ref, &oid) &&
oideq(&oid, &merge_remote_util(commit)->obj->oid))
is_throwaway_tag = 0;
else
@@ -1284,7 +1285,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
* Check if we are _not_ on a detached HEAD, i.e. if there is a
* current branch.
*/
- branch = branch_to_free = resolve_refdup("HEAD", 0, &head_oid, NULL);
+ branch = branch_to_free = refs_resolve_refdup(get_main_ref_store(the_repository),
+ "HEAD", 0, &head_oid,
+ NULL);
if (branch)
skip_prefix(branch, "refs/heads/", &branch);
@@ -1325,8 +1328,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
if (!file_exists(git_path_merge_head(the_repository)))
die(_("There is no merge to abort (MERGE_HEAD missing)."));
- if (!read_ref("MERGE_AUTOSTASH", &stash_oid))
- delete_ref("", "MERGE_AUTOSTASH", &stash_oid, REF_NO_DEREF);
+ if (!refs_read_ref(get_main_ref_store(the_repository), "MERGE_AUTOSTASH", &stash_oid))
+ refs_delete_ref(get_main_ref_store(the_repository),
+ "", "MERGE_AUTOSTASH", &stash_oid,
+ REF_NO_DEREF);
/* Invoke 'git reset --merge' */
ret = cmd_reset(nargc, nargv, prefix);
@@ -1379,14 +1384,14 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
else
die(_("You have not concluded your merge (MERGE_HEAD exists)."));
}
- if (ref_exists("CHERRY_PICK_HEAD")) {
+ if (refs_ref_exists(get_main_ref_store(the_repository), "CHERRY_PICK_HEAD")) {
if (advice_enabled(ADVICE_RESOLVE_CONFLICT))
die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
"Please, commit your changes before you merge."));
else
die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."));
}
- resolve_undo_clear_index(&the_index);
+ resolve_undo_clear_index(the_repository->index);
if (option_edit < 0)
option_edit = default_edit_option();
@@ -1450,8 +1455,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
remote_head_oid = &remoteheads->item->object.oid;
read_empty(remote_head_oid);
- update_ref("initial pull", "HEAD", remote_head_oid, NULL, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository),
+ "initial pull", "HEAD", remote_head_oid, NULL,
+ 0,
+ UPDATE_REFS_DIE_ON_ERR);
goto done;
}
@@ -1531,8 +1538,10 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
free(list);
}
- update_ref("updating ORIG_HEAD", "ORIG_HEAD",
- &head_commit->object.oid, NULL, 0, UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository),
+ "updating ORIG_HEAD", "ORIG_HEAD",
+ &head_commit->object.oid, NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
if (remoteheads && !common) {
/* No common ancestors found. */
@@ -1595,7 +1604,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
* We are not doing octopus, not fast-forward, and have
* only one common.
*/
- refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL);
+ refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL, NULL);
if (allow_trivial && fast_forward != FF_ONLY) {
/*
* Must first ensure that index matches HEAD before
@@ -1784,6 +1793,6 @@ done:
}
strbuf_release(&buf);
free(branch_to_free);
- discard_index(&the_index);
+ discard_index(the_repository->index);
return ret;
}
diff --git a/builtin/multi-pack-index.c b/builtin/multi-pack-index.c
index a72aebecaa..8360932d2e 100644
--- a/builtin/multi-pack-index.c
+++ b/builtin/multi-pack-index.c
@@ -8,6 +8,7 @@
#include "strbuf.h"
#include "trace2.h"
#include "object-store-ll.h"
+#include "replace-object.h"
#define BUILTIN_MIDX_WRITE_USAGE \
N_("git multi-pack-index [<options>] write [--preferred-pack=<pack>]" \
@@ -273,6 +274,8 @@ int cmd_multi_pack_index(int argc, const char **argv,
};
struct option *options = parse_options_concat(builtin_multi_pack_index_options, common_opts);
+ disable_replace_refs();
+
git_config(git_default_config, NULL);
if (the_repository &&
diff --git a/builtin/mv.c b/builtin/mv.c
index 22e64fc290..74aa9746aa 100644
--- a/builtin/mv.c
+++ b/builtin/mv.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2006 Johannes Schindelin
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "abspath.h"
#include "advice.h"
@@ -95,9 +95,9 @@ static void prepare_move_submodule(const char *src, int first,
const char **submodule_gitfile)
{
struct strbuf submodule_dotgit = STRBUF_INIT;
- if (!S_ISGITLINK(the_index.cache[first]->ce_mode))
+ if (!S_ISGITLINK(the_repository->index->cache[first]->ce_mode))
die(_("Directory %s is in index and no submodule?"), src);
- if (!is_staging_gitmodules_ok(&the_index))
+ if (!is_staging_gitmodules_ok(the_repository->index))
die(_("Please stage your changes to .gitmodules or stash them to proceed"));
strbuf_addf(&submodule_dotgit, "%s/.git", src);
*submodule_gitfile = read_gitfile(submodule_dotgit.buf);
@@ -114,13 +114,13 @@ static int index_range_of_same_dir(const char *src, int length,
const char *src_w_slash = add_slash(src);
int first, last, len_w_slash = length + 1;
- first = index_name_pos(&the_index, src_w_slash, len_w_slash);
+ first = index_name_pos(the_repository->index, src_w_slash, len_w_slash);
if (first >= 0)
die(_("%.*s is in index"), len_w_slash, src_w_slash);
first = -1 - first;
- for (last = first; last < the_index.cache_nr; last++) {
- const char *path = the_index.cache[last]->name;
+ for (last = first; last < the_repository->index->cache_nr; last++) {
+ const char *path = the_repository->index->cache[last]->name;
if (strncmp(path, src_w_slash, len_w_slash))
break;
}
@@ -144,14 +144,14 @@ static int empty_dir_has_sparse_contents(const char *name)
const char *with_slash = add_slash(name);
int length = strlen(with_slash);
- int pos = index_name_pos(&the_index, with_slash, length);
+ int pos = index_name_pos(the_repository->index, with_slash, length);
const struct cache_entry *ce;
if (pos < 0) {
pos = -pos - 1;
- if (pos >= the_index.cache_nr)
+ if (pos >= the_repository->index->cache_nr)
goto free_return;
- ce = the_index.cache[pos];
+ ce = the_repository->index->cache[pos];
if (strncmp(with_slash, ce->name, length))
goto free_return;
if (ce_skip_worktree(ce))
@@ -223,7 +223,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
S_ISDIR(st.st_mode)) {
destination = internal_prefix_pathspec(dst_w_slash, argv, argc, DUP_BASENAME);
} else {
- if (!path_in_sparse_checkout(dst_w_slash, &the_index) &&
+ if (!path_in_sparse_checkout(dst_w_slash, the_repository->index) &&
empty_dir_has_sparse_contents(dst_w_slash)) {
destination = internal_prefix_pathspec(dst_w_slash, argv, argc, DUP_BASENAME);
dst_mode = SKIP_WORKTREE_DIR;
@@ -239,7 +239,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
* is deprecated at this point) sparse-checkout. As
* SPARSE here is only considering cone-mode situation.
*/
- if (!path_in_cone_mode_sparse_checkout(destination[0], &the_index))
+ if (!path_in_cone_mode_sparse_checkout(destination[0], the_repository->index))
dst_mode = SPARSE;
}
}
@@ -263,10 +263,10 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
int pos;
const struct cache_entry *ce;
- pos = index_name_pos(&the_index, src, length);
+ pos = index_name_pos(the_repository->index, src, length);
if (pos < 0) {
const char *src_w_slash = add_slash(src);
- if (!path_in_sparse_checkout(src_w_slash, &the_index) &&
+ if (!path_in_sparse_checkout(src_w_slash, the_repository->index) &&
empty_dir_has_sparse_contents(src)) {
modes[i] |= SKIP_WORKTREE_DIR;
goto dir_check;
@@ -276,7 +276,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
bad = _("bad source");
goto act_on_entry;
}
- ce = the_index.cache[pos];
+ ce = the_repository->index->cache[pos];
if (!ce_skip_worktree(ce)) {
bad = _("bad source");
goto act_on_entry;
@@ -286,7 +286,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
goto act_on_entry;
}
/* Check if dst exists in index */
- if (index_name_pos(&the_index, dst, strlen(dst)) < 0) {
+ if (index_name_pos(the_repository->index, dst, strlen(dst)) < 0) {
modes[i] |= SPARSE;
goto act_on_entry;
}
@@ -311,7 +311,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
dir_check:
if (S_ISDIR(st.st_mode)) {
int j, dst_len, n;
- int first = index_name_pos(&the_index, src, length), last;
+ int first = index_name_pos(the_repository->index, src, length), last;
if (first >= 0) {
prepare_move_submodule(src, first,
@@ -339,7 +339,7 @@ dir_check:
dst_len = strlen(dst);
for (j = 0; j < last - first; j++) {
- const struct cache_entry *ce = the_index.cache[first + j];
+ const struct cache_entry *ce = the_repository->index->cache[first + j];
const char *path = ce->name;
source[argc + j] = path;
destination[argc + j] =
@@ -351,7 +351,7 @@ dir_check:
argc += last - first;
goto act_on_entry;
}
- if (!(ce = index_file_exists(&the_index, src, length, 0))) {
+ if (!(ce = index_file_exists(the_repository->index, src, length, 0))) {
bad = _("not under version control");
goto act_on_entry;
}
@@ -387,7 +387,7 @@ dir_check:
if (ignore_sparse &&
(dst_mode & (SKIP_WORKTREE_DIR | SPARSE)) &&
- index_entry_exists(&the_index, dst, strlen(dst))) {
+ index_entry_exists(the_repository->index, dst, strlen(dst))) {
bad = _("destination exists in the index");
if (force) {
if (verbose)
@@ -404,12 +404,12 @@ dir_check:
* option as a way to have a successful run.
*/
if (!ignore_sparse &&
- !path_in_sparse_checkout(src, &the_index)) {
+ !path_in_sparse_checkout(src, the_repository->index)) {
string_list_append(&only_match_skip_worktree, src);
skip_sparse = 1;
}
if (!ignore_sparse &&
- !path_in_sparse_checkout(dst, &the_index)) {
+ !path_in_sparse_checkout(dst, the_repository->index)) {
string_list_append(&only_match_skip_worktree, dst);
skip_sparse = 1;
}
@@ -449,7 +449,7 @@ remove_entry:
int pos;
int sparse_and_dirty = 0;
struct checkout state = CHECKOUT_INIT;
- state.istate = &the_index;
+ state.istate = the_repository->index;
if (force)
state.force = 1;
@@ -476,14 +476,14 @@ remove_entry:
if (mode & (WORKING_DIRECTORY | SKIP_WORKTREE_DIR))
continue;
- pos = index_name_pos(&the_index, src, strlen(src));
+ pos = index_name_pos(the_repository->index, src, strlen(src));
assert(pos >= 0);
if (!(mode & SPARSE) && !lstat(src, &st))
- sparse_and_dirty = ie_modified(&the_index,
- the_index.cache[pos],
+ sparse_and_dirty = ie_modified(the_repository->index,
+ the_repository->index->cache[pos],
&st,
0);
- rename_index_entry_at(&the_index, pos, dst);
+ rename_index_entry_at(the_repository->index, pos, dst);
if (ignore_sparse &&
core_apply_sparse_checkout &&
@@ -495,11 +495,11 @@ remove_entry:
* should be added in a future patch.
*/
if ((mode & SPARSE) &&
- path_in_sparse_checkout(dst, &the_index)) {
+ path_in_sparse_checkout(dst, the_repository->index)) {
/* from out-of-cone to in-cone */
- int dst_pos = index_name_pos(&the_index, dst,
+ int dst_pos = index_name_pos(the_repository->index, dst,
strlen(dst));
- struct cache_entry *dst_ce = the_index.cache[dst_pos];
+ struct cache_entry *dst_ce = the_repository->index->cache[dst_pos];
dst_ce->ce_flags &= ~CE_SKIP_WORKTREE;
@@ -507,11 +507,11 @@ remove_entry:
die(_("cannot checkout %s"), dst_ce->name);
} else if ((dst_mode & (SKIP_WORKTREE_DIR | SPARSE)) &&
!(mode & SPARSE) &&
- !path_in_sparse_checkout(dst, &the_index)) {
+ !path_in_sparse_checkout(dst, the_repository->index)) {
/* from in-cone to out-of-cone */
- int dst_pos = index_name_pos(&the_index, dst,
+ int dst_pos = index_name_pos(the_repository->index, dst,
strlen(dst));
- struct cache_entry *dst_ce = the_index.cache[dst_pos];
+ struct cache_entry *dst_ce = the_repository->index->cache[dst_pos];
/*
* if src is clean, it will suffice to remove it
@@ -559,9 +559,9 @@ remove_entry:
advise_on_moving_dirty_path(&dirty_paths);
if (gitmodules_modified)
- stage_updated_gitmodules(&the_index);
+ stage_updated_gitmodules(the_repository->index);
- if (write_locked_index(&the_index, &lock_file,
+ if (write_locked_index(the_repository->index, &lock_file,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
die(_("Unable to write new index file"));
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index ad9930c831..70e9ec4e47 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -296,7 +296,8 @@ static void add_to_tip_table(const struct object_id *oid, const char *refname,
char *short_refname = NULL;
if (shorten_unambiguous)
- short_refname = shorten_unambiguous_ref(refname, 0);
+ short_refname = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+ refname, 0);
else if (skip_prefix(refname, "refs/heads/", &refname))
; /* refname already advanced */
else
@@ -647,7 +648,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
adjust_cutoff_timestamp_for_slop();
- for_each_ref(name_ref, &data);
+ refs_for_each_ref(get_main_ref_store(the_repository), name_ref, &data);
name_tips(&string_pool);
if (annotate_stdin) {
diff --git a/builtin/notes.c b/builtin/notes.c
index cb011303e6..7f80b3449b 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -794,9 +794,9 @@ static int merge_abort(struct notes_merge_options *o)
* notes_merge_abort() to remove .git/NOTES_MERGE_WORKTREE.
*/
- if (delete_ref(NULL, "NOTES_MERGE_PARTIAL", NULL, 0))
+ if (refs_delete_ref(get_main_ref_store(the_repository), NULL, "NOTES_MERGE_PARTIAL", NULL, 0))
ret += error(_("failed to delete ref NOTES_MERGE_PARTIAL"));
- if (delete_ref(NULL, "NOTES_MERGE_REF", NULL, REF_NO_DEREF))
+ if (refs_delete_ref(get_main_ref_store(the_repository), NULL, "NOTES_MERGE_REF", NULL, REF_NO_DEREF))
ret += error(_("failed to delete ref NOTES_MERGE_REF"));
if (notes_merge_abort(o))
ret += error(_("failed to remove 'git notes merge' worktree"));
@@ -834,7 +834,8 @@ static int merge_commit(struct notes_merge_options *o)
init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0);
o->local_ref = local_ref_to_free =
- resolve_refdup("NOTES_MERGE_REF", 0, &oid, NULL);
+ refs_resolve_refdup(get_main_ref_store(the_repository),
+ "NOTES_MERGE_REF", 0, &oid, NULL);
if (!o->local_ref)
die(_("failed to resolve NOTES_MERGE_REF"));
@@ -847,9 +848,10 @@ static int merge_commit(struct notes_merge_options *o)
&pretty_ctx);
strbuf_trim(&msg);
strbuf_insertstr(&msg, 0, "notes: ");
- update_ref(msg.buf, o->local_ref, &oid,
- is_null_oid(&parent_oid) ? NULL : &parent_oid,
- 0, UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), msg.buf,
+ o->local_ref, &oid,
+ is_null_oid(&parent_oid) ? NULL : &parent_oid,
+ 0, UPDATE_REFS_DIE_ON_ERR);
free_notes(t);
strbuf_release(&msg);
@@ -961,14 +963,16 @@ static int merge(int argc, const char **argv, const char *prefix)
if (result >= 0) /* Merge resulted (trivially) in result_oid */
/* Update default notes ref with new commit */
- update_ref(msg.buf, default_notes_ref(), &result_oid, NULL, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), msg.buf,
+ default_notes_ref(), &result_oid, NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
else { /* Merge has unresolved conflicts */
struct worktree **worktrees;
const struct worktree *wt;
/* Update .git/NOTES_MERGE_PARTIAL with partial merge result */
- update_ref(msg.buf, "NOTES_MERGE_PARTIAL", &result_oid, NULL,
- 0, UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), msg.buf,
+ "NOTES_MERGE_PARTIAL", &result_oid, NULL,
+ 0, UPDATE_REFS_DIE_ON_ERR);
/* Store ref-to-be-updated into .git/NOTES_MERGE_REF */
worktrees = get_worktrees();
wt = find_shared_symref(worktrees, "NOTES_MERGE_REF",
@@ -977,7 +981,7 @@ static int merge(int argc, const char **argv, const char *prefix)
die(_("a notes merge into %s is already in-progress at %s"),
default_notes_ref(), wt->path);
free_worktrees(worktrees);
- if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL))
+ if (refs_update_symref(get_main_ref_store(the_repository), "NOTES_MERGE_REF", default_notes_ref(), NULL))
die(_("failed to store link to current notes ref (%s)"),
default_notes_ref());
fprintf(stderr, _("Automatic notes merge failed. Fix conflicts in %s "
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index baf0090fc8..d64d386e84 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -939,7 +939,8 @@ static struct object_entry **compute_write_order(void)
/*
* Mark objects that are at the tip of tags.
*/
- for_each_tag_ref(mark_tagged, NULL);
+ refs_for_each_tag_ref(get_main_ref_store(the_repository), mark_tagged,
+ NULL);
if (use_delta_islands) {
max_layers = compute_pack_layers(&to_pack);
@@ -1339,6 +1340,7 @@ static void write_pack_file(void)
hash_to_hex(hash));
if (write_bitmap_index) {
+ bitmap_writer_init(the_repository);
bitmap_writer_set_checksum(hash);
bitmap_writer_build_type_index(
&to_pack, written_list, nr_written);
@@ -1359,7 +1361,7 @@ static void write_pack_file(void)
stop_progress(&progress_state);
bitmap_writer_show_progress(progress);
- bitmap_writer_select_commits(indexed_commits, indexed_commits_nr, -1);
+ bitmap_writer_select_commits(indexed_commits, indexed_commits_nr);
if (bitmap_writer_build(&to_pack) < 0)
die(_("failed to write bitmap index"));
bitmap_writer_finish(written_list, nr_written,
@@ -4093,7 +4095,9 @@ static void mark_bitmap_preferred_tips(void)
return;
for_each_string_list_item(item, preferred_tips) {
- for_each_ref_in(item->string, mark_bitmap_preferred_tip, NULL);
+ refs_for_each_ref_in(get_main_ref_store(the_repository),
+ item->string, mark_bitmap_preferred_tip,
+ NULL);
}
}
@@ -4588,7 +4592,8 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
}
cleanup_preferred_base();
if (include_tag && nr_result)
- for_each_tag_ref(add_ref_tag, NULL);
+ refs_for_each_tag_ref(get_main_ref_store(the_repository),
+ add_ref_tag, NULL);
stop_progress(&progress_state);
trace2_region_leave("pack-objects", "enumerate-objects",
the_repository);
diff --git a/builtin/patch-id.c b/builtin/patch-id.c
index 3894d2b970..583099cacf 100644
--- a/builtin/patch-id.c
+++ b/builtin/patch-id.c
@@ -5,6 +5,7 @@
#include "hash.h"
#include "hex.h"
#include "parse-options.h"
+#include "setup.h"
static void flush_current_id(int patchlen, struct object_id *id, struct object_id *result)
{
@@ -237,6 +238,18 @@ int cmd_patch_id(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, builtin_patch_id_options,
patch_id_usage, 0);
+ /*
+ * We rely on `the_hash_algo` to compute patch IDs. This is dubious as
+ * it means that the hash algorithm now depends on the object hash of
+ * the repository, even though git-patch-id(1) clearly defines that
+ * patch IDs always use SHA1.
+ *
+ * NEEDSWORK: This hack should be removed in favor of converting
+ * the code that computes patch IDs to always use SHA1.
+ */
+ if (!the_hash_algo)
+ repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
+
generate_id_list(opts ? opts > 1 : config.stable,
opts ? opts == 3 : config.verbatim);
return 0;
diff --git a/builtin/pull.c b/builtin/pull.c
index 72cbb76d52..d622202bce 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -5,7 +5,7 @@
*
* Fetch one or more remote refs and merge it/them into the current HEAD.
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "advice.h"
#include "config.h"
@@ -611,7 +611,7 @@ static int pull_into_void(const struct object_id *merge_head,
merge_head, 0))
return 1;
- if (update_ref("initial pull", "HEAD", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR))
+ if (refs_update_ref(get_main_ref_store(the_repository), "initial pull", "HEAD", merge_head, curr_head, 0, UPDATE_REFS_DIE_ON_ERR))
return 1;
return 0;
@@ -1044,7 +1044,7 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
if (opt_autostash == -1)
opt_autostash = config_autostash;
- if (is_null_oid(&orig_head) && !is_index_unborn(&the_index))
+ if (is_null_oid(&orig_head) && !is_index_unborn(the_repository->index))
die(_("Updating an unborn branch with changes added to the index."));
if (!opt_autostash)
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index 6f89cec0fb..a8cf8504b8 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -4,7 +4,6 @@
* Copyright (C) Linus Torvalds, 2005
*/
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "config.h"
#include "gettext.h"
@@ -159,8 +158,8 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
memset(&opts, 0, sizeof(opts));
opts.head_idx = -1;
- opts.src_index = &the_index;
- opts.dst_index = &the_index;
+ opts.src_index = the_repository->index;
+ opts.dst_index = the_repository->index;
git_config(git_read_tree_config, NULL);
@@ -197,7 +196,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
die(_("You need to resolve your current index first"));
stage = opts.merge = 1;
}
- resolve_undo_clear_index(&the_index);
+ resolve_undo_clear_index(the_repository->index);
for (i = 0; i < argc; i++) {
const char *arg = argv[i];
@@ -225,7 +224,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
setup_work_tree();
if (opts.skip_sparse_checkout)
- ensure_full_index(&the_index);
+ ensure_full_index(the_repository->index);
if (opts.merge) {
switch (stage - 1) {
@@ -237,7 +236,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
break;
case 2:
opts.fn = twoway_merge;
- opts.initial_checkout = is_index_unborn(&the_index);
+ opts.initial_checkout = is_index_unborn(the_repository->index);
break;
case 3:
default:
@@ -258,7 +257,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
if (nr_trees == 1 && !opts.prefix)
opts.skip_cache_tree_update = 1;
- cache_tree_free(&the_index.cache_tree);
+ cache_tree_free(&the_repository->index->cache_tree);
for (i = 0; i < nr_trees; i++) {
struct tree *tree = trees[i];
if (parse_tree(tree) < 0)
@@ -282,7 +281,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
the_repository->index,
trees[0]);
- if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
+ if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
die("unable to write new index file");
return 0;
}
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 891f28468e..9fb0a6888d 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -4,7 +4,6 @@
* Copyright (c) 2018 Pratik Karki
*/
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "environment.h"
@@ -194,7 +193,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
return replay;
}
-static int edit_todo_file(unsigned flags)
+static int edit_todo_file(unsigned flags, struct replay_opts *opts)
{
const char *todo_file = rebase_path_todo();
struct todo_list todo_list = TODO_LIST_INIT,
@@ -205,7 +204,8 @@ static int edit_todo_file(unsigned flags)
return error_errno(_("could not read '%s'."), todo_file);
strbuf_stripspace(&todo_list.buf, comment_line_str);
- res = edit_todo_list(the_repository, &todo_list, &new_todo, NULL, NULL, flags);
+ res = edit_todo_list(the_repository, opts, &todo_list, &new_todo,
+ NULL, NULL, flags);
if (!res && todo_list_write_to_file(the_repository, &new_todo, todo_file,
NULL, NULL, -1, flags & ~(TODO_LIST_SHORTEN_IDS)))
res = error_errno(_("could not write '%s'"), todo_file);
@@ -252,7 +252,7 @@ static int init_basic_state(struct replay_opts *opts, const char *head_name,
if (!is_directory(merge_dir()) && mkdir_in_gitdir(merge_dir()))
return error_errno(_("could not create temporary %s"), merge_dir());
- delete_reflog("REBASE_HEAD");
+ refs_delete_reflog(get_main_ref_store(the_repository), "REBASE_HEAD");
interactive = fopen(path_interactive(), "w");
if (!interactive)
@@ -295,9 +295,9 @@ static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
if (ret)
error(_("could not generate todo list"));
else {
- discard_index(&the_index);
- if (todo_list_parse_insn_buffer(the_repository, todo_list.buf.buf,
- &todo_list))
+ discard_index(the_repository->index);
+ if (todo_list_parse_insn_buffer(the_repository, &replay,
+ todo_list.buf.buf, &todo_list))
BUG("unusable todo list");
ret = complete_action(the_repository, &replay, flags,
@@ -352,9 +352,13 @@ static int run_sequencer_rebase(struct rebase_options *opts)
replay_opts_release(&replay_opts);
break;
}
- case ACTION_EDIT_TODO:
- ret = edit_todo_file(flags);
+ case ACTION_EDIT_TODO: {
+ struct replay_opts replay_opts = get_replay_opts(opts);
+
+ ret = edit_todo_file(flags, &replay_opts);
+ replay_opts_release(&replay_opts);
break;
+ }
case ACTION_SHOW_CURRENT_PATCH: {
struct child_process cmd = CHILD_PROCESS_INIT;
@@ -514,8 +518,10 @@ static int finish_rebase(struct rebase_options *opts)
struct strbuf dir = STRBUF_INIT;
int ret = 0;
- delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
- delete_ref(NULL, "AUTO_MERGE", NULL, REF_NO_DEREF);
+ refs_delete_ref(get_main_ref_store(the_repository), NULL,
+ "REBASE_HEAD", NULL, REF_NO_DEREF);
+ refs_delete_ref(get_main_ref_store(the_repository), NULL,
+ "AUTO_MERGE", NULL, REF_NO_DEREF);
apply_autostash(state_dir_path("autostash", opts));
/*
* We ignore errors in 'git maintenance run --auto', since the
@@ -1623,7 +1629,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
/* Is it a local branch? */
strbuf_reset(&buf);
strbuf_addf(&buf, "refs/heads/%s", branch_name);
- if (!read_ref(buf.buf, &branch_oid)) {
+ if (!refs_read_ref(get_main_ref_store(the_repository), buf.buf, &branch_oid)) {
die_if_checked_out(buf.buf, 1);
options.head_name = xstrdup(buf.buf);
options.orig_head =
@@ -1640,8 +1646,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
} else if (argc == 0) {
/* Do not need to switch branches, we are already on it. */
options.head_name =
- xstrdup_or_null(resolve_ref_unsafe("HEAD", 0, NULL,
- &flags));
+ xstrdup_or_null(refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", 0, NULL,
+ &flags));
if (!options.head_name)
die(_("No such ref: %s"), "HEAD");
if (flags & REF_ISSYMREF) {
@@ -1735,7 +1741,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (!(options.flags & REBASE_NO_QUIET))
; /* be quiet */
else if (!strcmp(branch_name, "HEAD") &&
- resolve_ref_unsafe("HEAD", 0, NULL, &flag))
+ refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", 0, NULL, &flag))
puts(_("HEAD is up to date."));
else
printf(_("Current branch %s is up to date.\n"),
@@ -1745,7 +1751,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
} else if (!(options.flags & REBASE_NO_QUIET))
; /* be quiet */
else if (!strcmp(branch_name, "HEAD") &&
- resolve_ref_unsafe("HEAD", 0, NULL, &flag))
+ refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", 0, NULL, &flag))
puts(_("HEAD is up to date, rebase forced."));
else
printf(_("Current branch %s is up to date, rebase "
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index e8d7df14b6..be8969a84a 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -1566,7 +1566,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
struct strbuf err = STRBUF_INIT;
if (!parse_object(the_repository, old_oid)) {
old_oid = NULL;
- if (ref_exists(name)) {
+ if (refs_ref_exists(get_main_ref_store(the_repository), name)) {
rp_warning("allowing deletion of corrupt ref");
} else {
rp_warning("deleting a non-existent ref");
@@ -1595,6 +1595,7 @@ static const char *update(struct command *cmd, struct shallow_info *si)
if (ref_transaction_update(transaction,
namespaced_name,
new_oid, old_oid,
+ NULL, NULL,
0, "push",
&err)) {
rp_error("%s", err.buf);
@@ -1693,7 +1694,8 @@ static void check_aliased_update(struct command *cmd, struct string_list *list)
int flag;
strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
- dst_name = resolve_ref_unsafe(buf.buf, 0, NULL, &flag);
+ dst_name = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ buf.buf, 0, NULL, &flag);
check_aliased_update_internal(cmd, list, dst_name, flag);
strbuf_release(&buf);
}
@@ -1829,7 +1831,8 @@ static void execute_commands_non_atomic(struct command *commands,
if (!should_process_cmd(cmd) || cmd->run_proc_receive)
continue;
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction) {
rp_error("%s", err.buf);
strbuf_reset(&err);
@@ -1857,7 +1860,8 @@ static void execute_commands_atomic(struct command *commands,
struct strbuf err = STRBUF_INIT;
const char *reported_error = "atomic push failure";
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction) {
rp_error("%s", err.buf);
strbuf_reset(&err);
@@ -1983,7 +1987,9 @@ static void execute_commands(struct command *commands,
check_aliased_updates(commands);
free(head_name_to_free);
- head_name = head_name_to_free = resolve_refdup("HEAD", 0, NULL, NULL);
+ head_name = head_name_to_free = refs_resolve_refdup(get_main_ref_store(the_repository),
+ "HEAD", 0, NULL,
+ NULL);
if (run_proc_receive &&
run_proc_receive_hook(commands, push_options))
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 060eb3377e..b4650cea16 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -364,11 +364,12 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
};
set_reflog_expiry_param(&cb.cmd, item->string);
- status |= reflog_expire(item->string, flags,
- reflog_expiry_prepare,
- should_prune_fn,
- reflog_expiry_cleanup,
- &cb);
+ status |= refs_reflog_expire(get_main_ref_store(the_repository),
+ item->string, flags,
+ reflog_expiry_prepare,
+ should_prune_fn,
+ reflog_expiry_cleanup,
+ &cb);
}
string_list_clear(&collected.reflogs, 0);
}
@@ -382,11 +383,12 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
continue;
}
set_reflog_expiry_param(&cb.cmd, ref);
- status |= reflog_expire(ref, flags,
- reflog_expiry_prepare,
- should_prune_fn,
- reflog_expiry_cleanup,
- &cb);
+ status |= refs_reflog_expire(get_main_ref_store(the_repository),
+ ref, flags,
+ reflog_expiry_prepare,
+ should_prune_fn,
+ reflog_expiry_cleanup,
+ &cb);
free(ref);
}
return status;
@@ -437,7 +439,8 @@ static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)
refname = argv[0];
if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL))
die(_("invalid ref format: %s"), refname);
- return !reflog_exists(refname);
+ return !refs_reflog_exists(get_main_ref_store(the_repository),
+ refname);
}
/*
diff --git a/builtin/remote.c b/builtin/remote.c
index 8412d12fa5..d52b1c0e10 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -240,7 +240,7 @@ static int add(int argc, const char **argv, const char *prefix)
strbuf_reset(&buf2);
strbuf_addf(&buf2, "refs/remotes/%s/%s", name, master);
- if (create_symref(buf.buf, buf2.buf, "remote add"))
+ if (refs_update_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, "remote add"))
return error(_("Could not setup master '%s'"), master);
}
@@ -376,7 +376,7 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
for (ref = fetch_map; ref; ref = ref->next) {
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))
+ else if (!ref->peer_ref || !refs_ref_exists(get_main_ref_store(the_repository), ref->peer_ref->name))
string_list_append(&states->new_refs, abbrev_branch(ref->name));
else
string_list_append(&states->tracked, abbrev_branch(ref->name));
@@ -598,8 +598,9 @@ static int read_remote_branches(const char *refname,
strbuf_addf(&buf, "refs/remotes/%s/", rename->old_name);
if (starts_with(refname, buf.buf)) {
item = string_list_append(rename->remote_branches, refname);
- symref = resolve_ref_unsafe(refname, RESOLVE_REF_READING,
- NULL, &flag);
+ symref = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ refname, RESOLVE_REF_READING,
+ NULL, &flag);
if (symref && (flag & REF_ISSYMREF)) {
item->util = xstrdup(symref);
rename->symrefs_nr++;
@@ -789,7 +790,8 @@ static int mv(int argc, const char **argv, const char *prefix)
* First remove symrefs, then rename the rest, finally create
* the new symrefs.
*/
- for_each_ref(read_remote_branches, &rename);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ read_remote_branches, &rename);
if (show_progress) {
/*
* Count symrefs twice, since "renaming" them is done by
@@ -805,7 +807,7 @@ static int mv(int argc, const char **argv, const char *prefix)
if (refs_read_symbolic_ref(get_main_ref_store(the_repository), item->string,
&referent))
continue;
- if (delete_ref(NULL, item->string, NULL, REF_NO_DEREF))
+ if (refs_delete_ref(get_main_ref_store(the_repository), NULL, item->string, NULL, REF_NO_DEREF))
die(_("deleting '%s' failed"), item->string);
strbuf_release(&referent);
@@ -823,7 +825,7 @@ static int mv(int argc, const char **argv, const char *prefix)
strbuf_reset(&buf2);
strbuf_addf(&buf2, "remote: renamed %s to %s",
item->string, buf.buf);
- if (rename_ref(item->string, buf.buf, buf2.buf))
+ if (refs_rename_ref(get_main_ref_store(the_repository), item->string, buf.buf, buf2.buf))
die(_("renaming '%s' failed"), item->string);
display_progress(progress, ++refs_renamed_nr);
}
@@ -843,7 +845,7 @@ static int mv(int argc, const char **argv, const char *prefix)
strbuf_reset(&buf3);
strbuf_addf(&buf3, "remote: renamed %s to %s",
item->string, buf.buf);
- if (create_symref(buf.buf, buf2.buf, buf3.buf))
+ if (refs_update_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, buf3.buf))
die(_("creating '%s' failed"), buf.buf);
display_progress(progress, ++refs_renamed_nr);
}
@@ -917,11 +919,14 @@ static int rm(int argc, const char **argv, const char *prefix)
* refs, which are invalidated when deleting a branch.
*/
cb_data.remote = remote;
- result = for_each_ref(add_branch_for_removal, &cb_data);
+ result = refs_for_each_ref(get_main_ref_store(the_repository),
+ add_branch_for_removal, &cb_data);
strbuf_release(&buf);
if (!result)
- result = delete_refs("remote: remove", &branches, REF_NO_DEREF);
+ result = refs_delete_refs(get_main_ref_store(the_repository),
+ "remote: remove", &branches,
+ REF_NO_DEREF);
string_list_clear(&branches, 0);
if (skipped.nr) {
@@ -1010,7 +1015,8 @@ static int get_remote_ref_states(const char *name,
get_push_ref_states(remote_refs, states);
transport_disconnect(transport);
} else {
- for_each_ref(append_ref_to_tracked_list, states);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ append_ref_to_tracked_list, states);
string_list_sort(&states->tracked);
get_push_ref_states_noquery(states);
}
@@ -1407,7 +1413,7 @@ static int set_head(int argc, const char **argv, const char *prefix)
head_name = xstrdup(states.heads.items[0].string);
free_remote_ref_states(&states);
} else if (opt_d && !opt_a && argc == 1) {
- if (delete_ref(NULL, buf.buf, NULL, REF_NO_DEREF))
+ if (refs_delete_ref(get_main_ref_store(the_repository), NULL, buf.buf, NULL, REF_NO_DEREF))
result |= error(_("Could not delete %s"), buf.buf);
} else
usage_with_options(builtin_remote_sethead_usage, options);
@@ -1415,9 +1421,9 @@ static int set_head(int argc, const char **argv, const char *prefix)
if (head_name) {
strbuf_addf(&buf2, "refs/remotes/%s/%s", argv[0], head_name);
/* make sure it's valid */
- if (!ref_exists(buf2.buf))
+ if (!refs_ref_exists(get_main_ref_store(the_repository), buf2.buf))
result |= error(_("Not a valid ref: %s"), buf2.buf);
- else if (create_symref(buf.buf, buf2.buf, "remote set-head"))
+ else if (refs_update_symref(get_main_ref_store(the_repository), buf.buf, buf2.buf, "remote set-head"))
result |= error(_("Could not setup %s"), buf.buf);
else if (opt_a)
printf("%s/HEAD set to %s\n", argv[0], head_name);
@@ -1457,7 +1463,8 @@ static int prune_remote(const char *remote, int dry_run)
string_list_sort(&refs_to_prune);
if (!dry_run)
- result |= delete_refs("remote: prune", &refs_to_prune, 0);
+ result |= refs_delete_refs(get_main_ref_store(the_repository),
+ "remote: prune", &refs_to_prune, 0);
for_each_string_list_item(item, &states.stale) {
const char *refname = item->util;
diff --git a/builtin/repack.c b/builtin/repack.c
index 15e4cccc45..43491a4cbf 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -706,11 +706,14 @@ static void midx_snapshot_refs(struct tempfile *f)
data.preferred = 1;
for_each_string_list_item(item, preferred)
- for_each_ref_in(item->string, midx_snapshot_ref_one, &data);
+ refs_for_each_ref_in(get_main_ref_store(the_repository),
+ item->string,
+ midx_snapshot_ref_one, &data);
data.preferred = 0;
}
- for_each_ref(midx_snapshot_ref_one, &data);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ midx_snapshot_ref_one, &data);
if (close_tempfile_gently(f)) {
int save_errno = errno;
diff --git a/builtin/replace.c b/builtin/replace.c
index da59600ad2..f46ff57691 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -130,7 +130,7 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
strbuf_addstr(&ref, oid_to_hex(&oid));
full_hex = ref.buf + base_len;
- if (read_ref(ref.buf, &oid)) {
+ if (refs_read_ref(get_main_ref_store(the_repository), ref.buf, &oid)) {
error(_("replace ref '%s' not found"), full_hex);
had_error = 1;
continue;
@@ -145,7 +145,7 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
static int delete_replace_ref(const char *name, const char *ref,
const struct object_id *oid)
{
- if (delete_ref(NULL, ref, oid, 0))
+ if (refs_delete_ref(get_main_ref_store(the_repository), NULL, ref, oid, 0))
return 1;
printf_ln(_("Deleted replace ref '%s'"), name);
return 0;
@@ -163,7 +163,7 @@ static int check_ref_valid(struct object_id *object,
if (check_refname_format(ref->buf, 0))
return error(_("'%s' is not a valid ref name"), ref->buf);
- if (read_ref(ref->buf, prev))
+ if (refs_read_ref(get_main_ref_store(the_repository), ref->buf, prev))
oidclr(prev);
else if (!force)
return error(_("replace ref '%s' already exists"), ref->buf);
@@ -198,10 +198,11 @@ static int replace_object_oid(const char *object_ref,
return -1;
}
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction ||
ref_transaction_update(transaction, ref.buf, repl, &prev,
- 0, NULL, &err) ||
+ NULL, NULL, 0, NULL, &err) ||
ref_transaction_commit(transaction, &err))
res = error("%s", err.buf);
diff --git a/builtin/replay.c b/builtin/replay.c
index 6bc4b47f09..6bf0691f15 100644
--- a/builtin/replay.c
+++ b/builtin/replay.c
@@ -2,7 +2,6 @@
* "git replay" builtin command
*/
-#define USE_THE_INDEX_VARIABLE
#include "git-compat-util.h"
#include "builtin.h"
diff --git a/builtin/reset.c b/builtin/reset.c
index 1d62ff6332..5f941fb3a2 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -7,7 +7,7 @@
*
* Copyright (c) 2005, 2006 Linus Torvalds and Junio C Hamano
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "advice.h"
#include "config.h"
@@ -66,8 +66,8 @@ static int reset_index(const char *ref, const struct object_id *oid, int reset_t
memset(&opts, 0, sizeof(opts));
opts.head_idx = 1;
- opts.src_index = &the_index;
- opts.dst_index = &the_index;
+ opts.src_index = the_repository->index;
+ opts.dst_index = the_repository->index;
opts.fn = oneway_merge;
opts.merge = 1;
init_checkout_metadata(&opts.meta, ref, oid, NULL);
@@ -159,11 +159,11 @@ static void update_index_from_diff(struct diff_queue_struct *q,
struct cache_entry *ce;
if (!is_in_reset_tree && !intent_to_add) {
- remove_file_from_index(&the_index, one->path);
+ remove_file_from_index(the_repository->index, one->path);
continue;
}
- ce = make_cache_entry(&the_index, one->mode, &one->oid, one->path,
+ ce = make_cache_entry(the_repository->index, one->mode, &one->oid, one->path,
0, 0);
/*
@@ -174,9 +174,9 @@ static void update_index_from_diff(struct diff_queue_struct *q,
* if this entry is outside the sparse cone - this is necessary
* to properly construct the reset sparse directory.
*/
- pos = index_name_pos(&the_index, one->path, strlen(one->path));
- if ((pos >= 0 && ce_skip_worktree(the_index.cache[pos])) ||
- (pos < 0 && !path_in_sparse_checkout(one->path, &the_index)))
+ pos = index_name_pos(the_repository->index, one->path, strlen(one->path));
+ if ((pos >= 0 && ce_skip_worktree(the_repository->index->cache[pos])) ||
+ (pos < 0 && !path_in_sparse_checkout(one->path, the_repository->index)))
ce->ce_flags |= CE_SKIP_WORKTREE;
if (!ce)
@@ -186,7 +186,7 @@ static void update_index_from_diff(struct diff_queue_struct *q,
ce->ce_flags |= CE_INTENT_TO_ADD;
set_object_name_for_intent_to_add_entry(ce);
}
- add_index_entry(&the_index, ce,
+ add_index_entry(the_repository->index, ce,
ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
}
}
@@ -208,8 +208,8 @@ static int read_from_tree(const struct pathspec *pathspec,
opt.change = diff_change;
opt.add_remove = diff_addremove;
- if (pathspec->nr && pathspec_needs_expanded_index(&the_index, pathspec))
- ensure_full_index(&the_index);
+ if (pathspec->nr && pathspec_needs_expanded_index(the_repository->index, pathspec))
+ ensure_full_index(the_repository->index);
if (do_diff_cache(tree_oid, &opt))
return 1;
@@ -235,7 +235,7 @@ static void set_reflog_message(struct strbuf *sb, const char *action,
static void die_if_unmerged_cache(int reset_type)
{
- if (is_merge() || unmerged_index(&the_index))
+ if (is_merge() || unmerged_index(the_repository->index))
die(_("Cannot do a %s reset in the middle of a merge."),
_(reset_type_names[reset_type]));
@@ -307,13 +307,16 @@ static int reset_refs(const char *rev, const struct object_id *oid)
if (!repo_get_oid(the_repository, "HEAD", &oid_orig)) {
orig = &oid_orig;
set_reflog_message(&msg, "updating ORIG_HEAD", NULL);
- update_ref(msg.buf, "ORIG_HEAD", orig, old_orig, 0,
- UPDATE_REFS_MSG_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), msg.buf,
+ "ORIG_HEAD", orig, old_orig, 0,
+ UPDATE_REFS_MSG_ON_ERR);
} else if (old_orig)
- delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
+ refs_delete_ref(get_main_ref_store(the_repository), NULL,
+ "ORIG_HEAD", old_orig, 0);
set_reflog_message(&msg, "updating HEAD", rev);
- update_ref_status = update_ref(msg.buf, "HEAD", oid, orig, 0,
- UPDATE_REFS_MSG_ON_ERR);
+ update_ref_status = refs_update_ref(get_main_ref_store(the_repository),
+ msg.buf, "HEAD", oid, orig, 0,
+ UPDATE_REFS_MSG_ON_ERR);
strbuf_release(&msg);
return update_ref_status;
}
@@ -470,12 +473,12 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
update_ref_status = 1;
goto cleanup;
}
- the_index.updated_skipworktree = 1;
+ the_repository->index->updated_skipworktree = 1;
if (!no_refresh && get_git_work_tree()) {
uint64_t t_begin, t_delta_in_ms;
t_begin = getnanotime();
- refresh_index(&the_index, flags, NULL, NULL,
+ refresh_index(the_repository->index, flags, NULL, NULL,
_("Unstaged changes after reset:"));
t_delta_in_ms = (getnanotime() - t_begin) / 1000000;
if (!quiet && advice_enabled(ADVICE_RESET_NO_REFRESH_WARNING) && t_delta_in_ms > REFRESH_INDEX_DELAY_WARNING_IN_MS) {
@@ -501,7 +504,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
free(ref);
}
- if (write_locked_index(&the_index, &lock, COMMIT_LOCK))
+ if (write_locked_index(the_repository->index, &lock, COMMIT_LOCK))
die(_("Could not write new index file."));
}
@@ -516,7 +519,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
if (!pathspec.nr)
remove_branch_state(the_repository, 0);
- discard_index(&the_index);
+ discard_index(the_repository->index);
cleanup:
clear_pathspec(&pathspec);
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index 624182e507..1e2919fd81 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -3,7 +3,7 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "abspath.h"
#include "config.h"
@@ -160,8 +160,9 @@ static void show_rev(int type, const struct object_id *oid, const char *name)
case 1: /* happy */
if (abbrev_ref) {
char *old = full;
- full = shorten_unambiguous_ref(full,
- abbrev_ref_strict);
+ full = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+ full,
+ abbrev_ref_strict);
free(old);
}
show_with_type(type, full);
@@ -599,9 +600,12 @@ static int opt_with_value(const char *arg, const char *opt, const char **value)
static void handle_ref_opt(const char *pattern, const char *prefix)
{
if (pattern)
- for_each_glob_ref_in(show_reference, pattern, prefix, NULL);
+ refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
+ show_reference, pattern, prefix,
+ NULL);
else
- for_each_ref_in(prefix, show_reference, NULL);
+ refs_for_each_ref_in(get_main_ref_store(the_repository),
+ prefix, show_reference, NULL);
clear_ref_exclusions(&ref_excludes);
}
@@ -687,7 +691,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
const char *name = NULL;
struct object_context unused;
struct strbuf buf = STRBUF_INIT;
- const int hexsz = the_hash_algo->hexsz;
int seen_end_of_options = 0;
enum format_type format = FORMAT_DEFAULT;
@@ -863,8 +866,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
abbrev = strtoul(arg, NULL, 10);
if (abbrev < MINIMUM_ABBREV)
abbrev = MINIMUM_ABBREV;
- else if (hexsz <= abbrev)
- abbrev = hexsz;
+ else if ((int)the_hash_algo->hexsz <= abbrev)
+ abbrev = the_hash_algo->hexsz;
continue;
}
if (!strcmp(arg, "--sq")) {
@@ -898,7 +901,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
continue;
}
if (!strcmp(arg, "--all")) {
- for_each_ref(show_reference, NULL);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ show_reference, NULL);
clear_ref_exclusions(&ref_excludes);
continue;
}
@@ -908,8 +912,14 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
continue;
}
if (!strcmp(arg, "--bisect")) {
- for_each_fullref_in("refs/bisect/bad", show_reference, NULL);
- for_each_fullref_in("refs/bisect/good", anti_reference, NULL);
+ refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ "refs/bisect/bad",
+ NULL, show_reference,
+ NULL);
+ refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ "refs/bisect/good",
+ NULL, anti_reference,
+ NULL);
continue;
}
if (opt_with_value(arg, "--branches", &arg)) {
@@ -1049,8 +1059,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
if (!strcmp(arg, "--shared-index-path")) {
if (repo_read_index(the_repository) < 0)
die(_("Could not read the index"));
- if (the_index.split_index) {
- const struct object_id *oid = &the_index.split_index->base_oid;
+ if (the_repository->index->split_index) {
+ const struct object_id *oid = &the_repository->index->split_index->base_oid;
const char *path = git_path("sharedindex.%s", oid_to_hex(oid));
print_path(path, prefix, format, DEFAULT_RELATIVE);
}
diff --git a/builtin/rm.c b/builtin/rm.c
index fd130cea2d..d195c16e74 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -3,7 +3,7 @@
*
* Copyright (C) Linus Torvalds 2006
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "advice.h"
#include "config.h"
@@ -41,8 +41,8 @@ static int get_ours_cache_pos(const char *path, int pos)
{
int i = -pos - 1;
- while ((i < the_index.cache_nr) && !strcmp(the_index.cache[i]->name, path)) {
- if (ce_stage(the_index.cache[i]) == 2)
+ while ((i < the_repository->index->cache_nr) && !strcmp(the_repository->index->cache[i]->name, path)) {
+ if (ce_stage(the_repository->index->cache[i]) == 2)
return i;
i++;
}
@@ -78,13 +78,13 @@ static void submodules_absorb_gitdir_if_needed(void)
int pos;
const struct cache_entry *ce;
- pos = index_name_pos(&the_index, name, strlen(name));
+ pos = index_name_pos(the_repository->index, name, strlen(name));
if (pos < 0) {
pos = get_ours_cache_pos(name, pos);
if (pos < 0)
continue;
}
- ce = the_index.cache[pos];
+ ce = the_repository->index->cache[pos];
if (!S_ISGITLINK(ce->ce_mode) ||
!file_exists(ce->name) ||
@@ -122,7 +122,7 @@ static int check_local_mod(struct object_id *head, int index_only)
int local_changes = 0;
int staged_changes = 0;
- pos = index_name_pos(&the_index, name, strlen(name));
+ pos = index_name_pos(the_repository->index, name, strlen(name));
if (pos < 0) {
/*
* Skip unmerged entries except for populated submodules
@@ -132,11 +132,11 @@ static int check_local_mod(struct object_id *head, int index_only)
if (pos < 0)
continue;
- if (!S_ISGITLINK(the_index.cache[pos]->ce_mode) ||
+ if (!S_ISGITLINK(the_repository->index->cache[pos]->ce_mode) ||
is_empty_dir(name))
continue;
}
- ce = the_index.cache[pos];
+ ce = the_repository->index->cache[pos];
if (lstat(ce->name, &st) < 0) {
if (!is_missing_file_error(errno))
@@ -173,7 +173,7 @@ static int check_local_mod(struct object_id *head, int index_only)
* Is the index different from the file in the work tree?
* If it's a submodule, is its work tree modified?
*/
- if (ie_match_stat(&the_index, ce, &st, 0) ||
+ if (ie_match_stat(the_repository->index, ce, &st, 0) ||
(S_ISGITLINK(ce->ce_mode) &&
bad_to_remove_submodule(ce->name,
SUBMODULE_REMOVAL_DIE_ON_ERROR |
@@ -301,27 +301,27 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
if (repo_read_index(the_repository) < 0)
die(_("index file corrupt"));
- refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, &pathspec, NULL, NULL);
+ refresh_index(the_repository->index, REFRESH_QUIET|REFRESH_UNMERGED, &pathspec, NULL, NULL);
seen = xcalloc(pathspec.nr, 1);
- if (pathspec_needs_expanded_index(&the_index, &pathspec))
- ensure_full_index(&the_index);
+ if (pathspec_needs_expanded_index(the_repository->index, &pathspec))
+ ensure_full_index(the_repository->index);
- for (i = 0; i < the_index.cache_nr; i++) {
- const struct cache_entry *ce = the_index.cache[i];
+ for (i = 0; i < the_repository->index->cache_nr; i++) {
+ const struct cache_entry *ce = the_repository->index->cache[i];
if (!include_sparse &&
(ce_skip_worktree(ce) ||
- !path_in_sparse_checkout(ce->name, &the_index)))
+ !path_in_sparse_checkout(ce->name, the_repository->index)))
continue;
- if (!ce_path_match(&the_index, ce, &pathspec, seen))
+ if (!ce_path_match(the_repository->index, ce, &pathspec, seen))
continue;
ALLOC_GROW(list.entry, list.nr + 1, list.alloc);
list.entry[list.nr].name = xstrdup(ce->name);
list.entry[list.nr].is_submodule = S_ISGITLINK(ce->ce_mode);
if (list.entry[list.nr++].is_submodule &&
- !is_staging_gitmodules_ok(&the_index))
+ !is_staging_gitmodules_ok(the_repository->index))
die(_("please stage your changes to .gitmodules or stash them to proceed"));
}
@@ -391,7 +391,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
if (!quiet)
printf("rm '%s'\n", path);
- if (remove_file_from_index(&the_index, path))
+ if (remove_file_from_index(the_repository->index, path))
die(_("git rm: unable to remove %s"), path);
}
@@ -432,10 +432,10 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
}
strbuf_release(&buf);
if (gitmodules_modified)
- stage_updated_gitmodules(&the_index);
+ stage_updated_gitmodules(the_repository->index);
}
- if (write_locked_index(&the_index, &lock_file,
+ if (write_locked_index(the_repository->index, &lock_file,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
die(_("Unable to write new index file"));
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 3c7cd2d6ef..d4daf31e22 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -435,7 +435,7 @@ parse_done:
usage_with_options(shortlog_usage, options);
}
- if (setup_revisions(argc, argv, &rev, NULL) != 1) {
+ if (!nongit && setup_revisions(argc, argv, &rev, NULL) != 1) {
error(_("unrecognized argument: %s"), argv[1]);
usage_with_options(shortlog_usage, options);
}
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index b01ec761d2..d72f4cb98d 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -479,13 +479,15 @@ static void snarf_refs(int head, int remotes)
if (head) {
int orig_cnt = ref_name_cnt;
- for_each_ref(append_head_ref, NULL);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ append_head_ref, NULL);
sort_ref_range(orig_cnt, ref_name_cnt);
}
if (remotes) {
int orig_cnt = ref_name_cnt;
- for_each_ref(append_remote_ref, NULL);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ append_remote_ref, NULL);
sort_ref_range(orig_cnt, ref_name_cnt);
}
}
@@ -549,7 +551,8 @@ static void append_one_rev(const char *av)
match_ref_pattern = av;
match_ref_slash = count_slashes(av);
- for_each_ref(append_matching_ref, NULL);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ append_matching_ref, NULL);
if (saved_matches == ref_name_cnt &&
ref_name_cnt < MAX_REVS)
error(_("no matching refs with %s"), av);
@@ -740,9 +743,11 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
if (ac == 0) {
static const char *fake_av[2];
- fake_av[0] = resolve_refdup("HEAD",
- RESOLVE_REF_READING, &oid,
- NULL);
+ fake_av[0] = refs_resolve_refdup(get_main_ref_store(the_repository),
+ "HEAD",
+ RESOLVE_REF_READING,
+ &oid,
+ NULL);
fake_av[1] = NULL;
av = fake_av;
ac = 1;
@@ -815,8 +820,9 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
snarf_refs(all_heads, all_remotes);
}
- head = resolve_refdup("HEAD", RESOLVE_REF_READING,
- &head_oid, NULL);
+ head = refs_resolve_refdup(get_main_ref_store(the_repository), "HEAD",
+ RESOLVE_REF_READING,
+ &head_oid, NULL);
if (with_current_branch && head) {
int has_head = 0;
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 1c15421e60..151ef35134 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -129,7 +129,8 @@ static int cmd_show_ref__exclude_existing(const struct exclude_existing_options
char buf[1024];
int patternlen = opts->pattern ? strlen(opts->pattern) : 0;
- for_each_ref(add_existing, &existing_refs);
+ refs_for_each_ref(get_main_ref_store(the_repository), add_existing,
+ &existing_refs);
while (fgets(buf, sizeof(buf), stdin)) {
char *ref;
int len = strlen(buf);
@@ -173,7 +174,7 @@ static int cmd_show_ref__verify(const struct show_one_options *show_one_opts,
struct object_id oid;
if ((starts_with(*refs, "refs/") || refname_is_safe(*refs)) &&
- !read_ref(*refs, &oid)) {
+ !refs_read_ref(get_main_ref_store(the_repository), *refs, &oid)) {
show_one(show_one_opts, *refs, &oid);
}
else if (!show_one_opts->quiet)
@@ -205,14 +206,20 @@ static int cmd_show_ref__patterns(const struct patterns_options *opts,
show_ref_data.patterns = patterns;
if (opts->show_head)
- head_ref(show_ref, &show_ref_data);
+ refs_head_ref(get_main_ref_store(the_repository), show_ref,
+ &show_ref_data);
if (opts->heads_only || opts->tags_only) {
if (opts->heads_only)
- for_each_fullref_in("refs/heads/", show_ref, &show_ref_data);
+ refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ "refs/heads/", NULL,
+ show_ref, &show_ref_data);
if (opts->tags_only)
- for_each_fullref_in("refs/tags/", show_ref, &show_ref_data);
+ refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ "refs/tags/", NULL, show_ref,
+ &show_ref_data);
} else {
- for_each_ref(show_ref, &show_ref_data);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ show_ref, &show_ref_data);
}
if (!show_ref_data.found_match)
return 1;
diff --git a/builtin/stash.c b/builtin/stash.c
index 062be1fbc0..7859bc0866 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "config.h"
@@ -196,7 +195,7 @@ static int get_stash_info(struct stash_info *info, int argc, const char **argv)
commit = argv[0];
if (!commit) {
- if (!ref_exists(ref_stash)) {
+ if (!refs_ref_exists(get_main_ref_store(the_repository), ref_stash)) {
fprintf_ln(stderr, _("No stash entries found."));
return -1;
}
@@ -244,7 +243,8 @@ static int do_clear_stash(void)
if (repo_get_oid(the_repository, ref_stash, &obj))
return 0;
- return delete_ref(NULL, ref_stash, &obj, 0);
+ return refs_delete_ref(get_main_ref_store(the_repository), NULL,
+ ref_stash, &obj, 0);
}
static int clear_stash(int argc, const char **argv, const char *prefix)
@@ -273,7 +273,7 @@ static int reset_tree(struct object_id *i_tree, int update, int reset)
struct lock_file lock_file = LOCK_INIT;
repo_read_index_preload(the_repository, NULL, 0);
- if (refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL))
+ if (refresh_index(the_repository->index, REFRESH_QUIET, NULL, NULL, NULL))
return -1;
repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
@@ -287,8 +287,8 @@ static int reset_tree(struct object_id *i_tree, int update, int reset)
init_tree_desc(t, &tree->object.oid, tree->buffer, tree->size);
opts.head_idx = 1;
- opts.src_index = &the_index;
- opts.dst_index = &the_index;
+ opts.src_index = the_repository->index;
+ opts.dst_index = the_repository->index;
opts.merge = 1;
opts.reset = reset ? UNPACK_RESET_PROTECT_UNTRACKED : 0;
opts.update = update;
@@ -299,7 +299,7 @@ static int reset_tree(struct object_id *i_tree, int update, int reset)
if (unpack_trees(nr_trees, t, &opts))
return -1;
- if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
+ if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
return error(_("unable to write new index file"));
return 0;
@@ -430,7 +430,7 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
state.force = 1;
state.quiet = 1;
state.refresh_cache = 1;
- state.istate = &the_index;
+ state.istate = the_repository->index;
/*
* Step 1: get a difference between orig_tree (which corresponding
@@ -454,7 +454,7 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
/* Look up the path's position in the current index. */
p = diff_queued_diff.queue[i];
- pos = index_name_pos(&the_index, p->two->path,
+ pos = index_name_pos(the_repository->index, p->two->path,
strlen(p->two->path));
/*
@@ -465,10 +465,10 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
* path, but left it out of the working tree, then clear the
* SKIP_WORKTREE bit and write it to the working tree.
*/
- if (pos >= 0 && ce_skip_worktree(the_index.cache[pos])) {
+ if (pos >= 0 && ce_skip_worktree(the_repository->index->cache[pos])) {
struct stat st;
- ce = the_index.cache[pos];
+ ce = the_repository->index->cache[pos];
if (!lstat(ce->name, &st)) {
/* Conflicting path present; relocate it */
struct strbuf new_path = STRBUF_INIT;
@@ -504,12 +504,12 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
if (pos < 0)
option = ADD_CACHE_OK_TO_ADD;
- ce = make_cache_entry(&the_index,
+ ce = make_cache_entry(the_repository->index,
p->one->mode,
&p->one->oid,
p->one->path,
0, 0);
- add_index_entry(&the_index, ce, option);
+ add_index_entry(the_repository->index, ce, option);
}
}
diff_flush(&diff_opts);
@@ -518,7 +518,7 @@ static void unstage_changes_unless_new(struct object_id *orig_tree)
* Step 4: write the new index to disk
*/
repo_hold_locked_index(the_repository, &lock, LOCK_DIE_ON_ERROR);
- if (write_locked_index(&the_index, &lock,
+ if (write_locked_index(the_repository->index, &lock,
COMMIT_LOCK | SKIP_IF_UNCHANGED))
die(_("could not write index"));
}
@@ -539,7 +539,7 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
NULL, NULL, NULL))
return error(_("could not write index"));
- if (write_index_as_tree(&c_tree, &the_index, get_index_file(), 0,
+ if (write_index_as_tree(&c_tree, the_repository->index, get_index_file(), 0,
NULL))
return error(_("cannot apply a stash in the middle of a merge"));
@@ -562,14 +562,14 @@ static int do_apply_stash(const char *prefix, struct stash_info *info,
return error(_("conflicts in index. "
"Try without --index."));
- discard_index(&the_index);
+ discard_index(the_repository->index);
repo_read_index(the_repository);
- if (write_index_as_tree(&index_tree, &the_index,
+ if (write_index_as_tree(&index_tree, the_repository->index,
get_index_file(), 0, NULL))
return error(_("could not save index tree"));
reset_head();
- discard_index(&the_index);
+ discard_index(the_repository->index);
repo_read_index(the_repository);
}
}
@@ -687,7 +687,8 @@ static int reject_reflog_ent(struct object_id *ooid UNUSED,
static int reflog_is_empty(const char *refname)
{
- return !for_each_reflog_ent(refname, reject_reflog_ent, NULL);
+ return !refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+ refname, reject_reflog_ent, NULL);
}
static int do_drop_stash(struct stash_info *info, int quiet)
@@ -824,7 +825,7 @@ static int list_stash(int argc, const char **argv, const char *prefix)
git_stash_list_usage,
PARSE_OPT_KEEP_UNKNOWN_OPT);
- if (!ref_exists(ref_stash))
+ if (!refs_ref_exists(get_main_ref_store(the_repository), ref_stash))
return 0;
cp.git_cmd = 1;
@@ -875,8 +876,8 @@ static void diff_include_untracked(const struct stash_info *info, struct diff_op
}
unpack_tree_opt.head_idx = -1;
- unpack_tree_opt.src_index = &the_index;
- unpack_tree_opt.dst_index = &the_index;
+ unpack_tree_opt.src_index = the_repository->index;
+ unpack_tree_opt.dst_index = the_repository->index;
unpack_tree_opt.merge = 1;
unpack_tree_opt.fn = stash_worktree_untracked_merge;
@@ -998,10 +999,10 @@ static int do_store_stash(const struct object_id *w_commit, const char *stash_ms
if (!stash_msg)
stash_msg = "Created via \"git stash store\".";
- if (update_ref(stash_msg, ref_stash, w_commit, NULL,
- REF_FORCE_CREATE_REFLOG,
- quiet ? UPDATE_REFS_QUIET_ON_ERR :
- UPDATE_REFS_MSG_ON_ERR)) {
+ if (refs_update_ref(get_main_ref_store(the_repository), stash_msg, ref_stash, w_commit, NULL,
+ REF_FORCE_CREATE_REFLOG,
+ quiet ? UPDATE_REFS_QUIET_ON_ERR :
+ UPDATE_REFS_MSG_ON_ERR)) {
if (!quiet) {
fprintf_ln(stderr, _("Cannot update %s with %s"),
ref_stash, oid_to_hex(w_commit));
@@ -1205,8 +1206,8 @@ static int stash_staged(struct stash_info *info, struct strbuf *out_patch,
}
cp_diff_tree.git_cmd = 1;
- strvec_pushl(&cp_diff_tree.args, "diff-tree", "-p", "-U1", "HEAD",
- oid_to_hex(&info->w_tree), "--", NULL);
+ strvec_pushl(&cp_diff_tree.args, "diff-tree", "-p", "--binary",
+ "-U1", "HEAD", oid_to_hex(&info->w_tree), "--", NULL);
if (pipe_command(&cp_diff_tree, NULL, 0, out_patch, 0, NULL, 0)) {
ret = -1;
goto done;
@@ -1384,7 +1385,8 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
goto done;
}
- branch_ref = resolve_ref_unsafe("HEAD", 0, NULL, &flags);
+ branch_ref = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ "HEAD", 0, NULL, &flags);
if (flags & REF_ISSYMREF)
skip_prefix(branch_ref, "refs/heads/", &branch_name);
head_short_sha1 = repo_find_unique_abbrev(the_repository,
@@ -1395,7 +1397,7 @@ static int do_create_stash(const struct pathspec *ps, struct strbuf *stash_msg_b
strbuf_addf(&commit_tree_label, "index on %s\n", msg.buf);
commit_list_insert(head_commit, &parents);
- if (write_index_as_tree(&info->i_tree, &the_index, get_index_file(), 0,
+ if (write_index_as_tree(&info->i_tree, the_repository->index, get_index_file(), 0,
NULL) ||
commit_tree(commit_tree_label.buf, commit_tree_label.len,
&info->i_tree, parents, &info->i_commit, NULL, NULL)) {
@@ -1540,9 +1542,9 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
char *ps_matched = xcalloc(ps->nr, 1);
/* TODO: audit for interaction with sparse-index. */
- ensure_full_index(&the_index);
- for (i = 0; i < the_index.cache_nr; i++)
- ce_path_match(&the_index, the_index.cache[i], ps,
+ ensure_full_index(the_repository->index);
+ for (i = 0; i < the_repository->index->cache_nr; i++)
+ ce_path_match(the_repository->index, the_repository->index->cache[i], ps,
ps_matched);
if (report_path_error(ps_matched, ps)) {
@@ -1566,7 +1568,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
goto done;
}
- if (!reflog_exists(ref_stash) && do_clear_stash()) {
+ if (!refs_reflog_exists(get_main_ref_store(the_repository), ref_stash) && do_clear_stash()) {
ret = -1;
if (!quiet)
fprintf_ln(stderr, _("Cannot initialize stash"));
@@ -1612,7 +1614,7 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
goto done;
}
}
- discard_index(&the_index);
+ discard_index(the_repository->index);
if (ps->nr) {
struct child_process cp_add = CHILD_PROCESS_INIT;
struct child_process cp_diff = CHILD_PROCESS_INIT;
diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c
index e4e18adb57..e604cb5ddb 100644
--- a/builtin/submodule--helper.c
+++ b/builtin/submodule--helper.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "builtin.h"
#include "abspath.h"
#include "environment.h"
@@ -207,18 +206,18 @@ static int module_list_compute(const char **argv,
if (repo_read_index(the_repository) < 0)
die(_("index file corrupt"));
- for (i = 0; i < the_index.cache_nr; i++) {
- const struct cache_entry *ce = the_index.cache[i];
+ for (i = 0; i < the_repository->index->cache_nr; i++) {
+ const struct cache_entry *ce = the_repository->index->cache[i];
- if (!match_pathspec(&the_index, pathspec, ce->name, ce_namelen(ce),
+ if (!match_pathspec(the_repository->index, pathspec, ce->name, ce_namelen(ce),
0, ps_matched, 1) ||
!S_ISGITLINK(ce->ce_mode))
continue;
ALLOC_GROW(list->entries, list->nr + 1, list->alloc);
list->entries[list->nr++] = ce;
- while (i + 1 < the_index.cache_nr &&
- !strcmp(ce->name, the_index.cache[i + 1]->name))
+ while (i + 1 < the_repository->index->cache_nr &&
+ !strcmp(ce->name, the_repository->index->cache[i + 1]->name))
/*
* Skip entries with the same name in different stages
* to make sure an entry is returned only once.
@@ -303,6 +302,9 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
struct child_process cp = CHILD_PROCESS_INIT;
char *displaypath;
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
displaypath = get_submodule_displaypath(path, info->prefix,
info->super_prefix);
@@ -634,6 +636,9 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
.free_removed_argv_elements = 1,
};
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
if (!submodule_from_path(the_repository, null_oid(), path))
die(_("no submodule mapping found in .gitmodules for path '%s'"),
path);
@@ -907,7 +912,7 @@ static void generate_submodule_summary(struct summary_cb *info,
int fd = open(p->sm_path, O_RDONLY);
if (fd < 0 || fstat(fd, &st) < 0 ||
- index_fd(&the_index, &p->oid_dst, fd, &st, OBJ_BLOB,
+ index_fd(the_repository->index, &p->oid_dst, fd, &st, OBJ_BLOB,
p->sm_path, 0))
error(_("couldn't hash object from '%s'"), p->sm_path);
} else {
@@ -1238,6 +1243,9 @@ static void sync_submodule(const char *path, const char *prefix,
if (!is_submodule_active(the_repository, path))
return;
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
sub = submodule_from_path(the_repository, null_oid(), path);
if (sub && sub->url) {
@@ -1381,6 +1389,9 @@ static void deinit_submodule(const char *path, const char *prefix,
struct strbuf sb_config = STRBUF_INIT;
char *sub_git_dir = xstrfmt("%s/.git", path);
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
sub = submodule_from_path(the_repository, null_oid(), path);
if (!sub || !sub->name)
@@ -1662,16 +1673,42 @@ static char *clone_submodule_sm_gitdir(const char *name)
return sm_gitdir;
}
+static int dir_contains_only_dotgit(const char *path)
+{
+ DIR *dir = opendir(path);
+ struct dirent *e;
+ int ret = 1;
+
+ if (!dir)
+ return 0;
+
+ e = readdir_skip_dot_and_dotdot(dir);
+ if (!e)
+ ret = 0;
+ else if (strcmp(DEFAULT_GIT_DIR_ENVIRONMENT, e->d_name) ||
+ (e = readdir_skip_dot_and_dotdot(dir))) {
+ error("unexpected item '%s' in '%s'", e->d_name, path);
+ ret = 0;
+ }
+
+ closedir(dir);
+ return ret;
+}
+
static int clone_submodule(const struct module_clone_data *clone_data,
struct string_list *reference)
{
char *p;
char *sm_gitdir = clone_submodule_sm_gitdir(clone_data->name);
char *sm_alternate = NULL, *error_strategy = NULL;
+ struct stat st;
struct child_process cp = CHILD_PROCESS_INIT;
const char *clone_data_path = clone_data->path;
char *to_free = NULL;
+ if (validate_submodule_path(clone_data_path) < 0)
+ exit(128);
+
if (!is_absolute_path(clone_data->path))
clone_data_path = to_free = xstrfmt("%s/%s", get_git_work_tree(),
clone_data->path);
@@ -1681,6 +1718,10 @@ static int clone_submodule(const struct module_clone_data *clone_data,
"git dir"), sm_gitdir);
if (!file_exists(sm_gitdir)) {
+ if (clone_data->require_init && !stat(clone_data_path, &st) &&
+ !is_empty_dir(clone_data_path))
+ die(_("directory not empty: '%s'"), clone_data_path);
+
if (safe_create_leading_directories_const(sm_gitdir) < 0)
die(_("could not create directory '%s'"), sm_gitdir);
@@ -1725,10 +1766,18 @@ static int clone_submodule(const struct module_clone_data *clone_data,
if(run_command(&cp))
die(_("clone of '%s' into submodule path '%s' failed"),
clone_data->url, clone_data_path);
+
+ if (clone_data->require_init && !stat(clone_data_path, &st) &&
+ !dir_contains_only_dotgit(clone_data_path)) {
+ char *dot_git = xstrfmt("%s/.git", clone_data_path);
+ unlink(dot_git);
+ free(dot_git);
+ die(_("directory not empty: '%s'"), clone_data_path);
+ }
} else {
char *path;
- if (clone_data->require_init && !access(clone_data_path, X_OK) &&
+ if (clone_data->require_init && !stat(clone_data_path, &st) &&
!is_empty_dir(clone_data_path))
die(_("directory not empty: '%s'"), clone_data_path);
if (safe_create_leading_directories_const(clone_data_path) < 0)
@@ -1738,6 +1787,23 @@ static int clone_submodule(const struct module_clone_data *clone_data,
free(path);
}
+ /*
+ * We already performed this check at the beginning of this function,
+ * before cloning the objects. This tries to detect racy behavior e.g.
+ * in parallel clones, where another process could easily have made the
+ * gitdir nested _after_ it was created.
+ *
+ * To prevent further harm coming from this unintentionally-nested
+ * gitdir, let's disable it by deleting the `HEAD` file.
+ */
+ if (validate_submodule_git_dir(sm_gitdir, clone_data->name) < 0) {
+ char *head = xstrfmt("%s/HEAD", sm_gitdir);
+ unlink(head);
+ free(head);
+ die(_("refusing to create/use '%s' in another submodule's "
+ "git dir"), sm_gitdir);
+ }
+
connect_work_tree_and_git_dir(clone_data_path, sm_gitdir, 0);
p = git_pathdup_submodule(clone_data_path, "config");
@@ -2390,7 +2456,9 @@ static int remote_submodule_branch(const char *path, const char **branch)
}
if (!strcmp(*branch, ".")) {
- const char *refname = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
+ const char *refname = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ "HEAD", 0, NULL,
+ NULL);
if (!refname)
return die_message(_("No such ref: %s"), "HEAD");
@@ -2517,6 +2585,9 @@ static int update_submodule(struct update_data *update_data)
{
int ret;
+ if (validate_submodule_path(update_data->sm_path) < 0)
+ return -1;
+
ret = determine_submodule_update_strategy(the_repository,
update_data->just_cloned,
update_data->sm_path,
@@ -2624,12 +2695,21 @@ static int update_submodules(struct update_data *update_data)
for (i = 0; i < suc.update_clone_nr; i++) {
struct update_clone_data ucd = suc.update_clone[i];
- int code;
+ int code = 128;
oidcpy(&update_data->oid, &ucd.oid);
update_data->just_cloned = ucd.just_cloned;
update_data->sm_path = ucd.sub->path;
+ /*
+ * Verify that the submodule path does not contain any
+ * symlinks; if it does, it might have been tampered with.
+ * TODO: allow exempting it via
+ * `safe.submodule.path` or something
+ */
+ if (validate_submodule_path(update_data->sm_path) < 0)
+ goto fail;
+
code = ensure_core_worktree(update_data->sm_path);
if (code)
goto fail;
@@ -2796,7 +2876,8 @@ static int push_check(int argc, const char **argv, const char *prefix UNUSED)
argv++;
argc--;
/* Get the submodule's head ref and determine if it is detached */
- head = resolve_refdup("HEAD", 0, &head_oid, NULL);
+ head = refs_resolve_refdup(get_main_ref_store(the_repository), "HEAD",
+ 0, &head_oid, NULL);
if (!head)
die(_("Failed to resolve HEAD as a valid ref."));
if (!strcmp(head, "HEAD"))
@@ -3243,21 +3324,21 @@ static void die_on_index_match(const char *path, int force)
char *ps_matched = xcalloc(ps.nr, 1);
/* TODO: audit for interaction with sparse-index. */
- ensure_full_index(&the_index);
+ ensure_full_index(the_repository->index);
/*
* Since there is only one pathspec, we just need to
* check ps_matched[0] to know if a cache entry matched.
*/
- for (i = 0; i < the_index.cache_nr; i++) {
- ce_path_match(&the_index, the_index.cache[i], &ps,
+ for (i = 0; i < the_repository->index->cache_nr; i++) {
+ ce_path_match(the_repository->index, the_repository->index->cache[i], &ps,
ps_matched);
if (ps_matched[0]) {
if (!force)
die(_("'%s' already exists in the index"),
path);
- if (!S_ISGITLINK(the_index.cache[i]->ce_mode))
+ if (!S_ISGITLINK(the_repository->index->cache[i]->ce_mode))
die(_("'%s' already exists in the index "
"and is not a submodule"), path);
break;
@@ -3356,6 +3437,9 @@ static int module_add(int argc, const char **argv, const char *prefix)
normalize_path_copy(add_data.sm_path, add_data.sm_path);
strip_dir_trailing_slashes(add_data.sm_path);
+ if (validate_submodule_path(add_data.sm_path) < 0)
+ exit(128);
+
die_on_index_match(add_data.sm_path, force);
die_on_repo_without_commits(add_data.sm_path);
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index c9defe4d2e..81abdd170f 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -18,7 +18,8 @@ static int check_symref(const char *HEAD, int quiet, int shorten, int recurse, i
const char *refname;
resolve_flags = (recurse ? 0 : RESOLVE_REF_NO_RECURSE);
- refname = resolve_ref_unsafe(HEAD, resolve_flags, NULL, &flag);
+ refname = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ HEAD, resolve_flags, NULL, &flag);
if (!refname)
die("No such ref: %s", HEAD);
@@ -31,7 +32,9 @@ static int check_symref(const char *HEAD, int quiet, int shorten, int recurse, i
if (print) {
char *to_free = NULL;
if (shorten)
- refname = to_free = shorten_unambiguous_ref(refname, 0);
+ refname = to_free = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+ refname,
+ 0);
puts(refname);
free(to_free);
}
@@ -66,7 +69,8 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
die("Cannot delete %s, not a symbolic ref", argv[0]);
if (!strcmp(argv[0], "HEAD"))
die("deleting '%s' is not allowed", argv[0]);
- return delete_ref(NULL, argv[0], NULL, REF_NO_DEREF);
+ return refs_delete_ref(get_main_ref_store(the_repository),
+ NULL, argv[0], NULL, REF_NO_DEREF);
}
switch (argc) {
@@ -79,7 +83,8 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
die("Refusing to point HEAD outside of refs/");
if (check_refname_format(argv[1], REFNAME_ALLOW_ONELEVEL) < 0)
die("Refusing to set '%s' to invalid ref '%s'", argv[0], argv[1]);
- ret = !!create_symref(argv[0], argv[1], msg);
+ ret = !!refs_update_symref(get_main_ref_store(the_repository),
+ argv[0], argv[1], msg);
break;
default:
usage_with_options(git_symbolic_ref_usage, options);
diff --git a/builtin/tag.c b/builtin/tag.c
index 9a33cb50b4..6e2c0cf342 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -28,9 +28,11 @@
#include "date.h"
#include "write-or-die.h"
#include "object-file-convert.h"
+#include "trailer.h"
static const char * const git_tag_usage[] = {
N_("git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n"
+ " [(--trailer <token>[(=|:)<value>])...]\n"
" <tagname> [<commit> | <object>]"),
N_("git tag -d <tagname>..."),
N_("git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]\n"
@@ -87,7 +89,7 @@ static int for_each_tag_name(const char **argv, each_tag_name_fn fn,
for (p = argv; *p; p++) {
strbuf_reset(&ref);
strbuf_addf(&ref, "refs/tags/%s", *p);
- if (read_ref(ref.buf, &oid)) {
+ if (refs_read_ref(get_main_ref_store(the_repository), ref.buf, &oid)) {
error(_("tag '%s' not found."), *p);
had_error = 1;
continue;
@@ -116,13 +118,13 @@ static int delete_tags(const char **argv)
struct string_list_item *item;
result = for_each_tag_name(argv, collect_tags, (void *)&refs_to_delete);
- if (delete_refs(NULL, &refs_to_delete, REF_NO_DEREF))
+ if (refs_delete_refs(get_main_ref_store(the_repository), NULL, &refs_to_delete, REF_NO_DEREF))
result = 1;
for_each_string_list_item(item, &refs_to_delete) {
const char *name = item->string;
struct object_id *oid = item->util;
- if (!ref_exists(name))
+ if (!refs_ref_exists(get_main_ref_store(the_repository), name))
printf(_("Deleted tag '%s' (was %s)\n"),
item->string + 10,
repo_find_unique_abbrev(the_repository, oid, DEFAULT_ABBREV));
@@ -290,10 +292,12 @@ static const char message_advice_nested_tag[] =
static void create_tag(const struct object_id *object, const char *object_ref,
const char *tag,
struct strbuf *buf, struct create_tag_options *opt,
- struct object_id *prev, struct object_id *result, char *path)
+ struct object_id *prev, struct object_id *result,
+ struct strvec *trailer_args, char *path)
{
enum object_type type;
struct strbuf header = STRBUF_INIT;
+ int should_edit;
type = oid_object_info(the_repository, object, NULL);
if (type <= OBJ_NONE)
@@ -313,13 +317,15 @@ static void create_tag(const struct object_id *object, const char *object_ref,
tag,
git_committer_info(IDENT_STRICT));
- if (!opt->message_given || opt->use_editor) {
+ should_edit = opt->use_editor || !opt->message_given;
+ if (should_edit || trailer_args->nr) {
int fd;
/* write the template message before editing: */
fd = xopen(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
- if (opt->message_given) {
+ if (opt->message_given && buf->len) {
+ strbuf_complete(buf, '\n');
write_or_die(fd, buf->buf, buf->len);
strbuf_reset(buf);
} else if (!is_null_oid(prev)) {
@@ -338,10 +344,19 @@ static void create_tag(const struct object_id *object, const char *object_ref,
}
close(fd);
- if (launch_editor(path, buf, NULL)) {
- fprintf(stderr,
- _("Please supply the message using either -m or -F option.\n"));
- exit(1);
+ if (trailer_args->nr && amend_file_with_trailers(path, trailer_args))
+ die(_("unable to pass trailers to --trailers"));
+
+ if (should_edit) {
+ if (launch_editor(path, buf, NULL)) {
+ fprintf(stderr,
+ _("Please supply the message using either -m or -F option.\n"));
+ exit(1);
+ }
+ } else if (trailer_args->nr) {
+ strbuf_reset(buf);
+ if (strbuf_read_file(buf, path, 0) < 0)
+ die_errno(_("failed to read '%s'"), path);
}
}
@@ -463,6 +478,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
struct ref_sorting *sorting;
struct string_list sorting_options = STRING_LIST_INIT_DUP;
struct ref_format format = REF_FORMAT_INIT;
+ struct strvec trailer_args = STRVEC_INIT;
int icase = 0;
int edit_flag = 0;
struct option options[] = {
@@ -479,6 +495,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
OPT_CALLBACK_F('m', "message", &msg, N_("message"),
N_("tag message"), PARSE_OPT_NONEG, parse_msg_arg),
OPT_FILENAME('F', "file", &msgfile, N_("read message from file")),
+ OPT_PASSTHRU_ARGV(0, "trailer", &trailer_args, N_("trailer"),
+ N_("add custom trailer(s)"), PARSE_OPT_NONEG),
OPT_BOOL('e', "edit", &edit_flag, N_("force edit of tag message")),
OPT_BOOL('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
OPT_CLEANUP(&cleanup_arg),
@@ -548,7 +566,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
opt.sign = 1;
set_signing_key(keyid);
}
- create_tag_object = (opt.sign || annotate || msg.given || msgfile);
+ create_tag_object = (opt.sign || annotate || msg.given || msgfile ||
+ edit_flag || trailer_args.nr);
if ((create_tag_object || force) && (cmdmode != 0))
usage_with_options(git_tag_usage, options);
@@ -630,7 +649,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
if (strbuf_check_tag_ref(&ref, tag))
die(_("'%s' is not a valid tag name."), tag);
- if (read_ref(ref.buf, &prev))
+ if (refs_read_ref(get_main_ref_store(the_repository), ref.buf, &prev))
oidclr(&prev);
else if (!force)
die(_("tag '%s' already exists"), tag);
@@ -654,12 +673,14 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
opt.sign = 1;
path = git_pathdup("TAG_EDITMSG");
create_tag(&object, object_ref, tag, &buf, &opt, &prev, &object,
- path);
+ &trailer_args, path);
}
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction ||
ref_transaction_update(transaction, ref.buf, &object, &prev,
+ NULL, NULL,
create_reflog ? REF_FORCE_CREATE_REFLOG : 0,
reflog_msg.buf, &err) ||
ref_transaction_commit(transaction, &err)) {
@@ -686,6 +707,7 @@ cleanup:
strbuf_release(&reflog_msg);
strbuf_release(&msg.buf);
strbuf_release(&err);
+ strvec_clear(&trailer_args);
free(msgfile);
return ret;
}
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 7bcaa1476c..20aa1c4c68 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -3,7 +3,7 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "bulk-checkin.h"
#include "config.h"
@@ -247,16 +247,16 @@ done:
static int mark_ce_flags(const char *path, int flag, int mark)
{
int namelen = strlen(path);
- int pos = index_name_pos(&the_index, path, namelen);
+ int pos = index_name_pos(the_repository->index, path, namelen);
if (0 <= pos) {
- mark_fsmonitor_invalid(&the_index, the_index.cache[pos]);
+ mark_fsmonitor_invalid(the_repository->index, the_repository->index->cache[pos]);
if (mark)
- the_index.cache[pos]->ce_flags |= flag;
+ the_repository->index->cache[pos]->ce_flags |= flag;
else
- the_index.cache[pos]->ce_flags &= ~flag;
- the_index.cache[pos]->ce_flags |= CE_UPDATE_IN_BASE;
- cache_tree_invalidate_path(&the_index, path);
- the_index.cache_changed |= CE_ENTRY_CHANGED;
+ the_repository->index->cache[pos]->ce_flags &= ~flag;
+ the_repository->index->cache[pos]->ce_flags |= CE_UPDATE_IN_BASE;
+ cache_tree_invalidate_path(the_repository->index, path);
+ the_repository->index->cache_changed |= CE_ENTRY_CHANGED;
return 0;
}
return -1;
@@ -266,7 +266,7 @@ static int remove_one_path(const char *path)
{
if (!allow_remove)
return error("%s: does not exist and --remove not passed", path);
- if (remove_file_from_index(&the_index, path))
+ if (remove_file_from_index(the_repository->index, path))
return error("%s: cannot remove from the index", path);
return 0;
}
@@ -291,24 +291,24 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len
struct cache_entry *ce;
/* Was the old index entry already up-to-date? */
- if (old && !ce_stage(old) && !ie_match_stat(&the_index, old, st, 0))
+ if (old && !ce_stage(old) && !ie_match_stat(the_repository->index, old, st, 0))
return 0;
- ce = make_empty_cache_entry(&the_index, len);
+ ce = make_empty_cache_entry(the_repository->index, len);
memcpy(ce->name, path, len);
ce->ce_flags = create_ce_flags(0);
ce->ce_namelen = len;
- fill_stat_cache_info(&the_index, ce, st);
+ fill_stat_cache_info(the_repository->index, ce, st);
ce->ce_mode = ce_mode_from_stat(old, st->st_mode);
- if (index_path(&the_index, &ce->oid, path, st,
+ if (index_path(the_repository->index, &ce->oid, path, st,
info_only ? 0 : HASH_WRITE_OBJECT)) {
discard_cache_entry(ce);
return -1;
}
option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
- if (add_index_entry(&the_index, ce, option)) {
+ if (add_index_entry(the_repository->index, ce, option)) {
discard_cache_entry(ce);
return error("%s: cannot add to the index - missing --add option?", path);
}
@@ -341,11 +341,11 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len
static int process_directory(const char *path, int len, struct stat *st)
{
struct object_id oid;
- int pos = index_name_pos(&the_index, path, len);
+ int pos = index_name_pos(the_repository->index, path, len);
/* Exact match: file or existing gitlink */
if (pos >= 0) {
- const struct cache_entry *ce = the_index.cache[pos];
+ const struct cache_entry *ce = the_repository->index->cache[pos];
if (S_ISGITLINK(ce->ce_mode)) {
/* Do nothing to the index if there is no HEAD! */
@@ -360,8 +360,8 @@ static int process_directory(const char *path, int len, struct stat *st)
/* Inexact match: is there perhaps a subdirectory match? */
pos = -pos-1;
- while (pos < the_index.cache_nr) {
- const struct cache_entry *ce = the_index.cache[pos++];
+ while (pos < the_repository->index->cache_nr) {
+ const struct cache_entry *ce = the_repository->index->cache[pos++];
if (strncmp(ce->name, path, len))
break;
@@ -391,8 +391,8 @@ static int process_path(const char *path, struct stat *st, int stat_errno)
if (has_symlink_leading_path(path, len))
return error("'%s' is beyond a symbolic link", path);
- pos = index_name_pos(&the_index, path, len);
- ce = pos < 0 ? NULL : the_index.cache[pos];
+ pos = index_name_pos(the_repository->index, path, len);
+ ce = pos < 0 ? NULL : the_repository->index->cache[pos];
if (ce && ce_skip_worktree(ce)) {
/*
* working directory version is assumed "good"
@@ -400,7 +400,7 @@ static int process_path(const char *path, struct stat *st, int stat_errno)
* On the other hand, removing it from index should work
*/
if (!ignore_skip_worktree_entries && allow_remove &&
- remove_file_from_index(&the_index, path))
+ remove_file_from_index(the_repository->index, path))
return error("%s: cannot remove from the index", path);
return 0;
}
@@ -428,7 +428,7 @@ static int add_cacheinfo(unsigned int mode, const struct object_id *oid,
return error("Invalid path '%s'", path);
len = strlen(path);
- ce = make_empty_cache_entry(&the_index, len);
+ ce = make_empty_cache_entry(the_repository->index, len);
oidcpy(&ce->oid, oid);
memcpy(ce->name, path, len);
@@ -439,7 +439,7 @@ static int add_cacheinfo(unsigned int mode, const struct object_id *oid,
ce->ce_flags |= CE_VALID;
option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
- if (add_index_entry(&the_index, ce, option))
+ if (add_index_entry(the_repository->index, ce, option))
return error("%s: cannot add to the index - missing --add option?",
path);
report("add '%s'", path);
@@ -451,11 +451,11 @@ static void chmod_path(char flip, const char *path)
int pos;
struct cache_entry *ce;
- pos = index_name_pos(&the_index, path, strlen(path));
+ pos = index_name_pos(the_repository->index, path, strlen(path));
if (pos < 0)
goto fail;
- ce = the_index.cache[pos];
- if (chmod_index_entry(&the_index, ce, flip) < 0)
+ ce = the_repository->index->cache[pos];
+ if (chmod_index_entry(the_repository->index, ce, flip) < 0)
goto fail;
report("chmod %cx '%s'", flip, path);
@@ -498,7 +498,7 @@ static void update_one(const char *path)
}
if (force_remove) {
- if (remove_file_from_index(&the_index, path))
+ if (remove_file_from_index(the_repository->index, path))
die("git update-index: unable to remove %s", path);
report("remove '%s'", path);
return;
@@ -581,7 +581,7 @@ static void read_index_info(int nul_term_line)
if (!mode) {
/* mode == 0 means there is no such path -- remove */
- if (remove_file_from_index(&the_index, path_name))
+ if (remove_file_from_index(the_repository->index, path_name))
die("git update-index: unable to remove %s",
ptr);
}
@@ -622,12 +622,12 @@ static struct cache_entry *read_one_ent(const char *which,
error("%s: not in %s branch.", path, which);
return NULL;
}
- if (!the_index.sparse_index && mode == S_IFDIR) {
+ if (!the_repository->index->sparse_index && mode == S_IFDIR) {
if (which)
error("%s: not a blob in %s branch.", path, which);
return NULL;
}
- ce = make_empty_cache_entry(&the_index, namelen);
+ ce = make_empty_cache_entry(the_repository->index, namelen);
oidcpy(&ce->oid, &oid);
memcpy(ce->name, path, namelen);
@@ -642,12 +642,12 @@ static int unresolve_one(const char *path)
struct string_list_item *item;
int res = 0;
- if (!the_index.resolve_undo)
+ if (!the_repository->index->resolve_undo)
return res;
- item = string_list_lookup(the_index.resolve_undo, path);
+ item = string_list_lookup(the_repository->index->resolve_undo, path);
if (!item)
return res; /* no resolve-undo record for the path */
- res = unmerge_index_entry(&the_index, path, item->util, 0);
+ res = unmerge_index_entry(the_repository->index, path, item->util, 0);
FREE_AND_NULL(item->util);
return res;
}
@@ -682,19 +682,19 @@ static int do_reupdate(const char **paths,
PATHSPEC_PREFER_CWD,
prefix, paths);
- if (read_ref("HEAD", &head_oid))
+ if (refs_read_ref(get_main_ref_store(the_repository), "HEAD", &head_oid))
/* If there is no HEAD, that means it is an initial
* commit. Update everything in the index.
*/
has_head = 0;
redo:
- for (pos = 0; pos < the_index.cache_nr; pos++) {
- const struct cache_entry *ce = the_index.cache[pos];
+ for (pos = 0; pos < the_repository->index->cache_nr; pos++) {
+ const struct cache_entry *ce = the_repository->index->cache[pos];
struct cache_entry *old = NULL;
int save_nr;
char *path;
- if (ce_stage(ce) || !ce_path_match(&the_index, ce, &pathspec, NULL))
+ if (ce_stage(ce) || !ce_path_match(the_repository->index, ce, &pathspec, NULL))
continue;
if (has_head)
old = read_one_ent(NULL, &head_oid,
@@ -710,7 +710,7 @@ static int do_reupdate(const char **paths,
* to process each path individually
*/
if (S_ISSPARSEDIR(ce->ce_mode)) {
- ensure_full_index(&the_index);
+ ensure_full_index(the_repository->index);
goto redo;
}
@@ -718,12 +718,12 @@ static int do_reupdate(const char **paths,
* path anymore, in which case, under 'allow_remove',
* or worse yet 'allow_replace', active_nr may decrease.
*/
- save_nr = the_index.cache_nr;
+ save_nr = the_repository->index->cache_nr;
path = xstrdup(ce->name);
update_one(path);
free(path);
discard_cache_entry(old);
- if (save_nr != the_index.cache_nr)
+ if (save_nr != the_repository->index->cache_nr)
goto redo;
}
clear_pathspec(&pathspec);
@@ -739,9 +739,9 @@ static int refresh(struct refresh_params *o, unsigned int flag)
{
setup_work_tree();
repo_read_index(the_repository);
- *o->has_errors |= refresh_index(&the_index, o->flags | flag, NULL,
+ *o->has_errors |= refresh_index(the_repository->index, o->flags | flag, NULL,
NULL, NULL);
- if (has_racy_timestamp(&the_index)) {
+ if (has_racy_timestamp(the_repository->index)) {
/*
* Even if nothing else has changed, updating the file
* increases the chance that racy timestamps become
@@ -750,7 +750,7 @@ static int refresh(struct refresh_params *o, unsigned int flag)
* refresh_index() as these are no actual errors.
* cmd_status() does the same.
*/
- the_index.cache_changed |= SOMETHING_CHANGED;
+ the_repository->index->cache_changed |= SOMETHING_CHANGED;
}
return 0;
}
@@ -787,7 +787,7 @@ static int resolve_undo_clear_callback(const struct option *opt UNUSED,
{
BUG_ON_OPT_NEG(unset);
BUG_ON_OPT_ARG(arg);
- resolve_undo_clear_index(&the_index);
+ resolve_undo_clear_index(the_repository->index);
return 0;
}
@@ -888,7 +888,7 @@ static enum parse_opt_result unresolve_callback(
*has_errors = do_unresolve(ctx->argc, ctx->argv,
prefix, prefix ? strlen(prefix) : 0);
if (*has_errors)
- the_index.cache_changed = 0;
+ the_repository->index->cache_changed = 0;
ctx->argv += ctx->argc - 1;
ctx->argc = 1;
@@ -909,7 +909,7 @@ static enum parse_opt_result reupdate_callback(
setup_work_tree();
*has_errors = do_reupdate(ctx->argv + 1, prefix);
if (*has_errors)
- the_index.cache_changed = 0;
+ the_repository->index->cache_changed = 0;
ctx->argv += ctx->argc - 1;
ctx->argc = 1;
@@ -1056,7 +1056,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
if (entries < 0)
die("cache corrupted");
- the_index.updated_skipworktree = 1;
+ the_repository->index->updated_skipworktree = 1;
/*
* Custom copy of parse_options() because we want to handle
@@ -1111,18 +1111,18 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
if (preferred_index_format) {
if (preferred_index_format < 0) {
- printf(_("%d\n"), the_index.version);
+ printf(_("%d\n"), the_repository->index->version);
} else if (preferred_index_format < INDEX_FORMAT_LB ||
INDEX_FORMAT_UB < preferred_index_format) {
die("index-version %d not in range: %d..%d",
preferred_index_format,
INDEX_FORMAT_LB, INDEX_FORMAT_UB);
} else {
- if (the_index.version != preferred_index_format)
- the_index.cache_changed |= SOMETHING_CHANGED;
+ if (the_repository->index->version != preferred_index_format)
+ the_repository->index->cache_changed |= SOMETHING_CHANGED;
report(_("index-version: was %d, set to %d"),
- the_index.version, preferred_index_format);
- the_index.version = preferred_index_format;
+ the_repository->index->version, preferred_index_format);
+ the_repository->index->version = preferred_index_format;
}
}
@@ -1159,16 +1159,16 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
warning(_("core.splitIndex is set to false; "
"remove or change it, if you really want to "
"enable split index"));
- if (the_index.split_index)
- the_index.cache_changed |= SPLIT_INDEX_ORDERED;
+ if (the_repository->index->split_index)
+ the_repository->index->cache_changed |= SPLIT_INDEX_ORDERED;
else
- add_split_index(&the_index);
+ add_split_index(the_repository->index);
} else if (!split_index) {
if (git_config_get_split_index() == 1)
warning(_("core.splitIndex is set to true; "
"remove or change it, if you really want to "
"disable split index"));
- remove_split_index(&the_index);
+ remove_split_index(the_repository->index);
}
prepare_repo_settings(r);
@@ -1180,7 +1180,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
warning(_("core.untrackedCache is set to true; "
"remove or change it, if you really want to "
"disable the untracked cache"));
- remove_untracked_cache(&the_index);
+ remove_untracked_cache(the_repository->index);
report(_("Untracked cache disabled"));
break;
case UC_TEST:
@@ -1192,7 +1192,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
warning(_("core.untrackedCache is set to false; "
"remove or change it, if you really want to "
"enable the untracked cache"));
- add_untracked_cache(&the_index);
+ add_untracked_cache(the_repository->index);
report(_("Untracked cache enabled for '%s'"), get_git_work_tree());
break;
default:
@@ -1222,7 +1222,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
"set it if you really want to "
"enable fsmonitor"));
}
- add_fsmonitor(&the_index);
+ add_fsmonitor(the_repository->index);
report(_("fsmonitor enabled"));
} else if (!fsmonitor) {
enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r);
@@ -1230,17 +1230,17 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
warning(_("core.fsmonitor is set; "
"remove it if you really want to "
"disable fsmonitor"));
- remove_fsmonitor(&the_index);
+ remove_fsmonitor(the_repository->index);
report(_("fsmonitor disabled"));
}
- if (the_index.cache_changed || force_write) {
+ if (the_repository->index->cache_changed || force_write) {
if (newfd < 0) {
if (refresh_args.flags & REFRESH_QUIET)
exit(128);
unable_to_lock_die(get_index_file(), lock_error);
}
- if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK))
+ if (write_locked_index(the_repository->index, &lock_file, COMMIT_LOCK))
die("Unable to write new index file");
}
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index e46afbc46d..6cda1c08aa 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -204,6 +204,7 @@ static void parse_cmd_update(struct ref_transaction *transaction,
if (ref_transaction_update(transaction, refname,
&new_oid, have_old ? &old_oid : NULL,
+ NULL, NULL,
update_flags | create_reflog_flag,
msg, &err))
die("%s", err.buf);
@@ -397,7 +398,8 @@ static void update_refs_stdin(void)
struct ref_transaction *transaction;
int i, j;
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction)
die("%s", err.buf);
@@ -464,7 +466,8 @@ static void update_refs_stdin(void)
* get a "start".
*/
state = cmd->state;
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction)
die("%s", err.buf);
@@ -571,11 +574,14 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
* For purposes of backwards compatibility, we treat
* NULL_SHA1 as "don't care" here:
*/
- return delete_ref(msg, refname,
- (oldval && !is_null_oid(&oldoid)) ? &oldoid : NULL,
- default_flags);
+ return refs_delete_ref(get_main_ref_store(the_repository),
+ msg, refname,
+ (oldval && !is_null_oid(&oldoid)) ? &oldoid : NULL,
+ default_flags);
else
- return update_ref(msg, refname, &oid, oldval ? &oldoid : NULL,
- default_flags | create_reflog_flag,
- UPDATE_REFS_DIE_ON_ERR);
+ return refs_update_ref(get_main_ref_store(the_repository),
+ msg, refname, &oid,
+ oldval ? &oldoid : NULL,
+ default_flags | create_reflog_flag,
+ UPDATE_REFS_DIE_ON_ERR);
}
diff --git a/builtin/upload-pack.c b/builtin/upload-pack.c
index 15afb97260..46d93278d9 100644
--- a/builtin/upload-pack.c
+++ b/builtin/upload-pack.c
@@ -9,6 +9,7 @@
#include "upload-pack.h"
#include "serve.h"
#include "commit.h"
+#include "environment.h"
static const char * const upload_pack_usage[] = {
N_("git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n"
@@ -39,6 +40,7 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix)
packet_trace_identity("upload-pack");
disable_replace_refs();
save_commit_buffer = 0;
+ xsetenv(NO_LAZY_FETCH_ENVIRONMENT, "1", 0);
argc = parse_options(argc, argv, prefix, options, upload_pack_usage, 0);
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 7c6c72536b..7e0868df72 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -433,7 +433,7 @@ static int add_worktree(const char *path, const char *refname,
/* is 'refname' a branch or commit? */
if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) &&
- ref_exists(symref.buf)) {
+ refs_ref_exists(get_main_ref_store(the_repository), symref.buf)) {
is_branch = 1;
if (!opts->force)
die_if_checked_out(symref.buf, 0);
@@ -517,7 +517,7 @@ static int add_worktree(const char *path, const char *refname,
ret = refs_update_ref(wt_refs, NULL, "HEAD", &commit->object.oid,
NULL, 0, UPDATE_REFS_MSG_ON_ERR);
else
- ret = refs_create_symref(wt_refs, "HEAD", symref.buf, NULL);
+ ret = refs_update_symref(wt_refs, "HEAD", symref.buf, NULL);
if (ret)
goto done;
@@ -605,7 +605,7 @@ static void print_preparing_worktree_line(int detach,
} else {
struct strbuf s = STRBUF_INIT;
if (!detach && !strbuf_check_branch_ref(&s, branch) &&
- ref_exists(s.buf))
+ refs_ref_exists(get_main_ref_store(the_repository), s.buf))
fprintf_ln(stderr, _("Preparing worktree (checking out '%s')"),
branch);
else {
@@ -647,9 +647,9 @@ static int first_valid_ref(const char *refname UNUSED,
*/
static int can_use_local_refs(const struct add_opts *opts)
{
- if (head_ref(first_valid_ref, NULL)) {
+ if (refs_head_ref(get_main_ref_store(the_repository), first_valid_ref, NULL)) {
return 1;
- } else if (for_each_branch_ref(first_valid_ref, NULL)) {
+ } else if (refs_for_each_branch_ref(get_main_ref_store(the_repository), first_valid_ref, NULL)) {
if (!opts->quiet) {
struct strbuf path = STRBUF_INIT;
struct strbuf contents = STRBUF_INIT;
@@ -689,7 +689,7 @@ static int can_use_remote_refs(const struct add_opts *opts)
{
if (!guess_remote) {
return 0;
- } else if (for_each_remote_ref(first_valid_ref, NULL)) {
+ } else if (refs_for_each_remote_ref(get_main_ref_store(the_repository), first_valid_ref, NULL)) {
return 1;
} else if (!opts->force && remote_get(NULL)) {
die(_("No local or remote refs exist despite at least one remote\n"
@@ -747,7 +747,8 @@ static const char *dwim_branch(const char *path, const char **new_branch)
UNLEAK(branchname);
branch_exists = !strbuf_check_branch_ref(&ref, branchname) &&
- ref_exists(ref.buf);
+ refs_ref_exists(get_main_ref_store(the_repository),
+ ref.buf);
strbuf_release(&ref);
if (branch_exists)
return branchname;
@@ -838,7 +839,7 @@ static int add(int ac, const char **av, const char *prefix)
if (!opts.force &&
!strbuf_check_branch_ref(&symref, new_branch) &&
- ref_exists(symref.buf))
+ refs_ref_exists(get_main_ref_store(the_repository), symref.buf))
die_if_checked_out(symref.buf, 0);
strbuf_release(&symref);
}
@@ -974,7 +975,9 @@ static void show_worktree(struct worktree *wt, int path_maxlen, int abbrev_len)
if (wt->is_detached)
strbuf_addstr(&sb, "(detached HEAD)");
else if (wt->head_ref) {
- char *ref = shorten_unambiguous_ref(wt->head_ref, 0);
+ char *ref = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+ wt->head_ref,
+ 0);
strbuf_addf(&sb, "[%s]", ref);
free(ref);
} else
diff --git a/builtin/write-tree.c b/builtin/write-tree.c
index 66e83d0ecb..8c75b4609b 100644
--- a/builtin/write-tree.c
+++ b/builtin/write-tree.c
@@ -3,7 +3,7 @@
*
* Copyright (C) Linus Torvalds, 2005
*/
-#define USE_THE_INDEX_VARIABLE
+
#include "builtin.h"
#include "config.h"
#include "environment.h"
@@ -44,8 +44,8 @@ int cmd_write_tree(int argc, const char **argv, const char *cmd_prefix)
prepare_repo_settings(the_repository);
the_repository->settings.command_requires_full_index = 0;
- ret = write_index_as_tree(&oid, &the_index, get_index_file(), flags,
- tree_prefix);
+ ret = write_index_as_tree(&oid, the_repository->index, get_index_file(),
+ flags, tree_prefix);
switch (ret) {
case 0:
printf("%s\n", oid_to_hex(&oid));
diff --git a/bundle-uri.c b/bundle-uri.c
index ca32050a78..91b3319a5c 100644
--- a/bundle-uri.c
+++ b/bundle-uri.c
@@ -395,11 +395,13 @@ static int unbundle_from_file(struct repository *r, const char *file)
strbuf_setlen(&bundle_ref, bundle_prefix_len);
strbuf_addstr(&bundle_ref, branch_name);
- has_old = !read_ref(bundle_ref.buf, &old_oid);
- update_ref("fetched bundle", bundle_ref.buf, oid,
- has_old ? &old_oid : NULL,
- REF_SKIP_OID_VERIFICATION,
- UPDATE_REFS_MSG_ON_ERR);
+ has_old = !refs_read_ref(get_main_ref_store(the_repository),
+ bundle_ref.buf, &old_oid);
+ refs_update_ref(get_main_ref_store(the_repository),
+ "fetched bundle", bundle_ref.buf, oid,
+ has_old ? &old_oid : NULL,
+ REF_SKIP_OID_VERIFICATION,
+ UPDATE_REFS_MSG_ON_ERR);
}
bundle_header_release(&header);
diff --git a/bundle.c b/bundle.c
index a9744da255..95367c2d0a 100644
--- a/bundle.c
+++ b/bundle.c
@@ -389,7 +389,7 @@ static int write_bundle_refs(int bundle_fd, struct rev_info *revs)
if (repo_dwim_ref(the_repository, e->name, strlen(e->name),
&oid, &ref, 0) != 1)
goto skip_write_ref;
- if (read_ref_full(e->name, RESOLVE_REF_READING, &oid, &flag))
+ if (refs_read_ref_full(get_main_ref_store(the_repository), e->name, RESOLVE_REF_READING, &oid, &flag))
flag = 0;
display_ref = (flag & REF_ISSYMREF) ? e->name : ref;
diff --git a/ci/check-whitespace.sh b/ci/check-whitespace.sh
new file mode 100755
index 0000000000..db399097a5
--- /dev/null
+++ b/ci/check-whitespace.sh
@@ -0,0 +1,95 @@
+#!/usr/bin/env bash
+#
+# Check that commits after a specified point do not contain new or modified
+# lines with whitespace errors. An optional formatted summary can be generated
+# by providing an output file path and url as additional arguments.
+#
+
+baseCommit=$1
+outputFile=$2
+url=$3
+
+if test "$#" -ne 1 && test "$#" -ne 3
+then
+ echo "USAGE: $0 <BASE_COMMIT> [<OUTPUT_FILE> <URL>]"
+ exit 1
+fi
+
+problems=()
+commit=
+commitText=
+commitTextmd=
+goodParent=
+
+while read dash sha etc
+do
+ case "${dash}" in
+ "---") # Line contains commit information.
+ if test -z "${goodParent}"
+ then
+ # Assume the commit has no whitespace errors until detected otherwise.
+ goodParent=${sha}
+ fi
+
+ commit="${sha}"
+ commitText="${sha} ${etc}"
+ commitTextmd="[${sha}](${url}/commit/${sha}) ${etc}"
+ ;;
+ "")
+ ;;
+ *) # Line contains whitespace error information for current commit.
+ if test -n "${goodParent}"
+ then
+ problems+=("1) --- ${commitTextmd}")
+ echo ""
+ echo "--- ${commitText}"
+ goodParent=
+ fi
+
+ case "${dash}" in
+ *:[1-9]*:) # contains file and line number information
+ dashend=${dash#*:}
+ problems+=("[${dash}](${url}/blob/${commit}/${dash%%:*}#L${dashend%:}) ${sha} ${etc}")
+ ;;
+ *)
+ problems+=("\`${dash} ${sha} ${etc}\`")
+ ;;
+ esac
+ echo "${dash} ${sha} ${etc}"
+ ;;
+ esac
+done <<< "$(git log --check --pretty=format:"---% h% s" "${baseCommit}"..)"
+
+if test ${#problems[*]} -gt 0
+then
+ if test -z "${goodParent}"
+ then
+ goodParent=${baseCommit: 0:7}
+ fi
+
+ echo "A whitespace issue was found in onen of more of the commits."
+ echo "Run the following command to resolve whitespace issues:"
+ echo "git rebase --whitespace=fix ${goodParent}"
+
+ # If target output file is provided, write formatted output.
+ if test -n "$outputFile"
+ then
+ echo "🛑 Please review the Summary output for further information."
+ (
+ echo "### :x: A whitespace issue was found in one or more of the commits."
+ echo ""
+ echo "Run these commands to correct the problem:"
+ echo "1. \`git rebase --whitespace=fix ${goodParent}\`"
+ echo "1. \`git push --force\`"
+ echo ""
+ echo "Errors:"
+
+ for i in "${problems[@]}"
+ do
+ echo "${i}"
+ done
+ ) >"$outputFile"
+ fi
+
+ exit 2
+fi
diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh
index b4e22de3cb..2e7688ae8b 100755
--- a/ci/install-dependencies.sh
+++ b/ci/install-dependencies.sh
@@ -1,49 +1,81 @@
-#!/usr/bin/env bash
+#!/bin/sh
#
# Install dependencies required to build and test Git on Linux and macOS
#
. ${0%/*}/lib.sh
+begin_group "Install dependencies"
+
P4WHENCE=https://cdist2.perforce.com/perforce/r21.2
LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION
-UBUNTU_COMMON_PKGS="make libssl-dev libcurl4-openssl-dev libexpat-dev
- tcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl
- libemail-valid-perl libio-socket-ssl-perl libnet-smtp-ssl-perl"
+JGITWHENCE=https://repo.eclipse.org/content/groups/releases//org/eclipse/jgit/org.eclipse.jgit.pgm/6.8.0.202311291450-r/org.eclipse.jgit.pgm-6.8.0.202311291450-r.sh
-case "$runs_on_pool" in
+# Make sudo a no-op and execute the command directly when running as root.
+# While using sudo would be fine on most platforms when we are root already,
+# some platforms like e.g. Alpine Linux do not have sudo available by default
+# and would thus break.
+if test "$(id -u)" -eq 0
+then
+ sudo () {
+ "$@"
+ }
+fi
+
+case "$distro" in
+alpine-*)
+ apk add --update shadow sudo build-base curl-dev openssl-dev expat-dev gettext \
+ pcre2-dev python3 musl-libintl perl-utils ncurses \
+ apache2 apache2-http2 apache2-proxy apache2-ssl apache2-webdav apr-util-dbd_sqlite3 \
+ bash cvs gnupg perl-cgi perl-dbd-sqlite >/dev/null
+ ;;
+fedora-*)
+ dnf -yq update >/dev/null &&
+ dnf -yq install make gcc findutils diffutils perl python3 gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null
+ ;;
ubuntu-*)
+ # Required so that apt doesn't wait for user input on certain packages.
+ export DEBIAN_FRONTEND=noninteractive
+
sudo apt-get -q update
- sudo apt-get -q -y install language-pack-is libsvn-perl apache2 \
- $UBUNTU_COMMON_PKGS $CC_PACKAGE $PYTHON_PACKAGE
- mkdir --parents "$P4_PATH"
- pushd "$P4_PATH"
- wget --quiet "$P4WHENCE/bin.linux26x86_64/p4d"
- wget --quiet "$P4WHENCE/bin.linux26x86_64/p4"
- chmod u+x p4d
- chmod u+x p4
- popd
- mkdir --parents "$GIT_LFS_PATH"
- pushd "$GIT_LFS_PATH"
- wget --quiet "$LFSWHENCE/git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
- tar --extract --gunzip --file "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
- cp git-lfs-$LINUX_GIT_LFS_VERSION/git-lfs .
- popd
+ sudo apt-get -q -y install \
+ language-pack-is libsvn-perl apache2 cvs cvsps git gnupg subversion \
+ make libssl-dev libcurl4-openssl-dev libexpat-dev wget sudo default-jre \
+ tcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl \
+ libemail-valid-perl libio-socket-ssl-perl libnet-smtp-ssl-perl libdbd-sqlite3-perl libcgi-pm-perl \
+ ${CC_PACKAGE:-${CC:-gcc}} $PYTHON_PACKAGE
+
+ mkdir --parents "$CUSTOM_PATH"
+ wget --quiet --directory-prefix="$CUSTOM_PATH" \
+ "$P4WHENCE/bin.linux26x86_64/p4d" "$P4WHENCE/bin.linux26x86_64/p4"
+ chmod a+x "$CUSTOM_PATH/p4d" "$CUSTOM_PATH/p4"
+
+ wget --quiet "$LFSWHENCE/git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
+ tar -xzf "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz" \
+ -C "$CUSTOM_PATH" --strip-components=1 "git-lfs-$LINUX_GIT_LFS_VERSION/git-lfs"
+ rm "git-lfs-linux-amd64-$LINUX_GIT_LFS_VERSION.tar.gz"
+
+ wget --quiet "$JGITWHENCE" --output-document="$CUSTOM_PATH/jgit"
+ chmod a+x "$CUSTOM_PATH/jgit"
+ ;;
+ubuntu32-*)
+ sudo linux32 --32bit i386 sh -c '
+ apt update >/dev/null &&
+ apt install -y build-essential libcurl4-openssl-dev \
+ libssl-dev libexpat-dev gettext python >/dev/null
+ '
;;
macos-*)
export HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1
# Uncomment this if you want to run perf tests:
# brew install gnu-time
- test -z "$BREW_INSTALL_PACKAGES" ||
- brew install $BREW_INSTALL_PACKAGES
brew link --force gettext
- mkdir -p "$P4_PATH"
- pushd "$P4_PATH"
- wget -q "$P4WHENCE/bin.macosx1015x86_64/helix-core-server.tgz" &&
- tar -xf helix-core-server.tgz &&
- sudo xattr -d com.apple.quarantine p4 p4d 2>/dev/null || true
- popd
+ mkdir -p "$CUSTOM_PATH"
+ wget -q "$P4WHENCE/bin.macosx1015x86_64/helix-core-server.tgz" &&
+ tar -xf helix-core-server.tgz -C "$CUSTOM_PATH" p4 p4d &&
+ sudo xattr -d com.apple.quarantine "$CUSTOM_PATH/p4" "$CUSTOM_PATH/p4d" 2>/dev/null || true
+ rm helix-core-server.tgz
if test -n "$CC_PACKAGE"
then
@@ -72,10 +104,6 @@ Documentation)
test -n "$ALREADY_HAVE_ASCIIDOCTOR" ||
sudo gem install --version 1.5.8 asciidoctor
;;
-linux-gcc-default)
- sudo apt-get -q update
- sudo apt-get -q -y install $UBUNTU_COMMON_PKGS
- ;;
esac
if type p4d >/dev/null 2>&1 && type p4 >/dev/null 2>&1
@@ -87,6 +115,7 @@ then
else
echo >&2 "WARNING: perforce wasn't installed, see above for clues why"
fi
+
if type git-lfs >/dev/null 2>&1
then
echo "$(tput setaf 6)Git-LFS Version$(tput sgr0)"
@@ -94,3 +123,13 @@ then
else
echo >&2 "WARNING: git-lfs wasn't installed, see above for clues why"
fi
+
+if type jgit >/dev/null 2>&1
+then
+ echo "$(tput setaf 6)JGit Version$(tput sgr0)"
+ jgit version
+else
+ echo >&2 "WARNING: JGit wasn't installed, see above for clues why"
+fi
+
+end_group "Install dependencies"
diff --git a/ci/install-docker-dependencies.sh b/ci/install-docker-dependencies.sh
deleted file mode 100755
index eb2c9e1eca..0000000000
--- a/ci/install-docker-dependencies.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/sh
-#
-# Install dependencies required to build and test Git inside container
-#
-
-. ${0%/*}/lib.sh
-
-begin_group "Install dependencies"
-
-case "$jobname" in
-linux32)
- linux32 --32bit i386 sh -c '
- apt update >/dev/null &&
- apt install -y build-essential libcurl4-openssl-dev \
- libssl-dev libexpat-dev gettext python >/dev/null
- '
- ;;
-linux-musl)
- apk add --update shadow sudo build-base curl-dev openssl-dev expat-dev gettext \
- pcre2-dev python3 musl-libintl perl-utils ncurses \
- apache2 apache2-http2 apache2-proxy apache2-ssl apache2-webdav apr-util-dbd_sqlite3 \
- bash cvs gnupg perl-cgi perl-dbd-sqlite >/dev/null
- ;;
-linux-*|StaticAnalysis)
- # Required so that apt doesn't wait for user input on certain packages.
- export DEBIAN_FRONTEND=noninteractive
-
- apt update -q &&
- apt install -q -y sudo git make language-pack-is libsvn-perl apache2 libssl-dev \
- libcurl4-openssl-dev libexpat-dev tcl tk gettext zlib1g-dev \
- perl-modules liberror-perl libauthen-sasl-perl libemail-valid-perl \
- libdbd-sqlite3-perl libio-socket-ssl-perl libnet-smtp-ssl-perl ${CC_PACKAGE:-${CC:-gcc}} \
- apache2 cvs cvsps gnupg libcgi-pm-perl subversion
-
- if test "$jobname" = StaticAnalysis
- then
- apt install -q -y coccinelle
- fi
- ;;
-pedantic)
- dnf -yq update >/dev/null &&
- dnf -yq install make gcc findutils diffutils perl python3 gettext zlib-devel expat-devel openssl-devel curl-devel pcre2-devel >/dev/null
- ;;
-esac
-
-end_group "Install dependencies"
diff --git a/ci/lib.sh b/ci/lib.sh
index 0a73fc7bd1..1f4059b1b8 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -18,7 +18,7 @@ elif test true = "$GITLAB_CI"
then
begin_group () {
need_to_end_group=t
- printf "\e[0Ksection_start:$(date +%s):$(echo "$1" | tr ' ' _)\r\e[0K$1\n"
+ printf "\e[0Ksection_start:$(date +%s):$(echo "$1" | tr ' ' _)[collapsed=true]\r\e[0K$1\n"
trap "end_group '$1'" EXIT
set -x
}
@@ -279,7 +279,7 @@ then
cache_dir="$HOME/none"
- runs_on_pool=$(echo "$CI_JOB_IMAGE" | tr : -)
+ distro=$(echo "$CI_JOB_IMAGE" | tr : -)
JOBS=$(nproc)
else
echo "Could not identify CI type" >&2
@@ -318,16 +318,20 @@ export DEFAULT_TEST_TARGET=prove
export GIT_TEST_CLONE_2GB=true
export SKIP_DASHED_BUILT_INS=YesPlease
-case "$runs_on_pool" in
+case "$distro" in
ubuntu-*)
if test "$jobname" = "linux-gcc-default"
then
break
fi
- PYTHON_PACKAGE=python2
- if test "$jobname" = linux-gcc
+ # Python 2 is end of life, and Ubuntu 23.04 and newer don't actually
+ # have it anymore. We thus only test with Python 2 on older LTS
+ # releases.
+ if "$distro" = "ubuntu-20.04"
then
+ PYTHON_PACKAGE=python2
+ else
PYTHON_PACKAGE=python3
fi
MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/$PYTHON_PACKAGE"
@@ -340,10 +344,6 @@ ubuntu-*)
# image.
# Keep that in mind when you encounter a broken OS X build!
export LINUX_GIT_LFS_VERSION="1.5.2"
-
- P4_PATH="$HOME/custom/p4"
- GIT_LFS_PATH="$HOME/custom/git-lfs"
- export PATH="$GIT_LFS_PATH:$P4_PATH:$PATH"
;;
macos-*)
MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=$(which python3)"
@@ -351,12 +351,12 @@ macos-*)
then
MAKEFLAGS="$MAKEFLAGS APPLE_COMMON_CRYPTO_SHA1=Yes"
fi
-
- P4_PATH="$HOME/custom/p4"
- export PATH="$P4_PATH:$PATH"
;;
esac
+CUSTOM_PATH="${CUSTOM_PATH:-$HOME/path}"
+export PATH="$CUSTOM_PATH:$PATH"
+
case "$jobname" in
linux32)
CC=gcc
diff --git a/ci/run-build-and-minimal-fuzzers.sh b/ci/run-build-and-minimal-fuzzers.sh
index a51076d18d..797d65c661 100755
--- a/ci/run-build-and-minimal-fuzzers.sh
+++ b/ci/run-build-and-minimal-fuzzers.sh
@@ -7,7 +7,7 @@
group "Build fuzzers" make \
CC=clang \
- CXX=clang++ \
+ FUZZ_CXX=clang++ \
CFLAGS="-fsanitize=fuzzer-no-link,address" \
LIB_FUZZING_ENGINE="-fsanitize=fuzzer,address" \
fuzz-all
diff --git a/ci/run-build-and-tests.sh b/ci/run-build-and-tests.sh
index c192bd613c..98dda42045 100755
--- a/ci/run-build-and-tests.sh
+++ b/ci/run-build-and-tests.sh
@@ -53,8 +53,6 @@ if test -n "$run_tests"
then
group "Run tests" make test ||
handle_failed_tests
- group "Run unit tests" \
- make DEFAULT_UNIT_TEST_TARGET=unit-tests-prove unit-tests
fi
check_unignored_build_artifacts
diff --git a/ci/run-test-slice.sh b/ci/run-test-slice.sh
index ae8094382f..e167e646f7 100755
--- a/ci/run-test-slice.sh
+++ b/ci/run-test-slice.sh
@@ -17,7 +17,7 @@ handle_failed_tests
# We only have one unit test at the moment, so run it in the first slice
if [ "$1" == "0" ] ; then
- group "Run unit tests" make --quiet -C t unit-tests-prove
+ group "Run unit tests" make --quiet -C t unit-tests-test-tool
fi
check_unignored_build_artifacts
diff --git a/color.c b/color.c
index f663c06ac4..227a5ab2f4 100644
--- a/color.c
+++ b/color.c
@@ -64,12 +64,16 @@ static int match_word(const char *word, int len, const char *match)
return !strncasecmp(word, match, len) && !match[len];
}
-static int get_hex_color(const char *in, unsigned char *out)
+static int get_hex_color(const char **inp, int width, unsigned char *out)
{
+ const char *in = *inp;
unsigned int val;
- val = (hexval(in[0]) << 4) | hexval(in[1]);
+
+ assert(width == 1 || width == 2);
+ val = (hexval(in[0]) << 4) | hexval(in[width - 1]);
if (val & ~0xff)
return -1;
+ *inp += width;
*out = val;
return 0;
}
@@ -135,11 +139,14 @@ static int parse_color(struct color *out, const char *name, int len)
return 0;
}
- /* Try a 24-bit RGB value */
- if (len == 7 && name[0] == '#') {
- if (!get_hex_color(name + 1, &out->red) &&
- !get_hex_color(name + 3, &out->green) &&
- !get_hex_color(name + 5, &out->blue)) {
+ /* Try a 24- or 12-bit RGB value prefixed with '#' */
+ if ((len == 7 || len == 4) && name[0] == '#') {
+ int width_per_color = (len == 7) ? 2 : 1;
+ const char *color = name + 1;
+
+ if (!get_hex_color(&color, width_per_color, &out->red) &&
+ !get_hex_color(&color, width_per_color, &out->green) &&
+ !get_hex_color(&color, width_per_color, &out->blue)) {
out->type = COLOR_RGB;
return 0;
}
diff --git a/color.h b/color.h
index bb28343be2..7ed259a35b 100644
--- a/color.h
+++ b/color.h
@@ -112,7 +112,8 @@ int want_color_fd(int fd, int var);
* Translate a Git color from 'value' into a string that the terminal can
* interpret and store it into 'dst'. The Git color values are of the form
* "foreground [background] [attr]" where fore- and background can be a color
- * name ("red"), a RGB code (#0xFF0000) or a 256-color-mode from the terminal.
+ * name ("red"), a RGB code (#FF0000 or #F00) or a 256-color-mode from the
+ * terminal.
*/
int color_parse(const char *value, char *dst);
int color_parse_mem(const char *value, int len, char *dst);
diff --git a/commit-graph.c b/commit-graph.c
index 45417d7412..99dda1340e 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -344,7 +344,6 @@ static int graph_read_bloom_data(const unsigned char *chunk_start,
size_t chunk_size, void *data)
{
struct commit_graph *g = data;
- uint32_t hash_version;
if (chunk_size < BLOOMDATA_CHUNK_HEADER_SIZE) {
warning(_("ignoring too-small changed-path chunk"
@@ -356,13 +355,9 @@ static int graph_read_bloom_data(const unsigned char *chunk_start,
g->chunk_bloom_data = chunk_start;
g->chunk_bloom_data_size = chunk_size;
- hash_version = get_be32(chunk_start);
-
- if (hash_version != 1)
- return 0;
g->bloom_filter_settings = xmalloc(sizeof(struct bloom_filter_settings));
- g->bloom_filter_settings->hash_version = hash_version;
+ g->bloom_filter_settings->hash_version = get_be32(chunk_start);
g->bloom_filter_settings->num_hashes = get_be32(chunk_start + 4);
g->bloom_filter_settings->bits_per_entry = get_be32(chunk_start + 8);
g->bloom_filter_settings->max_changed_paths = DEFAULT_BLOOM_MAX_CHANGES;
@@ -459,7 +454,7 @@ struct commit_graph *parse_commit_graph(struct repo_settings *s,
graph->read_generation_data = 1;
}
- if (s->commit_graph_read_changed_paths) {
+ if (s->commit_graph_changed_paths_version) {
read_chunk(cf, GRAPH_CHUNKID_BLOOMINDEXES,
graph_read_bloom_index, graph);
read_chunk(cf, GRAPH_CHUNKID_BLOOMDATA,
@@ -543,6 +538,31 @@ static int validate_mixed_generation_chain(struct commit_graph *g)
return 0;
}
+static void validate_mixed_bloom_settings(struct commit_graph *g)
+{
+ struct bloom_filter_settings *settings = NULL;
+ for (; g; g = g->base_graph) {
+ if (!g->bloom_filter_settings)
+ continue;
+ if (!settings) {
+ settings = g->bloom_filter_settings;
+ continue;
+ }
+
+ if (g->bloom_filter_settings->bits_per_entry != settings->bits_per_entry ||
+ g->bloom_filter_settings->num_hashes != settings->num_hashes ||
+ g->bloom_filter_settings->hash_version != settings->hash_version) {
+ g->chunk_bloom_indexes = NULL;
+ g->chunk_bloom_data = NULL;
+ FREE_AND_NULL(g->bloom_filter_settings);
+
+ warning(_("disabling Bloom filters for commit-graph "
+ "layer '%s' due to incompatible settings"),
+ oid_to_hex(&g->oid));
+ }
+ }
+}
+
static int add_graph_to_chain(struct commit_graph *g,
struct commit_graph *chain,
struct object_id *oids,
@@ -666,6 +686,7 @@ struct commit_graph *load_commit_graph_chain_fd_st(struct repository *r,
}
validate_mixed_generation_chain(graph_chain);
+ validate_mixed_bloom_settings(graph_chain);
free(oids);
fclose(fp);
@@ -810,6 +831,7 @@ void close_commit_graph(struct raw_object_store *o)
return;
clear_commit_graph_data_slab(&commit_graph_data_slab);
+ deinit_bloom_filters();
free_commit_graph(o->commit_graph);
o->commit_graph = NULL;
}
@@ -1147,6 +1169,7 @@ struct write_commit_graph_context {
int count_bloom_filter_not_computed;
int count_bloom_filter_trunc_empty;
int count_bloom_filter_trunc_large;
+ int count_bloom_filter_upgraded;
};
static int write_graph_chunk_fanout(struct hashfile *f,
@@ -1754,6 +1777,8 @@ static void trace2_bloom_filter_write_statistics(struct write_commit_graph_conte
ctx->count_bloom_filter_trunc_empty);
trace2_data_intmax("commit-graph", ctx->r, "filter-trunc-large",
ctx->count_bloom_filter_trunc_large);
+ trace2_data_intmax("commit-graph", ctx->r, "filter-upgraded",
+ ctx->count_bloom_filter_upgraded);
}
static void compute_bloom_filters(struct write_commit_graph_context *ctx)
@@ -1795,6 +1820,8 @@ static void compute_bloom_filters(struct write_commit_graph_context *ctx)
ctx->count_bloom_filter_trunc_empty++;
if (computed & BLOOM_TRUNC_LARGE)
ctx->count_bloom_filter_trunc_large++;
+ } else if (computed & BLOOM_UPGRADED) {
+ ctx->count_bloom_filter_upgraded++;
} else if (computed & BLOOM_NOT_COMPUTED)
ctx->count_bloom_filter_not_computed++;
ctx->total_bloom_filter_data_size += filter
@@ -1845,7 +1872,8 @@ int write_commit_graph_reachable(struct object_directory *odb,
data.progress = start_delayed_progress(
_("Collecting referenced commits"), 0);
- for_each_ref(add_ref_to_set, &data);
+ refs_for_each_ref(get_main_ref_store(the_repository), add_ref_to_set,
+ &data);
stop_progress(&data.progress);
@@ -2478,6 +2506,13 @@ int write_commit_graph(struct object_directory *odb,
}
if (!commit_graph_compatible(r))
return 0;
+ if (r->settings.commit_graph_changed_paths_version < -1
+ || r->settings.commit_graph_changed_paths_version > 2) {
+ warning(_("attempting to write a commit-graph, but "
+ "'commitgraph.changedPathsVersion' (%d) is not supported"),
+ r->settings.commit_graph_changed_paths_version);
+ return 0;
+ }
CALLOC_ARRAY(ctx, 1);
ctx->r = r;
@@ -2490,6 +2525,7 @@ int write_commit_graph(struct object_directory *odb,
ctx->write_generation_data = (get_configured_generation_version(r) == 2);
ctx->num_generation_data_overflows = 0;
+ bloom_settings.hash_version = r->settings.commit_graph_changed_paths_version;
bloom_settings.bits_per_entry = git_env_ulong("GIT_TEST_BLOOM_SETTINGS_BITS_PER_ENTRY",
bloom_settings.bits_per_entry);
bloom_settings.num_hashes = git_env_ulong("GIT_TEST_BLOOM_SETTINGS_NUM_HASHES",
@@ -2519,12 +2555,20 @@ int write_commit_graph(struct object_directory *odb,
g = ctx->r->objects->commit_graph;
/* We have changed-paths already. Keep them in the next graph */
- if (g && g->chunk_bloom_data) {
+ if (g && g->bloom_filter_settings) {
ctx->changed_paths = 1;
- ctx->bloom_settings = g->bloom_filter_settings;
+
+ /* don't propagate the hash_version unless unspecified */
+ if (bloom_settings.hash_version == -1)
+ bloom_settings.hash_version = g->bloom_filter_settings->hash_version;
+ bloom_settings.bits_per_entry = g->bloom_filter_settings->bits_per_entry;
+ bloom_settings.num_hashes = g->bloom_filter_settings->num_hashes;
+ bloom_settings.max_changed_paths = g->bloom_filter_settings->max_changed_paths;
}
}
+ bloom_settings.hash_version = bloom_settings.hash_version == 2 ? 2 : 1;
+
if (ctx->split) {
struct commit_graph *g = ctx->r->objects->commit_graph;
@@ -2607,6 +2651,9 @@ int write_commit_graph(struct object_directory *odb,
res = write_commit_graph_file(ctx);
+ if (ctx->changed_paths)
+ deinit_bloom_filters();
+
if (ctx->split)
mark_commit_graphs(ctx);
diff --git a/commit.c b/commit.c
index 1a479a997c..1d08951007 100644
--- a/commit.c
+++ b/commit.c
@@ -1070,7 +1070,8 @@ struct commit *get_fork_point(const char *refname, struct commit *commit)
memset(&revs, 0, sizeof(revs));
revs.initial = 1;
- for_each_reflog_ent(full_refname, collect_one_reflog_ent, &revs);
+ refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+ full_refname, collect_one_reflog_ent, &revs);
if (!revs.nr)
add_one_commit(&oid, &revs);
diff --git a/common-main.c b/common-main.c
index 033778b3c5..b86f40600f 100644
--- a/common-main.c
+++ b/common-main.c
@@ -48,7 +48,7 @@ int main(int argc, const char **argv)
setlocale(LC_CTYPE, "");
git_setup_gettext();
- initialize_the_repository();
+ initialize_repository(the_repository);
attr_start();
diff --git a/compat/mingw.c b/compat/mingw.c
index 4876344b5b..6b06ea540f 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -3159,6 +3159,7 @@ int uname(struct utsname *buf)
return 0;
}
+#ifndef NO_UNIX_SOCKETS
int mingw_have_unix_sockets(void)
{
SC_HANDLE scm, srvc;
@@ -3177,3 +3178,4 @@ int mingw_have_unix_sockets(void)
}
return ret;
}
+#endif
diff --git a/compat/precompose_utf8.c b/compat/precompose_utf8.c
index 0bd5c24250..5a7c90c90d 100644
--- a/compat/precompose_utf8.c
+++ b/compat/precompose_utf8.c
@@ -94,6 +94,16 @@ const char *precompose_string_if_needed(const char *in)
return in;
}
+void precompose_strbuf_if_needed(struct strbuf *sb)
+{
+ char *buf_prec = (char *)precompose_string_if_needed(sb->buf);
+ if (buf_prec != sb->buf) {
+ size_t buf_prec_len = strlen(buf_prec);
+ free(strbuf_detach(sb, NULL));
+ strbuf_attach(sb, buf_prec, buf_prec_len, buf_prec_len + 1);
+ }
+}
+
const char *precompose_argv_prefix(int argc, const char **argv, const char *prefix)
{
int i = 0;
diff --git a/compat/precompose_utf8.h b/compat/precompose_utf8.h
index fea06cf28a..7c3cfcadb0 100644
--- a/compat/precompose_utf8.h
+++ b/compat/precompose_utf8.h
@@ -30,6 +30,7 @@ typedef struct {
const char *precompose_argv_prefix(int argc, const char **argv, const char *prefix);
const char *precompose_string_if_needed(const char *in);
+void precompose_strbuf_if_needed(struct strbuf *sb);
void probe_utf8_pathname_composition(void);
PREC_DIR *precompose_utf8_opendir(const char *dirname);
diff --git a/compat/regex/regcomp.c b/compat/regex/regcomp.c
index d1bc09e49b..2bc0f1187a 100644
--- a/compat/regex/regcomp.c
+++ b/compat/regex/regcomp.c
@@ -868,7 +868,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
if (table_size > pat_len)
break;
- dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
+ dfa->state_table = calloc (table_size, sizeof (struct re_state_table_entry));
dfa->state_hash_mask = table_size - 1;
dfa->mb_cur_max = MB_CUR_MAX;
@@ -936,7 +936,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len)
{
int i, j, ch;
- dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
+ dfa->sb_char = (re_bitset_ptr_t) calloc (1, sizeof (bitset_t));
if (BE (dfa->sb_char == NULL, 0))
return REG_ESPACE;
@@ -3079,9 +3079,9 @@ parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
_NL_COLLATE_SYMB_EXTRAMB);
}
#endif
- sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
+ sbcset = (re_bitset_ptr_t) calloc (1, sizeof (bitset_t));
#ifdef RE_ENABLE_I18N
- mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
+ mbcset = (re_charset_t *) calloc (1, sizeof (re_charset_t));
#endif /* RE_ENABLE_I18N */
#ifdef RE_ENABLE_I18N
if (BE (sbcset == NULL || mbcset == NULL, 0))
@@ -3626,9 +3626,9 @@ build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
re_token_t br_token;
bin_tree_t *tree;
- sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
+ sbcset = (re_bitset_ptr_t) calloc (1, sizeof (bitset_t));
#ifdef RE_ENABLE_I18N
- mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
+ mbcset = (re_charset_t *) calloc (1, sizeof (re_charset_t));
#endif /* RE_ENABLE_I18N */
#ifdef RE_ENABLE_I18N
diff --git a/compat/regex/regex_internal.c b/compat/regex/regex_internal.c
index ec51cf3446..ec5cc5d2dd 100644
--- a/compat/regex/regex_internal.c
+++ b/compat/regex/regex_internal.c
@@ -1628,7 +1628,7 @@ create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
reg_errcode_t err;
re_dfastate_t *newstate;
- newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
+ newstate = (re_dfastate_t *) calloc (1, sizeof (re_dfastate_t));
if (BE (newstate == NULL, 0))
return NULL;
err = re_node_set_init_copy (&newstate->nodes, nodes);
@@ -1678,7 +1678,7 @@ create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
reg_errcode_t err;
re_dfastate_t *newstate;
- newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
+ newstate = (re_dfastate_t *) calloc (1, sizeof (re_dfastate_t));
if (BE (newstate == NULL, 0))
return NULL;
err = re_node_set_init_copy (&newstate->nodes, nodes);
diff --git a/compat/regex/regexec.c b/compat/regex/regexec.c
index 49358ae475..e92be5741d 100644
--- a/compat/regex/regexec.c
+++ b/compat/regex/regexec.c
@@ -2796,8 +2796,8 @@ get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
continue; /* No. */
if (sub_top->path == NULL)
{
- sub_top->path = calloc (sizeof (state_array_t),
- sl_str - sub_top->str_idx + 1);
+ sub_top->path = calloc (sl_str - sub_top->str_idx + 1,
+ sizeof (state_array_t));
if (sub_top->path == NULL)
return REG_ESPACE;
}
@@ -3361,7 +3361,7 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
if (ndests == 0)
{
state->trtable = (re_dfastate_t **)
- calloc (sizeof (re_dfastate_t *), SBC_MAX);
+ calloc (SBC_MAX, sizeof (re_dfastate_t *));
return 1;
}
return 0;
@@ -3457,7 +3457,7 @@ out_free:
discern by looking at the character code: allocate a
256-entry transition table. */
trtable = state->trtable =
- (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);
+ (re_dfastate_t **) calloc (SBC_MAX, sizeof (re_dfastate_t *));
if (BE (trtable == NULL, 0))
goto out_free;
@@ -3488,7 +3488,7 @@ out_free:
transition tables, one starting at trtable[0] and one
starting at trtable[SBC_MAX]. */
trtable = state->word_trtable =
- (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX);
+ (re_dfastate_t **) calloc (2 * SBC_MAX, sizeof (re_dfastate_t *));
if (BE (trtable == NULL, 0))
goto out_free;
diff --git a/config.c b/config.c
index ae3652b08f..1b2ec5de46 100644
--- a/config.c
+++ b/config.c
@@ -125,7 +125,7 @@ struct config_include_data {
config_fn_t fn;
void *data;
const struct config_options *opts;
- struct git_config_source *config_source;
+ const struct git_config_source *config_source;
struct repository *repo;
/*
@@ -303,7 +303,8 @@ static int include_by_branch(const char *cond, size_t cond_len)
int ret;
struct strbuf pattern = STRBUF_INIT;
const char *refname = !the_repository->gitdir ?
- NULL : resolve_ref_unsafe("HEAD", 0, NULL, &flags);
+ NULL : refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ "HEAD", 0, NULL, &flags);
const char *shortname;
if (!refname || !(flags & REF_ISSYMREF) ||
@@ -317,6 +318,21 @@ static int include_by_branch(const char *cond, size_t cond_len)
return ret;
}
+static int include_by_hostname(const char *cond, size_t cond_len)
+{
+ int ret;
+ char my_host[HOST_NAME_MAX + 1];
+ struct strbuf pattern = STRBUF_INIT;
+
+ if (xgethostname(my_host, sizeof(my_host)))
+ return 0;
+
+ strbuf_add(&pattern, cond, cond_len);
+ ret = !wildmatch(pattern.buf, my_host, 0);
+ strbuf_release(&pattern);
+ return ret;
+}
+
static int add_remote_url(const char *var, const char *value,
const struct config_context *ctx UNUSED, void *data)
{
@@ -406,6 +422,8 @@ static int include_condition_is_true(const struct key_value_info *kvi,
else if (skip_prefix_mem(cond, cond_len, "hasconfig:remote.*.url:", &cond,
&cond_len))
return include_by_remote_url(inc, cond, cond_len);
+ else if (skip_prefix_mem(cond, cond_len, "hostname:", &cond, &cond_len))
+ return include_by_hostname(cond, cond_len);
/* unknown conditionals are always false */
return 0;
@@ -1416,8 +1434,19 @@ static int git_default_core_config(const char *var, const char *value,
if (!strcmp(var, "core.attributesfile"))
return git_config_pathname(&git_attributes_file, var, value);
- if (!strcmp(var, "core.hookspath"))
+ if (!strcmp(var, "core.hookspath")) {
+ if (ctx->kvi && ctx->kvi->scope == CONFIG_SCOPE_LOCAL &&
+ git_env_bool("GIT_CLONE_PROTECTION_ACTIVE", 0))
+ die(_("active `core.hooksPath` found in the local "
+ "repository config:\n\t%s\nFor security "
+ "reasons, this is disallowed by default.\nIf "
+ "this is intentional and the hook should "
+ "actually be run, please\nrun the command "
+ "again with "
+ "`GIT_CLONE_PROTECTION_ACTIVE=false`"),
+ value);
return git_config_pathname(&git_hooks_path, var, value);
+ }
if (!strcmp(var, "core.bare")) {
is_bare_repository_cfg = git_config_bool(var, value);
@@ -2105,7 +2134,7 @@ static int do_git_config_sequence(const struct config_options *opts,
}
int config_with_options(config_fn_t fn, void *data,
- struct git_config_source *config_source,
+ const struct git_config_source *config_source,
struct repository *repo,
const struct config_options *opts)
{
@@ -3182,14 +3211,10 @@ void git_config_set(const char *key, const char *value)
trace2_cmd_set_config(key, value);
}
-/*
- * The ownership rule is that the caller will own the string
- * if it receives a piece of memory different from what it passed
- * as the parameter.
- */
-const char *git_config_prepare_comment_string(const char *comment)
+char *git_config_prepare_comment_string(const char *comment)
{
size_t leading_blanks;
+ char *prepared;
if (!comment)
return NULL;
@@ -3210,13 +3235,13 @@ const char *git_config_prepare_comment_string(const char *comment)
leading_blanks = strspn(comment, " \t");
if (leading_blanks && comment[leading_blanks] == '#')
- ; /* use it as-is */
+ prepared = xstrdup(comment); /* use it as-is */
else if (comment[0] == '#')
- comment = xstrfmt(" %s", comment);
+ prepared = xstrfmt(" %s", comment);
else
- comment = xstrfmt(" # %s", comment);
+ prepared = xstrfmt(" # %s", comment);
- return comment;
+ return prepared;
}
static void validate_comment_string(const char *comment)
diff --git a/config.h b/config.h
index f4966e3749..e66c84520b 100644
--- a/config.h
+++ b/config.h
@@ -232,7 +232,7 @@ void git_config(config_fn_t fn, void *);
* sets `opts.respect_includes` to `1` by default.
*/
int config_with_options(config_fn_t fn, void *,
- struct git_config_source *config_source,
+ const struct git_config_source *config_source,
struct repository *repo,
const struct config_options *opts);
@@ -338,7 +338,7 @@ void git_config_set_multivar(const char *, const char *, const char *, unsigned)
int repo_config_set_multivar_gently(struct repository *, const char *, const char *, const char *, unsigned);
int git_config_set_multivar_in_file_gently(const char *, const char *, const char *, const char *, const char *, unsigned);
-const char *git_config_prepare_comment_string(const char *);
+char *git_config_prepare_comment_string(const char *);
/**
* takes four parameters:
diff --git a/config.mak.uname b/config.mak.uname
index a7607a5676..85d63821ec 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -68,6 +68,7 @@ ifeq ($(uname_S),Linux)
ifneq ($(findstring .el7.,$(uname_R)),)
BASIC_CFLAGS += -std=c99
endif
+ LINK_FUZZ_PROGRAMS = YesPlease
endif
ifeq ($(uname_S),GNU/kFreeBSD)
HAVE_ALLOCA_H = YesPlease
diff --git a/contrib/buildsystems/CMakeLists.txt b/contrib/buildsystems/CMakeLists.txt
index 804629c525..2f9c33585c 100644
--- a/contrib/buildsystems/CMakeLists.txt
+++ b/contrib/buildsystems/CMakeLists.txt
@@ -1005,10 +1005,11 @@ endforeach()
#test-tool
parse_makefile_for_sources(test-tool_SOURCES "TEST_BUILTINS_OBJS")
+add_library(test-lib OBJECT ${CMAKE_SOURCE_DIR}/t/unit-tests/test-lib.c)
list(TRANSFORM test-tool_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/t/helper/")
add_executable(test-tool ${CMAKE_SOURCE_DIR}/t/helper/test-tool.c ${test-tool_SOURCES} ${test-reftable_SOURCES})
-target_link_libraries(test-tool common-main)
+target_link_libraries(test-tool test-lib common-main)
set_target_properties(test-fake-ssh test-tool
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/helper)
diff --git a/contrib/coccinelle/refs.cocci b/contrib/coccinelle/refs.cocci
new file mode 100644
index 0000000000..31d9cad8f3
--- /dev/null
+++ b/contrib/coccinelle/refs.cocci
@@ -0,0 +1,103 @@
+// Migrate "refs.h" to not rely on `the_repository` implicitly anymore.
+@@
+@@
+(
+- resolve_ref_unsafe
++ refs_resolve_ref_unsafe
+|
+- resolve_refdup
++ refs_resolve_refdup
+|
+- read_ref_full
++ refs_read_ref_full
+|
+- read_ref
++ refs_read_ref
+|
+- ref_exists
++ refs_ref_exists
+|
+- head_ref
++ refs_head_ref
+|
+- for_each_ref
++ refs_for_each_ref
+|
+- for_each_ref_in
++ refs_for_each_ref_in
+|
+- for_each_fullref_in
++ refs_for_each_fullref_in
+|
+- for_each_tag_ref
++ refs_for_each_tag_ref
+|
+- for_each_branch_ref
++ refs_for_each_branch_ref
+|
+- for_each_remote_ref
++ refs_for_each_remote_ref
+|
+- for_each_glob_ref
++ refs_for_each_glob_ref
+|
+- for_each_glob_ref_in
++ refs_for_each_glob_ref_in
+|
+- head_ref_namespaced
++ refs_head_ref_namespaced
+|
+- for_each_namespaced_ref
++ refs_for_each_namespaced_ref
+|
+- for_each_rawref
++ refs_for_each_rawref
+|
+- safe_create_reflog
++ refs_create_reflog
+|
+- reflog_exists
++ refs_reflog_exists
+|
+- delete_ref
++ refs_delete_ref
+|
+- delete_refs
++ refs_delete_refs
+|
+- delete_reflog
++ refs_delete_reflog
+|
+- for_each_reflog_ent
++ refs_for_each_reflog_ent
+|
+- for_each_reflog_ent_reverse
++ refs_for_each_reflog_ent_reverse
+|
+- for_each_reflog
++ refs_for_each_reflog
+|
+- shorten_unambiguous_ref
++ refs_shorten_unambiguous_ref
+|
+- rename_ref
++ refs_rename_ref
+|
+- copy_existing_ref
++ refs_copy_existing_ref
+|
+- create_symref
++ refs_create_symref
+|
+- ref_transaction_begin
++ ref_store_transaction_begin
+|
+- update_ref
++ refs_update_ref
+|
+- reflog_expire
++ refs_reflog_expire
+)
+ (
++ get_main_ref_store(the_repository),
+ ...)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 75193ded4b..5571440883 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -31,15 +31,29 @@
# Note that "git" is optional --- '!f() { : commit; ...}; f' would complete
# just like the 'git commit' command.
#
-# If you have a command that is not part of git, but you would still
-# like completion, you can use __git_complete:
+# To add completion for git subcommands that are implemented in external
+# scripts, define a function of the form '_git_${subcommand}' while replacing
+# all dashes with underscores, and the main git completion will make use of it.
+# For example, to add completion for 'git do-stuff' (which could e.g. live
+# in /usr/bin/git-do-stuff), name the completion function '_git_do_stuff'.
+# See _git_show, _git_bisect etc. below for more examples.
+#
+# If you have a shell command that is not part of git (and is not called as a
+# git subcommand), but you would still like git-style completion for it, use
+# __git_complete. For example, to use the same completion as for 'git log' also
+# for the 'gl' command:
#
# __git_complete gl git_log
#
-# Or if it's a main command (i.e. git or gitk):
+# Or if the 'gk' command should be completed the same as 'gitk':
#
# __git_complete gk gitk
#
+# The second parameter of __git_complete gives the completion function; it is
+# resolved as a function named "$2", or "__$2_main", or "_$2" in that order.
+# In the examples above, the actual functions used for completion will be
+# _git_log and __gitk_main.
+#
# Compatible with bash 3.2.57.
#
# You can set the following environment variables to influence the behavior of
@@ -1315,10 +1329,12 @@ __git_find_last_on_cmdline ()
while test $# -gt 1; do
case "$1" in
--show-idx) show_idx=y ;;
+ --) shift && break ;;
*) return 1 ;;
esac
shift
done
+ [ $# -eq 1 ] || return 1 # return 1 if we got wrong # of non-opts
local wordlist="$1"
while [ $c -gt "$__git_cmd_idx" ]; do
@@ -1429,6 +1445,29 @@ __git_count_arguments ()
printf "%d" $c
}
+# Complete actual dir (not pathspec), respecting any -C options.
+#
+# Usage: __git_complete_refs [<option>]...
+# --cur=<word>: The current dir to be completed. Defaults to the current word.
+__git_complete_dir ()
+{
+ local cur_="$cur"
+
+ while test $# != 0; do
+ case "$1" in
+ --cur=*) cur_="${1##--cur=}" ;;
+ *) return 1 ;;
+ esac
+ shift
+ done
+
+ # This rev-parse invocation amounts to a pwd which respects -C options
+ local context_dir=$(__git rev-parse --show-toplevel --show-prefix 2>/dev/null | paste -s -d '/' 2>/dev/null)
+ [ -d "$context_dir" ] || return 1
+
+ COMPREPLY=$(cd "$context_dir" 2>/dev/null && compgen -d -- "$cur_")
+}
+
__git_whitespacelist="nowarn warn error error-all fix"
__git_patchformat="mbox stgit stgit-series hg mboxrd"
__git_showcurrentpatch="diff raw"
@@ -1447,6 +1486,10 @@ _git_am ()
__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
return
;;
+ --directory=*)
+ __git_complete_dir --cur="${cur##--directory=}"
+ return
+ ;;
--patch-format=*)
__gitcomp "$__git_patchformat" "" "${cur##--patch-format=}"
return
@@ -1978,7 +2021,17 @@ __git_format_patch_extra_options="
_git_format_patch ()
{
+ case "$prev,$cur" in
+ -o,*)
+ __git_complete_dir
+ return
+ ;;
+ esac
case "$cur" in
+ --output-directory=*)
+ __git_complete_dir --cur="${cur##--output-directory=}"
+ return
+ ;;
--thread=*)
__gitcomp "
deep shallow
@@ -2582,7 +2635,9 @@ _git_send_email ()
return
;;
esac
- __git_complete_revlist
+ if [ "$(__git_find_last_on_cmdline -- "--format-patch --no-format-patch")" != "--no-format-patch" ]; then
+ __git_complete_revlist
+ fi
}
_git_stage ()
@@ -3581,6 +3636,17 @@ _git_svn ()
fi
}
+_git_symbolic_ref () {
+ case "$cur" in
+ --*)
+ __gitcomp_builtin symbolic-ref
+ return
+ ;;
+ esac
+
+ __git_complete_refs
+}
+
_git_tag ()
{
local i c="$__git_cmd_idx" f=0
diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh
index cac6f61881..f5877bd7a1 100644
--- a/contrib/completion/git-completion.zsh
+++ b/contrib/completion/git-completion.zsh
@@ -272,6 +272,7 @@ _git ()
{
local _ret=1
local cur cword prev
+ local __git_repo_path
cur=${words[CURRENT]}
prev=${words[CURRENT-1]}
diff --git a/copy.c b/copy.c
index 23d84c6c1d..3df156f6ce 100644
--- a/copy.c
+++ b/copy.c
@@ -1,6 +1,9 @@
#include "git-compat-util.h"
#include "copy.h"
#include "path.h"
+#include "gettext.h"
+#include "strbuf.h"
+#include "abspath.h"
int copy_fd(int ifd, int ofd)
{
@@ -67,3 +70,61 @@ int copy_file_with_time(const char *dst, const char *src, int mode)
return copy_times(dst, src);
return status;
}
+
+static int do_symlinks_match(const char *path1, const char *path2)
+{
+ struct strbuf buf1 = STRBUF_INIT, buf2 = STRBUF_INIT;
+ int ret = 0;
+
+ if (!strbuf_readlink(&buf1, path1, 0) &&
+ !strbuf_readlink(&buf2, path2, 0))
+ ret = !strcmp(buf1.buf, buf2.buf);
+
+ strbuf_release(&buf1);
+ strbuf_release(&buf2);
+ return ret;
+}
+
+int do_files_match(const char *path1, const char *path2)
+{
+ struct stat st1, st2;
+ int fd1 = -1, fd2 = -1, ret = 1;
+ char buf1[8192], buf2[8192];
+
+ if ((fd1 = open_nofollow(path1, O_RDONLY)) < 0 ||
+ fstat(fd1, &st1) || !S_ISREG(st1.st_mode)) {
+ if (fd1 < 0 && errno == ELOOP)
+ /* maybe this is a symbolic link? */
+ return do_symlinks_match(path1, path2);
+ ret = 0;
+ } else if ((fd2 = open_nofollow(path2, O_RDONLY)) < 0 ||
+ fstat(fd2, &st2) || !S_ISREG(st2.st_mode)) {
+ ret = 0;
+ }
+
+ if (ret)
+ /* to match, neither must be executable, or both */
+ ret = !(st1.st_mode & 0111) == !(st2.st_mode & 0111);
+
+ if (ret)
+ ret = st1.st_size == st2.st_size;
+
+ while (ret) {
+ ssize_t len1 = read_in_full(fd1, buf1, sizeof(buf1));
+ ssize_t len2 = read_in_full(fd2, buf2, sizeof(buf2));
+
+ if (len1 < 0 || len2 < 0 || len1 != len2)
+ ret = 0; /* read error or different file size */
+ else if (!len1) /* len2 is also 0; hit EOF on both */
+ break; /* ret is still true */
+ else
+ ret = !memcmp(buf1, buf2, len1);
+ }
+
+ if (fd1 >= 0)
+ close(fd1);
+ if (fd2 >= 0)
+ close(fd2);
+
+ return ret;
+}
diff --git a/copy.h b/copy.h
index 2af77cba86..057259a3a7 100644
--- a/copy.h
+++ b/copy.h
@@ -7,4 +7,18 @@ int copy_fd(int ifd, int ofd);
int copy_file(const char *dst, const char *src, int mode);
int copy_file_with_time(const char *dst, const char *src, int mode);
+/*
+ * Compare the file mode and contents of two given files.
+ *
+ * If both files are actually symbolic links, the function returns 1 if the link
+ * targets are identical or 0 if they are not.
+ *
+ * If any of the two files cannot be accessed or in case of read failures, this
+ * function returns 0.
+ *
+ * If the file modes and contents are identical, the function returns 1,
+ * otherwise it returns 0.
+ */
+int do_files_match(const char *path1, const char *path2);
+
#endif /* COPY_H */
diff --git a/credential.c b/credential.c
index 18098bd35e..758528b291 100644
--- a/credential.c
+++ b/credential.c
@@ -25,13 +25,64 @@ void credential_clear(struct credential *c)
free(c->path);
free(c->username);
free(c->password);
+ free(c->credential);
free(c->oauth_refresh_token);
+ free(c->authtype);
string_list_clear(&c->helpers, 0);
strvec_clear(&c->wwwauth_headers);
+ strvec_clear(&c->state_headers);
+ strvec_clear(&c->state_headers_to_send);
credential_init(c);
}
+void credential_next_state(struct credential *c)
+{
+ strvec_clear(&c->state_headers_to_send);
+ SWAP(c->state_headers, c->state_headers_to_send);
+}
+
+void credential_clear_secrets(struct credential *c)
+{
+ FREE_AND_NULL(c->password);
+ FREE_AND_NULL(c->credential);
+}
+
+static void credential_set_capability(struct credential_capability *capa,
+ enum credential_op_type op_type)
+{
+ switch (op_type) {
+ case CREDENTIAL_OP_INITIAL:
+ capa->request_initial = 1;
+ break;
+ case CREDENTIAL_OP_HELPER:
+ capa->request_helper = 1;
+ break;
+ case CREDENTIAL_OP_RESPONSE:
+ capa->response = 1;
+ break;
+ }
+}
+
+
+void credential_set_all_capabilities(struct credential *c,
+ enum credential_op_type op_type)
+{
+ credential_set_capability(&c->capa_authtype, op_type);
+ credential_set_capability(&c->capa_state, op_type);
+}
+
+static void announce_one(struct credential_capability *cc, const char *name, FILE *fp) {
+ if (cc->request_initial)
+ fprintf(fp, "capability %s\n", name);
+}
+
+void credential_announce_capabilities(struct credential *c, FILE *fp) {
+ fprintf(fp, "version 0\n");
+ announce_one(&c->capa_authtype, "authtype", fp);
+ announce_one(&c->capa_state, "state", fp);
+}
+
int credential_match(const struct credential *want,
const struct credential *have, int match_password)
{
@@ -40,7 +91,8 @@ int credential_match(const struct credential *want,
CHECK(host) &&
CHECK(path) &&
CHECK(username) &&
- (!match_password || CHECK(password));
+ (!match_password || CHECK(password)) &&
+ (!match_password || CHECK(credential));
#undef CHECK
}
@@ -208,7 +260,26 @@ static void credential_getpass(struct credential *c)
PROMPT_ASKPASS);
}
-int credential_read(struct credential *c, FILE *fp)
+int credential_has_capability(const struct credential_capability *capa,
+ enum credential_op_type op_type)
+{
+ /*
+ * We're checking here if each previous step indicated that we had the
+ * capability. If it did, then we want to pass it along; conversely, if
+ * it did not, we don't want to report that to our caller.
+ */
+ switch (op_type) {
+ case CREDENTIAL_OP_HELPER:
+ return capa->request_initial;
+ case CREDENTIAL_OP_RESPONSE:
+ return capa->request_initial && capa->request_helper;
+ default:
+ return 0;
+ }
+}
+
+int credential_read(struct credential *c, FILE *fp,
+ enum credential_op_type op_type)
{
struct strbuf line = STRBUF_INIT;
@@ -233,6 +304,9 @@ int credential_read(struct credential *c, FILE *fp)
} else if (!strcmp(key, "password")) {
free(c->password);
c->password = xstrdup(value);
+ } else if (!strcmp(key, "credential")) {
+ free(c->credential);
+ c->credential = xstrdup(value);
} else if (!strcmp(key, "protocol")) {
free(c->protocol);
c->protocol = xstrdup(value);
@@ -242,8 +316,19 @@ int credential_read(struct credential *c, FILE *fp)
} else if (!strcmp(key, "path")) {
free(c->path);
c->path = xstrdup(value);
+ } else if (!strcmp(key, "ephemeral")) {
+ c->ephemeral = !!git_config_bool("ephemeral", value);
} else if (!strcmp(key, "wwwauth[]")) {
strvec_push(&c->wwwauth_headers, value);
+ } else if (!strcmp(key, "state[]")) {
+ strvec_push(&c->state_headers, value);
+ } else if (!strcmp(key, "capability[]")) {
+ if (!strcmp(value, "authtype"))
+ credential_set_capability(&c->capa_authtype, op_type);
+ else if (!strcmp(value, "state"))
+ credential_set_capability(&c->capa_state, op_type);
+ } else if (!strcmp(key, "continue")) {
+ c->multistage = !!git_config_bool("continue", value);
} else if (!strcmp(key, "password_expiry_utc")) {
errno = 0;
c->password_expiry_utc = parse_timestamp(value, NULL, 10);
@@ -252,6 +337,9 @@ int credential_read(struct credential *c, FILE *fp)
} else if (!strcmp(key, "oauth_refresh_token")) {
free(c->oauth_refresh_token);
c->oauth_refresh_token = xstrdup(value);
+ } else if (!strcmp(key, "authtype")) {
+ free(c->authtype);
+ c->authtype = xstrdup(value);
} else if (!strcmp(key, "url")) {
credential_from_url(c, value);
} else if (!strcmp(key, "quit")) {
@@ -280,8 +368,20 @@ static void credential_write_item(FILE *fp, const char *key, const char *value,
fprintf(fp, "%s=%s\n", key, value);
}
-void credential_write(const struct credential *c, FILE *fp)
+void credential_write(const struct credential *c, FILE *fp,
+ enum credential_op_type op_type)
{
+ if (credential_has_capability(&c->capa_authtype, op_type))
+ credential_write_item(fp, "capability[]", "authtype", 0);
+ if (credential_has_capability(&c->capa_state, op_type))
+ credential_write_item(fp, "capability[]", "state", 0);
+
+ if (credential_has_capability(&c->capa_authtype, op_type)) {
+ credential_write_item(fp, "authtype", c->authtype, 0);
+ credential_write_item(fp, "credential", c->credential, 0);
+ if (c->ephemeral)
+ credential_write_item(fp, "ephemeral", "1", 0);
+ }
credential_write_item(fp, "protocol", c->protocol, 1);
credential_write_item(fp, "host", c->host, 1);
credential_write_item(fp, "path", c->path, 0);
@@ -295,6 +395,12 @@ void credential_write(const struct credential *c, FILE *fp)
}
for (size_t i = 0; i < c->wwwauth_headers.nr; i++)
credential_write_item(fp, "wwwauth[]", c->wwwauth_headers.v[i], 0);
+ if (credential_has_capability(&c->capa_state, op_type)) {
+ if (c->multistage)
+ credential_write_item(fp, "continue", "1", 0);
+ for (size_t i = 0; i < c->state_headers_to_send.nr; i++)
+ credential_write_item(fp, "state[]", c->state_headers_to_send.v[i], 0);
+ }
}
static int run_credential_helper(struct credential *c,
@@ -317,14 +423,14 @@ static int run_credential_helper(struct credential *c,
fp = xfdopen(helper.in, "w");
sigchain_push(SIGPIPE, SIG_IGN);
- credential_write(c, fp);
+ credential_write(c, fp, want_output ? CREDENTIAL_OP_HELPER : CREDENTIAL_OP_RESPONSE);
fclose(fp);
sigchain_pop(SIGPIPE);
if (want_output) {
int r;
fp = xfdopen(helper.out, "r");
- r = credential_read(c, fp);
+ r = credential_read(c, fp, CREDENTIAL_OP_HELPER);
fclose(fp);
if (r < 0) {
finish_command(&helper);
@@ -357,14 +463,19 @@ static int credential_do(struct credential *c, const char *helper,
return r;
}
-void credential_fill(struct credential *c)
+void credential_fill(struct credential *c, int all_capabilities)
{
int i;
- if (c->username && c->password)
+ if ((c->username && c->password) || c->credential)
return;
+ credential_next_state(c);
+ c->multistage = 0;
+
credential_apply_config(c);
+ if (all_capabilities)
+ credential_set_all_capabilities(c, CREDENTIAL_OP_INITIAL);
for (i = 0; i < c->helpers.nr; i++) {
credential_do(c, c->helpers.items[i].string, "get");
@@ -374,15 +485,17 @@ void credential_fill(struct credential *c)
/* Reset expiry to maintain consistency */
c->password_expiry_utc = TIME_MAX;
}
- if (c->username && c->password)
+ if ((c->username && c->password) || c->credential) {
+ strvec_clear(&c->wwwauth_headers);
return;
+ }
if (c->quit)
die("credential helper '%s' told us to quit",
c->helpers.items[i].string);
}
credential_getpass(c);
- if (!c->username && !c->password)
+ if (!c->username && !c->password && !c->credential)
die("unable to get password from user");
}
@@ -392,9 +505,11 @@ void credential_approve(struct credential *c)
if (c->approved)
return;
- if (!c->username || !c->password || c->password_expiry_utc < time(NULL))
+ if (((!c->username || !c->password) && !c->credential) || c->password_expiry_utc < time(NULL))
return;
+ credential_next_state(c);
+
credential_apply_config(c);
for (i = 0; i < c->helpers.nr; i++)
@@ -406,6 +521,8 @@ void credential_reject(struct credential *c)
{
int i;
+ credential_next_state(c);
+
credential_apply_config(c);
for (i = 0; i < c->helpers.nr; i++)
@@ -413,6 +530,7 @@ void credential_reject(struct credential *c)
FREE_AND_NULL(c->username);
FREE_AND_NULL(c->password);
+ FREE_AND_NULL(c->credential);
FREE_AND_NULL(c->oauth_refresh_token);
c->password_expiry_utc = TIME_MAX;
c->approved = 0;
diff --git a/credential.h b/credential.h
index acc41adf54..af8c287ff2 100644
--- a/credential.h
+++ b/credential.h
@@ -93,6 +93,27 @@
* -----------------------------------------------------------------------
*/
+/*
+ * These values define the kind of operation we're performing and the
+ * capabilities at each stage. The first is either an external request (via git
+ * credential fill) or an internal request (e.g., via the HTTP) code. The
+ * second is the call to the credential helper, and the third is the response
+ * we're providing.
+ *
+ * At each stage, we will emit the capability only if the previous stage
+ * supported it.
+ */
+enum credential_op_type {
+ CREDENTIAL_OP_INITIAL = 1,
+ CREDENTIAL_OP_HELPER = 2,
+ CREDENTIAL_OP_RESPONSE = 3,
+};
+
+struct credential_capability {
+ unsigned request_initial:1,
+ request_helper:1,
+ response:1;
+};
/**
* This struct represents a single username/password combination
@@ -124,6 +145,16 @@ struct credential {
struct strvec wwwauth_headers;
/**
+ * A `strvec` of state headers received from credential helpers.
+ */
+ struct strvec state_headers;
+
+ /**
+ * A `strvec` of state headers to send to credential helpers.
+ */
+ struct strvec state_headers_to_send;
+
+ /**
* Internal use only. Keeps track of if we previously matched against a
* WWW-Authenticate header line in order to re-fold future continuation
* lines into one value.
@@ -131,24 +162,38 @@ struct credential {
unsigned header_is_last_match:1;
unsigned approved:1,
+ ephemeral:1,
configured:1,
+ multistage: 1,
quit:1,
use_http_path:1,
username_from_proto:1;
+ struct credential_capability capa_authtype;
+ struct credential_capability capa_state;
+
char *username;
char *password;
+ char *credential;
char *protocol;
char *host;
char *path;
char *oauth_refresh_token;
timestamp_t password_expiry_utc;
+
+ /**
+ * The authorization scheme to use. If this is NULL, libcurl is free to
+ * negotiate any scheme it likes.
+ */
+ char *authtype;
};
#define CREDENTIAL_INIT { \
.helpers = STRING_LIST_INIT_DUP, \
.password_expiry_utc = TIME_MAX, \
.wwwauth_headers = STRVEC_INIT, \
+ .state_headers = STRVEC_INIT, \
+ .state_headers_to_send = STRVEC_INIT, \
}
/* Initialize a credential structure, setting all fields to empty. */
@@ -167,8 +212,11 @@ void credential_clear(struct credential *);
* returns, the username and password fields of the credential are
* guaranteed to be non-NULL. If an error occurs, the function will
* die().
+ *
+ * If all_capabilities is set, this is an internal user that is prepared
+ * to deal with all known capabilities, and we should advertise that fact.
*/
-void credential_fill(struct credential *);
+void credential_fill(struct credential *, int all_capabilities);
/**
* Inform the credential subsystem that the provided credentials
@@ -191,8 +239,46 @@ void credential_approve(struct credential *);
*/
void credential_reject(struct credential *);
-int credential_read(struct credential *, FILE *);
-void credential_write(const struct credential *, FILE *);
+/**
+ * Enable all of the supported credential flags in this credential.
+ */
+void credential_set_all_capabilities(struct credential *c,
+ enum credential_op_type op_type);
+
+/**
+ * Clear the secrets in this credential, but leave other data intact.
+ *
+ * This is useful for resetting credentials in preparation for a subsequent
+ * stage of filling.
+ */
+void credential_clear_secrets(struct credential *c);
+
+/**
+ * Print a list of supported capabilities and version numbers to standard
+ * output.
+ */
+void credential_announce_capabilities(struct credential *c, FILE *fp);
+
+/**
+ * Prepares the credential for the next iteration of the helper protocol by
+ * updating the state headers to send with the ones read by the last iteration
+ * of the protocol.
+ *
+ * Except for internal callers, this should be called exactly once between
+ * reading credentials with `credential_fill` and writing them.
+ */
+void credential_next_state(struct credential *c);
+
+/**
+ * Return true if the capability is enabled for an operation of op_type.
+ */
+int credential_has_capability(const struct credential_capability *capa,
+ enum credential_op_type op_type);
+
+int credential_read(struct credential *, FILE *,
+ enum credential_op_type);
+void credential_write(const struct credential *, FILE *,
+ enum credential_op_type);
/*
* Parse a url into a credential struct, replacing any existing contents.
diff --git a/delta-islands.c b/delta-islands.c
index f7e079425f..62b5bc1921 100644
--- a/delta-islands.c
+++ b/delta-islands.c
@@ -10,14 +10,14 @@
#include "diff.h"
#include "progress.h"
#include "refs.h"
-#include "khash.h"
+#include "khashl.h"
#include "pack-bitmap.h"
#include "pack-objects.h"
#include "delta-islands.h"
#include "oid-array.h"
#include "config.h"
-KHASH_INIT(str, const char *, void *, 1, kh_str_hash_func, kh_str_hash_equal)
+KHASHL_MAP_INIT(KH_LOCAL, kh_str, str, const char *, void *, kh_hash_str, kh_eq_str)
static kh_oid_map_t *island_marks;
static unsigned island_counter;
@@ -488,7 +488,8 @@ void load_delta_islands(struct repository *r, int progress)
git_config(island_config_callback, &ild);
ild.remote_islands = kh_init_str();
- for_each_ref(find_island_for_ref, &ild);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ find_island_for_ref, &ild);
free_config_regexes(&ild);
deduplicate_islands(ild.remote_islands, r);
free_remote_islands(ild.remote_islands);
diff --git a/diff-lib.c b/diff-lib.c
index 683f11e509..12b1541478 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -660,7 +660,6 @@ int do_diff_cache(const struct object_id *tree_oid, struct diff_options *opt)
repo_init_revisions(opt->repo, &revs, NULL);
copy_pathspec(&revs.prune_data, &opt->pathspec);
- diff_setup_done(&revs.diffopt);
revs.diffopt = *opt;
if (diff_cache(&revs, tree_oid, NULL, 1))
diff --git a/diff.c b/diff.c
index 108c187577..cd3c8a3978 100644
--- a/diff.c
+++ b/diff.c
@@ -40,6 +40,7 @@
#include "setup.h"
#include "strmap.h"
#include "ws.h"
+#include "write-or-die.h"
#ifdef NO_FAST_WORKING_DIRECTORY
#define FAST_WORKING_DIRECTORY 0
@@ -4404,8 +4405,33 @@ static void run_external_diff(const char *pgm,
diff_free_filespec_data(one);
diff_free_filespec_data(two);
cmd.use_shell = 1;
- if (run_command(&cmd))
- die(_("external diff died, stopping at %s"), name);
+ if (o->flags.diff_from_contents) {
+ int got_output = 0;
+ cmd.out = -1;
+ if (start_command(&cmd))
+ die(_("external diff died, stopping at %s"), name);
+ for (;;) {
+ char buffer[8192];
+ ssize_t len = xread(cmd.out, buffer, sizeof(buffer));
+ if (!len)
+ break;
+ if (len < 0)
+ die(_("unable to read from external diff,"
+ " stopping at %s"), name);
+ got_output = 1;
+ if (write_in_full(1, buffer, len) < 0)
+ die(_("unable to write output of external diff,"
+ " stopping at %s"), name);
+ }
+ close(cmd.out);
+ if (finish_command(&cmd))
+ die(_("external diff died, stopping at %s"), name);
+ if (got_output)
+ o->found_changes = 1;
+ } else {
+ if (run_command(&cmd))
+ die(_("external diff died, stopping at %s"), name);
+ }
remove_tempfile();
}
@@ -4555,6 +4581,7 @@ static void run_diff_cmd(const char *pgm,
o, complete_rewrite);
} else {
fprintf(o->file, "* Unmerged path %s\n", name);
+ o->found_changes = 1;
}
}
@@ -4851,6 +4878,7 @@ void diff_setup_done(struct diff_options *options)
*/
if ((options->xdl_opts & XDF_WHITESPACE_FLAGS) ||
+ options->flags.exit_with_status ||
options->ignore_regex_nr)
options->flags.diff_from_contents = 1;
else
@@ -6741,7 +6769,7 @@ void diff_flush(struct diff_options *options)
if (output_format & DIFF_FORMAT_CALLBACK)
options->format_callback(q, options, options->format_callback_data);
- if (output_format & DIFF_FORMAT_NO_OUTPUT &&
+ if ((!output_format || output_format & DIFF_FORMAT_NO_OUTPUT) &&
options->flags.exit_with_status &&
options->flags.diff_from_contents) {
/*
diff --git a/dir.c b/dir.c
index 20ebe4cba2..2d83f3311a 100644
--- a/dir.c
+++ b/dir.c
@@ -100,6 +100,18 @@ int fspathncmp(const char *a, const char *b, size_t count)
return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);
}
+int paths_collide(const char *a, const char *b)
+{
+ size_t len_a = strlen(a), len_b = strlen(b);
+
+ if (len_a == len_b)
+ return fspatheq(a, b);
+
+ if (len_a < len_b)
+ return is_dir_sep(b[len_a]) && !fspathncmp(a, b, len_a);
+ return is_dir_sep(a[len_b]) && !fspathncmp(a, b, len_b);
+}
+
unsigned int fspathhash(const char *str)
{
return ignore_case ? strihash(str) : strhash(str);
diff --git a/dir.h b/dir.h
index 45a7b9ec5f..b9e8e96128 100644
--- a/dir.h
+++ b/dir.h
@@ -549,6 +549,13 @@ int fspathncmp(const char *a, const char *b, size_t count);
unsigned int fspathhash(const char *str);
/*
+ * Reports whether paths collide. This may be because the paths differ only in
+ * case on a case-sensitive filesystem, or that one path refers to a symlink
+ * that collides with one of the parent directories of the other.
+ */
+int paths_collide(const char *a, const char *b);
+
+/*
* The prefix part of pattern must not contains wildcards.
*/
struct pathspec_item;
diff --git a/entry.c b/entry.c
index f918a3a78e..b8c257f6f9 100644
--- a/entry.c
+++ b/entry.c
@@ -460,7 +460,7 @@ static void mark_colliding_entries(const struct checkout *state,
continue;
if ((trust_ino && !match_stat_data(&dup->ce_stat_data, st)) ||
- (!trust_ino && !fspathcmp(ce->name, dup->name))) {
+ paths_collide(ce->name, dup->name)) {
dup->ce_flags |= CE_MATCHED;
break;
}
@@ -547,6 +547,20 @@ int checkout_entry_ca(struct cache_entry *ce, struct conv_attrs *ca,
/* If it is a gitlink, leave it alone! */
if (S_ISGITLINK(ce->ce_mode))
return 0;
+ /*
+ * We must avoid replacing submodules' leading
+ * directories with symbolic links, lest recursive
+ * clones can write into arbitrary locations.
+ *
+ * Technically, this logic is not limited
+ * to recursive clones, or for that matter to
+ * submodules' paths colliding with symbolic links'
+ * paths. Yet it strikes a balance in favor of
+ * simplicity, and if paths are colliding, we might
+ * just as well keep the directories during a clone.
+ */
+ if (state->clone && S_ISLNK(ce->ce_mode))
+ return 0;
remove_subtree(&path);
} else if (unlink(path.buf))
return error_errno("unable to unlink old '%s'", path.buf);
diff --git a/environment.h b/environment.h
index 05fd94d7be..be543ee995 100644
--- a/environment.h
+++ b/environment.h
@@ -56,6 +56,14 @@ const char *getenv_safe(struct strvec *argv, const char *name);
#define GIT_OPTIONAL_LOCKS_ENVIRONMENT "GIT_OPTIONAL_LOCKS"
#define GIT_TEXT_DOMAIN_DIR_ENVIRONMENT "GIT_TEXTDOMAINDIR"
#define GIT_ATTR_SOURCE_ENVIRONMENT "GIT_ATTR_SOURCE"
+#define GIT_DEFAULT_HASH_ENVIRONMENT "GIT_DEFAULT_HASH"
+
+/*
+ * Environment variable used to propagate the --no-advice global option to the
+ * advice_enabled() helper, even when run in a subprocess.
+ * This is an internal variable that should not be set by the user.
+ */
+#define GIT_ADVICE_ENVIRONMENT "GIT_ADVICE"
/*
* Environment variable used in handshaking the wire protocol.
diff --git a/ewah/bitmap.c b/ewah/bitmap.c
index ac7e0af622..55928dada8 100644
--- a/ewah/bitmap.c
+++ b/ewah/bitmap.c
@@ -138,6 +138,49 @@ void bitmap_or(struct bitmap *self, const struct bitmap *other)
self->words[i] |= other->words[i];
}
+int ewah_bitmap_is_subset(struct ewah_bitmap *self, struct bitmap *other)
+{
+ struct ewah_iterator it;
+ eword_t word;
+ size_t i;
+
+ ewah_iterator_init(&it, self);
+
+ for (i = 0; i < other->word_alloc; i++) {
+ if (!ewah_iterator_next(&word, &it)) {
+ /*
+ * If we reached the end of `self`, and haven't
+ * rejected `self` as a possible subset of
+ * `other` yet, then we are done and `self` is
+ * indeed a subset of `other`.
+ */
+ return 1;
+ }
+ if (word & ~other->words[i]) {
+ /*
+ * Otherwise, compare the next two pairs of
+ * words. If the word from `self` has bit(s) not
+ * in the word from `other`, `self` is not a
+ * subset of `other`.
+ */
+ return 0;
+ }
+ }
+
+ /*
+ * If we got to this point, there may be zero or more words
+ * remaining in `self`, with no remaining words left in `other`.
+ * If there are any bits set in the remaining word(s) in `self`,
+ * then `self` is not a subset of `other`.
+ */
+ while (ewah_iterator_next(&word, &it))
+ if (word)
+ return 0;
+
+ /* `self` is definitely a subset of `other` */
+ return 1;
+}
+
void bitmap_or_ewah(struct bitmap *self, struct ewah_bitmap *other)
{
size_t original_size = self->word_alloc;
@@ -169,6 +212,20 @@ size_t bitmap_popcount(struct bitmap *self)
return count;
}
+size_t ewah_bitmap_popcount(struct ewah_bitmap *self)
+{
+ struct ewah_iterator it;
+ eword_t word;
+ size_t count = 0;
+
+ ewah_iterator_init(&it, self);
+
+ while (ewah_iterator_next(&word, &it))
+ count += ewah_bit_popcount64(word);
+
+ return count;
+}
+
int bitmap_is_empty(struct bitmap *self)
{
size_t i;
@@ -204,6 +261,25 @@ int bitmap_equals(struct bitmap *self, struct bitmap *other)
return 1;
}
+int bitmap_equals_ewah(struct bitmap *self, struct ewah_bitmap *other)
+{
+ struct ewah_iterator it;
+ eword_t word;
+ size_t i = 0;
+
+ ewah_iterator_init(&it, other);
+
+ while (ewah_iterator_next(&word, &it))
+ if (word != (i < self->word_alloc ? self->words[i++] : 0))
+ return 0;
+
+ for (; i < self->word_alloc; i++)
+ if (self->words[i])
+ return 0;
+
+ return 1;
+}
+
int bitmap_is_subset(struct bitmap *self, struct bitmap *other)
{
size_t common_size, i;
diff --git a/ewah/ewok.h b/ewah/ewok.h
index c11d76c6f3..5e357e2493 100644
--- a/ewah/ewok.h
+++ b/ewah/ewok.h
@@ -179,7 +179,14 @@ void bitmap_unset(struct bitmap *self, size_t pos);
int bitmap_get(struct bitmap *self, size_t pos);
void bitmap_free(struct bitmap *self);
int bitmap_equals(struct bitmap *self, struct bitmap *other);
+int bitmap_equals_ewah(struct bitmap *self, struct ewah_bitmap *other);
+
+/*
+ * Both `bitmap_is_subset()` and `ewah_bitmap_is_subset()` return 1 if the set
+ * of bits in 'self' are a subset of the bits in 'other'. Returns 0 otherwise.
+ */
int bitmap_is_subset(struct bitmap *self, struct bitmap *other);
+int ewah_bitmap_is_subset(struct ewah_bitmap *self, struct bitmap *other);
struct ewah_bitmap * bitmap_to_ewah(struct bitmap *bitmap);
struct bitmap *ewah_to_bitmap(struct ewah_bitmap *ewah);
@@ -189,6 +196,7 @@ void bitmap_or_ewah(struct bitmap *self, struct ewah_bitmap *other);
void bitmap_or(struct bitmap *self, const struct bitmap *other);
size_t bitmap_popcount(struct bitmap *self);
+size_t ewah_bitmap_popcount(struct ewah_bitmap *self);
int bitmap_is_empty(struct bitmap *self);
#endif
diff --git a/fetch-pack.c b/fetch-pack.c
index 091f9a80a9..7d2aef21ad 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -290,7 +290,8 @@ static void mark_tips(struct fetch_negotiator *negotiator,
int i;
if (!negotiation_tips) {
- for_each_rawref(rev_list_insert_ref_oid, negotiator);
+ refs_for_each_rawref(get_main_ref_store(the_repository),
+ rev_list_insert_ref_oid, negotiator);
return;
}
@@ -732,11 +733,6 @@ static void mark_alternate_complete(struct fetch_negotiator *negotiator UNUSED,
mark_complete(&obj->oid);
}
-struct loose_object_iter {
- struct oidset *loose_object_set;
- struct ref *refs;
-};
-
/*
* Mark recent commits available locally and reachable from a local ref as
* COMPLETE.
@@ -793,7 +789,8 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
*/
trace2_region_enter("fetch-pack", "mark_complete_local_refs", NULL);
if (!args->deepen) {
- for_each_rawref(mark_complete_oid, NULL);
+ refs_for_each_rawref(get_main_ref_store(the_repository),
+ mark_complete_oid, NULL);
for_each_cached_alternate(NULL, mark_alternate_complete);
commit_list_sort_by_date(&complete);
if (cutoff)
diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
index ae201e21db..7d144b803a 100644
--- a/fmt-merge-msg.c
+++ b/fmt-merge-msg.c
@@ -661,7 +661,9 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
/* learn the commit that we merge into and the current branch name */
current_branch = current_branch_to_free =
- resolve_refdup("HEAD", RESOLVE_REF_READING, &head_oid, NULL);
+ refs_resolve_refdup(get_main_ref_store(the_repository),
+ "HEAD", RESOLVE_REF_READING, &head_oid,
+ NULL);
if (!current_branch)
die("No current branch");
diff --git a/fsck.c b/fsck.c
index 78af29d264..8ef962199f 100644
--- a/fsck.c
+++ b/fsck.c
@@ -658,6 +658,8 @@ static int fsck_tree(const struct object_id *tree_oid,
retval += report(options, tree_oid, OBJ_TREE,
FSCK_MSG_MAILMAP_SYMLINK,
".mailmap is a symlink");
+ oidset_insert(&options->symlink_targets_found,
+ entry_oid);
}
if ((backslash = strchr(name, '\\'))) {
@@ -1166,6 +1168,56 @@ static int fsck_blob(const struct object_id *oid, const char *buf,
}
}
+ if (oidset_contains(&options->symlink_targets_found, oid)) {
+ const char *ptr = buf;
+ const struct object_id *reported = NULL;
+
+ oidset_insert(&options->symlink_targets_done, oid);
+
+ if (!buf || size > PATH_MAX) {
+ /*
+ * A missing buffer here is a sign that the caller found the
+ * blob too gigantic to load into memory. Let's just consider
+ * that an error.
+ */
+ return report(options, oid, OBJ_BLOB,
+ FSCK_MSG_SYMLINK_TARGET_LENGTH,
+ "symlink target too long");
+ }
+
+ while (!reported && ptr) {
+ const char *p = ptr;
+ char c, *slash = strchrnul(ptr, '/');
+ char *backslash = memchr(ptr, '\\', slash - ptr);
+
+ c = *slash;
+ *slash = '\0';
+
+ while (!reported && backslash) {
+ *backslash = '\0';
+ if (is_ntfs_dotgit(p))
+ ret |= report(options, reported = oid, OBJ_BLOB,
+ FSCK_MSG_SYMLINK_POINTS_TO_GIT_DIR,
+ "symlink target points to git dir");
+ *backslash = '\\';
+ p = backslash + 1;
+ backslash = memchr(p, '\\', slash - p);
+ }
+ if (!reported && is_ntfs_dotgit(p))
+ ret |= report(options, reported = oid, OBJ_BLOB,
+ FSCK_MSG_SYMLINK_POINTS_TO_GIT_DIR,
+ "symlink target points to git dir");
+
+ if (!reported && is_hfs_dotgit(ptr))
+ ret |= report(options, reported = oid, OBJ_BLOB,
+ FSCK_MSG_SYMLINK_POINTS_TO_GIT_DIR,
+ "symlink target points to git dir");
+
+ *slash = c;
+ ptr = c ? slash + 1 : NULL;
+ }
+ }
+
return ret;
}
@@ -1264,6 +1316,10 @@ int fsck_finish(struct fsck_options *options)
FSCK_MSG_GITATTRIBUTES_MISSING, FSCK_MSG_GITATTRIBUTES_BLOB,
options, ".gitattributes");
+ ret |= fsck_blobs(&options->symlink_targets_found, &options->symlink_targets_done,
+ FSCK_MSG_SYMLINK_TARGET_MISSING, FSCK_MSG_SYMLINK_TARGET_BLOB,
+ options, "<symlink-target>");
+
return ret;
}
diff --git a/fsck.h b/fsck.h
index e3adf9d911..17fa2dda5d 100644
--- a/fsck.h
+++ b/fsck.h
@@ -64,6 +64,8 @@ enum fsck_msg_type {
FUNC(GITATTRIBUTES_LARGE, ERROR) \
FUNC(GITATTRIBUTES_LINE_LENGTH, ERROR) \
FUNC(GITATTRIBUTES_BLOB, ERROR) \
+ FUNC(SYMLINK_TARGET_MISSING, ERROR) \
+ FUNC(SYMLINK_TARGET_BLOB, ERROR) \
/* warnings */ \
FUNC(EMPTY_NAME, WARN) \
FUNC(FULL_PATHNAME, WARN) \
@@ -74,6 +76,8 @@ enum fsck_msg_type {
FUNC(ZERO_PADDED_FILEMODE, WARN) \
FUNC(NUL_IN_COMMIT, WARN) \
FUNC(LARGE_PATHNAME, WARN) \
+ FUNC(SYMLINK_TARGET_LENGTH, WARN) \
+ FUNC(SYMLINK_POINTS_TO_GIT_DIR, WARN) \
/* infos (reported as warnings, but ignored by default) */ \
FUNC(BAD_FILEMODE, INFO) \
FUNC(GITMODULES_PARSE, INFO) \
@@ -141,6 +145,8 @@ struct fsck_options {
struct oidset gitmodules_done;
struct oidset gitattributes_found;
struct oidset gitattributes_done;
+ struct oidset symlink_targets_found;
+ struct oidset symlink_targets_done;
kh_oid_map_t *object_names;
};
@@ -150,6 +156,8 @@ struct fsck_options {
.gitmodules_done = OIDSET_INIT, \
.gitattributes_found = OIDSET_INIT, \
.gitattributes_done = OIDSET_INIT, \
+ .symlink_targets_found = OIDSET_INIT, \
+ .symlink_targets_done = OIDSET_INIT, \
.error_func = fsck_error_function \
}
#define FSCK_OPTIONS_STRICT { \
@@ -158,6 +166,8 @@ struct fsck_options {
.gitmodules_done = OIDSET_INIT, \
.gitattributes_found = OIDSET_INIT, \
.gitattributes_done = OIDSET_INIT, \
+ .symlink_targets_found = OIDSET_INIT, \
+ .symlink_targets_done = OIDSET_INIT, \
.error_func = fsck_error_function, \
}
#define FSCK_OPTIONS_MISSING_GITMODULES { \
@@ -166,6 +176,8 @@ struct fsck_options {
.gitmodules_done = OIDSET_INIT, \
.gitattributes_found = OIDSET_INIT, \
.gitattributes_done = OIDSET_INIT, \
+ .symlink_targets_found = OIDSET_INIT, \
+ .symlink_targets_done = OIDSET_INIT, \
.error_func = fsck_error_cb_print_missing_gitmodules, \
}
diff --git a/git-compat-util.h b/git-compat-util.h
index ca7678a379..892e1f9067 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -344,6 +344,7 @@ static inline const char *precompose_string_if_needed(const char *in)
return in;
}
+#define precompose_strbuf_if_needed(a)
#define probe_utf8_pathname_composition()
#endif
diff --git a/git-p4.py b/git-p4.py
index 28ab12c72b..f1ab31d540 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -3253,17 +3253,19 @@ class P4Sync(Command, P4UserMap):
if self.stream_have_file_info:
if "depotFile" in self.stream_file:
f = self.stream_file["depotFile"]
- # force a failure in fast-import, else an empty
- # commit will be made
- self.gitStream.write("\n")
- self.gitStream.write("die-now\n")
- self.gitStream.close()
- # ignore errors, but make sure it exits first
- self.importProcess.wait()
- if f:
- die("Error from p4 print for %s: %s" % (f, err))
- else:
- die("Error from p4 print: %s" % err)
+ try:
+ # force a failure in fast-import, else an empty
+ # commit will be made
+ self.gitStream.write("\n")
+ self.gitStream.write("die-now\n")
+ self.gitStream.close()
+ # ignore errors, but make sure it exits first
+ self.importProcess.wait()
+ finally:
+ if f:
+ die("Error from p4 print for %s: %s" % (f, err))
+ else:
+ die("Error from p4 print: %s" % err)
if 'depotFile' in marshalled and self.stream_have_file_info:
# start of a new file - output the old one first
diff --git a/git-send-email.perl b/git-send-email.perl
index 821b2b3a13..1d6712a44e 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -1361,7 +1361,6 @@ sub smtp_host_string {
# Returns 1 if authentication succeeded or was not necessary
# (smtp_user was not specified), and 0 otherwise.
-
sub smtp_auth_maybe {
if (!defined $smtp_authuser || $auth || (defined $smtp_auth && $smtp_auth eq "none")) {
return 1;
@@ -1510,6 +1509,7 @@ Message-ID: $message_id
sub send_message {
my ($recipients_ref, $to, $date, $gitversion, $cc, $ccline, $header) = gen_header();
my @recipients = @$recipients_ref;
+ my $confirm_shown = 0;
my @sendmail_parameters = ('-i', @recipients);
my $raw_from = $sender;
@@ -1555,6 +1555,7 @@ EOF
} elsif (/^a/i) {
$confirm = 'never';
}
+ $confirm_shown = 1;
}
unshift (@sendmail_parameters, @smtp_server_options);
@@ -1576,7 +1577,6 @@ EOF
print $sm "$header\n$message";
close $sm or die $!;
} else {
-
if (!defined $smtp_server) {
die __("The required SMTP server is not properly defined.")
}
@@ -1664,9 +1664,13 @@ EOF
$smtp->code =~ /250|200/ or die sprintf(__("Failed to send %s\n"), $subject).$smtp->message;
}
if ($quiet) {
- printf($dry_run ? __("Dry-Sent %s\n") : __("Sent %s\n"), $subject);
+ print "\n" if ($confirm_shown);
+ printf($dry_run ? __("Dry-Sent %s") : __("Sent %s"), $subject);
+ print "\n";
} else {
- print($dry_run ? __("Dry-OK. Log says:\n") : __("OK. Log says:\n"));
+ print "\n";
+ print($dry_run ? __("Dry-OK. Log says:") : __("OK. Log says:"));
+ print "\n";
if (!defined $sendmail_cmd && !file_name_is_absolute($smtp_server)) {
print "Server: $smtp_server\n";
print "MAIL FROM:<$raw_from>\n";
@@ -1686,10 +1690,11 @@ EOF
print $header, "\n";
if ($smtp) {
print __("Result: "), $smtp->code, ' ',
- ($smtp->message =~ /\n([^\n]+\n)$/s), "\n";
+ ($smtp->message =~ /\n([^\n]+\n)$/s);
} else {
- print __("Result: OK\n");
+ print __("Result: OK");
}
+ print "\n";
}
return 1;
@@ -1920,7 +1925,7 @@ sub pre_process_file {
sub process_file {
my ($t) = @_;
- pre_process_file($t, $quiet);
+ pre_process_file($t, $quiet);
my $message_was_sent = send_message();
if ($message_was_sent == -1) {
diff --git a/git.c b/git.c
index 654d615a18..637c61ca9c 100644
--- a/git.c
+++ b/git.c
@@ -36,9 +36,10 @@ struct cmd_struct {
const char git_usage_string[] =
N_("git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n"
" [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
- " [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]\n"
- " [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
- " [--config-env=<name>=<envvar>] <command> [<args>]");
+ " [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--no-lazy-fetch]\n"
+ " [--no-optional-locks] [--no-advice] [--bare] [--git-dir=<path>]\n"
+ " [--work-tree=<path>] [--namespace=<name>] [--config-env=<name>=<envvar>]\n"
+ " <command> [<args>]");
const char git_more_info_string[] =
N_("'git help -a' and 'git help -g' list available subcommands and some\n"
@@ -337,6 +338,10 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
setenv(GIT_ATTR_SOURCE_ENVIRONMENT, cmd, 1);
if (envchanged)
*envchanged = 1;
+ } else if (!strcmp(cmd, "--no-advice")) {
+ setenv(GIT_ADVICE_ENVIRONMENT, "0", 1);
+ if (envchanged)
+ *envchanged = 1;
} else {
fprintf(stderr, _("unknown option: %s\n"), cmd);
usage(git_usage_string);
diff --git a/help.c b/help.c
index 2dbe57b413..1d057aa607 100644
--- a/help.c
+++ b/help.c
@@ -800,7 +800,7 @@ static int append_similar_ref(const char *refname,
if (starts_with(refname, "refs/remotes/") &&
!strcmp(branch, cb->base_ref))
string_list_append_nodup(cb->similar_refs,
- shorten_unambiguous_ref(refname, 1));
+ refs_shorten_unambiguous_ref(get_main_ref_store(the_repository), refname, 1));
return 0;
}
@@ -811,7 +811,8 @@ static struct string_list guess_refs(const char *ref)
ref_cb.base_ref = ref;
ref_cb.similar_refs = &similar_refs;
- for_each_ref(append_similar_ref, &ref_cb);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ append_similar_ref, &ref_cb);
return similar_refs;
}
diff --git a/hook.c b/hook.c
index f6306d72b3..eebc4d4473 100644
--- a/hook.c
+++ b/hook.c
@@ -7,25 +7,56 @@
#include "run-command.h"
#include "config.h"
#include "strbuf.h"
+#include "environment.h"
+#include "setup.h"
+#include "copy.h"
+
+static int identical_to_template_hook(const char *name, const char *path)
+{
+ const char *env = getenv("GIT_CLONE_TEMPLATE_DIR");
+ const char *template_dir = get_template_dir(env && *env ? env : NULL);
+ struct strbuf template_path = STRBUF_INIT;
+ int found_template_hook, ret;
+
+ strbuf_addf(&template_path, "%s/hooks/%s", template_dir, name);
+ found_template_hook = access(template_path.buf, X_OK) >= 0;
+#ifdef STRIP_EXTENSION
+ if (!found_template_hook) {
+ strbuf_addstr(&template_path, STRIP_EXTENSION);
+ found_template_hook = access(template_path.buf, X_OK) >= 0;
+ }
+#endif
+ if (!found_template_hook)
+ return 0;
+
+ ret = do_files_match(template_path.buf, path);
+
+ strbuf_release(&template_path);
+ return ret;
+}
const char *find_hook(const char *name)
{
static struct strbuf path = STRBUF_INIT;
+ int found_hook;
+
strbuf_reset(&path);
strbuf_git_path(&path, "hooks/%s", name);
- if (access(path.buf, X_OK) < 0) {
+ found_hook = access(path.buf, X_OK) >= 0;
+#ifdef STRIP_EXTENSION
+ if (!found_hook) {
int err = errno;
-#ifdef STRIP_EXTENSION
strbuf_addstr(&path, STRIP_EXTENSION);
- if (access(path.buf, X_OK) >= 0)
- return path.buf;
- if (errno == EACCES)
- err = errno;
+ found_hook = access(path.buf, X_OK) >= 0;
+ if (!found_hook)
+ errno = err;
+ }
#endif
- if (err == EACCES && advice_enabled(ADVICE_IGNORED_HOOK)) {
+ if (!found_hook) {
+ if (errno == EACCES && advice_enabled(ADVICE_IGNORED_HOOK)) {
static struct string_list advise_given = STRING_LIST_INIT_DUP;
if (!string_list_lookup(&advise_given, name)) {
@@ -39,6 +70,14 @@ const char *find_hook(const char *name)
}
return NULL;
}
+ if (!git_hooks_path && git_env_bool("GIT_CLONE_PROTECTION_ACTIVE", 0) &&
+ !identical_to_template_hook(name, path.buf))
+ die(_("active `%s` hook found during `git clone`:\n\t%s\n"
+ "For security reasons, this is disallowed by default.\n"
+ "If this is intentional and the hook should actually "
+ "be run, please\nrun the command again with "
+ "`GIT_CLONE_PROTECTION_ACTIVE=false`"),
+ name, path.buf);
return path.buf;
}
diff --git a/http-backend.c b/http-backend.c
index 1ed1e29d07..5b65287ac9 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -559,7 +559,8 @@ static void get_info_refs(struct strbuf *hdr, char *arg UNUSED)
} else {
select_getanyfile(hdr);
- for_each_namespaced_ref(NULL, show_text_ref, &buf);
+ refs_for_each_namespaced_ref(get_main_ref_store(the_repository),
+ NULL, show_text_ref, &buf);
send_strbuf(hdr, "text/plain", &buf);
}
strbuf_release(&buf);
@@ -571,9 +572,10 @@ static int show_head_ref(const char *refname, const struct object_id *oid,
struct strbuf *buf = cb_data;
if (flag & REF_ISSYMREF) {
- const char *target = resolve_ref_unsafe(refname,
- RESOLVE_REF_READING,
- NULL, NULL);
+ const char *target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ refname,
+ RESOLVE_REF_READING,
+ NULL, NULL);
if (target)
strbuf_addf(buf, "ref: %s\n", strip_namespace(target));
@@ -589,7 +591,8 @@ static void get_head(struct strbuf *hdr, char *arg UNUSED)
struct strbuf buf = STRBUF_INIT;
select_getanyfile(hdr);
- head_ref_namespaced(show_head_ref, &buf);
+ refs_head_ref_namespaced(get_main_ref_store(the_repository),
+ show_head_ref, &buf);
send_strbuf(hdr, "text/plain", &buf);
strbuf_release(&buf);
}
diff --git a/http.c b/http.c
index 3d80bd6116..752c879c1f 100644
--- a/http.c
+++ b/http.c
@@ -128,7 +128,6 @@ static unsigned long empty_auth_useless =
| CURLAUTH_DIGEST;
static struct curl_slist *pragma_header;
-static struct curl_slist *no_pragma_header;
static struct string_list extra_http_headers = STRING_LIST_INIT_DUP;
static struct curl_slist *host_resolutions;
@@ -299,6 +298,11 @@ size_t fwrite_null(char *ptr UNUSED, size_t eltsize UNUSED, size_t nmemb,
return nmemb;
}
+static struct curl_slist *object_request_headers(void)
+{
+ return curl_slist_append(http_copy_default_headers(), "Pragma:");
+}
+
static void closedown_active_slot(struct active_request_slot *slot)
{
active_requests--;
@@ -557,18 +561,34 @@ static int curl_empty_auth_enabled(void)
return 0;
}
+struct curl_slist *http_append_auth_header(const struct credential *c,
+ struct curl_slist *headers)
+{
+ if (c->authtype && c->credential) {
+ struct strbuf auth = STRBUF_INIT;
+ strbuf_addf(&auth, "Authorization: %s %s",
+ c->authtype, c->credential);
+ headers = curl_slist_append(headers, auth.buf);
+ strbuf_release(&auth);
+ }
+ return headers;
+}
+
static void init_curl_http_auth(CURL *result)
{
- if (!http_auth.username || !*http_auth.username) {
+ if ((!http_auth.username || !*http_auth.username) &&
+ (!http_auth.credential || !*http_auth.credential)) {
if (curl_empty_auth_enabled())
curl_easy_setopt(result, CURLOPT_USERPWD, ":");
return;
}
- credential_fill(&http_auth);
+ credential_fill(&http_auth, 1);
- curl_easy_setopt(result, CURLOPT_USERNAME, http_auth.username);
- curl_easy_setopt(result, CURLOPT_PASSWORD, http_auth.password);
+ if (http_auth.password) {
+ curl_easy_setopt(result, CURLOPT_USERNAME, http_auth.username);
+ curl_easy_setopt(result, CURLOPT_PASSWORD, http_auth.password);
+ }
}
/* *var must be free-able */
@@ -582,17 +602,22 @@ static void var_override(const char **var, char *value)
static void set_proxyauth_name_password(CURL *result)
{
+ if (proxy_auth.password) {
curl_easy_setopt(result, CURLOPT_PROXYUSERNAME,
proxy_auth.username);
curl_easy_setopt(result, CURLOPT_PROXYPASSWORD,
proxy_auth.password);
+ } else if (proxy_auth.authtype && proxy_auth.credential) {
+ curl_easy_setopt(result, CURLOPT_PROXYHEADER,
+ http_append_auth_header(&proxy_auth, NULL));
+ }
}
static void init_curl_proxy_auth(CURL *result)
{
if (proxy_auth.username) {
- if (!proxy_auth.password)
- credential_fill(&proxy_auth);
+ if (!proxy_auth.password && !proxy_auth.credential)
+ credential_fill(&proxy_auth, 1);
set_proxyauth_name_password(result);
}
@@ -626,7 +651,7 @@ static int has_cert_password(void)
cert_auth.host = xstrdup("");
cert_auth.username = xstrdup("");
cert_auth.path = xstrdup(ssl_cert);
- credential_fill(&cert_auth);
+ credential_fill(&cert_auth, 0);
}
return 1;
}
@@ -641,7 +666,7 @@ static int has_proxy_cert_password(void)
proxy_cert_auth.host = xstrdup("");
proxy_cert_auth.username = xstrdup("");
proxy_cert_auth.path = xstrdup(http_proxy_ssl_cert);
- credential_fill(&proxy_cert_auth);
+ credential_fill(&proxy_cert_auth, 0);
}
return 1;
}
@@ -1275,8 +1300,6 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
pragma_header = curl_slist_append(http_copy_default_headers(),
"Pragma: no-cache");
- no_pragma_header = curl_slist_append(http_copy_default_headers(),
- "Pragma:");
{
char *http_max_requests = getenv("GIT_HTTP_MAX_REQUESTS");
@@ -1360,9 +1383,6 @@ void http_cleanup(void)
curl_slist_free_all(pragma_header);
pragma_header = NULL;
- curl_slist_free_all(no_pragma_header);
- no_pragma_header = NULL;
-
curl_slist_free_all(host_resolutions);
host_resolutions = NULL;
@@ -1470,7 +1490,7 @@ struct active_request_slot *get_active_slot(void)
curl_easy_setopt(slot->curl, CURLOPT_IPRESOLVE, git_curl_ipresolve);
curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods);
- if (http_auth.password || curl_empty_auth_enabled())
+ if (http_auth.password || http_auth.credential || curl_empty_auth_enabled())
init_curl_http_auth(slot->curl);
return slot;
@@ -1759,7 +1779,12 @@ static int handle_curl_result(struct slot_results *results)
} else if (missing_target(results))
return HTTP_MISSING_TARGET;
else if (results->http_code == 401) {
- if (http_auth.username && http_auth.password) {
+ if ((http_auth.username && http_auth.password) ||\
+ (http_auth.authtype && http_auth.credential)) {
+ if (http_auth.multistage) {
+ credential_clear_secrets(&http_auth);
+ return HTTP_REAUTH;
+ }
credential_reject(&http_auth);
return HTTP_NOAUTH;
} else {
@@ -2067,11 +2092,15 @@ static int http_request(const char *url,
/* Add additional headers here */
if (options && options->extra_headers) {
const struct string_list_item *item;
- for_each_string_list_item(item, options->extra_headers) {
- headers = curl_slist_append(headers, item->string);
+ if (options && options->extra_headers) {
+ for_each_string_list_item(item, options->extra_headers) {
+ headers = curl_slist_append(headers, item->string);
+ }
}
}
+ headers = http_append_auth_header(&http_auth, headers);
+
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "");
@@ -2153,6 +2182,7 @@ static int http_request_reauth(const char *url,
void *result, int target,
struct http_get_options *options)
{
+ int i = 3;
int ret = http_request(url, result, target, options);
if (ret != HTTP_OK && ret != HTTP_REAUTH)
@@ -2166,35 +2196,35 @@ static int http_request_reauth(const char *url,
}
}
- if (ret != HTTP_REAUTH)
- return ret;
-
- /*
- * The previous request may have put cruft into our output stream; we
- * should clear it out before making our next request.
- */
- switch (target) {
- case HTTP_REQUEST_STRBUF:
- strbuf_reset(result);
- break;
- case HTTP_REQUEST_FILE:
- if (fflush(result)) {
- error_errno("unable to flush a file");
- return HTTP_START_FAILED;
- }
- rewind(result);
- if (ftruncate(fileno(result), 0) < 0) {
- error_errno("unable to truncate a file");
- return HTTP_START_FAILED;
+ while (ret == HTTP_REAUTH && --i) {
+ /*
+ * The previous request may have put cruft into our output stream; we
+ * should clear it out before making our next request.
+ */
+ switch (target) {
+ case HTTP_REQUEST_STRBUF:
+ strbuf_reset(result);
+ break;
+ case HTTP_REQUEST_FILE:
+ if (fflush(result)) {
+ error_errno("unable to flush a file");
+ return HTTP_START_FAILED;
+ }
+ rewind(result);
+ if (ftruncate(fileno(result), 0) < 0) {
+ error_errno("unable to truncate a file");
+ return HTTP_START_FAILED;
+ }
+ break;
+ default:
+ BUG("Unknown http_request target");
}
- break;
- default:
- BUG("Unknown http_request target");
- }
- credential_fill(&http_auth);
+ credential_fill(&http_auth, 1);
- return http_request(url, result, target, options);
+ ret = http_request(url, result, target, options);
+ }
+ return ret;
}
int http_get_strbuf(const char *url,
@@ -2371,6 +2401,7 @@ void release_http_pack_request(struct http_pack_request *preq)
}
preq->slot = NULL;
strbuf_release(&preq->tmpfile);
+ curl_slist_free_all(preq->headers);
free(preq->url);
free(preq);
}
@@ -2455,11 +2486,11 @@ struct http_pack_request *new_direct_http_pack_request(
}
preq->slot = get_active_slot();
+ preq->headers = object_request_headers();
curl_easy_setopt(preq->slot->curl, CURLOPT_WRITEDATA, preq->packfile);
curl_easy_setopt(preq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite);
curl_easy_setopt(preq->slot->curl, CURLOPT_URL, preq->url);
- curl_easy_setopt(preq->slot->curl, CURLOPT_HTTPHEADER,
- no_pragma_header);
+ curl_easy_setopt(preq->slot->curl, CURLOPT_HTTPHEADER, preq->headers);
/*
* If there is data present from a previous transfer attempt,
@@ -2625,13 +2656,14 @@ struct http_object_request *new_http_object_request(const char *base_url,
}
freq->slot = get_active_slot();
+ freq->headers = object_request_headers();
curl_easy_setopt(freq->slot->curl, CURLOPT_WRITEDATA, freq);
curl_easy_setopt(freq->slot->curl, CURLOPT_FAILONERROR, 0);
curl_easy_setopt(freq->slot->curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);
curl_easy_setopt(freq->slot->curl, CURLOPT_ERRORBUFFER, freq->errorstr);
curl_easy_setopt(freq->slot->curl, CURLOPT_URL, freq->url);
- curl_easy_setopt(freq->slot->curl, CURLOPT_HTTPHEADER, no_pragma_header);
+ curl_easy_setopt(freq->slot->curl, CURLOPT_HTTPHEADER, freq->headers);
/*
* If we have successfully processed data from a previous fetch
@@ -2719,5 +2751,6 @@ void release_http_object_request(struct http_object_request *freq)
release_active_slot(freq->slot);
freq->slot = NULL;
}
+ curl_slist_free_all(freq->headers);
strbuf_release(&freq->tmpfile);
}
diff --git a/http.h b/http.h
index 3af19a8bf5..a516ca4a9a 100644
--- a/http.h
+++ b/http.h
@@ -175,6 +175,9 @@ int http_get_file(const char *url, const char *filename,
int http_fetch_ref(const char *base, struct ref *ref);
+struct curl_slist *http_append_auth_header(const struct credential *c,
+ struct curl_slist *headers);
+
/* Helpers for fetching packs */
int http_get_info_packs(const char *base_url,
struct packed_git **packs_head);
@@ -196,6 +199,7 @@ struct http_pack_request {
FILE *packfile;
struct strbuf tmpfile;
struct active_request_slot *slot;
+ struct curl_slist *headers;
};
struct http_pack_request *new_http_pack_request(
@@ -229,6 +233,7 @@ struct http_object_request {
int zret;
int rename;
struct active_request_slot *slot;
+ struct curl_slist *headers;
};
struct http_object_request *new_http_object_request(
diff --git a/imap-send.c b/imap-send.c
index 0afd088d8a..c0130d0e02 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -917,7 +917,7 @@ static void server_fill_credential(struct imap_server_conf *srvc, struct credent
cred->username = xstrdup_or_null(srvc->user);
cred->password = xstrdup_or_null(srvc->pass);
- credential_fill(cred);
+ credential_fill(cred, 1);
if (!srvc->user)
srvc->user = xstrdup(cred->username);
diff --git a/khash.h b/khash.h
deleted file mode 100644
index ff88163177..0000000000
--- a/khash.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/* The MIT License
-
- Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk>
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-*/
-
-#ifndef __AC_KHASH_H
-#define __AC_KHASH_H
-
-#include "hash.h"
-
-#define AC_VERSION_KHASH_H "0.2.8"
-
-typedef uint32_t khint32_t;
-typedef uint64_t khint64_t;
-
-typedef khint32_t khint_t;
-typedef khint_t khiter_t;
-
-#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
-#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1)
-#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3)
-#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1)))
-#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1)))
-#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1)))
-#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1))
-
-#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4)
-
-#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
-
-static inline khint_t __ac_X31_hash_string(const char *s)
-{
- khint_t h = (khint_t)*s;
- if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s;
- return h;
-}
-
-#define kh_str_hash_func(key) __ac_X31_hash_string(key)
-#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
-
-static const double __ac_HASH_UPPER = 0.77;
-
-#define __KHASH_TYPE(name, khkey_t, khval_t) \
- typedef struct kh_##name { \
- khint_t n_buckets, size, n_occupied, upper_bound; \
- khint32_t *flags; \
- khkey_t *keys; \
- khval_t *vals; \
- } kh_##name##_t;
-
-#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \
- kh_##name##_t *kh_init_##name(void); \
- void kh_destroy_##name(kh_##name##_t *h); \
- void kh_clear_##name(kh_##name##_t *h); \
- khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \
- void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
- khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
- void kh_del_##name(kh_##name##_t *h, khint_t x);
-
-#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
- SCOPE kh_##name##_t *kh_init_##name(void) { \
- return (kh_##name##_t*)xcalloc(1, sizeof(kh_##name##_t)); \
- } \
- SCOPE void kh_release_##name(kh_##name##_t *h) \
- { \
- free(h->flags); \
- free((void *)h->keys); \
- free((void *)h->vals); \
- } \
- SCOPE void kh_destroy_##name(kh_##name##_t *h) \
- { \
- if (h) { \
- kh_release_##name(h); \
- free(h); \
- } \
- } \
- SCOPE void kh_clear_##name(kh_##name##_t *h) \
- { \
- if (h && h->flags) { \
- memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \
- h->size = h->n_occupied = 0; \
- } \
- } \
- SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \
- { \
- if (h->n_buckets) { \
- khint_t k, i, last, mask, step = 0; \
- mask = h->n_buckets - 1; \
- k = __hash_func(key); i = k & mask; \
- last = i; \
- while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
- i = (i + (++step)) & mask; \
- if (i == last) return h->n_buckets; \
- } \
- return __ac_iseither(h->flags, i)? h->n_buckets : i; \
- } else return 0; \
- } \
- SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
- { /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \
- khint32_t *new_flags = NULL; \
- khint_t j = 1; \
- { \
- kroundup32(new_n_buckets); \
- if (new_n_buckets < 4) new_n_buckets = 4; \
- if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \
- else { /* hash table size to be changed (shrink or expand); rehash */ \
- ALLOC_ARRAY(new_flags, __ac_fsize(new_n_buckets)); \
- memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
- if (h->n_buckets < new_n_buckets) { /* expand */ \
- REALLOC_ARRAY(h->keys, new_n_buckets); \
- if (kh_is_map) { \
- REALLOC_ARRAY(h->vals, new_n_buckets); \
- } \
- } /* otherwise shrink */ \
- } \
- } \
- if (j) { /* rehashing is needed */ \
- for (j = 0; j != h->n_buckets; ++j) { \
- if (__ac_iseither(h->flags, j) == 0) { \
- khkey_t key = h->keys[j]; \
- khval_t val; \
- khint_t new_mask; \
- new_mask = new_n_buckets - 1; \
- if (kh_is_map) val = h->vals[j]; \
- __ac_set_isdel_true(h->flags, j); \
- while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \
- khint_t k, i, step = 0; \
- k = __hash_func(key); \
- i = k & new_mask; \
- while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \
- __ac_set_isempty_false(new_flags, i); \
- if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \
- { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \
- if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \
- __ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \
- } else { /* write the element and jump out of the loop */ \
- h->keys[i] = key; \
- if (kh_is_map) h->vals[i] = val; \
- break; \
- } \
- } \
- } \
- } \
- if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \
- REALLOC_ARRAY(h->keys, new_n_buckets); \
- if (kh_is_map) REALLOC_ARRAY(h->vals, new_n_buckets); \
- } \
- free(h->flags); /* free the working space */ \
- h->flags = new_flags; \
- h->n_buckets = new_n_buckets; \
- h->n_occupied = h->size; \
- h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \
- } \
- } \
- SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \
- { \
- khint_t x; \
- if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \
- if (h->n_buckets > (h->size<<1)) { \
- kh_resize_##name(h, h->n_buckets - 1); /* clear "deleted" elements */ \
- } else { \
- kh_resize_##name(h, h->n_buckets + 1); /* expand the hash table */ \
- } \
- } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \
- { \
- khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \
- x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \
- if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \
- else { \
- last = i; \
- while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
- if (__ac_isdel(h->flags, i)) site = i; \
- i = (i + (++step)) & mask; \
- if (i == last) { x = site; break; } \
- } \
- if (x == h->n_buckets) { \
- if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \
- else x = i; \
- } \
- } \
- } \
- if (__ac_isempty(h->flags, x)) { /* not present at all */ \
- h->keys[x] = key; \
- __ac_set_isboth_false(h->flags, x); \
- ++h->size; ++h->n_occupied; \
- *ret = 1; \
- } else if (__ac_isdel(h->flags, x)) { /* deleted */ \
- h->keys[x] = key; \
- __ac_set_isboth_false(h->flags, x); \
- ++h->size; \
- *ret = 2; \
- } else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \
- return x; \
- } \
- SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \
- { \
- if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \
- __ac_set_isdel_true(h->flags, x); \
- --h->size; \
- } \
- }
-
-#define KHASH_DECLARE(name, khkey_t, khval_t) \
- __KHASH_TYPE(name, khkey_t, khval_t) \
- __KHASH_PROTOTYPES(name, khkey_t, khval_t)
-
-#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
- __KHASH_TYPE(name, khkey_t, khval_t) \
- __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
-
-#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
- KHASH_INIT2(name, MAYBE_UNUSED static inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
-
-/* Other convenient macros... */
-
-/*! @function
- @abstract Test whether a bucket contains data.
- @param h Pointer to the hash table [khash_t(name)*]
- @param x Iterator to the bucket [khint_t]
- @return 1 if containing data; 0 otherwise [int]
- */
-#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x)))
-
-/*! @function
- @abstract Get key given an iterator
- @param h Pointer to the hash table [khash_t(name)*]
- @param x Iterator to the bucket [khint_t]
- @return Key [type of keys]
- */
-#define kh_key(h, x) ((h)->keys[x])
-
-/*! @function
- @abstract Get value given an iterator
- @param h Pointer to the hash table [khash_t(name)*]
- @param x Iterator to the bucket [khint_t]
- @return Value [type of values]
- @discussion For hash sets, calling this results in segfault.
- */
-#define kh_val(h, x) ((h)->vals[x])
-
-/*! @function
- @abstract Alias of kh_val()
- */
-#define kh_value(h, x) ((h)->vals[x])
-
-/*! @function
- @abstract Get the start iterator
- @param h Pointer to the hash table [khash_t(name)*]
- @return The start iterator [khint_t]
- */
-#define kh_begin(h) (khint_t)(0)
-
-/*! @function
- @abstract Get the end iterator
- @param h Pointer to the hash table [khash_t(name)*]
- @return The end iterator [khint_t]
- */
-#define kh_end(h) ((h)->n_buckets)
-
-/*! @function
- @abstract Get the number of elements in the hash table
- @param h Pointer to the hash table [khash_t(name)*]
- @return Number of elements in the hash table [khint_t]
- */
-#define kh_size(h) ((h)->size)
-
-/*! @function
- @abstract Get the number of buckets in the hash table
- @param h Pointer to the hash table [khash_t(name)*]
- @return Number of buckets in the hash table [khint_t]
- */
-#define kh_n_buckets(h) ((h)->n_buckets)
-
-/*! @function
- @abstract Iterate over the entries in the hash table
- @param h Pointer to the hash table [khash_t(name)*]
- @param kvar Variable to which key will be assigned
- @param vvar Variable to which value will be assigned
- @param code Block of code to execute
- */
-#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \
- for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
- if (!kh_exist(h,__i)) continue; \
- (kvar) = kh_key(h,__i); \
- (vvar) = kh_val(h,__i); \
- code; \
- } }
-
-/*! @function
- @abstract Iterate over the values in the hash table
- @param h Pointer to the hash table [khash_t(name)*]
- @param vvar Variable to which value will be assigned
- @param code Block of code to execute
- */
-#define kh_foreach_value(h, vvar, code) { khint_t __i; \
- for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
- if (!kh_exist(h,__i)) continue; \
- (vvar) = kh_val(h,__i); \
- code; \
- } }
-
-static inline unsigned int oidhash_by_value(struct object_id oid)
-{
- return oidhash(&oid);
-}
-
-static inline int oideq_by_value(struct object_id a, struct object_id b)
-{
- return oideq(&a, &b);
-}
-
-KHASH_INIT(oid_set, struct object_id, int, 0, oidhash_by_value, oideq_by_value)
-
-KHASH_INIT(oid_map, struct object_id, void *, 1, oidhash_by_value, oideq_by_value)
-
-KHASH_INIT(oid_pos, struct object_id, int, 1, oidhash_by_value, oideq_by_value)
-
-#endif /* __AC_KHASH_H */
diff --git a/khashl.h b/khashl.h
new file mode 100644
index 0000000000..30f85dc5e2
--- /dev/null
+++ b/khashl.h
@@ -0,0 +1,522 @@
+/* The MIT License
+
+ Copyright (c) 2019-2023 by Attractive Chaos <attractor@live.co.uk>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#ifndef __AC_KHASHL_H
+#define __AC_KHASHL_H
+
+#include "hash.h"
+
+#define AC_VERSION_KHASHL_H "0.2"
+
+typedef uint32_t khint32_t;
+typedef uint64_t khint64_t;
+
+typedef khint32_t khint_t;
+typedef khint_t khiter_t;
+
+#define kh_inline inline /* portably handled elsewhere */
+#define KH_LOCAL static kh_inline MAYBE_UNUSED
+
+#ifndef kcalloc
+#define kcalloc(N,Z) xcalloc(N,Z)
+#endif
+#ifndef kfree
+#define kfree(P) free(P)
+#endif
+
+/****************************
+ * Simple private functions *
+ ****************************/
+
+#define __kh_used(flag, i) (flag[i>>5] >> (i&0x1fU) & 1U)
+#define __kh_set_used(flag, i) (flag[i>>5] |= 1U<<(i&0x1fU))
+#define __kh_set_unused(flag, i) (flag[i>>5] &= ~(1U<<(i&0x1fU)))
+
+#define __kh_fsize(m) ((m) < 32? 1 : (m)>>5)
+
+static kh_inline khint_t __kh_h2b(khint_t hash, khint_t bits) { return hash * 2654435769U >> (32 - bits); }
+
+/*******************
+ * Hash table base *
+ *******************/
+
+#define __KHASHL_TYPE(HType, khkey_t) \
+ typedef struct HType { \
+ khint_t bits, count; \
+ khint32_t *used; \
+ khkey_t *keys; \
+ } HType;
+
+#define __KHASHL_PROTOTYPES(HType, prefix, khkey_t) \
+ extern HType *prefix##_init(void); \
+ extern void prefix##_destroy(HType *h); \
+ extern void prefix##_clear(HType *h); \
+ extern khint_t prefix##_getp(const HType *h, const khkey_t *key); \
+ extern void prefix##_resize(HType *h, khint_t new_n_buckets); \
+ extern khint_t prefix##_putp(HType *h, const khkey_t *key, int *absent); \
+ extern void prefix##_del(HType *h, khint_t k);
+
+#define __KHASHL_IMPL_BASIC(SCOPE, HType, prefix) \
+ SCOPE HType *prefix##_init(void) { \
+ return (HType*)kcalloc(1, sizeof(HType)); \
+ } \
+ SCOPE void prefix##_release(HType *h) { \
+ kfree((void *)h->keys); kfree(h->used); \
+ } \
+ SCOPE void prefix##_destroy(HType *h) { \
+ if (!h) return; \
+ prefix##_release(h); \
+ kfree(h); \
+ } \
+ SCOPE void prefix##_clear(HType *h) { \
+ if (h && h->used) { \
+ khint_t n_buckets = (khint_t)1U << h->bits; \
+ memset(h->used, 0, __kh_fsize(n_buckets) * sizeof(khint32_t)); \
+ h->count = 0; \
+ } \
+ }
+
+#define __KHASHL_IMPL_GET(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \
+ SCOPE khint_t prefix##_getp_core(const HType *h, const khkey_t *key, khint_t hash) { \
+ khint_t i, last, n_buckets, mask; \
+ if (!h->keys) return 0; \
+ n_buckets = (khint_t)1U << h->bits; \
+ mask = n_buckets - 1U; \
+ i = last = __kh_h2b(hash, h->bits); \
+ while (__kh_used(h->used, i) && !__hash_eq(h->keys[i], *key)) { \
+ i = (i + 1U) & mask; \
+ if (i == last) return n_buckets; \
+ } \
+ return !__kh_used(h->used, i)? n_buckets : i; \
+ } \
+ SCOPE khint_t prefix##_getp(const HType *h, const khkey_t *key) { return prefix##_getp_core(h, key, __hash_fn(*key)); } \
+ SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { return prefix##_getp_core(h, &key, __hash_fn(key)); }
+
+#define __KHASHL_IMPL_RESIZE(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \
+ SCOPE void prefix##_resize(HType *h, khint_t new_n_buckets) { \
+ khint32_t *new_used = NULL; \
+ khint_t j = 0, x = new_n_buckets, n_buckets, new_bits, new_mask; \
+ while ((x >>= 1) != 0) ++j; \
+ if (new_n_buckets & (new_n_buckets - 1)) ++j; \
+ new_bits = j > 2? j : 2; \
+ new_n_buckets = (khint_t)1U << new_bits; \
+ if (h->count > (new_n_buckets>>1) + (new_n_buckets>>2)) return; /* noop, requested size is too small */ \
+ new_used = (khint32_t*)kcalloc(__kh_fsize(new_n_buckets), sizeof(khint32_t)); \
+ n_buckets = h->keys? (khint_t)1U<<h->bits : 0U; \
+ if (n_buckets < new_n_buckets) { /* expand */ \
+ REALLOC_ARRAY(h->keys, new_n_buckets); \
+ } /* otherwise shrink */ \
+ new_mask = new_n_buckets - 1; \
+ for (j = 0; j != n_buckets; ++j) { \
+ khkey_t key; \
+ if (!__kh_used(h->used, j)) continue; \
+ key = h->keys[j]; \
+ __kh_set_unused(h->used, j); \
+ while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \
+ khint_t i; \
+ i = __kh_h2b(__hash_fn(key), new_bits); \
+ while (__kh_used(new_used, i)) i = (i + 1) & new_mask; \
+ __kh_set_used(new_used, i); \
+ if (i < n_buckets && __kh_used(h->used, i)) { /* kick out the existing element */ \
+ { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \
+ __kh_set_unused(h->used, i); /* mark it as deleted in the old hash table */ \
+ } else { /* write the element and jump out of the loop */ \
+ h->keys[i] = key; \
+ break; \
+ } \
+ } \
+ } \
+ if (n_buckets > new_n_buckets) /* shrink the hash table */ \
+ REALLOC_ARRAY(h->keys, new_n_buckets); \
+ kfree(h->used); /* free the working space */ \
+ h->used = new_used, h->bits = new_bits; \
+ }
+
+#define __KHASHL_IMPL_PUT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \
+ SCOPE khint_t prefix##_putp_core(HType *h, const khkey_t *key, khint_t hash, int *absent) { \
+ khint_t n_buckets, i, last, mask; \
+ n_buckets = h->keys? (khint_t)1U<<h->bits : 0U; \
+ *absent = -1; \
+ if (h->count >= (n_buckets>>1) + (n_buckets>>2)) { /* rehashing */ \
+ prefix##_resize(h, n_buckets + 1U); \
+ n_buckets = (khint_t)1U<<h->bits; \
+ } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \
+ mask = n_buckets - 1; \
+ i = last = __kh_h2b(hash, h->bits); \
+ while (__kh_used(h->used, i) && !__hash_eq(h->keys[i], *key)) { \
+ i = (i + 1U) & mask; \
+ if (i == last) break; \
+ } \
+ if (!__kh_used(h->used, i)) { /* not present at all */ \
+ h->keys[i] = *key; \
+ __kh_set_used(h->used, i); \
+ ++h->count; \
+ *absent = 1; \
+ } else *absent = 0; /* Don't touch h->keys[i] if present */ \
+ return i; \
+ } \
+ SCOPE khint_t prefix##_putp(HType *h, const khkey_t *key, int *absent) { return prefix##_putp_core(h, key, __hash_fn(*key), absent); } \
+ SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { return prefix##_putp_core(h, &key, __hash_fn(key), absent); }
+
+#define __KHASHL_IMPL_DEL(SCOPE, HType, prefix, khkey_t, __hash_fn) \
+ SCOPE int prefix##_del(HType *h, khint_t i) { \
+ khint_t j = i, k, mask, n_buckets; \
+ if (!h->keys) return 0; \
+ n_buckets = (khint_t)1U<<h->bits; \
+ mask = n_buckets - 1U; \
+ while (1) { \
+ j = (j + 1U) & mask; \
+ if (j == i || !__kh_used(h->used, j)) break; /* j==i only when the table is completely full */ \
+ k = __kh_h2b(__hash_fn(h->keys[j]), h->bits); \
+ if ((j > i && (k <= i || k > j)) || (j < i && (k <= i && k > j))) \
+ h->keys[i] = h->keys[j], i = j; \
+ } \
+ __kh_set_unused(h->used, i); \
+ --h->count; \
+ return 1; \
+ }
+
+#define KHASHL_DECLARE(HType, prefix, khkey_t) \
+ __KHASHL_TYPE(HType, khkey_t) \
+ __KHASHL_PROTOTYPES(HType, prefix, khkey_t)
+
+/* compatibility wrappers to make khash -> khashl migration easier */
+#define __KHASH_COMPAT(SCOPE, HType, prefix, khkey_t) \
+ typedef HType HType##_t; \
+ SCOPE HType *kh_init_##prefix(void) { return prefix##_init(); } \
+ SCOPE void kh_release_##prefix(HType *h) { prefix##_release(h); } \
+ SCOPE void kh_destroy_##prefix(HType *h) { prefix##_destroy(h); } \
+ SCOPE void kh_clear_##prefix(HType *h) { prefix##_clear(h); } \
+ SCOPE khint_t kh_get_##prefix(const HType *h, khkey_t key) { \
+ return prefix##_get(h, key); \
+ } \
+ SCOPE void kh_resize_##prefix(HType *h, khint_t new_n_buckets) { \
+ prefix##_resize(h, new_n_buckets); \
+ } \
+ SCOPE khint_t kh_put_##prefix(HType *h, khkey_t key, int *absent) { \
+ return prefix##_put(h, key, absent); \
+ } \
+ SCOPE int kh_del_##prefix(HType *h, khint_t i) { \
+ return prefix##_del(h, i); \
+ }
+
+#define KHASHL_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \
+ __KHASHL_TYPE(HType, khkey_t) \
+ __KHASHL_IMPL_BASIC(SCOPE, HType, prefix) \
+ __KHASHL_IMPL_GET(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \
+ __KHASHL_IMPL_RESIZE(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \
+ __KHASHL_IMPL_PUT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \
+ __KHASHL_IMPL_DEL(SCOPE, HType, prefix, khkey_t, __hash_fn)
+
+/***************************
+ * Ensemble of hash tables *
+ ***************************/
+
+typedef struct {
+ khint_t sub, pos;
+} kh_ensitr_t;
+
+#define KHASHE_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \
+ KHASHL_INIT(KH_LOCAL, HType##_sub, prefix##_sub, khkey_t, __hash_fn, __hash_eq) \
+ typedef struct HType { \
+ khint64_t count:54, bits:8; \
+ HType##_sub *sub; \
+ } HType; \
+ SCOPE HType *prefix##_init(int bits) { \
+ HType *g; \
+ g = (HType*)kcalloc(1, sizeof(*g)); \
+ g->bits = bits; \
+ g->sub = (HType##_sub*)kcalloc(1U<<bits, sizeof(*g->sub)); \
+ return g; \
+ } \
+ SCOPE void prefix##_destroy(HType *g) { \
+ int t; \
+ if (!g) return; \
+ for (t = 0; t < 1<<g->bits; ++t) { kfree((void*)g->sub[t].keys); kfree(g->sub[t].used); } \
+ kfree(g->sub); kfree(g); \
+ } \
+ SCOPE kh_ensitr_t prefix##_getp(const HType *g, const khkey_t *key) { \
+ khint_t hash, low, ret; \
+ kh_ensitr_t r; \
+ HType##_sub *h; \
+ hash = __hash_fn(*key); \
+ low = hash & ((1U<<g->bits) - 1); \
+ h = &g->sub[low]; \
+ ret = prefix##_sub_getp_core(h, key, hash); \
+ if (ret >= kh_end(h)) r.sub = low, r.pos = (khint_t)-1; \
+ else r.sub = low, r.pos = ret; \
+ return r; \
+ } \
+ SCOPE kh_ensitr_t prefix##_get(const HType *g, const khkey_t key) { return prefix##_getp(g, &key); } \
+ SCOPE kh_ensitr_t prefix##_putp(HType *g, const khkey_t *key, int *absent) { \
+ khint_t hash, low, ret; \
+ kh_ensitr_t r; \
+ HType##_sub *h; \
+ hash = __hash_fn(*key); \
+ low = hash & ((1U<<g->bits) - 1); \
+ h = &g->sub[low]; \
+ ret = prefix##_sub_putp_core(h, key, hash, absent); \
+ if (*absent) ++g->count; \
+ if (ret == 1U<<h->bits) r.sub = low, r.pos = (khint_t)-1; \
+ else r.sub = low, r.pos = ret; \
+ return r; \
+ } \
+ SCOPE kh_ensitr_t prefix##_put(HType *g, const khkey_t key, int *absent) { return prefix##_putp(g, &key, absent); } \
+ SCOPE int prefix##_del(HType *g, kh_ensitr_t itr) { \
+ HType##_sub *h = &g->sub[itr.sub]; \
+ int ret; \
+ ret = prefix##_sub_del(h, itr.pos); \
+ if (ret) --g->count; \
+ return ret; \
+ }
+
+/*****************************
+ * More convenient interface *
+ *****************************/
+
+#define __kh_packed /* noop, we use -Werror=address-of-packed-member */
+#define __kh_cached_hash(x) ((x).hash)
+
+#define KHASHL_SET_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \
+ typedef struct { khkey_t key; } __kh_packed HType##_s_bucket_t; \
+ static kh_inline khint_t prefix##_s_hash(HType##_s_bucket_t x) { return __hash_fn(x.key); } \
+ static kh_inline int prefix##_s_eq(HType##_s_bucket_t x, HType##_s_bucket_t y) { return __hash_eq(x.key, y.key); } \
+ KHASHL_INIT(KH_LOCAL, HType, prefix##_s, HType##_s_bucket_t, prefix##_s_hash, prefix##_s_eq) \
+ SCOPE HType *prefix##_init(void) { return prefix##_s_init(); } \
+ SCOPE void prefix##_release(HType *h) { prefix##_s_release(h); } \
+ SCOPE void prefix##_destroy(HType *h) { prefix##_s_destroy(h); } \
+ SCOPE void prefix##_clear(HType *h) { prefix##_s_clear(h); } \
+ SCOPE void prefix##_resize(HType *h, khint_t new_n_buckets) { prefix##_s_resize(h, new_n_buckets); } \
+ SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_s_bucket_t t; t.key = key; return prefix##_s_getp(h, &t); } \
+ SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_s_del(h, k); } \
+ SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_s_bucket_t t; t.key = key; return prefix##_s_putp(h, &t, absent); } \
+ __KHASH_COMPAT(SCOPE, HType, prefix, khkey_t)
+
+#define KHASHL_MAP_INIT(SCOPE, HType, prefix, khkey_t, kh_val_t, __hash_fn, __hash_eq) \
+ typedef struct { khkey_t key; kh_val_t val; } __kh_packed HType##_m_bucket_t; \
+ static kh_inline khint_t prefix##_m_hash(HType##_m_bucket_t x) { return __hash_fn(x.key); } \
+ static kh_inline int prefix##_m_eq(HType##_m_bucket_t x, HType##_m_bucket_t y) { return __hash_eq(x.key, y.key); } \
+ KHASHL_INIT(KH_LOCAL, HType, prefix##_m, HType##_m_bucket_t, prefix##_m_hash, prefix##_m_eq) \
+ SCOPE HType *prefix##_init(void) { return prefix##_m_init(); } \
+ SCOPE void prefix##_release(HType *h) { prefix##_m_release(h); } \
+ SCOPE void prefix##_destroy(HType *h) { prefix##_m_destroy(h); } \
+ SCOPE void prefix##_clear(HType *h) { prefix##_m_clear(h); } \
+ SCOPE void prefix##_resize(HType *h, khint_t new_n_buckets) { prefix##_m_resize(h, new_n_buckets); } \
+ SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_m_bucket_t t; t.key = key; return prefix##_m_getp(h, &t); } \
+ SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_m_del(h, k); } \
+ SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_m_bucket_t t; t.key = key; return prefix##_m_putp(h, &t, absent); } \
+ __KHASH_COMPAT(SCOPE, HType, prefix, khkey_t)
+
+#define KHASHL_CSET_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \
+ typedef struct { khkey_t key; khint_t hash; } __kh_packed HType##_cs_bucket_t; \
+ static kh_inline int prefix##_cs_eq(HType##_cs_bucket_t x, HType##_cs_bucket_t y) { return x.hash == y.hash && __hash_eq(x.key, y.key); } \
+ KHASHL_INIT(KH_LOCAL, HType, prefix##_cs, HType##_cs_bucket_t, __kh_cached_hash, prefix##_cs_eq) \
+ SCOPE HType *prefix##_init(void) { return prefix##_cs_init(); } \
+ SCOPE void prefix##_destroy(HType *h) { prefix##_cs_destroy(h); } \
+ SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_cs_bucket_t t; t.key = key; t.hash = __hash_fn(key); return prefix##_cs_getp(h, &t); } \
+ SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_cs_del(h, k); } \
+ SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_cs_bucket_t t; t.key = key, t.hash = __hash_fn(key); return prefix##_cs_putp(h, &t, absent); }
+
+#define KHASHL_CMAP_INIT(SCOPE, HType, prefix, khkey_t, kh_val_t, __hash_fn, __hash_eq) \
+ typedef struct { khkey_t key; kh_val_t val; khint_t hash; } __kh_packed HType##_cm_bucket_t; \
+ static kh_inline int prefix##_cm_eq(HType##_cm_bucket_t x, HType##_cm_bucket_t y) { return x.hash == y.hash && __hash_eq(x.key, y.key); } \
+ KHASHL_INIT(KH_LOCAL, HType, prefix##_cm, HType##_cm_bucket_t, __kh_cached_hash, prefix##_cm_eq) \
+ SCOPE HType *prefix##_init(void) { return prefix##_cm_init(); } \
+ SCOPE void prefix##_destroy(HType *h) { prefix##_cm_destroy(h); } \
+ SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_cm_bucket_t t; t.key = key; t.hash = __hash_fn(key); return prefix##_cm_getp(h, &t); } \
+ SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_cm_del(h, k); } \
+ SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_cm_bucket_t t; t.key = key, t.hash = __hash_fn(key); return prefix##_cm_putp(h, &t, absent); }
+
+#define KHASHE_MAP_INIT(SCOPE, HType, prefix, khkey_t, kh_val_t, __hash_fn, __hash_eq) \
+ typedef struct { khkey_t key; kh_val_t val; } __kh_packed HType##_m_bucket_t; \
+ static kh_inline khint_t prefix##_m_hash(HType##_m_bucket_t x) { return __hash_fn(x.key); } \
+ static kh_inline int prefix##_m_eq(HType##_m_bucket_t x, HType##_m_bucket_t y) { return __hash_eq(x.key, y.key); } \
+ KHASHE_INIT(KH_LOCAL, HType, prefix##_m, HType##_m_bucket_t, prefix##_m_hash, prefix##_m_eq) \
+ SCOPE HType *prefix##_init(int bits) { return prefix##_m_init(bits); } \
+ SCOPE void prefix##_destroy(HType *h) { prefix##_m_destroy(h); } \
+ SCOPE kh_ensitr_t prefix##_get(const HType *h, khkey_t key) { HType##_m_bucket_t t; t.key = key; return prefix##_m_getp(h, &t); } \
+ SCOPE int prefix##_del(HType *h, kh_ensitr_t k) { return prefix##_m_del(h, k); } \
+ SCOPE kh_ensitr_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_m_bucket_t t; t.key = key; return prefix##_m_putp(h, &t, absent); }
+
+/**************************
+ * Public macro functions *
+ **************************/
+
+#define kh_bucket(h, x) ((h)->keys[x])
+
+/*! @function
+ @abstract Get the number of elements in the hash table
+ @param h Pointer to the hash table
+ @return Number of elements in the hash table [khint_t]
+ */
+#define kh_size(h) ((h)->count)
+
+#define kh_capacity(h) ((h)->keys? 1U<<(h)->bits : 0U)
+
+/*! @function
+ @abstract Get the end iterator
+ @param h Pointer to the hash table
+ @return The end iterator [khint_t]
+ */
+#define kh_end(h) kh_capacity(h)
+
+/*! @function
+ @abstract Get key given an iterator
+ @param h Pointer to the hash table
+ @param x Iterator to the bucket [khint_t]
+ @return Key [type of keys]
+ */
+#define kh_key(h, x) ((h)->keys[x].key)
+
+/*! @function
+ @abstract Get value given an iterator
+ @param h Pointer to the hash table
+ @param x Iterator to the bucket [khint_t]
+ @return Value [type of values]
+ @discussion For hash sets, calling this results in segfault.
+ */
+#define kh_val(h, x) ((h)->keys[x].val)
+
+/*! @function
+ @abstract Alias of kh_val()
+ */
+#define kh_value(h, x) kh_val(h, x)
+
+/*! @function
+ @abstract Test whether a bucket contains data.
+ @param h Pointer to the hash table
+ @param x Iterator to the bucket [khint_t]
+ @return 1 if containing data; 0 otherwise [int]
+ */
+#define kh_exist(h, x) __kh_used((h)->used, (x))
+
+#define kh_ens_key(g, x) kh_key(&(g)->sub[(x).sub], (x).pos)
+#define kh_ens_val(g, x) kh_val(&(g)->sub[(x).sub], (x).pos)
+#define kh_ens_exist(g, x) kh_exist(&(g)->sub[(x).sub], (x).pos)
+#define kh_ens_is_end(x) ((x).pos == (khint_t)-1)
+#define kh_ens_size(g) ((g)->count)
+
+/**************************************
+ * Common hash and equality functions *
+ **************************************/
+
+#define kh_eq_generic(a, b) ((a) == (b))
+#define kh_eq_str(a, b) (strcmp((a), (b)) == 0)
+#define kh_hash_dummy(x) ((khint_t)(x))
+
+static kh_inline khint_t kh_hash_uint32(khint_t key) {
+ key += ~(key << 15);
+ key ^= (key >> 10);
+ key += (key << 3);
+ key ^= (key >> 6);
+ key += ~(key << 11);
+ key ^= (key >> 16);
+ return key;
+}
+
+static kh_inline khint_t kh_hash_uint64(khint64_t key) {
+ key = ~key + (key << 21);
+ key = key ^ key >> 24;
+ key = (key + (key << 3)) + (key << 8);
+ key = key ^ key >> 14;
+ key = (key + (key << 2)) + (key << 4);
+ key = key ^ key >> 28;
+ key = key + (key << 31);
+ return (khint_t)key;
+}
+
+#define KH_FNV_SEED 11
+
+static kh_inline khint_t kh_hash_str(const char *s) { /* FNV1a */
+ khint_t h = KH_FNV_SEED ^ 2166136261U;
+ const unsigned char *t = (const unsigned char*)s;
+ for (; *t; ++t)
+ h ^= *t, h *= 16777619;
+ return h;
+}
+
+static kh_inline khint_t kh_hash_bytes(int len, const unsigned char *s) {
+ khint_t h = KH_FNV_SEED ^ 2166136261U;
+ int i;
+ for (i = 0; i < len; ++i)
+ h ^= s[i], h *= 16777619;
+ return h;
+}
+
+/*! @function
+ @abstract Get the start iterator
+ @param h Pointer to the hash table
+ @return The start iterator [khint_t]
+ */
+#define kh_begin(h) (khint_t)(0)
+
+/*! @function
+ @abstract Iterate over the entries in the hash table
+ @param h Pointer to the hash table
+ @param kvar Variable to which key will be assigned
+ @param vvar Variable to which value will be assigned
+ @param code Block of code to execute
+ */
+#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \
+ for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
+ if (!kh_exist(h,__i)) continue; \
+ (kvar) = kh_key(h,__i); \
+ (vvar) = kh_val(h,__i); \
+ code; \
+ } }
+
+/*! @function
+ @abstract Iterate over the values in the hash table
+ @param h Pointer to the hash table
+ @param vvar Variable to which value will be assigned
+ @param code Block of code to execute
+ */
+#define kh_foreach_value(h, vvar, code) { khint_t __i; \
+ for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \
+ if (!kh_exist(h,__i)) continue; \
+ (vvar) = kh_val(h,__i); \
+ code; \
+ } }
+
+static inline unsigned int oidhash_by_value(struct object_id oid)
+{
+ return oidhash(&oid);
+}
+
+static inline int oideq_by_value(struct object_id a, struct object_id b)
+{
+ return oideq(&a, &b);
+}
+
+KHASHL_SET_INIT(KH_LOCAL, kh_oid_set, oid_set, struct object_id,
+ oidhash_by_value, oideq_by_value)
+
+KHASHL_MAP_INIT(KH_LOCAL, kh_oid_map, oid_map, struct object_id, void *,
+ oidhash_by_value, oideq_by_value)
+
+KHASHL_MAP_INIT(KH_LOCAL, kh_oid_pos, oid_pos, struct object_id, int,
+ oidhash_by_value, oideq_by_value)
+
+#endif /* __AC_KHASHL_H */
diff --git a/list-objects-filter.c b/list-objects-filter.c
index 4346f8da45..440f112d23 100644
--- a/list-objects-filter.c
+++ b/list-objects-filter.c
@@ -704,7 +704,7 @@ static void filter_combine__free(void *filter_data)
for (sub = 0; sub < d->nr; sub++) {
list_objects_filter__free(d->sub[sub].filter);
oidset_clear(&d->sub[sub].seen);
- if (d->sub[sub].omits.set.size)
+ if (kh_size(&d->sub[sub].omits.set))
BUG("expected oidset to be cleared already");
}
free(d->sub);
diff --git a/log-tree.c b/log-tree.c
index 16031b44e7..41416de4e3 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -232,8 +232,10 @@ void load_ref_decorations(struct decoration_filter *filter, int flags)
}
decoration_loaded = 1;
decoration_flags = flags;
- for_each_ref(add_ref_decoration, filter);
- head_ref(add_ref_decoration, filter);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ add_ref_decoration, filter);
+ refs_head_ref(get_main_ref_store(the_repository),
+ add_ref_decoration, filter);
for_each_commit_graft(add_graft_decoration, filter);
}
}
@@ -277,7 +279,8 @@ static const struct name_decoration *current_pointed_by_HEAD(const struct name_d
return NULL;
/* Now resolve and find the matching current branch */
- branch_name = resolve_ref_unsafe("HEAD", 0, NULL, &rru_flags);
+ branch_name = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ "HEAD", 0, NULL, &rru_flags);
if (!branch_name || !(rru_flags & REF_ISSYMREF))
return NULL;
diff --git a/loose.h b/loose.h
index 2c2957072c..4f7915ed13 100644
--- a/loose.h
+++ b/loose.h
@@ -1,7 +1,7 @@
#ifndef LOOSE_H
#define LOOSE_H
-#include "khash.h"
+#include "khashl.h"
struct loose_object_map {
kh_oid_map_t *to_compat;
diff --git a/ls-refs.c b/ls-refs.c
index 819cbefee3..8e3ffff811 100644
--- a/ls-refs.c
+++ b/ls-refs.c
@@ -95,9 +95,11 @@ static int send_ref(const char *refname, const struct object_id *oid,
strbuf_addf(&data->buf, "unborn %s", refname_nons);
if (data->symrefs && flag & REF_ISSYMREF) {
struct object_id unused;
- const char *symref_target = resolve_ref_unsafe(refname, 0,
- &unused,
- &flag);
+ const char *symref_target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ refname,
+ 0,
+ &unused,
+ &flag);
if (!symref_target)
die("'%s' is a symref but it is not?", refname);
@@ -126,7 +128,7 @@ static void send_possibly_unborn_head(struct ls_refs_data *data)
int oid_is_null;
strbuf_addf(&namespaced, "%sHEAD", get_git_namespace());
- if (!resolve_ref_unsafe(namespaced.buf, 0, &oid, &flag))
+ if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), namespaced.buf, 0, &oid, &flag))
return; /* bad ref */
oid_is_null = is_null_oid(&oid);
if (!oid_is_null ||
diff --git a/mem-pool.c b/mem-pool.c
index 3065b12b23..a3ba38831d 100644
--- a/mem-pool.c
+++ b/mem-pool.c
@@ -4,6 +4,7 @@
#include "git-compat-util.h"
#include "mem-pool.h"
+#include "gettext.h"
#define BLOCK_GROWTH_SIZE (1024 * 1024 - sizeof(struct mp_block))
@@ -122,7 +123,7 @@ static char *mem_pool_strvfmt(struct mem_pool *pool, const char *fmt,
len = vsnprintf(next_free, available, fmt, cp);
va_end(cp);
if (len < 0)
- BUG("your vsnprintf is broken (returned %d)", len);
+ die(_("unable to format message: %s"), fmt);
size = st_add(len, 1); /* 1 for NUL */
ret = mem_pool_alloc(pool, size);
diff --git a/midx-write.c b/midx-write.c
index 65e69d2de7..8b826602c9 100644
--- a/midx-write.c
+++ b/midx-write.c
@@ -755,7 +755,8 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr
read_refs_snapshot(refs_snapshot, &revs);
} else {
setup_revisions(0, NULL, &revs, NULL);
- for_each_ref(add_ref_to_pending, &revs);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ add_ref_to_pending, &revs);
}
/*
@@ -819,6 +820,7 @@ static int write_midx_bitmap(const char *midx_name,
for (i = 0; i < pdata->nr_objects; i++)
index[i] = &pdata->objects[i].idx;
+ bitmap_writer_init(the_repository);
bitmap_writer_show_progress(flags & MIDX_PROGRESS);
bitmap_writer_build_type_index(pdata, index, pdata->nr_objects);
@@ -838,7 +840,7 @@ static int write_midx_bitmap(const char *midx_name,
for (i = 0; i < pdata->nr_objects; i++)
index[pack_order[i]] = &pdata->objects[i].idx;
- bitmap_writer_select_commits(commits, commits_nr, -1);
+ bitmap_writer_select_commits(commits, commits_nr);
ret = bitmap_writer_build(pdata);
if (ret < 0)
goto cleanup;
diff --git a/negotiator/default.c b/negotiator/default.c
index 9a5b696327..518b3c43b2 100644
--- a/negotiator/default.c
+++ b/negotiator/default.c
@@ -192,6 +192,7 @@ void default_negotiator_init(struct fetch_negotiator *negotiator)
ns->rev_list.compare = compare_commits_by_commit_date;
if (marked)
- for_each_ref(clear_marks, NULL);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ clear_marks, NULL);
marked = 1;
}
diff --git a/negotiator/skipping.c b/negotiator/skipping.c
index 5b91520430..b7e008c2fd 100644
--- a/negotiator/skipping.c
+++ b/negotiator/skipping.c
@@ -261,6 +261,7 @@ void skipping_negotiator_init(struct fetch_negotiator *negotiator)
data->rev_list.compare = compare;
if (marked)
- for_each_ref(clear_marks, NULL);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ clear_marks, NULL);
marked = 1;
}
diff --git a/notes-cache.c b/notes-cache.c
index 0e1d5b1ac7..038db01ca0 100644
--- a/notes-cache.c
+++ b/notes-cache.c
@@ -17,7 +17,7 @@ static int notes_cache_match_validity(struct repository *r,
struct strbuf msg = STRBUF_INIT;
int ret;
- if (read_ref(ref, &oid) < 0)
+ if (refs_read_ref(get_main_ref_store(the_repository), ref, &oid) < 0)
return 0;
commit = lookup_commit_reference_gently(r, &oid, 1);
@@ -66,8 +66,8 @@ int notes_cache_write(struct notes_cache *c)
if (commit_tree(c->validity, strlen(c->validity), &tree_oid, NULL,
&commit_oid, NULL, NULL) < 0)
return -1;
- if (update_ref("update notes cache", c->tree.update_ref, &commit_oid,
- NULL, 0, UPDATE_REFS_QUIET_ON_ERR) < 0)
+ if (refs_update_ref(get_main_ref_store(the_repository), "update notes cache", c->tree.update_ref, &commit_oid,
+ NULL, 0, UPDATE_REFS_QUIET_ON_ERR) < 0)
return -1;
return 0;
diff --git a/notes-merge.c b/notes-merge.c
index 51282934ae..6a9a139b12 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -562,7 +562,7 @@ int notes_merge(struct notes_merge_options *o,
o->local_ref, o->remote_ref);
/* Dereference o->local_ref into local_sha1 */
- if (read_ref_full(o->local_ref, 0, &local_oid, NULL))
+ if (refs_read_ref_full(get_main_ref_store(the_repository), o->local_ref, 0, &local_oid, NULL))
die("Failed to resolve local notes ref '%s'", o->local_ref);
else if (!check_refname_format(o->local_ref, 0) &&
is_null_oid(&local_oid))
diff --git a/notes-utils.c b/notes-utils.c
index 6197a5a455..e33aa86c4b 100644
--- a/notes-utils.c
+++ b/notes-utils.c
@@ -23,7 +23,7 @@ void create_notes_commit(struct repository *r,
if (!parents) {
/* Deduce parent commit from t->ref */
struct object_id parent_oid;
- if (!read_ref(t->ref, &parent_oid)) {
+ if (!refs_read_ref(get_main_ref_store(the_repository), t->ref, &parent_oid)) {
struct commit *parent = lookup_commit(r, &parent_oid);
if (repo_parse_commit(r, parent))
die("Failed to find/parse commit %s", t->ref);
@@ -55,8 +55,9 @@ void commit_notes(struct repository *r, struct notes_tree *t, const char *msg)
create_notes_commit(r, t, NULL, buf.buf, buf.len, &commit_oid);
strbuf_insertstr(&buf, 0, "notes: ");
- update_ref(buf.buf, t->update_ref, &commit_oid, NULL, 0,
- UPDATE_REFS_DIE_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository), buf.buf,
+ t->update_ref, &commit_oid, NULL, 0,
+ UPDATE_REFS_DIE_ON_ERR);
strbuf_release(&buf);
}
diff --git a/notes.c b/notes.c
index fed1eda80c..53ca25c814 100644
--- a/notes.c
+++ b/notes.c
@@ -945,7 +945,8 @@ void string_list_add_refs_by_glob(struct string_list *list, const char *glob)
{
assert(list->strdup_strings);
if (has_glob_specials(glob)) {
- for_each_glob_ref(string_list_add_one_ref, glob, list);
+ refs_for_each_glob_ref(get_main_ref_store(the_repository),
+ string_list_add_one_ref, glob, list);
} else {
struct object_id oid;
if (repo_get_oid(the_repository, glob, &oid))
@@ -1029,7 +1030,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
if (flags & NOTES_INIT_EMPTY ||
repo_get_oid_treeish(the_repository, notes_ref, &object_oid))
return;
- if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, &object_oid))
+ if (flags & NOTES_INIT_WRITABLE && refs_read_ref(get_main_ref_store(the_repository), notes_ref, &object_oid))
die("Cannot use notes ref %s", notes_ref);
if (get_tree_entry(the_repository, &object_oid, "", &oid, &mode))
die("Failed to read notes tree referenced by %s (%s)",
diff --git a/object-store-ll.h b/object-store-ll.h
index c5f2bb2fc2..0a99b85167 100644
--- a/object-store-ll.h
+++ b/object-store-ll.h
@@ -163,7 +163,7 @@ struct raw_object_store {
*/
struct object_directory *odb;
struct object_directory **odb_tail;
- struct kh_odb_path_map *odb_by_path;
+ struct odb_path_map *odb_by_path;
int loaded_alternates;
diff --git a/object-store.h b/object-store.h
index 1b3e3d7d01..3db4802e86 100644
--- a/object-store.h
+++ b/object-store.h
@@ -1,11 +1,12 @@
#ifndef OBJECT_STORE_H
#define OBJECT_STORE_H
-#include "khash.h"
+#include "khashl.h"
#include "dir.h"
#include "object-store-ll.h"
-KHASH_INIT(odb_path_map, const char * /* key: odb_path */,
- struct object_directory *, 1, fspathhash, fspatheq)
+KHASHL_MAP_INIT(KH_LOCAL, odb_path_map, odb_path_map,
+ const char * /* key: odb_path */, struct object_directory *,
+ fspathhash, fspatheq)
#endif /* OBJECT_STORE_H */
diff --git a/object.h b/object.h
index 9293e703cc..683d1897d3 100644
--- a/object.h
+++ b/object.h
@@ -62,7 +62,7 @@ void object_array_init(struct object_array *array);
/*
* object flag allocation:
- * revision.h: 0---------10 15 23------27
+ * revision.h: 0---------10 15 23------27
* fetch-pack.c: 01 67
* negotiator/default.c: 2--5
* walker.c: 0-2
@@ -75,6 +75,7 @@ void object_array_init(struct object_array *array);
* commit-reach.c: 16-----19
* sha1-name.c: 20
* list-objects-filter.c: 21
+ * bloom.c: 2122
* builtin/fsck.c: 0--3
* builtin/gc.c: 0
* builtin/index-pack.c: 2021
diff --git a/oidset.h b/oidset.h
index 262f4256d6..17af1b6708 100644
--- a/oidset.h
+++ b/oidset.h
@@ -1,7 +1,7 @@
#ifndef OIDSET_H
#define OIDSET_H
-#include "khash.h"
+#include "khashl.h"
/**
* This API is similar to oid-array, in that it maintains a set of object ids
diff --git a/oss-fuzz/fuzz-commit-graph.c b/oss-fuzz/fuzz-commit-graph.c
index 2992079dd9..c4e555fbe3 100644
--- a/oss-fuzz/fuzz-commit-graph.c
+++ b/oss-fuzz/fuzz-commit-graph.c
@@ -11,15 +11,17 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
struct commit_graph *g;
- initialize_the_repository();
+ initialize_repository(the_repository);
+
/*
* 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.
*/
+ repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
the_repository->settings.commit_graph_generation_version = 2;
- the_repository->settings.commit_graph_read_changed_paths = 1;
+ the_repository->settings.commit_graph_changed_paths_version = 1;
g = parse_commit_graph(&the_repository->settings, (void *)data, size);
repo_clear(the_repository);
free_commit_graph(g);
diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c
index c6c8f94cc5..f7245d7d6f 100644
--- a/pack-bitmap-write.c
+++ b/pack-bitmap-write.c
@@ -17,6 +17,12 @@
#include "trace2.h"
#include "tree.h"
#include "tree-walk.h"
+#include "pseudo-merge.h"
+#include "oid-array.h"
+#include "config.h"
+#include "alloc.h"
+#include "refs.h"
+#include "strmap.h"
struct bitmapped_commit {
struct commit *commit;
@@ -24,7 +30,7 @@ struct bitmapped_commit {
struct ewah_bitmap *write_as;
int flags;
int xor_offset;
- uint32_t commit_pos;
+ unsigned pseudo_merge : 1;
};
struct bitmap_writer {
@@ -39,6 +45,10 @@ struct bitmap_writer {
struct bitmapped_commit *selected;
unsigned int selected_nr, selected_alloc;
+ struct string_list pseudo_merge_groups;
+ kh_oid_map_t *pseudo_merge_commits; /* oid -> pseudo merge(s) */
+ uint32_t pseudo_merges_nr;
+
struct progress *progress;
int show_progress;
unsigned char pack_checksum[GIT_MAX_RAWSZ];
@@ -46,6 +56,21 @@ struct bitmap_writer {
static struct bitmap_writer writer;
+static inline int bitmap_writer_selected_nr(void)
+{
+ return writer.selected_nr - writer.pseudo_merges_nr;
+}
+
+void bitmap_writer_init(struct repository *r)
+{
+ writer.bitmaps = kh_init_oid_map();
+ writer.pseudo_merge_commits = kh_init_oid_map();
+
+ string_list_init_dup(&writer.pseudo_merge_groups);
+
+ load_pseudo_merges_from_config(&writer.pseudo_merge_groups);
+}
+
void bitmap_writer_show_progress(int show)
{
writer.show_progress = show;
@@ -111,20 +136,39 @@ void bitmap_writer_build_type_index(struct packing_data *to_pack,
}
}
+int bitmap_writer_has_bitmapped_object_id(const struct object_id *oid)
+{
+ return kh_get_oid_map(writer.bitmaps, *oid) != kh_end(writer.bitmaps);
+}
+
/**
* Compute the actual bitmaps
*/
-static inline void push_bitmapped_commit(struct commit *commit)
+void bitmap_writer_push_bitmapped_commit(struct commit *commit,
+ unsigned pseudo_merge)
{
if (writer.selected_nr >= writer.selected_alloc) {
writer.selected_alloc = (writer.selected_alloc + 32) * 2;
REALLOC_ARRAY(writer.selected, writer.selected_alloc);
}
+ if (!pseudo_merge) {
+ int hash_ret;
+ khiter_t hash_pos = kh_put_oid_map(writer.bitmaps,
+ commit->object.oid,
+ &hash_ret);
+
+ if (!hash_ret)
+ die(_("duplicate entry when writing bitmap index: %s"),
+ oid_to_hex(&commit->object.oid));
+ kh_value(writer.bitmaps, hash_pos) = NULL;
+ }
+
writer.selected[writer.selected_nr].commit = commit;
writer.selected[writer.selected_nr].bitmap = NULL;
writer.selected[writer.selected_nr].flags = 0;
+ writer.selected[writer.selected_nr].pseudo_merge = pseudo_merge;
writer.selected_nr++;
}
@@ -154,16 +198,20 @@ static void compute_xor_offsets(void)
while (next < writer.selected_nr) {
struct bitmapped_commit *stored = &writer.selected[next];
-
int best_offset = 0;
struct ewah_bitmap *best_bitmap = stored->bitmap;
struct ewah_bitmap *test_xor;
+ if (stored->pseudo_merge)
+ goto next;
+
for (i = 1; i <= MAX_XOR_OFFSET_SEARCH; ++i) {
int curr = next - i;
if (curr < 0)
break;
+ if (writer.selected[curr].pseudo_merge)
+ continue;
test_xor = ewah_pool_new();
ewah_xor(writer.selected[curr].bitmap, stored->bitmap, test_xor);
@@ -179,6 +227,7 @@ static void compute_xor_offsets(void)
}
}
+next:
stored->xor_offset = best_offset;
stored->write_as = best_bitmap;
@@ -191,7 +240,8 @@ struct bb_commit {
struct bitmap *commit_mask;
struct bitmap *bitmap;
unsigned selected:1,
- maximal:1;
+ maximal:1,
+ pseudo_merge:1;
unsigned idx; /* within selected array */
};
@@ -229,17 +279,18 @@ static void bitmap_builder_init(struct bitmap_builder *bb,
revs.first_parent_only = 1;
for (i = 0; i < writer->selected_nr; i++) {
- struct commit *c = writer->selected[i].commit;
- struct bb_commit *ent = bb_data_at(&bb->data, c);
+ struct bitmapped_commit *bc = &writer->selected[i];
+ struct bb_commit *ent = bb_data_at(&bb->data, bc->commit);
ent->selected = 1;
ent->maximal = 1;
+ ent->pseudo_merge = bc->pseudo_merge;
ent->idx = i;
ent->commit_mask = bitmap_new();
bitmap_set(ent->commit_mask, i);
- add_pending_object(&revs, &c->object, "");
+ add_pending_object(&revs, &bc->commit->object, "");
}
if (prepare_revision_walk(&revs))
@@ -396,6 +447,7 @@ static int fill_bitmap_tree(struct bitmap *bitmap,
}
static int reused_bitmaps_nr;
+static int reused_pseudo_merge_bitmaps_nr;
static int fill_bitmap_commit(struct bb_commit *ent,
struct commit *commit,
@@ -416,8 +468,13 @@ static int fill_bitmap_commit(struct bb_commit *ent,
struct commit *c = prio_queue_get(queue);
if (old_bitmap && mapping) {
- struct ewah_bitmap *old = bitmap_for_commit(old_bitmap, c);
+ struct ewah_bitmap *old;
struct bitmap *remapped = bitmap_new();
+
+ if (commit->object.flags & BITMAP_PSEUDO_MERGE)
+ old = pseudo_merge_bitmap_for_commit(old_bitmap, c);
+ else
+ old = bitmap_for_commit(old_bitmap, c);
/*
* If this commit has an old bitmap, then translate that
* bitmap and add its bits to this one. No need to walk
@@ -426,7 +483,10 @@ static int fill_bitmap_commit(struct bb_commit *ent,
if (old && !rebuild_bitmap(mapping, old, remapped)) {
bitmap_or(ent->bitmap, remapped);
bitmap_free(remapped);
- reused_bitmaps_nr++;
+ if (commit->object.flags & BITMAP_PSEUDO_MERGE)
+ reused_pseudo_merge_bitmaps_nr++;
+ else
+ reused_bitmaps_nr++;
continue;
}
bitmap_free(remapped);
@@ -436,12 +496,14 @@ static int fill_bitmap_commit(struct bb_commit *ent,
* Mark ourselves and queue our tree. The commit
* walk ensures we cover all parents.
*/
- pos = find_object_pos(&c->object.oid, &found);
- if (!found)
- return -1;
- bitmap_set(ent->bitmap, pos);
- prio_queue_put(tree_queue,
- repo_get_commit_tree(the_repository, c));
+ if (!(c->object.flags & BITMAP_PSEUDO_MERGE)) {
+ pos = find_object_pos(&c->object.oid, &found);
+ if (!found)
+ return -1;
+ bitmap_set(ent->bitmap, pos);
+ prio_queue_put(tree_queue,
+ repo_get_commit_tree(the_repository, c));
+ }
for (p = c->parents; p; p = p->next) {
pos = find_object_pos(&p->item->object.oid, &found);
@@ -466,14 +528,17 @@ static void store_selected(struct bb_commit *ent, struct commit *commit)
{
struct bitmapped_commit *stored = &writer.selected[ent->idx];
khiter_t hash_pos;
- int hash_ret;
stored->bitmap = bitmap_to_ewah(ent->bitmap);
- hash_pos = kh_put_oid_map(writer.bitmaps, commit->object.oid, &hash_ret);
- if (hash_ret == 0)
- die("Duplicate entry when writing index: %s",
+ if (ent->pseudo_merge)
+ return;
+
+ hash_pos = kh_get_oid_map(writer.bitmaps, commit->object.oid);
+ if (hash_pos == kh_end(writer.bitmaps))
+ die(_("attempted to store non-selected commit: '%s'"),
oid_to_hex(&commit->object.oid));
+
kh_value(writer.bitmaps, hash_pos) = stored;
}
@@ -488,7 +553,6 @@ int bitmap_writer_build(struct packing_data *to_pack)
uint32_t *mapping;
int closed = 1; /* until proven otherwise */
- writer.bitmaps = kh_init_oid_map();
writer.to_pack = to_pack;
if (writer.show_progress)
@@ -548,6 +612,9 @@ int bitmap_writer_build(struct packing_data *to_pack)
the_repository);
trace2_data_intmax("pack-bitmap-write", the_repository,
"building_bitmaps_reused", reused_bitmaps_nr);
+ trace2_data_intmax("pack-bitmap-write", the_repository,
+ "building_bitmaps_pseudo_merge_reused",
+ reused_pseudo_merge_bitmaps_nr);
stop_progress(&writer.progress);
@@ -591,8 +658,7 @@ static int date_compare(const void *_a, const void *_b)
}
void bitmap_writer_select_commits(struct commit **indexed_commits,
- unsigned int indexed_commits_nr,
- int max_bitmaps)
+ unsigned int indexed_commits_nr)
{
unsigned int i = 0, j, next;
@@ -600,7 +666,7 @@ void bitmap_writer_select_commits(struct commit **indexed_commits,
if (indexed_commits_nr < 100) {
for (i = 0; i < indexed_commits_nr; ++i)
- push_bitmapped_commit(indexed_commits[i]);
+ bitmap_writer_push_bitmapped_commit(indexed_commits[i], 0);
return;
}
@@ -615,11 +681,6 @@ void bitmap_writer_select_commits(struct commit **indexed_commits,
if (i + next >= indexed_commits_nr)
break;
- if (max_bitmaps > 0 && writer.selected_nr >= max_bitmaps) {
- writer.selected_nr = max_bitmaps;
- break;
- }
-
if (next == 0) {
chosen = indexed_commits[i];
} else {
@@ -638,13 +699,19 @@ void bitmap_writer_select_commits(struct commit **indexed_commits,
}
}
- push_bitmapped_commit(chosen);
+ bitmap_writer_push_bitmapped_commit(chosen, 0);
i += next + 1;
display_progress(writer.progress, i);
}
stop_progress(&writer.progress);
+
+ select_pseudo_merges(&writer.pseudo_merge_groups,
+ indexed_commits, indexed_commits_nr,
+ writer.pseudo_merge_commits,
+ &writer.pseudo_merges_nr,
+ writer.show_progress);
}
@@ -676,8 +743,11 @@ static void write_selected_commits_v1(struct hashfile *f,
{
int i;
- for (i = 0; i < writer.selected_nr; ++i) {
+ for (i = 0; i < bitmap_writer_selected_nr(); ++i) {
struct bitmapped_commit *stored = &writer.selected[i];
+ if (stored->pseudo_merge)
+ BUG("unexpected pseudo-merge among selected: %s",
+ oid_to_hex(&stored->commit->object.oid));
if (offsets)
offsets[i] = hashfile_total(f);
@@ -690,6 +760,127 @@ static void write_selected_commits_v1(struct hashfile *f,
}
}
+static void write_pseudo_merges(struct hashfile *f)
+{
+ struct oid_array commits = OID_ARRAY_INIT;
+ struct bitmap **commits_bitmap = NULL;
+ off_t *pseudo_merge_ofs = NULL;
+ off_t start, table_start, next_ext;
+
+ uint32_t base = bitmap_writer_selected_nr();
+ size_t i, j = 0;
+
+ CALLOC_ARRAY(commits_bitmap, writer.pseudo_merges_nr);
+ CALLOC_ARRAY(pseudo_merge_ofs, writer.pseudo_merges_nr);
+
+ for (i = 0; i < writer.pseudo_merges_nr; i++) {
+ struct bitmapped_commit *merge = &writer.selected[base + i];
+ struct commit_list *p;
+
+ if (!merge->pseudo_merge)
+ BUG("found non-pseudo merge commit at %"PRIuMAX, (uintmax_t)i);
+
+ commits_bitmap[i] = bitmap_new();
+
+ for (p = merge->commit->parents; p; p = p->next)
+ bitmap_set(commits_bitmap[i],
+ find_object_pos(&p->item->object.oid, NULL));
+ }
+
+ start = hashfile_total(f);
+
+ for (i = 0; i < writer.pseudo_merges_nr; i++) {
+ struct ewah_bitmap *commits_ewah = bitmap_to_ewah(commits_bitmap[i]);
+
+ pseudo_merge_ofs[i] = hashfile_total(f);
+
+ dump_bitmap(f, commits_ewah);
+ dump_bitmap(f, writer.selected[base+i].write_as);
+
+ ewah_free(commits_ewah);
+ }
+
+ next_ext = st_add(hashfile_total(f),
+ st_mult(kh_size(writer.pseudo_merge_commits),
+ sizeof(uint64_t)));
+
+ table_start = hashfile_total(f);
+
+ commits.alloc = kh_size(writer.pseudo_merge_commits);
+ CALLOC_ARRAY(commits.oid, commits.alloc);
+
+ for (i = kh_begin(writer.pseudo_merge_commits); i != kh_end(writer.pseudo_merge_commits); i++) {
+ if (!kh_exist(writer.pseudo_merge_commits, i))
+ continue;
+ oid_array_append(&commits, &kh_key(writer.pseudo_merge_commits, i));
+ }
+
+ oid_array_sort(&commits);
+
+ /* write lookup table (non-extended) */
+ for (i = 0; i < commits.nr; i++) {
+ int hash_pos;
+ struct pseudo_merge_commit_idx *c;
+
+ hash_pos = kh_get_oid_map(writer.pseudo_merge_commits,
+ commits.oid[i]);
+ if (hash_pos == kh_end(writer.pseudo_merge_commits))
+ BUG("could not find pseudo-merge commit %s",
+ oid_to_hex(&commits.oid[i]));
+
+ c = kh_value(writer.pseudo_merge_commits, hash_pos);
+
+ hashwrite_be32(f, find_object_pos(&commits.oid[i], NULL));
+ if (c->nr == 1)
+ hashwrite_be64(f, pseudo_merge_ofs[c->pseudo_merge[0]]);
+ else if (c->nr > 1) {
+ if (next_ext & ((uint64_t)1<<63))
+ die(_("too many pseudo-merges"));
+ hashwrite_be64(f, next_ext | ((uint64_t)1<<63));
+ next_ext = st_add3(next_ext,
+ sizeof(uint32_t),
+ st_mult(c->nr, sizeof(uint64_t)));
+ } else
+ BUG("expected commit '%s' to have at least one "
+ "pseudo-merge", oid_to_hex(&commits.oid[i]));
+ }
+
+ /* write lookup table (extended) */
+ for (i = 0; i < commits.nr; i++) {
+ int hash_pos;
+ struct pseudo_merge_commit_idx *c;
+
+ hash_pos = kh_get_oid_map(writer.pseudo_merge_commits,
+ commits.oid[i]);
+ if (hash_pos == kh_end(writer.pseudo_merge_commits))
+ BUG("could not find pseudo-merge commit %s",
+ oid_to_hex(&commits.oid[i]));
+
+ c = kh_value(writer.pseudo_merge_commits, hash_pos);
+ if (c->nr == 1)
+ continue;
+
+ hashwrite_be32(f, c->nr);
+ for (j = 0; j < c->nr; j++)
+ hashwrite_be64(f, pseudo_merge_ofs[c->pseudo_merge[j]]);
+ }
+
+ /* write positions for all pseudo merges */
+ for (i = 0; i < writer.pseudo_merges_nr; i++)
+ hashwrite_be64(f, pseudo_merge_ofs[i]);
+
+ hashwrite_be32(f, writer.pseudo_merges_nr);
+ hashwrite_be32(f, kh_size(writer.pseudo_merge_commits));
+ hashwrite_be64(f, table_start - start);
+ hashwrite_be64(f, hashfile_total(f) - start + sizeof(uint64_t));
+
+ for (i = 0; i < writer.pseudo_merges_nr; i++)
+ bitmap_free(commits_bitmap[i]);
+
+ free(pseudo_merge_ofs);
+ free(commits_bitmap);
+}
+
static int table_cmp(const void *_va, const void *_vb, void *_data)
{
uint32_t *commit_positions = _data;
@@ -711,10 +902,10 @@ static void write_lookup_table(struct hashfile *f,
uint32_t i;
uint32_t *table, *table_inv;
- ALLOC_ARRAY(table, writer.selected_nr);
- ALLOC_ARRAY(table_inv, writer.selected_nr);
+ ALLOC_ARRAY(table, bitmap_writer_selected_nr());
+ ALLOC_ARRAY(table_inv, bitmap_writer_selected_nr());
- for (i = 0; i < writer.selected_nr; i++)
+ for (i = 0; i < bitmap_writer_selected_nr(); i++)
table[i] = i;
/*
@@ -722,16 +913,16 @@ static void write_lookup_table(struct hashfile *f,
* bitmap corresponds to j'th bitmapped commit (among the selected
* commits) in lex order of OIDs.
*/
- QSORT_S(table, writer.selected_nr, table_cmp, commit_positions);
+ QSORT_S(table, bitmap_writer_selected_nr(), table_cmp, commit_positions);
/* table_inv helps us discover that relationship (i'th bitmap
* to j'th commit by j = table_inv[i])
*/
- for (i = 0; i < writer.selected_nr; i++)
+ for (i = 0; i < bitmap_writer_selected_nr(); i++)
table_inv[table[i]] = i;
trace2_region_enter("pack-bitmap-write", "writing_lookup_table", the_repository);
- for (i = 0; i < writer.selected_nr; i++) {
+ for (i = 0; i < bitmap_writer_selected_nr(); i++) {
struct bitmapped_commit *selected = &writer.selected[table[i]];
uint32_t xor_offset = selected->xor_offset;
uint32_t xor_row;
@@ -797,12 +988,15 @@ void bitmap_writer_finish(struct pack_idx_entry **index,
int fd = odb_mkstemp(&tmp_file, "pack/tmp_bitmap_XXXXXX");
+ if (writer.pseudo_merges_nr)
+ options |= BITMAP_OPT_PSEUDO_MERGES;
+
f = hashfd(fd, tmp_file.buf);
memcpy(header.magic, BITMAP_IDX_SIGNATURE, sizeof(BITMAP_IDX_SIGNATURE));
header.version = htons(default_version);
header.options = htons(flags | options);
- header.entry_count = htonl(writer.selected_nr);
+ header.entry_count = htonl(bitmap_writer_selected_nr());
hashcpy(header.checksum, writer.pack_checksum);
hashwrite(f, &header, sizeof(header) - GIT_MAX_RAWSZ + the_hash_algo->rawsz);
@@ -814,9 +1008,9 @@ void bitmap_writer_finish(struct pack_idx_entry **index,
if (options & BITMAP_OPT_LOOKUP_TABLE)
CALLOC_ARRAY(offsets, index_nr);
- ALLOC_ARRAY(commit_positions, writer.selected_nr);
+ ALLOC_ARRAY(commit_positions, bitmap_writer_selected_nr());
- for (i = 0; i < writer.selected_nr; i++) {
+ for (i = 0; i < bitmap_writer_selected_nr(); i++) {
struct bitmapped_commit *stored = &writer.selected[i];
int commit_pos = oid_pos(&stored->commit->object.oid, index, index_nr, oid_access);
@@ -828,6 +1022,9 @@ void bitmap_writer_finish(struct pack_idx_entry **index,
write_selected_commits_v1(f, commit_positions, offsets);
+ if (options & BITMAP_OPT_PSEUDO_MERGES)
+ write_pseudo_merges(f);
+
if (options & BITMAP_OPT_LOOKUP_TABLE)
write_lookup_table(f, commit_positions, offsets);
diff --git a/pack-bitmap.c b/pack-bitmap.c
index 35c5ef9d3c..70230e2647 100644
--- a/pack-bitmap.c
+++ b/pack-bitmap.c
@@ -20,6 +20,7 @@
#include "list-objects-filter-options.h"
#include "midx.h"
#include "config.h"
+#include "pseudo-merge.h"
/*
* An entry on the bitmap index, representing the bitmap for a given
@@ -86,6 +87,9 @@ struct bitmap_index {
*/
unsigned char *table_lookup;
+ /* This contains the pseudo-merge cache within 'map' (if found). */
+ struct pseudo_merge_map pseudo_merges;
+
/*
* Extended index.
*
@@ -110,6 +114,13 @@ struct bitmap_index {
unsigned int version;
};
+static int pseudo_merges_satisfied_nr;
+static int pseudo_merges_cascades_nr;
+static int existing_bitmaps_hits_nr;
+static int existing_bitmaps_misses_nr;
+static int roots_with_bitmaps_nr;
+static int roots_without_bitmaps_nr;
+
static struct ewah_bitmap *lookup_stored_bitmap(struct stored_bitmap *st)
{
struct ewah_bitmap *parent;
@@ -129,17 +140,13 @@ static struct ewah_bitmap *lookup_stored_bitmap(struct stored_bitmap *st)
return composed;
}
-/*
- * Read a bitmap from the current read position on the mmaped
- * index, and increase the read position accordingly
- */
-static struct ewah_bitmap *read_bitmap_1(struct bitmap_index *index)
+struct ewah_bitmap *read_bitmap(const unsigned char *map,
+ size_t map_size, size_t *map_pos)
{
struct ewah_bitmap *b = ewah_pool_new();
- ssize_t bitmap_size = ewah_read_mmap(b,
- index->map + index->map_pos,
- index->map_size - index->map_pos);
+ ssize_t bitmap_size = ewah_read_mmap(b, map + *map_pos,
+ map_size - *map_pos);
if (bitmap_size < 0) {
error(_("failed to load bitmap index (corrupted?)"));
@@ -147,10 +154,20 @@ static struct ewah_bitmap *read_bitmap_1(struct bitmap_index *index)
return NULL;
}
- index->map_pos += bitmap_size;
+ *map_pos += bitmap_size;
+
return b;
}
+/*
+ * Read a bitmap from the current read position on the mmaped
+ * index, and increase the read position accordingly
+ */
+static struct ewah_bitmap *read_bitmap_1(struct bitmap_index *index)
+{
+ return read_bitmap(index->map, index->map_size, &index->map_pos);
+}
+
static uint32_t bitmap_num_objects(struct bitmap_index *index)
{
if (index->midx)
@@ -199,6 +216,41 @@ static int load_bitmap_header(struct bitmap_index *index)
index->table_lookup = (void *)(index_end - table_size);
index_end -= table_size;
}
+
+ if (flags & BITMAP_OPT_PSEUDO_MERGES) {
+ unsigned char *pseudo_merge_ofs;
+ size_t table_size;
+ uint32_t i;
+
+ if (sizeof(table_size) > index_end - index->map - header_size)
+ return error(_("corrupted bitmap index file (too short to fit pseudo-merge table header)"));
+
+ table_size = get_be64(index_end - 8);
+ if (table_size > index_end - index->map - header_size)
+ return error(_("corrupted bitmap index file (too short to fit pseudo-merge table)"));
+
+ if (git_env_bool("GIT_TEST_USE_PSEUDO_MERGES", 1)) {
+ const unsigned char *ext = (index_end - table_size);
+
+ index->pseudo_merges.map = index->map;
+ index->pseudo_merges.map_size = index->map_size;
+ index->pseudo_merges.commits = ext + get_be64(index_end - 16);
+ index->pseudo_merges.commits_nr = get_be32(index_end - 20);
+ index->pseudo_merges.nr = get_be32(index_end - 24);
+
+ CALLOC_ARRAY(index->pseudo_merges.v,
+ index->pseudo_merges.nr);
+
+ pseudo_merge_ofs = index_end - 24 -
+ (index->pseudo_merges.nr * sizeof(uint64_t));
+ for (i = 0; i < index->pseudo_merges.nr; i++) {
+ index->pseudo_merges.v[i].at = get_be64(pseudo_merge_ofs);
+ pseudo_merge_ofs += sizeof(uint64_t);
+ }
+ }
+
+ index_end -= table_size;
+ }
}
index->entry_count = ntohl(header->entry_count);
@@ -961,6 +1013,22 @@ static void show_commit(struct commit *commit UNUSED,
{
}
+static unsigned apply_pseudo_merges_for_commit_1(struct bitmap_index *bitmap_git,
+ struct bitmap *result,
+ struct commit *commit,
+ uint32_t commit_pos)
+{
+ int ret;
+
+ ret = apply_pseudo_merges_for_commit(&bitmap_git->pseudo_merges,
+ result, commit, commit_pos);
+
+ if (ret)
+ pseudo_merges_satisfied_nr += ret;
+
+ return ret;
+}
+
static int add_to_include_set(struct bitmap_index *bitmap_git,
struct include_data *data,
struct commit *commit,
@@ -976,11 +1044,19 @@ static int add_to_include_set(struct bitmap_index *bitmap_git,
partial = bitmap_for_commit(bitmap_git, commit);
if (partial) {
+ existing_bitmaps_hits_nr++;
+
bitmap_or_ewah(data->base, partial);
return 0;
}
+ existing_bitmaps_misses_nr++;
+
bitmap_set(data->base, bitmap_pos);
+ if (apply_pseudo_merges_for_commit_1(bitmap_git, data->base, commit,
+ bitmap_pos))
+ return 0;
+
return 1;
}
@@ -1031,8 +1107,12 @@ static int add_commit_to_bitmap(struct bitmap_index *bitmap_git,
{
struct ewah_bitmap *or_with = bitmap_for_commit(bitmap_git, commit);
- if (!or_with)
+ if (!or_with) {
+ existing_bitmaps_misses_nr++;
return 0;
+ }
+
+ existing_bitmaps_hits_nr++;
if (!*base)
*base = ewah_to_bitmap(or_with);
@@ -1106,6 +1186,20 @@ static void show_boundary_object(struct object *object UNUSED,
BUG("should not be called");
}
+static unsigned cascade_pseudo_merges_1(struct bitmap_index *bitmap_git,
+ struct bitmap *result,
+ struct bitmap *roots)
+{
+ int ret = cascade_pseudo_merges(&bitmap_git->pseudo_merges,
+ result, roots);
+ if (ret) {
+ pseudo_merges_cascades_nr++;
+ pseudo_merges_satisfied_nr += ret;
+ }
+
+ return ret;
+}
+
static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
struct rev_info *revs,
struct object_list *roots)
@@ -1115,6 +1209,7 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
unsigned int i;
unsigned int tmp_blobs, tmp_trees, tmp_tags;
int any_missing = 0;
+ int existing_bitmaps = 0;
cb.bitmap_git = bitmap_git;
cb.base = bitmap_new();
@@ -1122,6 +1217,25 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
revs->ignore_missing_links = 1;
+ if (bitmap_git->pseudo_merges.nr) {
+ struct bitmap *roots_bitmap = bitmap_new();
+ struct object_list *objects = NULL;
+
+ for (objects = roots; objects; objects = objects->next) {
+ struct object *object = objects->item;
+ int pos;
+
+ pos = bitmap_position(bitmap_git, &object->oid);
+ if (pos < 0)
+ continue;
+
+ bitmap_set(roots_bitmap, pos);
+ }
+
+ if (!cascade_pseudo_merges_1(bitmap_git, cb.base, roots_bitmap))
+ bitmap_free(roots_bitmap);
+ }
+
/*
* OR in any existing reachability bitmaps among `roots` into
* `cb.base`.
@@ -1133,8 +1247,10 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
continue;
if (add_commit_to_bitmap(bitmap_git, &cb.base,
- (struct commit *)object))
+ (struct commit *)object)) {
+ existing_bitmaps = 1;
continue;
+ }
any_missing = 1;
}
@@ -1142,6 +1258,9 @@ static struct bitmap *find_boundary_objects(struct bitmap_index *bitmap_git,
if (!any_missing)
goto cleanup;
+ if (existing_bitmaps)
+ cascade_pseudo_merges_1(bitmap_git, cb.base, NULL);
+
tmp_blobs = revs->blob_objects;
tmp_trees = revs->tree_objects;
tmp_tags = revs->blob_objects;
@@ -1197,6 +1316,44 @@ cleanup:
return cb.base;
}
+struct ewah_bitmap *pseudo_merge_bitmap_for_commit(struct bitmap_index *bitmap_git,
+ struct commit *commit)
+{
+ struct commit_list *p;
+ struct bitmap *parents;
+ struct pseudo_merge *match = NULL;
+
+ if (!bitmap_git->pseudo_merges.nr)
+ return NULL;
+
+ parents = bitmap_new();
+
+ for (p = commit->parents; p; p = p->next) {
+ int pos = bitmap_position(bitmap_git, &p->item->object.oid);
+ if (pos < 0 || pos >= bitmap_num_objects(bitmap_git))
+ goto done;
+
+ bitmap_set(parents, pos);
+ }
+
+ match = pseudo_merge_for_parents(&bitmap_git->pseudo_merges,
+ parents);
+
+done:
+ bitmap_free(parents);
+ if (match)
+ return pseudo_merge_bitmap(&bitmap_git->pseudo_merges, match);
+
+ return NULL;
+}
+
+static void unsatisfy_all_pseudo_merges(struct bitmap_index *bitmap_git)
+{
+ uint32_t i;
+ for (i = 0; i < bitmap_git->pseudo_merges.nr; i++)
+ bitmap_git->pseudo_merges.v[i].satisfied = 0;
+}
+
static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
struct rev_info *revs,
struct object_list *roots,
@@ -1204,9 +1361,32 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
{
struct bitmap *base = NULL;
int needs_walk = 0;
+ unsigned existing_bitmaps = 0;
struct object_list *not_mapped = NULL;
+ unsatisfy_all_pseudo_merges(bitmap_git);
+
+ if (bitmap_git->pseudo_merges.nr) {
+ struct bitmap *roots_bitmap = bitmap_new();
+ struct object_list *objects = NULL;
+
+ for (objects = roots; objects; objects = objects->next) {
+ struct object *object = objects->item;
+ int pos;
+
+ pos = bitmap_position(bitmap_git, &object->oid);
+ if (pos < 0)
+ continue;
+
+ bitmap_set(roots_bitmap, pos);
+ }
+
+ base = bitmap_new();
+ if (!cascade_pseudo_merges_1(bitmap_git, base, roots_bitmap))
+ bitmap_free(roots_bitmap);
+ }
+
/*
* Go through all the roots for the walk. The ones that have bitmaps
* on the bitmap index will be `or`ed together to form an initial
@@ -1217,11 +1397,21 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
*/
while (roots) {
struct object *object = roots->item;
+
roots = roots->next;
+ if (base) {
+ int pos = bitmap_position(bitmap_git, &object->oid);
+ if (pos > 0 && bitmap_get(base, pos)) {
+ object->flags |= SEEN;
+ continue;
+ }
+ }
+
if (object->type == OBJ_COMMIT &&
add_commit_to_bitmap(bitmap_git, &base, (struct commit *)object)) {
object->flags |= SEEN;
+ existing_bitmaps = 1;
continue;
}
@@ -1237,6 +1427,9 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
roots = not_mapped;
+ if (existing_bitmaps)
+ cascade_pseudo_merges_1(bitmap_git, base, NULL);
+
/*
* Let's iterate through all the roots that don't have bitmaps to
* check if we can determine them to be reachable from the existing
@@ -1257,8 +1450,12 @@ static struct bitmap *find_objects(struct bitmap_index *bitmap_git,
object->flags &= ~UNINTERESTING;
add_pending_object(revs, object, "");
needs_walk = 1;
+
+ roots_without_bitmaps_nr++;
} else {
object->flags |= SEEN;
+
+ roots_with_bitmaps_nr++;
}
}
@@ -1821,6 +2018,19 @@ struct bitmap_index *prepare_bitmap_walk(struct rev_info *revs,
object_list_free(&wants);
object_list_free(&haves);
+ trace2_data_intmax("bitmap", the_repository, "pseudo_merges_satisfied",
+ pseudo_merges_satisfied_nr);
+ trace2_data_intmax("bitmap", the_repository, "pseudo_merges_cascades",
+ pseudo_merges_cascades_nr);
+ trace2_data_intmax("bitmap", the_repository, "bitmap/hits",
+ existing_bitmaps_hits_nr);
+ trace2_data_intmax("bitmap", the_repository, "bitmap/misses",
+ existing_bitmaps_misses_nr);
+ trace2_data_intmax("bitmap", the_repository, "bitmap/roots_with_bitmap",
+ roots_with_bitmaps_nr);
+ trace2_data_intmax("bitmap", the_repository, "bitmap/roots_without_bitmap",
+ roots_without_bitmaps_nr);
+
return bitmap_git;
cleanup:
@@ -2398,6 +2608,132 @@ cleanup:
return 0;
}
+static void bit_pos_to_object_id(struct bitmap_index *bitmap_git,
+ uint32_t bit_pos,
+ struct object_id *oid)
+{
+ uint32_t index_pos;
+
+ if (bitmap_is_midx(bitmap_git))
+ index_pos = pack_pos_to_midx(bitmap_git->midx, bit_pos);
+ else
+ index_pos = pack_pos_to_index(bitmap_git->pack, bit_pos);
+
+ nth_bitmap_object_oid(bitmap_git, oid, index_pos);
+}
+
+int test_bitmap_pseudo_merges(struct repository *r)
+{
+ struct bitmap_index *bitmap_git;
+ uint32_t i;
+
+ bitmap_git = prepare_bitmap_git(r);
+ if (!bitmap_git || !bitmap_git->pseudo_merges.nr)
+ goto cleanup;
+
+ for (i = 0; i < bitmap_git->pseudo_merges.nr; i++) {
+ struct pseudo_merge *merge;
+ struct ewah_bitmap *commits_bitmap, *merge_bitmap;
+
+ merge = use_pseudo_merge(&bitmap_git->pseudo_merges,
+ &bitmap_git->pseudo_merges.v[i]);
+ commits_bitmap = merge->commits;
+ merge_bitmap = pseudo_merge_bitmap(&bitmap_git->pseudo_merges,
+ merge);
+
+ printf("at=%"PRIuMAX", commits=%"PRIuMAX", objects=%"PRIuMAX"\n",
+ (uintmax_t)merge->at,
+ (uintmax_t)ewah_bitmap_popcount(commits_bitmap),
+ (uintmax_t)ewah_bitmap_popcount(merge_bitmap));
+ }
+
+cleanup:
+ free_bitmap_index(bitmap_git);
+ return 0;
+}
+
+static void dump_ewah_object_ids(struct bitmap_index *bitmap_git,
+ struct ewah_bitmap *bitmap)
+
+{
+ struct ewah_iterator it;
+ eword_t word;
+ uint32_t pos = 0;
+
+ ewah_iterator_init(&it, bitmap);
+
+ while (ewah_iterator_next(&word, &it)) {
+ struct object_id oid;
+ uint32_t offset;
+
+ for (offset = 0; offset < BITS_IN_EWORD; offset++) {
+ if (!(word >> offset))
+ break;
+
+ offset += ewah_bit_ctz64(word >> offset);
+
+ bit_pos_to_object_id(bitmap_git, pos + offset, &oid);
+ printf("%s\n", oid_to_hex(&oid));
+ }
+ pos += BITS_IN_EWORD;
+ }
+}
+
+int test_bitmap_pseudo_merge_commits(struct repository *r, uint32_t n)
+{
+ struct bitmap_index *bitmap_git;
+ struct pseudo_merge *merge;
+ int ret = 0;
+
+ bitmap_git = prepare_bitmap_git(r);
+ if (!bitmap_git || !bitmap_git->pseudo_merges.nr)
+ goto cleanup;
+
+ if (n >= bitmap_git->pseudo_merges.nr) {
+ ret = error(_("pseudo-merge index out of range "
+ "(%"PRIu32" >= %"PRIuMAX")"),
+ n, (uintmax_t)bitmap_git->pseudo_merges.nr);
+ goto cleanup;
+ }
+
+ merge = use_pseudo_merge(&bitmap_git->pseudo_merges,
+ &bitmap_git->pseudo_merges.v[n]);
+ dump_ewah_object_ids(bitmap_git, merge->commits);
+
+cleanup:
+ free_bitmap_index(bitmap_git);
+ return ret;
+}
+
+int test_bitmap_pseudo_merge_objects(struct repository *r, uint32_t n)
+{
+ struct bitmap_index *bitmap_git;
+ struct pseudo_merge *merge;
+ int ret = 0;
+
+ bitmap_git = prepare_bitmap_git(r);
+ if (!bitmap_git || !bitmap_git->pseudo_merges.nr)
+ goto cleanup;
+
+ if (n >= bitmap_git->pseudo_merges.nr) {
+ ret = error(_("pseudo-merge index out of range "
+ "(%"PRIu32" >= %"PRIuMAX")"),
+ n, (uintmax_t)bitmap_git->pseudo_merges.nr);
+ goto cleanup;
+ }
+
+ merge = use_pseudo_merge(&bitmap_git->pseudo_merges,
+ &bitmap_git->pseudo_merges.v[n]);
+
+ dump_ewah_object_ids(bitmap_git,
+ pseudo_merge_bitmap(&bitmap_git->pseudo_merges,
+ merge));
+
+cleanup:
+ free_bitmap_index(bitmap_git);
+ return ret;
+}
+
int rebuild_bitmap(const uint32_t *reposition,
struct ewah_bitmap *source,
struct bitmap *dest)
@@ -2504,6 +2840,7 @@ void free_bitmap_index(struct bitmap_index *b)
*/
close_midx_revindex(b->midx);
}
+ free_pseudo_merge_map(&b->pseudo_merges);
free(b);
}
diff --git a/pack-bitmap.h b/pack-bitmap.h
index c7dea13217..481f089f25 100644
--- a/pack-bitmap.h
+++ b/pack-bitmap.h
@@ -2,7 +2,7 @@
#define PACK_BITMAP_H
#include "ewah/ewok.h"
-#include "khash.h"
+#include "khashl.h"
#include "pack.h"
#include "pack-objects.h"
#include "string-list.h"
@@ -21,6 +21,7 @@ struct bitmap_disk_header {
unsigned char checksum[GIT_MAX_RAWSZ];
};
+#define BITMAP_PSEUDO_MERGE (1u<<21)
#define NEEDS_BITMAP (1u<<22)
/*
@@ -36,6 +37,7 @@ enum pack_bitmap_opts {
BITMAP_OPT_FULL_DAG = 0x1,
BITMAP_OPT_HASH_CACHE = 0x4,
BITMAP_OPT_LOOKUP_TABLE = 0x10,
+ BITMAP_OPT_PSEUDO_MERGES = 0x20,
};
enum pack_bitmap_flags {
@@ -71,6 +73,9 @@ void traverse_bitmap_commit_list(struct bitmap_index *,
void test_bitmap_walk(struct rev_info *revs);
int test_bitmap_commits(struct repository *r);
int test_bitmap_hashes(struct repository *r);
+int test_bitmap_pseudo_merges(struct repository *r);
+int test_bitmap_pseudo_merge_commits(struct repository *r, uint32_t n);
+int test_bitmap_pseudo_merge_objects(struct repository *r, uint32_t n);
#define GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL \
"GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL"
@@ -97,6 +102,11 @@ 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 *);
+int bitmap_writer_has_bitmapped_object_id(const struct object_id *oid);
+void bitmap_writer_push_bitmapped_commit(struct commit *commit,
+ unsigned pseudo_merge);
+
+void bitmap_writer_init(struct repository *r);
void bitmap_writer_show_progress(int show);
void bitmap_writer_set_checksum(const unsigned char *sha1);
void bitmap_writer_build_type_index(struct packing_data *to_pack,
@@ -109,8 +119,10 @@ int rebuild_bitmap(const uint32_t *reposition,
struct bitmap *dest);
struct ewah_bitmap *bitmap_for_commit(struct bitmap_index *bitmap_git,
struct commit *commit);
+struct ewah_bitmap *pseudo_merge_bitmap_for_commit(struct bitmap_index *bitmap_git,
+ struct commit *commit);
void bitmap_writer_select_commits(struct commit **indexed_commits,
- unsigned int indexed_commits_nr, int max_bitmaps);
+ unsigned int indexed_commits_nr);
int bitmap_writer_build(struct packing_data *to_pack);
void bitmap_writer_finish(struct pack_idx_entry **index,
uint32_t index_nr,
@@ -126,4 +138,6 @@ int bitmap_is_preferred_refname(struct repository *r, const char *refname);
int verify_bitmap_files(struct repository *r);
+struct ewah_bitmap *read_bitmap(const unsigned char *map,
+ size_t map_size, size_t *map_pos);
#endif
diff --git a/parse-options-cb.c b/parse-options-cb.c
index bdc7fae497..d99d688d3c 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -7,6 +7,7 @@
#include "environment.h"
#include "gettext.h"
#include "object-name.h"
+#include "setup.h"
#include "string-list.h"
#include "strvec.h"
#include "oid-array.h"
@@ -29,7 +30,7 @@ int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)
opt->long_name);
if (v && v < MINIMUM_ABBREV)
v = MINIMUM_ABBREV;
- else if (v > the_hash_algo->hexsz)
+ else if (startup_info->have_repository && v > the_hash_algo->hexsz)
v = the_hash_algo->hexsz;
}
*(int *)(opt->value) = v;
diff --git a/path.c b/path.c
index 67229edb9c..adfb3d3eb7 100644
--- a/path.c
+++ b/path.c
@@ -5,7 +5,6 @@
#include "abspath.h"
#include "environment.h"
#include "gettext.h"
-#include "hex.h"
#include "repository.h"
#include "strbuf.h"
#include "string-list.h"
@@ -647,58 +646,6 @@ void strbuf_git_common_path(struct strbuf *sb,
va_end(args);
}
-int validate_headref(const char *path)
-{
- struct stat st;
- char buffer[256];
- const char *refname;
- struct object_id oid;
- int fd;
- ssize_t len;
-
- if (lstat(path, &st) < 0)
- return -1;
-
- /* Make sure it is a "refs/.." symlink */
- if (S_ISLNK(st.st_mode)) {
- len = readlink(path, buffer, sizeof(buffer)-1);
- if (len >= 5 && !memcmp("refs/", buffer, 5))
- return 0;
- return -1;
- }
-
- /*
- * Anything else, just open it and try to see if it is a symbolic ref.
- */
- fd = open(path, O_RDONLY);
- if (fd < 0)
- return -1;
- len = read_in_full(fd, buffer, sizeof(buffer)-1);
- close(fd);
-
- if (len < 0)
- return -1;
- buffer[len] = '\0';
-
- /*
- * Is it a symbolic ref?
- */
- if (skip_prefix(buffer, "ref:", &refname)) {
- while (isspace(*refname))
- refname++;
- if (starts_with(refname, "refs/"))
- return 0;
- }
-
- /*
- * Is this a detached HEAD?
- */
- if (!get_oid_hex(buffer, &oid))
- return 0;
-
- return -1;
-}
-
static struct passwd *getpw_str(const char *username, size_t len)
{
struct passwd *pw;
@@ -829,6 +776,7 @@ const char *enter_repo(const char *path, int strict)
if (!suffix[i])
return NULL;
gitfile = read_gitfile(used_path.buf);
+ die_upon_dubious_ownership(gitfile, NULL, used_path.buf);
if (gitfile) {
strbuf_reset(&used_path);
strbuf_addstr(&used_path, gitfile);
@@ -839,6 +787,7 @@ const char *enter_repo(const char *path, int strict)
}
else {
const char *gitfile = read_gitfile(path);
+ die_upon_dubious_ownership(gitfile, NULL, path);
if (gitfile)
path = gitfile;
if (chdir(path))
diff --git a/path.h b/path.h
index ea96487b29..c3bc8617bd 100644
--- a/path.h
+++ b/path.h
@@ -173,7 +173,6 @@ const char *git_path_fetch_head(struct repository *r);
const char *git_path_shallow(struct repository *r);
int ends_with_path_components(const char *path, const char *components);
-int validate_headref(const char *ref);
int calc_shared_perm(int mode);
int adjust_shared_perm(const char *path);
diff --git a/po/TEAMS b/po/TEAMS
index 87df7c6962..2775a971aa 100644
--- a/po/TEAMS
+++ b/po/TEAMS
@@ -18,11 +18,11 @@ Members: Matthias Rüster <matthias.ruester@gmail.com>
Language: el (Greek)
Repository: https://github.com/vyruss/git-po-el
-Leader: Jimmy Angelakos <vyruss@hellug.gr>
+Members: Jimmy Angelakos <vyruss@hellug.gr>
Language: es (Spanish)
Repository: https://github.com/ChrisADR/git-po
-Leader: Christopher Díaz <christopher.diaz.riv@gmail.com>
+Members: Christopher Díaz <christopher.diaz.riv@gmail.com>
Language: fr (French)
Repository: https://github.com/jnavila/git
@@ -34,25 +34,25 @@ Repository: https://github.com/bagasme/git-po
Leader: Bagas Sanjaya <bagasdotme@gmail.com>
Language: is (Icelandic)
-Leader: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+Members: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Language: it (Italian)
Repository: https://github.com/AlessandroMenti/git-po
-Leader: Alessandro Menti <alessandro.menti@alessandromenti.it>
+Members: Alessandro Menti <alessandro.menti@alessandromenti.it>
Language: ko (Korean)
Repository: https://github.com/git-l10n-ko/git-l10n-ko/
-Leader: Gwan-gyeong Mun <elongbug@gmail.com>
-Members: Changwoo Ryu <cwryu@debian.org>
+Members: Gwan-gyeong Mun <elongbug@gmail.com>
+ Changwoo Ryu <cwryu@debian.org>
Sihyeon Jang <uneedsihyeon@gmail.com>
Language: pl (Polish)
Repository: https://github.com/Arusekk/git-po
-Leader: Arusekk <arek_koz@o2.pl>
+Members: Arusekk <arek_koz@o2.pl>
Language: pt_PT (Portuguese - Portugal)
Repository: https://gitlab.com/alexandre1985/git-pt/
-Leader: Daniel Santos <dacs.git@brilhante.top>
+Members: Daniel Santos <dacs.git@brilhante.top>
Language: ru (Russian)
Repository: https://github.com/DJm00n/git-po-ru/
@@ -73,9 +73,10 @@ Leader: Arkadii Yakovets <ark@cho.red>
Members: Kateryna Golovanova <kate@kgthreads.com>
Language: vi (Vietnamese)
-Repository: https://github.com/vnwildman/git/
-Leader: Trần Ngá»c Quân <vnwildman AT gmail.com>
-Members: Nguyá»…n Thái Ngá»c Duy <pclouds AT gmail.com>
+Repository: https://github.com/Nekosha/git-po/
+Leader: Vũ Tiến Hưng <newcomerminecraft@gmail.com>
+Members: Trần Ngá»c Quân <vnwildman AT gmail.com>
+ Nguyá»…n Thái Ngá»c Duy <pclouds AT gmail.com>
Language: zh_CN (Simplified Chinese)
Repository: https://github.com/dyrone/git/
diff --git a/po/bg.po b/po/bg.po
index 6b95addef4..a7cbc617a5 100644
--- a/po/bg.po
+++ b/po/bg.po
@@ -191,7 +191,7 @@
# resolve-undo отмÑна на разрешените подаваниÑ
# resolve conflict коригирам конфликт
# resolve reference уÑтановÑване на обекта, Ñочен от указателÑ, проÑледÑване на указателÑ
-# cannot resolve reference не може да Ñее открие към какво Ñочи указателÑÑ‚
+# cannot resolve reference не може да Ñе открие към какво Ñочи указателÑÑ‚
# maintenance задачи по поддръжка
# GLE поÑледна грешка в нишката - от GetLatError: https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror
# lookup table таблица ÑÑŠÑ ÑъответÑтвиÑ
@@ -216,7 +216,10 @@
# OID lookup chunk Ð¾Ñ‚ÐºÑŠÑ Ð·Ð° Ñ‚ÑŠÑ€Ñенето
# autostash автоматично Ñкатано
# symref файл Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ» (regular file that stores a string that begins with ref: refs/)
-#
+# human-readable четим от хора
+# pseudoref пÑевдоуказател, напр. MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD или REBASE_HEAD
+# reftable таблица Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸
+# its referent '%s' ÑÐ¾Ñ‡ÐµÑ‰Ð¸Ñ Ð³Ð¾ „%s“
#
#
# ------------------------
@@ -244,10 +247,10 @@
# for i in `sort -u FILES`; do cnt=`grep $i FILES | wc -l`; echo $cnt $i ;done | sort -n
msgid ""
msgstr ""
-"Project-Id-Version: git 2.44\n"
+"Project-Id-Version: git 2.45\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2024-02-16 09:33+0100\n"
-"PO-Revision-Date: 2024-02-16 09:38+0100\n"
+"POT-Creation-Date: 2024-04-21 16:59+0200\n"
+"PO-Revision-Date: 2024-04-21 17:00+0200\n"
"Last-Translator: Alexander Shopov <ash@kambanaria.org>\n"
"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
"Language: bg\n"
@@ -749,13 +752,13 @@ msgid ""
"---\n"
"To remove '%c' lines, make them ' ' lines (context).\n"
"To remove '%c' lines, delete them.\n"
-"Lines starting with %c will be removed.\n"
+"Lines starting with %s will be removed.\n"
msgstr ""
"———\n"
"За да пропуÑнете редовете, започващи Ñ â€ž%c“: заменете знака Ñ â€ž “ (Ñтават "
"контекÑÑ‚)\n"
"За да пропуÑнете редовете, започващи Ñ â€ž%c“: изтрийте ги.\n"
-"Редовете, които започват Ñ â€ž%c“ ще Ñе пропуÑнат.\n"
+"Редовете, които започват Ñ â€ž%s“ ще Ñе пропуÑнат.\n"
msgid ""
"If it does not apply cleanly, you will be given an opportunity to\n"
@@ -782,8 +785,8 @@ msgid ""
"Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? "
msgstr ""
"Редактираното парче не може да Ñе приложи. Да Ñе продължи ли Ñ "
-"редактирането? (текущите редакции ще Ñе отменÑÑ‚ при отказ!): „y“ (да)/ "
-"„n“ (не)? "
+"редактирането? (текущите редакции ще Ñе отменÑÑ‚ при отказ!): „y“ (да)/ „n“ "
+"(не)? "
msgid "The selected hunks do not apply to the index!"
msgstr "Избраните парчета не може да Ñе добавÑÑ‚ в индекÑа!"
@@ -803,6 +806,7 @@ msgid ""
"/ - search for a hunk matching the given regex\n"
"s - split the current hunk into smaller hunks\n"
"e - manually edit the current hunk\n"
+"p - print the current hunk\n"
"? - print help\n"
msgstr ""
"j — без решение за парчето, към Ñледващото парче без решение\n"
@@ -813,7 +817,8 @@ msgstr ""
"/ — Ñ‚ÑŠÑ€Ñене на парче, напаÑващо към даден регулÑрен израз\n"
"s — разделÑне на текущото парче на по-малки\n"
"e — ръчно редактиране на текущото парче\n"
-"? — извеждане не помощта\n"
+"p — извеждане на текущото парче\n"
+"? — извеждане на помощта\n"
msgid "No previous hunk"
msgstr "ÐÑма друго парче преди това"
@@ -877,8 +882,8 @@ msgstr ""
" git config advice.%s false"
#, c-format
-msgid "%shint: %.*s%s\n"
-msgstr "%sподÑказка: %.*s%s\n"
+msgid "%shint:%s%.*s%s\n"
+msgstr "%sподÑказка:%s%.*s%s\n"
msgid "Cherry-picking is not possible because you have unmerged files."
msgstr "Отбирането на Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ðµ блокирано от неÑлети файлове."
@@ -1981,6 +1986,12 @@ msgstr ""
msgid "'%s' is not a valid branch name"
msgstr "„%s“ не е позволено име за клон"
+msgid "See `man git check-ref-format`"
+msgstr ""
+"Вижте Ñтраницата в ръководÑтвото:\n"
+"\n"
+" git check-ref-format"
+
#, c-format
msgid "a branch named '%s' already exists"
msgstr "вече ÑъщеÑтвува клон Ñ Ð¸Ð¼Ðµ „%s“."
@@ -2179,15 +2190,8 @@ msgstr ""
msgid "adding embedded git repository: %s"
msgstr "добавÑне на вградено хранилище: %s"
-msgid ""
-"Use -f if you really want to add them.\n"
-"Turn this message off by running\n"
-"\"git config advice.addIgnoredFile false\""
-msgstr ""
-"Ползвайте опциÑта „-f“, ако наиÑтина иÑкате да ги добавите.\n"
-"За да изключите това Ñъобщение, изпълнете:\n"
-"\n"
-" git config advice.addIgnoredFile false"
+msgid "Use -f if you really want to add them."
+msgstr "Използвайте „-f“, за да ги добавите"
msgid "adding files failed"
msgstr "неуÑпешно добавÑне на файлове"
@@ -2204,15 +2208,8 @@ msgstr "опциÑта „%s“ и път Ñа неÑъвмеÑтими"
msgid "Nothing specified, nothing added.\n"
msgstr "Ðищо не е зададено и нищо не е добавено.\n"
-msgid ""
-"Maybe you wanted to say 'git add .'?\n"
-"Turn this message off by running\n"
-"\"git config advice.addEmptyPathspec false\""
-msgstr ""
-"„git add .“ ли иÑкахте да изпълните?\n"
-"За да изключите това Ñъобщение, изпълнете:\n"
-"\n"
-" git config advice.addEmptyPathspec false"
+msgid "Maybe you wanted to say 'git add .'?"
+msgstr "ВероÑтно иÑкахте да използвате „git add .“?"
msgid "index file corrupt"
msgstr "файлът Ñ Ð¸Ð½Ð´ÐµÐºÑа е повреден"
@@ -2290,25 +2287,26 @@ msgid "Failed to split patches."
msgstr "Кръпките не може да Ñе разделÑÑ‚."
#, c-format
-msgid "When you have resolved this problem, run \"%s --continue\"."
+msgid "When you have resolved this problem, run \"%s --continue\".\n"
msgstr ""
"След коригирането на този проблем изпълнете:\n"
"\n"
-" %s --continue“"
+" %s --continue“\n"
#, c-format
-msgid "If you prefer to skip this patch, run \"%s --skip\" instead."
+msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n"
msgstr ""
"Ðко предпочитате да преÑкочите тази кръпка, изпълнете:\n"
"\n"
-" %s --skip"
+" %s --skip\n"
#, c-format
-msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"."
+msgid ""
+"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"
msgstr ""
"За да включите празната кръпка като празно подаване, изпълнете:\n"
"\n"
-" %s --allow-empty"
+" %s --allow-empty\n"
#, c-format
msgid "To restore the original branch and stop patching, run \"%s --abort\"."
@@ -3204,11 +3202,11 @@ msgstr "клонът е копиран, но конфигурационниÑÑ‚
msgid ""
"Please edit the description for the branch\n"
" %s\n"
-"Lines starting with '%c' will be stripped.\n"
+"Lines starting with '%s' will be stripped.\n"
msgstr ""
"Въведете опиÑание на клона.\n"
" %s\n"
-"Редовете, които започват Ñ â€ž%c“, ще бъдат пропуÑнати.\n"
+"Редовете, които започват Ñ â€ž%s“, ще бъдат пропуÑнати.\n"
msgid "Generic options"
msgstr "Общи наÑтройки"
@@ -3413,10 +3411,12 @@ msgid "not run from a git repository - no hooks to show\n"
msgstr "командата е Ñтартирана извън хранилище на Git, затова нÑма куки\n"
msgid ""
-"git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"git bugreport [(-o | --output-directory) <path>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
" [--diagnose[=<mode>]]"
msgstr ""
-"git bugreport [(-o|--output-directory) ПЪТ] [(-s|--suffix) ФОРМÐТ]\n"
+"git bugreport [(-o|--output-directory) ПЪТ]\n"
+" [(-s|--suffix) ФОРМÐТ|--no-suffix]\n"
" [--diagnose[=РЕЖИМ]]"
msgid ""
@@ -3610,8 +3610,8 @@ msgstr "Извеждане на атрибутите на обектите (Ñ Ð
msgid "show object type (one of 'blob', 'tree', 'commit', 'tag', ...)"
msgstr ""
-"показване на обекти от този ВИД: „blob“ (BLOB), „tree“ (дърво), "
-"„commit“ (подаване), „tag“ (етикет и т.н.…)"
+"показване на обекти от този ВИД: „blob“ (BLOB), „tree“ (дърво), „commit“ "
+"(подаване), „tag“ (етикет и т.н.…)"
msgid "show object size"
msgstr "извеждане на размера на обект"
@@ -3907,6 +3907,10 @@ msgstr "„%s“, „%s“ и „%s“ Ñа неÑъвмеÑтими Ñ Ð¸Ð·Ñ‚Ðµ
msgid "path '%s' is unmerged"
msgstr "пътÑÑ‚ „%s“ не е ÑлÑÑ‚"
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr "дървото не може да бъде прочетено (%s)"
+
msgid "you need to resolve your current index first"
msgstr "първо Ñ‚Ñ€Ñбва да коригирате индекÑа Ñи"
@@ -4142,6 +4146,10 @@ msgstr ""
msgid "missing branch or commit argument"
msgstr "липÑва аргумент — клон или подаване"
+#, c-format
+msgid "unknown conflict style '%s'"
+msgstr "непознат вид конфликт „%s“"
+
msgid "perform a 3-way merge with the new branch"
msgstr "извършване на тройно Ñливане Ñ Ð½Ð¾Ð²Ð¸Ñ ÐºÐ»Ð¾Ð½"
@@ -4401,20 +4409,10 @@ msgstr "изтриване и на игнорираните файлове"
msgid "remove only ignored files"
msgstr "изтриване Ñамо на игнорирани файлове"
-msgid ""
-"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to "
-"clean"
-msgstr ""
-"ÐаÑтройката „clean.requireForce“ е зададена като иÑтина, което изиÑква нÑÐºÐ¾Ñ "
-"от опциите „-i“, „-n“ или „-f“. ÐÑма да Ñе извърши изчиÑтване"
-
-msgid ""
-"clean.requireForce defaults to true and neither -i, -n, nor -f given; "
-"refusing to clean"
+msgid "clean.requireForce is true and -f not given: refusing to clean"
msgstr ""
-"ÐаÑтройката „clean.requireForce“ не е зададена, но Ñтандартно е иÑтина, "
-"което изиÑква нÑÐºÐ¾Ñ Ð¾Ñ‚ опциите „-i“, „-n“ или „-f“. ÐÑма да Ñе извърши "
-"изчиÑтване"
+"ÐаÑтройката „clean.requireForce“ е зададена, което изиÑква опцииÑта „-f“. "
+"ÐÑма да Ñе извърши изчиÑтване"
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [ОПЦИЯ…] [--] ХРÐÐИЛИЩЕ [ДИРЕКТОРИЯ]"
@@ -4428,7 +4426,7 @@ msgstr "без Ñъздаване на работно дърво"
msgid "create a bare repository"
msgstr "Ñъздаване на голо хранилище"
-msgid "create a mirror repository (implies bare)"
+msgid "create a mirror repository (implies --bare)"
msgstr ""
"Ñъздаване на хранилище-огледало (включва опциÑта „--bare“ за голо хранилище)"
@@ -4762,6 +4760,10 @@ msgstr "поле в знаци отдÑÑно"
msgid "padding space between columns"
msgstr "поле в знаци между колоните"
+#, c-format
+msgid "%s must be non-negative"
+msgstr "%s Ñ‚Ñ€Ñбва да е неотрицателно"
+
msgid "--command must be the first argument"
msgstr "опциÑта „--command“ Ñ‚Ñ€Ñбва да е първиÑÑ‚ аргумент"
@@ -5088,35 +5090,35 @@ msgstr "шаблонът за подаване не може да бъде заÐ
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored.\n"
+"with '%s' will be ignored.\n"
msgstr ""
"Въведете Ñъобщението за подаване на промѐните. Редовете, които започват\n"
-"Ñ â€ž%c“, ще бъдат пропуÑнати.\n"
+"Ñ â€ž%s“, ще бъдат пропуÑнати.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored, and an empty message aborts the commit.\n"
+"with '%s' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
"Въведете Ñъобщението за подаване на промѐните. Редовете, които започват\n"
-"Ñ â€ž%c“, ще бъдат пропуÑнати, а празно Ñъобщение преуÑтановÑва подаването.\n"
+"Ñ â€ž%s“, ще бъдат пропуÑнати, а празно Ñъобщение преуÑтановÑва подаването.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
msgstr ""
"Въведете Ñъобщението за подаване на промѐните. Редовете, които започват\n"
-"Ñ â€ž%c“, Ñъщо ще бъдат включени — може да ги изтриете вие.\n"
+"Ñ â€ž%s“, Ñъщо ще бъдат включени — може да ги изтриете вие.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
"Въведете Ñъобщението за подаване на промѐните. Редовете, които започват\n"
-"Ñ â€ž%c“, Ñъщо ще бъдат включени — може да ги изтриете вие. Празно \n"
+"Ñ â€ž%s“, Ñъщо ще бъдат включени — може да ги изтриете вие. Празно \n"
"Ñъобщение преуÑтановÑва подаването.\n"
msgid ""
@@ -5262,9 +5264,9 @@ msgid ""
"show ignored files, optional modes: traditional, matching, no. (Default: "
"traditional)"
msgstr ""
-"извеждане на игнорираните файлове. Възможните РЕЖИМи Ñа "
-"„traditional“ (традиционен), „matching“ (напаÑващи), „no“ (без игнорираните "
-"файлове). СтандартниÑÑ‚ РЕЖИМ е: „traditional“."
+"извеждане на игнорираните файлове. Възможните РЕЖИМи Ñа „traditional“ "
+"(традиционен), „matching“ (напаÑващи), „no“ (без игнорираните файлове). "
+"СтандартниÑÑ‚ РЕЖИМ е: „traditional“."
msgid "when"
msgstr "КОГÐ"
@@ -5274,8 +5276,8 @@ msgid ""
"(Default: all)"
msgstr ""
"игнориране на промѐните в подмодулите. ÐžÐ¿Ñ†Ð¸Ñ Ñ Ð½ÐµÐ·Ð°Ð´ÑŠÐ»Ð¶Ð¸Ñ‚ÐµÐ»Ð½Ð° ÑтойноÑÑ‚ — "
-"една от „all“ (вÑички), „dirty“ (тези Ñ Ð½ÐµÐ¿Ð¾Ð´Ð°Ð´ÐµÐ½Ð¸ промѐни), "
-"„untracked“ (неÑледени)"
+"една от „all“ (вÑички), „dirty“ (тези Ñ Ð½ÐµÐ¿Ð¾Ð´Ð°Ð´ÐµÐ½Ð¸ промѐни), „untracked“ "
+"(неÑледени)"
msgid "list untracked files in columns"
msgstr "извеждане на неÑледените файлове в колони"
@@ -5568,9 +5570,8 @@ msgstr ""
msgid "show scope of config (worktree, local, global, system, command)"
msgstr ""
-"извеждане на обхвата на наÑтройката „worktree“ (работно дърво), "
-"„local“ (хранилище), „global“ (потребител), „system“ (ÑиÑтема), "
-"„command“ (команда)"
+"извеждане на обхвата на наÑтройката „worktree“ (работно дърво), „local“ "
+"(хранилище), „global“ (потребител), „system“ (ÑиÑтема), „command“ (команда)"
msgid "value"
msgstr "СТОЙÐОСТ"
@@ -5578,6 +5579,9 @@ msgstr "СТОЙÐОСТ"
msgid "with --get, use default value when missing entry"
msgstr "Ñ â€ž--get“ Ñе използва Ñтандартна СТОЙÐОСТ при липÑваща"
+msgid "human-readable comment string (# will be prepended as needed)"
+msgstr "низ за подаване четим от хора (при нужда отпред Ñе Ð´Ð¾Ð±Ð°Ð²Ñ â€ž#“)"
+
#, c-format
msgid "wrong number of arguments, should be %d"
msgstr "неправилен брой аргументи, Ñ‚Ñ€Ñбва да е точно %d"
@@ -5673,6 +5677,11 @@ msgstr ""
msgid "--default is only applicable to --get"
msgstr "опциÑта „--default“ е приложима Ñамо към опциÑта „--get“"
+msgid "--comment is only applicable to add/set/replace operations"
+msgstr ""
+"опциÑта „--comment“ е ÑъвмеÑтима Ñамо Ñ Ð´ÐµÐ¹ÑтвиÑта „add“ (добавÑне)/„set“ "
+"(задаване)/„replace“ (замÑна)"
+
msgid "--fixed-value only applies with 'value-pattern'"
msgstr "опциÑта „--fixed-value“ е приложима Ñамо ÑÑŠÑ Ð¨ÐБЛОÐ_ЗÐ_СТОЙÐОСТ"
@@ -5707,7 +5716,7 @@ msgid "no such section: %s"
msgstr "такъв раззел нÑма: %s"
msgid "print sizes in human readable format"
-msgstr "извеждане на размерите на обектите във формат леÑно четим от хора"
+msgstr "извеждане на размерите на обектите във формат четим от хора"
#, c-format
msgid ""
@@ -6535,6 +6544,9 @@ msgstr "извеждане Ñамо на указателите, които не
msgid "read reference patterns from stdin"
msgstr "изчитане на шаблоните за указатели от ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´"
+msgid "also include HEAD ref and pseudorefs"
+msgstr "включване и на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“ както и пÑевдоуказателите"
+
msgid "unknown arguments supplied with --stdin"
msgstr "непознат аргумент към опциÑта „--stdin“"
@@ -7162,10 +7174,6 @@ msgid "no threads support, ignoring %s"
msgstr "липÑва поддръжка за нишки. „%s“ ще Ñе пренебрегне"
#, c-format
-msgid "unable to read tree (%s)"
-msgstr "дървото не може да бъде прочетено (%s)"
-
-#, c-format
msgid "unable to read tree %s"
msgstr "дървото не може да бъде прочетено: %s"
@@ -7783,13 +7791,39 @@ msgstr "опциÑта „--separate-git-dir“ е неÑъвмеÑтима Ñ Ð
msgid ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n"
+" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
" [--parse] [<file>...]"
msgstr ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
" [(--trailer (КЛЮЧ|СИÐОÐИМ)[(=|:)СТОЙÐОСТ])…]\n"
" [--parse] [ФÐЙЛ…]"
+#, c-format
+msgid "could not stat %s"
+msgstr "Ðе може да Ñе получи Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%s“"
+
+#, c-format
+msgid "file %s is not a regular file"
+msgstr "„%s“ не е обикновен файл"
+
+#, c-format
+msgid "file %s is not writable by user"
+msgstr "„%s“: нÑма права̀ за запиÑване на файла"
+
+msgid "could not open temporary file"
+msgstr "временниÑÑ‚ файл не може да Ñе отвори"
+
+#, c-format
+msgid "could not read input file '%s'"
+msgstr "входниÑÑ‚ файл „%s“ не може да бъде прочетен"
+
+msgid "could not read from stdin"
+msgstr "от ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´ не може да Ñе чете"
+
+#, c-format
+msgid "could not rename temporary file to %s"
+msgstr "временниÑÑ‚ файл не може да Ñе преименува на „%s“"
+
msgid "edit files in place"
msgstr "директно редактиране на файловете"
@@ -8088,8 +8122,8 @@ msgstr "включване на кръпката в текÑта на пиÑма
msgid "enable message threading, styles: shallow, deep"
msgstr ""
-"използване на нишки за ÑъобщениÑта. СТИЛът е „shallow“ (плитък) или "
-"„deep“ (дълбок)"
+"използване на нишки за ÑъобщениÑта. СТИЛът е „shallow“ (плитък) или „deep“ "
+"(дълбок)"
msgid "signature"
msgstr "подпиÑ"
@@ -8196,18 +8230,6 @@ msgstr ""
msgid "could not get object info about '%s'"
msgstr "не може да Ñе получи Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° обекта „%s“"
-#, c-format
-msgid "bad ls-files format: element '%s' does not start with '('"
-msgstr "неправилен формат за „ls-tree“: елементът „%s“ не започва Ñ â€ž(“"
-
-#, c-format
-msgid "bad ls-files format: element '%s' does not end in ')'"
-msgstr "неправилен формат за „ls-tree“: елементът „%s“ не завършва Ñ â€ž)“"
-
-#, c-format
-msgid "bad ls-files format: %%%.*s"
-msgstr "неправилен формат за „ls-tree“: %%%.*s"
-
msgid "git ls-files [<options>] [<file>...]"
msgstr "git ls-files [ОПЦИЯ…] [ФÐЙЛ…]"
@@ -8341,18 +8363,6 @@ msgstr "извеждане на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ Ð·Ð°ÐµÐ´Ð½Ð¾ Ñ Ð¾Ð±ÐµÐºÑ‚Ð°
msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
msgstr "git ls-tree [ОПЦИЯ…] УКÐЗÐТЕЛ_КЪМ_ДЪРВО [ПЪТ…]"
-#, c-format
-msgid "bad ls-tree format: element '%s' does not start with '('"
-msgstr "неправилен формат за „ls-tree“: елементът „%s“ не започва Ñ â€ž(“"
-
-#, c-format
-msgid "bad ls-tree format: element '%s' does not end in ')'"
-msgstr "неправилен формат за „ls-tree“: елементът „%s“ не завършва Ñ â€ž(“"
-
-#, c-format
-msgid "bad ls-tree format: %%%.*s"
-msgstr "неправилен формат за „ls-tree“: %%%.*s"
-
msgid "only show trees"
msgstr "извеждане Ñамо на дървета"
@@ -8547,6 +8557,10 @@ msgstr "указателÑÑ‚ „%s“ не може да бъде проÑлед
msgid "Merging %s with %s\n"
msgstr "Сливане на „%s“ Ñ â€ž%s“\n"
+#, c-format
+msgid "could not parse as tree '%s'"
+msgstr "„%s“ не може да Ñе анализира като дърво"
+
msgid "not something we can merge"
msgstr "не може да Ñе Ñлее"
@@ -8754,10 +8768,10 @@ msgstr "Празно Ñъобщение предотвратÑва подаваÐ
#, c-format
msgid ""
-"Lines starting with '%c' will be ignored, and an empty message aborts\n"
+"Lines starting with '%s' will be ignored, and an empty message aborts\n"
"the commit.\n"
msgstr ""
-"Редовете, които започват Ñ â€ž%c“, ще бъдат пропуÑнати, а празно\n"
+"Редовете, които започват Ñ â€ž%s“, ще бъдат пропуÑнати, а празно\n"
"Ñъобщение преуÑтановÑва подаването.\n"
msgid "Empty commit message."
@@ -8923,9 +8937,6 @@ msgstr "обектът Ñ ÐµÑ‚Ð¸ÐºÐµÑ‚ не може да бъде прочетÐ
msgid "object '%s' tagged as '%s', but is a '%s' type"
msgstr "обектът „%s“ е Ñ ÐµÑ‚Ð¸ÐºÐµÑ‚ за %s, но е %s"
-msgid "could not read from stdin"
-msgstr "от ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´ не може да Ñе чете"
-
msgid "tag on stdin did not pass our strict fsck check"
msgstr "етикетът на ÑÑ‚Ð°Ð½Ð´Ð°Ñ€Ñ‚Ð½Ð¸Ñ Ð²Ñ…Ð¾Ð´ не преминава Ñтрогата проверка Ñ â€žfsck“"
@@ -9365,9 +9376,8 @@ msgid ""
"cat_sort_uniq)"
msgstr ""
"коригиране на конфликтите при Ñливане на бележките чрез тази СТРÐТЕГИЯ — "
-"„manual“ (ръчно), „ours“ (вашата верÑиÑ), „theirs“ (чуждата верÑиÑ), "
-"„union“ (обединÑване), „cat_sort_uniq“ (обединÑване, подреждане, уникални "
-"резултати)"
+"„manual“ (ръчно), „ours“ (вашата верÑиÑ), „theirs“ (чуждата верÑиÑ), „union“ "
+"(обединÑване), „cat_sort_uniq“ (обединÑване, подреждане, уникални резултати)"
msgid "Committing unmerged notes"
msgstr "Подаване на неÑлети бележки"
@@ -9572,8 +9582,8 @@ msgstr ""
msgid ""
"object already configured in another uploadpack.blobpackfileuri (got '%s')"
msgstr ""
-"вече има наÑтройка за обекта в друг ред „uploadpack."
-"blobpackfileuri“ (получена е „%s“)"
+"вече има наÑтройка за обекта в друг ред „uploadpack.blobpackfileuri“ "
+"(получена е „%s“)"
#, c-format
msgid "could not get type of object %s in pack %s"
@@ -9855,10 +9865,11 @@ msgid "refusing to run without --i-still-use-this"
msgstr "Ñ‚Ñ€Ñбва да добавите и опциÑта „--i-still-use-this“"
msgid ""
-"git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude "
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
"<pattern>]"
msgstr ""
-"git pack-refs [--all] [--no-prune] [--include ШÐБЛОÐ] [--exclude ШÐБЛОÐ]"
+"git pack-refs [--all] [--no-prune] [--auto] [--include ШÐБЛОÐ] [--exclude "
+"ШÐБЛОÐ]"
msgid "pack everything"
msgstr "пакетиране на вÑичко"
@@ -9866,6 +9877,9 @@ msgstr "пакетиране на вÑичко"
msgid "prune loose refs (default)"
msgstr "окаÑÑ‚Ñ€Ñне на недоÑтижимите указатели (Ñтандартно)"
+msgid "auto-pack refs as needed"
+msgstr "автоматично пакетиране на указателите при нужда"
+
msgid "references to include"
msgstr "кои указатели да Ñе включат"
@@ -10186,8 +10200,8 @@ msgstr ""
msgid ""
"You didn't specify any refspecs to push, and push.default is \"nothing\"."
msgstr ""
-"Ðе Ñте указали верÑÐ¸Ñ Ð·Ð° подаване, а наÑтройката „push.default“ е "
-"„nothing“ (нищо без изрично указана верÑÐ¸Ñ Ð´Ð° не Ñе изтлаÑква)"
+"Ðе Ñте указали верÑÐ¸Ñ Ð·Ð° подаване, а наÑтройката „push.default“ е „nothing“ "
+"(нищо без изрично указана верÑÐ¸Ñ Ð´Ð° не Ñе изтлаÑква)"
#, c-format
msgid ""
@@ -10542,19 +10556,6 @@ msgstr "неправилната ÑтойноÑÑ‚ на „allow_rerere_autoupdat
msgid "could not remove '%s'"
msgstr "„%s“ не може да бъде изтрит"
-msgid ""
-"Resolve all conflicts manually, mark them as resolved with\n"
-"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
-"You can instead skip this commit: run \"git rebase --skip\".\n"
-"To abort and get back to the state before \"git rebase\", run \"git rebase --"
-"abort\"."
-msgstr ""
-"След коригирането на конфликтите отбележете решаването им чрез:\n"
-"„git add/rm ФÐЙЛ_С_КОÐФЛИКТ…“ и изпълнете „git rebase --continue“.\n"
-"Ðко предпочитате да преÑкочите тази кръпка, изпълнете „git rebase --skip“.\n"
-"За да откажете пребазирането и да Ñе върнете към първоначалното ÑÑŠÑтоÑние,\n"
-"изпълнете „git rebase --abort“."
-
#, c-format
msgid ""
"\n"
@@ -10583,13 +10584,17 @@ msgstr "не може да Ñе премине към „%s“"
msgid "apply options and merge options cannot be used together"
msgstr "опциите за прилагане и Ñливане Ñа неÑъвмеÑтими"
+msgid "--empty=ask is deprecated; use '--empty=stop' instead."
+msgstr ""
+"комбинациÑта „--empty=ask“ е оÑтарÑла. ВмеÑто Ð½ÐµÑ Ð¿Ð¾Ð»Ð·Ð²Ð°Ð¹Ñ‚Ðµ „--empty=stop“."
+
#, c-format
msgid ""
"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
-"\"ask\"."
+"\"stop\"."
msgstr ""
-"неправилна ÑтойноÑÑ‚ „%s“: вариантите Ñа „drop“ (преÑкачане), "
-"„keep“ (запазване) и „ask“ (питане)"
+"неправилна празна ÑтойноÑÑ‚ „%s“: вариантите Ñа „drop“ (преÑкачане), „keep“ "
+"(запазване) и „stop“ (Ñпиране)"
msgid ""
"--rebase-merges with an empty string argument is deprecated and will stop "
@@ -10782,8 +10787,8 @@ msgstr ""
"„preserve“.\n"
"Тази ÑтойноÑÑ‚ вече не Ñе поддържа, заменете Ñ Ñ â€žmerges“."
-msgid "No rebase in progress?"
-msgstr "Изглежда в момента не тече пребазиране"
+msgid "no rebase in progress"
+msgstr "изглежда в момента не тече пребазиране"
msgid "The --edit-todo action can only be used during interactive rebase."
msgstr ""
@@ -10984,6 +10989,9 @@ msgstr "Ñ‚Ñ€Ñбва да укажете директориÑ"
msgid "git reflog [show] [<log-options>] [<ref>]"
msgstr "git reflog [show] [ОПЦИЯ…] [УКÐЗÐТЕЛ]"
+msgid "git reflog list"
+msgstr "git reflog list"
+
msgid ""
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
" [--rewrite] [--updateref] [--stale-fix]\n"
@@ -11009,6 +11017,10 @@ msgstr "git reflog exists УКÐЗÐТЕЛ"
msgid "invalid timestamp '%s' given to '--%s'"
msgstr "неправилно времево клеймо „%s“ подадено към „--%s“"
+#, c-format
+msgid "%s does not accept arguments: '%s'"
+msgstr "„%s“ не приема аргументи: „%s“"
+
msgid "do not actually prune any entries"
msgstr "без окаÑÑ‚Ñ€Ñне на запиÑи"
@@ -11140,7 +11152,7 @@ msgstr ""
"ползвайте „--mirror=fetch“ или „--mirror=push“"
#, c-format
-msgid "unknown mirror argument: %s"
+msgid "unknown --mirror argument: %s"
msgstr "неправилна ÑтойноÑÑ‚ за „--mirror“: %s"
msgid "fetch the remote branches"
@@ -11517,6 +11529,10 @@ msgstr ""
"командата „pack-objects“ не може да Ñе Ñтартира за препакетирането на "
"гарантиращите обекти"
+msgid "failed to feed promisor objects to pack-objects"
+msgstr ""
+"гарантиращите обекти не може да Ñе подадат на командата „git pack-objects“"
+
msgid "repack: Expecting full hex object ID lines only from pack-objects."
msgstr ""
"repack: от „pack-objects“ Ñе изиÑкват редове Ñамо Ñ Ð¿ÑŠÐ»Ð½Ð¸ шеÑтнайÑетични "
@@ -12127,6 +12143,13 @@ msgstr "опциÑта „--default“ изиÑква аргумент"
msgid "--prefix requires an argument"
msgstr "опциÑта „--prefix“ изиÑква аргумент"
+msgid "no object format specified"
+msgstr "не е указан формат на обект"
+
+#, c-format
+msgid "unsupported object format: %s"
+msgstr "неподдържан формат на обект: „%s“"
+
#, c-format
msgid "unknown mode for --abbrev-ref: %s"
msgstr "непознат режим за „--abbrev-ref“: „%s“"
@@ -12208,8 +12231,8 @@ msgstr "запазване на първоначално празните под
msgid "allow commits with empty messages"
msgstr "позволÑване на празни ÑÑŠÐ¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸ подаване"
-msgid "keep redundant, empty commits"
-msgstr "запазване на излишните, празни подаваниÑ"
+msgid "deprecated: use --empty=keep instead"
+msgstr "ОСТÐРЯЛО: вмеÑто това ползвайте „--empty=keep“"
msgid "use the 'reference' format to refer to commits"
msgstr "указване на Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð²ÑŠÐ² формат за указател"
@@ -13567,25 +13590,25 @@ msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be ignored.\n"
+"Lines starting with '%s' will be ignored.\n"
msgstr ""
"\n"
"Въведете Ñъобщение за етикета.\n"
" %s\n"
-"Редовете, които започват Ñ â€ž%c“, ще бъдат пропуÑнати.\n"
+"Редовете, които започват Ñ â€ž%s“, ще бъдат пропуÑнати.\n"
#, c-format
msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be kept; you may remove them yourself if you "
+"Lines starting with '%s' will be kept; you may remove them yourself if you "
"want to.\n"
msgstr ""
"\n"
"Въведете Ñъобщение за етикет.\n"
" %s\n"
-"Редовете, които започват Ñ â€ž%c“, Ñъщо ще бъдат включени — може да ги "
+"Редовете, които започват Ñ â€ž%s“, Ñъщо ще бъдат включени — може да ги "
"изтриете вие.\n"
msgid "unable to sign the tag"
@@ -13671,6 +13694,9 @@ msgstr "извеждане Ñамо на неÑлетите етикети"
msgid "print only tags of the object"
msgstr "извеждане Ñамо на етикетите на ОБЕКТÐ"
+msgid "could not start 'git column'"
+msgstr "неуÑпешно изпълнение на „git column“"
+
#, c-format
msgid "the '%s' option is only allowed in list mode"
msgstr "опциÑта „%s“ изиÑква режим на ÑпиÑък"
@@ -13936,11 +13962,14 @@ msgstr ""
msgid "fsmonitor disabled"
msgstr "Ñледенето чрез файловата ÑиÑтема е изключено"
-msgid "git update-ref [<options>] -d <refname> [<old-val>]"
-msgstr "git update-ref [ОПЦИЯ…] -d ИМЕ_ÐÐ_УКÐЗÐТЕЛ [СТÐРÐ_СТОЙÐОСТ]"
+msgid "git update-ref [<options>] -d <refname> [<old-oid>]"
+msgstr ""
+"git update-ref [ОПЦИЯ…] -d ИМЕ_ÐÐ_УКÐЗÐТЕЛ [СТÐР_ИДЕÐТИФИКÐТОР_ÐÐ_ОБЕКТ]"
-msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]"
-msgstr "git update-ref [ОПЦИЯ…] ИМЕ_ÐÐ_УКÐЗÐТЕЛ ÐОВÐ_СТОЙÐОСТ [СТÐРÐ_СТОЙÐОСТ]"
+msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]"
+msgstr ""
+"git update-ref [ОПЦИЯ…] ИМЕ_ÐÐ_УКÐЗÐТЕЛ ÐОВ_ИДЕÐТИФИКÐТОР_ÐÐ_ОБЕКТ "
+"[СТÐР_ИДЕÐТИФИКÐТОР_ÐÐ_ОБЕКТ]"
msgid "git update-ref [<options>] --stdin [-z]"
msgstr "git update-ref [ОПЦИЯ…] --stdin [-z]"
@@ -14623,9 +14652,7 @@ msgid "A really simple server for Git repositories"
msgstr "Силно опроÑтен Ñървър за хранилища на Git"
msgid "Give an object a human readable name based on an available ref"
-msgstr ""
-"Задаване на име удобно за потребителите на обект въз оÑнова на наличен "
-"указател"
+msgstr "Задаване на четимо от хора име на обект въз оÑнова на наличен указател"
msgid "Generate a zip archive of diagnostic information"
msgstr "Създаване на архив във формат zip Ñ Ð´Ð¸Ð°Ð³Ð½Ð¾Ñтична информациÑ"
@@ -15341,6 +15368,10 @@ msgid "Verifying commits in commit graph"
msgstr "Проверка на подаваниÑта в гра̀фа"
#, c-format
+msgid "could not parse commit %s"
+msgstr "подаването „%s“ не може да бъде анализирано"
+
+#, c-format
msgid "%s %s is not a commit!"
msgstr "%s %s не е подаване!"
@@ -15792,8 +15823,13 @@ msgstr "дължината на Ñъкращаване е извън диапаÐ
msgid "bad zlib compression level %d"
msgstr "неправилно ниво на компреÑиране: %d"
-msgid "core.commentChar should only be one ASCII character"
-msgstr "наÑтройката „core.commentChar“ Ñ‚Ñ€Ñбва да е Ñамо един знак от ASCII"
+#, c-format
+msgid "%s cannot contain newline"
+msgstr "%s не може да Ñъдържа нови редове"
+
+#, c-format
+msgid "%s must have at least one character"
+msgstr "%s Ñ‚Ñ€Ñбва да Ñъдържа поне един знак"
#, c-format
msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -15818,9 +15854,9 @@ msgstr "неправилна ÑтойноÑÑ‚ за „%s“: „%s“"
msgid "must be one of nothing, matching, simple, upstream or current"
msgstr ""
"Ñ‚Ñ€Ñбва да е една от Ñледните ÑтойноÑти: „nothing“ (без изтлаÑкване при липÑа "
-"на указател), „matching“ (вÑички клони ÑÑŠÑ Ñъвпадащи имена), "
-"„simple“ (клонът ÑÑŠÑ Ñъщото име, от който Ñе издърпва), „upstream“ (клонът, "
-"от който Ñе издърпва) или „current“ (клонът ÑÑŠÑ Ñъщото име)"
+"на указател), „matching“ (вÑички клони ÑÑŠÑ Ñъвпадащи имена), „simple“ "
+"(клонът ÑÑŠÑ Ñъщото име, от който Ñе издърпва), „upstream“ (клонът, от който "
+"Ñе издърпва) или „current“ (клонът ÑÑŠÑ Ñъщото име)"
#, c-format
msgid "unable to load config blob object '%s'"
@@ -15871,6 +15907,10 @@ msgid "failed to write new configuration file %s"
msgstr "новиÑÑ‚ конфигурационен файл „%s“ не може да бъде запазен"
#, c-format
+msgid "no multi-line comment allowed: '%s'"
+msgstr "коментари на повече от един ред не Ñа позволени: „%s“"
+
+#, c-format
msgid "could not lock config file %s"
msgstr "конфигурационниÑÑ‚ файл „%s“ не може да бъде заключен"
@@ -16358,8 +16398,8 @@ msgid ""
"'dimmed-zebra', 'plain'"
msgstr ""
"наÑтройката за цвÑÑ‚ за премеÑтване Ñ‚Ñ€Ñбва да е една от: „no“ (без), "
-"„default“ (Ñтандартно), „blocks“ (парчета), „zebra“ (райе), „dimmed-"
-"zebra“ (тъмно райе), „plain“ (обикновено)"
+"„default“ (Ñтандартно), „blocks“ (парчета), „zebra“ (райе), „dimmed-zebra“ "
+"(тъмно райе), „plain“ (обикновено)"
#, c-format
msgid ""
@@ -17718,6 +17758,14 @@ msgid "Unable to create '%s.lock': %s"
msgstr "Файлът-ключалка „%s.lock“ не може да бъде Ñъздаден: %s"
#, c-format
+msgid "could not write loose object index %s"
+msgstr "индекÑÑŠÑ‚ Ñ Ð½ÐµÐ¿Ð°ÐºÐµÑ‚Ð¸Ñ€Ð°Ð½Ð¸ обекти не може да Ñе запише: %s"
+
+#, c-format
+msgid "failed to write loose object index %s\n"
+msgstr "грешка при запиÑа на индекÑа Ñ Ð½ÐµÐ¿Ð°ÐºÐµÑ‚Ð¸Ñ€Ð°Ð½Ð¸ обекти %s\n"
+
+#, c-format
msgid "unexpected line: '%s'"
msgstr "неочакван ред: „%s“"
@@ -17740,6 +17788,10 @@ msgid "Failed to merge submodule %s (commits not present)"
msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (нÑма подаваниÑ)"
#, c-format
+msgid "Failed to merge submodule %s (repository corrupt)"
+msgstr "ÐеуÑпешно Ñливане на подмодула „%s“ (хранилището е Ñ Ð³Ñ€ÐµÑˆÐºÐ¸)"
+
+#, c-format
msgid "Failed to merge submodule %s (commits don't follow merge-base)"
msgstr ""
"Подмодулът „%s“ не може да бъде ÑлÑÑ‚ (базата за Ñливане не предшеÑтва "
@@ -18219,6 +18271,86 @@ msgstr "ÐеуÑпешен анализ на обекта „%s“"
msgid "failed to read the cache"
msgstr "кешът не може да бъде прочетен"
+#, c-format
+msgid "failed to add packfile '%s'"
+msgstr "пакетниÑÑ‚ файл „%s“ не може да бъде добавен"
+
+#, c-format
+msgid "failed to open pack-index '%s'"
+msgstr "индекÑÑŠÑ‚ за пакети „%s“ не може да бъде отворен"
+
+#, c-format
+msgid "failed to locate object %d in packfile"
+msgstr "обект %d в Ð¿Ð°ÐºÐµÑ‚Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð» липÑва"
+
+msgid "cannot store reverse index file"
+msgstr "файлът за индекÑа не може да бъде Ñъхранен"
+
+#, c-format
+msgid "could not parse line: %s"
+msgstr "редът не може да Ñе анализира: „%s“"
+
+#, c-format
+msgid "malformed line: %s"
+msgstr "неправилен ред: „%s“."
+
+msgid "ignoring existing multi-pack-index; checksum mismatch"
+msgstr ""
+"индекÑÑŠÑ‚ за множеÑтво пакети Ñе преÑкача, защото Ñумата за проверка не "
+"Ñъвпада"
+
+msgid "could not load pack"
+msgstr "пакетът не може да Ñе зареди"
+
+#, c-format
+msgid "could not open index for %s"
+msgstr "индекÑÑŠÑ‚ за „%s“ не може да Ñе отвори"
+
+msgid "Adding packfiles to multi-pack-index"
+msgstr "ДобавÑне на пакетни файлове към Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети"
+
+#, c-format
+msgid "unknown preferred pack: '%s'"
+msgstr "непознат предпочитан пакет: %s"
+
+#, c-format
+msgid "cannot select preferred pack %s with no objects"
+msgstr ""
+"не може да изберете „%s“, който не Ñъдържа обекти, за предпочитан пакет"
+
+#, c-format
+msgid "did not see pack-file %s to drop"
+msgstr "пакетниÑÑ‚ файл за триене „%s“ не може да Ñе открие"
+
+#, c-format
+msgid "preferred pack '%s' is expired"
+msgstr "предпочитаниÑÑ‚ пакет „%s“ е оÑтарÑл"
+
+msgid "no pack files to index."
+msgstr "нÑма пакетни файлове за индекÑиране"
+
+msgid "refusing to write multi-pack .bitmap without any objects"
+msgstr ""
+"многопакетната битова маÑка без никакви обекти не може да бъде запазена"
+
+msgid "could not write multi-pack bitmap"
+msgstr "многопакетната битова маÑка не може да бъде запазена"
+
+msgid "could not write multi-pack-index"
+msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да бъде запазен"
+
+msgid "Counting referenced objects"
+msgstr "ПреброÑване на Ñвързаните обекти"
+
+msgid "Finding and deleting unreferenced packfiles"
+msgstr "ТърÑене и изтриване на неÑвързаните пакетни файлове"
+
+msgid "could not start pack-objects"
+msgstr "командата „pack-objects“ не може да бъде Ñтартирана"
+
+msgid "could not finish pack-objects"
+msgstr "командата „pack-objects“ не може да бъде завършена"
+
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr ""
"неправилен размер на откъÑа за разпределÑнето в индекÑа за множеÑтво пакети"
@@ -18304,74 +18436,6 @@ msgstr ""
"ÑтойноÑтта на отмеÑтването в индекÑа за множеÑтво пакети е извън диапазона"
#, c-format
-msgid "failed to add packfile '%s'"
-msgstr "пакетниÑÑ‚ файл „%s“ не може да бъде добавен"
-
-#, c-format
-msgid "failed to open pack-index '%s'"
-msgstr "индекÑÑŠÑ‚ за пакети „%s“ не може да бъде отворен"
-
-#, c-format
-msgid "failed to locate object %d in packfile"
-msgstr "обект %d в Ð¿Ð°ÐºÐµÑ‚Ð½Ð¸Ñ Ñ„Ð°Ð¹Ð» липÑва"
-
-msgid "cannot store reverse index file"
-msgstr "файлът за индекÑа не може да бъде Ñъхранен"
-
-#, c-format
-msgid "could not parse line: %s"
-msgstr "редът не може да Ñе анализира: „%s“"
-
-#, c-format
-msgid "malformed line: %s"
-msgstr "неправилен ред: „%s“."
-
-msgid "ignoring existing multi-pack-index; checksum mismatch"
-msgstr ""
-"индекÑÑŠÑ‚ за множеÑтво пакети Ñе преÑкача, защото Ñумата за проверка не "
-"Ñъвпада"
-
-msgid "could not load pack"
-msgstr "пакетът не може да Ñе зареди"
-
-#, c-format
-msgid "could not open index for %s"
-msgstr "индекÑÑŠÑ‚ за „%s“ не може да Ñе отвори"
-
-msgid "Adding packfiles to multi-pack-index"
-msgstr "ДобавÑне на пакетни файлове към Ð¸Ð½Ð´ÐµÐºÑ Ð·Ð° множеÑтво пакети"
-
-#, c-format
-msgid "unknown preferred pack: '%s'"
-msgstr "непознат предпочитан пакет: %s"
-
-#, c-format
-msgid "cannot select preferred pack %s with no objects"
-msgstr ""
-"не може да изберете „%s“, който не Ñъдържа обекти, за предпочитан пакет"
-
-#, c-format
-msgid "did not see pack-file %s to drop"
-msgstr "пакетниÑÑ‚ файл за триене „%s“ не може да Ñе открие"
-
-#, c-format
-msgid "preferred pack '%s' is expired"
-msgstr "предпочитаниÑÑ‚ пакет „%s“ е оÑтарÑл"
-
-msgid "no pack files to index."
-msgstr "нÑма пакетни файлове за индекÑиране"
-
-msgid "refusing to write multi-pack .bitmap without any objects"
-msgstr ""
-"многопакетната битова маÑка без никакви обекти не може да бъде запазена"
-
-msgid "could not write multi-pack bitmap"
-msgstr "многопакетната битова маÑка не може да бъде запазена"
-
-msgid "could not write multi-pack-index"
-msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да бъде запазен"
-
-#, c-format
msgid "failed to clear multi-pack-index at %s"
msgstr "индекÑÑŠÑ‚ за множеÑтво пакети не може да бъде изчиÑтен при „%s“"
@@ -18417,18 +18481,6 @@ msgstr "индекÑÑŠÑ‚ на пакета „%s“ не може да бъде
msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>"
msgstr "неправилно отмеÑтване на обект за oid[%d] = %s: %<PRIx64> != %<PRIx64>"
-msgid "Counting referenced objects"
-msgstr "ПреброÑване на Ñвързаните обекти"
-
-msgid "Finding and deleting unreferenced packfiles"
-msgstr "ТърÑене и изтриване на неÑвързаните пакетни файлове"
-
-msgid "could not start pack-objects"
-msgstr "командата „pack-objects“ не може да бъде Ñтартирана"
-
-msgid "could not finish pack-objects"
-msgstr "командата „pack-objects“ не може да бъде завършена"
-
#, c-format
msgid "unable to create lazy_dir thread: %s"
msgstr "не може да Ñе Ñъздаде нишка за директории (lazy_dir): %s"
@@ -18483,6 +18535,25 @@ msgstr ""
msgid "Bad %s value: '%s'"
msgstr "Зададена е лоша ÑтойноÑÑ‚ на променливата „%s“: „%s“"
+msgid "failed to decode tree entry"
+msgstr "запиÑÑŠÑ‚ в дърво не може да Ñе декодира"
+
+#, c-format
+msgid "failed to map tree entry for %s"
+msgstr "не може да Ñе открие ÑъответÑтвието на запиÑа в дърво за „%s“"
+
+#, c-format
+msgid "bad %s in commit"
+msgstr "неправилен Ð·Ð°Ð¿Ð¸Ñ â€ž%s“ в подаването"
+
+#, c-format
+msgid "unable to map %s %s in commit object"
+msgstr "не може да Ñе открие ÑъответÑтвието на „%s %s“ в обекта-подаване"
+
+#, c-format
+msgid "Failed to convert object from %s to %s"
+msgstr "ÐеуÑпешно преобразуване на „%s“ към „%s“"
+
#, c-format
msgid "object directory %s does not exist; check .git/objects/info/alternates"
msgstr ""
@@ -18589,6 +18660,10 @@ msgid "packed object %s (stored in %s) is corrupt"
msgstr "пакетираниÑÑ‚ обект „%s“ (в „%s“) е повреден"
#, c-format
+msgid "missing mapping of %s to %s"
+msgstr "липÑва ÑъответÑтвие на „%s“ към „%s“"
+
+#, c-format
msgid "unable to write file %s"
msgstr "файлът „%s“ не може да бъде запиÑан"
@@ -18643,6 +18718,10 @@ msgid "cannot read object for %s"
msgstr "обектът за „%s“ не може да Ñе прочете"
#, c-format
+msgid "cannot map object %s to %s"
+msgstr "липÑва ÑъответÑтвие на обекта „%s“ към „%s“"
+
+#, c-format
msgid "object fails fsck: %s"
msgstr "„fsck“ откри грешка в обект: „%s“"
@@ -19110,8 +19189,8 @@ msgstr "неправилна дата на Ñрок: „%s“"
#, c-format
msgid "option `%s' expects \"always\", \"auto\", or \"never\""
msgstr ""
-"опциÑта „%s“ изиÑква нÑÐºÐ¾Ñ Ð¾Ñ‚ ÑтойноÑтите: „always“ (винаги), "
-"„auto“ (автоматично) или „never“ (никога)"
+"опциÑта „%s“ изиÑква нÑÐºÐ¾Ñ Ð¾Ñ‚ ÑтойноÑтите: „always“ (винаги), „auto“ "
+"(автоматично) или „never“ (никога)"
#, c-format
msgid "malformed object name '%s'"
@@ -19165,6 +19244,18 @@ msgstr "непознат флаг „%c“"
msgid "unknown non-ascii option in string: `%s'"
msgstr "непозната ÑтойноÑÑ‚ извън „ascii“ в низа: „%s“"
+#, c-format
+msgid "[=<%s>]"
+msgstr "[=%s]"
+
+#, c-format
+msgid "[<%s>]"
+msgstr "[%s]"
+
+#, c-format
+msgid " <%s>"
+msgstr " %s"
+
msgid "..."
msgstr "…"
@@ -20056,6 +20147,78 @@ msgid "could not delete references: %s"
msgstr "Указателите не може да бъдат изтрити: %s"
#, c-format
+msgid "refname is dangerous: %s"
+msgstr "опаÑно име на указател: %s"
+
+#, c-format
+msgid "trying to write ref '%s' with nonexistent object %s"
+msgstr "опит за Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° указател „%s“ към обект, който не ÑъщеÑтвува: %s"
+
+#, c-format
+msgid "trying to write non-commit object %s to branch '%s'"
+msgstr "опит за запиÑване на обект, който не е подаване — %s, в клона „%s“"
+
+#, c-format
+msgid ""
+"multiple updates for 'HEAD' (including one via its referent '%s') are not "
+"allowed"
+msgstr ""
+"не Ñа позволени повече от една промѐни (включително чрез ÑÐ¾Ñ‡ÐµÑ‰Ð¸Ñ Ð³Ð¾ „%s“) на "
+"ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€žHEAD“"
+
+#, c-format
+msgid "cannot lock ref '%s': unable to resolve reference '%s'"
+msgstr ""
+"указателÑÑ‚ „%s“ не може да Ñе заключи: не може да Ñе открие към какво Ñочи "
+"указателÑÑ‚ „%s“"
+
+#, c-format
+msgid "cannot lock ref '%s': error reading reference"
+msgstr "указателÑÑ‚ „%s“ не може да Ñе заключи: грешка при четене на указателÑ"
+
+#, c-format
+msgid ""
+"multiple updates for '%s' (including one via symref '%s') are not allowed"
+msgstr ""
+"не Ñа позволени повече от една промѐни на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€ž%s“ (включително през "
+"ÑÐ¸Ð¼Ð²Ð¾Ð»Ð½Ð¸Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ» „%s“)"
+
+#, c-format
+msgid "cannot lock ref '%s': reference already exists"
+msgstr "указателÑÑ‚ „%s“ не може да Ñе заключи:cуказателÑÑ‚ вече ÑъщеÑтвува"
+
+#, c-format
+msgid "cannot lock ref '%s': reference is missing but expected %s"
+msgstr ""
+"указателÑÑ‚ „%s“ не може да Ñе заключи: указателÑÑ‚ липÑва, а Ñе очаква „%s“"
+
+#, c-format
+msgid "cannot lock ref '%s': is at %s but expected %s"
+msgstr ""
+"указателÑÑ‚ „%s“ не може да Ñе заключи: той Ñочи към „%s“, а Ñе очаква да "
+"Ñочи към „%s“"
+
+#, c-format
+msgid "reftable: transaction prepare: %s"
+msgstr "таблица Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸: подготовка на транзакциÑ: %s"
+
+#, c-format
+msgid "reftable: transaction failure: %s"
+msgstr "таблица Ñ ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ð¸: неуÑпешна транзакциÑ: %s"
+
+#, c-format
+msgid "unable to compact stack: %s"
+msgstr "Ñтекът не може да Ñе Ñвие: %s"
+
+#, c-format
+msgid "refname %s not found"
+msgstr "името на ÑƒÐºÐ°Ð·Ð°Ñ‚ÐµÐ»Ñ â€ž%s“ не може да бъде открито"
+
+#, c-format
+msgid "refname %s is a symbolic ref, copying it is not supported"
+msgstr "името на указател „%s“ е Ñимволен указател, не може да Ñе копира"
+
+#, c-format
msgid "invalid refspec '%s'"
msgstr "неправилен указател: „%s“"
@@ -20066,6 +20229,10 @@ msgstr ""
"„%s“"
#, c-format
+msgid "unknown value for object-format: %s"
+msgstr "непозната ÑтойноÑÑ‚ за „--object-format“: „%s“"
+
+#, c-format
msgid "%sinfo/refs not valid: is this a git repository?"
msgstr "„%sinfo/refs“ е неизползваемо, проверете дали е хранилище на git"
@@ -20521,7 +20688,18 @@ msgstr ""
"липÑва"
#, c-format
-msgid "could not get commit for ancestry-path argument %s"
+msgid "%s exists but is a symbolic ref"
+msgstr "„%s“ ÑъщеÑтвува и не е Ñимволна връзка"
+
+msgid ""
+"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD or REBASE_HEAD"
+msgstr ""
+"„--merge“ изиÑква нÑкой от пÑевдоуказателите „MERGE_HEAD“, "
+"„CHERRY_PICK_HEAD“, „REVERT_HEAD“ или „REBASE_HEAD“"
+
+#, c-format
+msgid "could not get commit for --ancestry-path argument %s"
msgstr "подаването „%s“ към опциÑта „--ancestry-path“ не може да бъде получено"
msgid "--unpacked=<packfile> no longer supported"
@@ -20815,6 +20993,19 @@ msgid "unknown action: %d"
msgstr "неизвеÑтно дейÑтвие: %d"
msgid ""
+"Resolve all conflicts manually, mark them as resolved with\n"
+"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
+"You can instead skip this commit: run \"git rebase --skip\".\n"
+"To abort and get back to the state before \"git rebase\", run \"git rebase --"
+"abort\"."
+msgstr ""
+"След коригирането на конфликтите отбележете решаването им чрез:\n"
+"„git add/rm ФÐЙЛ_С_КОÐФЛИКТ…“ и изпълнете „git rebase --continue“.\n"
+"Ðко предпочитате да преÑкочите тази кръпка, изпълнете „git rebase --skip“.\n"
+"За да откажете пребазирането и да Ñе върнете към първоначалното ÑÑŠÑтоÑние,\n"
+"изпълнете „git rebase --abort“."
+
+msgid ""
"after resolving the conflicts, mark the corrected paths\n"
"with 'git add <paths>' or 'git rm <paths>'"
msgstr ""
@@ -21065,10 +21256,6 @@ msgid "could not update %s"
msgstr "„%s“ не може да Ñе обнови"
#, c-format
-msgid "could not parse commit %s"
-msgstr "подаването „%s“ не може да бъде анализирано"
-
-#, c-format
msgid "could not parse parent commit %s"
msgstr "родителÑкото подаване „%s“ не може да бъде анализирано"
@@ -21174,10 +21361,6 @@ msgid "invalid command '%.*s'"
msgstr "неправилна команда „%.*s“"
#, c-format
-msgid "%s does not accept arguments: '%s'"
-msgstr "„%s“ не приема аргументи: „%s“"
-
-#, c-format
msgid "missing arguments for %s"
msgstr "„%s“ изиÑква аргументи"
@@ -21651,6 +21834,10 @@ msgstr ""
"не може да Ñе зададе текуща работна Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ Ð¿Ñ€Ð¸ неправилни наÑтройки"
#, c-format
+msgid "'%s' already specified as '%s'"
+msgstr "„%s“ вече ÑъщеÑтвува като „%s“"
+
+#, c-format
msgid "Expected git repo version <= %d, found %d"
msgstr "Очаква Ñе верÑÐ¸Ñ Ð½Ð° хранилището на git <= %d, а не %d"
@@ -21848,6 +22035,21 @@ msgstr "обектът в индекÑа е директориÑ, но не ча
msgid "cannot use split index with a sparse index"
msgstr "разделѐн Ð¸Ð½Ð´ÐµÐºÑ Ð½Ðµ може да Ñе ползва чаÑтичен индекÑ"
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not start with '('"
+msgstr "неправилен формат за „%s“: елементът „%s“ не започва Ñ â€ž(“"
+
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not end in ')'"
+msgstr "неправилен формат за „%s“: елементът „%s“ не завършва Ñ â€ž)“"
+
+#. TRANSLATORS: %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: %%%.*s"
+msgstr "неправилен формат за „%s“: %%%.*s"
+
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#, c-format
msgid "%u.%2.2u GiB"
@@ -22175,29 +22377,6 @@ msgstr "непозната ÑтойноÑÑ‚ „%s“ за наÑтройката
msgid "empty trailer token in trailer '%.*s'"
msgstr "празна завършваща лекÑема в епилога „%.*s“"
-#, c-format
-msgid "could not read input file '%s'"
-msgstr "входниÑÑ‚ файл „%s“ не може да бъде прочетен"
-
-#, c-format
-msgid "could not stat %s"
-msgstr "Ðе може да Ñе получи Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ñ‡Ñ€ÐµÐ· „stat“ за „%s“"
-
-#, c-format
-msgid "file %s is not a regular file"
-msgstr "„%s“ не е обикновен файл"
-
-#, c-format
-msgid "file %s is not writable by user"
-msgstr "„%s“: нÑма права̀ за запиÑване на файла"
-
-msgid "could not open temporary file"
-msgstr "временниÑÑ‚ файл не може да Ñе отвори"
-
-#, c-format
-msgid "could not rename temporary file to %s"
-msgstr "временниÑÑ‚ файл не може да Ñе преименува на „%s“"
-
msgid "full write to remote helper failed"
msgstr "неуÑпешен пълен Ð·Ð°Ð¿Ð¸Ñ ÐºÑŠÐ¼ наÑрещната помощна програма"
@@ -22301,7 +22480,7 @@ msgstr ""
"изброÑване на указателите"
#, c-format
-msgid "helper %s does not support 'force'"
+msgid "helper %s does not support '--force'"
msgstr "наÑрещната помощна програма „%s“ не поддържа опциÑта „--force“"
msgid "couldn't run fast-export"
@@ -22715,6 +22894,10 @@ msgstr "неправилен номер на порт"
msgid "invalid '..' path segment"
msgstr "неправилна чаÑÑ‚ от Ð¿ÑŠÑ‚Ñ â€ž..“"
+#, c-format
+msgid "error: unable to format message: %s\n"
+msgstr "ГРЕШКÐ: Ñъобщението не може да Ñе форматира: %s\n"
+
msgid "usage: "
msgstr "употреба: "
@@ -23539,8 +23722,8 @@ msgstr "ГРЕШКÐ: не може да Ñе извлече Ð°Ð´Ñ€ÐµÑ Ð¾Ñ‚ „
#. at this point.
msgid "What to do with this address? ([q]uit|[d]rop|[e]dit): "
msgstr ""
-"Какво да Ñе направи Ñ Ñ‚Ð¾Ð·Ð¸ адреÑ? „q“ (Ñпиране), „d“ (изтриване), "
-"„e“ (редактиране): "
+"Какво да Ñе направи Ñ Ñ‚Ð¾Ð·Ð¸ адреÑ? „q“ (Ñпиране), „d“ (изтриване), „e“ "
+"(редактиране): "
#, perl-format
msgid "CA path \"%s\" does not exist"
diff --git a/po/de.po b/po/de.po
index 37d6c80998..2946566597 100644
--- a/po/de.po
+++ b/po/de.po
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2024-02-17 18:07+0100\n"
-"PO-Revision-Date: 2024-02-17 18:14+0100\n"
+"POT-Creation-Date: 2024-04-26 16:16+0200\n"
+"PO-Revision-Date: 2024-04-26 16:22+0200\n"
"Last-Translator: Ralf Thielow <ralf.thielow@gmail.com>\n"
"Language-Team: German\n"
"Language: de\n"
@@ -512,12 +512,12 @@ msgid ""
"---\n"
"To remove '%c' lines, make them ' ' lines (context).\n"
"To remove '%c' lines, delete them.\n"
-"Lines starting with %c will be removed.\n"
+"Lines starting with %s will be removed.\n"
msgstr ""
"---\n"
"Um '%c' Zeilen zu entfernen, machen Sie aus diesen ' ' Zeilen (Kontext).\n"
"Um '%c' Zeilen zu entfernen, löschen Sie diese.\n"
-"Zeilen, die mit %c beginnen, werden entfernt.\n"
+"Zeilen, die mit %s beginnen, werden entfernt.\n"
msgid ""
"If it does not apply cleanly, you will be given an opportunity to\n"
@@ -566,6 +566,7 @@ msgid ""
"/ - search for a hunk matching the given regex\n"
"s - split the current hunk into smaller hunks\n"
"e - manually edit the current hunk\n"
+"p - print the current hunk\n"
"? - print help\n"
msgstr ""
"j - diesen Patch-Block unbestimmt lassen, nächsten unbestimmten Patch-Block "
@@ -575,9 +576,10 @@ msgstr ""
"Block anzeigen\n"
"K - diesen Patch-Block unbestimmt lassen, vorherigen Patch-Block anzeigen\n"
"g - Patch-Block zum Hinspringen auswählen\n"
-"/ - nach Patch-Block suchen, der gegebenem regulärem Ausdruck entspricht\n"
+"/ - nach Patch-Block suchen, der regulärem Ausdruck entspricht\n"
"s - aktuellen Patch-Block in kleinere Patch-Blöcke aufteilen\n"
"e - aktuellen Patch-Block manuell editieren\n"
+"p - aktuellen Patch-Block anzeigen\n"
"? - Hilfe anzeigen\n"
msgid "No previous hunk"
@@ -640,8 +642,8 @@ msgstr ""
"Deaktivieren Sie diese Nachricht mit \"git config advice.%s false\""
#, c-format
-msgid "%shint: %.*s%s\n"
-msgstr "%sHinweis: %.*s%s\n"
+msgid "%shint:%s%.*s%s\n"
+msgstr "%sHinweis:%s%.*s%s\n"
msgid "Cherry-picking is not possible because you have unmerged files."
msgstr ""
@@ -1160,10 +1162,6 @@ msgstr[0] "Wende Patch %%s mit %d Zurückweisung an..."
msgstr[1] "Wende Patch %%s mit %d Zurückweisungen an..."
#, c-format
-msgid "truncating .rej filename to %.*s.rej"
-msgstr "Verkürze Name von .rej Datei zu %.*s.rej"
-
-#, c-format
msgid "cannot open %s"
msgstr "kann '%s' nicht öffnen"
@@ -1600,6 +1598,10 @@ msgid "could not create file '%s'"
msgstr "konnte Datei '%s' nicht erstellen"
#, c-format
+msgid "unable to start 'show' for object '%s'"
+msgstr "konnte 'show' für Objekt '%s' nicht starten"
+
+#, c-format
msgid "could not read file '%s'"
msgstr "Konnte Datei '%s' nicht lesen"
@@ -1751,6 +1753,9 @@ msgstr ""
msgid "'%s' is not a valid branch name"
msgstr "'%s' ist kein gültiger Branchname"
+msgid "See `man git check-ref-format`"
+msgstr "Siehe `man git check-ref-format`"
+
#, c-format
msgid "a branch named '%s' already exists"
msgstr "Branch '%s' existiert bereits"
@@ -1957,14 +1962,8 @@ msgstr ""
msgid "adding embedded git repository: %s"
msgstr "Füge eingebettetes Repository hinzu: %s"
-msgid ""
-"Use -f if you really want to add them.\n"
-"Turn this message off by running\n"
-"\"git config advice.addIgnoredFile false\""
-msgstr ""
-"Nutzen Sie die Option -f, wenn sie wirklich hinzugefügt werden sollen.\n"
-"Um diese Meldung abzuschalten, führen Sie folgenden Befehl aus:\n"
-"\"git config advice.addIgnoredFile false\""
+msgid "Use -f if you really want to add them."
+msgstr "Verwenden Sie -f, wenn Sie diese wirklich hinzufügen möchten."
msgid "adding files failed"
msgstr "Hinzufügen von Dateien fehlgeschlagen"
@@ -1982,14 +1981,8 @@ msgstr ""
msgid "Nothing specified, nothing added.\n"
msgstr "Nichts spezifiziert, nichts hinzugefügt.\n"
-msgid ""
-"Maybe you wanted to say 'git add .'?\n"
-"Turn this message off by running\n"
-"\"git config advice.addEmptyPathspec false\""
-msgstr ""
-"Eventuell meinten Sie 'git add .'?\n"
-"Um diese Meldung abzuschalten, führen Sie folgenden Befehl aus:\n"
-"\"git config advice.addEmptyPathspec false\""
+msgid "Maybe you wanted to say 'git add .'?"
+msgstr "Meinten Sie vielleicht 'git add .'?"
msgid "index file corrupt"
msgstr "Index-Datei beschädigt"
@@ -2066,21 +2059,22 @@ msgid "Failed to split patches."
msgstr "Fehler beim Aufteilen der Patches."
#, c-format
-msgid "When you have resolved this problem, run \"%s --continue\"."
+msgid "When you have resolved this problem, run \"%s --continue\".\n"
msgstr ""
-"Wenn Sie das Problem aufgelöst haben, führen Sie \"%s --continue\" aus."
+"Wenn Sie dieses Problem behoben haben, führen Sie \"%s --continue\" aus.\n"
#, c-format
-msgid "If you prefer to skip this patch, run \"%s --skip\" instead."
+msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n"
msgstr ""
"Falls Sie diesen Patch auslassen möchten, führen Sie stattdessen \"%s --"
-"skip\" aus."
+"skip\" aus.\n"
#, c-format
-msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"."
+msgid ""
+"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"
msgstr ""
-"Um den leeren Patch als einen leeren Commit zu speichern, führen Sie \"%s --"
-"allow-empty\" aus."
+"Um den leeren Patch als leeren Commit aufzuzeichnen, führen Sie \"%s --allow-"
+"empty\" aus.\n"
#, c-format
msgid "To restore the original branch and stop patching, run \"%s --abort\"."
@@ -2950,11 +2944,11 @@ msgstr ""
msgid ""
"Please edit the description for the branch\n"
" %s\n"
-"Lines starting with '%c' will be stripped.\n"
+"Lines starting with '%s' will be stripped.\n"
msgstr ""
"Bitte ändern Sie die Beschreibung für den Branch\n"
" %s\n"
-"Zeilen, die mit '%c' beginnen, werden entfernt.\n"
+"Zeilen, die mit '%s' beginnen, werden entfernt.\n"
msgid "Generic options"
msgstr "Allgemeine Optionen"
@@ -3163,10 +3157,12 @@ msgid "not run from a git repository - no hooks to show\n"
msgstr "nicht in einem Git-Repository ausgeführt - keine Hooks zum Anzeigen\n"
msgid ""
-"git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"git bugreport [(-o | --output-directory) <path>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
" [--diagnose[=<mode>]]"
msgstr ""
-"git bugreport [(-o | --output-directory) <Pfad>] [(-s | --suffix) <Format>]\n"
+"git bugreport [(-o | --output-directory) <Pfad>]\n"
+" [(-s | --suffix) <Format> | --no-suffix]\n"
" [--diagnose[=<Modus>]]"
msgid ""
@@ -3660,6 +3656,10 @@ msgstr ""
msgid "path '%s' is unmerged"
msgstr "Pfad '%s' ist nicht zusammengeführt"
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr "konnte \"Tree\"-Objekt (%s) nicht lesen"
+
msgid "you need to resolve your current index first"
msgstr "Sie müssen zuerst die Konflikte in Ihrem aktuellen Index auflösen."
@@ -3898,6 +3898,10 @@ msgstr "Kann Branch nicht zu Nicht-Commit '%s' wechseln"
msgid "missing branch or commit argument"
msgstr "Branch- oder Commit-Argument fehlt"
+#, c-format
+msgid "unknown conflict style '%s'"
+msgstr "unbekannter Konfliktstil '%s'"
+
msgid "perform a 3-way merge with the new branch"
msgstr "einen 3-Wege-Merge mit dem neuen Branch ausführen"
@@ -4157,19 +4161,10 @@ msgstr "auch ignorierte Dateien löschen"
msgid "remove only ignored files"
msgstr "nur ignorierte Dateien löschen"
-msgid ""
-"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to "
-"clean"
-msgstr ""
-"clean.requireForce auf \"true\" gesetzt und weder -i, -n noch -f gegeben; "
-"\"clean\" verweigert"
-
-msgid ""
-"clean.requireForce defaults to true and neither -i, -n, nor -f given; "
-"refusing to clean"
+msgid "clean.requireForce is true and -f not given: refusing to clean"
msgstr ""
-"clean.requireForce standardmäßig auf \"true\" gesetzt und weder -i, -n noch -"
-"f gegeben; \"clean\" verweigert"
+"clean.requireForce ist 'true' und -f ist nicht angegeben: clean wird "
+"verweigert"
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<Optionen>] [--] <Repository> [<Verzeichnis>]"
@@ -4183,8 +4178,8 @@ msgstr "kein Auschecken"
msgid "create a bare repository"
msgstr "ein Bare-Repository erstellen"
-msgid "create a mirror repository (implies bare)"
-msgstr "ein Spiegelarchiv erstellen (impliziert bare)"
+msgid "create a mirror repository (implies --bare)"
+msgstr "ein Spiegel-Repository erstellen (impliziert --bare)"
msgid "to clone from a local repository"
msgstr "von einem lokalen Repository klonen"
@@ -4519,6 +4514,10 @@ msgstr "Abstand zum rechten Rand auffüllen"
msgid "padding space between columns"
msgstr "Abstand zwischen Spalten auffüllen"
+#, c-format
+msgid "%s must be non-negative"
+msgstr "%s muss nicht-negativ sein"
+
msgid "--command must be the first argument"
msgstr "--command muss an erster Stelle stehen"
@@ -4837,38 +4836,38 @@ msgstr "Konnte Commit-Vorlage nicht schreiben"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored.\n"
+"with '%s' will be ignored.\n"
msgstr ""
"Bitte geben Sie eine Commit-Beschreibung für Ihre Änderungen ein. Zeilen,\n"
-"die mit '%c' beginnen, werden ignoriert.\n"
+"die mit '%s' beginnen, werden ignoriert.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored, and an empty message aborts the commit.\n"
+"with '%s' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
"Bitte geben Sie eine Commit-Beschreibung für Ihre Änderungen ein. Zeilen,\n"
-"die mit '%c' beginnen, werden ignoriert, und eine leere Beschreibung\n"
+"die mit '%s' beginnen, werden ignoriert, und eine leere Beschreibung\n"
"bricht den Commit ab.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
msgstr ""
"Bitte geben Sie eine Commit-Beschreibung für Ihre Änderungen ein. Zeilen,\n"
-"die mit '%c' beginnen, werden beibehalten; wenn Sie möchten, können Sie\n"
+"die mit '%s' beginnen, werden beibehalten; wenn Sie möchten, können Sie\n"
"diese entfernen.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
"Bitte geben Sie eine Commit-Beschreibung für Ihre Änderungen ein. Zeilen, "
"die\n"
-"mit '%c' beginnen, werden beibehalten; wenn Sie möchten, können Sie diese "
+"mit '%s' beginnen, werden beibehalten; wenn Sie möchten, können Sie diese "
"entfernen.\n"
"Eine leere Beschreibung bricht den Commit ab.\n"
@@ -5319,6 +5318,10 @@ msgstr "Wert"
msgid "with --get, use default value when missing entry"
msgstr "mit --get, benutze den Standardwert, wenn der Eintrag fehlt"
+msgid "human-readable comment string (# will be prepended as needed)"
+msgstr ""
+"menschenlesbare Kommentarzeichenfolge (# wird bei Bedarf vorangestellt)"
+
#, c-format
msgid "wrong number of arguments, should be %d"
msgstr "Falsche Anzahl von Argumenten - sollte %d sein."
@@ -5413,6 +5416,10 @@ msgstr ""
msgid "--default is only applicable to --get"
msgstr "--default ist nur anwendbar auf --get"
+msgid "--comment is only applicable to add/set/replace operations"
+msgstr ""
+"--comment darf nur für die Operationen add/set/replace verwendet werden"
+
msgid "--fixed-value only applies with 'value-pattern'"
msgstr "--fixed-value wird nur zusammen mit 'Wert-Muster' angewendet"
@@ -6284,6 +6291,9 @@ msgstr "nur Referenzen ausgeben, die diesen Commit nicht enthalten"
msgid "read reference patterns from stdin"
msgstr "Referenzmuster von Standard-Eingabe lesen"
+msgid "also include HEAD ref and pseudorefs"
+msgstr "auch die Referenz HEAD und Pseudoreferenzen einschließen"
+
msgid "unknown arguments supplied with --stdin"
msgstr "unbekannte Argumente mit --stdin geliefert"
@@ -6909,10 +6919,6 @@ msgid "no threads support, ignoring %s"
msgstr "keine Unterstützung von Threads, '%s' wird ignoriert"
#, c-format
-msgid "unable to read tree (%s)"
-msgstr "konnte \"Tree\"-Objekt (%s) nicht lesen"
-
-#, c-format
msgid "unable to read tree %s"
msgstr "konnte \"Tree\"-Objekt (%s) nicht lesen"
@@ -7527,7 +7533,7 @@ msgstr "--separate-git-dir nicht kompatibel mit Bare-Repository"
msgid ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n"
+" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
" [--parse] [<file>...]"
msgstr ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
@@ -7535,6 +7541,32 @@ msgstr ""
"[(=|:)<Wert>])...]\n"
" [--parse] [<Datei>...]"
+#, c-format
+msgid "could not stat %s"
+msgstr "Konnte '%s' nicht lesen"
+
+#, c-format
+msgid "file %s is not a regular file"
+msgstr "Datei '%s' ist keine reguläre Datei"
+
+#, c-format
+msgid "file %s is not writable by user"
+msgstr "Datei %s ist vom Benutzer nicht beschreibbar."
+
+msgid "could not open temporary file"
+msgstr "konnte temporäre Datei '%s' nicht öffnen"
+
+#, c-format
+msgid "could not read input file '%s'"
+msgstr "Konnte Eingabe-Datei '%s' nicht lesen"
+
+msgid "could not read from stdin"
+msgstr "konnte nicht von der Standard-Eingabe lesen"
+
+#, c-format
+msgid "could not rename temporary file to %s"
+msgstr "konnte temporäre Datei nicht zu %s umbenennen"
+
msgid "edit files in place"
msgstr "vorhandene Dateien direkt bearbeiten"
@@ -7929,18 +7961,6 @@ msgstr ""
msgid "could not get object info about '%s'"
msgstr "konnte Objekt-Informationen über '%s' nicht bestimmen"
-#, c-format
-msgid "bad ls-files format: element '%s' does not start with '('"
-msgstr "ungültiges ls-files-Format: Element '%s' fängt nicht mit '(' an"
-
-#, c-format
-msgid "bad ls-files format: element '%s' does not end in ')'"
-msgstr "ungültiges ls-files-Format: Element '%s' endet nicht auf ')'"
-
-#, c-format
-msgid "bad ls-files format: %%%.*s"
-msgstr "ungültiges ls-files-Format: %%%.*s"
-
msgid "git ls-files [<options>] [<file>...]"
msgstr "git ls-files [<Optionen>] [<Datei>...]"
@@ -8078,18 +8098,6 @@ msgstr "zusätzlich zum Objekt die darauf verweisenden Referenzen anzeigen"
msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
msgstr "git ls-tree [<Optionen>] <Commit-Referenz> [<Pfad>...]"
-#, c-format
-msgid "bad ls-tree format: element '%s' does not start with '('"
-msgstr "ungültiges ls-tree-Format: Element '%s' fängt nicht mit '(' an"
-
-#, c-format
-msgid "bad ls-tree format: element '%s' does not end in ')'"
-msgstr "ungültiges ls-tree-Format: Element '%s' endet nicht mit ')'"
-
-#, c-format
-msgid "bad ls-tree format: %%%.*s"
-msgstr "ungültiges ls-tree-Format: %%%.*s"
-
msgid "only show trees"
msgstr "nur Verzeichnisse anzeigen"
@@ -8279,6 +8287,10 @@ msgstr "Konnte Referenz '%s' nicht auflösen"
msgid "Merging %s with %s\n"
msgstr "Führe %s mit %s zusammen\n"
+#, c-format
+msgid "could not parse as tree '%s'"
+msgstr "'%s' konnte nicht als Tree geparst werden"
+
msgid "not something we can merge"
msgstr "nichts was wir zusammenführen können"
@@ -8487,10 +8499,10 @@ msgstr "Eine leere Commit-Beschreibung bricht den Commit ab.\n"
#, c-format
msgid ""
-"Lines starting with '%c' will be ignored, and an empty message aborts\n"
+"Lines starting with '%s' will be ignored, and an empty message aborts\n"
"the commit.\n"
msgstr ""
-"Zeilen, die mit '%c' beginnen, werden ignoriert,\n"
+"Zeilen, die mit '%s' beginnen, werden ignoriert,\n"
"und eine leere Beschreibung bricht den Commit ab.\n"
msgid "Empty commit message."
@@ -8655,9 +8667,6 @@ msgstr "konnte getaggtes Objekt '%s' nicht lesen"
msgid "object '%s' tagged as '%s', but is a '%s' type"
msgstr "Objekt '%s' als '%s' getaggt, aber ist ein '%s' Typ"
-msgid "could not read from stdin"
-msgstr "konnte nicht von der Standard-Eingabe lesen"
-
msgid "tag on stdin did not pass our strict fsck check"
msgstr ""
"Tag von der Standardeingabe für unsere strenge Überprüfung bei fsck ungültig"
@@ -8924,10 +8933,6 @@ msgstr "git notes prune [<Optionen>]"
msgid "Write/edit the notes for the following object:"
msgstr "Schreiben/Bearbeiten der Notizen für das folgende Objekt:"
-#, c-format
-msgid "unable to start 'show' for object '%s'"
-msgstr "konnte 'show' für Objekt '%s' nicht starten"
-
msgid "could not read 'show' output"
msgstr "Konnte Ausgabe von 'show' nicht lesen."
@@ -9579,10 +9584,11 @@ msgid "refusing to run without --i-still-use-this"
msgstr "Ausführung ohne --i-still-use-this verweigert"
msgid ""
-"git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude "
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
"<pattern>]"
msgstr ""
-"git pack-refs [--all] [--no-prune] [--include <Muster>] [--exclude <Muster>]"
+"git pack-refs [--all] [--no-prune] [--auto] [--include <Muster>] [--exclude "
+"<Muster>]"
msgid "pack everything"
msgstr "alles packen"
@@ -9590,6 +9596,9 @@ msgstr "alles packen"
msgid "prune loose refs (default)"
msgstr "lose Referenzen entfernen (Standard)"
+msgid "auto-pack refs as needed"
+msgstr "auto-pack-Referenzen nach Bedarf"
+
msgid "references to include"
msgstr "einzubeziehende Referenzen"
@@ -9826,7 +9835,7 @@ msgid "git push [<options>] [<repository> [<refspec>...]]"
msgstr "git push [<Optionen>] [<Repository> [<Refspec>...]]"
msgid "tag shorthand without <tag>"
-msgstr "Kurzschrift für Tag ohne <Tag>"
+msgstr "Kurzschrift für das Tag ohne <Tag>"
msgid "--delete only accepts plain target ref names"
msgstr "--delete akzeptiert nur reine Referenznamen als Ziel"
@@ -10281,21 +10290,6 @@ msgstr "Ignoriere ungültiges allow_rerere_autoupdate: '%s'"
msgid "could not remove '%s'"
msgstr "Konnte '%s' nicht löschen"
-msgid ""
-"Resolve all conflicts manually, mark them as resolved with\n"
-"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
-"You can instead skip this commit: run \"git rebase --skip\".\n"
-"To abort and get back to the state before \"git rebase\", run \"git rebase --"
-"abort\"."
-msgstr ""
-"Lösen Sie alle Konflikte manuell auf, markieren Sie diese mit\n"
-"\"git add/rm <konfliktbehaftete_Dateien>\" und führen Sie dann\n"
-"\"git rebase --continue\" aus.\n"
-"Sie können auch stattdessen diesen Commit auslassen, indem\n"
-"Sie \"git rebase --skip\" ausführen.\n"
-"Um abzubrechen und zurück zum Zustand vor \"git rebase\" zu gelangen,\n"
-"führen Sie \"git rebase --abort\" aus."
-
#, c-format
msgid ""
"\n"
@@ -10328,13 +10322,16 @@ msgstr ""
"Optionen für \"am\" und Optionen für \"merge\" können nicht gemeinsam "
"verwendet werden"
+msgid "--empty=ask is deprecated; use '--empty=stop' instead."
+msgstr "--empty=ask ist veraltet; verwenden Sie stattdessen '--empty=stop'."
+
#, c-format
msgid ""
"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
-"\"ask\"."
+"\"stop\"."
msgstr ""
"nicht erkannter leerer Typ '%s'; gültige Werte sind \"drop\", \"keep\", und "
-"\"ask\"."
+"\"stop\"."
msgid ""
"--rebase-merges with an empty string argument is deprecated and will stop "
@@ -10522,8 +10519,8 @@ msgstr ""
"'preserve' gesetzt, was nicht länger unterstützt wird; nutzen Sie\n"
"stattdessen 'merges'"
-msgid "No rebase in progress?"
-msgstr "Kein Rebase im Gange?"
+msgid "no rebase in progress"
+msgstr "kein Rebase im Gange"
msgid "The --edit-todo action can only be used during interactive rebase."
msgstr ""
@@ -10722,6 +10719,9 @@ msgstr "Sie müssen ein Verzeichnis angeben"
msgid "git reflog [show] [<log-options>] [<ref>]"
msgstr "git reflog [show] [<log-Optionen>] [<Referenz>]"
+msgid "git reflog list"
+msgstr "git reflog list"
+
msgid ""
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
" [--rewrite] [--updateref] [--stale-fix]\n"
@@ -10748,6 +10748,10 @@ msgstr "git reflog exists <Referenz>"
msgid "invalid timestamp '%s' given to '--%s'"
msgstr "ungültiger Zeitstempel '%s' für '--%s'"
+#, c-format
+msgid "%s does not accept arguments: '%s'"
+msgstr "%s akzeptiert keine Argumente: '%s'"
+
msgid "do not actually prune any entries"
msgstr "Einträge nicht wirklich löschen"
@@ -10877,8 +10881,8 @@ msgstr ""
"\t benutzen Sie stattdessen --mirror=fetch oder --mirror=push"
#, c-format
-msgid "unknown mirror argument: %s"
-msgstr "unbekanntes Argument für Option mirror: %s"
+msgid "unknown --mirror argument: %s"
+msgstr "unbekanntes --mirror Argument: %s"
msgid "fetch the remote branches"
msgstr "die Remote-Branches anfordern"
@@ -11254,6 +11258,9 @@ msgstr ""
"Konnte 'pack-objects' für das Neupacken von Objekten aus partiell geklonten\n"
"Remote-Repositories nicht starten."
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "promisor-Objekte konnten nicht an pack-objects übergeben werden"
+
msgid "repack: Expecting full hex object ID lines only from pack-objects."
msgstr ""
"repack: Erwarte Zeilen mit vollständiger Hex-Objekt-ID nur von pack-objects."
@@ -11861,6 +11868,13 @@ msgstr "--default benötigt ein Argument"
msgid "--prefix requires an argument"
msgstr "--prefix benötigt ein Argument"
+msgid "no object format specified"
+msgstr "kein Objektformat angegeben"
+
+#, c-format
+msgid "unsupported object format: %s"
+msgstr "nicht unterstütztes Objekt-Format: %s"
+
#, c-format
msgid "unknown mode for --abbrev-ref: %s"
msgstr "unbekannter Modus für --abbrev-ref: %s"
@@ -11943,8 +11957,8 @@ msgstr "ursprüngliche, leere Commits erhalten"
msgid "allow commits with empty messages"
msgstr "Commits mit leerer Beschreibung erlauben"
-msgid "keep redundant, empty commits"
-msgstr "redundante, leere Commits behalten"
+msgid "deprecated: use --empty=keep instead"
+msgstr "veraltet: benutzen Sie stattdessen --empty=keep"
msgid "use the 'reference' format to refer to commits"
msgstr "das 'reference' Format nutzen, um auf Commits zu verweisen"
@@ -13318,26 +13332,26 @@ msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be ignored.\n"
+"Lines starting with '%s' will be ignored.\n"
msgstr ""
"\n"
-"Geben Sie eine Beschreibung für Tag\n"
+"Geben Sie eine Beschreibung für das Tag:\n"
" %s\n"
-"ein. Zeilen, die mit '%c' beginnen, werden ignoriert.\n"
+"ein. Zeilen, die mit '%s' beginnen, werden ignoriert.\n"
#, c-format
msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be kept; you may remove them yourself if you "
+"Lines starting with '%s' will be kept; you may remove them yourself if you "
"want to.\n"
msgstr ""
"\n"
-"Geben Sie eine Beschreibung für Tag\n"
+"Geben Sie eine Beschreibung für das Tag\n"
" %s\n"
-"ein. Zeilen, die mit '%c' beginnen, werden behalten; Sie dürfen diese\n"
-"selbst entfernen wenn Sie möchten.\n"
+"ein. Zeilen, die mit '%s' beginnen, werden behalten; Sie dürfen diese\n"
+"selbst entfernen, wenn Sie möchten.\n"
msgid "unable to sign the tag"
msgstr "konnte Tag nicht signieren"
@@ -13422,6 +13436,9 @@ msgstr "nur Tags ausgeben, die nicht gemerged wurden"
msgid "print only tags of the object"
msgstr "nur Tags von dem Objekt ausgeben"
+msgid "could not start 'git column'"
+msgstr "konnte 'git column' nicht starten"
+
#, c-format
msgid "the '%s' option is only allowed in list mode"
msgstr "die Option '%s' ist nur im Listenmodus erlaubt"
@@ -13685,12 +13702,11 @@ msgstr ""
msgid "fsmonitor disabled"
msgstr "Dateisystem-Monitor deaktiviert"
-msgid "git update-ref [<options>] -d <refname> [<old-val>]"
-msgstr "git update-ref [<Optionen>] -d <Referenzname> [<alter-Wert>]"
+msgid "git update-ref [<options>] -d <refname> [<old-oid>]"
+msgstr "git update-ref [<Optionen>] -d <Referenzname> [<alte-oid>]"
-msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]"
-msgstr ""
-"git update-ref [<Optionen>] <Referenzname> <neuer-Wert> [<alter-Wert>]"
+msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]"
+msgstr "git update-ref [<Optionen>] <Referenzname> <neue-oid> [<alte-oid>]"
msgid "git update-ref [<options>] --stdin [-z]"
msgstr "git update-ref [<Optionen>] --stdin [-z]"
@@ -15099,6 +15115,10 @@ msgid "Verifying commits in commit graph"
msgstr "Commit in Commit-Graph überprüfen"
#, c-format
+msgid "could not parse commit %s"
+msgstr "Konnte Commit %s nicht parsen."
+
+#, c-format
msgid "%s %s is not a commit!"
msgstr "%s %s ist kein Commit!"
@@ -15537,8 +15557,13 @@ msgstr "Länge für Abkürzung von Commit-IDs außerhalb des Bereichs: %d"
msgid "bad zlib compression level %d"
msgstr "ungültiger zlib Komprimierungsgrad %d"
-msgid "core.commentChar should only be one ASCII character"
-msgstr "core.commentChar sollte nur ein ASCII-Zeichen sein"
+#, c-format
+msgid "%s cannot contain newline"
+msgstr "%s kann keinen Zeilenumbruch enthalten"
+
+#, c-format
+msgid "%s must have at least one character"
+msgstr "%s muss mindestens ein Zeichen enthalten"
#, c-format
msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -15616,6 +15641,10 @@ msgid "failed to write new configuration file %s"
msgstr "Konnte neue Konfigurationsdatei '%s' nicht schreiben."
#, c-format
+msgid "no multi-line comment allowed: '%s'"
+msgstr "kein mehrzeiliger Kommentar erlaubt: '%s'"
+
+#, c-format
msgid "could not lock config file %s"
msgstr "Konnte Konfigurationsdatei '%s' nicht sperren."
@@ -17442,6 +17471,14 @@ msgid "Unable to create '%s.lock': %s"
msgstr "Konnte '%s.lock' nicht erstellen: %s"
#, c-format
+msgid "could not write loose object index %s"
+msgstr "konnte den losen Objektindex %s nicht schreiben"
+
+#, c-format
+msgid "failed to write loose object index %s\n"
+msgstr "Fehler beim Schreiben des losen Objektindexes %s\n"
+
+#, c-format
msgid "unexpected line: '%s'"
msgstr "unerwartete Zeile: '%s'"
@@ -17452,6 +17489,10 @@ msgid "quoted CRLF detected"
msgstr "angeführtes CRLF entdeckt"
#, c-format
+msgid "unable to format message: %s"
+msgstr "Meldung kann nicht formatiert werden: %s"
+
+#, c-format
msgid "Failed to merge submodule %s (not checked out)"
msgstr "Fehler beim Merge von Submodul %s (nicht ausgecheckt)."
@@ -17464,6 +17505,11 @@ msgid "Failed to merge submodule %s (commits not present)"
msgstr "Fehler beim Merge von Submodul %s (Commits nicht vorhanden)."
#, c-format
+msgid "Failed to merge submodule %s (repository corrupt)"
+msgstr ""
+"Submodul %s konnte nicht zusammengeführt werden (Repository beschädigt)"
+
+#, c-format
msgid "Failed to merge submodule %s (commits don't follow merge-base)"
msgstr "Fehler beim Merge von Submodul %s (Commits folgen keiner Merge-Basis)"
@@ -17950,6 +17996,83 @@ msgstr "Konnte Objekt '%s' nicht parsen."
msgid "failed to read the cache"
msgstr "Lesen des Zwischenspeichers fehlgeschlagen"
+#, c-format
+msgid "failed to add packfile '%s'"
+msgstr "Fehler beim Hinzufügen von Packdatei '%s'"
+
+#, c-format
+msgid "failed to open pack-index '%s'"
+msgstr "Fehler beim Öffnen von pack-index '%s'"
+
+#, c-format
+msgid "failed to locate object %d in packfile"
+msgstr "Fehler beim Lokalisieren von Objekt %d in Packdatei"
+
+msgid "cannot store reverse index file"
+msgstr "kann Reverse-Index-Datei nicht speichern"
+
+#, c-format
+msgid "could not parse line: %s"
+msgstr "Zeile konnte nicht geparst werden: %s"
+
+#, c-format
+msgid "malformed line: %s"
+msgstr "fehlerhafte Zeile: %s"
+
+msgid "ignoring existing multi-pack-index; checksum mismatch"
+msgstr ""
+"ignoriere existierenden Multi-Pack-Index; Prüfsumme stimmt nicht überein"
+
+msgid "could not load pack"
+msgstr "Paket konnte nicht geladen werden"
+
+#, c-format
+msgid "could not open index for %s"
+msgstr "konnte Index für %s nicht öffnen"
+
+msgid "Adding packfiles to multi-pack-index"
+msgstr "Packdateien zum Multi-Pack-Index hinzufügen"
+
+#, c-format
+msgid "unknown preferred pack: '%s'"
+msgstr "unbekanntes bevorzugtes Paket: '%s'"
+
+#, c-format
+msgid "cannot select preferred pack %s with no objects"
+msgstr "bevorzugtes Paket %s ohne Objekte kann nicht ausgewählt werden"
+
+#, c-format
+msgid "did not see pack-file %s to drop"
+msgstr "Pack-Datei %s zum Weglassen nicht gefunden"
+
+#, c-format
+msgid "preferred pack '%s' is expired"
+msgstr "bevorzugtes Paket '%s' ist abgelaufen"
+
+msgid "no pack files to index."
+msgstr "keine Packdateien zum Indizieren."
+
+msgid "refusing to write multi-pack .bitmap without any objects"
+msgstr "Schreiben der Multi-Pack-Bitmap ohne Objekte abgelehnt"
+
+msgid "could not write multi-pack bitmap"
+msgstr "Multi-Pack-Bitmap konnte nicht geschrieben werden"
+
+msgid "could not write multi-pack-index"
+msgstr "Multi-Pack-Index konnte nicht geschrieben werden"
+
+msgid "Counting referenced objects"
+msgstr "Referenzierte Objekte zählen"
+
+msgid "Finding and deleting unreferenced packfiles"
+msgstr "Suchen und Löschen von unreferenzierten Pack-Dateien"
+
+msgid "could not start pack-objects"
+msgstr "Konnte 'pack-objects' nicht ausführen"
+
+msgid "could not finish pack-objects"
+msgstr "Konnte 'pack-objects' nicht beenden"
+
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "Multi-Pack-Index OID fanout hat die falsche Größe"
@@ -18025,71 +18148,6 @@ msgid "multi-pack-index large offset out of bounds"
msgstr "multi-pack-index großer Offset außerhalb der Grenzen"
#, c-format
-msgid "failed to add packfile '%s'"
-msgstr "Fehler beim Hinzufügen von Packdatei '%s'"
-
-#, c-format
-msgid "failed to open pack-index '%s'"
-msgstr "Fehler beim Öffnen von pack-index '%s'"
-
-#, c-format
-msgid "failed to locate object %d in packfile"
-msgstr "Fehler beim Lokalisieren von Objekt %d in Packdatei"
-
-msgid "cannot store reverse index file"
-msgstr "kann Reverse-Index-Datei nicht speichern"
-
-#, c-format
-msgid "could not parse line: %s"
-msgstr "Zeile konnte nicht geparst werden: %s"
-
-#, c-format
-msgid "malformed line: %s"
-msgstr "fehlerhafte Zeile: %s"
-
-msgid "ignoring existing multi-pack-index; checksum mismatch"
-msgstr ""
-"ignoriere existierenden Multi-Pack-Index; Prüfsumme stimmt nicht überein"
-
-msgid "could not load pack"
-msgstr "Paket konnte nicht geladen werden"
-
-#, c-format
-msgid "could not open index for %s"
-msgstr "konnte Index für %s nicht öffnen"
-
-msgid "Adding packfiles to multi-pack-index"
-msgstr "Packdateien zum Multi-Pack-Index hinzufügen"
-
-#, c-format
-msgid "unknown preferred pack: '%s'"
-msgstr "unbekanntes bevorzugtes Paket: '%s'"
-
-#, c-format
-msgid "cannot select preferred pack %s with no objects"
-msgstr "bevorzugtes Paket %s ohne Objekte kann nicht ausgewählt werden"
-
-#, c-format
-msgid "did not see pack-file %s to drop"
-msgstr "Pack-Datei %s zum Weglassen nicht gefunden"
-
-#, c-format
-msgid "preferred pack '%s' is expired"
-msgstr "bevorzugtes Paket '%s' ist abgelaufen"
-
-msgid "no pack files to index."
-msgstr "keine Packdateien zum Indizieren."
-
-msgid "refusing to write multi-pack .bitmap without any objects"
-msgstr "Schreiben der Multi-Pack-Bitmap ohne Objekte abgelehnt"
-
-msgid "could not write multi-pack bitmap"
-msgstr "Multi-Pack-Bitmap konnte nicht geschrieben werden"
-
-msgid "could not write multi-pack-index"
-msgstr "Multi-Pack-Index konnte nicht geschrieben werden"
-
-#, c-format
msgid "failed to clear multi-pack-index at %s"
msgstr "Fehler beim Löschen des Multi-Pack-Index bei %s"
@@ -18130,18 +18188,6 @@ msgstr "Fehler beim Laden des Pack-Index für Packdatei %s"
msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>"
msgstr "Falscher Objekt-Offset für oid[%d] = %s: %<PRIx64> != %<PRIx64>"
-msgid "Counting referenced objects"
-msgstr "Referenzierte Objekte zählen"
-
-msgid "Finding and deleting unreferenced packfiles"
-msgstr "Suchen und Löschen von unreferenzierten Pack-Dateien"
-
-msgid "could not start pack-objects"
-msgstr "Konnte 'pack-objects' nicht ausführen"
-
-msgid "could not finish pack-objects"
-msgstr "Konnte 'pack-objects' nicht beenden"
-
#, c-format
msgid "unable to create lazy_dir thread: %s"
msgstr "Kann lazy_dir Thread nicht erzeugen: %s"
@@ -18193,6 +18239,25 @@ msgstr ""
msgid "Bad %s value: '%s'"
msgstr "Ungültiger %s Wert: '%s'"
+msgid "failed to decode tree entry"
+msgstr "Tree-Eintrag konnte nicht dekodiert werden"
+
+#, c-format
+msgid "failed to map tree entry for %s"
+msgstr "der Tree-Eintrag für %s konnte nicht zugeordnet werden"
+
+#, c-format
+msgid "bad %s in commit"
+msgstr "ungültiges %s in Commit"
+
+#, c-format
+msgid "unable to map %s %s in commit object"
+msgstr "kann %s %s in Commit-Objekt nicht zuordnen"
+
+#, c-format
+msgid "Failed to convert object from %s to %s"
+msgstr "Objekt konnte nicht von %s nach %s konvertiert werden"
+
#, c-format
msgid "object directory %s does not exist; check .git/objects/info/alternates"
msgstr ""
@@ -18300,6 +18365,10 @@ msgid "packed object %s (stored in %s) is corrupt"
msgstr "Gepacktes Objekt %s (gespeichert in %s) ist beschädigt."
#, c-format
+msgid "missing mapping of %s to %s"
+msgstr "fehlende Abbildung von %s auf %s"
+
+#, c-format
msgid "unable to write file %s"
msgstr "Konnte Datei %s nicht schreiben."
@@ -18355,6 +18424,10 @@ msgid "cannot read object for %s"
msgstr "Kann Objekt für %s nicht lesen."
#, c-format
+msgid "cannot map object %s to %s"
+msgstr "kann Objekt %s nicht auf %s abbilden"
+
+#, c-format
msgid "object fails fsck: %s"
msgstr "fsck schlägt bei Objekt fehl: %s"
@@ -18668,6 +18741,11 @@ msgstr ""
"Paket kann nicht geladen werden: '%s', Deaktivierung der Paket-"
"Wiederverwendung"
+msgid "unable to compute preferred pack, disabling pack-reuse"
+msgstr ""
+"kann bevorzugtes Paket nicht berechnen, Wiederverwendung von Paketen wird "
+"deaktiviert"
+
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "Objekt '%s' nicht im Typ Bitmaps gefunden"
@@ -19737,6 +19815,76 @@ msgid "could not delete references: %s"
msgstr "konnte Referenzen nicht entfernen: %s"
#, c-format
+msgid "refname is dangerous: %s"
+msgstr "Referenzname ist gefährlich: %s"
+
+#, c-format
+msgid "trying to write ref '%s' with nonexistent object %s"
+msgstr "Versuch, Referenz '%s' mit nicht existierendem Objekt %s zu schreiben"
+
+#, c-format
+msgid "trying to write non-commit object %s to branch '%s'"
+msgstr "Versuch, Nicht-Commit-Objekt %s in Branch '%s' zu schreiben"
+
+#, c-format
+msgid ""
+"multiple updates for 'HEAD' (including one via its referent '%s') are not "
+"allowed"
+msgstr ""
+"mehrere Aktualisierungen für 'HEAD' (einschließlich einer über seinen "
+"Referenten '%s') sind nicht erlaubt"
+
+#, c-format
+msgid "cannot lock ref '%s': unable to resolve reference '%s'"
+msgstr ""
+"kann Referenz '%s' nicht sperren: Referenz '%s' kann nicht aufgelöst werden"
+
+#, c-format
+msgid "cannot lock ref '%s': error reading reference"
+msgstr "kann Referenz '%s' nicht sperren: Fehler beim Lesen der Referenz"
+
+#, c-format
+msgid ""
+"multiple updates for '%s' (including one via symref '%s') are not allowed"
+msgstr ""
+"mehrere Aktualisierungen für '%s' (einschließlich einer über die symbolische "
+"Referenz '%s') sind nicht erlaubt"
+
+#, c-format
+msgid "cannot lock ref '%s': reference already exists"
+msgstr "kann Referenz '%s' nicht sperren: Referenz existiert bereits"
+
+#, c-format
+msgid "cannot lock ref '%s': reference is missing but expected %s"
+msgstr "kann Referenz '%s' nicht sperren: Referenz fehlt, aber bei %s erwartet"
+
+#, c-format
+msgid "cannot lock ref '%s': is at %s but expected %s"
+msgstr "kann Referenz '%s' nicht sperren: ist bei %s, aber bei %s erwartet"
+
+#, c-format
+msgid "reftable: transaction prepare: %s"
+msgstr "reftable: Transaktion vorbereiten: %s"
+
+#, c-format
+msgid "reftable: transaction failure: %s"
+msgstr "reftable: Transaktionsfehler: %s"
+
+#, c-format
+msgid "unable to compact stack: %s"
+msgstr "kann Stapel nicht verkleinern: %s"
+
+#, c-format
+msgid "refname %s not found"
+msgstr "Referenzname %s nicht gefunden"
+
+#, c-format
+msgid "refname %s is a symbolic ref, copying it is not supported"
+msgstr ""
+"Referenzname %s ist eine symbolische Referenz, Kopieren wird nicht "
+"unterstützt"
+
+#, c-format
msgid "invalid refspec '%s'"
msgstr "ungültige Refspec '%s'"
@@ -19745,6 +19893,10 @@ msgid "invalid quoting in push-option value: '%s'"
msgstr "Ungültiges Quoting beim \"push-option\"-Wert: '%s'"
#, c-format
+msgid "unknown value for object-format: %s"
+msgstr "unbekannter Wert für Objektformat: %s"
+
+#, c-format
msgid "%sinfo/refs not valid: is this a git repository?"
msgstr "%sinfo/refs nicht gültig: Ist das ein Git-Repository?"
@@ -20198,8 +20350,19 @@ msgid "resolve-undo records `%s` which is missing"
msgstr "resolve-undo zeichnet `%s` auf, das fehlt"
#, c-format
-msgid "could not get commit for ancestry-path argument %s"
-msgstr "konnte kein Commit für das Argument ancestry-path %s erhalten"
+msgid "%s exists but is a symbolic ref"
+msgstr "%s existiert, ist aber eine symbolische Referenz"
+
+msgid ""
+"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD or REBASE_HEAD"
+msgstr ""
+"--merge erfordert einen der Pseudoreferenzen MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD oder REBASE_HEAD"
+
+#, c-format
+msgid "could not get commit for --ancestry-path argument %s"
+msgstr "konnte keinen Commit für das Argument --ancestry-path erhalten %s"
msgid "--unpacked=<packfile> no longer supported"
msgstr "--unpacked=<Pack-Datei> wird nicht länger unterstützt"
@@ -20487,6 +20650,21 @@ msgid "unknown action: %d"
msgstr "Unbekannte Aktion: %d"
msgid ""
+"Resolve all conflicts manually, mark them as resolved with\n"
+"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
+"You can instead skip this commit: run \"git rebase --skip\".\n"
+"To abort and get back to the state before \"git rebase\", run \"git rebase --"
+"abort\"."
+msgstr ""
+"Lösen Sie alle Konflikte manuell auf, markieren Sie diese mit\n"
+"\"git add/rm <konfliktbehaftete_Dateien>\" und führen Sie dann\n"
+"\"git rebase --continue\" aus.\n"
+"Sie können auch stattdessen diesen Commit auslassen, indem\n"
+"Sie \"git rebase --skip\" ausführen.\n"
+"Um abzubrechen und zurück zum Zustand vor \"git rebase\" zu gelangen,\n"
+"führen Sie \"git rebase --abort\" aus."
+
+msgid ""
"after resolving the conflicts, mark the corrected paths\n"
"with 'git add <paths>' or 'git rm <paths>'"
msgstr ""
@@ -20714,10 +20892,6 @@ msgid "could not update %s"
msgstr "Konnte %s nicht aktualisieren."
#, c-format
-msgid "could not parse commit %s"
-msgstr "Konnte Commit %s nicht parsen."
-
-#, c-format
msgid "could not parse parent commit %s"
msgstr "Konnte Eltern-Commit %s nicht parsen."
@@ -20823,10 +20997,6 @@ msgid "invalid command '%.*s'"
msgstr "ungültiger Befehl '%.*s'"
#, c-format
-msgid "%s does not accept arguments: '%s'"
-msgstr "%s akzeptiert keine Argumente: '%s'"
-
-#, c-format
msgid "missing arguments for %s"
msgstr "Fehlende Argumente für %s."
@@ -21292,6 +21462,10 @@ msgstr ""
"Konnte Arbeitsverzeichnis mit ungültiger Konfiguration nicht einrichten."
#, c-format
+msgid "'%s' already specified as '%s'"
+msgstr "'%s' bereits als '%s' angegeben"
+
+#, c-format
msgid "Expected git repo version <= %d, found %d"
msgstr "Erwartete Git-Repository-Version <= %d, %d gefunden"
@@ -21483,6 +21657,21 @@ msgstr "Index-Eintrag ist ein Verzeichnis, aber nicht partiell (%08x)"
msgid "cannot use split index with a sparse index"
msgstr "kann aufgeteilten Index nicht mit einem Sparse-Index benutzen"
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not start with '('"
+msgstr "ungültiges %s-Format: Element '%s' beginnt nicht mit '('"
+
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not end in ')'"
+msgstr "ungültiges %s-Format: Element '%s' endet nicht auf ')'"
+
+#. TRANSLATORS: %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: %%%.*s"
+msgstr "ungültiges %s-Format: %%%.*s"
+
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#, c-format
msgid "%u.%2.2u GiB"
@@ -21809,29 +21998,6 @@ msgstr "unbekannter Wert '%s' für Schlüssel %s"
msgid "empty trailer token in trailer '%.*s'"
msgstr "leerer Anhang-Token in Anhang '%.*s'"
-#, c-format
-msgid "could not read input file '%s'"
-msgstr "Konnte Eingabe-Datei '%s' nicht lesen"
-
-#, c-format
-msgid "could not stat %s"
-msgstr "Konnte '%s' nicht lesen"
-
-#, c-format
-msgid "file %s is not a regular file"
-msgstr "Datei '%s' ist keine reguläre Datei"
-
-#, c-format
-msgid "file %s is not writable by user"
-msgstr "Datei %s ist vom Benutzer nicht beschreibbar."
-
-msgid "could not open temporary file"
-msgstr "konnte temporäre Datei '%s' nicht öffnen"
-
-#, c-format
-msgid "could not rename temporary file to %s"
-msgstr "konnte temporäre Datei nicht zu %s umbenennen"
-
msgid "full write to remote helper failed"
msgstr "Vollständiges Schreiben zu Remote-Helper fehlgeschlagen."
@@ -21930,8 +22096,8 @@ msgid "remote-helper doesn't support push; refspec needed"
msgstr "Remote-Helper unterstützt kein Push; Refspec benötigt"
#, c-format
-msgid "helper %s does not support 'force'"
-msgstr "Remote-Helper %s unterstützt kein 'force'."
+msgid "helper %s does not support '--force'"
+msgstr "Helper %s unterstützt '--force' nicht"
msgid "couldn't run fast-export"
msgstr "Konnte \"fast-export\" nicht ausführen."
@@ -22364,6 +22530,10 @@ msgstr "ungültige Portnummer"
msgid "invalid '..' path segment"
msgstr "ungültiges '..' Pfadsegment"
+#, c-format
+msgid "error: unable to format message: %s\n"
+msgstr "Fehler: Meldung kann nicht formatiert werden: %s\n"
+
msgid "usage: "
msgstr "Verwendung: "
diff --git a/po/fr.po b/po/fr.po
index 736a90f6bb..837a695485 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -80,8 +80,8 @@ msgid ""
msgstr ""
"Project-Id-Version: git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2024-02-16 19:18+0100\n"
-"PO-Revision-Date: 2024-02-16 19:19+0100\n"
+"POT-Creation-Date: 2024-04-16 22:57+0000\n"
+"PO-Revision-Date: 2024-04-20 17:11+0800\n"
"Last-Translator: Cédric Malard <c.malard-git@valdun.net>\n"
"Language-Team: Jean-Noël Avila <jn.avila@free.fr>\n"
"Language: fr\n"
@@ -576,12 +576,12 @@ msgid ""
"---\n"
"To remove '%c' lines, make them ' ' lines (context).\n"
"To remove '%c' lines, delete them.\n"
-"Lines starting with %c will be removed.\n"
+"Lines starting with %s will be removed.\n"
msgstr ""
"---\n"
"Pour éliminer les lignes '%c', rendez-les ' ' (contexte).\n"
"Pour éliminer les lignes '%c', effacez-les.\n"
-"Les lignes commençant par %c seront éliminées.\n"
+"Les lignes commençant par %s seront éliminées.\n"
msgid ""
"If it does not apply cleanly, you will be given an opportunity to\n"
@@ -628,6 +628,7 @@ msgid ""
"/ - search for a hunk matching the given regex\n"
"s - split the current hunk into smaller hunks\n"
"e - manually edit the current hunk\n"
+"p - print the current hunk\n"
"? - print help\n"
msgstr ""
"j - laisser cette section non décidée et aller à la suivante non-décidée\n"
@@ -638,6 +639,7 @@ msgstr ""
"/ - rechercher une section correspondant à une regex donnée\n"
"s - découper la section en sections plus petites\n"
"e - éditer manuellement la section actuelle\n"
+"p - afficher la section actuelle\n"
"? - afficher l'aide\n"
msgid "No previous hunk"
@@ -700,8 +702,8 @@ msgstr ""
"Désactivez ce message avec \"git config advice.%s false\""
#, c-format
-msgid "%shint: %.*s%s\n"
-msgstr "%sastuce: %.*s%s\n"
+msgid "%shint:%s%.*s%s\n"
+msgstr "%sastuce :%s%.*s%s\n"
msgid "Cherry-picking is not possible because you have unmerged files."
msgstr "Impossible de picorer car vous avez des fichiers non fusionnés."
@@ -1801,6 +1803,9 @@ msgstr ""
msgid "'%s' is not a valid branch name"
msgstr "'%s' n'est pas un nom de branche valide"
+msgid "See `man git check-ref-format`"
+msgstr "Voir `man git check-ref-format`"
+
#, c-format
msgid "a branch named '%s' already exists"
msgstr "Une branche nommée '%s' existe déjà"
@@ -2000,14 +2005,8 @@ msgstr ""
msgid "adding embedded git repository: %s"
msgstr "dépôt git embarqué ajouté : %s"
-msgid ""
-"Use -f if you really want to add them.\n"
-"Turn this message off by running\n"
-"\"git config advice.addIgnoredFile false\""
-msgstr ""
-"Utilisez -f si vous voulez vraiment les ajouter.\n"
-"Éliminez ce message en lançant\n"
-"\"git config advice.addIgnoredFile false\""
+msgid "Use -f if you really want to add them."
+msgstr "Utilisez -f si vous voulez vraiment les ajouter"
msgid "adding files failed"
msgstr "échec de l'ajout de fichiers"
@@ -2026,14 +2025,8 @@ msgstr ""
msgid "Nothing specified, nothing added.\n"
msgstr "Rien de spécifié, rien n'a été ajouté.\n"
-msgid ""
-"Maybe you wanted to say 'git add .'?\n"
-"Turn this message off by running\n"
-"\"git config advice.addEmptyPathspec false\""
-msgstr ""
-"Peut-être avez-vous voulu dire 'git add .' ?\n"
-"Éliminez ce message en lançant\n"
-"\"git config advice.addEmptyPathspec false\""
+msgid "Maybe you wanted to say 'git add .'?"
+msgstr "Vous vouliez sûrement utiliser 'git add .' ?"
msgid "index file corrupt"
msgstr "fichier d'index corrompu"
@@ -2110,18 +2103,19 @@ msgid "Failed to split patches."
msgstr "Échec de découpage des patchs."
#, c-format
-msgid "When you have resolved this problem, run \"%s --continue\"."
-msgstr "Quand vous avez résolu ce problème, lancez \"%s --continue\"."
+msgid "When you have resolved this problem, run \"%s --continue\".\n"
+msgstr "Quand vous avez résolu ce problème, lancez \"%s --continue\".\n"
#, c-format
-msgid "If you prefer to skip this patch, run \"%s --skip\" instead."
-msgstr "Si vous préférez plutôt sauter ce patch, lancez \"%s --skip\"."
+msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n"
+msgstr "Si vous préférez plutôt sauter cette rustine, lancez \"%s --skip\".\n"
#, c-format
-msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"."
+msgid ""
+"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"
msgstr ""
"Pour enregistrer la rustine vide comme un commit vide, lancez \"%s --allow-"
-"empty\"."
+"empty\".\n"
#, c-format
msgid "To restore the original branch and stop patching, run \"%s --abort\"."
@@ -2995,11 +2989,11 @@ msgstr ""
msgid ""
"Please edit the description for the branch\n"
" %s\n"
-"Lines starting with '%c' will be stripped.\n"
+"Lines starting with '%s' will be stripped.\n"
msgstr ""
"Veuillez éditer la description de la branche\n"
" %s\n"
-"Les lignes commençant par '%c' seront ignorées.\n"
+"Les lignes commençant par '%s' seront ignorées.\n"
msgid "Generic options"
msgstr "Options génériques"
@@ -3202,11 +3196,12 @@ msgid "not run from a git repository - no hooks to show\n"
msgstr "lancé hors d'un dépôt git - aucun crochet à montrer\n"
msgid ""
-"git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"git bugreport [(-o | --output-directory) <path>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
" [--diagnose[=<mode>]]"
msgstr ""
-"git bugreport [(-o | --output-directory) <chemin>] [(-s | --suffix) "
-"<format>]\n"
+"git bugreport [(-o | --output-directory) <chemin>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
" [--diagnose[=<mode>]]"
msgid ""
@@ -3698,6 +3693,10 @@ msgstr ""
msgid "path '%s' is unmerged"
msgstr "le chemin '%s' n'est pas fusionné"
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr "impossible de lire l'arbre (%s)"
+
msgid "you need to resolve your current index first"
msgstr "vous devez d'abord résoudre votre index courant"
@@ -3931,6 +3930,10 @@ msgstr "Impossible de basculer de branche vers '%s' qui n'est pas un commit"
msgid "missing branch or commit argument"
msgstr "argument de branche ou de commit manquant"
+#, c-format
+msgid "unknown conflict style '%s'"
+msgstr "style de conflit inconnu '%s'"
+
msgid "perform a 3-way merge with the new branch"
msgstr "effectuer une fusion à 3 points avec la nouvelle branche"
@@ -4190,19 +4193,9 @@ msgstr "supprimer les fichiers ignorés, aussi"
msgid "remove only ignored files"
msgstr "supprimer seulement les fichiers ignorés"
-msgid ""
-"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to "
-"clean"
-msgstr ""
-"clean.requireForce positionné à true et ni -i, -n ou -f fourni ; refus de "
-"nettoyer"
-
-msgid ""
-"clean.requireForce defaults to true and neither -i, -n, nor -f given; "
-"refusing to clean"
+msgid "clean.requireForce is true and -f not given: refusing to clean"
msgstr ""
-"clean.requireForce à true par défaut et ni -i, -n ou -f fourni ; refus de "
-"nettoyer"
+"clean.requireForce positionné est true et -f non fourni ; refus de nettoyer"
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<options>] [--] <dépôt> [<répertoire>]"
@@ -4216,8 +4209,8 @@ msgstr "ne pas créer d'extraction"
msgid "create a bare repository"
msgstr "créer un dépôt nu"
-msgid "create a mirror repository (implies bare)"
-msgstr "créer un dépôt miroir (implique dépôt nu)"
+msgid "create a mirror repository (implies --bare)"
+msgstr "créer un dépôt miroir (implique --bare)"
msgid "to clone from a local repository"
msgstr "pour cloner depuis un dépôt local"
@@ -4541,6 +4534,10 @@ msgstr "remplissage d'espace sur le côté droit"
msgid "padding space between columns"
msgstr "remplissage d'espace entre les colonnes"
+#, c-format
+msgid "%s must be non-negative"
+msgstr "%s doit être non négatif"
+
msgid "--command must be the first argument"
msgstr "--command doit être le premier argument"
@@ -4854,38 +4851,38 @@ msgstr "impossible d'écrire le modèle de commit"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored.\n"
+"with '%s' will be ignored.\n"
msgstr ""
"Veuillez saisir le message de validation pour vos modifications. Les lignes\n"
-"commençant par '%c' seront ignorées.\n"
+"commençant par '%s' seront ignorées.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored, and an empty message aborts the commit.\n"
+"with '%s' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
"Veuillez saisir le message de validation pour vos modifications. Les lignes\n"
-"commençant par '%c' seront ignorées, et un message vide abandonne la "
+"commençant par '%s' seront ignorées, et un message vide abandonne la "
"validation.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
msgstr ""
"Veuillez saisir le message de validation pour vos modifications. Les lignes "
"commençant\n"
-"par '%c' seront conservées ; vous pouvez les supprimer vous-même si vous le "
+"par '%s' seront conservées ; vous pouvez les supprimer vous-même si vous le "
"souhaitez.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
"Veuillez saisir le message de validation pour vos modifications. Les lignes\n"
-"commençant par '%c' seront conservées ; vous pouvez les supprimer vous-même\n"
+"commençant par '%s' seront conservées ; vous pouvez les supprimer vous-même\n"
"si vous le souhaitez. Un message vide abandonne la validation.\n"
msgid ""
@@ -5337,6 +5334,11 @@ msgstr "valeur"
msgid "with --get, use default value when missing entry"
msgstr "avec --get, utiliser le valeur par défaut quand l'entrée n'existe pas"
+msgid "human-readable comment string (# will be prepended as needed)"
+msgstr ""
+"chaîne des commentaires lisibles par l'utilisateur (# sera ajouté en préfixe "
+"selon les besoins)"
+
#, c-format
msgid "wrong number of arguments, should be %d"
msgstr "mauvais nombre d'arguments, devrait être %d"
@@ -5431,6 +5433,9 @@ msgstr ""
msgid "--default is only applicable to --get"
msgstr "--default n'est applicable qu'avec --get"
+msgid "--comment is only applicable to add/set/replace operations"
+msgstr "--comment n'est applicable qu'avec les opérations add/set/replace"
+
msgid "--fixed-value only applies with 'value-pattern'"
msgstr "--fixed-value ne s'applique qu'à 'motif-de-valeur'"
@@ -6287,6 +6292,9 @@ msgstr "afficher seulement les références qui ne contiennent pas le commit"
msgid "read reference patterns from stdin"
msgstr "lire les motifs de références depuis l'entrée standard"
+msgid "also include HEAD ref and pseudorefs"
+msgstr "inclure aussi la référence HEAD et les pseudo-réfs"
+
msgid "unknown arguments supplied with --stdin"
msgstr "arguments inconnus fournis avec l'option --stdin"
@@ -6912,10 +6920,6 @@ msgid "no threads support, ignoring %s"
msgstr "pas de support des fils, ignore %s"
#, c-format
-msgid "unable to read tree (%s)"
-msgstr "impossible de lire l'arbre (%s)"
-
-#, c-format
msgid "unable to read tree %s"
msgstr "impossible de lire l'arbre %s"
@@ -7528,7 +7532,7 @@ msgstr "--separate-git-dir est incompatible avec un dépôt nu"
msgid ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n"
+" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
" [--parse] [<file>...]"
msgstr ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
@@ -7536,6 +7540,32 @@ msgstr ""
"[(=|:)<valeur>])...]\n"
" [--parse] [<fichier>...]"
+#, c-format
+msgid "could not stat %s"
+msgstr "stat impossible de %s"
+
+#, c-format
+msgid "file %s is not a regular file"
+msgstr "%s n'est pas un fichier régulier"
+
+#, c-format
+msgid "file %s is not writable by user"
+msgstr "le fichier %s n'est pas inscriptible par l'utilisateur"
+
+msgid "could not open temporary file"
+msgstr "impossible de créer un fichier temporaire"
+
+#, c-format
+msgid "could not read input file '%s'"
+msgstr "impossible de lire le fichier d'entrée '%s'"
+
+msgid "could not read from stdin"
+msgstr "impossible de lire depuis l'entrée standard"
+
+#, c-format
+msgid "could not rename temporary file to %s"
+msgstr "impossible de renommer un fichier temporaire en %s"
+
msgid "edit files in place"
msgstr "éditer les fichiers sur place"
@@ -7941,18 +7971,6 @@ msgstr ""
msgid "could not get object info about '%s'"
msgstr "impossible d'obtenir l'information d'objet pour '%s'"
-#, c-format
-msgid "bad ls-files format: element '%s' does not start with '('"
-msgstr "mauvais format ls-files : l'élément '%s' ne commence pas par '('"
-
-#, c-format
-msgid "bad ls-files format: element '%s' does not end in ')'"
-msgstr "mauvais format ls-files : l'élément '%s' ne se termine pas par ')'"
-
-#, c-format
-msgid "bad ls-files format: %%%.*s"
-msgstr "mauvais format ls-files : %%%.*s"
-
msgid "git ls-files [<options>] [<file>...]"
msgstr "git ls-files [<options>] [<fichier>...]"
@@ -8088,18 +8106,6 @@ msgstr "afficher la réf sous-jacente en plus de l'objet pointé par elle"
msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
msgstr "git ls-tree [<options>] <arbre ou apparenté> [<chemin>...]"
-#, c-format
-msgid "bad ls-tree format: element '%s' does not start with '('"
-msgstr "mauvais format ls-tree : l'élément '%s' ne commence pas par '('"
-
-#, c-format
-msgid "bad ls-tree format: element '%s' does not end in ')'"
-msgstr "mauvais format ls-tree : l'élément '%s' ne se termine pas ')'"
-
-#, c-format
-msgid "bad ls-tree format: %%%.*s"
-msgstr "mauvais format ls-tree : %%%.*s"
-
msgid "only show trees"
msgstr "afficher seulement les arbres"
@@ -8290,6 +8296,10 @@ msgstr "impossible de résoudre la référence '%s'"
msgid "Merging %s with %s\n"
msgstr "Fusion de %s avec %s\n"
+#, c-format
+msgid "could not parse as tree '%s'"
+msgstr "impossible d'analyser '%s' comme un arbre"
+
msgid "not something we can merge"
msgstr "pas possible de fusionner ceci"
@@ -8497,10 +8507,10 @@ msgstr "Un message vide abandonne la validation.\n"
#, c-format
msgid ""
-"Lines starting with '%c' will be ignored, and an empty message aborts\n"
+"Lines starting with '%s' will be ignored, and an empty message aborts\n"
"the commit.\n"
msgstr ""
-"Les lignes commençant par '%c' seront ignorées, et un message vide\n"
+"Les lignes commençant par '%s' seront ignorées, et un message vide\n"
"abandonne la validation.\n"
msgid "Empty commit message."
@@ -8662,9 +8672,6 @@ msgstr "impossible de lire l'objet étiqueté '%s'"
msgid "object '%s' tagged as '%s', but is a '%s' type"
msgstr "l'objet '%s' étiqueté comme '%s', mais est de type '%s'"
-msgid "could not read from stdin"
-msgstr "impossible de lire depuis l'entrée standard"
-
msgid "tag on stdin did not pass our strict fsck check"
msgstr "l'étiquette sur stdin n'a pas passé le test strict fsck"
@@ -9574,10 +9581,11 @@ msgid "refusing to run without --i-still-use-this"
msgstr "refus de lancer sans --i-still-use-this"
msgid ""
-"git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude "
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
"<pattern>]"
msgstr ""
-"git pack-refs [--all] [--no-prune] [--include <motif>] [--exclude <motif>]"
+"git pack-refs [--all] [--no-prune] [--auto] [--include <motif>] [--exclude "
+"<motif>]"
msgid "pack everything"
msgstr "empaqueter tout"
@@ -9585,6 +9593,9 @@ msgstr "empaqueter tout"
msgid "prune loose refs (default)"
msgstr "élaguer les références perdues (défaut)"
+msgid "auto-pack refs as needed"
+msgstr "auto-empaqueter les réfs au besoin"
+
msgid "references to include"
msgstr "références à inclure"
@@ -10264,19 +10275,6 @@ msgstr "allow_rerere_autoupdate invalide ignoré : '%s'"
msgid "could not remove '%s'"
msgstr "impossible de supprimer '%s'"
-msgid ""
-"Resolve all conflicts manually, mark them as resolved with\n"
-"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
-"You can instead skip this commit: run \"git rebase --skip\".\n"
-"To abort and get back to the state before \"git rebase\", run \"git rebase --"
-"abort\"."
-msgstr ""
-"Résolvez tous les conflits manuellement, marquez-les comme résolus avec\n"
-"\"git add/rm <fichier en conflit>\", puis lancez \"git rebase --continue\".\n"
-"Si vous préférez sauter ce commit, lancez \"git rebase --skip\". Pour "
-"arrêter\n"
-"et revenir à l'état antérieur à la commande, lancez \"git rebase --abort\"."
-
#, c-format
msgid ""
"\n"
@@ -10307,13 +10305,16 @@ msgid "apply options and merge options cannot be used together"
msgstr ""
"Les options d'apply et celles de merge ne peuvent pas être utilisées ensemble"
+msgid "--empty=ask is deprecated; use '--empty=stop' instead."
+msgstr "--empty=ask est obsolète ; utilisez '--empty=stop' à la place."
+
#, c-format
msgid ""
"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
-"\"ask\"."
+"\"stop\"."
msgstr ""
"type vide non connu '%s' ; les valeurs valides sont \"drop\" (abandonner), "
-"\"keep\" (garder) et \"ask\" (demander)."
+"\"keep\" (garder) et \"stop\" (arrêter)."
msgid ""
"--rebase-merges with an empty string argument is deprecated and will stop "
@@ -10495,8 +10496,8 @@ msgstr ""
"Note : votre configuration `pull.rebase` peut aussi être 'preserve',\n"
"qui n'est plus géré ; utilisez 'merges' à la place"
-msgid "No rebase in progress?"
-msgstr "Pas de rebasage en cours ?"
+msgid "no rebase in progress"
+msgstr "Pas de rebasage en cours"
msgid "The --edit-todo action can only be used during interactive rebase."
msgstr ""
@@ -10693,6 +10694,9 @@ msgstr "Vous devez spécifier un répertoire"
msgid "git reflog [show] [<log-options>] [<ref>]"
msgstr "git reflog [show] [<options-de-journal>] [<réf>]"
+msgid "git reflog list"
+msgstr "git reflog list"
+
msgid ""
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
" [--rewrite] [--updateref] [--stale-fix]\n"
@@ -10718,6 +10722,10 @@ msgstr "git reflog exists <référence>"
msgid "invalid timestamp '%s' given to '--%s'"
msgstr "horodatage invalide '%s' fourni à '--%s'"
+#, c-format
+msgid "%s does not accept arguments: '%s'"
+msgstr "%s n'accepte pas d'argument : '%s'"
+
msgid "do not actually prune any entries"
msgstr "ne pas réellement élaguer des entrées"
@@ -10848,8 +10856,8 @@ msgstr ""
"\t d'utiliser --mirror=fetch ou --mirror=push à la place"
#, c-format
-msgid "unknown mirror argument: %s"
-msgstr "argument miroir inconnu : %s"
+msgid "unknown --mirror argument: %s"
+msgstr "argument de --mirror inconnu : %s"
msgid "fetch the remote branches"
msgstr "rapatrier les branches distantes"
@@ -11224,6 +11232,9 @@ msgid "could not start pack-objects to repack promisor objects"
msgstr ""
"ne pas démarrer pack-objects pour ré-empaqueter les objects de prometteur"
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "Échéc de la fourniture les objets du prometteur à pack-objects"
+
msgid "repack: Expecting full hex object ID lines only from pack-objects."
msgstr ""
"repack : attente de lignes d'Id d'objets en hexa complet seulement depuis "
@@ -11831,6 +11842,13 @@ msgstr "--default exige un argument"
msgid "--prefix requires an argument"
msgstr "--prefix exige un argument"
+msgid "no object format specified"
+msgstr "aucun format d'objet spécifié"
+
+#, c-format
+msgid "unsupported object format: %s"
+msgstr "format d'objet non géré : %s"
+
#, c-format
msgid "unknown mode for --abbrev-ref: %s"
msgstr "mode inconnu pour --abbrev-ref : %s"
@@ -11912,8 +11930,8 @@ msgstr "préserver les validations vides initialement"
msgid "allow commits with empty messages"
msgstr "autoriser les validations avec des messages vides"
-msgid "keep redundant, empty commits"
-msgstr "garder les validations redondantes, vides"
+msgid "deprecated: use --empty=keep instead"
+msgstr "obsolète : utilisez --empty=keep à la place"
msgid "use the 'reference' format to refer to commits"
msgstr "utiliser le format 'reference' pour se référer aux commits"
@@ -13283,25 +13301,25 @@ msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be ignored.\n"
+"Lines starting with '%s' will be ignored.\n"
msgstr ""
"\n"
"Écrivez un message pour l'étiquette :\n"
" %s\n"
-"Les lignes commençant par '%c' seront ignorées.\n"
+"Les lignes commençant par '%s' seront ignorées.\n"
#, c-format
msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be kept; you may remove them yourself if you "
+"Lines starting with '%s' will be kept; you may remove them yourself if you "
"want to.\n"
msgstr ""
"\n"
"Écrivez un message pour l'étiquette :\n"
" %s\n"
-"Les lignes commençant par '%c' seront gardées ; vous pouvez les retirer vous-"
+"Les lignes commençant par '%s' seront gardées ; vous pouvez les retirer vous-"
"même si vous le souhaitez.\n"
msgid "unable to sign the tag"
@@ -13388,6 +13406,9 @@ msgstr "afficher seulement les étiquettes qui ne sont pas fusionnées"
msgid "print only tags of the object"
msgstr "afficher seulement les étiquettes de l'objet"
+msgid "could not start 'git column'"
+msgstr "impossible de démarrer 'git column'"
+
#, c-format
msgid "the '%s' option is only allowed in list mode"
msgstr "l'option '%s' est autorisée seulement en mode de liste"
@@ -13643,13 +13664,12 @@ msgstr ""
msgid "fsmonitor disabled"
msgstr "fsmonitor désactivé"
-msgid "git update-ref [<options>] -d <refname> [<old-val>]"
-msgstr "git update-ref [<options>] -d <nom-référence> [<ancienne-valeur>]"
+msgid "git update-ref [<options>] -d <refname> [<old-oid>]"
+msgstr "git update-ref [<options>] -d <nom-référence> [<ancien-oid>]"
-msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]"
+msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]"
msgstr ""
-"git update-ref [<options>] <nom-référence> <nouvelle-valeur> [<ancienne-"
-"valeur>]"
+"git update-ref [<options>] <nom-référence> <nouvel-oid> [<ancien-oid>]"
msgid "git update-ref [<options>] --stdin [-z]"
msgstr "git update-ref [<options>] --stdin [-z]"
@@ -15070,6 +15090,10 @@ msgid "Verifying commits in commit graph"
msgstr "Verification des commits dans le graphe de commits"
#, c-format
+msgid "could not parse commit %s"
+msgstr "impossible d'analyser le commit %s"
+
+#, c-format
msgid "%s %s is not a commit!"
msgstr "%s %s n'est pas un commit !"
@@ -15508,8 +15532,13 @@ msgstr "longueur d'abbrev hors plage : %d"
msgid "bad zlib compression level %d"
msgstr "niveau de compression zlib incorrect %d"
-msgid "core.commentChar should only be one ASCII character"
-msgstr "core.commentChar ne devrait être qu'un unique caractère ASCII"
+#, c-format
+msgid "%s cannot contain newline"
+msgstr "%s ne peut pas contenir de retour à la ligne"
+
+#, c-format
+msgid "%s must have at least one character"
+msgstr "%s doit contenir au moins un caractère"
#, c-format
msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -15584,6 +15613,10 @@ msgid "failed to write new configuration file %s"
msgstr "impossible d'écrire le fichier de configuration %s"
#, c-format
+msgid "no multi-line comment allowed: '%s'"
+msgstr "aucun commentaire multi-ligne permis : '%s'"
+
+#, c-format
msgid "could not lock config file %s"
msgstr "impossible de verrouiller le fichier de configuration %s"
@@ -17430,6 +17463,14 @@ msgid "Unable to create '%s.lock': %s"
msgstr "Impossible de créer '%s.lock' : %s"
#, c-format
+msgid "could not write loose object index %s"
+msgstr "impossible d'écrire l'objet esseulé %s"
+
+#, c-format
+msgid "failed to write loose object index %s\n"
+msgstr "Échec de l'écriture de l'index d'objet esseulé %s\n"
+
+#, c-format
msgid "unexpected line: '%s'"
msgstr "ligne inattendue : '%s'"
@@ -17452,6 +17493,10 @@ msgid "Failed to merge submodule %s (commits not present)"
msgstr "Échec de fusion du sous-module %s (commits non présents)"
#, c-format
+msgid "Failed to merge submodule %s (repository corrupt)"
+msgstr "Échec de la fusion du sous-module %s (dépôt corrompu)"
+
+#, c-format
msgid "Failed to merge submodule %s (commits don't follow merge-base)"
msgstr ""
"Échec de la fusion du sous-module %s (les commits ne descendent pas de la "
@@ -17925,6 +17970,83 @@ msgstr "Impossible d'analyser l'objet '%s'"
msgid "failed to read the cache"
msgstr "impossible de lire le cache"
+#, c-format
+msgid "failed to add packfile '%s'"
+msgstr "échec de l'ajout du fichier paquet '%s'"
+
+#, c-format
+msgid "failed to open pack-index '%s'"
+msgstr "échec à l'ouverture du fichier paquet '%s'"
+
+#, c-format
+msgid "failed to locate object %d in packfile"
+msgstr "échec de localisation de l'objet %d dans le fichier paquet"
+
+msgid "cannot store reverse index file"
+msgstr "impossible de stocker le fichier d'index inversé"
+
+#, c-format
+msgid "could not parse line: %s"
+msgstr "impossible d'analyser la ligne : %s"
+
+#, c-format
+msgid "malformed line: %s"
+msgstr "ligne malformée : %s"
+
+msgid "ignoring existing multi-pack-index; checksum mismatch"
+msgstr ""
+"index multi-paquet existant ignoré ; non-concordance de la somme de contrôle"
+
+msgid "could not load pack"
+msgstr "impossible de charger le paquet"
+
+#, c-format
+msgid "could not open index for %s"
+msgstr "impossible d'ouvrir l'index pour %s"
+
+msgid "Adding packfiles to multi-pack-index"
+msgstr "Ajout de fichiers paquet à un index multi-paquet"
+
+#, c-format
+msgid "unknown preferred pack: '%s'"
+msgstr "paquet préféré inconnu : %s"
+
+#, c-format
+msgid "cannot select preferred pack %s with no objects"
+msgstr "impossible de sélectionner le paquet préféré %s avec aucun objet"
+
+#, c-format
+msgid "did not see pack-file %s to drop"
+msgstr "fichier paquet à éliminer %s non trouvé"
+
+#, c-format
+msgid "preferred pack '%s' is expired"
+msgstr "le paquet préféré '%s' est expiré"
+
+msgid "no pack files to index."
+msgstr "aucun fichier paquet à l'index."
+
+msgid "refusing to write multi-pack .bitmap without any objects"
+msgstr "refus d'écrire le .bitmap multi-paquet sans aucun objet"
+
+msgid "could not write multi-pack bitmap"
+msgstr "impossible d'écrire le bitmap multi-paquet"
+
+msgid "could not write multi-pack-index"
+msgstr "échec de l'écriture de l'index de multi-paquet"
+
+msgid "Counting referenced objects"
+msgstr "Comptage des objets référencés"
+
+msgid "Finding and deleting unreferenced packfiles"
+msgstr "Recherche et effacement des fichiers paquets non-référencés"
+
+msgid "could not start pack-objects"
+msgstr "impossible de démarrer le groupement d'objets"
+
+msgid "could not finish pack-objects"
+msgstr "impossible de finir le groupement d'objets"
+
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "l'étalement de l'OID d'index multi-paquet n'a pas la bonne taille"
@@ -18010,71 +18132,6 @@ msgid "multi-pack-index large offset out of bounds"
msgstr "le grand décalage de l'index-multi-paquet est hors limite"
#, c-format
-msgid "failed to add packfile '%s'"
-msgstr "échec de l'ajout du fichier paquet '%s'"
-
-#, c-format
-msgid "failed to open pack-index '%s'"
-msgstr "échec à l'ouverture du fichier paquet '%s'"
-
-#, c-format
-msgid "failed to locate object %d in packfile"
-msgstr "échec de localisation de l'objet %d dans le fichier paquet"
-
-msgid "cannot store reverse index file"
-msgstr "impossible de stocker le fichier d'index inversé"
-
-#, c-format
-msgid "could not parse line: %s"
-msgstr "impossible d'analyser la ligne : %s"
-
-#, c-format
-msgid "malformed line: %s"
-msgstr "ligne malformée : %s"
-
-msgid "ignoring existing multi-pack-index; checksum mismatch"
-msgstr ""
-"index multi-paquet existant ignoré ; non-concordance de la somme de contrôle"
-
-msgid "could not load pack"
-msgstr "impossible de charger le paquet"
-
-#, c-format
-msgid "could not open index for %s"
-msgstr "impossible d'ouvrir l'index pour %s"
-
-msgid "Adding packfiles to multi-pack-index"
-msgstr "Ajout de fichiers paquet à un index multi-paquet"
-
-#, c-format
-msgid "unknown preferred pack: '%s'"
-msgstr "paquet préféré inconnu : %s"
-
-#, c-format
-msgid "cannot select preferred pack %s with no objects"
-msgstr "impossible de sélectionner le paquet préféré %s avec aucun objet"
-
-#, c-format
-msgid "did not see pack-file %s to drop"
-msgstr "fichier paquet à éliminer %s non trouvé"
-
-#, c-format
-msgid "preferred pack '%s' is expired"
-msgstr "le paquet préféré '%s' est expiré"
-
-msgid "no pack files to index."
-msgstr "aucun fichier paquet à l'index."
-
-msgid "refusing to write multi-pack .bitmap without any objects"
-msgstr "refus d'écrire le .bitmap multi-paquet sans aucun objet"
-
-msgid "could not write multi-pack bitmap"
-msgstr "impossible d'écrire le bitmap multi-paquet"
-
-msgid "could not write multi-pack-index"
-msgstr "échec de l'écriture de l'index de multi-paquet"
-
-#, c-format
msgid "failed to clear multi-pack-index at %s"
msgstr "échec du nettoyage de l'index de multi-paquet à %s"
@@ -18115,18 +18172,6 @@ msgstr "impossible de lire le fichier paquet %s"
msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>"
msgstr "décalage d'objet incorrect pour oid[%d] = %s : %<PRIx64> != %<PRIx64>"
-msgid "Counting referenced objects"
-msgstr "Comptage des objets référencés"
-
-msgid "Finding and deleting unreferenced packfiles"
-msgstr "Recherche et effacement des fichiers paquets non-référencés"
-
-msgid "could not start pack-objects"
-msgstr "impossible de démarrer le groupement d'objets"
-
-msgid "could not finish pack-objects"
-msgstr "impossible de finir le groupement d'objets"
-
#, c-format
msgid "unable to create lazy_dir thread: %s"
msgstr "impossible de créer le fil lazy_dir : %s"
@@ -18172,6 +18217,25 @@ msgstr "Refus de réécrire des notes dans %s (hors de refs/notes/)"
msgid "Bad %s value: '%s'"
msgstr "Mauvaise valeur de %s : '%s'"
+msgid "failed to decode tree entry"
+msgstr "échec de décodage de l'entrée d'abre"
+
+#, c-format
+msgid "failed to map tree entry for %s"
+msgstr "échec de mise en correspondance de l'entrée d'arbre avec %s"
+
+#, c-format
+msgid "bad %s in commit"
+msgstr "%s mauvais dans le commit"
+
+#, c-format
+msgid "unable to map %s %s in commit object"
+msgstr "impossible de faire correspondre %s %s dans l'objet de commit"
+
+#, c-format
+msgid "Failed to convert object from %s to %s"
+msgstr "Échec de conversion de l'objet de %s vers %s"
+
#, c-format
msgid "object directory %s does not exist; check .git/objects/info/alternates"
msgstr ""
@@ -18276,6 +18340,10 @@ msgid "packed object %s (stored in %s) is corrupt"
msgstr "l'objet empaqueté %s (stocké dans %s) est corrompu"
#, c-format
+msgid "missing mapping of %s to %s"
+msgstr "correspondance manquante entre %s et %s"
+
+#, c-format
msgid "unable to write file %s"
msgstr "impossible d'écrire le fichier %s"
@@ -18330,6 +18398,10 @@ msgid "cannot read object for %s"
msgstr "impossible de lire l'objet pour %s"
#, c-format
+msgid "cannot map object %s to %s"
+msgstr "impossible de faire correspondre l'objet %s avec %s"
+
+#, c-format
msgid "object fails fsck: %s"
msgstr "l'objet est en échec de fsck : %s"
@@ -19712,6 +19784,79 @@ msgid "could not delete references: %s"
msgstr "impossible de supprimer les références : %s"
#, c-format
+msgid "refname is dangerous: %s"
+msgstr "le nom de réference est dangereux : %s"
+
+#, c-format
+msgid "trying to write ref '%s' with nonexistent object %s"
+msgstr "essai d'écriture de la réf '%s' avec l'objet inexistant %s"
+
+#, c-format
+msgid "trying to write non-commit object %s to branch '%s'"
+msgstr "essai d'écriture de l'objet non commit %s dans la branche '%s'"
+
+#, c-format
+msgid ""
+"multiple updates for 'HEAD' (including one via its referent '%s') are not "
+"allowed"
+msgstr ""
+"mises à jour multiples pour la réf 'HEAD' (l'une d'elle étant via son "
+"référence '%s') non permises"
+
+#, c-format
+msgid "cannot lock ref '%s': unable to resolve reference '%s'"
+msgstr ""
+"impossible de verrouiller la référence '%s' : impossible de résoudre la "
+"référence '%s'"
+
+#, c-format
+msgid "cannot lock ref '%s': error reading reference"
+msgstr ""
+"impossible de verrouiller la référence '%s' : erreur de lecture de la "
+"référence"
+
+#, c-format
+msgid ""
+"multiple updates for '%s' (including one via symref '%s') are not allowed"
+msgstr ""
+"mises à jour multiples pour '%s' (dont un via la symref '%s') non permises"
+
+#, c-format
+msgid "cannot lock ref '%s': reference already exists"
+msgstr "impossible de verrouiller la référence '%s' : la référence existe déjà"
+
+#, c-format
+msgid "cannot lock ref '%s': reference is missing but expected %s"
+msgstr ""
+"impossible de verrouiller la réf '%s' : la référence manque mais %s était "
+"attendu"
+
+#, c-format
+msgid "cannot lock ref '%s': is at %s but expected %s"
+msgstr "impossible de verrouiller '%s' : pointe sur %s mais %s était attendu"
+
+#, c-format
+msgid "reftable: transaction prepare: %s"
+msgstr "reftable : préparation de transaction : %s"
+
+#, c-format
+msgid "reftable: transaction failure: %s"
+msgstr "reftable : échec de transaction : %s"
+
+#, c-format
+msgid "unable to compact stack: %s"
+msgstr "impossible de compacter la pile : %s"
+
+#, c-format
+msgid "refname %s not found"
+msgstr "nom de réf '%s' non trouvé"
+
+#, c-format
+msgid "refname %s is a symbolic ref, copying it is not supported"
+msgstr ""
+"le nom de réf %s est une réf symbolique, la copie n'est pas prise en charge"
+
+#, c-format
msgid "invalid refspec '%s'"
msgstr "spécificateur de réference invalide : '%s'"
@@ -19720,6 +19865,10 @@ msgid "invalid quoting in push-option value: '%s'"
msgstr "citation invalide dans la valeur push-option : '%s'"
#, c-format
+msgid "unknown value for object-format: %s"
+msgstr "valeur inconnue pour object-format : %s"
+
+#, c-format
msgid "%sinfo/refs not valid: is this a git repository?"
msgstr "%sinfo/refs n'est pas valide : est-ce bien un dépôt git ?"
@@ -20175,9 +20324,19 @@ msgid "resolve-undo records `%s` which is missing"
msgstr "resolve-undo enregistre `%s` qui manque"
#, c-format
-msgid "could not get commit for ancestry-path argument %s"
+msgid "%s exists but is a symbolic ref"
+msgstr "%s existe mais c'est une référence symbolique"
+
+msgid ""
+"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD or REBASE_HEAD"
msgstr ""
-"impossible de récupérer le commit pour l'argument de chemin d'ascendance %s"
+"--merge nécessite une pseudo-réf MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD "
+"ou REBASE_HEAD"
+
+#, c-format
+msgid "could not get commit for --ancestry-path argument %s"
+msgstr "impossible de récupérer le commit pour l'argument --ancestry-path %s"
msgid "--unpacked=<packfile> no longer supported"
msgstr "--unpacked=<fichier-paquet> n'est plus géré"
@@ -20467,6 +20626,19 @@ msgid "unknown action: %d"
msgstr "action inconnue : %d"
msgid ""
+"Resolve all conflicts manually, mark them as resolved with\n"
+"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
+"You can instead skip this commit: run \"git rebase --skip\".\n"
+"To abort and get back to the state before \"git rebase\", run \"git rebase --"
+"abort\"."
+msgstr ""
+"Résolvez tous les conflits manuellement, marquez-les comme résolus avec\n"
+"\"git add/rm <fichier en conflit>\", puis lancez \"git rebase --continue\".\n"
+"Si vous préférez sauter ce commit, lancez \"git rebase --skip\". Pour "
+"arrêter\n"
+"et revenir à l'état antérieur à la commande, lancez \"git rebase --abort\"."
+
+msgid ""
"after resolving the conflicts, mark the corrected paths\n"
"with 'git add <paths>' or 'git rm <paths>'"
msgstr ""
@@ -20690,10 +20862,6 @@ msgid "could not update %s"
msgstr "impossible de mettre à jour %s"
#, c-format
-msgid "could not parse commit %s"
-msgstr "impossible d'analyser le commit %s"
-
-#, c-format
msgid "could not parse parent commit %s"
msgstr "impossible d'analyser le commit parent %s"
@@ -20799,10 +20967,6 @@ msgid "invalid command '%.*s'"
msgstr "commande '%.*s' invalide"
#, c-format
-msgid "%s does not accept arguments: '%s'"
-msgstr "%s n'accepte pas d'argument : '%s'"
-
-#, c-format
msgid "missing arguments for %s"
msgstr "argument manquant pour %s"
@@ -21261,6 +21425,10 @@ msgstr ""
"configuration invalide"
#, c-format
+msgid "'%s' already specified as '%s'"
+msgstr "'%s' déjà spécifié comme '%s'"
+
+#, c-format
msgid "Expected git repo version <= %d, found %d"
msgstr "Version attendue du dépôt git <= %d, %d trouvée"
@@ -21455,6 +21623,21 @@ msgstr "l'entrée d'index est un répertoire, mais pas clairsemé (%08x)"
msgid "cannot use split index with a sparse index"
msgstr "impossible d'utiliser l'index scindé avec un index clairsemé"
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not start with '('"
+msgstr "mauvais format %s : l'élément '%s' ne commence pas par '('"
+
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not end in ')'"
+msgstr "mauvais format '%s' : l'élément '%s' ne se termine pas ')'"
+
+#. TRANSLATORS: %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: %%%.*s"
+msgstr "mauvais format %s : %%%.*s"
+
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#, c-format
msgid "%u.%2.2u GiB"
@@ -21785,29 +21968,6 @@ msgstr "valeur inconnue '%s' pour la clé '%s'"
msgid "empty trailer token in trailer '%.*s'"
msgstr "symbole vide dans la ligne de fin '%.*s'"
-#, c-format
-msgid "could not read input file '%s'"
-msgstr "impossible de lire le fichier d'entrée '%s'"
-
-#, c-format
-msgid "could not stat %s"
-msgstr "stat impossible de %s"
-
-#, c-format
-msgid "file %s is not a regular file"
-msgstr "%s n'est pas un fichier régulier"
-
-#, c-format
-msgid "file %s is not writable by user"
-msgstr "le fichier %s n'est pas inscriptible par l'utilisateur"
-
-msgid "could not open temporary file"
-msgstr "impossible de créer un fichier temporaire"
-
-#, c-format
-msgid "could not rename temporary file to %s"
-msgstr "impossible de renommer un fichier temporaire en %s"
-
msgid "full write to remote helper failed"
msgstr "échec de l'écriture totale sur l'assistant distant"
@@ -21908,8 +22068,8 @@ msgstr ""
"nécessaire"
#, c-format
-msgid "helper %s does not support 'force'"
-msgstr "l'assistant %s ne gère pas 'force'"
+msgid "helper %s does not support '--force'"
+msgstr "l'assistant %s ne gère pas '--force'"
msgid "couldn't run fast-export"
msgstr "impossible de lancer fast-export"
@@ -22332,6 +22492,10 @@ msgstr "numéro de port invalide"
msgid "invalid '..' path segment"
msgstr "segment de chemin '..' invalide"
+#, c-format
+msgid "error: unable to format message: %s\n"
+msgstr "erreur : impossible de formater le message : %s\n"
+
msgid "usage: "
msgstr "usage : "
@@ -23302,6 +23466,49 @@ msgstr "%s sauté avec un suffix de sauvegarde '%s'.\n"
msgid "Do you really want to send %s? [y|N]: "
msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : "
+#~ msgid ""
+#~ "Use -f if you really want to add them.\n"
+#~ "Turn this message off by running\n"
+#~ "\"git config advice.addIgnoredFile false\""
+#~ msgstr ""
+#~ "Utilisez -f si vous voulez vraiment les ajouter.\n"
+#~ "Éliminez ce message en lançant\n"
+#~ "\"git config advice.addIgnoredFile false\""
+
+#~ msgid ""
+#~ "Maybe you wanted to say 'git add .'?\n"
+#~ "Turn this message off by running\n"
+#~ "\"git config advice.addEmptyPathspec false\""
+#~ msgstr ""
+#~ "Peut-être avez-vous voulu dire 'git add .' ?\n"
+#~ "Éliminez ce message en lançant\n"
+#~ "\"git config advice.addEmptyPathspec false\""
+
+#~ msgid ""
+#~ "clean.requireForce defaults to true and neither -i, -n, nor -f given; "
+#~ "refusing to clean"
+#~ msgstr ""
+#~ "clean.requireForce à true par défaut et ni -i, -n ou -f fourni ; refus de "
+#~ "nettoyer"
+
+#, c-format
+#~ msgid "bad ls-files format: element '%s' does not start with '('"
+#~ msgstr "mauvais format ls-files : l'élément '%s' ne commence pas par '('"
+
+#, c-format
+#~ msgid "bad ls-files format: element '%s' does not end in ')'"
+#~ msgstr "mauvais format ls-files : l'élément '%s' ne se termine pas par ')'"
+
+#, c-format
+#~ msgid "bad ls-files format: %%%.*s"
+#~ msgstr "mauvais format ls-files : %%%.*s"
+
+#~ msgid "keep redundant, empty commits"
+#~ msgstr "garder les validations redondantes, vides"
+
+#~ msgid "core.commentChar should only be one ASCII character"
+#~ msgstr "core.commentChar ne devrait être qu'un unique caractère ASCII"
+
#~ msgid "-x and -X cannot be used together"
#~ msgstr "-x et -X ne peuvent pas être utilisés ensemble"
@@ -23350,10 +23557,6 @@ msgstr "Souhaitez-vous réellement envoyer %s ?[y|N] : "
#~ msgid "%s is incompatible with %s"
#~ msgstr "%s est incompatible avec %s"
-#, c-format
-#~ msgid "could not remove reference %s"
-#~ msgstr "impossible de supprimer la référence %s"
-
#~ msgid "unhandled options"
#~ msgstr "options non gérées"
diff --git a/po/id.po b/po/id.po
index 3e8b212b61..2dc4b79e8a 100644
--- a/po/id.po
+++ b/po/id.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2024-02-16 09:36+0700\n"
-"PO-Revision-Date: 2024-02-16 10:45+0700\n"
+"POT-Creation-Date: 2024-04-25 18:57+0000\n"
+"PO-Revision-Date: 2024-04-26 15:33+0700\n"
"Last-Translator: Bagas Sanjaya <bagasdotme@gmail.com>\n"
"Language-Team: Indonesian\n"
"Language: id\n"
@@ -591,12 +591,12 @@ msgid ""
"---\n"
"To remove '%c' lines, make them ' ' lines (context).\n"
"To remove '%c' lines, delete them.\n"
-"Lines starting with %c will be removed.\n"
+"Lines starting with %s will be removed.\n"
msgstr ""
"---\n"
"Untuk menghapus baris '%c', buatlah menjadi baris ' ' (konteks).\n"
"Untuk menghapus baris '%c', hapuslahnya.\n"
-"Baris yang diawali dengan %c akan dihapus.\n"
+"Baris yang diawali dengan %s akan dihapus.\n"
#: add-patch.c
msgid ""
@@ -651,17 +651,19 @@ msgid ""
"/ - search for a hunk matching the given regex\n"
"s - split the current hunk into smaller hunks\n"
"e - manually edit the current hunk\n"
+"p - print the current hunk\n"
"? - print help\n"
msgstr ""
-"j - biarkan bingkah ini ragu, lihat bingkah ragu berikutnya\n"
-"J - biarkan bingkah ini ragu, lihat bingkah berikutnya\n"
-"k - biarkan bingkah ini ragu, lihat bingkah ragu sebelumnya\n"
-"K - biarkan bingkah ini ragu, lihat bingkah sebelumnya\n"
+"j - biarkan bingkah ini, lihat bingkah berikutnya yang belum diputuskan\n"
+"J - biarkan bingkah ini, lihat bingkah berikutnya\n"
+"k - biarkan bingkah ini, lihat bingkah sebelumnya yang belum diputuskan\n"
+"K - biarkan bingkah ini, lihat bingkah sebelumnya\n"
"g - pilih satu bingkah untuk dikunjungi\n"
"/ - cari satu bingkah yang cocok dengan regex yang diberikan\n"
"s - belah bingkah saat ini ke dalam bingkah yang lebih kecil\n"
"e - sunting bingkah saat ini secara manual\n"
-"? - cetak bantuan\n"
+"p - lihat bingkah saat ini\n"
+"? - lihat bantuan\n"
#: add-patch.c
msgid "No previous hunk"
@@ -740,8 +742,8 @@ msgstr ""
#: advice.c
#, c-format
-msgid "%shint: %.*s%s\n"
-msgstr "%shint: %.*s%s\n"
+msgid "%shint:%s%.*s%s\n"
+msgstr "%spetunjuk:%s%.*s%s\n"
#: advice.c
msgid "Cherry-picking is not possible because you have unmerged files."
@@ -1359,11 +1361,6 @@ msgstr[1] "Menerapkan tambalan %%s dengan %d penolakan..."
#: apply.c
#, c-format
-msgid "truncating .rej filename to %.*s.rej"
-msgstr "memotong nama berkas .rej ke %.*s.rej"
-
-#: apply.c
-#, c-format
msgid "cannot open %s"
msgstr "tidak dapat membuka %s"
@@ -1904,6 +1901,11 @@ msgstr "sebuah revisi %s diperlukan"
msgid "could not create file '%s'"
msgstr "tidak dapat membuat berkas '%s'"
+#: bisect.c builtin/notes.c
+#, c-format
+msgid "unable to start 'show' for object '%s'"
+msgstr "tidak dapat memulai 'show' untuk objek '%s'"
+
#: bisect.c builtin/merge.c
#, c-format
msgid "could not read file '%s'"
@@ -1954,8 +1956,8 @@ msgstr ""
"--reverse dan --first-parent bersama-sama butuh komit terbaru yang disebutkan"
#: blame.c builtin/commit.c builtin/log.c builtin/merge.c
-#: builtin/pack-objects.c builtin/shortlog.c midx.c pack-bitmap.c remote.c
-#: sequencer.c submodule.c
+#: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c
+#: remote.c sequencer.c submodule.c
msgid "revision walk setup failed"
msgstr "persiapan jalan revisi gagal"
@@ -2080,6 +2082,10 @@ msgstr ""
msgid "'%s' is not a valid branch name"
msgstr "'%s' bukan nama cabang valid"
+#: branch.c builtin/branch.c
+msgid "See `man git check-ref-format`"
+msgstr "Lihat `man git check-ref-format`"
+
#: branch.c
#, c-format
msgid "a branch named '%s' already exists"
@@ -2319,14 +2325,8 @@ msgid "adding embedded git repository: %s"
msgstr "menambahkan repositori git tertanam: %s"
#: builtin/add.c
-msgid ""
-"Use -f if you really want to add them.\n"
-"Turn this message off by running\n"
-"\"git config advice.addIgnoredFile false\""
-msgstr ""
-"Gunakan -f jika Anda benar-benar ingin menambahkannya.\n"
-"Matikan pesan ini dengan menjalankan\n"
-"\"git config advice.addIgnoredFile false\""
+msgid "Use -f if you really want to add them."
+msgstr "Gunakan -f jika Anda benar-benar ingin menambahkannya."
#: builtin/add.c
msgid "adding files failed"
@@ -2349,14 +2349,8 @@ msgid "Nothing specified, nothing added.\n"
msgstr "Tidak ada yang disebutkan, tidak ada yang ditambahkan.\n"
#: builtin/add.c
-msgid ""
-"Maybe you wanted to say 'git add .'?\n"
-"Turn this message off by running\n"
-"\"git config advice.addEmptyPathspec false\""
-msgstr ""
-"Mungkin Anda ingin bilang 'git add .'?\n"
-"Matikan pesan ini dengan menjalankan\n"
-"\"git config advice.addEmptyPathspec false\""
+msgid "Maybe you wanted to say 'git add .'?"
+msgstr "Mungkin Anda ingin bilang 'git add .'?"
#: builtin/add.c builtin/check-ignore.c builtin/checkout.c builtin/clean.c
#: builtin/commit.c builtin/diff-tree.c builtin/grep.c builtin/mv.c
@@ -2376,8 +2370,8 @@ msgid "bad action '%s' for '%s'"
msgstr "tindakan jelek '%s' untuk '%s'"
#: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c
-#: builtin/pull.c config.c diff-merges.c gpg-interface.c ls-refs.c
-#: parallel-checkout.c sequencer.c setup.c
+#: builtin/pull.c builtin/revert.c config.c diff-merges.c gpg-interface.c
+#: ls-refs.c parallel-checkout.c sequencer.c setup.c
#, c-format
msgid "invalid value for '%s': '%s'"
msgstr "nilai tidak valid untuk '%s': '%s'"
@@ -2461,29 +2455,30 @@ msgstr "Gagal memecah tambalan."
#: builtin/am.c
#, c-format
-msgid "When you have resolved this problem, run \"%s --continue\"."
-msgstr "Saat Anda sudah menyelesaikan masalah ini, jalankan \"%s --continue\"."
+msgid "When you have resolved this problem, run \"%s --continue\".\n"
+msgstr ""
+"Saat Anda sudah menyelesaikan masalah ini, jalankan \"%s --continue\".\n"
#: builtin/am.c
#, c-format
-msgid "If you prefer to skip this patch, run \"%s --skip\" instead."
+msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n"
msgstr ""
-"Jika Anda lebih suka melewati tambalan ini, jalankan \"%s --skip\" sebagai "
-"gantinya."
+"Jika Anda lebih suka melewati tambalan ini, jalankan \"%s --skip\" saja.\n"
#: builtin/am.c
#, c-format
-msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"."
+msgid ""
+"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"
msgstr ""
"Untuk merekam tambalan kosong sebagai komit kosong, jalankan \"%s --allow-"
-"empty\"."
+"empty\".\n"
#: builtin/am.c
#, c-format
msgid "To restore the original branch and stop patching, run \"%s --abort\"."
msgstr ""
"Untuk mengembalikan cabang yang asli dan berhenti menambal, jalankan \"%s --"
-"abort\""
+"abort\"."
#: builtin/am.c
msgid "Patch sent with format=flowed; space at the end of lines might be lost."
@@ -3553,11 +3548,11 @@ msgstr "cabang disalin, tapi pembaruan berkas konfigurasi gagal"
msgid ""
"Please edit the description for the branch\n"
" %s\n"
-"Lines starting with '%c' will be stripped.\n"
+"Lines starting with '%s' will be stripped.\n"
msgstr ""
"Mohon sunting deskripsi untuk cabang\n"
" %s\n"
-"Baris yang diawali dengan '%c' akan dicopot.\n"
+"Baris yang diawali dengan '%s' akan dicopot.\n"
#: builtin/branch.c
msgid "Generic options"
@@ -3820,11 +3815,12 @@ msgstr ""
#: builtin/bugreport.c
msgid ""
-"git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"git bugreport [(-o | --output-directory) <path>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
" [--diagnose[=<mode>]]"
msgstr ""
-"git bugreport [(-o | --output-directory) <berkas>] [(-s |-- suffix) "
-"<format>]\n"
+"git bugreport [(-o | --output-directory) <jalur>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
" [--diagnose[=<mode>]]"
#: builtin/bugreport.c
@@ -4438,6 +4434,12 @@ msgstr "'%s', '%s', atau '%s' tidak dapat digunakan ketika men-checkout pohon"
msgid "path '%s' is unmerged"
msgstr "jalur '%s' tak tergabung"
+#: builtin/checkout.c builtin/grep.c builtin/merge-tree.c builtin/reset.c
+#: merge-ort.c reset.c sequencer.c tree-walk.c
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr "tidak dapat membaca pohon (%s)"
+
#: builtin/checkout.c
msgid "you need to resolve your current index first"
msgstr "Anda perlu selesaikan dulu indeks Anda saat ini"
@@ -4708,6 +4710,11 @@ msgid "missing branch or commit argument"
msgstr "kehilangan argumen cabang atau komit"
#: builtin/checkout.c
+#, c-format
+msgid "unknown conflict style '%s'"
+msgstr "gaya konflik '%s' tidak dikenal"
+
+#: builtin/checkout.c
msgid "perform a 3-way merge with the new branch"
msgstr "lakukan penggabungan 3 arah dengan cabang baru"
@@ -5030,20 +5037,8 @@ msgid "remove only ignored files"
msgstr "hanya hapus berkas terabaikan"
#: builtin/clean.c
-msgid ""
-"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to "
-"clean"
-msgstr ""
-"clean.requireForce disetel ke true dan baik -i, -n, atau -f tidak diberikan; "
-"menolak membersihkan"
-
-#: builtin/clean.c
-msgid ""
-"clean.requireForce defaults to true and neither -i, -n, nor -f given; "
-"refusing to clean"
-msgstr ""
-"clean.requireForce asal ke true dan baik -i, -n, atau -f tidak diberikan; "
-"menolak membersihkan"
+msgid "clean.requireForce is true and -f not given: refusing to clean"
+msgstr "clean.requireForce 'true' dan -f tidak diberikan: menolak membersihkan"
#: builtin/clone.c
msgid "git clone [<options>] [--] <repo> [<dir>]"
@@ -5062,8 +5057,8 @@ msgid "create a bare repository"
msgstr "buat repositori bare"
#: builtin/clone.c
-msgid "create a mirror repository (implies bare)"
-msgstr "buat repositori cermin (implikasikan bare)"
+msgid "create a mirror repository (implies --bare)"
+msgstr "buat repositori cermin (mengimplikasikan --bare)"
#: builtin/clone.c
msgid "to clone from a local repository"
@@ -5470,6 +5465,11 @@ msgid "padding space between columns"
msgstr "bantalan spasi di antara kolom"
#: builtin/column.c
+#, c-format
+msgid "%s must be non-negative"
+msgstr "%s harus non-negatif"
+
+#: builtin/column.c
msgid "--command must be the first argument"
msgstr "--command harus menjadi argumen pertama"
@@ -5810,7 +5810,7 @@ msgstr ""
"tidak dapat memilih karakter komentar yang tidak terpakai\n"
"dalam pesan komit saat ini"
-#: builtin/commit.c builtin/merge-tree.c
+#: builtin/commit.c
#, c-format
msgid "could not lookup commit '%s'"
msgstr "tidak dapat mencari komit '%s'"
@@ -5855,38 +5855,38 @@ msgstr "tidak dapat menulis templat komit"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored.\n"
+"with '%s' will be ignored.\n"
msgstr ""
"Mohon masukkan pesan komit untuk perubahan Anda. Baris yang diawali\n"
-"dengan '%c' akan diabaikan.\n"
+"dengan '%s' akan diabaikan.\n"
#: builtin/commit.c
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored, and an empty message aborts the commit.\n"
+"with '%s' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
"Mohon masukkan pesan komit untuk perubahan Anda. Baris yang diawali\n"
-"dengan '%c' akan diabaikan, dan pesan kosong batalkan komit.\n"
+"dengan '%s' akan diabaikan, dan pesan kosong batalkan komit.\n"
#: builtin/commit.c
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
msgstr ""
"Mohon masukkan pesan komit untuk perubahan Anda. Baris yang diawali\n"
-"dengan '%c' akan tetap; Anda dapat menghapusnya jika Anda mau.\n"
+"dengan '%s' akan tetap; Anda dapat menghapusnya jika Anda mau.\n"
#: builtin/commit.c
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
"Mohon masukkan pesan komit untuk perubahan Anda. Baris yang diawali\n"
-"dengan '%c' akan tetap; Anda dapat menghapusnya jika Anda mau.\n"
+"dengan '%s' akan tetap; Anda dapat menghapusnya jika Anda mau.\n"
"Pesan kosong batalkan komit.\n"
#: builtin/commit.c
@@ -6118,7 +6118,7 @@ msgstr "tangal"
msgid "override date for commit"
msgstr "timpa tanggal komit"
-#: builtin/commit.c builtin/merge-tree.c parse-options.h ref-filter.h
+#: builtin/commit.c parse-options.h ref-filter.h
msgid "commit"
msgstr "komit"
@@ -6449,6 +6449,11 @@ msgid "with --get, use default value when missing entry"
msgstr "dengan --get, gunakan nilai asali ketika kehilangan entri"
#: builtin/config.c
+msgid "human-readable comment string (# will be prepended as needed)"
+msgstr ""
+"untai komentar yang dapat dibaca manusia (# akan ditambahkan bila diperlukan"
+
+#: builtin/config.c
#, c-format
msgid "wrong number of arguments, should be %d"
msgstr "jumlah argumen salah, seharusnya %d"
@@ -6564,6 +6569,12 @@ msgid "--default is only applicable to --get"
msgstr "--default hanya dapat diterapkan pada --get"
#: builtin/config.c
+msgid "--comment is only applicable to add/set/replace operations"
+msgstr ""
+"--comment hanya dapat diterapkan pada operasi penambahan/penyetelan/"
+"penggantian"
+
+#: builtin/config.c
msgid "--fixed-value only applies with 'value-pattern'"
msgstr "--fixed-value hanya diterapkan dengan 'pola nilai'"
@@ -7631,6 +7642,10 @@ msgid "read reference patterns from stdin"
msgstr "baca pola referensi dari masukan standar"
#: builtin/for-each-ref.c
+msgid "also include HEAD ref and pseudorefs"
+msgstr "juga termasuk referensi HEAD dan referensi semu"
+
+#: builtin/for-each-ref.c
msgid "unknown arguments supplied with --stdin"
msgstr "argumen tidak dikenal diberikan dengan --stdin"
@@ -8413,11 +8428,6 @@ msgstr "tidak ada dukungan utas, abaikan %s"
#: builtin/grep.c
#, c-format
-msgid "unable to read tree (%s)"
-msgstr "tidak dapat membaca pohon (%s)"
-
-#: builtin/grep.c
-#, c-format
msgid "unable to read tree %s"
msgstr "tidak dapat membaca pohon %s"
@@ -9189,7 +9199,7 @@ msgstr "--separate-git-dir tidak kompatibel dengan repositori bare"
#: builtin/interpret-trailers.c
msgid ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n"
+" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
" [--parse] [<file>...]"
msgstr ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
@@ -9197,6 +9207,39 @@ msgstr ""
"[(=|:)<nilai>])...]\n"
" [--parse] [<berkas>...]"
+#: builtin/interpret-trailers.c wrapper.c
+#, c-format
+msgid "could not stat %s"
+msgstr "tidak dapat membaca %s"
+
+#: builtin/interpret-trailers.c
+#, c-format
+msgid "file %s is not a regular file"
+msgstr "berkas %s bukan sebuah berkas reguler"
+
+#: builtin/interpret-trailers.c
+#, c-format
+msgid "file %s is not writable by user"
+msgstr "berkas %s tidak dapat ditulis oleh pengguna"
+
+#: builtin/interpret-trailers.c
+msgid "could not open temporary file"
+msgstr "tidak dapat membuka berkas sementara"
+
+#: builtin/interpret-trailers.c
+#, c-format
+msgid "could not read input file '%s'"
+msgstr "tidak dapat membaca berkas masukan '%s'"
+
+#: builtin/interpret-trailers.c builtin/mktag.c imap-send.c
+msgid "could not read from stdin"
+msgstr "tidak dapat membaca dari masukan standar"
+
+#: builtin/interpret-trailers.c
+#, c-format
+msgid "could not rename temporary file to %s"
+msgstr "tidak dapat menamai ulang berkas sementara ke %s"
+
#: builtin/interpret-trailers.c
msgid "edit files in place"
msgstr "sunting berkas di tempat"
@@ -9705,21 +9748,6 @@ msgid "could not get object info about '%s'"
msgstr "tidak dapat mendapatkan info objek tentang '%s'"
#: builtin/ls-files.c
-#, c-format
-msgid "bad ls-files format: element '%s' does not start with '('"
-msgstr "format ls-files jelek: elemen '%s' tidak dimulai dengan '('"
-
-#: builtin/ls-files.c
-#, c-format
-msgid "bad ls-files format: element '%s' does not end in ')'"
-msgstr "format ls-files jelek: elemen '%s' tidak diakhiri dengan ')'"
-
-#: builtin/ls-files.c
-#, c-format
-msgid "bad ls-files format: %%%.*s"
-msgstr "format ls-files jelek: %%%.*s"
-
-#: builtin/ls-files.c
msgid "git ls-files [<options>] [<file>...]"
msgstr "git ls-files [<opsi>] [<berkas>...]"
@@ -9812,7 +9840,7 @@ msgid "if any <file> is not in the index, treat this as an error"
msgstr ""
"jika <berkas> apapun tidak berada di indeks, perlakukan sebagai kesalahan"
-#: builtin/ls-files.c
+#: builtin/ls-files.c builtin/merge-tree.c
msgid "tree-ish"
msgstr "mirip-pohon"
@@ -9892,21 +9920,6 @@ msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
msgstr "git ls-tree [<opsi>] <mirip-pohon> [<jalur>...]"
#: builtin/ls-tree.c
-#, c-format
-msgid "bad ls-tree format: element '%s' does not start with '('"
-msgstr "format ls-tree jelek: elemen '%s' tidak dimulai dengan '('"
-
-#: builtin/ls-tree.c
-#, c-format
-msgid "bad ls-tree format: element '%s' does not end in ')'"
-msgstr "format ls-tree jelek: elemen '%s' tidak diakhiri dengan ')'"
-
-#: builtin/ls-tree.c
-#, c-format
-msgid "bad ls-tree format: %%%.*s"
-msgstr "format ls-tree jelek: %%%.*s"
-
-#: builtin/ls-tree.c
msgid "only show trees"
msgstr "hanya perlihatkan pohon"
@@ -10150,6 +10163,11 @@ msgstr "tidak dapat menguraikan referensi '%s'"
msgid "Merging %s with %s\n"
msgstr "Menggabungkan %s dengan %s\n"
+#: builtin/merge-tree.c
+#, c-format
+msgid "could not parse as tree '%s'"
+msgstr "tidak dapat mengurai '%s' sebagai pohon"
+
#: builtin/merge-tree.c builtin/merge.c
msgid "not something we can merge"
msgstr "bukan sesuatu yang kami bisa gabungkan"
@@ -10414,10 +10432,10 @@ msgstr "Pesan kosong membatalkan komit.\n"
#: builtin/merge.c
#, c-format
msgid ""
-"Lines starting with '%c' will be ignored, and an empty message aborts\n"
+"Lines starting with '%s' will be ignored, and an empty message aborts\n"
"the commit.\n"
msgstr ""
-"Baris yang diawali dengan '%c' akan diabaikan, dan pesan kosong batalkan\n"
+"Baris yang diawali dengan '%s' akan diabaikan, dan pesan kosong batalkan\n"
"komit.\n"
#: builtin/merge.c
@@ -10615,10 +10633,6 @@ msgstr "tidak dapat membaca objek tertag '%s'"
msgid "object '%s' tagged as '%s', but is a '%s' type"
msgstr "objek '%s' ditag sebagai '%s', tetapi bertipe '%s'"
-#: builtin/mktag.c imap-send.c trailer.c
-msgid "could not read from stdin"
-msgstr "tidak dapat membaca dari masukan standar"
-
#: builtin/mktag.c
msgid "tag on stdin did not pass our strict fsck check"
msgstr "tag pada masukan standar tidak lolos pemeriksaan fsck ketat kami"
@@ -10956,11 +10970,6 @@ msgid "Write/edit the notes for the following object:"
msgstr "Tulis/sunting catatan untuk objek berikut:"
#: builtin/notes.c
-#, c-format
-msgid "unable to start 'show' for object '%s'"
-msgstr "tidak dapat memulai 'show' untuk objek '%s'"
-
-#: builtin/notes.c
msgid "could not read 'show' output"
msgstr "tidak dapat membaca keluaran 'show'"
@@ -11754,10 +11763,11 @@ msgstr "menolak menjalankan tanpa --i-still-use-this"
#: builtin/pack-refs.c
msgid ""
-"git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude "
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
"<pattern>]"
msgstr ""
-"git pack-refs [--all] [--no-prune] [--include <pola>] [--exclude <pola>]"
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pola>][--exclude "
+"<pola>]"
#: builtin/pack-refs.c
msgid "pack everything"
@@ -11768,6 +11778,10 @@ msgid "prune loose refs (default)"
msgstr "pangkas referensi longgar (asali)"
#: builtin/pack-refs.c
+msgid "auto-pack refs as needed"
+msgstr "otomatis pak referensi jika dibutuhkan"
+
+#: builtin/pack-refs.c
msgid "references to include"
msgstr "referensi untuk ditambahkan"
@@ -12565,21 +12579,6 @@ msgid "could not remove '%s'"
msgstr "tidak dapat menghapus '%s'"
#: builtin/rebase.c
-msgid ""
-"Resolve all conflicts manually, mark them as resolved with\n"
-"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
-"You can instead skip this commit: run \"git rebase --skip\".\n"
-"To abort and get back to the state before \"git rebase\", run \"git rebase --"
-"abort\"."
-msgstr ""
-"Selesaikan semua konflik secara manual, tandai sebagai terselesaikan\n"
-"dengan \"git add/rm <berkas terkonflik>\", lalu jalankan\n"
-"\"git rebase --continue\".\n"
-"Anda juga bisa melewatkan komit ini: jalankan \"git rebase --skip\".\n"
-"Untuk membatalkan dan kembali ke kondisi sebelum \"git rebase\",jalankan "
-"\"git rebase --abort\"."
-
-#: builtin/rebase.c
#, c-format
msgid ""
"\n"
@@ -12613,13 +12612,17 @@ msgid "apply options and merge options cannot be used together"
msgstr "opsi apply dan opsi merge tidak dapat digunakan bersamaan"
#: builtin/rebase.c
+msgid "--empty=ask is deprecated; use '--empty=stop' instead."
+msgstr "--empty=ask usang; gunakan '--empty=stop' sebagai gantinya."
+
+#: builtin/rebase.c
#, c-format
msgid ""
"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
-"\"ask\"."
+"\"stop\"."
msgstr ""
"tipe kosong tak dikenali '%s'; nilai yang valid adalah \"drop\", \"keep\", "
-"dan \"ask\"."
+"dan \"stop\"."
#: builtin/rebase.c
msgid ""
@@ -12761,7 +12764,7 @@ msgstr "biarkan pengguna menyunting daftar komit untuk didasarkan ulang"
msgid "(REMOVED) was: try to recreate merges instead of ignoring them"
msgstr "(USANG) yaitu: coba buat ulang penggabungan daripada abaikannya"
-#: builtin/rebase.c
+#: builtin/rebase.c builtin/revert.c
msgid "how to handle commits that become empty"
msgstr "bagaimana cara menangani komit yang menjadi kosong"
@@ -12843,8 +12846,8 @@ msgstr ""
"yang tidak lagi didukung; gunakan 'merges' sebagai gantinya"
#: builtin/rebase.c
-msgid "No rebase in progress?"
-msgstr "Tidak ada pendasaran ulang yang sedang berjalan?"
+msgid "no rebase in progress"
+msgstr "tidak ada pendasaran ulang yang sedang berjalan"
#: builtin/rebase.c
msgid "The --edit-todo action can only be used during interactive rebase."
@@ -13073,6 +13076,10 @@ msgid "git reflog [show] [<log-options>] [<ref>]"
msgstr "git remote [show] [<opsi log>] [<referensi>]"
#: builtin/reflog.c
+msgid "git reflog list"
+msgstr "git reflog list"
+
+#: builtin/reflog.c
msgid ""
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
" [--rewrite] [--updateref] [--stale-fix]\n"
@@ -13101,6 +13108,11 @@ msgstr "git reflog exists <referensi>"
msgid "invalid timestamp '%s' given to '--%s'"
msgstr "stempel waktu tidak valid '%s' diberikan ke '--%s'"
+#: builtin/reflog.c sequencer.c
+#, c-format
+msgid "%s does not accept arguments: '%s'"
+msgstr "%s tidak menerima argumen: '%s'"
+
#: builtin/reflog.c
msgid "do not actually prune any entries"
msgstr "jangan benar-benar pangkas entri apapun"
@@ -13263,8 +13275,8 @@ msgstr ""
#: builtin/remote.c
#, c-format
-msgid "unknown mirror argument: %s"
-msgstr "argumen mirror tidak dikenal: %s"
+msgid "unknown --mirror argument: %s"
+msgstr "argumen --mirror tidak dikenal: %s"
#: builtin/remote.c
msgid "fetch the remote branches"
@@ -13721,6 +13733,10 @@ msgid "could not start pack-objects to repack promisor objects"
msgstr "tidak dapat memulai pack-objects untuk mengepak ulang objek pejanji"
#: builtin/repack.c
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "gagal mengumpan objek penjanji ke pack-objects"
+
+#: builtin/repack.c
msgid "repack: Expecting full hex object ID lines only from pack-objects."
msgstr "repack: Mengharapkan baris ID objek hex penuh hanya dari pack-objects."
@@ -14481,6 +14497,15 @@ msgid "--prefix requires an argument"
msgstr "--prefix butuh sebuah argumen"
#: builtin/rev-parse.c
+msgid "no object format specified"
+msgstr "tidak ada format objek yang disebutkan"
+
+#: builtin/rev-parse.c
+#, c-format
+msgid "unsupported object format: %s"
+msgstr "format objek tidak didukung: '%s'"
+
+#: builtin/rev-parse.c
#, c-format
msgid "unknown mode for --abbrev-ref: %s"
msgstr "mode untuk --abbrev-ref tidak dikenal: %s"
@@ -14585,8 +14610,8 @@ msgid "allow commits with empty messages"
msgstr "perbolehkan komit dengan pesan kosong"
#: builtin/revert.c
-msgid "keep redundant, empty commits"
-msgstr "simpan komit kosong mubazir"
+msgid "deprecated: use --empty=keep instead"
+msgstr "usang: gunakan --empty=keep sebagai gantinya"
#: builtin/revert.c
msgid "use the 'reference' format to refer to commits"
@@ -15047,7 +15072,7 @@ msgstr "inisialisasi checkout tipis dalam mode kerucut"
msgid "toggle the use of a sparse index"
msgstr "gunakan indeks tipis"
-#: builtin/sparse-checkout.c commit-graph.c midx.c sequencer.c
+#: builtin/sparse-checkout.c commit-graph.c midx-write.c sequencer.c
#, c-format
msgid "unable to create leading directories of %s"
msgstr "tidak dapat membuat direktori utama dari %s"
@@ -16246,12 +16271,12 @@ msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be ignored.\n"
+"Lines starting with '%s' will be ignored.\n"
msgstr ""
"\n"
"Tulis pesan untuk tag:\n"
" %s\n"
-"Baris yang diawali dengan '%c' akan diabaikan.\n"
+"Baris yang diawali dengan '%s' akan diabaikan.\n"
#: builtin/tag.c
#, c-format
@@ -16259,13 +16284,13 @@ msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be kept; you may remove them yourself if you "
+"Lines starting with '%s' will be kept; you may remove them yourself if you "
"want to.\n"
msgstr ""
"\n"
"Tulis pesan untuk tag:\n"
" %s\n"
-"Baris yang diawali dengan '%c' akan disimpan; Anda dapat menghapusnya bila "
+"Baris yang diawali dengan '%s' akan disimpan; Anda dapat menghapusnya bila "
"Anda mau.\n"
#: builtin/tag.c
@@ -16376,6 +16401,10 @@ msgid "print only tags of the object"
msgstr "hanya cetak tag dari objek"
#: builtin/tag.c
+msgid "could not start 'git column'"
+msgstr "tidak dapat memulai 'git column'"
+
+#: builtin/tag.c
#, c-format
msgid "the '%s' option is only allowed in list mode"
msgstr "opsi '%s' hanya diperbolehkan dalam mode daftar"
@@ -16687,13 +16716,12 @@ msgid "fsmonitor disabled"
msgstr "fsmonitor dinonaktifkan"
#: builtin/update-ref.c
-msgid "git update-ref [<options>] -d <refname> [<old-val>]"
-msgstr "git update-ref [<opsi>] -d <nama referensi> [<nilai lama>]"
+msgid "git update-ref [<options>] -d <refname> [<old-oid>]"
+msgstr "git update-ref [<opsi>] -d <nama referensi> [<oid lama>]"
#: builtin/update-ref.c
-msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]"
-msgstr ""
-"git update-ref [<opsi>] <nama referensi> <nilai baru> [<nilai lama>]"
+msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]"
+msgstr "git update-ref [<options>] <nama referensi> <oid baru> [<oid lama>]"
#: builtin/update-ref.c
msgid "git update-ref [<options>] --stdin [-z]"
@@ -18428,6 +18456,11 @@ msgstr ""
msgid "Verifying commits in commit graph"
msgstr "Memverifikasi komit di dalam grafik komit"
+#: commit-reach.c sequencer.c
+#, c-format
+msgid "could not parse commit %s"
+msgstr "tidak dapat menguraikan komit %s"
+
#: commit.c
#, c-format
msgid "%s %s is not a commit!"
@@ -18961,8 +18994,14 @@ msgid "bad zlib compression level %d"
msgstr "level kompresi zlib jelek %d"
#: config.c
-msgid "core.commentChar should only be one ASCII character"
-msgstr "core.commentChar seharusnya hanya satu karakter ASCII"
+#, c-format
+msgid "%s cannot contain newline"
+msgstr "%s tidak dapat berisi baris baru"
+
+#: config.c
+#, c-format
+msgid "%s must have at least one character"
+msgstr "%s harus ada sedikitnya satu karakter"
#: config.c
#, c-format
@@ -19052,6 +19091,11 @@ msgstr "gagal menulis berkas konfigurasi baru %s"
#: config.c
#, c-format
+msgid "no multi-line comment allowed: '%s'"
+msgstr "komentar multi baris tidak diperbolehkan: '%s'"
+
+#: config.c
+#, c-format
msgid "could not lock config file %s"
msgstr "tidak dapat mengunci berkas konfigurasi %s"
@@ -21280,6 +21324,16 @@ msgstr ""
msgid "Unable to create '%s.lock': %s"
msgstr "Tidak dapat membuat '%s.lock': %s"
+#: loose.c
+#, c-format
+msgid "could not write loose object index %s"
+msgstr "tidak dapat menulis indeks objek longgar %s"
+
+#: loose.c
+#, c-format
+msgid "failed to write loose object index %s\n"
+msgstr "gagal menulis indeks objek longgar %s\n"
+
#: ls-refs.c
#, c-format
msgid "unexpected line: '%s'"
@@ -21293,6 +21347,11 @@ msgstr "bilasan diharapkan setelah argumen ls-refs"
msgid "quoted CRLF detected"
msgstr "CRLF terkutip terdeteksi"
+#: mem-pool.c strbuf.c wrapper.c
+#, c-format
+msgid "unable to format message: %s"
+msgstr "tidak dapat memformat pesan: %s"
+
#: merge-ort.c merge-recursive.c
#, c-format
msgid "Failed to merge submodule %s (not checked out)"
@@ -21310,6 +21369,11 @@ msgstr "Gagal menggabungkan submodul %s (komit tidak ada)"
#: merge-ort.c merge-recursive.c
#, c-format
+msgid "Failed to merge submodule %s (repository corrupt)"
+msgstr "Gagal menggabungkan submodul %s (repositori rusak)"
+
+#: merge-ort.c merge-recursive.c
+#, c-format
msgid "Failed to merge submodule %s (commits don't follow merge-base)"
msgstr ""
"Gagal menggabungkan submodul %s (komit tidak mengikuti dasar penggabungan)"
@@ -21868,6 +21932,104 @@ msgstr "Tidak dapat menguraikan objek '%s'"
msgid "failed to read the cache"
msgstr "gagal membaca tembolok"
+#: midx-write.c
+#, c-format
+msgid "failed to add packfile '%s'"
+msgstr "gagal menambah berkas pak '%s'"
+
+#: midx-write.c
+#, c-format
+msgid "failed to open pack-index '%s'"
+msgstr "gagal membuka indeks pak '%s'"
+
+#: midx-write.c
+#, c-format
+msgid "failed to locate object %d in packfile"
+msgstr "gagal melokasi objek %d di dalam berkas pak"
+
+#: midx-write.c
+msgid "cannot store reverse index file"
+msgstr "tidak dapat menyimpan berkas indeks balik"
+
+#: midx-write.c
+#, c-format
+msgid "could not parse line: %s"
+msgstr "tidak dapat menguraikan baris: %s"
+
+#: midx-write.c
+#, c-format
+msgid "malformed line: %s"
+msgstr "baris jelek '%s'."
+
+#: midx-write.c
+msgid "ignoring existing multi-pack-index; checksum mismatch"
+msgstr "abaikan indeks multipak yang sudah ada; checksum tidak cocok"
+
+#: midx-write.c
+msgid "could not load pack"
+msgstr "tidak dapat memuat pak"
+
+#: midx-write.c
+#, c-format
+msgid "could not open index for %s"
+msgstr "tidak dapat membuka indeks untuk %s"
+
+#: midx-write.c
+msgid "Adding packfiles to multi-pack-index"
+msgstr "Menambahkan berkas pak ke indeks multipak"
+
+#: midx-write.c
+#, c-format
+msgid "unknown preferred pack: '%s'"
+msgstr "pak yang disukai tidak dikenal: '%s'"
+
+#: midx-write.c
+#, c-format
+msgid "cannot select preferred pack %s with no objects"
+msgstr "tidak dapat memilih pak yang disukai %s tanpa objek"
+
+#: midx-write.c
+#, c-format
+msgid "did not see pack-file %s to drop"
+msgstr "tidak melihat berkas pak %s untuk dijeblokkan"
+
+#: midx-write.c
+#, c-format
+msgid "preferred pack '%s' is expired"
+msgstr "pak yang disukai '%s' kadaluarsa"
+
+#: midx-write.c
+msgid "no pack files to index."
+msgstr "tidak ada berkas pak untuk diindeks."
+
+#: midx-write.c
+msgid "refusing to write multi-pack .bitmap without any objects"
+msgstr "menolak menulis .bitmap multipak tanpa objek apapun"
+
+#: midx-write.c
+msgid "could not write multi-pack bitmap"
+msgstr "tidak dapat menulis bitmap multipak"
+
+#: midx-write.c
+msgid "could not write multi-pack-index"
+msgstr "gagal menulis indeks multipak"
+
+#: midx-write.c
+msgid "Counting referenced objects"
+msgstr "Menghitung objek tereferensi"
+
+#: midx-write.c
+msgid "Finding and deleting unreferenced packfiles"
+msgstr "Mencari dan menghapus berkas pak tak tereferensi"
+
+#: midx-write.c
+msgid "could not start pack-objects"
+msgstr "tidak dapat memulai pack-objects"
+
+#: midx-write.c
+msgid "could not finish pack-objects"
+msgstr "tidak dapat menyelesaikan pack-objects"
+
#: midx.c
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "OID kipas-keluar indeks multipak salah ukuran"
@@ -21960,88 +22122,6 @@ msgstr "offset indeks multipak besar di luar jangkauan"
#: midx.c
#, c-format
-msgid "failed to add packfile '%s'"
-msgstr "gagal menambah berkas pak '%s'"
-
-#: midx.c
-#, c-format
-msgid "failed to open pack-index '%s'"
-msgstr "gagal membuka indeks pak '%s'"
-
-#: midx.c
-#, c-format
-msgid "failed to locate object %d in packfile"
-msgstr "gagal melokasi objek %d di dalam berkas pak"
-
-#: midx.c
-msgid "cannot store reverse index file"
-msgstr "tidak dapat menyimpan berkas indeks balik"
-
-#: midx.c
-#, c-format
-msgid "could not parse line: %s"
-msgstr "tidak dapat menguraikan baris: %s"
-
-#: midx.c
-#, c-format
-msgid "malformed line: %s"
-msgstr "baris jelek '%s'."
-
-#: midx.c
-msgid "ignoring existing multi-pack-index; checksum mismatch"
-msgstr "abaikan indeks multipak yang sudah ada; checksum tidak cocok"
-
-#: midx.c
-msgid "could not load pack"
-msgstr "tidak dapat memuat pak"
-
-#: midx.c
-#, c-format
-msgid "could not open index for %s"
-msgstr "tidak dapat membuka indeks untuk %s"
-
-#: midx.c
-msgid "Adding packfiles to multi-pack-index"
-msgstr "Menambahkan berkas pak ke indeks multipak"
-
-#: midx.c
-#, c-format
-msgid "unknown preferred pack: '%s'"
-msgstr "pak yang disukai tidak dikenal: '%s'"
-
-#: midx.c
-#, c-format
-msgid "cannot select preferred pack %s with no objects"
-msgstr "tidak dapat memilih pak yang disukai %s tanpa objek"
-
-#: midx.c
-#, c-format
-msgid "did not see pack-file %s to drop"
-msgstr "tidak melihat berkas pak %s untuk dijeblokkan"
-
-#: midx.c
-#, c-format
-msgid "preferred pack '%s' is expired"
-msgstr "pak yang disukai '%s' kadaluarsa"
-
-#: midx.c
-msgid "no pack files to index."
-msgstr "tidak ada berkas pak untuk diindeks."
-
-#: midx.c
-msgid "refusing to write multi-pack .bitmap without any objects"
-msgstr "menolak menulis .bitmap multipak tanpa objek apapun"
-
-#: midx.c
-msgid "could not write multi-pack bitmap"
-msgstr "tidak dapat menulis bitmap multipak"
-
-#: midx.c
-msgid "could not write multi-pack-index"
-msgstr "gagal menulis indeks multipak"
-
-#: midx.c
-#, c-format
msgid "failed to clear multi-pack-index at %s"
msgstr "gagal membersihkan indeks multipak pada %s"
@@ -22093,22 +22173,6 @@ msgstr "gagal memuat indeks pak untuk berkas pak %s"
msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>"
msgstr "offset objek salah untuk oid[%d] = %s: %<PRIx64> != %<PRIx64>"
-#: midx.c
-msgid "Counting referenced objects"
-msgstr "Menghitung objek tereferensi"
-
-#: midx.c
-msgid "Finding and deleting unreferenced packfiles"
-msgstr "Mencari dan menghapus berkas pak tak tereferensi"
-
-#: midx.c
-msgid "could not start pack-objects"
-msgstr "tidak dapat memulai pack-objects"
-
-#: midx.c
-msgid "could not finish pack-objects"
-msgstr "tidak dapat menyelesaikan pack-objects"
-
#: name-hash.c
#, c-format
msgid "unable to create lazy_dir thread: %s"
@@ -22164,6 +22228,30 @@ msgstr "Menolak menulis ulang catatan di %s (di luar refs/notes/)"
msgid "Bad %s value: '%s'"
msgstr "Nilai %s jelek: '%s'"
+#: object-file-convert.c
+msgid "failed to decode tree entry"
+msgstr "gagal mendekode entri pohon"
+
+#: object-file-convert.c
+#, c-format
+msgid "failed to map tree entry for %s"
+msgstr "gagal memetakan entri pohon untuk %s"
+
+#: object-file-convert.c
+#, c-format
+msgid "bad %s in commit"
+msgstr "%s di dalam komit"
+
+#: object-file-convert.c
+#, c-format
+msgid "unable to map %s %s in commit object"
+msgstr "tidak dapat memetakan %s %s pada objek komit"
+
+#: object-file-convert.c
+#, c-format
+msgid "Failed to convert object from %s to %s"
+msgstr "Gagal mengkonversi objek dari %s ke %s"
+
#: object-file.c
#, c-format
msgid "object directory %s does not exist; check .git/objects/info/alternates"
@@ -22293,6 +22381,11 @@ msgstr "objek terpak %s (disimpan di %s) rusak"
#: object-file.c
#, c-format
+msgid "missing mapping of %s to %s"
+msgstr "pemetaan %s ke %s hilang"
+
+#: object-file.c
+#, c-format
msgid "unable to write file %s"
msgstr "tidak dapat menulis berkas %s"
@@ -22362,6 +22455,11 @@ msgstr "tidak dapat membaca objek untuk %s"
#: object-file.c
#, c-format
+msgid "cannot map object %s to %s"
+msgstr "tidak dapat memetakan objek %s ke %s"
+
+#: object-file.c
+#, c-format
msgid "object fails fsck: %s"
msgstr "fsck objek gagal: %s"
@@ -22727,6 +22825,11 @@ msgid "unable to load pack: '%s', disabling pack-reuse"
msgstr "tidak dapat memuat pak: '%s', mematikan penggunaan ulang pak"
#: pack-bitmap.c
+msgid "unable to compute preferred pack, disabling pack-reuse"
+msgstr ""
+"tidak dapat menghitung pak yang disukai, mematikan penggunaan ulang pak"
+
+#: pack-bitmap.c
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "objek '%s' tidak ditemukan di bitmap tipe"
@@ -24020,6 +24123,89 @@ msgstr "tidak dapat menghapus referensi %s: %s"
msgid "could not delete references: %s"
msgstr "tidak dapat menghapus referensi: %s"
+#: refs/reftable-backend.c
+#, c-format
+msgid "refname is dangerous: %s"
+msgstr "nama referensi berbahaya: %s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "trying to write ref '%s' with nonexistent object %s"
+msgstr "mencoba menulis referensi '%s' dengan objek %s yang tak ada"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "trying to write non-commit object %s to branch '%s'"
+msgstr "mencoba menulis objek non-komit %s pada cabang '%s'"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid ""
+"multiple updates for 'HEAD' (including one via its referent '%s') are not "
+"allowed"
+msgstr ""
+"beberapa pembaruan 'HEAD' (termasuk yang lewat perujuknya '%s' tidak "
+"diperbolehkan"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': unable to resolve reference '%s'"
+msgstr "tidak dapat mengunci '%s': tidak dapat menguraikan referensi '%s'"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': error reading reference"
+msgstr "tidak dapat mengunci referensi '%s': kesalahan membaca referensi"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid ""
+"multiple updates for '%s' (including one via symref '%s') are not allowed"
+msgstr ""
+"beberapa pembaruan '%s' (termasuk yang lewat referensi simboliknya "
+"'%s')tidak diperbolehkan"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': reference already exists"
+msgstr "tidak dapat mengunci referensi '%s': referensi sudah ada"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': reference is missing but expected %s"
+msgstr ""
+"tidak dapat mengunci referensi '%s' referensi %s hilang tapi diharapkan"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': is at %s but expected %s"
+msgstr "tidak dapat mengunci referensi '%s': pada %s tetapi diharapkan %s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "reftable: transaction prepare: %s"
+msgstr "reftable: menyiapkan transaksi: %s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "reftable: transaction failure: %s"
+msgstr "reftable: transaksi gagal: %s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "unable to compact stack: %s"
+msgstr "tidak dapat memampatkan tumpukan: %s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "refname %s not found"
+msgstr "nama referensi %s tidak ditemukan"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "refname %s is a symbolic ref, copying it is not supported"
+msgstr "nama referensi %s simbolik, menyalinnya tidak didukung"
+
#: refspec.c
#, c-format
msgid "invalid refspec '%s'"
@@ -24032,6 +24218,11 @@ msgstr "kuotasi tidak valid dalam nilai push-option: '%s'"
#: remote-curl.c
#, c-format
+msgid "unknown value for object-format: %s"
+msgstr "nilai object-format tidak dikenal: %s"
+
+#: remote-curl.c
+#, c-format
msgid "%sinfo/refs not valid: is this a git repository?"
msgstr "%sinfo/refs tidak valid: apakah ini sebuah repositori git?"
@@ -24579,8 +24770,21 @@ msgstr "resolve-undo merekam `%s` yang dimana hilang"
#: revision.c
#, c-format
-msgid "could not get commit for ancestry-path argument %s"
-msgstr "tidak dapat mendapatkan komit untuk argumen jalur leluhur '%s'"
+msgid "%s exists but is a symbolic ref"
+msgstr "%s ada dan tapi referensi simbolik"
+
+#: revision.c
+msgid ""
+"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD or REBASE_HEAD"
+msgstr ""
+"--merge butuh salah satu dari referensi semu MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD atau REBASE_HEAD"
+
+#: revision.c
+#, c-format
+msgid "could not get commit for --ancestry-path argument %s"
+msgstr "tidak dapat mendapatkan komit untuk argumen --ancestry-path %s"
#: revision.c
msgid "--unpacked=<packfile> no longer supported"
@@ -24944,6 +25148,21 @@ msgstr "aksi tidak dikenal: %d"
#: sequencer.c
msgid ""
+"Resolve all conflicts manually, mark them as resolved with\n"
+"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
+"You can instead skip this commit: run \"git rebase --skip\".\n"
+"To abort and get back to the state before \"git rebase\", run \"git rebase --"
+"abort\"."
+msgstr ""
+"Selesaikan semua konflik secara manual, tandai sebagai terselesaikan\n"
+"dengan \"git add/rm <berkas terkonflik>\", lalu jalankan\n"
+"\"git rebase --continue\".\n"
+"Anda juga bisa melewatkan komit ini: jalankan \"git rebase --skip\".\n"
+"Untuk membatalkan dan kembali ke kondisi sebelum \"git rebase\",jalankan "
+"\"git rebase --abort\"."
+
+#: sequencer.c
+msgid ""
"after resolving the conflicts, mark the corrected paths\n"
"with 'git add <paths>' or 'git rm <paths>'"
msgstr ""
@@ -25199,11 +25418,6 @@ msgstr "tidak dapat memperbarui %s"
#: sequencer.c
#, c-format
-msgid "could not parse commit %s"
-msgstr "tidak dapat menguraikan komit %s"
-
-#: sequencer.c
-#, c-format
msgid "could not parse parent commit %s"
msgstr "tidak dapat menguraikan komit induk %s"
@@ -25336,11 +25550,6 @@ msgstr "perintah tidak valid '%.*s'"
#: sequencer.c
#, c-format
-msgid "%s does not accept arguments: '%s'"
-msgstr "%s tidak menerima argumen: '%s'"
-
-#: sequencer.c
-#, c-format
msgid "missing arguments for %s"
msgstr "argumen hilang untuk %s"
@@ -25896,6 +26105,11 @@ msgstr "tidak dapat memasang pohon kerja menggunakan konfigurasi tidak valid"
#: setup.c
#, c-format
+msgid "'%s' already specified as '%s'"
+msgstr "'%s' sudah diberikan yaitu '%s'"
+
+#: setup.c
+#, c-format
msgid "Expected git repo version <= %d, found %d"
msgstr "Versi repositori git diharapkan <= %d, dapat %d"
@@ -26130,6 +26344,24 @@ msgstr "entri indeks adalah direktori, tapi bukan tipis (%08x)"
msgid "cannot use split index with a sparse index"
msgstr "tidak dapat menggunakan indeks terpisah dengan indeks tipis"
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#: strbuf.c
+#, c-format
+msgid "bad %s format: element '%s' does not start with '('"
+msgstr "format %s jelek: elemen '%s' tidak dimulai dengan '('"
+
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#: strbuf.c
+#, c-format
+msgid "bad %s format: element '%s' does not end in ')'"
+msgstr "format %s jelek: elemen '%s' tidak diakhiri dengan ')'"
+
+#. TRANSLATORS: %s is a command like "ls-tree".
+#: strbuf.c
+#, c-format
+msgid "bad %s format: %%%.*s"
+msgstr "format %s jelek: %%%.*s"
+
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#: strbuf.c
#, c-format
@@ -26531,35 +26763,6 @@ msgstr "nilai tidak dikenal '%s' untuk kunci '%s'"
msgid "empty trailer token in trailer '%.*s'"
msgstr "token trailer kosong dalam trailer '%.*s'"
-#: trailer.c
-#, c-format
-msgid "could not read input file '%s'"
-msgstr "tidak dapat membaca berkas masukan '%s'"
-
-#: trailer.c wrapper.c
-#, c-format
-msgid "could not stat %s"
-msgstr "tidak dapat membaca %s"
-
-#: trailer.c
-#, c-format
-msgid "file %s is not a regular file"
-msgstr "berkas %s bukan sebuah berkas reguler"
-
-#: trailer.c
-#, c-format
-msgid "file %s is not writable by user"
-msgstr "berkas %s tidak dapat ditulis oleh pengguna"
-
-#: trailer.c
-msgid "could not open temporary file"
-msgstr "tidak dapat membuka berkas sementara"
-
-#: trailer.c
-#, c-format
-msgid "could not rename temporary file to %s"
-msgstr "tidak dapat menamai ulang berkas sementara ke %s"
-
#: transport-helper.c
msgid "full write to remote helper failed"
msgstr "gagal menulis penuh ke pembantu remote"
@@ -26681,8 +26884,8 @@ msgstr "pembantu tidak mendukung pendorongan; spek referensi diperlukan"
#: transport-helper.c
#, c-format
-msgid "helper %s does not support 'force'"
-msgstr "pembantu %s tidak mendukung 'force'"
+msgid "helper %s does not support '--force'"
+msgstr "pembantu %s tidak mendukung '--force'"
#: transport-helper.c
msgid "couldn't run fast-export"
@@ -27165,6 +27368,11 @@ msgid "invalid '..' path segment"
msgstr "segmen jalur '..' tidak valid"
#: usage.c
+#, c-format
+msgid "error: unable to format message: %s\n"
+msgstr "kesalahan: tidak dapat memformat pesan: %s\n"
+
+#: usage.c
msgid "usage: "
msgstr "penggunaan: "
diff --git a/po/sv.po b/po/sv.po
index 786c2f749e..ad1aad94ff 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -5,10 +5,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: git 2.44.0\n"
+"Project-Id-Version: git 2.45.0\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2024-02-16 07:58+0100\n"
-"PO-Revision-Date: 2024-02-16 07:59+0100\n"
+"POT-Creation-Date: 2024-04-27 15:19+0100\n"
+"PO-Revision-Date: 2024-04-27 15:20+0100\n"
"Last-Translator: Peter Krefting <peter@softwolves.pp.se>\n"
"Language-Team: Svenska <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
@@ -490,12 +490,12 @@ msgid ""
"---\n"
"To remove '%c' lines, make them ' ' lines (context).\n"
"To remove '%c' lines, delete them.\n"
-"Lines starting with %c will be removed.\n"
+"Lines starting with %s will be removed.\n"
msgstr ""
"---\n"
"Ta bort â€%c†rader genom att göra dem †â€-rader (sammanhang).\n"
"Ta bort â€%c†rader genom att radera dem.\n"
-"Rader som börjar med %c kommer att tas bort.\n"
+"Rader som börjar med %s kommer att tas bort.\n"
msgid ""
"If it does not apply cleanly, you will be given an opportunity to\n"
@@ -542,6 +542,7 @@ msgid ""
"/ - search for a hunk matching the given regex\n"
"s - split the current hunk into smaller hunks\n"
"e - manually edit the current hunk\n"
+"p - print the current hunk\n"
"? - print help\n"
msgstr ""
"j - lämna stycket obestämt, se nästa obestämda stycke\n"
@@ -552,6 +553,7 @@ msgstr ""
"/ - sök efter stycke som motsvarar angivet reguljärt uttryck\n"
"s - dela aktuellt stycke i mindre styckens\n"
"e - redigera aktuellt stycke manuellt\n"
+"p - visa aktuellt stycke\n"
"? - visa hjälp\n"
msgid "No previous hunk"
@@ -614,8 +616,8 @@ msgstr ""
"SlÃ¥ av meddelandet med â€git config advice.%s falseâ€"
#, c-format
-msgid "%shint: %.*s%s\n"
-msgstr "%stips: %.*s%s\n"
+msgid "%shint:%s%.*s%s\n"
+msgstr "%stips:%s%.*s%s\n"
msgid "Cherry-picking is not possible because you have unmerged files."
msgstr ""
@@ -889,11 +891,11 @@ msgstr "patch med bara skräp på rad %d"
#, c-format
msgid "unable to read symlink %s"
-msgstr "kunde inte läsa symboliska länken %s"
+msgstr "kan inte läsa symboliska länken %s"
#, c-format
msgid "unable to open or read %s"
-msgstr "kunde inte öppna eller läsa %s"
+msgstr "kan inte öppna eller läsa %s"
#, c-format
msgid "invalid start of line: '%c'"
@@ -1116,10 +1118,6 @@ msgstr[0] "Tillämpade patchen %%s med %d refuserad..."
msgstr[1] "Tillämpade patchen %%s med %d refuserade..."
#, c-format
-msgid "truncating .rej filename to %.*s.rej"
-msgstr "trunkerar .rej-filnamnet till %.*s.rej"
-
-#, c-format
msgid "cannot open %s"
msgstr "kan inte öppna %s"
@@ -1168,7 +1166,7 @@ msgstr[0] "%d rad applicerade efter att ha rättat fel i blanksteg."
msgstr[1] "%d rader applicerade efter att ha rättat fel i blanksteg."
msgid "Unable to write new index file"
-msgstr "Kunde inte skriva ny indexfil"
+msgstr "Kan inte skriva ny indexfil"
msgid "don't apply changes matching the given path"
msgstr "tillämpa inte ändringar som motsvarar given sökväg"
@@ -1276,7 +1274,7 @@ msgstr "fel i deflate (%d)"
#, c-format
msgid "unable to start '%s' filter"
-msgstr "kunde inte starta filtret â€%sâ€"
+msgstr "kane inte starta filtret â€%sâ€"
msgid "unable to redirect descriptor"
msgstr "kan inte omdirigera handtag"
@@ -1434,7 +1432,7 @@ msgid "%.*s is not a valid attribute name"
msgstr "%-*s är inte ett giltigt namn på attribut"
msgid "unable to add additional attribute"
-msgstr "Kunde inte lägga till ytterligare attribut"
+msgstr "kan inte lägga till ytterligare attribut"
#, c-format
msgid "ignoring overly long attributes line %d"
@@ -1472,7 +1470,7 @@ msgstr "kan inte ta status pÃ¥ â€%sâ€"
#, c-format
msgid "unable to read %s"
-msgstr "kunde inte läsa %s"
+msgstr "kan inte läsa %s"
#, c-format
msgid "Badly quoted content in file '%s': %s"
@@ -1544,6 +1542,10 @@ msgid "could not create file '%s'"
msgstr "kunde inte skapa filen â€%sâ€"
#, c-format
+msgid "unable to start 'show' for object '%s'"
+msgstr "kan inte starta â€show†för objektet â€%sâ€"
+
+#, c-format
msgid "could not read file '%s'"
msgstr "kunde inte läsa filen â€%sâ€"
@@ -1693,6 +1695,9 @@ msgstr ""
msgid "'%s' is not a valid branch name"
msgstr "â€%s†är inte ett giltigt grennamn"
+msgid "See `man git check-ref-format`"
+msgstr "Se â€man git check-ref-formatâ€"
+
#, c-format
msgid "a branch named '%s' already exists"
msgstr "det finns redan en gren som heter â€%sâ€"
@@ -1885,14 +1890,8 @@ msgstr ""
msgid "adding embedded git repository: %s"
msgstr "lägger till inbäddat git-arkiv: %s"
-msgid ""
-"Use -f if you really want to add them.\n"
-"Turn this message off by running\n"
-"\"git config advice.addIgnoredFile false\""
-msgstr ""
-"Använd -f om du verkligen vill lägga till dem.\n"
-"Slå av detta meddelande med\n"
-"â€git config advice.addIgnoredFile falseâ€"
+msgid "Use -f if you really want to add them."
+msgstr "Använd -f om du verkligen vill lägga till dem."
msgid "adding files failed"
msgstr "misslyckades lägga till filer"
@@ -1909,20 +1908,14 @@ msgstr "â€%s†kan inte användas tillsammans med sökvägsangivelser"
msgid "Nothing specified, nothing added.\n"
msgstr "Inget angivet, inget tillagt.\n"
-msgid ""
-"Maybe you wanted to say 'git add .'?\n"
-"Turn this message off by running\n"
-"\"git config advice.addEmptyPathspec false\""
-msgstr ""
-"Tänkte du kanske säga â€git add .â€?\n"
-"Slå av detta meddelande genom att köra\n"
-"â€git config advice.addEmptyPathspec falseâ€"
+msgid "Maybe you wanted to say 'git add .'?"
+msgstr "Tänkte du kanske säga â€git add .â€?"
msgid "index file corrupt"
msgstr "indexfilen trasig"
msgid "unable to write new index file"
-msgstr "kunde inte skriva ny indexfil"
+msgstr "kan inte skriva ny indexfil"
#, c-format
msgid "bad action '%s' for '%s'"
@@ -1993,18 +1986,19 @@ msgid "Failed to split patches."
msgstr "Misslyckades dela patchar."
#, c-format
-msgid "When you have resolved this problem, run \"%s --continue\"."
-msgstr "När du har löst problemet, kör â€%s --continueâ€."
+msgid "When you have resolved this problem, run \"%s --continue\".\n"
+msgstr "När du har löst problemet, kör â€%s --continueâ€.\n"
#, c-format
-msgid "If you prefer to skip this patch, run \"%s --skip\" instead."
-msgstr "Om du hellre vill hoppa över patchen, kör â€%s --skip†i stället."
+msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n"
+msgstr "Om du hellre vill hoppa över patchen, kör â€%s --skip†i stället.\n"
#, c-format
-msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"."
+msgid ""
+"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"
msgstr ""
"För att registrera den tomma patchen som en tom incheckning, kör â€%s --allow-"
-"emptyâ€."
+"emptyâ€.\n"
#, c-format
msgid "To restore the original branch and stop patching, run \"%s --abort\"."
@@ -2025,7 +2019,7 @@ msgstr "ogiltig ident-rad: %.*s"
#, c-format
msgid "unable to parse commit %s"
-msgstr "kunde inte tolka incheckningen %s"
+msgstr "kan inte tolka incheckningen %s"
msgid "Repository lacks necessary blobs to fall back on 3-way merge."
msgstr ""
@@ -2056,7 +2050,7 @@ msgid "applying to an empty history"
msgstr "tillämpar på en tom historik"
msgid "failed to write commit object"
-msgstr "kunde inte skriva incheckningsobjekt"
+msgstr "misslyckades skriva incheckningsobjekt"
#, c-format
msgid "cannot resume: %s does not exist."
@@ -2357,7 +2351,7 @@ msgstr "â€%s†är inte en giltig incheckning"
msgid ""
"could not check out original HEAD '%s'. Try 'git bisect reset <commit>'."
msgstr ""
-"Kunde inte checka ut original-HEAD â€%sâ€. Försök â€git bisect reset "
+"kan inte checka ut original-HEAD â€%sâ€. Försök â€git bisect reset "
"<incheckning>â€."
#, c-format
@@ -2849,11 +2843,11 @@ msgstr "grenen kopierades, men misslyckades uppdatera konfigurationsfilen"
msgid ""
"Please edit the description for the branch\n"
" %s\n"
-"Lines starting with '%c' will be stripped.\n"
+"Lines starting with '%s' will be stripped.\n"
msgstr ""
"Redigera beskrivningen för grenen\n"
" %s\n"
-"Rader som inleds med â€%c†ignoreras.\n"
+"Rader som inleds med â€%s†ignoreras.\n"
msgid "Generic options"
msgstr "Allmänna flaggor"
@@ -3052,11 +3046,13 @@ msgid "not run from a git repository - no hooks to show\n"
msgstr "körs inte från ett git-arkiv - inga krokar att visa\n"
msgid ""
-"git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"git bugreport [(-o | --output-directory) <path>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
" [--diagnose[=<mode>]]"
msgstr ""
-"git bugreport [(-o | --output-directory) <fil>] [(-s | --suffix) <format>]\n"
-" [--diagnose[=<läge>]"
+"git bugreport [(-o | --output-directory) <sökväg>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
+" [--diagnose[=<läge>]]"
msgid ""
"Thank you for filling out a Git bug report!\n"
@@ -3117,7 +3113,7 @@ msgstr "kunde inte skapa inledande kataloger för â€%sâ€"
#, c-format
msgid "unable to create diagnostics archive %s"
-msgstr "kunde inte skapa diagnostikarkiven %s"
+msgstr "kan inte skapa diagnostikarkiven %s"
msgid "System Info"
msgstr "Systeminfo"
@@ -3127,7 +3123,7 @@ msgstr "Aktiverade krokar"
#, c-format
msgid "unable to write to %s"
-msgstr "kunde inte skriva till %s"
+msgstr "kan inte skriva till %s"
#, c-format
msgid "Created new report at '%s'.\n"
@@ -3407,7 +3403,7 @@ msgstr "läs även kontakter från standard in"
#, c-format
msgid "unable to parse contact: %s"
-msgstr "kunde inte tolka kontakt: %s"
+msgstr "kan inte tolka kontakt: %s"
msgid "no contacts specified"
msgstr "inga kontakter angavs"
@@ -3488,7 +3484,7 @@ msgstr "sökväg â€%sâ€: kan inte slÃ¥ ihop"
#, c-format
msgid "Unable to add merge result for '%s'"
-msgstr "Kunde inte lägga till sammanslagningsresultat för â€%sâ€"
+msgstr "Kan inte lägga till sammanslagningsresultat för â€%sâ€"
#, c-format
msgid "Recreated %d merge conflict"
@@ -3536,6 +3532,10 @@ msgstr "â€%sâ€, â€%s†eller â€%s†kan inte användas när en katalog che
msgid "path '%s' is unmerged"
msgstr "sökvägen â€%s†har inte slagits ihop"
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr "kan inte läsa träd (%s)"
+
msgid "you need to resolve your current index first"
msgstr "du måste lösa ditt befintliga index först"
@@ -3766,6 +3766,10 @@ msgstr "Kan inte växla gren till icke-incheckningen â€%sâ€"
msgid "missing branch or commit argument"
msgstr "saknar gren- eller incheckingsargument"
+#, c-format
+msgid "unknown conflict style '%s'"
+msgstr "okänd konflikttyp â€%sâ€"
+
msgid "perform a 3-way merge with the new branch"
msgstr "utför en 3-vägssammanslagning för den nya grenen"
@@ -4021,19 +4025,8 @@ msgstr "ta även bort ignorerade filer"
msgid "remove only ignored files"
msgstr "ta endast bort ignorerade filer"
-msgid ""
-"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to "
-"clean"
-msgstr ""
-"clean.requireForce satt till true, men varken -i, -n eller -f angavs; vägrar "
-"städa"
-
-msgid ""
-"clean.requireForce defaults to true and neither -i, -n, nor -f given; "
-"refusing to clean"
-msgstr ""
-"clean.requireForce har standardvärdet true och varken -i, -n eller -f "
-"angavs; vägrar städa"
+msgid "clean.requireForce is true and -f not given: refusing to clean"
+msgstr "clean.requireForce är true och -f angavs inte: vägrar städa"
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<flaggor>] [--] <arkiv> [<kat>]"
@@ -4047,8 +4040,8 @@ msgstr "skapa inte någon utcheckning"
msgid "create a bare repository"
msgstr "skapa ett naket (â€bareâ€) arkiv"
-msgid "create a mirror repository (implies bare)"
-msgstr "skapa ett spegelarkiv (implicerar â€bareâ€)"
+msgid "create a mirror repository (implies --bare)"
+msgstr "skapa ett spegelarkiv (implicerar --bare)"
msgid "to clone from a local repository"
msgstr "för att klona från ett lokalt arkiv"
@@ -4223,10 +4216,10 @@ msgid "remote HEAD refers to nonexistent ref, unable to checkout"
msgstr "HEAD hos fjärren pekar på en obefintlig referens, kan inte checka ut"
msgid "unable to checkout working tree"
-msgstr "kunde inte checka ut arbetskatalogen"
+msgstr "kan inte checka ut arbetskatalogen"
msgid "unable to write parameters to config file"
-msgstr "kunde inte skriva parametrar till konfigurationsfilen"
+msgstr "kan inte skriva parametrar till konfigurationsfilen"
msgid "cannot repack to clean up"
msgstr "kan inte packa om för att städa upp"
@@ -4356,6 +4349,10 @@ msgstr "spaltfyllnad i högerkanten"
msgid "padding space between columns"
msgstr "spaltfyllnad mellan spalter"
+#, c-format
+msgid "%s must be non-negative"
+msgstr "%s måste vara icke-negativt"
+
msgid "--command must be the first argument"
msgstr "--command måste vara första argument"
@@ -4584,7 +4581,7 @@ msgid "No paths with --include/--only does not make sense."
msgstr "Du måste ange sökvägar tillsammans med --include/--only."
msgid "unable to create temporary index"
-msgstr "kunde inte skapa temporär indexfil"
+msgstr "kan inte skapa temporär indexfil"
msgid "interactive add failed"
msgstr "interaktiv tilläggning misslyckades"
@@ -4608,7 +4605,7 @@ msgid "cannot read the index"
msgstr "kan inte läsa indexet"
msgid "unable to write temporary index file"
-msgstr "kunde inte skriva temporär indexfil"
+msgstr "kan inte skriva temporär indexfil"
#, c-format
msgid "commit '%s' lacks author header"
@@ -4629,7 +4626,7 @@ msgid ""
"unable to select a comment character that is not used\n"
"in the current commit message"
msgstr ""
-"kunde inte välja ett kommentarstecken som inte använts\n"
+"kan inte välja ett kommentarstecken som inte använts\n"
"i det befintliga incheckningsmeddelandet"
#, c-format
@@ -4667,35 +4664,35 @@ msgstr "kunde inte skriva incheckningsmall"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored.\n"
+"with '%s' will be ignored.\n"
msgstr ""
"Ange incheckningsmeddelandet för dina ändringar. Rader som inleds\n"
-"med â€%c†kommer ignoreras.\n"
+"med â€%s†kommer ignoreras.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored, and an empty message aborts the commit.\n"
+"with '%s' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
"Ange incheckningsmeddelandet för dina ändringar. Rader som inleds\n"
-"med â€%c†kommer ignoreras, och ett tomt meddelande avbryter incheckningen.\n"
+"med â€%s†kommer ignoreras, och ett tomt meddelande avbryter incheckningen.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
msgstr ""
"Ange incheckningsmeddelandet för dina ändringar. Rader som inleds\n"
-"med â€%c†kommer behÃ¥llas; du kan själv ta bort dem om du vill.\n"
+"med â€%s†kommer behÃ¥llas; du kan själv ta bort dem om du vill.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
"Ange incheckningsmeddelandet för dina ändringar. Rader som inleds\n"
-"med â€%c†kommer behÃ¥llas; du kan själv ta bort dem om du vill.\n"
+"med â€%s†kommer behÃ¥llas; du kan själv ta bort dem om du vill.\n"
"Ett tomt meddelande avbryter incheckningen.\n"
msgid ""
@@ -5134,6 +5131,9 @@ msgstr "värde"
msgid "with --get, use default value when missing entry"
msgstr "med --get, använd standardvärde vid saknad post"
+msgid "human-readable comment string (# will be prepended as needed)"
+msgstr "människoläsbar kommentarssträng (# läggs in först efter behov)"
+
#, c-format
msgid "wrong number of arguments, should be %d"
msgstr "fel antal argument, skulle vara %d"
@@ -5226,6 +5226,9 @@ msgstr ""
msgid "--default is only applicable to --get"
msgstr "--default gäller bara för --get"
+msgid "--comment is only applicable to add/set/replace operations"
+msgstr "--comment gäller bara för â€getâ€/â€setâ€/â€replaceâ€-operationerna"
+
msgid "--fixed-value only applies with 'value-pattern'"
msgstr "--fixed-value gäller endast med â€värde-mönsterâ€"
@@ -5284,7 +5287,7 @@ msgstr "â€credential-cache†ej tillgänglig; stöd för unix-uttag saknas"
#, c-format
msgid "unable to get credential storage lock in %d ms"
-msgstr "kunde inte erhålla låset för lagring av inlogginsuppgifter på %d ms"
+msgstr "kan inte erhålla låset för lagring av inlogginsuppgifter på %d ms"
msgid ""
"git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]"
@@ -5693,7 +5696,7 @@ msgid "[tag update]"
msgstr "[uppdaterad tagg]"
msgid "unable to update local ref"
-msgstr "kunde inte uppdatera lokal ref"
+msgstr "kan inte uppdatera lokal ref"
msgid "would clobber existing tag"
msgstr "skulle skriva över befintlig tagg"
@@ -6061,6 +6064,9 @@ msgstr "visa endast referenser som inte innehåller incheckningen"
msgid "read reference patterns from stdin"
msgstr "läs referensmönster från standard in"
+msgid "also include HEAD ref and pseudorefs"
+msgstr "ta också med HEAD- och pseudo-referenser"
+
msgid "unknown arguments supplied with --stdin"
msgstr "okända argument angavs tillsammans med --stdin"
@@ -6247,7 +6253,7 @@ msgstr "%s: ogiltig sha1-pekare i resolve-undo för %s"
#, c-format
msgid "unable to load rev-index for pack '%s'"
-msgstr "kunde inte läsa rev-index för paketfil â€%sâ€"
+msgstr "kan inte läsa rev-index för paketfil â€%sâ€"
#, c-format
msgid "invalid rev-index for pack '%s'"
@@ -6456,11 +6462,11 @@ msgstr "packa om alla paket förutom det största paketet"
#, c-format
msgid "failed to parse gc.logExpiry value %s"
-msgstr "kunde inte tolka värdet %s för gc.logExpiry"
+msgstr "misslyckades tolka värdet %s för gc.logExpiry"
#, c-format
msgid "failed to parse prune expiry value %s"
-msgstr "kunde inte tolka värdet %s för prune expiry"
+msgstr "misslyckades tolka värdet %s för prune expiry"
#, c-format
msgid "Auto packing the repository in background for optimum performance.\n"
@@ -6499,19 +6505,19 @@ msgid "unrecognized --schedule argument '%s'"
msgstr "okänt argument för --schedule, %s"
msgid "failed to write commit-graph"
-msgstr "kunde inte skriva incheckningsgraf"
+msgstr "misslyckades skriva incheckningsgraf"
msgid "failed to prefetch remotes"
-msgstr "kunde inte förhämta fjärrar"
+msgstr "misslyckades förhämta fjärrar"
msgid "failed to start 'git pack-objects' process"
-msgstr "kunde inte starta â€git pack-objectsâ€-process"
+msgstr "misslyckades starta â€git pack-objectsâ€-process"
msgid "failed to finish 'git pack-objects' process"
-msgstr "kunde inte avsluta â€git pack-objectsâ€-process"
+msgstr "misslyckades att avsluta â€git pack-objectsâ€-process"
msgid "failed to write multi-pack-index"
-msgstr "kunde inte skriva multi-pack-index"
+msgstr "misslyckades skriva multi-pack-index"
msgid "'git multi-pack-index expire' failed"
msgstr "â€git multi-pack-index expire†misslyckades"
@@ -6680,16 +6686,12 @@ msgid "no threads support, ignoring %s"
msgstr "trådstöd saknas, ignorerar %s"
#, c-format
-msgid "unable to read tree (%s)"
-msgstr "kunde inte läsa träd (%s)"
-
-#, c-format
msgid "unable to read tree %s"
-msgstr "kunde inte läsa trädet %s"
+msgstr "kan inte läsa trädet %s"
#, c-format
msgid "unable to grep from object of type %s"
-msgstr "kunde inte â€grep†frÃ¥n objekt av typen %s"
+msgstr "kan inte â€grep†frÃ¥n objekt av typen %s"
#, c-format
msgid "switch `%c' expects a numerical value"
@@ -6945,7 +6947,7 @@ msgid "Failed to start emacsclient."
msgstr "Misslyckades starta emacsclient."
msgid "Failed to parse emacsclient version."
-msgstr "Kunde inte tolka emacsclient-version."
+msgstr "Misslyckades tolka emacsclient-version."
#, c-format
msgid "emacsclient version '%d' too old (< 22)."
@@ -6953,7 +6955,7 @@ msgstr "emacsclient version â€%d†för gammal (< 22)."
#, c-format
msgid "failed to exec '%s'"
-msgstr "exec misslyckades för â€%sâ€"
+msgstr "â€exec†misslyckades för â€%sâ€"
#, c-format
msgid ""
@@ -7138,7 +7140,7 @@ msgstr "Analyserar delta"
#, c-format
msgid "unable to create thread: %s"
-msgstr "kunde inte skapa tråd: %s"
+msgstr "kan inte skapa tråd: %s"
msgid "confusion beyond insanity"
msgstr "förvirrad bortom vanvett"
@@ -7161,7 +7163,7 @@ msgstr[1] "paketet har %d oanalyserade delta"
#, c-format
msgid "unable to deflate appended object (%d)"
-msgstr "kunde inte utföra â€deflate†pÃ¥ tillagt objekt (%d)"
+msgstr "kan inte utföra â€deflate†pÃ¥ tillagt objekt (%d)"
#, c-format
msgid "local object %s is corrupt"
@@ -7181,7 +7183,7 @@ msgstr "kan inte stänga skriven %s-fil â€%sâ€"
#, c-format
msgid "unable to rename temporary '*.%s' file to '%s'"
-msgstr "kunde inte byta namn pÃ¥ temporär â€*.%sâ€-fil till â€%sâ€"
+msgstr "kan inte byta namn pÃ¥ temporär â€*.%sâ€-fil till â€%sâ€"
msgid "error while closing pack file"
msgstr "fel vid stängning av paketfil"
@@ -7283,14 +7285,40 @@ msgstr "--separate-git-dir är inkompatibelt med naket arkiv"
msgid ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n"
+" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
" [--parse] [<file>...]"
msgstr ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<nyckel>|<nyckelAlias>)"
+" [(--trailer (<nyckel>|<nyckel-alias>)"
"[(=|:)<värde>])...]\n"
" [--parse] [<fil>...]"
+#, c-format
+msgid "could not stat %s"
+msgstr "kunde inte ta status på %s"
+
+#, c-format
+msgid "file %s is not a regular file"
+msgstr "filen %s är inte en normal fil"
+
+#, c-format
+msgid "file %s is not writable by user"
+msgstr "filen %s är inte skrivbar av användaren"
+
+msgid "could not open temporary file"
+msgstr "kunde inte öppna temporär fil"
+
+#, c-format
+msgid "could not read input file '%s'"
+msgstr "kunde inte läsa indatafilen â€%sâ€"
+
+msgid "could not read from stdin"
+msgstr "kunde inte läsa från standard in"
+
+#, c-format
+msgid "could not rename temporary file to %s"
+msgstr "kunde inte byta namn på temporär fil till %s"
+
msgid "edit files in place"
msgstr "redigera filer på plats"
@@ -7380,7 +7408,7 @@ msgid "Final output: %d %s\n"
msgstr "Slututdata: %d %s\n"
msgid "unable to create temporary object directory"
-msgstr "kunde inte skapa temporär objektkatalog"
+msgstr "kan inte skapa temporär objektkatalog"
#, c-format
msgid "git show %s: bad file"
@@ -7447,12 +7475,12 @@ msgid ""
"please use git branch --set-upstream-to to track a remote branch.\n"
"Or you could specify base commit by --base=<base-commit-id> manually"
msgstr ""
-"kunde inte hämta uppström, om du vill lagra basincheckningen automatiskt,\n"
+"misslyckades hämta uppström, om du vill lagra basincheckningen automatiskt,\n"
"använd git branch --set-upstream-to för att spåra en fjärrgren.\n"
"Eller så kan du ange basincheckning med --base=<bas-inchecknings-id> manuellt"
msgid "failed to find exact merge base"
-msgstr "kunde inte hitta exakt sammanslagningsbas"
+msgstr "misslyckades hitta exakt sammanslagningsbas"
msgid "base commit should be the ancestor of revision list"
msgstr "basincheckningen bör vara förfader till revisionslistan"
@@ -7653,7 +7681,7 @@ msgstr "Intervall-diff mot v%d:"
#, c-format
msgid "unable to read signature file '%s'"
-msgstr "kunde inte läsa signaturfil â€%sâ€"
+msgstr "kan inte läsa signaturfil â€%sâ€"
msgid "Generating patches"
msgstr "Skapar patchar"
@@ -7673,18 +7701,6 @@ msgstr "Kunde inte hitta en spårad fjärrgren, ange <uppström> manuellt.\n"
msgid "could not get object info about '%s'"
msgstr "kunde inte hämta objektinfo om â€%sâ€"
-#, c-format
-msgid "bad ls-files format: element '%s' does not start with '('"
-msgstr "felaktigt ls-files-format: elementet â€%s†börjar inte med â€(â€"
-
-#, c-format
-msgid "bad ls-files format: element '%s' does not end in ')'"
-msgstr "felaktigt ls-files-format: elementet â€%s†slutar inte med â€)â€"
-
-#, c-format
-msgid "bad ls-files format: %%%.*s"
-msgstr "felaktigt ls-files-format: %%%.*s"
-
msgid "git ls-files [<options>] [<file>...]"
msgstr "git ls-files [<flaggor>] [<fil>...]"
@@ -7815,18 +7831,6 @@ msgstr "visa underliggande referens och objektet det pekar på"
msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
msgstr "git ls-tree [<flaggor>] <träd-igt> [<sökväg>...]"
-#, c-format
-msgid "bad ls-tree format: element '%s' does not start with '('"
-msgstr "felaktigt ls-tree-format: elementet â€%s†börjar inte med â€(â€"
-
-#, c-format
-msgid "bad ls-tree format: element '%s' does not end in ')'"
-msgstr "felaktigt ls-tree-format: elementet â€%s†slutar inte med â€)â€"
-
-#, c-format
-msgid "bad ls-tree format: %%%.*s"
-msgstr "felaktigt ls-tree-format: %%%.*s"
-
msgid "only show trees"
msgstr "visa endast träd"
@@ -8012,6 +8016,10 @@ msgstr "kunde inte bestämma referensen â€%sâ€"
msgid "Merging %s with %s\n"
msgstr "Slår ihop %s med %s\n"
+#, c-format
+msgid "could not parse as tree '%s'"
+msgstr "kunde inte tolka som träd â€%sâ€"
+
msgid "not something we can merge"
msgstr "inte något vi kan slå ihop"
@@ -8182,14 +8190,14 @@ msgid "Bad branch.%s.mergeoptions string: %s"
msgstr "Felaktig branch.%s.mergeoptions-sträng: %s"
msgid "Unable to write index."
-msgstr "Kunde inte skriva indexet."
+msgstr "Kan inte skriva indexet."
msgid "Not handling anything other than two heads merge."
msgstr "Hanterar inte något annat än en sammanslagning av två huvuden."
#, c-format
msgid "unable to write %s"
-msgstr "kunde inte skriva %s"
+msgstr "kan inte skriva %s"
#, c-format
msgid "Could not read from '%s'"
@@ -8215,10 +8223,10 @@ msgstr "Ett tomt meddelande avbryter incheckningen.\n"
#, c-format
msgid ""
-"Lines starting with '%c' will be ignored, and an empty message aborts\n"
+"Lines starting with '%s' will be ignored, and an empty message aborts\n"
"the commit.\n"
msgstr ""
-"Rader som inleds med â€%c†kommer ignoreras, och ett tomt meddelande\n"
+"Rader som inleds med â€%s†kommer ignoreras, och ett tomt meddelande\n"
"avbryter incheckningen.\n"
msgid "Empty commit message."
@@ -8376,9 +8384,6 @@ msgstr "kunde inte läsa det taggade objektet â€%sâ€"
msgid "object '%s' tagged as '%s', but is a '%s' type"
msgstr "objektet â€%s†taggat som â€%sâ€, men är av typen â€%sâ€"
-msgid "could not read from stdin"
-msgstr "kunde inte läsa från standard in"
-
msgid "tag on stdin did not pass our strict fsck check"
msgstr "tagg på stdin godkänns inte av vår strikta fsck-kontroll"
@@ -8386,7 +8391,7 @@ msgid "tag on stdin did not refer to a valid object"
msgstr "taggen på stdin pekar inte på ett giltigt objekt"
msgid "unable to write tag file"
-msgstr "kunde inte skriva tagg-filen"
+msgstr "kan inte skriva tagg-filen"
msgid "input is NUL terminated"
msgstr "indata är NUL-terminerad"
@@ -8640,22 +8645,18 @@ msgstr "git notes prune [<flaggor>]"
msgid "Write/edit the notes for the following object:"
msgstr "Skriv/redigera anteckningar för följande objekt:"
-#, c-format
-msgid "unable to start 'show' for object '%s'"
-msgstr "kunde inte starta â€show†för objektet â€%sâ€"
-
msgid "could not read 'show' output"
-msgstr "kunde inte läsa utdata frÃ¥n â€showâ€"
+msgstr "kan inte läsa utdata frÃ¥n â€showâ€"
#, c-format
msgid "failed to finish 'show' for object '%s'"
-msgstr "kunde inte avsluta â€show†för objektet â€%sâ€"
+msgstr "misslyckades att avsluta â€show†för objektet â€%sâ€"
msgid "please supply the note contents using either -m or -F option"
msgstr "ange innehåll för anteckningen med antingen -m eller -F"
msgid "unable to write note object"
-msgstr "kunde inte skriva anteckningsobjekt"
+msgstr "kan inte skriva anteckningsobjekt"
#, c-format
msgid "the note contents have been left in %s"
@@ -8667,11 +8668,11 @@ msgstr "kunde inte öppna eller läsa â€%sâ€"
#, c-format
msgid "failed to resolve '%s' as a valid ref."
-msgstr "kunde inte slÃ¥ upp â€%s†som en giltig referens."
+msgstr "misslyckades slÃ¥ upp â€%s†som en giltig referens."
#, c-format
msgid "failed to read object '%s'."
-msgstr "kunde inte läsa objektet â€%sâ€."
+msgstr "misslyckades läsa objektet â€%sâ€."
#, c-format
msgid "cannot read note data from non-blob object '%s'."
@@ -8849,7 +8850,7 @@ msgstr ""
#, c-format
msgid "Failed to resolve '%s' as a valid ref."
-msgstr "Kunde inte slÃ¥ upp â€%s†som en giltig referens."
+msgstr "Misslyckades slÃ¥ upp â€%s†som en giltig referens."
#, c-format
msgid "Object %s has no note\n"
@@ -8955,7 +8956,7 @@ msgstr "kan inte hämta storlek på %s"
#, c-format
msgid "unable to parse object header of %s"
-msgstr "kunde inte tolka objekthuvud för %s"
+msgstr "kan inte tolka objekthuvud för %s"
#, c-format
msgid "object %s cannot be read"
@@ -8978,7 +8979,7 @@ msgstr "kan inte packa objekt nåbara från taggen %s"
#, c-format
msgid "unable to get type of object %s"
-msgstr "kunde inte hämta typ för objektet %s"
+msgstr "kan inte hämta typ för objektet %s"
msgid "Compressing objects"
msgstr "Komprimerar objekt"
@@ -9265,10 +9266,10 @@ msgid "refusing to run without --i-still-use-this"
msgstr "vägrar köra utan --i-still-use-this"
msgid ""
-"git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude "
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
"<pattern>]"
msgstr ""
-"git pack-refs [--all] [--no-prune] [--include <mönster>] [--exclude "
+"git pack-refs [--all] [--no-prune] [--auto] [--include <mönster>] [--exclude "
"<mönster>]"
msgid "pack everything"
@@ -9277,6 +9278,9 @@ msgstr "packa allt"
msgid "prune loose refs (default)"
msgstr "ta bort lösa referenser (standard)"
+msgid "auto-pack refs as needed"
+msgstr "packa referenser automatiskt om nödvändigt"
+
msgid "references to include"
msgstr "referenser att ta med"
@@ -9411,7 +9415,7 @@ msgstr ""
#, c-format
msgid "unable to access commit %s"
-msgstr "kunde inte komma åt incheckningen %s"
+msgstr "kan inte komma åt incheckningen %s"
msgid "ignoring --verify-signatures for rebase"
msgstr "ignorera --verify-signatures för ombasering"
@@ -9902,7 +9906,7 @@ msgid "could not mark as interactive"
msgstr "kunde inte markera som interaktiv"
msgid "could not generate todo list"
-msgstr "Kunde inte skapa attgöra-lista"
+msgstr "kunde inte skapa attgöra-lista"
msgid "a base commit must be provided with --upstream or --onto"
msgstr "en basincheckning måste anges med --upstream eller --onto"
@@ -9927,19 +9931,6 @@ msgstr "ignorera ogiltigt allow_rerere_autoupdate: â€%sâ€"
msgid "could not remove '%s'"
msgstr "kunde inte ta bort â€%sâ€"
-msgid ""
-"Resolve all conflicts manually, mark them as resolved with\n"
-"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
-"You can instead skip this commit: run \"git rebase --skip\".\n"
-"To abort and get back to the state before \"git rebase\", run \"git rebase --"
-"abort\"."
-msgstr ""
-"Lös alla konflikter manuellt, märk dem som lösta med\n"
-"â€git add/rm <filer_i_konflikt>â€, kör sedan â€git rebase --continueâ€.\n"
-"Du kan hoppa över incheckningen istället: kör â€git rebase --skipâ€.\n"
-"För att avbryta och Ã¥tergÃ¥ till där du var före ombaseringen, kör â€git "
-"rebase --abortâ€."
-
#, c-format
msgid ""
"\n"
@@ -9970,11 +9961,14 @@ msgid "apply options and merge options cannot be used together"
msgstr ""
"appliceringsflaggor och sammanslagningsflaggor kan inte användas tillsammans"
+msgid "--empty=ask is deprecated; use '--empty=stop' instead."
+msgstr "--empty=ask rekommenderas inte; använd â€--empty=stop†istället."
+
#, c-format
msgid ""
"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
-"\"ask\"."
-msgstr "okänd tom-typ â€%sâ€; giltiga värden är â€dropâ€, â€keep†och â€askâ€."
+"\"stop\"."
+msgstr "okänd tom-typ â€%sâ€; giltiga värden är â€dropâ€, â€keep†och â€stopâ€."
msgid ""
"--rebase-merges with an empty string argument is deprecated and will stop "
@@ -10153,8 +10147,8 @@ msgstr ""
"Observera: Din inställning för â€pull.rebase†kan ocksÃ¥ vara satt till\n"
"â€preserveâ€, som inte längre stöds; använd â€merges†istället"
-msgid "No rebase in progress?"
-msgstr "Ingen ombasering pågår?"
+msgid "no rebase in progress"
+msgstr "ingen ombasering pågår"
msgid "The --edit-todo action can only be used during interactive rebase."
msgstr "Åtgärden --edit-todo kan endast användas under interaktiv ombasering."
@@ -10348,6 +10342,9 @@ msgstr "du måste ange en katalog"
msgid "git reflog [show] [<log-options>] [<ref>]"
msgstr "git reflog [show] [<log-flaggor>] [<ref>]"
+msgid "git reflog list"
+msgstr "git reflog list"
+
msgid ""
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
" [--rewrite] [--updateref] [--stale-fix]\n"
@@ -10373,6 +10370,10 @@ msgstr "git reflog exists <referens>"
msgid "invalid timestamp '%s' given to '--%s'"
msgstr "ogiltig tidsstämpel â€%s†given i â€--%sâ€"
+#, c-format
+msgid "%s does not accept arguments: '%s'"
+msgstr "%s tar inte argument: â€%sâ€"
+
msgid "do not actually prune any entries"
msgstr "rensa faktiskt inte några poster"
@@ -10498,8 +10499,8 @@ msgstr ""
"\t --mirror=fetch eller --mirror=push istället"
#, c-format
-msgid "unknown mirror argument: %s"
-msgstr "okänt argument till mirror: %s"
+msgid "unknown --mirror argument: %s"
+msgstr "okänt argument till --mirror: %s"
msgid "fetch the remote branches"
msgstr "hämta fjärrgrenarna"
@@ -10862,6 +10863,9 @@ msgstr ""
msgid "could not start pack-objects to repack promisor objects"
msgstr "kunde inte starta pack-objects för att packa om kontraktsobjekt"
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "misslyckades sända kontraktsobjekt till pack-objects"
+
msgid "repack: Expecting full hex object ID lines only from pack-objects."
msgstr ""
"repack: Förväntar kompletta hex-objekt-id-rader endast från pack-objects."
@@ -11267,7 +11271,7 @@ msgstr "â€git rerere forget†utan sökvägar är förÃ¥ldrat"
#, c-format
msgid "unable to generate diff for '%s'"
-msgstr "misslyckades skapa diff för â€%sâ€"
+msgstr "kan inte skapa diff för â€%sâ€"
msgid ""
"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"
@@ -11304,11 +11308,11 @@ msgid "You do not have a valid HEAD."
msgstr "Du har inte en giltig HEAD."
msgid "Failed to find tree of HEAD."
-msgstr "Kunde inte hitta trädet för HEAD."
+msgstr "Misslyckades hitta trädet för HEAD."
#, c-format
msgid "Failed to find tree of %s."
-msgstr "Kunde inte hitta trädet för %s."
+msgstr "Misslyckades hitta trädet för %s."
#, c-format
msgid "HEAD is now at %s"
@@ -11341,11 +11345,11 @@ msgstr "registrera endast att borttagna sökvägar kommer läggas till senare"
#, c-format
msgid "Failed to resolve '%s' as a valid revision."
-msgstr "Kunde inte slÃ¥ upp â€%s†som en giltig revision."
+msgstr "Misslyckades slÃ¥ upp â€%s†som en giltig revision."
#, c-format
msgid "Failed to resolve '%s' as a valid tree."
-msgstr "Kunde inte slÃ¥ upp â€%s†som ett giltigt träd."
+msgstr "Misslyckades slÃ¥ upp â€%s†som ett giltigt träd."
msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
msgstr ""
@@ -11456,6 +11460,13 @@ msgstr "--default kräver ett argument"
msgid "--prefix requires an argument"
msgstr "--prefix kräver ett argument"
+msgid "no object format specified"
+msgstr "inget objektformat angavs"
+
+#, c-format
+msgid "unsupported object format: %s"
+msgstr "objektformatet stöds ej: %s"
+
#, c-format
msgid "unknown mode for --abbrev-ref: %s"
msgstr "okänt läge för --abbrev-ref: %s"
@@ -11537,8 +11548,8 @@ msgstr "behåll incheckningar som börjar som tomma"
msgid "allow commits with empty messages"
msgstr "tillåt incheckningar med tomt meddelande"
-msgid "keep redundant, empty commits"
-msgstr "behåll redundanta, tomma incheckningar"
+msgid "deprecated: use --empty=keep instead"
+msgstr "avråds: använd --empty=keep istället"
msgid "use the 'reference' format to refer to commits"
msgstr "använd â€referensâ€-format för att referera till incheckningar"
@@ -11905,7 +11916,7 @@ msgstr "slå på/av använding av glest index"
#, c-format
msgid "unable to create leading directories of %s"
-msgstr "kunde inte skapa inledande kataloger för %s"
+msgstr "kan inte skapa inledande kataloger för %s"
#, c-format
msgid "failed to open '%s'"
@@ -11920,7 +11931,7 @@ msgid "unable to unquote C-style string '%s'"
msgstr "kan inte ta bort citering av C-sträng â€%sâ€"
msgid "unable to load existing sparse-checkout patterns"
-msgstr "kunde inte läsa in existerande mönster för gles utcheckning"
+msgstr "kan inte läsa in existerande mönster för gles utcheckning"
msgid "existing sparse-checkout patterns do not use cone mode"
msgstr "befintliga filter för gles utcheckning använder inte konläge"
@@ -12860,29 +12871,29 @@ msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be ignored.\n"
+"Lines starting with '%s' will be ignored.\n"
msgstr ""
"\n"
"Skriv ett meddelande för taggen:\n"
" %s\n"
-"Rader som inleds med â€%c†ignoreras.\n"
+"Rader som inleds med â€%s†ignoreras.\n"
#, c-format
msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be kept; you may remove them yourself if you "
+"Lines starting with '%s' will be kept; you may remove them yourself if you "
"want to.\n"
msgstr ""
"\n"
"Skriv ett meddelande för taggen:\n"
" %s\n"
-"Rader som inleds med â€%c†kommer behÃ¥llas; du kan själv ta bort dem om\n"
+"Rader som inleds med â€%s†kommer behÃ¥llas; du kan själv ta bort dem om\n"
"du vill.\n"
msgid "unable to sign the tag"
-msgstr "kunde inte signera taggen"
+msgstr "kan inte signera taggen"
#, c-format
msgid ""
@@ -12963,6 +12974,9 @@ msgstr "visa endast taggar som ej slagits samman"
msgid "print only tags of the object"
msgstr "visa endast taggar för objektet"
+msgid "could not start 'git column'"
+msgstr "kunde inte starta â€git columnâ€"
+
#, c-format
msgid "the '%s' option is only allowed in list mode"
msgstr "flaggan â€%s†är endast tillÃ¥ten i listläge"
@@ -13204,11 +13218,11 @@ msgstr ""
msgid "fsmonitor disabled"
msgstr "fsmonitor inaktiverat"
-msgid "git update-ref [<options>] -d <refname> [<old-val>]"
-msgstr "git update-ref [<flaggor>] -d <refnamn> [<gammaltvärde>]"
+msgid "git update-ref [<options>] -d <refname> [<old-oid>]"
+msgstr "git update-ref [<flaggor>] -d <refnamn> [<gammalt-oid>]"
-msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]"
-msgstr "git update-ref [<flaggor>] <refnamn> <gammaltvärde> [<nyttvärde>]"
+msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]"
+msgstr "git update-ref [<flaggor>] <refnamn> <gammalt-oid> [<nytt-oid>]"
msgid "git update-ref [<options>] --stdin [-z]"
msgstr "git update-ref [<flaggor>] --stdin [-z]"
@@ -13627,7 +13641,7 @@ msgstr "överskred buntens URI-rekursionsgräns (%d)"
#, c-format
msgid "failed to download bundle from URI '%s'"
-msgstr "kunde inte hämta bunt frÃ¥n URI:en â€%sâ€"
+msgstr "misslyckades hämta bunt frÃ¥n URI:en â€%sâ€"
#, c-format
msgid "file at URI '%s' is not a bundle or bundle list"
@@ -14454,7 +14468,7 @@ msgid "Finding extra edges in commit graph"
msgstr "Söker ytterligare kanter i incheckingsgraf"
msgid "failed to write correct number of base graph ids"
-msgstr "kunde inte skriva korrekt antal bas-graf-id:n"
+msgstr "misslyckades skriva korrekt antal bas-graf-id:n"
msgid "unable to create temporary graph layer"
msgstr "kan inte skapa temporärt graflager"
@@ -14470,13 +14484,13 @@ msgstr[0] "Skriver ut incheckningsgraf i %d pass"
msgstr[1] "Skriver ut incheckningsgraf i %d pass"
msgid "unable to open commit-graph chain file"
-msgstr "Kunde inte öppna incheckningsgrafkedjefilen"
+msgstr "kan inte öppna incheckningsgrafkedjefilen"
msgid "failed to rename base commit-graph file"
-msgstr "kunde inte byta namn på bas-incheckingsgraffilen"
+msgstr "misslyckades byta namn på bas-incheckingsgraffilen"
msgid "failed to rename temporary commit-graph file"
-msgstr "kunde inte byta namn på temporär incheckningsgraffil"
+msgstr "misslyckades byta namn på temporär incheckningsgraffil"
#, c-format
msgid "cannot merge graphs with %<PRIuMAX>, %<PRIuMAX> commits"
@@ -14515,12 +14529,12 @@ msgstr ""
#, c-format
msgid "failed to parse commit %s from commit-graph"
-msgstr "kunde inte tolka incheckning %s från incheckningsgraf"
+msgstr "misslyckades tolka incheckningen %s från incheckningsgraf"
#, c-format
msgid "failed to parse commit %s from object database for commit-graph"
msgstr ""
-"misslyckades tolka incheckning %s från objektdatabasen för incheckningsgraf"
+"misslyckades tolka incheckningen %s från objektdatabasen för incheckningsgraf"
#, c-format
msgid "root tree OID for commit %s in commit-graph is %s != %s"
@@ -14563,6 +14577,10 @@ msgid "Verifying commits in commit graph"
msgstr "Bekräftar incheckningar i incheckningsgrafen"
#, c-format
+msgid "could not parse commit %s"
+msgstr "kunde inte tolka incheckningen %s"
+
+#, c-format
msgid "%s %s is not a commit!"
msgstr "%s %s är inte en incheckning!"
@@ -14707,11 +14725,11 @@ msgstr "closedir('%s') misslyckades"
#, c-format
msgid "[GLE %ld] unable to open for read '%ls'"
-msgstr "[GLE %ld] kunde inte öppna â€%ls†för läsning"
+msgstr "[GLE %ld] kan inte öppna â€%ls†för läsning"
#, c-format
msgid "[GLE %ld] unable to get protocol information for '%ls'"
-msgstr "[GLE %ld] kunde inte hämta protokollinformation för â€%lsâ€"
+msgstr "[GLE %ld] kan inte hämta protokollinformation för â€%lsâ€"
#, c-format
msgid "failed to copy SID (%ld)"
@@ -14990,8 +15008,13 @@ msgstr "förkortningslängd utanför intervallet: %d"
msgid "bad zlib compression level %d"
msgstr "felaktigt zlib-komprimeringsgrad %d"
-msgid "core.commentChar should only be one ASCII character"
-msgstr "core.commentChar kan bara vara ett ASCII-tecken"
+#, c-format
+msgid "%s cannot contain newline"
+msgstr "%s kan inte innehålla nyradstecken"
+
+#, c-format
+msgid "%s must have at least one character"
+msgstr "%s måste innehålla minst ett tecken"
#, c-format
msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -15017,7 +15040,7 @@ msgstr "måste vara en av nothing, matching, simple, upstream eller current"
#, c-format
msgid "unable to load config blob object '%s'"
-msgstr "kunde inte läsa konfigurerings-blobobjektet â€%sâ€"
+msgstr "kan inte läsa konfigurerings-blobobjektet â€%sâ€"
#, c-format
msgid "reference '%s' does not point to a blob"
@@ -15044,7 +15067,7 @@ msgstr ""
#, c-format
msgid "unable to parse '%s' from command-line config"
-msgstr "kunde inte tolka värdet â€%s†frÃ¥n kommandoradskonfiguration"
+msgstr "kan inte tolka värdet â€%s†frÃ¥n kommandoradskonfiguration"
#, c-format
msgid "bad config variable '%s' in file '%s' at line %d"
@@ -15060,7 +15083,11 @@ msgstr "%s har flera värden"
#, c-format
msgid "failed to write new configuration file %s"
-msgstr "kan inte skriva nya konfigurationsfilen â€%sâ€"
+msgstr "misslyckades skriva nya konfigurationsfilen â€%sâ€"
+
+#, c-format
+msgid "no multi-line comment allowed: '%s'"
+msgstr "inga flerradiga kommentarer tillÃ¥tna: â€%sâ€"
#, c-format
msgid "could not lock config file %s"
@@ -15080,7 +15107,7 @@ msgstr "fstat misslyckades på %s"
#, c-format
msgid "unable to mmap '%s'%s"
-msgstr "kunde inte utföra mmap pÃ¥ â€%sâ€%s"
+msgstr "kan inte utföra mmap pÃ¥ â€%sâ€%s"
#, c-format
msgid "chmod on %s failed"
@@ -15178,7 +15205,7 @@ msgid "protocol '%s' is not supported"
msgstr "protokollet â€%s†stöds inte"
msgid "unable to set SO_KEEPALIVE on socket"
-msgstr "kunde inte sätta SO_KEEPALIVE på uttaget"
+msgstr "kan inte sätta SO_KEEPALIVE på uttaget"
#, c-format
msgid "Looking up %s ... "
@@ -15202,7 +15229,7 @@ msgid ""
"unable to connect to %s:\n"
"%s"
msgstr ""
-"kunde inte ansluta till %s:\n"
+"kan inte ansluta till %s:\n"
"%s"
#. TRANSLATORS: this is the end of "Connecting to %s (port %s) ... "
@@ -15211,7 +15238,7 @@ msgstr "klart."
#, c-format
msgid "unable to look up %s (%s)"
-msgstr "kunde inte slå upp %s (%s)"
+msgstr "kan inte slå upp %s (%s)"
#, c-format
msgid "unknown port %s"
@@ -15249,16 +15276,16 @@ msgid "strange pathname '%s' blocked"
msgstr "konstigt sökvägsnamn â€%s†blockerat"
msgid "unable to fork"
-msgstr "kunde inte grena (fork)"
+msgstr "kan inte grena (fork)"
msgid "Could not run 'git rev-list'"
msgstr "Kunde inte köra â€git rev-listâ€"
msgid "failed write to rev-list"
-msgstr "kunde inte skriva till rev-list"
+msgstr "misslyckades skriva till rev-list"
msgid "failed to close rev-list's stdin"
-msgstr "kunde inte stänga rev-list:s standard in"
+msgstr "misslyckades stänga rev-list:s standard in"
#, c-format
msgid "illegal crlf_action %d"
@@ -15320,7 +15347,7 @@ msgstr "omkodning av â€%s†frÃ¥n %s till %s och tillbaka ger inte samma resul
#, c-format
msgid "cannot fork to run external filter '%s'"
-msgstr "kan inte grena (fork) för att köra externt filter â€%sâ€"
+msgstr "kan inte grena (fork) av för att köra externt filter â€%sâ€"
#, c-format
msgid "cannot feed the input to external filter '%s'"
@@ -15452,7 +15479,7 @@ msgstr "felaktigt trädobjektet %s"
#, c-format
msgid "failed to load island regex for '%s': %s"
-msgstr "kunde inte hämta ö-regex för â€%sâ€: %s"
+msgstr "misslyckades hämta ö-regex för â€%sâ€: %s"
#, c-format
msgid "island regex from config has too many capture groups (max=%d)"
@@ -15615,7 +15642,7 @@ msgstr "okänt värde efter ws-error-highlight=%.*s"
#, c-format
msgid "unable to resolve '%s'"
-msgstr "kunde inte slÃ¥ upp â€%sâ€"
+msgstr "kan inte slÃ¥ upp â€%sâ€"
#, c-format
msgid "%s expects <n>/<m> form"
@@ -15998,7 +16025,7 @@ msgstr ""
#, c-format
msgid "failed to read orderfile '%s'"
-msgstr "kunde inte läsa orderfilen â€%sâ€"
+msgstr "misslyckades läsa orderfilen â€%sâ€"
msgid "Performing inexact rename detection"
msgstr "Utför onöjaktig namnbytesdetektering"
@@ -16098,7 +16125,7 @@ msgid "git fetch-pack: expected ACK/NAK, got '%s'"
msgstr "git fetch-pack: förväntade ACK/NAK, fick â€%sâ€"
msgid "unable to write to remote"
-msgstr "kunde inte skriva till fjärren"
+msgstr "kan inte skriva till fjärren"
msgid "Server supports filter"
msgstr "Servern stöder filter"
@@ -16154,14 +16181,14 @@ msgid "already have %s (%s)"
msgstr "har redan %s (%s)"
msgid "fetch-pack: unable to fork off sideband demultiplexer"
-msgstr "fetch-patch: kunde inte grena av sidbandsmultiplexare"
+msgstr "fetch-patch: kan inte grena (fork) av sidbandsmultiplexare"
msgid "protocol error: bad pack header"
msgstr "protokollfel: felaktigt packhuvud"
#, c-format
msgid "fetch-pack: unable to fork off %s"
-msgstr "fetch-patch: kunde inte grena av %s"
+msgstr "fetch-patch: kan inte grena (fork) av %s"
msgid "fetch-pack: invalid index-pack output"
msgstr "fetch-patch: ogiltig utdata från index-pack"
@@ -16214,7 +16241,7 @@ msgid "Server does not support shallow requests"
msgstr "Servern stöder inte grunda förfrågningar"
msgid "unable to write request to remote"
-msgstr "kunde inte skriva anrop till fjärren"
+msgstr "kan inte skriva anrop till fjärren"
#, c-format
msgid "expected '%s', received '%s'"
@@ -16516,7 +16543,7 @@ msgstr ""
#, c-format
msgid "'%s': unable to read %s"
-msgstr "â€%s†kunde inte läsa %s"
+msgstr "â€%sâ€: kan inte läsa %s"
#, c-format
msgid "'%s': short read"
@@ -16747,14 +16774,14 @@ msgstr "ingen e-post angavs och autodetektering är inaktiverad"
#, c-format
msgid "unable to auto-detect email address (got '%s')"
-msgstr "kunde inte autodetektera e-postadress (fick â€%sâ€)"
+msgstr "kan inte autodetektera e-postadress (fick â€%sâ€)"
msgid "no name was given and auto-detection is disabled"
msgstr "inget namn angavs och autodetektering är inaktiverad"
#, c-format
msgid "unable to auto-detect name (got '%s')"
-msgstr "kunde inte autodetektera namn (fick â€%sâ€)"
+msgstr "kan inte autodetektera namn (fick â€%sâ€)"
#, c-format
msgid "empty ident name (for <%s>) not allowed"
@@ -16789,7 +16816,7 @@ msgid "multiple filter-specs cannot be combined"
msgstr "flera filterspecifikationer kan inte kombineras"
msgid "unable to upgrade repository format to support partial clone"
-msgstr "kunde inte uppgradera arkivformat till att stöda delvis klon"
+msgstr "kan inte uppgradera arkivformat till att stöda delvis klon"
msgid "args"
msgstr "argument"
@@ -16799,11 +16826,11 @@ msgstr "objektfiltrering"
#, c-format
msgid "unable to access sparse blob in '%s'"
-msgstr "kunde inte nÃ¥ gles blob pÃ¥ â€%sâ€"
+msgstr "kan inte nÃ¥ gles blob pÃ¥ â€%sâ€"
#, c-format
msgid "unable to parse sparse filter data in %s"
-msgstr "kunde inte tolka gles filterdata i %s"
+msgstr "kan inte tolka gles filterdata i %s"
#, c-format
msgid "entry '%s' in tree %s has tree mode, but is not a tree"
@@ -16815,7 +16842,7 @@ msgstr "posten â€%s†i trädet %s har blob-läge, men är inte en blob"
#, c-format
msgid "unable to load root tree for commit %s"
-msgstr "kunde inte läsa in rot-trädet för incheckningen %s"
+msgstr "kan inte läsa in rot-trädet för incheckningen %s"
#, c-format
msgid ""
@@ -16841,6 +16868,14 @@ msgid "Unable to create '%s.lock': %s"
msgstr "Kunde inte skapa â€%s.lockâ€: %s"
#, c-format
+msgid "could not write loose object index %s"
+msgstr "kunde inte skriva löst objektindex %s"
+
+#, c-format
+msgid "failed to write loose object index %s\n"
+msgstr "misslyckades skriva löst objektindex %s\n"
+
+#, c-format
msgid "unexpected line: '%s'"
msgstr "oväntad rad: â€%sâ€"
@@ -16851,6 +16886,10 @@ msgid "quoted CRLF detected"
msgstr "citerad CRLF upptäcktes"
#, c-format
+msgid "unable to format message: %s"
+msgstr "kan inte formatera meddelandet: %s"
+
+#, c-format
msgid "Failed to merge submodule %s (not checked out)"
msgstr "Misslyckades slå ihop undermodulen %s (ej utcheckad)"
@@ -16863,6 +16902,10 @@ msgid "Failed to merge submodule %s (commits not present)"
msgstr "Misslyckades slå ihop undermodulen %s (incheckningar saknas)"
#, c-format
+msgid "Failed to merge submodule %s (repository corrupt)"
+msgstr "Misslyckades slå ihop undermodulen %s (arkivet är trasigt)"
+
+#, c-format
msgid "Failed to merge submodule %s (commits don't follow merge-base)"
msgstr ""
"Misslyckades slå ihop undermodulen %s (incheckningar följer inte "
@@ -16895,7 +16938,7 @@ msgstr "misslyckades exekvera intern sammanslagning"
#, c-format
msgid "unable to add %s to database"
-msgstr "kunde inte lägga till %s till databasen"
+msgstr "kan inte lägga till %s till databasen"
#, c-format
msgid "Auto-merging %s"
@@ -17329,6 +17372,82 @@ msgstr "Kunde inte tolka objektet â€%sâ€"
msgid "failed to read the cache"
msgstr "misslyckades läsa cachen"
+#, c-format
+msgid "failed to add packfile '%s'"
+msgstr "misslyckades läsa paketfilen â€%sâ€"
+
+#, c-format
+msgid "failed to open pack-index '%s'"
+msgstr "misslyckades öppna paketindexet â€%sâ€"
+
+#, c-format
+msgid "failed to locate object %d in packfile"
+msgstr "misslyckades hitta objekt %d i paketfilen"
+
+msgid "cannot store reverse index file"
+msgstr "kan inte spara reverse-index-fil"
+
+#, c-format
+msgid "could not parse line: %s"
+msgstr "kunde inte tolka rad: %s"
+
+#, c-format
+msgid "malformed line: %s"
+msgstr "felaktig rad: %s"
+
+msgid "ignoring existing multi-pack-index; checksum mismatch"
+msgstr "ignorerar befintlig multi-pack-index; felaktig kontrollsumma"
+
+msgid "could not load pack"
+msgstr "kunde inte läsa paket{"
+
+#, c-format
+msgid "could not open index for %s"
+msgstr "kunde inte öppna indexet för %s"
+
+msgid "Adding packfiles to multi-pack-index"
+msgstr "Lägger till paketfiler till multi-pack-index"
+
+#, c-format
+msgid "unknown preferred pack: '%s'"
+msgstr "okänt föredraget paket: %s"
+
+#, c-format
+msgid "cannot select preferred pack %s with no objects"
+msgstr "kan inte välja föredraget paket %s som inte har några objekt"
+
+#, c-format
+msgid "did not see pack-file %s to drop"
+msgstr "såg inte paketfilen %s som skulle kastas"
+
+#, c-format
+msgid "preferred pack '%s' is expired"
+msgstr "föredraget paket â€%s†har löpt ut"
+
+msgid "no pack files to index."
+msgstr "inga paketfiler att indexera."
+
+msgid "refusing to write multi-pack .bitmap without any objects"
+msgstr "kunde inte skriva fler-paketsbitkarta utan några objekt"
+
+msgid "could not write multi-pack bitmap"
+msgstr "kunde inte skriva fler-paketsbitkarta"
+
+msgid "could not write multi-pack-index"
+msgstr "kunde inte skriva flerpakets-index"
+
+msgid "Counting referenced objects"
+msgstr "Räknar refererade objekt"
+
+msgid "Finding and deleting unreferenced packfiles"
+msgstr "Ser efter och tar bort orefererade packfiler"
+
+msgid "could not start pack-objects"
+msgstr "kunde inte starta pack-objects"
+
+msgid "could not finish pack-objects"
+msgstr "kunde inte avsluta pack-objects"
+
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "OID-utbredning för multi-pack-index har fel storlek"
@@ -17402,70 +17521,6 @@ msgid "multi-pack-index large offset out of bounds"
msgstr "stort offset för mult-pack-index utanför gränsen"
#, c-format
-msgid "failed to add packfile '%s'"
-msgstr "misslyckades läsa paketfilen â€%sâ€"
-
-#, c-format
-msgid "failed to open pack-index '%s'"
-msgstr "misslyckades öppna paketindexet â€%sâ€"
-
-#, c-format
-msgid "failed to locate object %d in packfile"
-msgstr "misslyckades hitta objekt %d i paketfilen"
-
-msgid "cannot store reverse index file"
-msgstr "kan inte spara reverse-index-fil"
-
-#, c-format
-msgid "could not parse line: %s"
-msgstr "kunde inte tolka rad: %s"
-
-#, c-format
-msgid "malformed line: %s"
-msgstr "felaktig rad: %s"
-
-msgid "ignoring existing multi-pack-index; checksum mismatch"
-msgstr "ignorerar befintlig multi-pack-index; felaktig kontrollsumma"
-
-msgid "could not load pack"
-msgstr "kunde inte läsa paket{"
-
-#, c-format
-msgid "could not open index for %s"
-msgstr "kunde inte öppna indexet för %s"
-
-msgid "Adding packfiles to multi-pack-index"
-msgstr "Lägger till paketfiler till multi-pack-index"
-
-#, c-format
-msgid "unknown preferred pack: '%s'"
-msgstr "okänt föredraget paket: %s"
-
-#, c-format
-msgid "cannot select preferred pack %s with no objects"
-msgstr "kan inte välja föredraget paket %s som inte har några objekt"
-
-#, c-format
-msgid "did not see pack-file %s to drop"
-msgstr "såg inte paketfilen %s som skulle kastas"
-
-#, c-format
-msgid "preferred pack '%s' is expired"
-msgstr "föredraget paket â€%s†har löpt ut"
-
-msgid "no pack files to index."
-msgstr "inga paketfiler att indexera."
-
-msgid "refusing to write multi-pack .bitmap without any objects"
-msgstr "kunde inte skriva fler-paketsbitkarta utan några objekt"
-
-msgid "could not write multi-pack bitmap"
-msgstr "kunde inte skriva fler-paketsbitkarta"
-
-msgid "could not write multi-pack-index"
-msgstr "kunde inte skriva flerpakets-index"
-
-#, c-format
msgid "failed to clear multi-pack-index at %s"
msgstr "misslyckades städa multi-pack-index på %s"
@@ -17506,29 +17561,17 @@ msgstr "misslyckades läsa paketindex för paketfil %s"
msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>"
msgstr "felaktigt objekt-offset för oid[%d] = %s: %<PRIx64> != %<PRIx64>"
-msgid "Counting referenced objects"
-msgstr "Räknar refererade objekt"
-
-msgid "Finding and deleting unreferenced packfiles"
-msgstr "Ser efter och tar bort orefererade packfiler"
-
-msgid "could not start pack-objects"
-msgstr "kunde inte starta pack-objects"
-
-msgid "could not finish pack-objects"
-msgstr "kunde inte avsluta pack-objects"
-
#, c-format
msgid "unable to create lazy_dir thread: %s"
-msgstr "misslyckades skapa lazy_dir-tråd: %s"
+msgstr "kan inte skapa lazy_dir-tråd: %s"
#, c-format
msgid "unable to create lazy_name thread: %s"
-msgstr "misslyckades skapa lazy_name-tråd: %s"
+msgstr "kan inte skapa lazy_name-tråd: %s"
#, c-format
msgid "unable to join lazy_name thread: %s"
-msgstr "misslyckades utföra join på lazy_name-tråd: %s"
+msgstr "kan inte utföra join på lazy_name-tråd: %s"
#, c-format
msgid ""
@@ -17564,13 +17607,32 @@ msgstr "Vägrar skriva över anteckningar i %s (utanför refs/notes/)"
msgid "Bad %s value: '%s'"
msgstr "Felaktigt värde pÃ¥ %s: â€%sâ€"
+msgid "failed to decode tree entry"
+msgstr "misslyckades avkoda trädposten"
+
+#, c-format
+msgid "failed to map tree entry for %s"
+msgstr "misslyckades koppla trädpost för %s"
+
+#, c-format
+msgid "bad %s in commit"
+msgstr "felaktig %s i incheckning"
+
+#, c-format
+msgid "unable to map %s %s in commit object"
+msgstr "kan inte koppla %s %s i incheckningsobjekt"
+
+#, c-format
+msgid "Failed to convert object from %s to %s"
+msgstr "Misslyckades konvertera objekt från %s till %s"
+
#, c-format
msgid "object directory %s does not exist; check .git/objects/info/alternates"
msgstr "objektkatalogen %s finns inte; se .git/objects/info/alternates"
#, c-format
msgid "unable to normalize alternate object path: %s"
-msgstr "kunde inte normalisera supplerande objektsökväg: %s"
+msgstr "kan inte normalisera supplerande objektsökväg: %s"
#, c-format
msgid "%s: ignoring alternate object stores, nesting too deep"
@@ -17665,8 +17727,12 @@ msgid "packed object %s (stored in %s) is corrupt"
msgstr "packat objekt %s (lagrat i %s) är trasigt"
#, c-format
+msgid "missing mapping of %s to %s"
+msgstr "saknar koppling av %s till %s"
+
+#, c-format
msgid "unable to write file %s"
-msgstr "kunde inte skriva filen %s"
+msgstr "kan inte skriva filen %s"
#, c-format
msgid "unable to set permission to '%s'"
@@ -17684,7 +17750,7 @@ msgid "unable to create temporary file"
msgstr "kan inte skapa temporär fil"
msgid "unable to write loose object file"
-msgstr "kunde inte skriva fil för löst objekt"
+msgstr "kan inte skriva fil för löst objekt"
#, c-format
msgid "unable to deflate new object %s (%d)"
@@ -17712,13 +17778,17 @@ msgstr "â€deflatEend†pÃ¥ strömobjektet misslyckades (%d)"
#, c-format
msgid "unable to create directory %s"
-msgstr "kunde inte skapa katalogen %s"
+msgstr "kan inte skapa katalogen %s"
#, c-format
msgid "cannot read object for %s"
msgstr "kan inte läsa objekt för %s"
#, c-format
+msgid "cannot map object %s to %s"
+msgstr "kan inte koppla objektet %s till %s"
+
+#, c-format
msgid "object fails fsck: %s"
msgstr "objekt klarar inte fsck: %s"
@@ -17935,7 +18005,7 @@ msgstr "objektet %s har okänd typ-id %d"
#, c-format
msgid "unable to parse object: %s"
-msgstr "kunde inte tolka objektet: %s"
+msgstr "kan inte tolka objektet: %s"
#, c-format
msgid "hash mismatch %s"
@@ -18018,7 +18088,10 @@ msgstr "trasig ewah-bitkarta: avhugget huvud för bitkarta för incheckning â€%
#, c-format
msgid "unable to load pack: '%s', disabling pack-reuse"
-msgstr "kunde inte läsa paketet: â€%sâ€, inaktiverar Ã¥teranvändning av paket"
+msgstr "kan inte läsa paketet: â€%sâ€, inaktiverar Ã¥teranvändning av paket"
+
+msgid "unable to compute preferred pack, disabling pack-reuse"
+msgstr "kan inte beräkna föredraget paket, inaktiverar återanvändning av paket"
#, c-format
msgid "object '%s' not found in type bitmaps"
@@ -18123,7 +18196,7 @@ msgstr "kunde inte ta status: %s"
#, c-format
msgid "failed to make %s readable"
-msgstr "kunde inte göra %s läsbar"
+msgstr "misslyckades göra %s läsbar"
#, c-format
msgid "could not write '%s' promisor file"
@@ -18285,7 +18358,7 @@ msgstr "felaktigt booleskt miljövariabelvärde â€%s†för â€%sâ€"
#, c-format
msgid "failed to parse %s"
-msgstr "kunde inte tolka %s"
+msgstr "misslyckades tolka %s"
#, c-format
msgid "Could not make %s writable by group"
@@ -18364,7 +18437,7 @@ msgid "unable to write delim packet"
msgstr "kan inte skriva delim-paket"
msgid "unable to write response end packet"
-msgstr "kunde inte skriva svarsavslutningspaket"
+msgstr "kan inte skriva svarsavslutningspaket"
msgid "flush packet write failed"
msgstr "fel vid skrivning av â€flushâ€-paket"
@@ -18405,16 +18478,16 @@ msgstr "Uppdaterar indexet"
#, c-format
msgid "unable to create threaded lstat: %s"
-msgstr "kunde inte skapa trådad lstat: %s"
+msgstr "kan inte skapa trådad lstat: %s"
msgid "unable to parse --pretty format"
-msgstr "kunde inte tolka format för --pretty"
+msgstr "kan inte tolka format för --pretty"
msgid "promisor-remote: unable to fork off fetch subprocess"
-msgstr "promisor-remote: kunde inte starta (fork) underprocessen för fetch"
+msgstr "promisor-remote: kan inte grena (fork) av underprocessen för fetch"
msgid "promisor-remote: could not write to fetch subprocess"
-msgstr "promisor-remote: kunde skriva till underprocessen för fetch"
+msgstr "promisor-remote: kan skriva till underprocessen för fetch"
msgid "promisor-remote: could not close stdin to fetch subprocess"
msgstr ""
@@ -18552,11 +18625,11 @@ msgstr "osorterade köposter för â€%sâ€"
#, c-format
msgid "unable to create load_cache_entries thread: %s"
-msgstr "kunde inte skapa tråd för load_cache_entries: %s"
+msgstr "kan inte skapa tråd för load_cache_entries: %s"
#, c-format
msgid "unable to join load_cache_entries thread: %s"
-msgstr "kunde inte ansluta till tråden för load_cache_entries: %s"
+msgstr "kan inte ansluta till tråden för load_cache_entries: %s"
#, c-format
msgid "%s: index file open failed"
@@ -18576,11 +18649,11 @@ msgstr "%s: kan inte koppla indexfilen%s"
#, c-format
msgid "unable to create load_index_extensions thread: %s"
-msgstr "kunde inte skapa load_index_extensions-tråden: %s"
+msgstr "kan inte skapa load_index_extensions-tråden: %s"
#, c-format
msgid "unable to join load_index_extensions thread: %s"
-msgstr "kunde inte utföra join på load_index_extensions-tråden: %s"
+msgstr "kan inte utföra join på load_index_extensions-tråden: %s"
#, c-format
msgid "could not freshen shared index '%s'"
@@ -18598,11 +18671,11 @@ msgstr "misslyckades omvandla till glest index"
#, c-format
msgid "unable to open git dir: %s"
-msgstr "kunde inte öppna git-katalog: %s"
+msgstr "kan inte öppna git-katalog: %s"
#, c-format
msgid "unable to unlink: %s"
-msgstr "misslyckades ta bort länken: %s"
+msgstr "kan inte ta bort länken: %s"
#, c-format
msgid "cannot fix permission bits on '%s'"
@@ -19070,6 +19143,72 @@ msgid "could not delete references: %s"
msgstr "kunde inte ta bort referenser: %s"
#, c-format
+msgid "refname is dangerous: %s"
+msgstr "refnamnet är farligt: %s"
+
+#, c-format
+msgid "trying to write ref '%s' with nonexistent object %s"
+msgstr "försöker skriva referensen â€%s†med icke-existerande objektet %s"
+
+#, c-format
+msgid "trying to write non-commit object %s to branch '%s'"
+msgstr "försöker skriva objektet %s som inte är incheckning till grenen â€%sâ€"
+
+#, c-format
+msgid ""
+"multiple updates for 'HEAD' (including one via its referent '%s') are not "
+"allowed"
+msgstr ""
+"flera uppdateringar för â€HEAD†(inklusive en via dess referent â€%sâ€) tillÃ¥ts "
+"inte"
+
+#, c-format
+msgid "cannot lock ref '%s': unable to resolve reference '%s'"
+msgstr "kan inte lÃ¥sa referensen â€%sâ€: kan inte slÃ¥ upp referensen â€%sâ€"
+
+#, c-format
+msgid "cannot lock ref '%s': error reading reference"
+msgstr "kan inte lÃ¥sa referensen â€%sâ€: fel vid läsning av referensen"
+
+#, c-format
+msgid ""
+"multiple updates for '%s' (including one via symref '%s') are not allowed"
+msgstr ""
+"flera uppdateringar för â€%s†(inklusive en via symrefen â€%sâ€) tillÃ¥ts inte"
+
+#, c-format
+msgid "cannot lock ref '%s': reference already exists"
+msgstr "kan inte lÃ¥sa referensen â€%sâ€: referensen finns redan"
+
+#, c-format
+msgid "cannot lock ref '%s': reference is missing but expected %s"
+msgstr "kan inte lÃ¥sa referensen â€%sâ€: referensen saknas men förväntade %s"
+
+#, c-format
+msgid "cannot lock ref '%s': is at %s but expected %s"
+msgstr "kan inte lÃ¥sa referensen â€%sâ€: är vid %s men förväntade %s"
+
+#, c-format
+msgid "reftable: transaction prepare: %s"
+msgstr "referenstabell: förbereder transaktion: %s"
+
+#, c-format
+msgid "reftable: transaction failure: %s"
+msgstr "referenstabell: transaktionen misslyckades: %s"
+
+#, c-format
+msgid "unable to compact stack: %s"
+msgstr "kan inte kompaktera stack: %s"
+
+#, c-format
+msgid "refname %s not found"
+msgstr "referensnamnet %s hittades inte"
+
+#, c-format
+msgid "refname %s is a symbolic ref, copying it is not supported"
+msgstr "referensnamnet %s är en symbolisk referens, kopiering stöds inte"
+
+#, c-format
msgid "invalid refspec '%s'"
msgstr "felaktig referensspecifikation: â€%sâ€"
@@ -19078,6 +19217,10 @@ msgid "invalid quoting in push-option value: '%s'"
msgstr "felaktig citering pÃ¥ värde för push-option: â€%sâ€"
#, c-format
+msgid "unknown value for object-format: %s"
+msgstr "okänt värde för object-format: %s"
+
+#, c-format
msgid "%sinfo/refs not valid: is this a git repository?"
msgstr "%sinfo/refs inte giltig: är detta ett git-arkiv?"
@@ -19115,7 +19258,7 @@ msgid "remote server sent unexpected response end packet"
msgstr "fjärrservern sände oväntat svarsavslutningspaketet"
msgid "unable to rewind rpc post data - try increasing http.postBuffer"
-msgstr "kunde inte spola tillbaka rpc-postdata - försök öka http.postBuffer"
+msgstr "kan inte spola tillbaka rpc-postdata - försök öka http.postBuffer"
#, c-format
msgid "remote-curl: bad line length character: %.4s"
@@ -19350,7 +19493,7 @@ msgstr "â€enkel push†motsvarar flera olika mÃ¥l"
#, c-format
msgid "couldn't find remote ref %s"
-msgstr "Kunde inte hitta fjärr-referensen %s"
+msgstr "kunde inte hitta fjärr-referensen %s"
#, c-format
msgid "* Ignoring funny ref '%s' locally"
@@ -19438,7 +19581,7 @@ msgid "corrupt MERGE_RR"
msgstr "trasig MERGE_RR"
msgid "unable to write rerere record"
-msgstr "kunde inte skriva rerere-post"
+msgstr "kan inte skriva rerere-post"
#, c-format
msgid "there were errors while writing '%s' (%s)"
@@ -19503,7 +19646,7 @@ msgstr "kunde inte bestämma HEAD-revision"
#, c-format
msgid "failed to find tree of %s"
-msgstr "kunde inte hitta trädet för %s."
+msgstr "misslyckades hitta trädet för %s."
#, c-format
msgid "unsupported section for hidden refs: %s"
@@ -19517,15 +19660,26 @@ msgid "resolve-undo records `%s` which is missing"
msgstr "resolve-undo registrerar â€%s†som saknas"
#, c-format
-msgid "could not get commit for ancestry-path argument %s"
-msgstr "kunde inte hämta incheckning för â€ancestry-pathâ€-argumentet %s"
+msgid "%s exists but is a symbolic ref"
+msgstr "%s finns men är en symbolisk referens"
+
+msgid ""
+"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD or REBASE_HEAD"
+msgstr ""
+"--merge kräver en av pseudoreferenserna MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD eller REBASE_HEAD"
+
+#, c-format
+msgid "could not get commit for --ancestry-path argument %s"
+msgstr "kunde inte hämta incheckning för â€--ancestry-pathâ€-argumentet %s"
msgid "--unpacked=<packfile> no longer supported"
msgstr "--unpacked=<paketfil> stöds inte längre"
#, c-format
msgid "invalid option '%s' in --stdin mode"
-msgstr "ogiltig flagga â€%s†i --stdin-läge"
+msgstr "ogiltig flagga â€%s†i â€--stdinâ€-läge"
msgid "your current branch appears to be broken"
msgstr "din nuvarande gren verkar vara trasig"
@@ -19747,7 +19901,7 @@ msgstr "oväntat flush-paket vid läsning av fjärruppackningsstatus"
#, c-format
msgid "unable to parse remote unpack status: %s"
-msgstr "kunde inte tolka fjärruppackningsstatus: %s"
+msgstr "kan inte tolka fjärruppackningsstatus: %s"
#, c-format
msgid "remote unpack failed: %s"
@@ -19757,7 +19911,7 @@ msgid "failed to sign the push certificate"
msgstr "misslyckades underteckna push-certifikatet"
msgid "send-pack: unable to fork off fetch subprocess"
-msgstr "send-pack: kunde inte starta (fork) underprocessen för fetch"
+msgstr "send-pack: kan inte grena (fork) av underprocessen för fetch"
msgid "push negotiation failed; proceeding anyway with push"
msgstr "sänd-förhandling misslyckades; fortsätter ändå med sändningen"
@@ -19803,6 +19957,19 @@ msgid "unknown action: %d"
msgstr "okänd funktion: %d"
msgid ""
+"Resolve all conflicts manually, mark them as resolved with\n"
+"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
+"You can instead skip this commit: run \"git rebase --skip\".\n"
+"To abort and get back to the state before \"git rebase\", run \"git rebase --"
+"abort\"."
+msgstr ""
+"Lös alla konflikter manuellt, märk dem som lösta med\n"
+"â€git add/rm <filer_i_konflikt>â€, kör sedan â€git rebase --continueâ€.\n"
+"Du kan hoppa över incheckningen istället: kör â€git rebase --skipâ€.\n"
+"För att avbryta och Ã¥tergÃ¥ till där du var före ombaseringen, kör â€git "
+"rebase --abortâ€."
+
+msgid ""
"after resolving the conflicts, mark the corrected paths\n"
"with 'git add <paths>' or 'git rm <paths>'"
msgstr ""
@@ -19989,7 +20156,7 @@ msgid "could not parse newly created commit"
msgstr "kunde inte tolka en precis skapad incheckning"
msgid "unable to resolve HEAD after creating commit"
-msgstr "kunde inte bestämma HEAD efter att ha skapat incheckning"
+msgstr "kan inte bestämma HEAD efter att ha skapat incheckning"
msgid "detached HEAD"
msgstr "frånkopplad HEAD"
@@ -20005,11 +20172,11 @@ msgid "HEAD %s is not a commit!"
msgstr "HEAD %s är inte en incheckning!"
msgid "unable to parse commit author"
-msgstr "kunde inte tolka incheckningens författare"
+msgstr "kan inte tolka incheckningens författare"
#, c-format
msgid "unable to read commit message from '%s'"
-msgstr "kunde inte läsa incheckningsmeddelande frÃ¥n â€%sâ€"
+msgstr "kan inte läsa incheckningsmeddelande frÃ¥n â€%sâ€"
#, c-format
msgid "invalid author identity '%s'"
@@ -20023,10 +20190,6 @@ msgid "could not update %s"
msgstr "kunde inte uppdatera %s"
#, c-format
-msgid "could not parse commit %s"
-msgstr "kunde inte tolka incheckningen %s"
-
-#, c-format
msgid "could not parse parent commit %s"
msgstr "kunde inte tolka föräldraincheckningen %s"
@@ -20130,10 +20293,6 @@ msgid "invalid command '%.*s'"
msgstr "ogiltigt kommando â€%.*sâ€"
#, c-format
-msgid "%s does not accept arguments: '%s'"
-msgstr "%s tar inte argument: â€%sâ€"
-
-#, c-format
msgid "missing arguments for %s"
msgstr "argument saknas för %s"
@@ -20231,7 +20390,7 @@ msgid "no cherry-pick in progress"
msgstr "ingen â€cherry-pick†pÃ¥gÃ¥r"
msgid "failed to skip the commit"
-msgstr "kunde inte hoppa över incheckningen"
+msgstr "misslyckades hoppa över incheckningen"
msgid "there is nothing to skip"
msgstr "ingenting att hoppa över"
@@ -20588,6 +20747,10 @@ msgid "unable to set up work tree using invalid config"
msgstr "kan inte skapa arbetskatalog med felaktig konfiguration"
#, c-format
+msgid "'%s' already specified as '%s'"
+msgstr "â€%s†har redan angivits som â€%sâ€"
+
+#, c-format
msgid "Expected git repo version <= %d, found %d"
msgstr "Förväntade git-arkivversion <= %d, hittade %d"
@@ -20776,6 +20939,21 @@ msgstr "indexposten är en katalog, men inte gles (%08x)"
msgid "cannot use split index with a sparse index"
msgstr "kan inte dela indexet med ett glest index"
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not start with '('"
+msgstr "felaktigt %s-format: elementet â€%s†börjar inte med â€(â€"
+
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not end in ')'"
+msgstr "felaktigt %s-format: elementet â€%s†slutar inte med â€)â€"
+
+#. TRANSLATORS: %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: %%%.*s"
+msgstr "felaktigt %s-format: %%%.*s"
+
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#, c-format
msgid "%u.%2.2u GiB"
@@ -20833,11 +21011,11 @@ msgstr "ignorerar â€%s†som kan tolkas som en kommandoradsflagga: %s"
#, c-format
msgid "Could not update .gitmodules entry %s"
-msgstr "Kunde inte uppdatera .gitmodules-posten %s"
+msgstr "Kunde inte uppdatera â€.gitmodulesâ€-posten %s"
msgid "Cannot change unmerged .gitmodules, resolve merge conflicts first"
msgstr ""
-"Kan inte ändra .gitmodules-fil som inte slagits ihop, lös "
+"Kan inte ändra â€.gitmodulesâ€-fil som inte slagits ihop, lös "
"sammanslagningskonflikter först"
#, c-format
@@ -20846,7 +21024,7 @@ msgstr "Hittade inte någon sektion i .gitmodules där sökväg=%s"
#, c-format
msgid "Could not remove .gitmodules entry for %s"
-msgstr "Kunde inte ta bort .gitmodules-posten för %s"
+msgstr "Kunde inte ta bort â€.gitmodulesâ€-posten för %s"
msgid "staging updated .gitmodules failed"
msgstr "misslyckades köa uppdaterad .gitmodules"
@@ -20909,7 +21087,7 @@ msgstr "Kunde inte komma Ã¥t undermodulen â€%s†vid incheckningen %s\n"
#, c-format
msgid "Fetching submodule %s%s at commit %s\n"
-msgstr "Hämtar undermodulen %s%s vvid incheckningen %s\n"
+msgstr "Hämtar undermodulen %s%s vid incheckningen %s\n"
#, c-format
msgid ""
@@ -21098,29 +21276,6 @@ msgstr "okänt värde â€%s†för nyckeln â€%sâ€"
msgid "empty trailer token in trailer '%.*s'"
msgstr "tom släpradssymbol i släpraden â€%.*sâ€"
-#, c-format
-msgid "could not read input file '%s'"
-msgstr "kunde inte läsa indatafilen â€%sâ€"
-
-#, c-format
-msgid "could not stat %s"
-msgstr "kunde inte ta status på %s"
-
-#, c-format
-msgid "file %s is not a regular file"
-msgstr "filen %s är inte en normal fil"
-
-#, c-format
-msgid "file %s is not writable by user"
-msgstr "filen %s är inte skrivbar av användaren"
-
-msgid "could not open temporary file"
-msgstr "kunde inte öppna temporär fil"
-
-#, c-format
-msgid "could not rename temporary file to %s"
-msgstr "kunde inte byta namn på temporär fil till %s"
-
msgid "full write to remote helper failed"
msgstr "komplett skrivning till fjärrhjälpare misslyckades"
@@ -21218,8 +21373,8 @@ msgid "remote-helper doesn't support push; refspec needed"
msgstr "fjärrhjälparen stöder inte push; referensspecifikation krävs"
#, c-format
-msgid "helper %s does not support 'force'"
-msgstr "hjälparen %s stöder inte â€forceâ€"
+msgid "helper %s does not support '--force'"
+msgstr "hjälparen %s stöder inte â€--forceâ€"
msgid "couldn't run fast-export"
msgstr "kunde inte köra fast-export"
@@ -21346,7 +21501,7 @@ msgid "Aborting."
msgstr "Avbryter."
msgid "failed to push all needed submodules"
-msgstr "kunde inte sända alla nödvändiga undermoduler"
+msgstr "misslyckades sända alla nödvändiga undermoduler"
msgid "bundle-uri operation not supported by protocol"
msgstr "bundle-uri-funktionen stöds inte av protokollet"
@@ -21636,6 +21791,10 @@ msgstr "felaktigt portnummer"
msgid "invalid '..' path segment"
msgstr "felaktigt â€..â€-sökvägssegment"
+#, c-format
+msgid "error: unable to format message: %s\n"
+msgstr "fel: kan inte formatera meddelande: %s\n"
+
msgid "usage: "
msgstr "användning: "
@@ -21683,13 +21842,13 @@ msgid "not a valid path"
msgstr "inte en giltig sökväg"
msgid "unable to locate repository; .git is not a file"
-msgstr "hittar inte arkivet; .git är inte en fil"
+msgstr "kan inte hitta arkivet; .git är inte en fil"
msgid "unable to locate repository; .git file does not reference a repository"
-msgstr "hittar inte arkivet; .git-filen hänvisar inte till ett arkiv"
+msgstr "kan inte hitta arkivet; â€.gitâ€-filen hänvisar inte till ett arkiv"
msgid "unable to locate repository; .git file broken"
-msgstr "hittar inte arkivet; .git-filen är trasig"
+msgstr "kan inte hitta arkivet; â€.gitâ€-filen är trasig"
msgid "gitdir unreadable"
msgstr "gitdir är oläsbar"
@@ -21701,21 +21860,21 @@ msgid "not a valid directory"
msgstr "inte i en giltig katalog"
msgid "gitdir file does not exist"
-msgstr "gitdir-filen existerar inte"
+msgstr "â€gitdirâ€-filen existerar inte"
#, c-format
msgid "unable to read gitdir file (%s)"
-msgstr "kunde inte läsa gitdir-filen (%s)"
+msgstr "kan inte läsa â€gitdirâ€-filen (%s)"
#, c-format
msgid "short read (expected %<PRIuMAX> bytes, read %<PRIuMAX>)"
msgstr "kort läsning (förväntade %<PRIuMAX> byte, läste %<PRIuMAX>)"
msgid "invalid gitdir file"
-msgstr "ogiltig gitdir-fil"
+msgstr "ogiltig â€gitdirâ€-fil"
msgid "gitdir file points to non-existent location"
-msgstr "gitdir-filen pekar på en ickeexisterande plats"
+msgstr "â€gitdirâ€-filen pekar pÃ¥ en ickeexisterande plats"
#, c-format
msgid "unable to set %s in '%s'"
@@ -21734,7 +21893,7 @@ msgstr "kunde inte lagra miljövariabeln â€%sâ€"
#, c-format
msgid "unable to create '%s'"
-msgstr "kunde inte skapa â€%sâ€"
+msgstr "kan inte skapa â€%sâ€"
#, c-format
msgid "could not open '%s' for reading and writing"
@@ -21748,7 +21907,7 @@ msgid "unable to get current working directory"
msgstr "kan inte hämta aktuell arbetskatalog"
msgid "unable to get random bytes"
-msgstr "kunde inte hämta slumpdata"
+msgstr "kan inte hämta slumpdata"
msgid "Unmerged paths:"
msgstr "Ej sammanslagna sökvägar:"
@@ -22222,7 +22381,7 @@ msgstr "använd: $dashless $USAGE"
#, sh-format
msgid "Cannot chdir to $cdup, the toplevel of the working tree"
-msgstr "Kunde inte byta katalog till $cdup, toppnivån på arbetskatalogen"
+msgstr "Kan inte byta katalog till $cdup, toppnivån på arbetskatalogen"
#, sh-format
msgid "fatal: $program_name cannot be used without a working tree."
@@ -22352,7 +22511,7 @@ msgstr "Ingen ärenderad i %s?"
#, perl-format
msgid "Failed to open for writing %s: %s"
-msgstr "Kunde inte öppna för skrivning %s: %s"
+msgstr "Misslyckades öppna för skrivning %s: %s"
msgid ""
"Lines beginning in \"GIT:\" will be removed.\n"
@@ -22417,7 +22576,7 @@ msgstr ""
#, perl-format
msgid "error: unable to extract a valid address from: %s\n"
-msgstr "fel: kunde inte få fram en giltig adress från: %s\n"
+msgstr "fel: kan inte få fram en giltig adress från: %s\n"
#. TRANSLATORS: Make sure to include [q] [d] [e] in your
#. translation. The program will only accept English input
@@ -22555,7 +22714,7 @@ msgstr ""
#, perl-format
msgid "unable to open %s: %s\n"
-msgstr "kunde inte öppna %s: %s\n"
+msgstr "kan inte öppna %s: %s\n"
#, perl-format
msgid ""
diff --git a/po/tr.po b/po/tr.po
index 5837752d0b..0e220e1c1c 100644
--- a/po/tr.po
+++ b/po/tr.po
@@ -49,8 +49,8 @@
# pathspec | yol belirteci #
# pattern | dizgi #
# porcelain | okunabilir #
-# prune | buda(mak) #
-# pseudoref | yalancıktan başvuru #
+# prune | buda(mak) #
+# pseudoref | yalancı başvuru #
# pull | çek(mek) #
# push | it(mek) #
# rebase | yeniden temellendirme(k) #
@@ -96,8 +96,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Git Turkish Localization Project\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2024-02-16 22:04+0300\n"
-"PO-Revision-Date: 2024-02-16 22:00+0300\n"
+"POT-Creation-Date: 2024-04-29 01:09+0300\n"
+"PO-Revision-Date: 2024-04-29 01:10+0300\n"
"Last-Translator: Emir SARI <emir_sari@icloud.com>\n"
"Language-Team: Turkish (https://github.com/bitigchi/git-po/)\n"
"Language: tr\n"
@@ -580,12 +580,12 @@ msgid ""
"---\n"
"To remove '%c' lines, make them ' ' lines (context).\n"
"To remove '%c' lines, delete them.\n"
-"Lines starting with %c will be removed.\n"
+"Lines starting with %s will be removed.\n"
msgstr ""
"---\n"
"'%c' satır kaldırmak için onları ' ' satır yapın (bağlam).\n"
"'%c' satır kaldırmak için onları silin.\n"
-"%c kaldırılacak.\n"
+"%s ile başlayan satırlar kaldırılacak.\n"
msgid ""
"If it does not apply cleanly, you will be given an opportunity to\n"
@@ -632,6 +632,7 @@ msgid ""
"/ - search for a hunk matching the given regex\n"
"s - split the current hunk into smaller hunks\n"
"e - manually edit the current hunk\n"
+"p - print the current hunk\n"
"? - print help\n"
msgstr ""
"j - bu parça için sonra karar ver, bir sonraki karar verilmemiş parçayı gör\n"
@@ -642,6 +643,7 @@ msgstr ""
"/ - verilen düzenli ifade ile eşleşen bir parça ara\n"
"s - geçerli parçayı daha ufak parçalara böl\n"
"e - geçerli parçayı el ile düzenle\n"
+"p - geçerli parçalı yazdır\n"
"? - yardımı yazdır\n"
msgid "No previous hunk"
@@ -704,8 +706,8 @@ msgstr ""
"Bu iletiyi \"git config advice.%s false\" ile devre dışı bırakın"
#, c-format
-msgid "%shint: %.*s%s\n"
-msgstr "%sipucu: %.*s%s\n"
+msgid "%shint:%s%.*s%s\n"
+msgstr "%sipucu: %s%.*s%s\n"
msgid "Cherry-picking is not possible because you have unmerged files."
msgstr "Seç-al yapılamaz; birleştirmesi tamamlanmamış dosyalarınız var."
@@ -1203,10 +1205,6 @@ msgstr[0] "%%s yaması %d geri çevirme ile uygulanıyor..."
msgstr[1] "%%s yaması %d geri çevirme ile uygulanıyor..."
#, c-format
-msgid "truncating .rej filename to %.*s.rej"
-msgstr ".rej dosya adı %.*s.rej olarak kısaltılıyor"
-
-#, c-format
msgid "cannot open %s"
msgstr "%s açılamıyor"
@@ -1627,6 +1625,10 @@ msgid "could not create file '%s'"
msgstr "'%s' dosyası oluşturulamadı"
#, c-format
+msgid "unable to start 'show' for object '%s'"
+msgstr "'%s' nesnesi için 'show' başlatılamıyor"
+
+#, c-format
msgid "could not read file '%s'"
msgstr "'%s' dosyası okunamadı"
@@ -1778,6 +1780,9 @@ msgstr ""
msgid "'%s' is not a valid branch name"
msgstr "'%s' geçerli bir dal adı değil"
+msgid "See `man git check-ref-format`"
+msgstr "'man git check-ref-format' kılavuz sayfasına bakın"
+
#, c-format
msgid "a branch named '%s' already exists"
msgstr "'%s' adında bir dal halihazırda var"
@@ -1973,14 +1978,8 @@ msgstr ""
msgid "adding embedded git repository: %s"
msgstr "gömülü git deposu ekleniyor: %s"
-msgid ""
-"Use -f if you really want to add them.\n"
-"Turn this message off by running\n"
-"\"git config advice.addIgnoredFile false\""
-msgstr ""
-"Gerçekten eklemek istiyorsanız -f kullanın.\n"
-"Bu iletiyi 'git config advice.addIgnoredFile false'\n"
-"yaparak kapatabilirsiniz"
+msgid "Use -f if you really want to add them."
+msgstr "Onları gerçekten eklemek istiyorsanız -f kullanın."
msgid "adding files failed"
msgstr "dosya ekleme başarısız"
@@ -1997,14 +1996,8 @@ msgstr "'%s' ve yol belirteci argümanları birlikte kullanılamaz"
msgid "Nothing specified, nothing added.\n"
msgstr "Hiçbir şey belirtilmedi, hiçbir şey eklenmedi.\n"
-msgid ""
-"Maybe you wanted to say 'git add .'?\n"
-"Turn this message off by running\n"
-"\"git config advice.addEmptyPathspec false\""
-msgstr ""
-"'git add .' mı demek istediniz?\n"
-"Bu iletiyi 'git config advice.addEmptyPathspec false'\n"
-"yaparak kapatabilirsiniz"
+msgid "Maybe you wanted to say 'git add .'?"
+msgstr "'git add .' mi demek istediniz?"
msgid "index file corrupt"
msgstr "indeks dosyası hasarlı"
@@ -2081,24 +2074,25 @@ msgid "Failed to split patches."
msgstr "Yamalar parçalanıp bölünemedi."
#, c-format
-msgid "When you have resolved this problem, run \"%s --continue\"."
-msgstr "Bu sorunu çözdüğünüzde \"%s --continue\" çalıştırın."
+msgid "When you have resolved this problem, run \"%s --continue\".\n"
+msgstr "Bu sorunu çözdüğünüzde \"%s --continue\" çalıştırın.\n"
#, c-format
-msgid "If you prefer to skip this patch, run \"%s --skip\" instead."
-msgstr "Eğer bu yamayı atlamayı yeğliyorsanız \"%s --skip\" çalıştırın."
+msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n"
+msgstr "Eğer bu yamayı atlamayı yeğliyorsanız \"%s --skip\" çalıştırın.\n"
#, c-format
-msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"."
+msgid ""
+"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"
msgstr ""
"Boş yamayı boş işleme kaydı olarak yazmak için \"%s --allow-empty\" "
-"çalıştırın."
+"çalıştırın.\n"
#, c-format
msgid "To restore the original branch and stop patching, run \"%s --abort\"."
msgstr ""
"İlk dalı eski durumuna getirip yamalamayı durdurmak için \"%s --abort\" "
-"çalıştır."
+"çalıştırın."
msgid "Patch sent with format=flowed; space at the end of lines might be lost."
msgstr ""
@@ -2941,11 +2935,11 @@ msgstr "dal kopyalandı; ancak config-file güncellenemedi"
msgid ""
"Please edit the description for the branch\n"
" %s\n"
-"Lines starting with '%c' will be stripped.\n"
+"Lines starting with '%s' will be stripped.\n"
msgstr ""
-"Lütfen dal açıklamasını düzenleyin:\n"
+"Lütfen dal açıklamasını düzenleyin\n"
"\t%s\n"
-"'%c' ile başlayan satırlar çıkarılacaktır.\n"
+"'%s' ile başlayan satırlar soyulacaktır.\n"
msgid "Generic options"
msgstr "Genel seçenekler"
@@ -3146,10 +3140,12 @@ msgid "not run from a git repository - no hooks to show\n"
msgstr "bir git deposundan çalıştırılmadı - gösterilecek kanca yok\n"
msgid ""
-"git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"git bugreport [(-o | --output-directory) <path>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
" [--diagnose[=<mode>]]"
msgstr ""
-"git bugreport [(-o | --output-directory) <yol>] [(-s | --suffix) <biçim>]\n"
+"git bugreport [(-o | --output-directory) <yol>]\n"
+" [(-s | --suffix) <biçim> | --no-suffix]\n"
" [--diagnose[=<kip>]]"
msgid ""
@@ -3630,6 +3626,10 @@ msgstr "'%s', '%s' veya '%s' bir ağaçtan çıkış yaparken kullanılamaz"
msgid "path '%s' is unmerged"
msgstr "'%s' yolu birleÅŸtirilmemiÅŸ"
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr "ağaç okunamıyor (%s)"
+
msgid "you need to resolve your current index first"
msgstr "önce geçerli indeksinizi çözmelisiniz"
@@ -3859,6 +3859,10 @@ msgstr "Dal, işleme olmayan '%s' ögesine değiştirilemez"
msgid "missing branch or commit argument"
msgstr "dal veya işleme argümanı eksik"
+#, c-format
+msgid "unknown conflict style '%s'"
+msgstr "bilinmeyen çakışma stili '%s'"
+
msgid "perform a 3-way merge with the new branch"
msgstr "yeni dal ile bir 3 yönlü birleştirme gerçekleştir"
@@ -4115,19 +4119,10 @@ msgstr "yok sayılan dosyalar da kaldırıldı"
msgid "remove only ignored files"
msgstr "yalnızca yok sayılan dosyaları kaldır"
-msgid ""
-"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to "
-"clean"
+msgid "clean.requireForce is true and -f not given: refusing to clean"
msgstr ""
-"clean.requireForce 'true' olarak ayarlanmış ve ne -i ne -n ne de -f "
-"verilmiÅŸ; temizleme reddediliyor"
-
-msgid ""
-"clean.requireForce defaults to true and neither -i, -n, nor -f given; "
-"refusing to clean"
-msgstr ""
-"clean.requireForce öntanımlı olarak 'true' ve ne -i ne -n ne de -f verilmiş; "
-"temizleme reddediliyor"
+"clean.requireForce 'true' olarak ayarlı ve -f verilmedi; temizlik "
+"reddediliyor"
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<seçenekler>] [--] <depo> [<dizin>]"
@@ -4141,8 +4136,8 @@ msgstr "çıkış yapma!"
msgid "create a bare repository"
msgstr "çıplak bir depo oluştur"
-msgid "create a mirror repository (implies bare)"
-msgstr "bir yansı depo oluştur (çıplak ima eder)"
+msgid "create a mirror repository (implies --bare)"
+msgstr "bir yansı depo oluştur (--bare ima eder)"
msgid "to clone from a local repository"
msgstr "bir yerel depodan klonla"
@@ -4262,7 +4257,7 @@ msgstr "%s var ve bir dizin deÄŸil"
#, c-format
msgid "'%s' is a symlink, refusing to clone with --local"
-msgstr "'%s' bir sembolik bağlantı; --local ile klonlama reddediliyor"
+msgstr "'%s' bir sembolik baÄŸ; --local ile klonlama reddediliyor"
#, c-format
msgid "failed to start iterator over '%s'"
@@ -4270,7 +4265,7 @@ msgstr "yineleyici '%s' üzerinden çalıştırılamadı"
#, c-format
msgid "symlink '%s' exists, refusing to clone with --local"
-msgstr "'%s' sembolik bağlantısı var, --local ile klonlama reddediliyor"
+msgstr "'%s' sembolik bağı var, --local ile klonlama reddediliyor"
#, c-format
msgid "failed to unlink '%s'"
@@ -4452,6 +4447,10 @@ msgstr "saÄŸ kenardaki dolgu boÅŸluÄŸu"
msgid "padding space between columns"
msgstr "sütunlar arasındaki dolgu boşluğu"
+#, c-format
+msgid "%s must be non-negative"
+msgstr "%s negatif dışı bir değer olmalı"
+
msgid "--command must be the first argument"
msgstr "--command ilk argüman olmalı"
@@ -4765,34 +4764,34 @@ msgstr "işleme şablonu yazılamadı"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored.\n"
+"with '%s' will be ignored.\n"
msgstr ""
-"Lütfen değişiklikleriniz için bir işleme iletisi girin. '%c' ile başlayan\n"
+"Lütfen değişiklikleriniz için bir işleme iletisi girin. '%s' ile başlayan\n"
"satırlar yok sayılacaktır.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored, and an empty message aborts the commit.\n"
+"with '%s' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
-"Lütfen değişiklikleriniz için bir işleme iletisi girin. '%c' ile başlayan\n"
+"Lütfen değişiklikleriniz için bir işleme iletisi girin. '%s' ile başlayan\n"
"satırlar yok sayılacaktır. Boş bir ileti işlemeyi iptal eder.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
msgstr ""
-"Lütfen değişiklikleriniz için bir işleme iletisi girin. '%c' ile başlayan\n"
+"Lütfen değişiklikleriniz için bir işleme iletisi girin. '%s' ile başlayan\n"
"satırlar tutulacaktır; isterseniz onları kaldırabilirsiniz.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
-"Lütfen değişiklikleriniz için bir işleme iletisi girin. '%c' ile başlayan\n"
+"Lütfen değişiklikleriniz için bir işleme iletisi girin. '%s' ile başlayan\n"
"satırlar tutulacaktır; isterseniz onları kaldırabilirsiniz.\n"
"BoÅŸ bir ileti iÅŸlemeyi iptal eder.\n"
@@ -5241,6 +5240,9 @@ msgstr "deÄŸer"
msgid "with --get, use default value when missing entry"
msgstr "--get ile girdi verilmemişse öntanımlı değeri kullan"
+msgid "human-readable comment string (# will be prepended as needed)"
+msgstr "kişi tarafından okunabilir yorum satırı (gerekirse önüne # koyulur)"
+
#, c-format
msgid "wrong number of arguments, should be %d"
msgstr "yanlış argüman sayısı, %d olmalı"
@@ -5332,7 +5334,10 @@ msgstr ""
"ve --list"
msgid "--default is only applicable to --get"
-msgstr "--default yalnızca şuna uygulanabilir: --get"
+msgstr "--default yalnızca --get için uygulanabilir"
+
+msgid "--comment is only applicable to add/set/replace operations"
+msgstr "--comment yalnızca ekle/ayarla/değiştir işlemlerine uygulanabilir"
msgid "--fixed-value only applies with 'value-pattern'"
msgstr "--fixed-value yalnızca 'değer-dizgisi' ile uygulanır"
@@ -6174,6 +6179,9 @@ msgstr "yalnızca işlemeyi içermeyen başvuruları yazdır"
msgid "read reference patterns from stdin"
msgstr "baÅŸvuru dizgilerini stdin'den oku"
+msgid "also include HEAD ref and pseudorefs"
+msgstr "ayrıca HEAD ve yalancı başvuruları içer"
+
msgid "unknown arguments supplied with --stdin"
msgstr "--stdin ile bilinmeyen argümanlar verilmiş"
@@ -6786,10 +6794,6 @@ msgid "no threads support, ignoring %s"
msgstr "iş parçacığı desteği yok, %s yok sayılıyor"
#, c-format
-msgid "unable to read tree (%s)"
-msgstr "ağaç okunamıyor (%s)"
-
-#, c-format
msgid "unable to read tree %s"
msgstr "%s ağacı okunamıyor"
@@ -7395,14 +7399,39 @@ msgstr "--separate-git-dir, çıplak depo ile uyumsuz"
msgid ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n"
+" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
" [--parse] [<file>...]"
msgstr ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<anahtar>|<anArması>)"
-"[(=|:)<deÄŸer>])...]\n"
+" [(--trailer (<anahtar>|<arma>)[(=|:)<deÄŸer>])...]\n"
" [--parse] [<dosya>...]"
+#, c-format
+msgid "could not stat %s"
+msgstr "%s dosya bilgileri alınamadı"
+
+#, c-format
+msgid "file %s is not a regular file"
+msgstr "%s dosyası sıradan bir dosya değil"
+
+#, c-format
+msgid "file %s is not writable by user"
+msgstr "%s dosyası kullanıcı tarafından yazılabilir değil"
+
+msgid "could not open temporary file"
+msgstr "geçici dosya açılamadı"
+
+#, c-format
+msgid "could not read input file '%s'"
+msgstr "'%s' girdi dosyası okunamadı"
+
+msgid "could not read from stdin"
+msgstr "stdin'den okunamadı"
+
+#, c-format
+msgid "could not rename temporary file to %s"
+msgstr "geçici dosya adı %s olarak değiştirilemedi"
+
msgid "edit files in place"
msgstr "dosyaları yerinde düzenle"
@@ -7788,18 +7817,6 @@ msgstr "İzlenen bir uzak dal bulunamadı, lütfen el ile <üstkaynak> belirtin.
msgid "could not get object info about '%s'"
msgstr "'%s' hakkında nesne bilgisi alınamadı"
-#, c-format
-msgid "bad ls-files format: element '%s' does not start with '('"
-msgstr "hatalı ls-files biçimi: '%s' ögesi, '(' ile başlamıyor"
-
-#, c-format
-msgid "bad ls-files format: element '%s' does not end in ')'"
-msgstr "hatalı ls-files biçimi: '%s' ögesi, ')' ile sonlanmıyor"
-
-#, c-format
-msgid "bad ls-files format: %%%.*s"
-msgstr "hatalı ls-files biçimi: %%%.*s"
-
msgid "git ls-files [<options>] [<file>...]"
msgstr "git ls-files [<seçenekler>] [<dosya>...]"
@@ -7930,18 +7947,6 @@ msgstr "işaret ettiği nesneye ek olarak altında yatan başvuruyu göster"
msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
msgstr "git ls-tree [<seçenekler>] <ağacımsı> [<yol>...]"
-#, c-format
-msgid "bad ls-tree format: element '%s' does not start with '('"
-msgstr "hatalı ls-tree biçimi: '%s' ögesi '(' ile başlamıyor"
-
-#, c-format
-msgid "bad ls-tree format: element '%s' does not end in ')'"
-msgstr "hatalı ls-tree biçimi: '%s' ögesi ')' ile sonlanmıyor"
-
-#, c-format
-msgid "bad ls-tree format: %%%.*s"
-msgstr "hatalı ls-tree biçimi: %%%.*s"
-
msgid "only show trees"
msgstr "yalnızca ağaçları göster"
@@ -8128,6 +8133,10 @@ msgstr "'%s' başvurusu çözülemedi"
msgid "Merging %s with %s\n"
msgstr "%s, %s ile birleÅŸtiriliyor\n"
+#, c-format
+msgid "could not parse as tree '%s'"
+msgstr "'%s' ağacı olarak ayrıştırılamadı"
+
msgid "not something we can merge"
msgstr "birleÅŸtirebileceÄŸimiz bir ÅŸey deÄŸil"
@@ -8330,10 +8339,10 @@ msgstr "BoÅŸ bir ileti iÅŸlemeyi iptal eder.\n"
#, c-format
msgid ""
-"Lines starting with '%c' will be ignored, and an empty message aborts\n"
+"Lines starting with '%s' will be ignored, and an empty message aborts\n"
"the commit.\n"
msgstr ""
-"'%c' ile başlayan satırlar yok sayılacaktır. Boş bir ileti işlemeyi\n"
+"'%s' ile başlayan satırlar yok sayılacaktır. Boş bir ileti işlemeyi\n"
"iptal eder.\n"
msgid "Empty commit message."
@@ -8490,9 +8499,6 @@ msgstr "etiketlenmiş nesne '%s' okunamadı"
msgid "object '%s' tagged as '%s', but is a '%s' type"
msgstr "'%s' nesnesi '%s' olarak etiketlenmiş; ancak bir '%s' türü"
-msgid "could not read from stdin"
-msgstr "stdin'den okunamadı"
-
msgid "tag on stdin did not pass our strict fsck check"
msgstr "stdin üzerindeki etiket bizim sıkı fsck denetimimizi geçemedi"
@@ -8753,10 +8759,6 @@ msgstr "git notes prune [<seçenekler>]"
msgid "Write/edit the notes for the following object:"
msgstr "Aşağıdaki nesneler için not yaz/düzenle:"
-#, c-format
-msgid "unable to start 'show' for object '%s'"
-msgstr "'%s' nesnesi için 'show' başlatılamıyor"
-
msgid "could not read 'show' output"
msgstr "'show' çıktısı okunamadı"
@@ -9383,11 +9385,11 @@ msgid "refusing to run without --i-still-use-this"
msgstr "--i-still-use-this olmadan çalıştırma reddediliyor"
msgid ""
-"git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude "
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
"<pattern>]"
msgstr ""
-"git pack-refs [--all] [--no-prune]git pack-refs [--all] [--no-prune] [--"
-"include <dizgi>] [--exclude <dizgi>]"
+"git pack-refs [--all] [--no-prune] [--auto] [--include <dizgi>] [--exclude "
+"<dizgi>]"
msgid "pack everything"
msgstr "her ÅŸeyi paketle"
@@ -9395,6 +9397,9 @@ msgstr "her ÅŸeyi paketle"
msgid "prune loose refs (default)"
msgstr "gevşek başvuruları buda (öntanımlı)"
+msgid "auto-pack refs as needed"
+msgstr "gerekirse başvuruları paketle"
+
msgid "references to include"
msgstr "içerilecek başvurular"
@@ -10047,19 +10052,6 @@ msgstr "geçersiz allow_rerere_autoupdate yok sayılıyor: '%s'"
msgid "could not remove '%s'"
msgstr "'%s' kaldırılamadı"
-msgid ""
-"Resolve all conflicts manually, mark them as resolved with\n"
-"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
-"You can instead skip this commit: run \"git rebase --skip\".\n"
-"To abort and get back to the state before \"git rebase\", run \"git rebase --"
-"abort\"."
-msgstr ""
-"Tüm çakışmaları el ile çözün, onları \"git add/rm <çakışan-dosyalar>\"\n"
-"ile tamam olarak imleyin, ardından \"git rebase --continue\"\n"
-"çalıştırın. Bunun yerine bu işlemeyi atlayabilirsiniz: \"git rebase\n"
-"--skip\" yapın. İptal edip \"git rebase\" öncesine geri dönmek için\n"
-"\"git rebase --abort\" çalıştırın."
-
#, c-format
msgid ""
"\n"
@@ -10089,12 +10081,15 @@ msgstr "şuraya geçilemedi: %s"
msgid "apply options and merge options cannot be used together"
msgstr "uygulama seçenekleri ve birleştirme seçenekleri birlikte kullanılamaz"
+msgid "--empty=ask is deprecated; use '--empty=stop' instead."
+msgstr "--empty=ask artık kullanılmıyor; yerine '--empty=stop' kullanın."
+
#, c-format
msgid ""
"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
-"\"ask\"."
+"\"stop\"."
msgstr ""
-"Tanımlanamayan boş tür '%s'; geçerli türler: \"drop\", \"keep\" ve \"ask\"."
+"Tanımlanamayan boş tür '%s'; geçerli türler: \"drop\", \"keep\" ve \"stop\"."
msgid ""
"--rebase-merges with an empty string argument is deprecated and will stop "
@@ -10278,8 +10273,8 @@ msgstr ""
"Not: `pull.rebase` yapılandırmanız, artık desteklenmeyen'\n"
"'preserve' olarak ayarlı olabilir; yerine 'merges' kullanın"
-msgid "No rebase in progress?"
-msgstr "Sürmekte olan bir yeniden temellendirme yok"
+msgid "no rebase in progress"
+msgstr "sürmekte olan yeniden temellendirme yok"
msgid "The --edit-todo action can only be used during interactive rebase."
msgstr ""
@@ -10475,6 +10470,9 @@ msgstr "bir dizin belirtmelisiniz"
msgid "git reflog [show] [<log-options>] [<ref>]"
msgstr "git reflog [show] [<günlük-seçenekleri>] [<başvuru>]"
+msgid "git reflog list"
+msgstr "git reflog list"
+
msgid ""
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
" [--rewrite] [--updateref] [--stale-fix]\n"
@@ -10500,6 +10498,10 @@ msgstr "git reflog exists <baÅŸvuru>"
msgid "invalid timestamp '%s' given to '--%s'"
msgstr "geçersiz zaman damgası '%s', '--%s' argümanına verildi"
+#, c-format
+msgid "%s does not accept arguments: '%s'"
+msgstr "%s argüman kabul etmiyor: '%s'"
+
msgid "do not actually prune any entries"
msgstr "özünde, hiçbir girdiyi budama"
@@ -10627,8 +10629,8 @@ msgstr ""
"\t yerine --mirror=fetch veya --mirror=push kullanın"
#, c-format
-msgid "unknown mirror argument: %s"
-msgstr "bilinmeyen yansı argümanı: %s"
+msgid "unknown --mirror argument: %s"
+msgstr "bilinmeyen --mirror argümanı: %s"
msgid "fetch the remote branches"
msgstr "uzak konum dallarını getir"
@@ -10997,6 +10999,9 @@ msgstr ""
msgid "could not start pack-objects to repack promisor objects"
msgstr "vaatçi nesneleri yeniden paketleme için pack-objects başlatılamadı"
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "vaatçi nesneleri pack-objects'e beslenemedi"
+
msgid "repack: Expecting full hex object ID lines only from pack-objects."
msgstr ""
"repack: Onaltılı tam nesne no satırları yalnızca pack-objects'ten bekleniyor."
@@ -11593,6 +11598,13 @@ msgstr "--default bir argüman gerektiriyor"
msgid "--prefix requires an argument"
msgstr "--prefix bir argüman gerektiriyor"
+msgid "no object format specified"
+msgstr "belirtilen nesne biçimi yok"
+
+#, c-format
+msgid "unsupported object format: %s"
+msgstr "desteklenmeyen nesne biçimi: %s"
+
#, c-format
msgid "unknown mode for --abbrev-ref: %s"
msgstr "--abbrev-ref için bilinmeyen kip: %s"
@@ -11674,8 +11686,8 @@ msgstr "başlangıçta boş olan işlemeleri koru"
msgid "allow commits with empty messages"
msgstr "boÅŸ iletili iÅŸlemelere izin ver"
-msgid "keep redundant, empty commits"
-msgstr "gereksiz, boÅŸ iÅŸlemeleri tut"
+msgid "deprecated: use --empty=keep instead"
+msgstr "kullanılmıyor: Yerine --empty=keep kullanın"
msgid "use the 'reference' format to refer to commits"
msgstr "işlemelere başvurmak için 'reference' biçimini kullan"
@@ -12999,25 +13011,25 @@ msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be ignored.\n"
+"Lines starting with '%s' will be ignored.\n"
msgstr ""
"\n"
"Etiket için bir ileti yazın:\n"
" %s\n"
-"'%c' ile başlayan satırlar yok sayılacaktır.\n"
+"'%s' ile başlayan satırlar yok sayılacaktır.\n"
#, c-format
msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be kept; you may remove them yourself if you "
+"Lines starting with '%s' will be kept; you may remove them yourself if you "
"want to.\n"
msgstr ""
"\n"
"Etiket için bir ileti yazın:\n"
" %s\n"
-"'%c' ile başlayan satırlar tutulacaktır; isterseniz onları "
+"'%s' ile başlayan satırlar tutulacaktır; isterseniz onları "
"kaldırabilirsiniz.\n"
msgid "unable to sign the tag"
@@ -13102,6 +13114,9 @@ msgstr "yalnızca birleştirilmeyen etiketleri yazdır"
msgid "print only tags of the object"
msgstr "yalnızca nesnenin etiketlerini yazdır"
+msgid "could not start 'git column'"
+msgstr "'git column' başlatılamadı"
+
#, c-format
msgid "the '%s' option is only allowed in list mode"
msgstr "'%s' seçeneğine yalnızca liste kipinde izin verilir"
@@ -13343,12 +13358,12 @@ msgstr ""
msgid "fsmonitor disabled"
msgstr "dosya sistemi monitörü devre dışı"
-msgid "git update-ref [<options>] -d <refname> [<old-val>]"
-msgstr "git update-ref [<seçenekler>] -d <bşvr-adı> [<eski-değer>]"
+msgid "git update-ref [<options>] -d <refname> [<old-oid>]"
+msgstr "git update-ref [<seçenekler>] -d <bşvr-adı> [<eski-nesne-kimliği>]"
-msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]"
+msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]"
msgstr ""
-"git update-ref [<seçenekler>] <bşvr-adı> <yeni-değer> [<eski-değer>]"
+"git update-ref [<seçenekler>] <bşvr-adı> <yeni-n-kiml> [<eski-n-kiml>]"
msgid "git update-ref [<options>] --stdin [-z]"
msgstr "git update-ref [<seçenekler>] --stdin [-z]"
@@ -14692,6 +14707,10 @@ msgid "Verifying commits in commit graph"
msgstr "İşleme grafiğindeki işlemeler doğrulanıyor"
#, c-format
+msgid "could not parse commit %s"
+msgstr "%s işlemesi ayrıştırılamadı"
+
+#, c-format
msgid "%s %s is not a commit!"
msgstr "%s %s bir iÅŸleme deÄŸil!"
@@ -15122,8 +15141,13 @@ msgstr "kısaltma uzunluğu erim dışında: %d"
msgid "bad zlib compression level %d"
msgstr "hatalı zlib sıkıştırma düzeyi %d"
-msgid "core.commentChar should only be one ASCII character"
-msgstr "core.commentChar yalnızca bir ASCII karakter olmalı"
+#, c-format
+msgid "%s cannot contain newline"
+msgstr "%s yenisatır içeremez"
+
+#, c-format
+msgid "%s must have at least one character"
+msgstr "%s, en az bir karaktere iye olmalı"
#, c-format
msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -15194,6 +15218,10 @@ msgid "failed to write new configuration file %s"
msgstr "yeni yapılandırma dosyası %s yazılamadı"
#, c-format
+msgid "no multi-line comment allowed: '%s'"
+msgstr "çok satırlı işlemeye izin verilmiyor: '%s'"
+
+#, c-format
msgid "could not lock config file %s"
msgstr "%s yapılandırma dosyası kilitlenemedi"
@@ -16985,6 +17013,14 @@ msgid "Unable to create '%s.lock': %s"
msgstr "'%s.lock' oluşturulamıyor: %s"
#, c-format
+msgid "could not write loose object index %s"
+msgstr "gevşek nesne indeksi %s yazılamadı"
+
+#, c-format
+msgid "failed to write loose object index %s\n"
+msgstr "gevşek nesne indeksi %s yazımı başarısız\n"
+
+#, c-format
msgid "unexpected line: '%s'"
msgstr "beklenmedik satır: '%s'"
@@ -16995,6 +17031,10 @@ msgid "quoted CRLF detected"
msgstr "alıntılanmış CRLF algılandı"
#, c-format
+msgid "unable to format message: %s"
+msgstr "ileti biçimlendirilemiyor: %s"
+
+#, c-format
msgid "Failed to merge submodule %s (not checked out)"
msgstr "%s altmodülü birleştirilemedi (çıkış yapılmadı)"
@@ -17007,6 +17047,10 @@ msgid "Failed to merge submodule %s (commits not present)"
msgstr "%s altmodülü birleştirilemedi (işlemeler yok)"
#, c-format
+msgid "Failed to merge submodule %s (repository corrupt)"
+msgstr "%s altmodülü birleştirilemedi (depo hasarlı)"
+
+#, c-format
msgid "Failed to merge submodule %s (commits don't follow merge-base)"
msgstr "%s altmodülü birleştirilemedi (işlemeler merge-base'i takip etmiyor)"
@@ -17480,6 +17524,82 @@ msgstr "'%s' nesnesi ayrıştırılamadı"
msgid "failed to read the cache"
msgstr "önbellek okunamadı"
+#, c-format
+msgid "failed to add packfile '%s'"
+msgstr "paket dosyası '%s' eklenemedi"
+
+#, c-format
+msgid "failed to open pack-index '%s'"
+msgstr "pack-index '%s' açılamadı"
+
+#, c-format
+msgid "failed to locate object %d in packfile"
+msgstr "%d nesnesi paket dosyasında bulunamadı"
+
+msgid "cannot store reverse index file"
+msgstr "ters indeks dosyası depolanamıyor"
+
+#, c-format
+msgid "could not parse line: %s"
+msgstr "satır ayrıştırılamadı: %s"
+
+#, c-format
+msgid "malformed line: %s"
+msgstr "hatalı oluşturulmuş satır: %s"
+
+msgid "ignoring existing multi-pack-index; checksum mismatch"
+msgstr "var olan multi-pack-index yok sayılıyor; sağlama toplamı uyumsuzluğu"
+
+msgid "could not load pack"
+msgstr "paket yüklenemedi"
+
+#, c-format
+msgid "could not open index for %s"
+msgstr "%s için indeks açılamadı"
+
+msgid "Adding packfiles to multi-pack-index"
+msgstr "Paket dosyaları multi-pack-index'e ekleniyor"
+
+#, c-format
+msgid "unknown preferred pack: '%s'"
+msgstr "bilinmeyen tercih edilen paket: '%s'"
+
+#, c-format
+msgid "cannot select preferred pack %s with no objects"
+msgstr "yeğlenen paket %s nesnesiz seçilemiyor"
+
+#, c-format
+msgid "did not see pack-file %s to drop"
+msgstr "bırakılacak pack-file %s görülmedi"
+
+#, c-format
+msgid "preferred pack '%s' is expired"
+msgstr "tercih edilen '%s' paketinin süresi geçmiş"
+
+msgid "no pack files to index."
+msgstr "indekslenecek paket dosyası yok."
+
+msgid "refusing to write multi-pack .bitmap without any objects"
+msgstr "bir nesne olmadan multi-pack .bitmap yazımı reddediliyor"
+
+msgid "could not write multi-pack bitmap"
+msgstr "çoklu paket biteşlem yazılamadı"
+
+msgid "could not write multi-pack-index"
+msgstr "multi-pack-index yazılamadı"
+
+msgid "Counting referenced objects"
+msgstr "Başvurulmuş nesneler sayılıyor"
+
+msgid "Finding and deleting unreferenced packfiles"
+msgstr "Başvurulmamış paket dosyaları bulunuyor ve siliniyor"
+
+msgid "could not start pack-objects"
+msgstr "pack-objects başlatılamadı"
+
+msgid "could not finish pack-objects"
+msgstr "pack-objects bitirilemedi"
+
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "multi-pack-index OID çıkış sayısı boyutu yanlış"
@@ -17549,70 +17669,6 @@ msgid "multi-pack-index large offset out of bounds"
msgstr "multi-pack-index geniş ofseti sınırlar dışında"
#, c-format
-msgid "failed to add packfile '%s'"
-msgstr "paket dosyası '%s' eklenemedi"
-
-#, c-format
-msgid "failed to open pack-index '%s'"
-msgstr "pack-index '%s' açılamadı"
-
-#, c-format
-msgid "failed to locate object %d in packfile"
-msgstr "%d nesnesi paket dosyasında bulunamadı"
-
-msgid "cannot store reverse index file"
-msgstr "ters indeks dosyası depolanamıyor"
-
-#, c-format
-msgid "could not parse line: %s"
-msgstr "satır ayrıştırılamadı: %s"
-
-#, c-format
-msgid "malformed line: %s"
-msgstr "hatalı oluşturulmuş satır: %s"
-
-msgid "ignoring existing multi-pack-index; checksum mismatch"
-msgstr "var olan multi-pack-index yok sayılıyor; sağlama toplamı uyumsuzluğu"
-
-msgid "could not load pack"
-msgstr "paket yüklenemedi"
-
-#, c-format
-msgid "could not open index for %s"
-msgstr "%s için indeks açılamadı"
-
-msgid "Adding packfiles to multi-pack-index"
-msgstr "Paket dosyaları multi-pack-index'e ekleniyor"
-
-#, c-format
-msgid "unknown preferred pack: '%s'"
-msgstr "bilinmeyen tercih edilen paket: '%s'"
-
-#, c-format
-msgid "cannot select preferred pack %s with no objects"
-msgstr "yeğlenen paket %s nesnesiz seçilemiyor"
-
-#, c-format
-msgid "did not see pack-file %s to drop"
-msgstr "bırakılacak pack-file %s görülmedi"
-
-#, c-format
-msgid "preferred pack '%s' is expired"
-msgstr "tercih edilen '%s' paketinin süresi geçmiş"
-
-msgid "no pack files to index."
-msgstr "indekslenecek paket dosyası yok."
-
-msgid "refusing to write multi-pack .bitmap without any objects"
-msgstr "bir nesne olmadan multi-pack .bitmap yazımı reddediliyor"
-
-msgid "could not write multi-pack bitmap"
-msgstr "çoklu paket biteşlem yazılamadı"
-
-msgid "could not write multi-pack-index"
-msgstr "multi-pack-index yazılamadı"
-
-#, c-format
msgid "failed to clear multi-pack-index at %s"
msgstr "multi-pack-index %s konumunda temizlenemedi"
@@ -17653,18 +17709,6 @@ msgstr "paket dosyası %s için pack-index yüklenemedi"
msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>"
msgstr "şunun için yanlış nesne ofseti: oid[%d] = %s: %<PRIx64> != %<PRIx64>"
-msgid "Counting referenced objects"
-msgstr "Başvurulmuş nesneler sayılıyor"
-
-msgid "Finding and deleting unreferenced packfiles"
-msgstr "Başvurulmamış paket dosyaları bulunuyor ve siliniyor"
-
-msgid "could not start pack-objects"
-msgstr "pack-objects başlatılamadı"
-
-msgid "could not finish pack-objects"
-msgstr "pack-objects bitirilemedi"
-
#, c-format
msgid "unable to create lazy_dir thread: %s"
msgstr "lazy_dir iş parçacığı oluşturulamıyor: %s"
@@ -17711,6 +17755,25 @@ msgstr "%s içindeki notları yeniden yazma reddediliyor (refs/notes/ dışında
msgid "Bad %s value: '%s'"
msgstr "Hatalı %s değeri: '%s'"
+msgid "failed to decode tree entry"
+msgstr "ağaç girdisinin kodu çözülemedi"
+
+#, c-format
+msgid "failed to map tree entry for %s"
+msgstr "%s için olan ağaç girdisi eşlemlenemedi"
+
+#, c-format
+msgid "bad %s in commit"
+msgstr "işlemede hatalı %s"
+
+#, c-format
+msgid "unable to map %s %s in commit object"
+msgstr "iÅŸleme nesnesinde %s %s eÅŸlemlenemiyor"
+
+#, c-format
+msgid "Failed to convert object from %s to %s"
+msgstr "Nesne, %s -> %s olarak dönüştürülemedi"
+
#, c-format
msgid "object directory %s does not exist; check .git/objects/info/alternates"
msgstr "nesne dizini %s yok; şurayı denetleyin: .git/objects/info/alternates"
@@ -17813,6 +17876,10 @@ msgid "packed object %s (stored in %s) is corrupt"
msgstr "paketlenmiş nesne %s (%s içinde depolanıyor) hasarlı"
#, c-format
+msgid "missing mapping of %s to %s"
+msgstr "%s ögesinin %s ögesine eksik eşlemlemesi"
+
+#, c-format
msgid "unable to write file %s"
msgstr "%s dosyası yazılamıyor"
@@ -17866,6 +17933,10 @@ msgid "cannot read object for %s"
msgstr "%s için nesne okunamıyor"
#, c-format
+msgid "cannot map object %s to %s"
+msgstr "%s nesnesi %s ögesine eşlemlenemiyor"
+
+#, c-format
msgid "object fails fsck: %s"
msgstr "nesne fsck'yi başarısız ediyor: %s"
@@ -18170,6 +18241,9 @@ msgstr ""
msgid "unable to load pack: '%s', disabling pack-reuse"
msgstr "paket yüklenemiyor: '%s', pack-reuse devre dışı bırakılıyor"
+msgid "unable to compute preferred pack, disabling pack-reuse"
+msgstr "yeğlenen paket hesaplanamıyor, pack-reuse devre dışı bırakılıyor"
+
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "'%s' nesnesi, tür biteşlemlerinde bulunamadı"
@@ -19219,6 +19293,73 @@ msgid "could not delete references: %s"
msgstr "baÅŸvurular silinemedi: %s"
#, c-format
+msgid "refname is dangerous: %s"
+msgstr "başvuru adı tehlikeli: %s"
+
+#, c-format
+msgid "trying to write ref '%s' with nonexistent object %s"
+msgstr "'%s' başvurusu, var olmayan %s nesnesiyle yazılmaya çalışılıyor"
+
+#, c-format
+msgid "trying to write non-commit object %s to branch '%s'"
+msgstr "işleme olmayan %s nesnesi '%s' dalına yazılmaya çalışılıyor"
+
+#, c-format
+msgid ""
+"multiple updates for 'HEAD' (including one via its referent '%s') are not "
+"allowed"
+msgstr ""
+"'HEAD' için birden çok güncellemeye (ona başvuran '%s' ile olan bir tanesini "
+"de içeren) izin verilmiyor"
+
+#, c-format
+msgid "cannot lock ref '%s': unable to resolve reference '%s'"
+msgstr "'%s' başvurusu kilitlenemiyor: '%s' başvurusu çözülemiyor"
+
+#, c-format
+msgid "cannot lock ref '%s': error reading reference"
+msgstr "'%s' baÅŸvurusu kilitlenemiyor: BaÅŸvuruyu okurken hata"
+
+#, c-format
+msgid ""
+"multiple updates for '%s' (including one via symref '%s') are not allowed"
+msgstr ""
+"'%s' için birden çok güncellemeye ('%s' sembolik bağlantısı ile olan bir "
+"tanesini de içeren) izin verilmiyor"
+
+#, c-format
+msgid "cannot lock ref '%s': reference already exists"
+msgstr "'%s' başvurusu kilitlenemiyor: Başvuru halihazırda var"
+
+#, c-format
+msgid "cannot lock ref '%s': reference is missing but expected %s"
+msgstr "'%s' baÅŸvurusu kilitlenemiyor: BaÅŸvuru eksik; ancak %s bekleniyordu"
+
+#, c-format
+msgid "cannot lock ref '%s': is at %s but expected %s"
+msgstr "'%s' başvurusu kilitlenemiyor: %s üzerinde; ancak %s bekleniyordu"
+
+#, c-format
+msgid "reftable: transaction prepare: %s"
+msgstr "reftable: İşlem hazırlığı: %s"
+
+#, c-format
+msgid "reftable: transaction failure: %s"
+msgstr "reftable: İşlem başarısız: %s"
+
+#, c-format
+msgid "unable to compact stack: %s"
+msgstr "yığın kompaktlaştırılamıyor: %s"
+
+#, c-format
+msgid "refname %s not found"
+msgstr "başvuru adı %s bulunamadı"
+
+#, c-format
+msgid "refname %s is a symbolic ref, copying it is not supported"
+msgstr "başvuru adı %s bir sembolik bağlantı, onu kopyalamak desteklenmiyor"
+
+#, c-format
msgid "invalid refspec '%s'"
msgstr "geçersiz başvuru belirteci '%s'"
@@ -19227,6 +19368,10 @@ msgid "invalid quoting in push-option value: '%s'"
msgstr "push-option değerinde geçersiz tırnak içine alım: '%s'"
#, c-format
+msgid "unknown value for object-format: %s"
+msgstr "object-format için bilinmeyen değer: %s"
+
+#, c-format
msgid "%sinfo/refs not valid: is this a git repository?"
msgstr "%sinfo/refs geçerli değil: bu bir git deposu mu?"
@@ -19669,8 +19814,19 @@ msgid "resolve-undo records `%s` which is missing"
msgstr "resolve-undo, kayıp olan '%s' ögesini kaydetmiş"
#, c-format
-msgid "could not get commit for ancestry-path argument %s"
-msgstr "soy yolu argümanı %s için işleme alınamadı"
+msgid "%s exists but is a symbolic ref"
+msgstr "%s var; ancak bir sembolik baÄŸ"
+
+msgid ""
+"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD or REBASE_HEAD"
+msgstr ""
+"--merge; MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD veya REBASE_HEAD yalancı "
+"başvurularından birini gerektiriyor"
+
+#, c-format
+msgid "could not get commit for --ancestry-path argument %s"
+msgstr "--ancestry-path argümanı %s için olan işleme alınamadı"
msgid "--unpacked=<packfile> no longer supported"
msgstr "--unpacked=<paketdosyası> artık desteklenmiyor"
@@ -19955,6 +20111,19 @@ msgid "unknown action: %d"
msgstr "bilinmeyen eylem: %d"
msgid ""
+"Resolve all conflicts manually, mark them as resolved with\n"
+"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
+"You can instead skip this commit: run \"git rebase --skip\".\n"
+"To abort and get back to the state before \"git rebase\", run \"git rebase --"
+"abort\"."
+msgstr ""
+"Tüm çakışmaları el ile çözün, onları \"git add/rm <çakışan-dosyalar>\"\n"
+"ile tamam olarak imleyin, ardından \"git rebase --continue\"\n"
+"çalıştırın. Bunun yerine bu işlemeyi atlayabilirsiniz: \"git rebase\n"
+"--skip\" yapın. İptal edip \"git rebase\" öncesine geri dönmek için\n"
+"\"git rebase --abort\" çalıştırın."
+
+msgid ""
"after resolving the conflicts, mark the corrected paths\n"
"with 'git add <paths>' or 'git rm <paths>'"
msgstr ""
@@ -20174,10 +20343,6 @@ msgid "could not update %s"
msgstr "%s güncellenemedi"
#, c-format
-msgid "could not parse commit %s"
-msgstr "%s işlemesi ayrıştırılamadı"
-
-#, c-format
msgid "could not parse parent commit %s"
msgstr "üst işleme %s ayrıştırılamadı"
@@ -20282,10 +20447,6 @@ msgid "invalid command '%.*s'"
msgstr "geçersiz komut %.*s"
#, c-format
-msgid "%s does not accept arguments: '%s'"
-msgstr "%s argüman kabul etmiyor: '%s'"
-
-#, c-format
msgid "missing arguments for %s"
msgstr "%s için eksik argüman"
@@ -20737,6 +20898,10 @@ msgid "unable to set up work tree using invalid config"
msgstr "geçersiz yapılandırma kullanılarak çalışma ağacı kurulamıyor"
#, c-format
+msgid "'%s' already specified as '%s'"
+msgstr "'%s', halihazırda '%s' olarak belirtilmiş"
+
+#, c-format
msgid "Expected git repo version <= %d, found %d"
msgstr "Beklenen git repo sürümü <= %d, %d bulundu"
@@ -20926,6 +21091,21 @@ msgstr "indeks girdisi bir dizin; ancak aralıklı değil (%08x)"
msgid "cannot use split index with a sparse index"
msgstr "bir aralıklı indeksle bölünmüş indeks kullanılamıyor"
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not start with '('"
+msgstr "hatalı %s biçimi: '%s' ögesi '(' ile başlamıyor"
+
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not end in ')'"
+msgstr "hatalı %s biçimi: '%s' ögesi ')' ile sonlanmıyor"
+
+#. TRANSLATORS: %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: %%%.*s"
+msgstr "hatalı %s biçimi: %%%.*s"
+
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#, c-format
msgid "%u.%2.2u GiB"
@@ -21248,29 +21428,6 @@ msgstr "bilinmeyen değer '%s' ('%s' anahtarı için)"
msgid "empty trailer token in trailer '%.*s'"
msgstr "'%.*s' artbilgisi içinde boş artbilgi jetonu"
-#, c-format
-msgid "could not read input file '%s'"
-msgstr "'%s' girdi dosyası okunamadı"
-
-#, c-format
-msgid "could not stat %s"
-msgstr "%s dosya bilgileri alınamadı"
-
-#, c-format
-msgid "file %s is not a regular file"
-msgstr "%s dosyası sıradan bir dosya değil"
-
-#, c-format
-msgid "file %s is not writable by user"
-msgstr "%s dosyası kullanıcı tarafından yazılabilir değil"
-
-msgid "could not open temporary file"
-msgstr "geçici dosya açılamadı"
-
-#, c-format
-msgid "could not rename temporary file to %s"
-msgstr "geçici dosya adı %s olarak değiştirilemedi"
-
msgid "full write to remote helper failed"
msgstr "uzak konum yardımcısına tam yazım başarısız"
@@ -21366,8 +21523,8 @@ msgid "remote-helper doesn't support push; refspec needed"
msgstr "remote-helper itme desteklemiyor; baÅŸvuru belirteci gerekli"
#, c-format
-msgid "helper %s does not support 'force'"
-msgstr "%s yardımcısı 'force' desteklemiyor"
+msgid "helper %s does not support '--force'"
+msgstr "%s yardımcısı '--force' desteklemiyor"
msgid "couldn't run fast-export"
msgstr "fast-export çalıştırılamadı"
@@ -21780,6 +21937,10 @@ msgstr "geçersiz kapı numarası"
msgid "invalid '..' path segment"
msgstr "geçersiz '..' yol kesimi"
+#, c-format
+msgid "error: unable to format message: %s\n"
+msgstr "hata: ileti biçimlendirilemiyor: %s\n"
+
msgid "usage: "
msgstr "kullanım: "
diff --git a/po/uk.po b/po/uk.po
index 0507e387ba..528a3dc6f7 100644
--- a/po/uk.po
+++ b/po/uk.po
@@ -6,10 +6,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Git v2.43\n"
+"Project-Id-Version: Git v2.45\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2023-11-09 14:26-0800\n"
-"PO-Revision-Date: 2024-02-11 09:26-0800\n"
+"POT-Creation-Date: 2024-04-27 09:55-0700\n"
+"PO-Revision-Date: 2024-04-15 15:55-0700\n"
"Last-Translator: Arkadii Yakovets <ark@cho.red>\n"
"Language-Team: Ukrainian <https://github.com/arkid15r/git-uk-l10n/>\n"
"Language: uk\n"
@@ -496,12 +496,12 @@ msgid ""
"---\n"
"To remove '%c' lines, make them ' ' lines (context).\n"
"To remove '%c' lines, delete them.\n"
-"Lines starting with %c will be removed.\n"
+"Lines starting with %s will be removed.\n"
msgstr ""
"---\n"
"Щоб видалити Ñ€Ñдки \"%c\", зробіть Ñ—Ñ… Ñ€Ñдками \" \" (контекÑÑ‚).\n"
"Щоб видалити Ñ€Ñдки \"%c\", вилучіть Ñ—Ñ….\n"
-"Буде видалено Ñ€Ñдки, що починаютьÑÑ Ð· %c.\n"
+"РÑдки, що починаютьÑÑ Ð· %s, будуть видалені.\n"
msgid ""
"If it does not apply cleanly, you will be given an opportunity to\n"
@@ -549,6 +549,7 @@ msgid ""
"/ - search for a hunk matching the given regex\n"
"s - split the current hunk into smaller hunks\n"
"e - manually edit the current hunk\n"
+"p - print the current hunk\n"
"? - print help\n"
msgstr ""
"j - залишити цей шматок невизначеним, перейти до наÑтупного невизначеного "
@@ -561,6 +562,7 @@ msgstr ""
"/ - шукати шматок, що відповідає заданому регвиру\n"
"s - розбити поточний шматок на менші шматки\n"
"e - редагувати поточний шматок вручну\n"
+"p - показати поточний шматок\n"
"? - показати довідку\n"
msgid "No previous hunk"
@@ -624,8 +626,8 @@ msgstr ""
"Вимкнути це Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶Ð½Ð° за допомогою \"git config advice.%s false\""
#, c-format
-msgid "%shint: %.*s%s\n"
-msgstr "%sпідказка: %.*s%s\n"
+msgid "%shint:%s%.*s%s\n"
+msgstr "%sпідказка:%s%.*s%s\n"
msgid "Cherry-picking is not possible because you have unmerged files."
msgstr "ВиÑÐ¼Ð¸ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ðµ, оÑкільки у Ð²Ð°Ñ Ñ” не злиті файли."
@@ -1138,10 +1140,6 @@ msgstr[1] "ЗаÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð°Ñ‚ÐºÐ¸ %%s з %d відкиданнÑмÐ
msgstr[2] "ЗаÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ð°Ñ‚ÐºÐ¸ %%s з %d відкиданнÑми..."
#, c-format
-msgid "truncating .rej filename to %.*s.rej"
-msgstr "ÑÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð½Ð°Ð·Ð²Ð¸ файлу .rej до %.*s.rej"
-
-#, c-format
msgid "cannot open %s"
msgstr "неможливо відкрити %s"
@@ -1570,6 +1568,10 @@ msgid "could not create file '%s'"
msgstr "не вдалоÑÑ Ñтворити файл \"%s\""
#, c-format
+msgid "unable to start 'show' for object '%s'"
+msgstr "не вдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити \"show\" Ð´Ð»Ñ Ð¾Ð±â€™Ñ”ÐºÑ‚Ð° \"%s\""
+
+#, c-format
msgid "could not read file '%s'"
msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ файл \"%s\""
@@ -1722,6 +1724,9 @@ msgstr ""
msgid "'%s' is not a valid branch name"
msgstr "\"%s\" не Ñ” допуÑтимою назвою гілки"
+msgid "See `man git check-ref-format`"
+msgstr "ДивітьÑÑ \"man git check-ref-format\""
+
#, c-format
msgid "a branch named '%s' already exists"
msgstr "гілка з ім’Ñм \"%s\" вже Ñ–Ñнує"
@@ -1918,14 +1923,8 @@ msgstr ""
msgid "adding embedded git repository: %s"
msgstr "Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ð±ÑƒÐ´Ð¾Ð²Ð°Ð½Ð¾Ð³Ð¾ git Ñховища: %s"
-msgid ""
-"Use -f if you really want to add them.\n"
-"Turn this message off by running\n"
-"\"git config advice.addIgnoredFile false\""
-msgstr ""
-"ВикориÑтовуйте -f, Ñкщо ви дійÑно хочете Ñ—Ñ… додати.\n"
-"Щоб вимкнути це повідомленнÑ, виконайте\n"
-"\"git config advice.addIgnoredFile false\""
+msgid "Use -f if you really want to add them."
+msgstr "СкориÑтайтеÑÑŒ -f, Ñкщо ви дійÑно хочете Ñ—Ñ… додати."
msgid "adding files failed"
msgstr "Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² завершилоÑÑ Ð½ÐµÐ²Ð´Ð°Ð»Ð¾"
@@ -1942,14 +1941,8 @@ msgstr "\"%s\" та аргументи визначника шлÑху не мо
msgid "Nothing specified, nothing added.\n"
msgstr "Ðічого не зазначено, нічого не додано.\n"
-msgid ""
-"Maybe you wanted to say 'git add .'?\n"
-"Turn this message off by running\n"
-"\"git config advice.addEmptyPathspec false\""
-msgstr ""
-"Можливо, ви хотіли вказати \"git add .\"?\n"
-"Щоб вимкнути це повідомленнÑ, виконайте\n"
-"\"git config advice.addEmptyPathspec false\""
+msgid "Maybe you wanted to say 'git add .'?"
+msgstr "Можливо, ви хотіли вказати \"git add .\"?"
msgid "index file corrupt"
msgstr "індекÑний файл пошкоджено"
@@ -2026,18 +2019,20 @@ msgid "Failed to split patches."
msgstr "Ðе вдалоÑÑ Ñ€Ð¾Ð·Ñ‰ÐµÐ¿Ð¸Ñ‚Ð¸ латки."
#, c-format
-msgid "When you have resolved this problem, run \"%s --continue\"."
-msgstr "Коли ви вирішите цю проблему, виконайте \"%s --continue\"."
+msgid "When you have resolved this problem, run \"%s --continue\".\n"
+msgstr "Коли ви вирішите цю проблему, виконайте \"%s --continue\".\n"
#, c-format
-msgid "If you prefer to skip this patch, run \"%s --skip\" instead."
+msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n"
msgstr ""
-"Якщо ви бажаєте пропуÑтити цю латку, виконайте \"%s --skip\" заміÑÑ‚ÑŒ цього."
+"Якщо ви бажаєте пропуÑтити цю латку, виконайте \"%s --skip\" заміÑÑ‚ÑŒ цього.\n"
#, c-format
-msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"."
+msgid ""
+"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"
msgstr ""
-"Щоб запиÑати порожню латку Ñк порожній коміт, виконайте \"%s --allow-empty\"."
+"Щоб запиÑати порожню латку Ñк порожній коміт, виконайте \"%s --allow-"
+"empty\".\n"
#, c-format
msgid "To restore the original branch and stop patching, run \"%s --abort\"."
@@ -2905,11 +2900,11 @@ msgstr "гілку Ñкопійовано, але не вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸
msgid ""
"Please edit the description for the branch\n"
" %s\n"
-"Lines starting with '%c' will be stripped.\n"
+"Lines starting with '%s' will be stripped.\n"
msgstr ""
"Будь лаÑка, відредагуйте Ð¾Ð¿Ð¸Ñ Ð³Ñ–Ð»ÐºÐ¸\n"
" %s\n"
-"РÑдки, що починаютьÑÑ Ð· \"%c\", будуть вилучені.\n"
+"РÑдки, що починаютьÑÑ Ð· \"%s\", будуть вилучені.\n"
msgid "Generic options"
msgstr "Загальні опції"
@@ -3112,10 +3107,12 @@ msgid "not run from a git repository - no hooks to show\n"
msgstr "запущено не з git Ñховища - немає гачків Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ\n"
msgid ""
-"git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"git bugreport [(-o | --output-directory) <path>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
" [--diagnose[=<mode>]]"
msgstr ""
-"git bugreport [(-o | --output-directory) <шлÑÑ…>] [(-s | --suffix) <формат>]\n"
+"git bugreport [(-o | --output-directory) <шлÑÑ…>]\n"
+" [(-s | --suffix) <формат> | --no-suffix]\n"
" [--diagnose[=<режим>]]"
msgid ""
@@ -3603,6 +3600,10 @@ msgstr ""
msgid "path '%s' is unmerged"
msgstr "шлÑÑ… '%s' не злитий"
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ дерево (%s)"
+
msgid "you need to resolve your current index first"
msgstr "Ñпочатку потрібно розібратиÑÑŒ з вашим поточним індекÑом"
@@ -3845,6 +3846,10 @@ msgstr "Ðеможливо переключити гілку на не коміÑ
msgid "missing branch or commit argument"
msgstr "відÑÑƒÑ‚Ð½Ñ Ð³Ñ–Ð»ÐºÐ° або коміт"
+#, c-format
+msgid "unknown conflict style '%s'"
+msgstr "невідомий Ñтиль конфлікту \"%s\""
+
msgid "perform a 3-way merge with the new branch"
msgstr "здійÑнити 3-Ñтороннє Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð· новою гілкою"
@@ -4101,19 +4106,9 @@ msgstr "видалити також ігноровані файли"
msgid "remove only ignored files"
msgstr "видалити лише ігноровані файли"
-msgid ""
-"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to "
-"clean"
+msgid "clean.requireForce is true and -f not given: refusing to clean"
msgstr ""
-"clean.requireForce вÑтановлено у true Ñ– не задано ні -i, ні -n, ні -f; "
-"відмовлено в прибиранні"
-
-msgid ""
-"clean.requireForce defaults to true and neither -i, -n, nor -f given; "
-"refusing to clean"
-msgstr ""
-"clean.requireForce вÑтановлено у true за замовчуваннÑм Ñ– не задано ні -i, ні "
-"-n, ні -f; відмовлено в прибиранні"
+"clean.requireForce вÑтановлено у true Ñ– -f не задано: відмовлено в прибиранні"
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<опції>] [--] <Ñховище> [<директоріÑ>]"
@@ -4127,8 +4122,8 @@ msgstr "не переходити на гілку"
msgid "create a bare repository"
msgstr "Ñтворити порожнє Ñховище"
-msgid "create a mirror repository (implies bare)"
-msgstr "Ñтворити дзеркальне Ñховище (включає опцію bare)"
+msgid "create a mirror repository (implies --bare)"
+msgstr "Ñтворити дзеркальне Ñховище (включає опцію --bare)"
msgid "to clone from a local repository"
msgstr "клонувати з локального Ñховища"
@@ -4448,6 +4443,10 @@ msgstr "відÑтуп по правому краю"
msgid "padding space between columns"
msgstr "відÑтуп між Ñтовпчиками"
+#, c-format
+msgid "%s must be non-negative"
+msgstr "%s має бути невідʼємним значеннÑм"
+
msgid "--command must be the first argument"
msgstr "--command має бути першим аргументом"
@@ -4761,35 +4760,35 @@ msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати шаблон комітів"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored.\n"
+"with '%s' will be ignored.\n"
msgstr ""
"Будь лаÑка, введіть Ð´Ð¾Ð¿Ð¸Ñ Ð´Ð¾ коміту Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… змін. РÑдки, що починаютьÑÑ Ð·\n"
-" \"%c\" будуть проігноровані.\n"
+" \"%s\" будуть проігноровані.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored, and an empty message aborts the commit.\n"
+"with '%s' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
"Будь лаÑка, введіть Ð´Ð¾Ð¿Ð¸Ñ Ð´Ð¾ коміту Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… змін. РÑдки, що починаютьÑÑ Ð·\n"
-" \"%c\" будуть проігноровані, а порожній Ð´Ð¾Ð¿Ð¸Ñ Ð¿ÐµÑ€ÐµÑ€Ð²Ðµ коміт.\n"
+" \"%s\" будуть проігноровані, а порожній Ð´Ð¾Ð¿Ð¸Ñ Ð¿ÐµÑ€ÐµÑ€Ð²Ðµ коміт.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
msgstr ""
"Будь лаÑка, введіть Ð´Ð¾Ð¿Ð¸Ñ Ð´Ð¾ коміту Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… змін. РÑдки, що починаютьÑÑ Ð·\n"
-" \"%c\" будуть збережені; ви можете вилучити Ñ—Ñ… ÑамоÑтійно, Ñкщо захочете.\n"
+" \"%s\" будуть збережені; ви можете вилучити Ñ—Ñ… ÑамоÑтійно, Ñкщо захочете.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
"Будь лаÑка, введіть Ð´Ð¾Ð¿Ð¸Ñ Ð´Ð¾ коміту Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… змін. РÑдки, що починаютьÑÑ Ð·\n"
-" \"%c\" будуть збережені; ви можете вилучити Ñ—Ñ… ÑамоÑтійно, Ñкщо захочете.\n"
+" \"%s\" будуть збережені; ви можете вилучити Ñ—Ñ… ÑамоÑтійно, Ñкщо захочете.\n"
"Порожній Ð´Ð¾Ð¿Ð¸Ñ Ð¿ÐµÑ€ÐµÑ€Ð¸Ð²Ð°Ñ” коміт.\n"
msgid ""
@@ -5235,6 +5234,10 @@ msgid "with --get, use default value when missing entry"
msgstr ""
"з --get викориÑтовувати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм, Ñкщо Ð·Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´Ñутній"
+msgid "human-readable comment string (# will be prepended as needed)"
+msgstr ""
+"зрозумілий Ð´Ð»Ñ Ð»ÑŽÐ´Ð¸Ð½Ð¸ Ñ€Ñдок ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ (# буде додано перед за потребою)"
+
#, c-format
msgid "wrong number of arguments, should be %d"
msgstr "невірна кількіÑÑ‚ÑŒ аргументів, має бути %d"
@@ -5329,6 +5332,9 @@ msgstr ""
msgid "--default is only applicable to --get"
msgstr "--default заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ до --get"
+msgid "--comment is only applicable to add/set/replace operations"
+msgstr "--comment заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ до add/set/replace операцій"
+
msgid "--fixed-value only applies with 'value-pattern'"
msgstr "--fixed-value заÑтоÑовуєтьÑÑ Ð»Ð¸ÑˆÐµ з \"шаблоном-значеннÑ\""
@@ -6179,6 +6185,9 @@ msgstr "виводити тільки Ñ‚Ñ– поÑиланнÑ, що не міÑÑ
msgid "read reference patterns from stdin"
msgstr "читати шаблони поÑилань з stdin"
+msgid "also include HEAD ref and pseudorefs"
+msgstr "також включити HEAD та пÑевдопоÑиланнÑ"
+
msgid "unknown arguments supplied with --stdin"
msgstr "невідомі аргументи надані через --stdin"
@@ -6799,10 +6808,6 @@ msgid "no threads support, ignoring %s"
msgstr "немає підтримки потоків, Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ %s"
#, c-format
-msgid "unable to read tree (%s)"
-msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ дерево (%s)"
-
-#, c-format
msgid "unable to read tree %s"
msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ дерево %s"
@@ -7412,7 +7417,7 @@ msgstr "--separate-git-dir неÑуміÑна з порожнім Ñховище
msgid ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n"
+" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
" [--parse] [<file>...]"
msgstr ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
@@ -7420,6 +7425,32 @@ msgstr ""
"<аліаÑКлюча>[(=|:)<значеннÑ>])...]\n"
" [--parse] [<файл>...]"
+#, c-format
+msgid "could not stat %s"
+msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ stat Ð´Ð»Ñ %s"
+
+#, c-format
+msgid "file %s is not a regular file"
+msgstr "файл %s не є звичайним файлом"
+
+#, c-format
+msgid "file %s is not writable by user"
+msgstr "файл %s не доÑтупний Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу кориÑтувачем"
+
+msgid "could not open temporary file"
+msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ тимчаÑовий файл"
+
+#, c-format
+msgid "could not read input file '%s'"
+msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ вхідний файл \"%s\""
+
+msgid "could not read from stdin"
+msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ з stdin"
+
+#, c-format
+msgid "could not rename temporary file to %s"
+msgstr "не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ñ‚Ð¸ тимчаÑовий файл на %s"
+
msgid "edit files in place"
msgstr "редагувати файли на міÑцÑÑ…"
@@ -7813,18 +7844,6 @@ msgstr ""
msgid "could not get object info about '%s'"
msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ інформацію про обʼєкт \"%s\""
-#, c-format
-msgid "bad ls-files format: element '%s' does not start with '('"
-msgstr "невірний ls-files формат: елемент \"%s\" не починаєтьÑÑ Ð· \"(\""
-
-#, c-format
-msgid "bad ls-files format: element '%s' does not end in ')'"
-msgstr "невірний ls-files формат: елемент \"%s\" не закінчуєтьÑÑ Ð½Ð° \")\""
-
-#, c-format
-msgid "bad ls-files format: %%%.*s"
-msgstr "невірний ls-files формат: %%%.*s"
-
msgid "git ls-files [<options>] [<file>...]"
msgstr "git ls-files [<опції>] [<файл>...]"
@@ -7956,18 +7975,6 @@ msgstr "показувати базове поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° додаток
msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
msgstr "git ls-tree [<опції>] <деревоподібне-джерело> [<шлÑÑ…>...]"
-#, c-format
-msgid "bad ls-tree format: element '%s' does not start with '('"
-msgstr "невірний формат ls-tree: елемент \"%s\" не починаєтьÑÑ Ð· \"(\""
-
-#, c-format
-msgid "bad ls-tree format: element '%s' does not end in ')'"
-msgstr "невірний формат ls-tree: елемент \"%s\" не закінчуєтьÑÑ Ð½Ð° \")\""
-
-#, c-format
-msgid "bad ls-tree format: %%%.*s"
-msgstr "невірний формат ls-tree: %%%.*s"
-
msgid "only show trees"
msgstr "показувати тільки дерева"
@@ -8157,6 +8164,11 @@ msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ð²Ê¼Ñзати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\""
msgid "Merging %s with %s\n"
msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ %s з %s\n"
+# c-format
+#, c-format
+msgid "could not parse as tree '%s'"
+msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ дерево з \"%s\""
+
msgid "not something we can merge"
msgstr "не те, що ми в змозі об’єднати"
@@ -8359,10 +8371,10 @@ msgstr "Порожній Ð´Ð¾Ð¿Ð¸Ñ Ð¿ÐµÑ€ÐµÑ€Ð²Ðµ Ð¿Ñ€Ð¾Ñ†ÐµÑ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ.\n"
#, c-format
msgid ""
-"Lines starting with '%c' will be ignored, and an empty message aborts\n"
+"Lines starting with '%s' will be ignored, and an empty message aborts\n"
"the commit.\n"
msgstr ""
-"РÑдки, що починаютьÑÑ Ð· \"%c\", будуть проігноровані, а порожній Ð´Ð¾Ð¿Ð¸Ñ "
+"РÑдки, що починаютьÑÑ Ð· \"%s\", будуть проігноровані, а порожній Ð´Ð¾Ð¿Ð¸Ñ "
"перерве\n"
"Ð¿Ñ€Ð¾Ñ†ÐµÑ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ.\n"
@@ -8523,9 +8535,6 @@ msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ тегований об’єкт
msgid "object '%s' tagged as '%s', but is a '%s' type"
msgstr "об’єкт \"%s\", позначений Ñк \"%s\", але має тип \"%s\""
-msgid "could not read from stdin"
-msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ з stdin"
-
msgid "tag on stdin did not pass our strict fsck check"
msgstr "тег з stdin не пройшов нашу Ñувору перевірку fsck"
@@ -8789,10 +8798,6 @@ msgstr "git notes prune [<опції>]"
msgid "Write/edit the notes for the following object:"
msgstr "ЗапиÑати/відредагувати нотатки Ð´Ð»Ñ Ð½Ð°Ñтупного обʼєкта:"
-#, c-format
-msgid "unable to start 'show' for object '%s'"
-msgstr "не вдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити \"show\" Ð´Ð»Ñ Ð¾Ð±â€™Ñ”ÐºÑ‚Ð° \"%s\""
-
msgid "could not read 'show' output"
msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ вивід \"show\""
@@ -9421,10 +9426,11 @@ msgid "refusing to run without --i-still-use-this"
msgstr "відмовлено в запуÑку без --i-still-use-this"
msgid ""
-"git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude "
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
"<pattern>]"
msgstr ""
-"git pack-refs [--all] [--no-prune] [--include <шаблон>] [--exclude <шаблон>]"
+"git pack-refs [--all] [--no-prune] [--auto] [--include <шаблон>] [--exclude "
+"<шаблон>]"
msgid "pack everything"
msgstr "запакувати вÑе"
@@ -9432,6 +9438,9 @@ msgstr "запакувати вÑе"
msgid "prune loose refs (default)"
msgstr "видалити вивільнені поÑÐ¸Ð»Ð°Ð½Ð½Ñ (за замовчуваннÑм)"
+msgid "auto-pack refs as needed"
+msgstr "Ð°Ð²Ñ‚Ð¾Ð¿Ð°ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñилань за потреби"
+
msgid "references to include"
msgstr "поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð²ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ"
@@ -10103,21 +10112,6 @@ msgstr "Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð½ÐµÐ¿Ñ€Ð¸Ð¿ÑƒÑтимого allow_rerere_autoupd
msgid "could not remove '%s'"
msgstr "не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ \"%s\""
-msgid ""
-"Resolve all conflicts manually, mark them as resolved with\n"
-"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
-"You can instead skip this commit: run \"git rebase --skip\".\n"
-"To abort and get back to the state before \"git rebase\", run \"git rebase --"
-"abort\"."
-msgstr ""
-"Вирішіть уÑÑ– конфлікти вручну, позначте Ñ—Ñ… Ñк вирішені за допомогою\n"
-"\"git add/rm <конфліктні_файли>\", а потім виконайте \"git rebase --"
-"continue\".\n"
-"ЗаміÑÑ‚ÑŒ цього ви можете пропуÑтити цей коміт: виконайте \"git rebase --"
-"skip\".\n"
-"Щоб перервати Ð¿Ñ€Ð¾Ñ†ÐµÑ Ñ– повернутиÑÑ Ð´Ð¾ Ñтану перед \"git rebase\", виконайте "
-"\"git rebase --abort\"."
-
#, c-format
msgid ""
"\n"
@@ -10147,13 +10141,16 @@ msgstr "не вдалоÑÑ Ð¿ÐµÑ€ÐµÐºÐ»ÑŽÑ‡Ð¸Ñ‚Ð¸ÑÑŒ на %s"
msgid "apply options and merge options cannot be used together"
msgstr "apply опції не можна викориÑтовувати разом з merge опціÑми"
+msgid "--empty=ask is deprecated; use '--empty=stop' instead."
+msgstr "--empty=ask заÑтаріло; викориÑтовуйте \"--empty=stop\" заміÑÑ‚ÑŒ цього."
+
#, c-format
msgid ""
"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
-"\"ask\"."
+"\"stop\"."
msgstr ""
"нерозпізнаний порожній тип \"%s\"; припуÑтимими значеннÑми Ñ” \"drop\", "
-"\"keep\" та \"ask\"."
+"\"keep\" та \"stop\"."
msgid ""
"--rebase-merges with an empty string argument is deprecated and will stop "
@@ -10341,8 +10338,8 @@ msgstr ""
"Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ \"preserve\",\n"
"Ñкий більше не підтримуєтьÑÑ; натоміÑÑ‚ÑŒ викориÑтовуйте \"merges\""
-msgid "No rebase in progress?"
-msgstr "ÐŸÐµÑ€ÐµÐ±Ð°Ð·ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ відбуваєтьÑÑ?"
+msgid "no rebase in progress"
+msgstr "Ð¿ÐµÑ€ÐµÐ±Ð°Ð·ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ відбуваєтьÑÑ"
msgid "The --edit-todo action can only be used during interactive rebase."
msgstr ""
@@ -10540,6 +10537,9 @@ msgstr "необхідно вказати директорію"
msgid "git reflog [show] [<log-options>] [<ref>]"
msgstr "git reflog [show] [<лог-опції>] [<поÑиланнÑ>]"
+msgid "git reflog list"
+msgstr "git reflog list"
+
msgid ""
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
" [--rewrite] [--updateref] [--stale-fix]\n"
@@ -10565,6 +10565,10 @@ msgstr "git reflog exists <поÑиланнÑ>"
msgid "invalid timestamp '%s' given to '--%s'"
msgstr "неприпуÑтима позначка чаÑу \"%s\" передана до \"--%s\""
+#, c-format
+msgid "%s does not accept arguments: '%s'"
+msgstr "%s не приймає аргументів: \"%s\""
+
msgid "do not actually prune any entries"
msgstr "наÑправді не видалÑти жодного запиÑу"
@@ -10693,8 +10697,8 @@ msgstr ""
"\t ÑкориÑтайтеÑÑŒ --mirror=fetch або --mirror=push"
#, c-format
-msgid "unknown mirror argument: %s"
-msgstr "невідомий аргумент дзеркала: %s"
+msgid "unknown --mirror argument: %s"
+msgstr "невідомий --mirror аргумент: %s"
msgid "fetch the remote branches"
msgstr "отримати віддалені гілки"
@@ -11070,6 +11074,9 @@ msgstr ""
msgid "could not start pack-objects to repack promisor objects"
msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ð¿Ð¾Ñ‡Ð°Ñ‚Ð¸ pack-objects Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¿Ð°ÐºÑƒÐ²Ð°Ð½Ð½Ñ promisor обʼєктів"
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‚Ð¸ promisor обʼєкти обʼєктам пакунків"
+
msgid "repack: Expecting full hex object ID lines only from pack-objects."
msgstr ""
"перепакуваннÑ: очікуютьÑÑ Ð¿Ð¾Ð²Ð½Ñ– Ñ€Ñдки hex ідентифікаторів обʼєктів тільки "
@@ -11671,6 +11678,13 @@ msgstr "--default потребує аргументу"
msgid "--prefix requires an argument"
msgstr "--prefix потребує аргументу"
+msgid "no object format specified"
+msgstr "не зазначено формат обʼєкту"
+
+#, c-format
+msgid "unsupported object format: %s"
+msgstr "непідтримуваний формат обʼєкту: %s"
+
#, c-format
msgid "unknown mode for --abbrev-ref: %s"
msgstr "невідомий режим Ð´Ð»Ñ --abbrev-ref: %s"
@@ -11752,8 +11766,8 @@ msgstr "зберігати первинно порожні коміти"
msgid "allow commits with empty messages"
msgstr "дозволити коміти з порожніми допиÑами"
-msgid "keep redundant, empty commits"
-msgstr "зберігати зайві порожні коміти"
+msgid "deprecated: use --empty=keep instead"
+msgstr "заÑтаріле: викориÑтовуйте --empty=keep заміÑÑ‚ÑŒ цього"
msgid "use the 'reference' format to refer to commits"
msgstr "викориÑтовувати \"reference\" формат Ð´Ð»Ñ Ð¿Ð¾Ñилань на коміти"
@@ -13108,25 +13122,25 @@ msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be ignored.\n"
+"Lines starting with '%s' will be ignored.\n"
msgstr ""
"\n"
"Ðапишіть Ð´Ð¾Ð¿Ð¸Ñ Ð´Ð¾ тегу:\n"
" %s\n"
-"РÑдки, що починаютьÑÑ Ð· \"%c\", будуть проігноровані.\n"
+"РÑдки, що починаютьÑÑ Ð· \"%s\", будуть проігноровані.\n"
#, c-format
msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be kept; you may remove them yourself if you "
+"Lines starting with '%s' will be kept; you may remove them yourself if you "
"want to.\n"
msgstr ""
"\n"
"Ðапишіть Ð´Ð¾Ð¿Ð¸Ñ Ð´Ð¾ тегу:\n"
" %s\n"
-"РÑдки, що починаютьÑÑ Ð· \"%c\", будуть збережені; ви можете вилучити Ñ—Ñ… "
+"РÑдки, що починаютьÑÑ Ð· \"%s\", будуть збережені; ви можете вилучити Ñ—Ñ… "
"ÑамоÑтійно, Ñкщо захочете.\n"
msgid "unable to sign the tag"
@@ -13212,6 +13226,9 @@ msgstr "вивеÑти тільки не злиті теги"
msgid "print only tags of the object"
msgstr "вивеÑти тільки теги обʼєкта"
+msgid "could not start 'git column'"
+msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ \"git column\""
+
#, c-format
msgid "the '%s' option is only allowed in list mode"
msgstr "Ð¾Ð¿Ñ†Ñ–Ñ \"%s\" дозволена лише в режимі виводу"
@@ -13458,12 +13475,12 @@ msgstr ""
msgid "fsmonitor disabled"
msgstr "fsmonitor вимкнено"
-msgid "git update-ref [<options>] -d <refname> [<old-val>]"
-msgstr "git update-ref [<опції>] -d <назва поÑиланнÑ> [<Ñтаре значеннÑ>]"
+msgid "git update-ref [<options>] -d <refname> [<old-oid>]"
+msgstr "git update-ref [<опції>] -d <назва-поÑиланнÑ> [<Ñтарий-oid>]"
-msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]"
+msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]"
msgstr ""
-"git update-ref [<опції>] <назва-поÑиланнÑ> <нове-значеннÑ> [<Ñтаре-значеннÑ>]"
+"git update-ref [<опції>] <назва-поÑиланнÑ> <новий-oid> [<Ñтарий-oid>]"
msgid "git update-ref [<options>] --stdin [-z]"
msgstr "git update-ref [<опції>] --stdin [-z]"
@@ -14821,6 +14838,10 @@ msgid "Verifying commits in commit graph"
msgstr "Перевірка комітів у коміт-графі"
#, c-format
+msgid "could not parse commit %s"
+msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ коміт %s"
+
+#, c-format
msgid "%s %s is not a commit!"
msgstr "%s %s не є комітом!"
@@ -15251,8 +15272,13 @@ msgstr "довжина ÑÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ð·Ð° діапазоном: %d"
msgid "bad zlib compression level %d"
msgstr "невірний рівень zlib компреÑÑ–Ñ— %d"
-msgid "core.commentChar should only be one ASCII character"
-msgstr "core.commentChar має бути лише одним Ñимволом ASCII"
+#, c-format
+msgid "%s cannot contain newline"
+msgstr "%s не може міÑтити Ñимволи нового Ñ€Ñдка"
+
+#, c-format
+msgid "%s must have at least one character"
+msgstr "%s повинен мати принаймні один Ñимвол"
#, c-format
msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -15324,6 +15350,10 @@ msgid "failed to write new configuration file %s"
msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати новий конфігураційний файл %s"
#, c-format
+msgid "no multi-line comment allowed: '%s'"
+msgstr "багаторÑдкові коментарі не дозволÑÑŽÑ‚ÑŒÑÑ: \"%s\""
+
+#, c-format
msgid "could not lock config file %s"
msgstr "не вдалоÑÑ Ð·Ð°Ñ„Ñ–ÐºÑувати файл конфігурації %s"
@@ -15508,7 +15538,7 @@ msgstr "ssh Ð¾Ð¿Ñ†Ñ–Ñ \"simple\" не підтримує вÑтановленн
#, c-format
msgid "strange pathname '%s' blocked"
-msgstr "дивне Ñ–Ð¼Ê¼Ñ ÑˆÐ»Ñху \"%s\" заблоковано"
+msgstr "дивна назва шлÑху \"%s\" заблокована"
msgid "unable to fork"
msgstr "неможливо розгалужити"
@@ -17134,6 +17164,14 @@ msgid "Unable to create '%s.lock': %s"
msgstr "Ðе вдалоÑÑ Ñтворити \"%s.lock\": %s"
#, c-format
+msgid "could not write loose object index %s"
+msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати Ñ–Ð½Ð´ÐµÐºÑ Ð²Ñ–Ð»ÑŒÐ½Ð¾Ð³Ð¾ обʼєкта %s"
+
+#, c-format
+msgid "failed to write loose object index %s\n"
+msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати Ñ–Ð½Ð´ÐµÐºÑ Ð²Ñ–Ð»ÑŒÐ½Ð¾Ð³Ð¾ обʼєкта %s\n"
+
+#, c-format
msgid "unexpected line: '%s'"
msgstr "неочікуваний Ñ€Ñдок: \"%s\""
@@ -17144,6 +17182,10 @@ msgid "quoted CRLF detected"
msgstr "виÑвлено цитований CRLF"
#, c-format
+msgid "unable to format message: %s"
+msgstr "не вдалоÑÑ Ð²Ñ–Ð´Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚ÑƒÐ²Ð°Ñ‚Ð¸ допиÑ: %s"
+
+#, c-format
msgid "Failed to merge submodule %s (not checked out)"
msgstr "Ðе вдалоÑÑ Ð¾Ð±Ê¼Ñ”Ð´Ð½Ð°Ñ‚Ð¸ підмодуль %s (не активне)"
@@ -17156,6 +17198,10 @@ msgid "Failed to merge submodule %s (commits not present)"
msgstr "Ðе вдалоÑÑ Ð·Ð»Ð¸Ñ‚Ð¸ підмодуль %s (відÑутні коміти)"
#, c-format
+msgid "Failed to merge submodule %s (repository corrupt)"
+msgstr "Ðе вдалоÑÑ Ð¾Ð±Ê¼Ñ”Ð´Ð½Ð°Ñ‚Ð¸ підмодуль %s (Ñховище пошкоджено)"
+
+#, c-format
msgid "Failed to merge submodule %s (commits don't follow merge-base)"
msgstr "Ðе вдалоÑÑ Ð·Ð»Ð¸Ñ‚Ð¸ підмодуль %s (коміти не відповідають базі)"
@@ -17624,6 +17670,83 @@ msgstr "Ðе вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ обʼєкт \"%s\""
msgid "failed to read the cache"
msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ кеш"
+#, c-format
+msgid "failed to add packfile '%s'"
+msgstr "не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ packfile \"%s\""
+
+#, c-format
+msgid "failed to open pack-index '%s'"
+msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ pack-index \"%s\""
+
+#, c-format
+msgid "failed to locate object %d in packfile"
+msgstr "не вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ обʼєкт %d у packfile"
+
+msgid "cannot store reverse index file"
+msgstr "неможливо зберегти файл зворотнього індекÑу"
+
+#, c-format
+msgid "could not parse line: %s"
+msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ Ñ€Ñдок: %s"
+
+#, c-format
+msgid "malformed line: %s"
+msgstr "невірно Ñформований Ñ€Ñдок: %s"
+
+msgid "ignoring existing multi-pack-index; checksum mismatch"
+msgstr ""
+"Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ñнуючого multi-pack-index; невідповідніÑÑ‚ÑŒ контрольних Ñум"
+
+msgid "could not load pack"
+msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ пакунок"
+
+#, c-format
+msgid "could not open index for %s"
+msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ Ñ–Ð½Ð´ÐµÐºÑ Ð´Ð»Ñ %s"
+
+msgid "Adding packfiles to multi-pack-index"
+msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ð°ÐºÑƒÐ½ÐºÑ–Ð² до multi-pack-index"
+
+#, c-format
+msgid "unknown preferred pack: '%s'"
+msgstr "невідомий бажаний пакунок: \"%s\""
+
+#, c-format
+msgid "cannot select preferred pack %s with no objects"
+msgstr "неможливо вибрати бажаний пакунок %s за відÑутноÑÑ‚Ñ– об’єктів"
+
+#, c-format
+msgid "did not see pack-file %s to drop"
+msgstr "не знайдено файл пакунка %s Ð´Ð»Ñ ÑкиданнÑ"
+
+#, c-format
+msgid "preferred pack '%s' is expired"
+msgstr "у бажаного пакунка \"%s\" закінчивÑÑ Ñ‚ÐµÑ€Ð¼Ñ–Ð½ дії"
+
+msgid "no pack files to index."
+msgstr "немає файлів пакунків Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑації."
+
+msgid "refusing to write multi-pack .bitmap without any objects"
+msgstr "відмовлено в запиÑÑ– мультіпакункового .bitmap без обʼєктів"
+
+msgid "could not write multi-pack bitmap"
+msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати мультіпакунковий bitmap"
+
+msgid "could not write multi-pack-index"
+msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати multi-pack-index"
+
+msgid "Counting referenced objects"
+msgstr "Підрахунок обʼєктів, на Ñкі Ñ” поÑиланнÑ"
+
+msgid "Finding and deleting unreferenced packfiles"
+msgstr "Пошук Ñ– Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² пакунків без поÑилань"
+
+msgid "could not start pack-objects"
+msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ð¿Ð¾Ñ‡Ð°Ñ‚Ð¸ pack-objects"
+
+msgid "could not finish pack-objects"
+msgstr "не вдалоÑÑ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ñ‚Ð¸ pack-objects"
+
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "multi-pack-index OID розÑÑ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð¼Ð°Ñ” невірний розмір"
@@ -17699,71 +17822,6 @@ msgid "multi-pack-index large offset out of bounds"
msgstr "large offset multi-pack-index виходить за межі"
#, c-format
-msgid "failed to add packfile '%s'"
-msgstr "не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ packfile \"%s\""
-
-#, c-format
-msgid "failed to open pack-index '%s'"
-msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ pack-index \"%s\""
-
-#, c-format
-msgid "failed to locate object %d in packfile"
-msgstr "не вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ обʼєкт %d у файлі пакунка"
-
-msgid "cannot store reverse index file"
-msgstr "неможливо зберегти файл зворотнього індекÑу"
-
-#, c-format
-msgid "could not parse line: %s"
-msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ Ñ€Ñдок: %s"
-
-#, c-format
-msgid "malformed line: %s"
-msgstr "невірно Ñформований Ñ€Ñдок: %s"
-
-msgid "ignoring existing multi-pack-index; checksum mismatch"
-msgstr ""
-"Ñ–Ð³Ð½Ð¾Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ñнуючого multi-pack-index; невідповідніÑÑ‚ÑŒ контрольних Ñум"
-
-msgid "could not load pack"
-msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ пакет"
-
-#, c-format
-msgid "could not open index for %s"
-msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ Ñ–Ð½Ð´ÐµÐºÑ Ð´Ð»Ñ %s"
-
-msgid "Adding packfiles to multi-pack-index"
-msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð¿Ð°ÐºÑƒÐ½ÐºÑ–Ð² до multi-pack-index"
-
-#, c-format
-msgid "unknown preferred pack: '%s'"
-msgstr "невідомий бажаний пакунок: \"%s\""
-
-#, c-format
-msgid "cannot select preferred pack %s with no objects"
-msgstr "неможливо вибрати бажаний пакунок %s за відÑутноÑÑ‚Ñ– об’єктів"
-
-#, c-format
-msgid "did not see pack-file %s to drop"
-msgstr "не побачив файл пакунка %s, Ñкий потрібно Ñкинути"
-
-#, c-format
-msgid "preferred pack '%s' is expired"
-msgstr "у бажаного пакета \"%s\" закінчивÑÑ Ñ‚ÐµÑ€Ð¼Ñ–Ð½ дії"
-
-msgid "no pack files to index."
-msgstr "немає файлів пакунків Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑації."
-
-msgid "refusing to write multi-pack .bitmap without any objects"
-msgstr "відмовлено в запиÑÑ– мультіпакункового .bitmap без обʼєктів"
-
-msgid "could not write multi-pack bitmap"
-msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати мультіпакунковий bitmap"
-
-msgid "could not write multi-pack-index"
-msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати multi-pack-index"
-
-#, c-format
msgid "failed to clear multi-pack-index at %s"
msgstr "не вдалоÑÑ Ð¾Ñ‡Ð¸Ñтити multi-pack-index при %s"
@@ -17804,18 +17862,6 @@ msgstr "не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ Ñ–Ð½Ð´ÐµÐºÑ Ñ„Ð°Ð¹Ð»Ð° паÐ
msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>"
msgstr "невірне Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¾Ð±Ê¼Ñ”ÐºÑ‚Ð° Ð´Ð»Ñ oid[%d] = %s: %<PRIx64> != %<PRIx64>"
-msgid "Counting referenced objects"
-msgstr "Підрахунок обʼєктів, на Ñкі Ñ” поÑиланнÑ"
-
-msgid "Finding and deleting unreferenced packfiles"
-msgstr "Пошук Ñ– Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð² пакунків без поÑилань"
-
-msgid "could not start pack-objects"
-msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ð¿Ð¾Ñ‡Ð°Ñ‚Ð¸ pack-objects"
-
-msgid "could not finish pack-objects"
-msgstr "не вдалоÑÑ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ñ‚Ð¸ pack-objects"
-
#, c-format
msgid "unable to create lazy_dir thread: %s"
msgstr "не вдалоÑÑ Ñтворити lazy_dir потік: %s"
@@ -17862,6 +17908,25 @@ msgstr "Відмовлено в перезапиÑÑ– нотаток у %s (за
msgid "Bad %s value: '%s'"
msgstr "Ðевірне %s значеннÑ: \"%s\""
+msgid "failed to decode tree entry"
+msgstr "не вдалоÑÑ Ð´ÐµÐºÐ¾Ð´ÑƒÐ²Ð°Ñ‚Ð¸ Ð·Ð°Ð¿Ð¸Ñ Ð´ÐµÑ€ÐµÐ²Ð°"
+
+#, c-format
+msgid "failed to map tree entry for %s"
+msgstr "не вдалоÑÑ Ð·Ñ–Ñтавити Ð·Ð°Ð¿Ð¸Ñ Ñƒ дереві Ð´Ð»Ñ %s"
+
+#, c-format
+msgid "bad %s in commit"
+msgstr "невірній %s у коміті"
+
+#, c-format
+msgid "unable to map %s %s in commit object"
+msgstr "не вдалоÑÑ Ð·Ñ–Ñтавити %s %s в обʼєкті коміту"
+
+#, c-format
+msgid "Failed to convert object from %s to %s"
+msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€Ð¸Ñ‚Ð¸ обʼєкт з \"%s\" на \"%s\""
+
#, c-format
msgid "object directory %s does not exist; check .git/objects/info/alternates"
msgstr "Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ñ–Ñ Ð¾Ð±â€™Ñ”ÐºÑ‚Ð° %s не Ñ–Ñнує; перевірте .git/objects/info/alternates"
@@ -17965,6 +18030,10 @@ msgid "packed object %s (stored in %s) is corrupt"
msgstr "упакований обʼєкт %s (що зберігаєтьÑÑ Ñƒ %s) пошкоджено"
#, c-format
+msgid "missing mapping of %s to %s"
+msgstr "відÑутнє зіÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð½Ñ %s до %s"
+
+#, c-format
msgid "unable to write file %s"
msgstr "не вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати файл %s"
@@ -18018,6 +18087,10 @@ msgid "cannot read object for %s"
msgstr "неможливо прочитати обʼєкт Ð´Ð»Ñ %s"
#, c-format
+msgid "cannot map object %s to %s"
+msgstr "неможливо зіÑтавити обʼєкт %s з %s"
+
+#, c-format
msgid "object fails fsck: %s"
msgstr "об’єкт не пройшов перевірку fsck: %s"
@@ -18329,6 +18402,11 @@ msgstr ""
"не вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ пакунок: \"%s\", Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð³Ð¾ викориÑÑ‚Ð°Ð½Ð½Ñ "
"пакунків"
+msgid "unable to compute preferred pack, disabling pack-reuse"
+msgstr ""
+"не вдалоÑÑ Ð¾Ð±Ñ‡Ð¸Ñлити бажаний пакунок, Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð³Ð¾ викориÑÑ‚Ð°Ð½Ð½Ñ "
+"пакунків"
+
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "обʼєкт \"%s\" не знайдено в типах bitmap"
@@ -19391,6 +19469,79 @@ msgid "could not delete references: %s"
msgstr "не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ поÑиланнÑ: %s"
#, c-format
+msgid "refname is dangerous: %s"
+msgstr "refname є небезпечним: %s"
+
+#, c-format
+msgid "trying to write ref '%s' with nonexistent object %s"
+msgstr "Ñпроба запиÑати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\" з неіÑнуючим обʼєктом %s"
+
+#, c-format
+msgid "trying to write non-commit object %s to branch '%s'"
+msgstr "Ñпроба запиÑати не коміт обʼєкт %s у гілку \"%s\""
+
+#, c-format
+msgid ""
+"multiple updates for 'HEAD' (including one via its referent '%s') are not "
+"allowed"
+msgstr ""
+"багаторазові Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ \"HEAD\" (включаючи через поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð· \"%s\") не "
+"дозволені"
+
+#, c-format
+msgid "cannot lock ref '%s': unable to resolve reference '%s'"
+msgstr ""
+"неможливо зафікÑуваті поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": не вдалоÑÑŒ розвʼÑзати поÑÐ¸Ð»Ð°Ð½Ð½Ñ "
+"\"%s\""
+
+#, c-format
+msgid "cannot lock ref '%s': error reading reference"
+msgstr ""
+"неможливо зафікÑувати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": помилка при зчитуванні поÑиланнÑ"
+
+#, c-format
+msgid ""
+"multiple updates for '%s' (including one via symref '%s') are not allowed"
+msgstr ""
+"багаторазові Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ \"%s\" (включаючи Ñимвольні поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð· \"%s\") "
+"не дозволені"
+
+#, c-format
+msgid "cannot lock ref '%s': reference already exists"
+msgstr "неможливо зафікÑувати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð²Ð¶Ðµ Ñ–Ñнує"
+
+#, c-format
+msgid "cannot lock ref '%s': reference is missing but expected %s"
+msgstr ""
+"неможливо зафікÑувати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ñутнє, але очікуване %s"
+
+#, c-format
+msgid "cannot lock ref '%s': is at %s but expected %s"
+msgstr ""
+"неможливо зафікÑувати поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\": Ñтановить %s, але очікуєтьÑÑ %s"
+
+#, c-format
+msgid "reftable: transaction prepare: %s"
+msgstr "Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Ð¿Ð¾Ñилань: підготовка транзакції: \"%s\""
+
+#, c-format
+msgid "reftable: transaction failure: %s"
+msgstr "Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Ð¿Ð¾Ñилань: помилка транзакції: \"%s\""
+
+#, c-format
+msgid "unable to compact stack: %s"
+msgstr "не вдалоÑÑ ÑтиÑнути Ñтек: %s"
+
+#, c-format
+msgid "refname %s not found"
+msgstr "назва поÑÐ¸Ð»Ð°Ð½Ð½Ñ %s не знайдена"
+
+#, c-format
+msgid "refname %s is a symbolic ref, copying it is not supported"
+msgstr ""
+"назва поÑÐ¸Ð»Ð°Ð½Ð½Ñ %s Ñ” Ñимвольним поÑиланнÑм, ÐºÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ñкого не підтримуєтьÑÑ"
+
+#, c-format
msgid "invalid refspec '%s'"
msgstr "неприпуÑтимий визначник поÑÐ¸Ð»Ð°Ð½Ð½Ñ \"%s\""
@@ -19399,6 +19550,10 @@ msgid "invalid quoting in push-option value: '%s'"
msgstr "неприпуÑтимі лапки у значенні push-опції: \"%s\""
#, c-format
+msgid "unknown value for object-format: %s"
+msgstr "невідоме Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ object-format: %s"
+
+#, c-format
msgid "%sinfo/refs not valid: is this a git repository?"
msgstr "%sinfo/refs не дійÑні: це git Ñховище?"
@@ -19860,8 +20015,19 @@ msgid "resolve-undo records `%s` which is missing"
msgstr "resolve-undo запиÑує \"%s\", Ñкий відÑутній"
#, c-format
-msgid "could not get commit for ancestry-path argument %s"
-msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ коміт Ð´Ð»Ñ ancestry-path аргументу %s"
+msgid "%s exists but is a symbolic ref"
+msgstr "%s Ñ–Ñнує але Ñ” Ñимвольним поÑиланнÑм"
+
+msgid ""
+"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD or REBASE_HEAD"
+msgstr ""
+"--merge вимагає одне з пÑевдопоÑилань MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD або REBASE_HEAD"
+
+#, c-format
+msgid "could not get commit for --ancestry-path argument %s"
+msgstr "не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ коміт Ð´Ð»Ñ --ancestry-path аргументу %s"
msgid "--unpacked=<packfile> no longer supported"
msgstr "--unpacked=<файл пакунка> більше не підтримуєтьÑÑ"
@@ -20149,6 +20315,21 @@ msgid "unknown action: %d"
msgstr "невідома діÑ: %d"
msgid ""
+"Resolve all conflicts manually, mark them as resolved with\n"
+"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
+"You can instead skip this commit: run \"git rebase --skip\".\n"
+"To abort and get back to the state before \"git rebase\", run \"git rebase --"
+"abort\"."
+msgstr ""
+"Вирішіть уÑÑ– конфлікти вручну, позначте Ñ—Ñ… Ñк вирішені за допомогою\n"
+"\"git add/rm <конфліктні_файли>\", а потім виконайте \"git rebase --"
+"continue\".\n"
+"ЗаміÑÑ‚ÑŒ цього ви можете пропуÑтити цей коміт: виконайте \"git rebase --"
+"skip\".\n"
+"Щоб перервати Ð¿Ñ€Ð¾Ñ†ÐµÑ Ñ– повернутиÑÑ Ð´Ð¾ Ñтану перед \"git rebase\", виконайте "
+"\"git rebase --abort\"."
+
+msgid ""
"after resolving the conflicts, mark the corrected paths\n"
"with 'git add <paths>' or 'git rm <paths>'"
msgstr ""
@@ -20376,10 +20557,6 @@ msgid "could not update %s"
msgstr "не вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ %s"
#, c-format
-msgid "could not parse commit %s"
-msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ коміт %s"
-
-#, c-format
msgid "could not parse parent commit %s"
msgstr "не вдалоÑÑ Ñ€Ð¾Ð·Ñ–Ð±Ñ€Ð°Ñ‚Ð¸ джерельний коміт %s"
@@ -20484,10 +20661,6 @@ msgid "invalid command '%.*s'"
msgstr "неприпуÑтима команда \"%.*s\""
#, c-format
-msgid "%s does not accept arguments: '%s'"
-msgstr "%s не приймає аргументи: \"%s\""
-
-#, c-format
msgid "missing arguments for %s"
msgstr "відÑутні аргументи Ð´Ð»Ñ %s"
@@ -20945,6 +21118,10 @@ msgstr ""
"конфігурацію"
#, c-format
+msgid "'%s' already specified as '%s'"
+msgstr "\"%s\" вже зазначено Ñк \"%s\""
+
+#, c-format
msgid "Expected git repo version <= %d, found %d"
msgstr "ОчікувалоÑÑŒ git Ñховищe верÑÑ–Ñ— <= %d, знайдено %d"
@@ -21138,6 +21315,21 @@ msgstr "Ð·Ð°Ð¿Ð¸Ñ Ñ–Ð½Ð´ÐµÐºÑу Ñ” директорією, але не розÑ
msgid "cannot use split index with a sparse index"
msgstr "неможливо викориÑтовувати розділений Ñ–Ð½Ð´ÐµÐºÑ Ð· розрідженим індекÑом"
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not start with '('"
+msgstr "невірний формат %s: елемент \"%s\" не починаєтьÑÑ Ð· \"(\""
+
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not end in ')'"
+msgstr "невірний формат %s: елемент \"%s\" не закінчуєтьÑÑ Ð½Ð° \")\""
+
+#. TRANSLATORS: %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: %%%.*s"
+msgstr "невірний формат %s: %%%.*s"
+
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#, c-format
msgid "%u.%2.2u GiB"
@@ -21470,29 +21662,6 @@ msgstr "невідоме Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ \"%s\" Ð´Ð»Ñ ÐºÐ»ÑŽÑ‡Ð° \"%s\""
msgid "empty trailer token in trailer '%.*s'"
msgstr "порожній токен трейлера в трейлері \"%.*s\""
-#, c-format
-msgid "could not read input file '%s'"
-msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ вхідний файл \"%s\""
-
-#, c-format
-msgid "could not stat %s"
-msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ %s"
-
-#, c-format
-msgid "file %s is not a regular file"
-msgstr "файл %s не є звичайним файлом"
-
-#, c-format
-msgid "file %s is not writable by user"
-msgstr "файл %s не доÑтупний Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу кориÑтувачем"
-
-msgid "could not open temporary file"
-msgstr "не вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ тимчаÑовий файл"
-
-#, c-format
-msgid "could not rename temporary file to %s"
-msgstr "не вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¹Ð¼ÐµÐ½ÑƒÐ²Ð°Ñ‚Ð¸ тимчаÑовий файл на %s"
-
msgid "full write to remote helper failed"
msgstr "не вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ повний Ð·Ð°Ð¿Ð¸Ñ Ð´Ð¾ віддаленого помічника"
@@ -21588,8 +21757,8 @@ msgid "remote-helper doesn't support push; refspec needed"
msgstr "remote-helper не підтримує push; потрібен refspec"
#, c-format
-msgid "helper %s does not support 'force'"
-msgstr "помічник %s не підтримує \"force\""
+msgid "helper %s does not support '--force'"
+msgstr "помічник %s не підтримує \"--force\""
msgid "couldn't run fast-export"
msgstr "не вдалоÑÑ Ð·Ð°Ð¿ÑƒÑтити fast-export"
@@ -22012,6 +22181,10 @@ msgstr "неприпуÑтимий номер порту"
msgid "invalid '..' path segment"
msgstr "неприпуÑтимий \"..\" Ñегмент шлÑху"
+#, c-format
+msgid "error: unable to format message: %s\n"
+msgstr "помилка: не вдалоÑÑ Ð²Ñ–Ð´Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚ÑƒÐ²Ð°Ñ‚Ð¸ допиÑ: %s\n"
+
msgid "usage: "
msgstr "викориÑтаннÑ: "
diff --git a/po/vi.po b/po/vi.po
index d673745ac5..965e79e965 100644
--- a/po/vi.po
+++ b/po/vi.po
@@ -2,32 +2,33 @@
# Bản dịch tiếng Việt dành cho GIT-CORE.
# This file is distributed under the same license as the git-core package.
# https://raw.githubusercontent.com/git-l10n/git-po/pot/main/po/git.pot
+# Copyright (C) 2012-2022, Translation Project, Vietnamese Team <http://translationproject.org/team/vi.html>
+# Copyright (C) 2024, Vũ Tiến Hưng <newcomerminecraft@gmail.com>
# Nguyá»…n Thái Ngá»c Duy <pclouds@gmail.com>, 2012.
# Äoàn Trần Công Danh <congdanhqx@gmail.com>, 2020.
# Trần Ngá»c Quân <vnwildman@gmail.com>, 2012-2022.
+# Vũ Tiến Hưng <newcomerminecraft@gmail.com>, 2024.
#
msgid ""
msgstr ""
-"Project-Id-Version: git v2.37.0\n"
+"Project-Id-Version: git 2.45\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2022-06-21 20:20+0000\n"
-"PO-Revision-Date: 2022-06-25 08:37+0700\n"
-"Last-Translator: Trần Ngá»c Quân <vnwildman@gmail.com>\n"
-"Language-Team: Vietnamese <translation-team-vi@lists.sourceforge.net>\n"
+"POT-Creation-Date: 2024-04-25 18:57+0000\n"
+"PO-Revision-Date: 2024-04-28 14:01+0700\n"
+"Last-Translator: Vũ Tiến Hưng <newcomerminecraft@gmail.com>\n"
+"Language-Team: Vietnamese <https://github.com/Nekosha/git-po>\n"
"Language: vi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0\n"
-"X-Language-Team-Website: <http://translationproject.org/team/vi.html>\n"
-"X-Generator: Gtranslator 42.0\n"
#, c-format
msgid "Huh (%s)?"
msgstr "Hả (%s)?"
msgid "could not read index"
-msgstr "không thể Ä‘á»c bảng mục lục"
+msgstr "không thể Ä‘á»c chỉ mục"
msgid "binary"
msgstr "nhị phân"
@@ -43,31 +44,31 @@ msgstr "Cập nhật"
#, c-format
msgid "could not stage '%s'"
-msgstr "không thể đưa “%s†lên bệ phóng"
+msgstr "không thể đưa '%s' lên bệ phóng"
msgid "could not write index"
-msgstr "không thể ghi bảng mục lục"
+msgstr "không thể ghi chỉ mục"
-#, c-format, perl-format
+#, c-format
msgid "updated %d path\n"
msgid_plural "updated %d paths\n"
msgstr[0] "đã cập nhật %d Ä‘Æ°á»ng dẫn\n"
-#, c-format, perl-format
+#, c-format
msgid "note: %s is untracked now.\n"
-msgstr "chú ý: %s giỠđã bỠtheo dõi.\n"
+msgstr "chú ý: đã bỠtheo dõi %s.\n"
#, c-format
msgid "make_cache_entry failed for path '%s'"
-msgstr "make_cache_entry gặp lá»—i đối vá»›i Ä‘Æ°á»ng dẫn “%sâ€"
+msgstr "make_cache_entry gặp lá»—i đối vá»›i Ä‘Æ°á»ng dẫn '%s'"
msgid "Revert"
msgstr "Hoàn nguyên"
msgid "Could not parse HEAD^{tree}"
-msgstr "Không thể phân tích cú pháp HEAD^{tree}"
+msgstr "Không hiểu cú pháp HEAD^{tree}"
-#, c-format, perl-format
+#, c-format
msgid "reverted %d path\n"
msgid_plural "reverted %d paths\n"
msgstr[0] "đã hoàn nguyên %d Ä‘Æ°á»ng dẫn\n"
@@ -77,33 +78,33 @@ msgid "No untracked files.\n"
msgstr "Không có tập tin nào chưa được theo dõi.\n"
msgid "Add untracked"
-msgstr "Thêm các cái chưa được theo dõi"
+msgstr "Thêm các tập tin chưa được theo dõi"
-#, c-format, perl-format
+#, c-format
msgid "added %d path\n"
msgid_plural "added %d paths\n"
msgstr[0] "đã thêm %d Ä‘Æ°á»ng dẫn\n"
#, c-format
msgid "ignoring unmerged: %s"
-msgstr "bỠqua những thứ chưa hòa trộn: %s"
+msgstr "bỠqua những tập tin chưa hòa trộn: %s"
#, c-format
msgid "Only binary files changed.\n"
-msgstr "Chỉ có các tập tin nhị phân là thay đổi.\n"
+msgstr "Chỉ có các tập tin nhị phân thay đổi.\n"
#, c-format
msgid "No changes.\n"
msgstr "Không có thay đổi nào.\n"
msgid "Patch update"
-msgstr "Cập nhật miếng vá"
+msgstr "Cập nhật bản vá"
msgid "Review diff"
-msgstr "Xem xét lại diff"
+msgstr "Xem xét lại thay đổi"
msgid "show paths with changes"
-msgstr "hiển thị Ä‘Æ°á»ng dẫn vá»›i các thay đổi"
+msgstr "hiển thị các Ä‘Æ°á»ng dẫn có thay đổi"
msgid "add working tree state to the staged set of changes"
msgstr ""
@@ -116,10 +117,10 @@ msgstr ""
"bản HEAD"
msgid "pick hunks and update selectively"
-msgstr "chá»n các “khúc†và cập nhật có tuyển chá»n"
+msgstr "chá»n các khúc và cập nhật có lá»±a chá»n"
msgid "view diff between HEAD and index"
-msgstr "xem khác biệt giữa HEAD và mục lục"
+msgstr "xem khác biệt giữa HEAD và chỉ mục"
msgid "add contents of untracked files to the staged set of changes"
msgstr ""
@@ -139,7 +140,7 @@ msgid "select multiple ranges"
msgstr "chá»n nhiá»u vùng"
msgid "select item based on unique prefix"
-msgstr "chá»n mục dá»±a trên tiá»n tố duy nhất"
+msgstr "chá»n mục dá»±a trên tiá»n tố Ä‘á»™c nhất"
msgid "unselect specified items"
msgstr "bá» chá»n các mục đã cho"
@@ -151,7 +152,7 @@ msgid "(empty) finish selecting"
msgstr "(để trống) hoàn tất chá»n lá»±a"
msgid "select a numbered item"
-msgstr "tùy chá»n mục bằng số"
+msgstr "lá»±a chá»n mục bằng số"
msgid "(empty) select nothing"
msgstr "(để trống) không chá»n gì"
@@ -172,25 +173,25 @@ msgid "path"
msgstr "Ä‘Æ°á»ng-dẫn"
msgid "could not refresh index"
-msgstr "không thể Ä‘á»c lại bảng mục lục"
+msgstr "không thể Ä‘á»c lại chỉ mục"
#, c-format
msgid "Bye.\n"
msgstr "Tạm biệt.\n"
-#, c-format, perl-format
+#, c-format
msgid "Stage mode change [y,n,q,a,d%s,?]? "
-msgstr "Thay đổi chế độ bệ phóng [y,n,q,a,d%s,?]? "
+msgstr "ÄÆ°a lên bệ phóng thay đổi chế Ä‘á»™ [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Stage deletion [y,n,q,a,d%s,?]? "
-msgstr "Xóa khá»i bệ phóng [y,n,q,a,d%s,?]? "
+msgstr "ÄÆ°a lên bệ phóng thao tác xoá [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Stage addition [y,n,q,a,d%s,?]? "
-msgstr "Thêm vào bệ phóng [y,n,q,a,d%s,?]? "
+msgstr "ÄÆ°a lên bệ phóng thao tác thêm [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Stage this hunk [y,n,q,a,d%s,?]? "
msgstr "ÄÆ°a lên bệ phóng khúc này [y,n,q,a,d%s,?]? "
@@ -198,7 +199,7 @@ msgid ""
"If the patch applies cleanly, the edited hunk will immediately be marked for "
"staging."
msgstr ""
-"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sửa sẽ ngay lập tức được đánh dấu "
+"Nếu bản vá được áp dụng hoàn toàn, khúc đã sửa sẽ ngay lập tức được đánh dấu "
"để chuyển lên bệ phóng."
msgid ""
@@ -210,24 +211,23 @@ msgid ""
msgstr ""
"y - đưa lên bệ phóng khúc này\n"
"n - đừng đưa lên bệ phóng khúc này\n"
-"q - thoát; đừng đưa lên bệ phóng khúc này cũng như bất kỳ cái nào còn lại\n"
+"q - thoát; đừng đưa lên bệ phóng khúc này hay bất kỳ cái nào còn lại\n"
"a - đưa lên bệ phóng khúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng đưa lên bệ phóng khúc này cũng như bất kỳ cái nào còn lại trong tập "
-"tin\n"
+"d - đừng đưa lên bệ phóng khúc này hay bất kỳ cái nào còn lại trong tập tin\n"
-#, c-format, perl-format
+#, c-format
msgid "Stash mode change [y,n,q,a,d%s,?]? "
-msgstr "Thay đổi chế độ tạm cất đi [y,n,q,a,d%s,?]? "
+msgstr "Tạm cất thay đổi chế độ [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Stash deletion [y,n,q,a,d%s,?]? "
-msgstr "Xóa tạm cất [y,n,q,a,d%s,?]? "
+msgstr "Tạm cất thao tác xoá [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Stash addition [y,n,q,a,d%s,?]? "
-msgstr "Thêm vào tạm cất [y,n,q,a,d%s,?]? "
+msgstr "Tạm cất thao tác thêm [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Stash this hunk [y,n,q,a,d%s,?]? "
msgstr "Tạm cất khúc này [y,n,q,a,d%s,?]? "
@@ -235,7 +235,7 @@ msgid ""
"If the patch applies cleanly, the edited hunk will immediately be marked for "
"stashing."
msgstr ""
-"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sửa sẽ ngay lập tức được đánh dấu "
+"Nếu bản vá được áp dụng hoàn toàn, khúc đã sửa sẽ ngay lập tức được đánh dấu "
"để tạm cất."
msgid ""
@@ -247,23 +247,23 @@ msgid ""
msgstr ""
"y - tạm cất khúc này\n"
"n - đừng tạm cất khúc này\n"
-"q - thoát; đừng tạm cất khúc này cũng như bất kỳ cái nào còn lại\n"
+"q - thoát; đừng tạm cất khúc này hay bất kỳ cái nào còn lại\n"
"a - tạm cất khúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng tạm cất khúc này cũng như bất kỳ cái nào còn lại trong tập tin\n"
+"d - đừng tạm cất khúc này hay bất kỳ cái nào còn lại trong tập tin\n"
-#, c-format, perl-format
+#, c-format
msgid "Unstage mode change [y,n,q,a,d%s,?]? "
-msgstr "Thay đổi chế Ä‘á»™ bá» ra khá»i bệ phóng [y,n,q,a,d%s,?]? "
+msgstr "Bá» ra khá»i bệ phóng thay đổi chế Ä‘á»™ [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Unstage deletion [y,n,q,a,d%s,?]? "
-msgstr "Xóa bá» việc bá» ra khá»i bệ phóng [y,n,q,a,d%s,?]? "
+msgstr "Bá» ra khá»i bệ phóng thao tác xoá [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Unstage addition [y,n,q,a,d%s,?]? "
-msgstr "Thêm vào việc bá» ra khá»i bệ phóng [y,n,q,a,d%s,?]? "
+msgstr "Bá» ra khá»i bệ phóng thao tác thêm [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Unstage this hunk [y,n,q,a,d%s,?]? "
msgstr "Bá» ra khá»i bệ phóng khúc này [y,n,q,a,d%s,?]? "
@@ -271,7 +271,7 @@ msgid ""
"If the patch applies cleanly, the edited hunk will immediately be marked for "
"unstaging."
msgstr ""
-"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sửa sẽ ngay lập tức được đánh dấu "
+"Nếu bản vá được áp dụng hoàn toàn, khúc đã sửa sẽ ngay lập tức được đánh dấu "
"để bá» ra khá»i bệ phóng."
msgid ""
@@ -283,33 +283,32 @@ msgid ""
msgstr ""
"y - Ä‘Æ°a ra khá»i bệ phóng khúc này\n"
"n - đừng Ä‘Æ°a ra khá»i bệ phóng khúc này\n"
-"q - thoát; đừng Ä‘Æ°a ra khá»i bệ phóng khúc này cÅ©ng nhÆ° bất kỳ cái nào còn "
-"lại\n"
+"q - thoát; đừng Ä‘Æ°a ra khá»i bệ phóng khúc này hay bất kỳ cái nào còn lại\n"
"a - Ä‘Æ°a ra khá»i bệ phóng khúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng Ä‘Æ°a ra khá»i bệ phóng khúc này cÅ©ng nhÆ° bất kỳ cái nào còn lại trong "
-"tập tin\n"
+"d - đừng Ä‘Æ°a ra khá»i bệ phóng khúc này hay bất kỳ cái nào còn lại trong tập "
+"tin\n"
-#, c-format, perl-format
+#, c-format
msgid "Apply mode change to index [y,n,q,a,d%s,?]? "
-msgstr "Ãp dụng thay đổi chế Ä‘á»™ cho mục lục [y,n,q,a,d%s,?]? "
+msgstr "Ãp dụng thay đổi chế Ä‘á»™ vào chỉ mục [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Apply deletion to index [y,n,q,a,d%s,?]? "
-msgstr "Ãp dụng việc xóa vào mục lục [y,n,q,a,d%s,?]? "
+msgstr "Ãp dụng thao tác xóa vào chỉ mục [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Apply addition to index [y,n,q,a,d%s,?]? "
-msgstr "Ãp dụng các thêm vào mục lục [y,n,q,a,d%s,?]? "
+msgstr "Ãp dụng thao tác thêm vào chỉ mục [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Apply this hunk to index [y,n,q,a,d%s,?]? "
-msgstr "Ão dụng khúc này vào mục lục [y,n,q,a,d%s,?]? "
+msgstr "Ão dụng khúc này vào chỉ mục [y,n,q,a,d%s,?]? "
msgid ""
"If the patch applies cleanly, the edited hunk will immediately be marked for "
"applying."
msgstr ""
-"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sửa sẽ ngay lập tức được đánh dấu "
+"Nếu bản vá được áp dụng hoàn toàn, khúc đã sửa sẽ ngay lập tức được đánh dấu "
"để áp dụng."
msgid ""
@@ -319,25 +318,25 @@ msgid ""
"a - apply this hunk and all later hunks in the file\n"
"d - do not apply this hunk or any of the later hunks in the file\n"
msgstr ""
-"y - áp dụng khúc này vào mục lục\n"
-"n - đừng áp dụng khúc này vào mục lục\n"
-"q - thoát; đừng áp dụng khúc này cũng như bất kỳ cái nào còn lại\n"
+"y - áp dụng khúc này vào chỉ mục\n"
+"n - đừng áp dụng khúc này vào chỉ mục\n"
+"q - thoát; đừng áp dụng khúc này hay bất kỳ cái nào còn lại\n"
"a - áp dụng khúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng áp dụng khúc này cũng như bất kỳ cái nào sau này trong tập tin\n"
+"d - đừng áp dụng khúc này hay bất kỳ cái nào sau này trong tập tin\n"
-#, c-format, perl-format
+#, c-format
msgid "Discard mode change from worktree [y,n,q,a,d%s,?]? "
-msgstr "Loại bỠcác thay đổi chế độ từ cây làm việc [y,n,q,a,d%s,?]? "
+msgstr "Loại bá» thay đổi chế Ä‘á»™ khá»i cây làm việc [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Discard deletion from worktree [y,n,q,a,d%s,?]? "
-msgstr "Loại bá» việc xóa khá»i cây làm việc [y,n,q,a,d%s,?]? "
+msgstr "Loại bá» thao tác xóa khá»i cây làm việc [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Discard addition from worktree [y,n,q,a,d%s,?]? "
-msgstr "Thêm các loại bá» khá»i cây làm việc [y,n,q,a,d%s,?]? "
+msgstr "Loại bá» thao tác thêm khá»i cây làm việc [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Discard this hunk from worktree [y,n,q,a,d%s,?]? "
msgstr "Loại bá» khúc này khá»i cây làm việc [y,n,q,a,d%s,?]? "
@@ -345,7 +344,7 @@ msgid ""
"If the patch applies cleanly, the edited hunk will immediately be marked for "
"discarding."
msgstr ""
-"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sửa sẽ ngay lập tức được đánh dấu "
+"Nếu bản vá được áp dụng hoàn toàn, khúc đã sửa sẽ ngay lập tức được đánh dấu "
"để loại bá»."
msgid ""
@@ -357,25 +356,25 @@ msgid ""
msgstr ""
"y - loại bá» khúc này khá»i cây làm việc\n"
"n - đừng loại bá» khúc khá»i cây làm việc\n"
-"q - thoát; đừng loại bỠkhúc này cũng như bất kỳ cái nào còn lại\n"
+"q - thoát; đừng loại bỠkhúc này hay bất kỳ cái nào còn lại\n"
"a - loại bỠkhúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng loại bỠkhúc này cũng như bất kỳ cái nào sau này trong tập tin\n"
+"d - đừng loại bỠkhúc này hay bất kỳ cái nào sau này trong tập tin\n"
-#, c-format, perl-format
+#, c-format
msgid "Discard mode change from index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Loại bỠthay đổi chế độ từ mục lục và cây làm việc [y,n,q,a,d%s,?]? "
+msgstr "Loại bá» thay đổi chế Ä‘á»™ khá»i chỉ mục và cây làm việc [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Discard deletion from index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Loại bá» việc xóa khá»i mục lục và cây làm việc [y,n,q,a,d%s,?]? "
+msgstr "Loại bá» thao tác xóa khá»i chỉ mục và cây làm việc [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Discard addition from index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Thêm các loại bỠtừ mục lục và cây làm việc [y,n,q,a,d%s,?]? "
+msgstr "Loại bá» thao tác thêm khá»i chỉ mục và cây làm việc [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Discard this hunk from index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Loại bá» khúc này khá»i mục lục và cây làm việc [y,n,q,a,d%s,?]? "
+msgstr "Loại bá» khúc này khá»i chỉ mục và cây làm việc [y,n,q,a,d%s,?]? "
msgid ""
"y - discard this hunk from index and worktree\n"
@@ -384,27 +383,27 @@ msgid ""
"a - discard this hunk and all later hunks in the file\n"
"d - do not discard this hunk or any of the later hunks in the file\n"
msgstr ""
-"y - loại bá» khúc này khá»i mục lục và cây làm việc\n"
-"n - đừng loại bá» khúc khá»i mục lục và cây làm việc\n"
-"q - thoát; đừng loại bỠkhúc này cũng như bất kỳ cái nào còn lại\n"
+"y - loại bá» khúc này khá»i chỉ mục và cây làm việc\n"
+"n - đừng loại bá» khúc khá»i chỉ mục và cây làm việc\n"
+"q - thoát; đừng loại bỠkhúc này hay bất kỳ cái nào còn lại\n"
"a - loại bỠkhúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng loại bỠkhúc này cũng như bất kỳ cái nào sau này trong tập tin\n"
+"d - đừng loại bỠkhúc này hay bất kỳ cái nào sau này trong tập tin\n"
-#, c-format, perl-format
+#, c-format
msgid "Apply mode change to index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Ãp dụng thay đổi chế Ä‘á»™ cho mục lục và cây làm việc [y,n,q,a,d%s,?]? "
+msgstr "Ãp dụng thay đổi chế Ä‘á»™ cho chỉ mục và cây làm việc [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Apply deletion to index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Ãp dụng việc xóa vào mục lục và cây làm việc [y,n,q,a,d%s,?]? "
+msgstr "Ãp dụng thao tác xóa vào chỉ mục và cây làm việc [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Apply addition to index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Ãp dụng thêm vào mục lục và cây làm việc [y,n,q,a,d%s,?]? "
+msgstr "Ãp dụng thao tác thêm vào chỉ mục và cây làm việc [y,n,q,a,d%s,?]? "
-#, c-format, perl-format
+#, c-format
msgid "Apply this hunk to index and worktree [y,n,q,a,d%s,?]? "
-msgstr "Ãp dụng khúc này vào mục lục và cây làm việc [y,n,q,a,d%s,?]? "
+msgstr "Ãp dụng khúc này vào chỉ mục và cây làm việc [y,n,q,a,d%s,?]? "
msgid ""
"y - apply this hunk to index and worktree\n"
@@ -413,11 +412,27 @@ msgid ""
"a - apply this hunk and all later hunks in the file\n"
"d - do not apply this hunk or any of the later hunks in the file\n"
msgstr ""
-"y - áp dụng khúc này vào mục lục và cây làm việc\n"
-"n - đừng áp dụng khúc vào mục lục và cây làm việc\n"
-"q - thoát; đừng áp dụng khúc này cũng như bất kỳ cái nào còn lại\n"
+"y - áp dụng khúc này vào chỉ mục và cây làm việc\n"
+"n - đừng áp dụng khúc vào chỉ mục và cây làm việc\n"
+"q - thoát; đừng áp dụng khúc này hay bất kỳ cái nào còn lại\n"
"a - áp dụng khúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng áp dụng khúc này cũng như bất kỳ cái nào sau này trong tập tin\n"
+"d - đừng áp dụng khúc này hay bất kỳ cái nào sau này trong tập tin\n"
+
+#, c-format
+msgid "Apply mode change to worktree [y,n,q,a,d%s,?]? "
+msgstr "Ãp dụng thay đổi chế Ä‘á»™ cho cây làm việc [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Apply deletion to worktree [y,n,q,a,d%s,?]? "
+msgstr "Ãp dụng thao tác xóa cho cây làm việc [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Apply addition to worktree [y,n,q,a,d%s,?]? "
+msgstr "Ãp dụng thao tác thêm cho cây làm việc [y,n,q,a,d%s,?]? "
+
+#, c-format
+msgid "Apply this hunk to worktree [y,n,q,a,d%s,?]? "
+msgstr "Ãp dụng khúc này vào cây làm việc [y,n,q,a,d%s,?]? "
msgid ""
"y - apply this hunk to worktree\n"
@@ -428,36 +443,32 @@ msgid ""
msgstr ""
"y - áp dụng khúc này vào cây làm việc\n"
"n - đừng áp dụng khúc vào cây làm việc\n"
-"q - thoát; đừng áp dụng khúc này cũng như bất kỳ cái nào còn lại\n"
+"q - thoát; đừng áp dụng khúc này hay bất kỳ cái nào còn lại\n"
"a - áp dụng khúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng áp dụng khúc này cũng như bất kỳ cái nào sau này trong tập tin\n"
+"d - đừng áp dụng khúc này hay bất kỳ cái nào sau này trong tập tin\n"
#, c-format
msgid "could not parse hunk header '%.*s'"
-msgstr "không thể phân tích cú pháp phần đầu của khúc “%.*sâ€"
-
-#, c-format
-msgid "could not parse colored hunk header '%.*s'"
-msgstr "không thể phân tích cú pháp phần đầu khúc đã tô màu “%.*sâ€"
+msgstr "không thể Ä‘á»c phần đầu của khúc '%.*s'"
msgid "could not parse diff"
-msgstr "không thể phân tích cú pháp khác biệt"
+msgstr "không thể Ä‘á»c diff"
msgid "could not parse colored diff"
-msgstr "không thể phân tích khác biệt được tô màu"
+msgstr "không thể Ä‘á»c diff có màu"
#, c-format
msgid "failed to run '%s'"
-msgstr "gặp lá»—i khi chạy “%sâ€"
+msgstr "gặp lỗi khi chạy '%s'"
msgid "mismatched output from interactive.diffFilter"
-msgstr "đầu ra không khớp từ interactive.diffFilter"
+msgstr "đầu ra không khớp nhau từ interactive.diffFilter"
msgid ""
"Your filter must maintain a one-to-one correspondence\n"
"between its input and output lines."
msgstr ""
-"Bá»™ lá»c của bạn phải duy trì má»™t quan hệ má»™t-đến-má»™t\n"
+"Bá»™ lá»c của bạn phải duy trì quan hệ má»™t-má»™t\n"
"giữa các dòng đầu vào và đầu ra của nó."
#, c-format
@@ -465,7 +476,7 @@ msgid ""
"expected context line #%d in\n"
"%.*s"
msgstr ""
-"cần dòng ngữ cảnh #%d trong\n"
+"cần dòng ngữ cảnh số %d trong\n"
"%.*s"
#, c-format
@@ -481,51 +492,42 @@ msgstr ""
"%.*s"
msgid "Manual hunk edit mode -- see bottom for a quick guide.\n"
-msgstr "Chế độ sửa khúc bằng tay -- xem ở đáy để có hướng dẫn sử dụng nhanh.\n"
+msgstr ""
+"Chế độ sửa khúc bằng tay -- xem ở dưới để có hướng dẫn sử dụng nhanh.\n"
#, c-format
msgid ""
"---\n"
"To remove '%c' lines, make them ' ' lines (context).\n"
"To remove '%c' lines, delete them.\n"
-"Lines starting with %c will be removed.\n"
+"Lines starting with %s will be removed.\n"
msgstr ""
"---\n"
-"Äể gỡ bá» dòng “%câ€, sá»­a chúng thành những dòng “ †(ngữ cảnh).\n"
-"Äể gõ bá» dòng “%câ€, xóa chúng Ä‘i.\n"
-"Những dòng bắt đầu bằng %c sẽ bị loại bá».\n"
+"Äể gỡ bá» dòng '%c', sá»­a chúng thành những dòng ' ' (ngữ cảnh).\n"
+"Äể gõ bá» dòng '%c', xóa chúng Ä‘i.\n"
+"Những dòng bắt đầu bằng %s sẽ bị loại bá».\n"
-#. #-#-#-#-# git-add--interactive.perl.po #-#-#-#-#
-#. TRANSLATORS: 'it' refers to the patch mentioned in the previous messages.
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"
"aborted and the hunk is left unchanged.\n"
msgstr ""
-"Nếu miếng vá không được áp dụng sạch sẽ, bạn sẽ có một cơ hội\n"
-"để sá»­a lần nữa. Nếu má»i dòng của khúc bị xóa bá», thế thì những\n"
-"sá»­a dổi sẽ bị loại bá», và khúc vẫn giữ nguyên.\n"
+"Nếu bản vá không được áp dụng hoàn toàn, bạn sẽ có cơ hội\n"
+"để sá»­a lại. Nếu má»i dòng của khúc bị xóa bá», thì những\n"
+"sá»­a đổi sẽ bị loại bá», và khúc vẫn giữ nguyên.\n"
msgid "could not parse hunk header"
-msgstr "không thể phân tích cú pháp phần đầu khúc"
+msgstr "không hiểu cú pháp phần đầu khúc"
msgid "'git apply --cached' failed"
-msgstr "“git apply --cached†gặp lỗi"
+msgstr "'git apply --cached' gặp lỗi"
-#. #-#-#-#-# 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.
msgid ""
"Your edited hunk does not apply. Edit again (saying \"no\" discards!) [y/n]? "
msgstr ""
@@ -533,7 +535,7 @@ msgstr ""
"bá»!) [y/n]? "
msgid "The selected hunks do not apply to the index!"
-msgstr "Các khúc đã chá»n không được áp dụng vào bảng mục lục!"
+msgstr "Các khúc đã chá»n không được áp dụng vào chỉ mục!"
msgid "Apply them to the worktree anyway? "
msgstr "Vẫn áp dụng chúng cho cây làm việc? "
@@ -550,6 +552,7 @@ msgid ""
"/ - search for a hunk matching the given regex\n"
"s - split the current hunk into smaller hunks\n"
"e - manually edit the current hunk\n"
+"p - print the current hunk\n"
"? - print help\n"
msgstr ""
"j - để lại khúc này là chưa quyết định, xem khúc chưa quyết định kế tiếp\n"
@@ -557,9 +560,10 @@ msgstr ""
"k - để lại khúc này là chưa quyết định, xem khúc chưa quyết định kế trước\n"
"K - để lại khúc này là chưa quyết định, xem khúc kế trước\n"
"g - chá»n má»™t khúc muốn tá»›i\n"
-"/ - tìm một khúc khớp với biểu thức chính quy đưa ra\n"
+"/ - tìm một khúc khớp với biểu thức chính quy\n"
"s - chia khúc hiện tại thành các khúc nhỠhơn\n"
"e - sửa bằng tay khúc hiện hành\n"
+"p - in ra khúc hiện hành\n"
"? - hiển thị trợ giúp\n"
msgid "No previous hunk"
@@ -569,48 +573,48 @@ msgid "No next hunk"
msgstr "Không có khúc kế tiếp"
msgid "No other hunks to goto"
-msgstr "Không còn khúc nào để mà nhảy đến"
+msgstr "Không còn khúc nào để nhảy đến"
msgid "go to which hunk (<ret> to see more)? "
-msgstr "nhảy đến khúc nào (<ret> để xem thêm)? "
+msgstr "nhảy đến khúc nào (<Enter> để xem thêm)? "
msgid "go to which hunk? "
msgstr "nhảy đến khúc nào? "
#, c-format
msgid "Invalid number: '%s'"
-msgstr "Số không hợp lệ: “%sâ€"
+msgstr "Số không hợp lệ: '%s'"
#, c-format
msgid "Sorry, only %d hunk available."
msgid_plural "Sorry, only %d hunks available."
-msgstr[0] "Rất tiếc, chỉ có sẵn %d khúc."
+msgstr[0] "Chỉ có %d khúc."
msgid "No other hunks to search"
-msgstr "Không còn khúc nào để mà tìm kiếm"
+msgstr "Không còn khúc nào để tìm kiếm"
msgid "search for regex? "
-msgstr "tìm kiếm cho biểu thức chính quy? "
+msgstr "tìm kiếm cho biểu thức chính quy (regex)? "
#, c-format
msgid "Malformed search regexp %s: %s"
-msgstr "Äịnh dạng tìm kiếm của biểu thức chính quy không đúng %s: %s"
+msgstr "Äịnh dạng tìm kiếm của biểu thức chính quy (regex) bất thÆ°á»ng %s: %s"
msgid "No hunk matches the given pattern"
msgstr "Không thấy khúc nào khớp mẫu đã cho"
msgid "Sorry, cannot split this hunk"
-msgstr "Rất tiếc, không thể chia nhỠkhúc này"
+msgstr "Không thể chia nhỠkhúc này"
#, c-format
msgid "Split into %d hunks."
-msgstr "Chi nhỠthành %d khúc."
+msgstr "Chia nhỠthành %d khúc."
msgid "Sorry, cannot edit this hunk"
-msgstr "Rất tiếc, không thể sửa khúc này"
+msgstr "Không thể sửa khúc này"
msgid "'git apply' failed"
-msgstr "“git apply†gặp lỗi"
+msgstr "'git apply' gặp lỗi"
#, c-format
msgid ""
@@ -621,47 +625,41 @@ msgstr ""
"Tắt lá»i nhắn này bằng \"git config advice.%s false\""
#, c-format
-msgid "%shint: %.*s%s\n"
-msgstr "%sgợi ý: %.*s%s\n"
+msgid "%shint:%s%.*s%s\n"
+msgstr "%sgợi ý:%s%.*s%s\n"
msgid "Cherry-picking is not possible because you have unmerged files."
msgstr ""
-"Cherry-picking là không thể thực hiện bởi vì bạn có những tập tin chưa được "
-"hòa trộn."
+"Không thể thực hiện cherry-pick vì bạn có những tập tin chưa được hòa trộn."
msgid "Committing is not possible because you have unmerged files."
msgstr ""
-"Không thể thực hiện chuyển giao được bởi vì bạn có những tập tin chưa được "
-"hòa trộn."
+"Không thể thực hiện chuyển giao vì bạn có những tập tin chưa được hòa trộn."
msgid "Merging is not possible because you have unmerged files."
msgstr ""
-"Không thể thực hiện hòa trộn bởi vì bạn có những tập tin chưa được hòa trộn."
+"Không thể thực hiện hòa trộn vì bạn có những tập tin chưa được hòa trộn."
msgid "Pulling is not possible because you have unmerged files."
-msgstr ""
-"Không thể thực hiện kéo vỠbởi vì bạn có những tập tin chưa được hòa trộn."
+msgstr "Không thể thực hiện kéo vỠvì bạn có những tập tin chưa được hòa trộn."
msgid "Reverting is not possible because you have unmerged files."
msgstr ""
-"Không thể thực hiện hoàn nguyên bởi vì bạn có những tập tin chưa được hòa "
-"trá»™n."
+"Không thể thực hiện hoàn nguyên vì bạn có những tập tin chưa được hòa trộn."
-#, c-format
-msgid "It is not possible to %s because you have unmerged files."
+msgid "Rebasing is not possible because you have unmerged files."
msgstr ""
-"Việc này không thể thực hiện với %s bởi vì bạn có những tập tin chưa được "
-"hòa trộn."
+"Không thể thực hiện hoàn nguyên vì bạn có những tập tin chưa được hòa trộn."
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."
msgstr ""
-"Sá»­a chúng trong cây làm việc, và sau đó dùng lệnh “git add/rm <tập-tin>â€\n"
-"dành riêng cho việc đánh dấu cần giải quyết và tạo lần chuyển giao."
+"Sửa chúng trong cây làm việc, và sau đó dùng lệnh 'git add/rm <tập-tin>'\n"
+"để chá»n cách giải quyết và tiến hành chuyển giao."
msgid "Exiting because of an unresolved conflict."
-msgstr "Thoát ra bởi vì xung đột không thể giải quyết."
+msgstr "Thoát vì không thể giải quyết xung đột."
msgid "You have not concluded your merge (MERGE_HEAD exists)."
msgstr "Bạn chưa kết thúc việc hòa trộn (MERGE_HEAD vẫn tồn tại)."
@@ -670,10 +668,27 @@ msgid "Please, commit your changes before merging."
msgstr "Vui lòng chuyển giao các thay đổi trước khi hòa trộn."
msgid "Exiting because of unfinished merge."
-msgstr "Thoát ra bởi vì việc hòa trộn không hoàn tất."
+msgstr "Thoát vì việc hòa trộn còn dang dở."
+
+msgid ""
+"Diverging branches can't be fast-forwarded, you need to either:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"or:\n"
+"\n"
+"\tgit rebase\n"
+msgstr ""
+"Không thể chuyển-tiếp-nhanh các nhánh phân kỳ, bạn cần dùng:\n"
+"\n"
+"\tgit merge --no-ff\n"
+"\n"
+"hoặc:\n"
+"\n"
+"\tgit rebase\n"
msgid "Not possible to fast-forward, aborting."
-msgstr "Thực hiện lệnh chuyển-tiếp-nhanh là không thể được, đang bỠqua."
+msgstr "Không thể chuyển-tiếp-nhanh, đang huỷ lệnh."
#, c-format
msgid ""
@@ -683,7 +698,7 @@ msgid ""
msgstr ""
"Các Ä‘Æ°á»ng dẫn và/hoặc đặc tả Ä‘Æ°á»ng dẫn sau đây khá»›p vá»›i các Ä‘Æ°á»ng dẫn tồn "
"tại\n"
-"bên ngoài định nghĩa “sparse-checkout†của bạn, vì vậy sẽ không\n"
+"bên ngoài định nghĩa 'sparse-checkout' của bạn, vì vậy sẽ không\n"
"cập nhật trong chỉ mục:\n"
msgid ""
@@ -693,7 +708,7 @@ msgid ""
msgstr ""
"Nếu bạn có ý định cập nhật các mục như vậy, hãy thử một trong các mục sau:\n"
"* Sá»­ dụng tùy chá»n --sparse.\n"
-"* Vô hiệu hóa hoặc sửa đổi các quy tắc thưa thớt."
+"* Vô hiệu hóa hoặc sửa đổi sparse rules (luật thưa)."
#, c-format
msgid ""
@@ -716,14 +731,14 @@ msgid ""
"false\n"
"\n"
msgstr ""
-"Chú ý: Ä‘ang chuyển sang “%sâ€.\n"
+"Chú ý: đang chuyển sang '%s'.\n"
"\n"
-"Bạn Ä‘ang ở tình trạng “detached HEADâ€. Bạn có thể xem qua, tạo các thay\n"
-"đổi thử nghiệm và chuyển giao chúng, bạn có thể loại bỠbất kỳ lần chuyển\n"
-"giao nào trong tình trạng này mà không cần đụng chạm đến bất kỳ nhánh nào\n"
+"Bạn đang ở tình trạng 'detached HEAD'. Bạn có thể xem qua, tạo và\n"
+"chuyển giao các thay đổi thử nghiệm, và bạn có thể loại bỠcác lần chuyển\n"
+"giao trong trạng thái này mà không ảnh hưởng đến bất kỳ nhánh nào\n"
"bằng cách chuyển trở lại một nhánh.\n"
"\n"
-"Nếu bạn muốn tạo một nhánh mới để giữ lại các lần chuyển giao bạn tạo,\n"
+"Nếu bạn muốn tạo một nhánh mới để giữ lại các lần chuyển giao đã tạo,\n"
"bạn có thể làm thế (ngay bây giá» hay sau này) bằng cách dùng tùy chá»n\n"
"dòng lệnh -c. Ví dụ:\n"
"\n"
@@ -736,19 +751,41 @@ msgstr ""
"Tắt hướng dẫn này bằng cách đặt biến advice.detachedHead thành false\n"
"\n"
+#, c-format
+msgid ""
+"The following paths have been moved outside the\n"
+"sparse-checkout definition but are not sparse due to local\n"
+"modifications.\n"
+msgstr ""
+"Các Ä‘Æ°á»ng dẫn sau đã được di chuyển ra ngoài định nghÄ©a\n"
+"sparse-checkout nhưng không còn thuộc loại sparse (thưa) vì có\n"
+"thay đổi nội bộ.\n"
+
+msgid ""
+"To correct the sparsity of these paths, do the following:\n"
+"* Use \"git add --sparse <paths>\" to update the index\n"
+"* Use \"git sparse-checkout reapply\" to apply the sparsity rules"
+msgstr ""
+"Äể sá»­a lại đúng loại sprase (thÆ°a) của các tập này, hãy thá»±c hiện:\n"
+"* Chạy \"git add --sparse <Ä‘Æ°á»ng-dẫn>\" để cập nhật chỉ mục\n"
+"* Chạy \"git sparse-checkout reapply\" để áp dụng luật thưa"
+
msgid "cmdline ends with \\"
-msgstr "cmdline kết thúc với \\"
+msgstr "cuối dòng lệnh có \\"
msgid "unclosed quote"
msgstr "chưa có dấu nháy đóng"
+msgid "too many arguments"
+msgstr "có quá nhiá»u đối số"
+
#, c-format
msgid "unrecognized whitespace option '%s'"
-msgstr "không nhận ra tùy chá»n vá» khoảng trắng “%sâ€"
+msgstr "không nhận ra tùy chá»n vá» khoảng trắng '%s'"
#, c-format
msgid "unrecognized whitespace ignore option '%s'"
-msgstr "không nhận ra tùy chá»n bá» qua khoảng trắng “%sâ€"
+msgstr "không nhận ra tùy chá»n bá» qua khoảng trắng '%s'"
#, c-format
msgid "options '%s' and '%s' cannot be used together"
@@ -756,13 +793,17 @@ msgstr "tùy chá»n '%s' và '%s' không thể dùng cùng nhau"
#, c-format
msgid "'%s' outside a repository"
-msgstr "'%s' ở ngoài một kho chứa"
+msgstr "'%s' ở ngoài kho chứa"
+
+msgid "failed to read patch"
+msgstr "gặp lá»—i khi Ä‘á»c bản vá"
+
+msgid "patch too large"
+msgstr "bản vá quá lớn"
#, c-format
msgid "Cannot prepare timestamp regexp %s"
-msgstr ""
-"Không thể chuẩn bị biểu thức chính qui dấu vết thá»i gian (timestamp regexp) "
-"%s"
+msgstr "Không thể chuẩn bị biểu thức chính quy dấu thá»i gian%s"
#, c-format
msgid "regexec returned %d for input: %s"
@@ -770,12 +811,11 @@ msgstr "thi hành biểu thức chính quy trả vỠ%d cho đầu vào: %s"
#, c-format
msgid "unable to find filename in patch at line %d"
-msgstr "không thể tìm thấy tên tập tin trong miếng vá tại dòng %d"
+msgstr "không thể tìm thấy tên tập tin trong bản vá tại dòng %d"
#, c-format
msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d"
-msgstr ""
-"git apply: git-diff sai - cần /dev/null, nhưng lại nhận được %s trên dòng %d"
+msgstr "git apply: git-diff sai - cần /dev/null, nhưng lại có %s trên dòng %d"
#, c-format
msgid "git apply: bad git-diff - inconsistent new filename on line %d"
@@ -787,7 +827,7 @@ msgstr "git apply: git-diff sai - tên tập tin cũ không nhất quán trên d
#, c-format
msgid "git apply: bad git-diff - expected /dev/null on line %d"
-msgstr "git apply: git-diff sai - cần “/dev/null†trên dòng %d"
+msgstr "git apply: git-diff sai - cần '/dev/null' trên dòng %d"
#, c-format
msgid "invalid mode on line %d: %s"
@@ -795,7 +835,7 @@ msgstr "chế độ không hợp lệ trên dòng %d: %s"
#, c-format
msgid "inconsistent header lines %d and %d"
-msgstr "phần đầu mâu thuẫn dòng %d và %d"
+msgstr "phần đầu không nhất quán tại dòng %d và %d"
#, c-format
msgid ""
@@ -805,8 +845,8 @@ msgid_plural ""
"git diff header lacks filename information when removing %d leading pathname "
"components (line %d)"
msgstr[0] ""
-"phần đầu diff cho git thiếu thông tin tên tập tin khi gỡ bỠđi %d trong "
-"thành phần dẫn đầu tên của Ä‘Æ°á»ng dẫn (dòng %d)"
+"phần đầu diff cho git thiếu thông tin tên tập tin khi xoá đi %d mục dẫn đầu "
+"trong tên của Ä‘Æ°á»ng dẫn (dòng %d)"
#, c-format
msgid "git diff header lacks filename information (line %d)"
@@ -814,11 +854,11 @@ msgstr "phần đầu diff cho git thiếu thông tin tên tập tin (dòng %d)"
#, c-format
msgid "recount: unexpected line: %.*s"
-msgstr "chi tiết: dòng không cần: %.*s"
+msgstr "recount: dòng bất thÆ°á»ng %.*s"
#, c-format
msgid "patch fragment without header at line %d: %.*s"
-msgstr "miếng vá phân mảnh mà không có phần đầu tại dòng %d: %.*s"
+msgstr "bản vá không có phần đầu tại dòng %d: %.*s"
msgid "new file depends on old contents"
msgstr "tập tin mới phụ thuộc vào nội dung cũ"
@@ -828,7 +868,7 @@ msgstr "tập tin đã xóa vẫn còn nội dung"
#, c-format
msgid "corrupt patch at line %d"
-msgstr "miếng vá há»ng tại dòng %d"
+msgstr "bản vá há»ng tại dòng %d"
#, c-format
msgid "new file %s depends on old contents"
@@ -844,15 +884,15 @@ msgstr "** cảnh báo: tập tin %s trở nên trống rá»—ng nhÆ°ng không bá»
#, c-format
msgid "corrupt binary patch at line %d: %.*s"
-msgstr "miếng vá định dạng nhị phân sai há»ng tại dòng %d: %.*s"
+msgstr "bản vá nhị phân há»ng tại dòng %d: %.*s"
#, c-format
msgid "unrecognized binary patch at line %d"
-msgstr "miếng vá định dạng nhị phân không được nhận ra tại dòng %d"
+msgstr "bản vá nhị phân không thể nhận diện tại dòng %d"
#, c-format
msgid "patch with only garbage at line %d"
-msgstr "vá chỉ với “rác†tại dòng %d"
+msgstr "bản vá chứa 'rác' tại dòng %d"
#, c-format
msgid "unable to read symlink %s"
@@ -864,64 +904,59 @@ msgstr "không thể mở hay Ä‘á»c %s"
#, c-format
msgid "invalid start of line: '%c'"
-msgstr "sai khởi đầu dòng: “%câ€"
+msgstr "sai khởi đầu dòng: '%c'"
#, c-format
msgid "Hunk #%d succeeded at %d (offset %d line)."
msgid_plural "Hunk #%d succeeded at %d (offset %d lines)."
-msgstr[0] "Khối dữ liệu #%d thành công tại %d (offset %d dòng)."
+msgstr[0] "Khối thứ %d thành công tại %d (offset %d dòng)."
#, c-format
msgid "Context reduced to (%ld/%ld) to apply fragment at %d"
-msgstr "Ngữ cảnh bị giảm xuống còn (%ld/%ld) để áp dụng mảnh dữ liệu tại %d"
+msgstr "Ngữ cảnh bị giảm xuống còn (%ld/%ld) để áp dụng bản vá tại %d"
#, c-format
msgid ""
"while searching for:\n"
"%.*s"
msgstr ""
-"trong khi đang tìm kiếm cho:\n"
+"trong khi đang tìm kiếm:\n"
"%.*s"
#, c-format
msgid "missing binary patch data for '%s'"
-msgstr "thiếu dữ liệu của miếng vá định dạng nhị phân cho “%sâ€"
+msgstr "thiếu dữ liệu của bản vá nhị phân cho '%s'"
#, c-format
msgid "cannot reverse-apply a binary patch without the reverse hunk to '%s'"
-msgstr ""
-"không thể reverse-apply một miếng vá nhị phân mà không đảo ngược khúc thành "
-"“%sâ€"
+msgstr "không thể đảo ngược bản vá nhị phân mà không có khúc ngược cho '%s'"
#, c-format
msgid "cannot apply binary patch to '%s' without full index line"
msgstr ""
-"không thể áp dụng miếng vá nhị phân thành “%s†mà không có dòng chỉ mục đầy "
-"đủ"
+"không thể áp dụng bản vá nhị phân cho '%s' mà không có dòng chỉ mục đầy đủ"
#, c-format
msgid ""
"the patch applies to '%s' (%s), which does not match the current contents."
-msgstr ""
-"miếng vá áp dụng cho “%s†(%s), cái mà không khớp với các nội dung hiện tại."
+msgstr "bản vá áp dụng cho '%s' (%s), nhưng không khớp với nội dung hiện tại."
#, c-format
msgid "the patch applies to an empty '%s' but it is not empty"
-msgstr "miếng vá áp dụng cho một “%s†trống rỗng nhưng nó lại không trống"
+msgstr "bản vá áp dụng cho '%s' trống rỗng nhưng nó lại không trống"
#, c-format
msgid "the necessary postimage %s for '%s' cannot be read"
-msgstr "không thể Ä‘á»c postimage %s cần thiết cho “%sâ€"
+msgstr "không thể Ä‘á»c hậu ảnh %s cần thiết cho '%s'"
#, c-format
msgid "binary patch does not apply to '%s'"
-msgstr "miếng vá định dạng nhị phân không được áp dụng cho “%sâ€"
+msgstr "bản vá nhị phân không được áp dụng cho '%s'"
#, c-format
msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)"
msgstr ""
-"vá nhị phân cho “%s†tạo ra kết quả không chính xác (mong chỠ%s, lại nhận "
-"%s)"
+"bản vá nhị phân cho '%s' cho ra kết quả không chính xác (cần %s, lại nhận %s)"
#, c-format
msgid "patch failed: %s:%ld"
@@ -929,7 +964,7 @@ msgstr "gặp lỗi khi vá: %s:%ld"
#, c-format
msgid "cannot checkout %s"
-msgstr "không thể lấy ra %s"
+msgstr "không thể checkout %s"
#, c-format
msgid "failed to read %s"
@@ -937,7 +972,7 @@ msgstr "gặp lá»—i khi Ä‘á»c %s"
#, c-format
msgid "reading from '%s' beyond a symbolic link"
-msgstr "Ä‘á»c từ “%s†vượt ra ngoài liên kết má»m"
+msgstr "Ä‘á»c từ '%s' đứng sau liên kết má»m"
#, c-format
msgid "path %s has been renamed/deleted"
@@ -945,41 +980,42 @@ msgstr "Ä‘Æ°á»ng dẫn %s đã bị xóa hoặc đổi tên"
#, c-format
msgid "%s: does not exist in index"
-msgstr "%s: không tồn tại trong bảng mục lục"
+msgstr "%s: không tồn tại trong chỉ mục"
#, c-format
msgid "%s: does not match index"
-msgstr "%s: không khớp trong mục lục"
+msgstr "%s: không khớp với chỉ mục"
msgid "repository lacks the necessary blob to perform 3-way merge."
-msgstr "kho thiếu đối tượng blob cần thiết để thá»±c hiện hòa trá»™n “3-wayâ€."
+msgstr ""
+"kho thiếu đối tượng blob cần thiết để thực hiện hòa trộn kiểu three-way."
#, c-format
msgid "Performing three-way merge...\n"
-msgstr "Äang thá»±c hiện hòa trá»™n “3-Ä‘Æ°á»ngâ€â€¦\n"
+msgstr "Äang thá»±c hiện hòa trá»™n three-way...\n"
#, c-format
msgid "cannot read the current contents of '%s'"
-msgstr "không thể Ä‘á»c ná»™i dung hiện hành của “%sâ€"
+msgstr "không thể Ä‘á»c ná»™i dung hiện hành của '%s'"
#, c-format
msgid "Failed to perform three-way merge...\n"
-msgstr "Gặp lá»—i khi thá»±c hiện hòa trá»™n kiểu “three-wayâ€â€¦\n"
+msgstr "Gặp lỗi khi thực hiện hòa trộn kiểu three-way...\n"
#, c-format
msgid "Applied patch to '%s' with conflicts.\n"
-msgstr "Äã áp dụng miếng vá %s vá»›i các xung Ä‘á»™t.\n"
+msgstr "Ãp dụng bản vá '%s' còn các xung Ä‘á»™t.\n"
#, c-format
msgid "Applied patch to '%s' cleanly.\n"
-msgstr "Äã áp dụng miếng vá %s má»™t cách sạch sẽ.\n"
+msgstr "Ãp dụng bản vá %s má»™t cách hoàn toàn.\n"
#, c-format
msgid "Falling back to direct application...\n"
-msgstr "Äang trở lại ứng dụng chi phối…\n"
+msgstr "Äang trở vá» cách áp dụng trá»±c tiếp..\n"
msgid "removal patch leaves file contents"
-msgstr "loại bỠmiếng vá để lại nội dung tập tin"
+msgstr "bản vá để lại tập tin còn nội dung"
#, c-format
msgid "%s: wrong type"
@@ -991,15 +1027,15 @@ msgstr "%s có kiểu %o, cần %o"
#, c-format
msgid "invalid path '%s'"
-msgstr "Ä‘Æ°á»ng dẫn không hợp lệ “%sâ€"
+msgstr "Ä‘Æ°á»ng dẫn không hợp lệ '%s'"
#, c-format
msgid "%s: already exists in index"
-msgstr "%s: đã có từ trước trong bảng mục lục"
+msgstr "%s: đã sẵn có trong chỉ mục"
#, c-format
msgid "%s: already exists in working directory"
-msgstr "%s: đã sẵn có trong thư mục đang làm việc"
+msgstr "%s: đã sẵn có trong thư mục làm việc"
#, c-format
msgid "new mode (%o) of %s does not match old mode (%o)"
@@ -1011,15 +1047,15 @@ msgstr "chế độ mới (%o) của %s không khớp với chế độ cũ (%o)
#, c-format
msgid "affected file '%s' is beyond a symbolic link"
-msgstr "tập tin chịu tác Ä‘á»™ng “%s†vượt ra ngoài liên kết má»m"
+msgstr "tập tin chịu tác Ä‘á»™ng '%s' đứng sau liên kết má»m"
#, c-format
msgid "%s: patch does not apply"
-msgstr "%s: miếng vá không được áp dụng"
+msgstr "%s: bản vá không được áp dụng"
#, c-format
msgid "Checking patch %s..."
-msgstr "Äang kiểm tra miếng vá %s…"
+msgstr "Äang kiểm tra bản vá %s..."
#, c-format
msgid "sha1 information is lacking or useless for submodule %s"
@@ -1027,35 +1063,35 @@ msgstr "thông tin sha1 thiếu hoặc không dùng được cho mô-đun %s"
#, c-format
msgid "mode change for %s, which is not in current HEAD"
-msgstr "thay đổi chế độ cho %s, cái mà không phải là HEAD hiện tại"
+msgstr "thay đổi chế độ cho %s, nhưng nó không nằm trong HEAD hiện tại"
#, c-format
msgid "sha1 information is lacking or useless (%s)."
-msgstr "thông tin sha1 còn thiếu hay không dùng được(%s)."
+msgstr "thông tin sha1 còn thiếu hay không dùng được (%s)."
#, c-format
msgid "could not add %s to temporary index"
-msgstr "không thể thêm %s vào chỉ mục tạm thá»i"
+msgstr "không thể thêm %s vào chỉ mục tạm"
#, c-format
msgid "could not write temporary index to %s"
-msgstr "không thể ghi mục lục tạm vào %s"
+msgstr "không thể ghi chỉ mục tạm vào %s"
#, c-format
msgid "unable to remove %s from index"
-msgstr "không thể gỡ bỠ%s từ mục lục"
+msgstr "không thể gỡ bỠ%s từ chỉ mục"
#, c-format
msgid "corrupt patch for submodule %s"
-msgstr "miếng vá sai há»ng cho mô-Ä‘un-con %s"
+msgstr "bản vá há»ng cho mô-Ä‘un-con %s"
#, c-format
msgid "unable to stat newly created file '%s'"
-msgstr "không thể lấy thống kê vỠtập tin %s mới hơn đã được tạo"
+msgstr "không thể stat tập tin '%s' mới tạo"
#, c-format
msgid "unable to create backing store for newly created file %s"
-msgstr "không thể tạo “kho lưu đằng sau†cho tập tin được tạo mới hơn %s"
+msgstr "không thể tạo 'backing store' cho tập tin mới tạo %s"
#, c-format
msgid "unable to add cache entry for %s"
@@ -1063,19 +1099,19 @@ msgstr "không thể thêm mục nhớ đệm cho %s"
#, c-format
msgid "failed to write to '%s'"
-msgstr "gặp lá»—i khi ghi vào “%sâ€"
+msgstr "gặp lỗi khi ghi vào '%s'"
#, c-format
msgid "closing file '%s'"
-msgstr "Ä‘ang đóng tập tin “%sâ€"
+msgstr "đang đóng tập tin '%s'"
#, c-format
msgid "unable to write file '%s' mode %o"
-msgstr "không thể ghi vào tập tin “%s†chế độ %o"
+msgstr "không thể ghi vào tập tin '%s' chế độ %o"
#, c-format
msgid "Applied patch %s cleanly."
-msgstr "Äã áp dụng miếng vá %s má»™t cách sạch sẽ."
+msgstr "Äã áp dụng bản vá %s má»™t cách hoàn toàn."
msgid "internal error"
msgstr "lá»—i ná»™i bá»™"
@@ -1083,43 +1119,43 @@ msgstr "lá»—i ná»™i bá»™"
#, c-format
msgid "Applying patch %%s with %d reject..."
msgid_plural "Applying patch %%s with %d rejects..."
-msgstr[0] "Äang áp dụng miếng vá %%s vá»›i %d lần từ chối…"
+msgstr[0] "Äang áp dụng bản vá %%s vá»›i %d lần từ chối..."
#, c-format
-msgid "truncating .rej filename to %.*s.rej"
-msgstr "đang cắt ngắn tên tập tin .rej thành %.*s.rej"
+msgid "cannot open %s"
+msgstr "không thể mở '%s'"
#, c-format
-msgid "cannot open %s"
-msgstr "không mở được “%sâ€"
+msgid "cannot unlink '%s'"
+msgstr "không thể unlink '%s'"
#, c-format
msgid "Hunk #%d applied cleanly."
-msgstr "Khối nhá»› #%d được áp dụng gá»n gàng."
+msgstr "Khúc #%d được áp dụng hoàn toàn."
#, c-format
msgid "Rejected hunk #%d."
-msgstr "Äoạn dữ liệu #%d bị từ chối."
+msgstr "Khúc #%d bị từ chối."
#, c-format
msgid "Skipped patch '%s'."
-msgstr "Bá» qua Ä‘Æ°á»ng dẫn “%sâ€."
+msgstr "Bá» qua Ä‘Æ°á»ng dẫn '%s'."
msgid "No valid patches in input (allow with \"--allow-empty\")"
msgstr ""
-"Không có miếng vá hợp lệ nào trong đầu vào (cho phép với \"--allow-empty\")"
+"Không có bản vá hợp lệ nào trong đầu vào (cho phép với \"--allow-empty\")"
msgid "unable to read index file"
-msgstr "không thể Ä‘á»c tập tin lÆ°u bảng mục lục"
+msgstr "không thể Ä‘á»c tập tin chỉ mục"
#, c-format
msgid "can't open patch '%s': %s"
-msgstr "không thể mở miếng vá “%sâ€: %s"
+msgstr "không thể mở bản vá '%s': %s"
#, c-format
msgid "squelched %d whitespace error"
msgid_plural "squelched %d whitespace errors"
-msgstr[0] "đã chấm dứt %d lỗi khoảng trắng"
+msgstr[0] "đã xử lý %d lỗi khoảng trắng"
#, c-format
msgid "%d line adds whitespace errors."
@@ -1132,7 +1168,7 @@ msgid_plural "%d lines applied after fixing whitespace errors."
msgstr[0] "%d dòng được áp dụng sau khi sửa các lỗi khoảng trắng."
msgid "Unable to write new index file"
-msgstr "Không thể ghi tập tin lưu bảng mục lục mới"
+msgstr "Không thể ghi tập tin chỉ mục mới"
msgid "don't apply changes matching the given path"
msgstr "không áp dụng các thay đổi khá»›p vá»›i Ä‘Æ°á»ng dẫn đã cho"
@@ -1144,52 +1180,46 @@ msgid "num"
msgstr "số"
msgid "remove <num> leading slashes from traditional diff paths"
-msgstr "gỡ bá» <số> dấu gạch chéo dẫn đầu từ Ä‘Æ°á»ng dẫn diff cổ Ä‘iển"
+msgstr "gỡ bá» <số> dấu gạch chéo dẫn đầu từ Ä‘Æ°á»ng dẫn diff"
msgid "ignore additions made by the patch"
-msgstr "lỠđi phần bổ xung được tạo ra bởi miếng vá"
+msgstr "bỠqua các bổ sung trong bản vá"
msgid "instead of applying the patch, output diffstat for the input"
-msgstr ""
-"thay vì áp dụng một miếng vá, kết xuất kết quả từ lệnh diffstat cho đầu ra"
+msgstr "thay vì áp dụng bản vá, xuất kết quả diffstat cho đầu vào"
msgid "show number of added and deleted lines in decimal notation"
-msgstr ""
-"hiển thị số lượng các dòng được thêm vào và xóa đi theo ký hiệu thập phân"
+msgstr "hiển thị số lượng các dòng được thêm vào và xóa đi theo hệ thập phân"
msgid "instead of applying the patch, output a summary for the input"
-msgstr "thay vì áp dụng một miếng vá, kết xuất kết quả cho đầu vào"
+msgstr "thay vì áp dụng bản vá, xuất tóm tắt kết quả cho đầu vào"
msgid "instead of applying the patch, see if the patch is applicable"
-msgstr "thay vì áp dụng miếng vá, hãy xem xem miếng vá có thích hợp không"
+msgstr "thay vì áp dụng bản vá, xem xem bản vá có thích hợp không"
msgid "make sure the patch is applicable to the current index"
-msgstr "hãy chắc chắn là miếng vá thích hợp với bảng mục lục hiện hành"
+msgstr "kiểm tra chắc chắn là bản vá thích hợp với chỉ mục hiện hành"
msgid "mark new files with `git add --intent-to-add`"
-msgstr "đánh dấu các tập tin má»›i vá»›i “git add --intent-to-addâ€"
+msgstr "đánh dấu các tập tin mới với 'git add --intent-to-add'"
msgid "apply a patch without touching the working tree"
-msgstr "áp dụng một miếng vá mà không động chạm đến cây làm việc"
+msgstr "áp dụng bản vá mà không động chạm đến cây làm việc"
msgid "accept a patch that touches outside the working area"
-msgstr "chấp nhận một miếng vá mà không động chạm đến cây làm việc"
+msgstr "chấp nhận bản vá có động chạm đến ngoài cây làm việc"
msgid "also apply the patch (use with --stat/--summary/--check)"
-msgstr ""
-"đồng thá»i áp dụng miếng vá (dùng vá»›i tùy chá»n --stat/--summary/--check)"
+msgstr "đồng thá»i áp dụng bản vá (dùng vá»›i tùy chá»n --stat/--summary/--check)"
msgid "attempt three-way merge, fall back on normal patch if that fails"
-msgstr ""
-"thá»­ hòa trá»™n kiểu three-way, quay lại dán bình thÆ°á»ng nếu không thể thá»±c "
-"hiện được"
+msgstr "thá»­ hòa trá»™n kiểu three-way, quay lại kiểu bình thÆ°á»ng nếu thất bại"
msgid "build a temporary index based on embedded index information"
-msgstr ""
-"xây dá»±ng bảng mục lục tạm thá»i trên cÆ¡ sở thông tin bảng mục lục được nhúng"
+msgstr "xây dá»±ng chỉ mục tạm thá»i dá»±a trên thông tin chỉ mục được nhúng"
msgid "paths are separated with NUL character"
-msgstr "các Ä‘Æ°á»ng dẫn bị ngăn cách bởi ký tá»± NULL"
+msgstr "các Ä‘Æ°á»ng dẫn được ngăn cách bởi ký tá»± NULL"
msgid "ensure at least <n> lines of context match"
msgstr "đảm bảo rằng có ít nhất <n> dòng ngữ cảnh khớp"
@@ -1198,22 +1228,22 @@ msgid "action"
msgstr "hành động"
msgid "detect new or modified lines that have whitespace errors"
-msgstr "tìm thấy một dòng mới hoặc bị sửa đổi mà nó có lỗi do khoảng trắng"
+msgstr "tìm thấy dòng mới hoặc dòng bị sửa đổi có lỗi khoảng trắng"
msgid "ignore changes in whitespace when finding context"
-msgstr "lỠđi sự thay đổi do khoảng trắng gây ra khi tìm ngữ cảnh"
+msgstr "bỠqua sự thay đổi do khoảng trắng gây ra khi tìm ngữ cảnh"
msgid "apply the patch in reverse"
-msgstr "áp dụng miếng vá theo chiá»u ngược"
+msgstr "áp dụng bản vá theo chiá»u ngược"
msgid "don't expect at least one line of context"
msgstr "đừng hy vá»ng có ít nhất má»™t dòng ngữ cảnh"
msgid "leave the rejected hunks in corresponding *.rej files"
-msgstr "để lại khối dữ liệu bị từ chối trong các tập tin *.rej tương ứng"
+msgstr "để lại khối bị từ chối trong các tập tin *.rej tương ứng"
msgid "allow overlapping hunks"
-msgstr "cho phép chồng khối nhớ"
+msgstr "cho phép chồng khối"
msgid "tolerate incorrectly detected missing new-line at the end of file"
msgstr ""
@@ -1226,65 +1256,69 @@ msgid "root"
msgstr "gốc"
msgid "prepend <root> to all filenames"
-msgstr "treo thêm <root> vào tất cả các tên tập tin"
+msgstr "thêm <gốc> vào trước tất cả các tên tập tin"
msgid "don't return error for empty patches"
-msgstr "đừng trả vỠlỗi khi các miếng vá trống rỗng"
+msgstr "đừng trả vỠlỗi khi các bản vá trống rỗng"
#, c-format
msgid "cannot stream blob %s"
-msgstr "không thể stream blob “%sâ€"
+msgstr "không thể stream blob '%s'"
#, c-format
msgid "unsupported file mode: 0%o (SHA1: %s)"
msgstr "chế độ tập tin không được hỗ trợ: 0%o (SHA1: %s)"
#, c-format
+msgid "deflate error (%d)"
+msgstr "lỗi giải nén (%d)"
+
+#, c-format
msgid "unable to start '%s' filter"
-msgstr "không thể bắt đầu bá»™ lá»c “%sâ€"
+msgstr "không thể khởi chạy bá»™ lá»c '%s'"
msgid "unable to redirect descriptor"
-msgstr "không thể chuyển hướng mô tả"
+msgstr "không thể chuyển hướng vào/ra"
#, c-format
msgid "'%s' filter reported error"
-msgstr "bá»™ lá»c “%s†đã báo cáo lá»—i"
+msgstr "bá»™ lá»c '%s' đã báo lá»—i"
#, c-format
msgid "path is not valid UTF-8: %s"
-msgstr "Ä‘Æ°á»ng dẫn không hợp lệ UTF-8: %s"
+msgstr "Ä‘Æ°á»ng dẫn không hợp lệ theo UTF-8: %s"
#, c-format
msgid "path too long (%d chars, SHA1: %s): %s"
msgstr "Ä‘Æ°á»ng dẫn quá dài (%d ký tá»±, SHA1: %s): %s"
#, c-format
-msgid "deflate error (%d)"
-msgstr "lỗi giải nén (%d)"
-
-#, c-format
msgid "timestamp too large for this system: %<PRIuMAX>"
-msgstr "dấu vết thá»i gian là quá lá»›n cho hệ thống này: %<PRIuMAX>"
+msgstr "dấu thá»i gian là quá lá»›n cho hệ thống này: %<PRIuMAX>"
msgid "git archive [<options>] <tree-ish> [<path>...]"
-msgstr "git archive [<các tùy chá»n>] <tree-ish> [</Ä‘Æ°á»ng/dẫn>…]"
+msgstr "git archive [<các tùy chá»n>] <tree-ish> [</Ä‘Æ°á»ng/dẫn>...]"
msgid ""
"git archive --remote <repo> [--exec <cmd>] [<options>] <tree-ish> [<path>...]"
msgstr ""
"git archive --remote <kho> [--exec <lệnh>] [<các tùy chá»n>] <tree-ish> [</"
-"Ä‘Æ°á»ng/dẫn>…]"
+"Ä‘Æ°á»ng/dẫn>...]"
msgid "git archive --remote <repo> [--exec <cmd>] --list"
msgstr "git archive --remote <kho> [--exec <lệnh>] --list"
#, c-format
msgid "cannot read '%s'"
-msgstr "không thể Ä‘á»c “%sâ€"
+msgstr "không thể Ä‘á»c '%s'"
+
+#, c-format
+msgid "pathspec '%s' matches files outside the current directory"
+msgstr "đặc tả Ä‘Æ°á»ng dẫn '%s' nằm ngoài thÆ° mục hiện hành"
#, c-format
msgid "pathspec '%s' did not match any files"
-msgstr "đặc tả Ä‘Æ°á»ng dẫn “%s†không khá»›p vá»›i bất kỳ tập tin nào"
+msgstr "đặc tả Ä‘Æ°á»ng dẫn '%s' không khá»›p vá»›i bất kỳ tập tin nào"
#, c-format
msgid "no such ref: %.*s"
@@ -1292,14 +1326,11 @@ msgstr "không có tham chiếu nào như thế: %.*s"
#, c-format
msgid "not a valid object name: %s"
-msgstr "không phải là tên đối tượng hợp lệ: “%sâ€"
+msgstr "không phải là tên đối tượng hợp lệ: %s"
#, c-format
msgid "not a tree object: %s"
-msgstr "không phải là đối tượng cây: “%sâ€"
-
-msgid "current working directory is untracked"
-msgstr "thư mục làm việc hiện hành chưa được theo dõi"
+msgstr "không phải là đối tượng cây: %s"
#, c-format
msgid "File not found: %s"
@@ -1307,7 +1338,7 @@ msgstr "Không tìm thấy tập tin: %s"
#, c-format
msgid "Not a regular file: %s"
-msgstr "Không phải má»™t tập tin thÆ°á»ng: %s"
+msgstr "Không phải tập tin thÆ°á»ng: %s"
#, c-format
msgid "unclosed quote: '%s'"
@@ -1315,26 +1346,26 @@ msgstr "chưa có dấu nháy đóng: '%s'"
#, c-format
msgid "missing colon: '%s'"
-msgstr "thiếu dấu hai chấm: “%sâ€"
+msgstr "thiếu dấu hai chấm: '%s'"
#, c-format
msgid "empty file name: '%s'"
-msgstr "tên tập tin trống rá»—ng: “%sâ€"
+msgstr "tên tập tin trống: '%s'"
msgid "fmt"
-msgstr "định_dạng"
+msgstr "định-dạng"
msgid "archive format"
msgstr "định dạng lưu trữ"
msgid "prefix"
-msgstr "tiá»n_tố"
+msgstr "tiá»n tố"
msgid "prepend prefix to each pathname in the archive"
msgstr "nối thêm tiá»n tố vào từng Ä‘Æ°á»ng dẫn tập tin trong kho lÆ°u"
msgid "file"
-msgstr "tập_tin"
+msgstr "tập tin"
msgid "add untracked file to archive"
msgstr "thêm các tập tin không được theo dõi vào kho lưu"
@@ -1349,7 +1380,13 @@ msgid "read .gitattributes in working directory"
msgstr "Ä‘á»c .gitattributes trong thÆ° mục làm việc"
msgid "report archived files on stderr"
-msgstr "liệt kê các tập tin được lưu trữ vào stderr (đầu ra lỗi tiêu chuẩn)"
+msgstr "liệt kê các tập tin được lưu trữ ra stderr"
+
+msgid "time"
+msgstr "thá»i-gian"
+
+msgid "set modification time of archive entries"
+msgstr "đặt thá»i Ä‘iểm sá»­a đổi của các mục nén"
msgid "set compression level"
msgstr "đặt mức nén"
@@ -1370,27 +1407,38 @@ msgid "path to the remote git-upload-archive command"
msgstr "Ä‘Æ°á»ng dẫn đến lệnh git-upload-archive trên máy chủ"
msgid "Unexpected option --remote"
-msgstr "Gặp tùy chá»n không cần --remote"
+msgstr "Gặp tùy chá»n bất thÆ°á»ng --remote"
#, c-format
msgid "the option '%s' requires '%s'"
-msgstr "tùy chá»n “%s†yêu cầu “%sâ€"
+msgstr "tùy chá»n '%s' yêu cầu '%s'"
msgid "Unexpected option --output"
-msgstr "Gặp tùy chá»n không cần --output"
+msgstr "Gặp tùy chá»n bất thÆ°á»ng --output"
+
+#, c-format
+msgid "extra command line parameter '%s'"
+msgstr "thừa tham số dòng lệnh '%s'"
#, c-format
msgid "Unknown archive format '%s'"
-msgstr "Không hiểu định dạng “%sâ€"
+msgstr "Không hiểu định dạng lưu trữ '%s'"
#, c-format
msgid "Argument not supported for format '%s': -%d"
-msgstr "Tham số không được há»— trợ cho định dạng “%sâ€: -%d"
+msgstr "Tham số không được hỗ trợ cho định dạng '%s': -%d"
#, c-format
msgid "%.*s is not a valid attribute name"
msgstr "%.*s không phải tên thuộc tính hợp lệ"
+msgid "unable to add additional attribute"
+msgstr "Không thể thêm thuộc tính"
+
+#, c-format
+msgid "ignoring overly long attributes line %d"
+msgstr "bỠqua dòng thuộc tính thứ %d quá dài"
+
#, c-format
msgid "%s not allowed: %s:%d"
msgstr "%s không được phép: %s:%d"
@@ -1399,16 +1447,39 @@ msgid ""
"Negative patterns are ignored in git attributes\n"
"Use '\\!' for literal leading exclamation."
msgstr ""
-"Các mẫu dạng phủ định bị cấm dùng cho các thuộc tính của git\n"
-"Dùng “\\!†cho các chuỗi văn bản có dấu chấm than dẫn đầu."
+"Các mẫu dạng phủ định bị cấm dùng cho git attribute\n"
+"Dùng '\\!' cho tên có dấu chấm than dẫn đầu."
+
+#, c-format
+msgid "cannot fstat gitattributes file '%s'"
+msgstr "không thể fstat tập tin gitattributes '%s'"
+
+#, c-format
+msgid "ignoring overly large gitattributes file '%s'"
+msgstr "bỠqua tập tin gitattributes quá lớn '%s'"
+
+#, c-format
+msgid "ignoring overly large gitattributes blob '%s'"
+msgstr "bỠqua blob gitattributes quá lớn '%s'"
+
+msgid "bad --attr-source or GIT_ATTR_SOURCE"
+msgstr "--attr-source hoặc GIT_ATTR_SOURCE sai"
+
+#, c-format
+msgid "unable to stat '%s'"
+msgstr "không thể stat '%s'"
+
+#, c-format
+msgid "unable to read %s"
+msgstr "không thể Ä‘á»c %s"
#, c-format
msgid "Badly quoted content in file '%s': %s"
-msgstr "Ná»™i dung được trích dẫn sai trong tập tin “%sâ€: %s"
+msgstr "Nội dung được trích dẫn sai trong tập tin '%s': %s"
#, c-format
msgid "We cannot bisect more!\n"
-msgstr "Chúng tôi không bisect thêm nữa!\n"
+msgstr "Không bisect thêm nữa!\n"
#, c-format
msgid "Not a valid commit name %s"
@@ -1419,16 +1490,16 @@ msgid ""
"The merge base %s is bad.\n"
"This means the bug has been fixed between %s and [%s].\n"
msgstr ""
-"Hòa trộn trên %s là sai.\n"
-"Äiá»u đó có nghÄ©a là lá»—i đã được sá»­a chữa giữa %s và [%s].\n"
+"Gốc hòa trộn trên %s là sai.\n"
+"Có nghĩa là lỗi đã được sửa chữa giữa %s và [%s].\n"
#, c-format
msgid ""
"The merge base %s is new.\n"
"The property has changed between %s and [%s].\n"
msgstr ""
-"Hòa trộn trên %s là mới.\n"
-"Gần như chắc chắn là có thay đổi giữa %s và [%s].\n"
+"Gốc hòa trộn trên %s là mới.\n"
+"Äã có thay đổi thuá»™c tính giữa %s và [%s].\n"
#, c-format
msgid ""
@@ -1436,7 +1507,7 @@ msgid ""
"This means the first '%s' commit is between %s and [%s].\n"
msgstr ""
"Hòa trộn trên %s là %s.\n"
-"Äiá»u đó có nghÄ©a là lần chuyển giao “%s†đầu tiên là giữa %s và [%s].\n"
+"Có nghĩa là lần chuyển giao '%s' đầu tiên là giữa %s và [%s].\n"
#, c-format
msgid ""
@@ -1445,7 +1516,7 @@ msgid ""
"Maybe you mistook %s and %s revs?\n"
msgstr ""
"Một số điểm xét duyệt %s không phải tổ tiên của điểm xét duyệt %s.\n"
-"git bisect không thể làm việc đúng đắn trong trÆ°á»ng hợp này.\n"
+"git bisect không thể làm việc đúng trong trÆ°á»ng hợp này.\n"
"Liệu có phải bạn nhầm lẫn các điểm %s và %s không?\n"
#, c-format
@@ -1454,14 +1525,13 @@ msgid ""
"So we cannot be sure the first %s commit is between %s and %s.\n"
"We continue anyway."
msgstr ""
-"hòa trộn trên cơ sở giữa %s và [%s] phải bị bỠqua.\n"
-"Do vậy chúng tôi không thể chắc lần chuyển giao đầu tiên %s là giữa %s và "
-"%s.\n"
-"Chúng tôi vẫn cứ tiếp tục."
+"gốc hòa trộn giữa %s và [%s] phải bị bỠqua.\n"
+"Do vậy không thể chắc chắn lần chuyển giao %s đầu tiên là giữa %s và %s.\n"
+"Vẫn tiếp tục."
#, c-format
msgid "Bisecting: a merge base must be tested\n"
-msgstr "Bisecting: ná»n hòa trá»™n cần phải được kiểm tra\n"
+msgstr "Äang bisect: gốc hòa trá»™n cần phải được kiểm tra\n"
#, c-format
msgid "a %s revision is needed"
@@ -1469,11 +1539,15 @@ msgstr "cần một điểm xét duyệt %s"
#, c-format
msgid "could not create file '%s'"
-msgstr "không thể tạo tập tin “%sâ€"
+msgstr "không thể tạo tập tin '%s'"
+
+#, c-format
+msgid "unable to start 'show' for object '%s'"
+msgstr "không thể khởi chạy 'show' cho đối tượng '%s'"
#, c-format
msgid "could not read file '%s'"
-msgstr "không thể Ä‘á»c tập tin “%sâ€"
+msgstr "không thể Ä‘á»c tập tin '%s'"
msgid "reading bisect refs failed"
msgstr "việc Ä‘á»c tham chiếu bisect gặp lá»—i"
@@ -1487,13 +1561,13 @@ msgid ""
"No testable commit found.\n"
"Maybe you started with bad path arguments?\n"
msgstr ""
-"Không tìm thấy lần chuyển giao kiểm tra được nào.\n"
+"Không tìm thấy lần chuyển giao nào kiểm tra được.\n"
"Có lẽ bạn bắt đầu vá»›i các tham số Ä‘Æ°á»ng dẫn sai?\n"
#, c-format
msgid "(roughly %d step)"
msgid_plural "(roughly %d steps)"
-msgstr[0] "(ước chừng %d bước)"
+msgstr[0] "(cần khoảng chừng %d bước)"
#. TRANSLATORS: the last %s will be replaced with "(roughly %d
#. steps)" translation.
@@ -1501,13 +1575,10 @@ msgstr[0] "(ước chừng %d bước)"
#, 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] "Bisecting: còn %d điểm xét duyệt để kiểm sau %s này\n"
+msgstr[0] "Bisecting: còn %d điểm xét duyệt để kiểm tra %s\n"
msgid "--contents and --reverse do not blend well."
-msgstr "tùy chá»n --contents và --reverse không được trá»™n vào nhau."
-
-msgid "cannot use --contents with final commit object name"
-msgstr "không thể dùng --contents với tên đối tượng chuyển giao cuối cùng"
+msgstr "tùy chá»n --contents và --reverse không nên Ä‘i vá»›i nhau."
msgid "--reverse and --first-parent together require specified latest commit"
msgstr ""
@@ -1519,16 +1590,16 @@ msgstr "cài đặt việc di chuyển qua các điểm xét duyệt gặp lỗi
msgid ""
"--reverse --first-parent together require range along first-parent chain"
msgstr ""
-"cùng sử dụng --reverse --first-parent yêu cầu vùng cùng với chuỗi cha-mẹ-đầu-"
-"tiên"
+"cùng sử dụng --reverse và --first-parent yêu cầu vùng cùng với chuỗi cha-mẹ-"
+"đầu-tiên"
#, c-format
msgid "no such path %s in %s"
-msgstr "không có Ä‘Æ°á»ng dẫn %s trong “%sâ€"
+msgstr "không có Ä‘Æ°á»ng dẫn %s trong '%s'"
#, c-format
msgid "cannot read blob %s for path %s"
-msgstr "không thể Ä‘á»c blob %s cho Ä‘Æ°á»ng dẫn “%sâ€"
+msgstr "không thể Ä‘á»c blob %s cho Ä‘Æ°á»ng dẫn '%s'"
msgid ""
"cannot inherit upstream tracking configuration of multiple refs when "
@@ -1539,19 +1610,19 @@ msgstr ""
#, c-format
msgid "not setting branch '%s' as its own upstream"
-msgstr "không cài đặt nhánh '%s' như là thượng nguồn của nó"
+msgstr "không đặt nhánh '%s' là thượng nguồn của chính nó"
#, c-format
msgid "branch '%s' set up to track '%s' by rebasing."
-msgstr "nhánh “%s†cài đặt để theo dõi “%s†bằng cách rebase."
+msgstr "nhánh '%s' cài đặt để theo dõi '%s' bằng cách rebase."
#, c-format
msgid "branch '%s' set up to track '%s'."
-msgstr "nhánh “%s†cài đặt để theo dõi “%sâ€."
+msgstr "nhánh '%s' cài đặt để theo dõi '%s'."
#, c-format
msgid "branch '%s' set up to track:"
-msgstr "nhánh “%s†cài đặt để theo dõi:"
+msgstr "nhánh '%s' cài đặt để theo dõi:"
msgid "unable to write upstream branch configuration"
msgstr "không thể ghi cấu hình nhánh thượng nguồn"
@@ -1562,19 +1633,17 @@ msgid ""
"the remote tracking information by invoking:"
msgstr ""
"\n"
-"Sau khi sửa nguyên nhân gây lỗi bạn có lẻ cần thử sửa\n"
+"Sau khi sửa nguyên nhân gây lỗi bạn có thể thử sửa\n"
"thông tin theo dõi máy chủ bằng cách gá»i lệnh:"
#, c-format
msgid "asked to inherit tracking from '%s', but no remote is set"
-msgstr ""
-"đã há»i để kế thừa theo dõi từ '%s', nhÆ°ng không có máy chủ nào được đặt"
+msgstr "đã yêu cầu kế thừa theo dõi từ '%s', nhưng chưa cấu hình máy chủ nào"
#, c-format
msgid "asked to inherit tracking from '%s', but no merge configuration is set"
msgstr ""
-"đã há»i để kế thừa theo dõi từ '%s', nhÆ°ng không có cấu hình hòa trá»™n nào "
-"được đặt"
+"đã yêu cầu kế thừa theo dõi từ '%s', nhưng không có cấu hình hòa trộn nào"
#, c-format
msgid "not tracking: ambiguous information for ref '%s'"
@@ -1609,8 +1678,8 @@ msgid ""
"different remotes' fetch refspecs map into different\n"
"tracking namespaces."
msgstr ""
-"Có nhiá»u máy chủ những cái lấy ánh xạ refspecs tham chiếu theo\n"
-"dõi máy chủ '%s':\n"
+"Có nhiá»u máy chủ có fetch refspec ánh xạ tá»›i refspecs tham chiếu\n"
+"theo dõi máy chủ '%s':\n"
"%s\n"
"Äây thÆ°á»ng là lá»—i cấu hình.\n"
"\n"
@@ -1620,25 +1689,29 @@ msgstr ""
#, c-format
msgid "'%s' is not a valid branch name"
-msgstr "“%s†không phải là một tên nhánh hợp lệ"
+msgstr "'%s' không phải là một tên nhánh hợp lệ"
+
+msgid "See `man git check-ref-format`"
+msgstr "Äá»c `man git check-ref-format`"
#, c-format
msgid "a branch named '%s' already exists"
-msgstr "đã có nhánh mang tên “%sâ€"
+msgstr "đã có nhánh mang tên '%s'"
#, c-format
-msgid "cannot force update the branch '%s' checked out at '%s'"
-msgstr "không thể ép buá»™c cập nhật nhánh “%s†đã được lấy ra tại “%sâ€"
+msgid "cannot force update the branch '%s' used by worktree at '%s'"
+msgstr ""
+"không thể ép buộc cập nhật nhánh '%s' đang được sử dụng tại cây làm việc '%s'"
#, c-format
msgid "cannot set up tracking information; starting point '%s' is not a branch"
msgstr ""
-"không thể cài đặt thông tin theo dõi; điểm bắt đầu “%s†không phải là một "
+"không thể cài đặt thông tin theo dõi; điểm bắt đầu '%s' không phải là một "
"nhánh"
#, c-format
msgid "the requested upstream branch '%s' does not exist"
-msgstr "nhánh thượng nguồn đã yêu cầu “%s†không tồn tại"
+msgstr "nhánh thượng nguồn đã yêu cầu '%s' không tồn tại"
msgid ""
"\n"
@@ -1651,95 +1724,83 @@ msgid ""
"\"git push -u\" to set the upstream config as you push."
msgstr ""
"\n"
-"Nếu bạn có ý định “cải tổ†công việc của bạn trên nhánh thượng nguồn\n"
-"(upstream) cái mà đã sẵn có trên máy chủ, bạn cần chạy\n"
+"Nếu bạn có ý định bắt đầu công việc của bạn trên nhánh thượng nguồn\n"
+"(upstream) đã sẵn có trên máy chủ, bạn cần chạy\n"
"lệnh \"git fetch\" để lấy nó vá».\n"
"\n"
-"Nếu bạn có ý định đẩy lên lên một nhánh nội bộ mới cái mà\n"
-"sẽ theo dõi bản đối chiếu máy chủ của nó, bạn cần dùng lệnh\n"
-"\"git push -u\" để đặt cấu hình thượng nguồn bạn muốn push."
+"Nếu bạn có ý định đẩy một nhánh nội bộ mới mà\n"
+"sẽ theo dõi nhánh trên máy chủ, bạn cần dùng lệnh\n"
+"\"git push -u\" để đặt cấu hình thượng nguồn khi push."
#, c-format
msgid "not a valid object name: '%s'"
-msgstr "không phải là tên đối tượng hợp lệ: “%sâ€"
+msgstr "không phải là tên đối tượng hợp lệ: '%s'"
#, c-format
msgid "ambiguous object name: '%s'"
-msgstr "tên đối tượng chÆ°a rõ ràng: “%sâ€."
+msgstr "tên đối tượng chưa rõ ràng: '%s'."
#, c-format
msgid "not a valid branch point: '%s'"
-msgstr "không phải là má»™t Ä‘iểm nhánh hợp lệ: “%sâ€"
+msgstr "không phải là một điểm nhánh hợp lệ: '%s'"
#, c-format
msgid "submodule '%s': unable to find submodule"
-msgstr "mô-Ä‘un-con “%sâ€: không thể tìm thấy mô-Ä‘un-con"
+msgstr "mô-đun-con '%s': không thể tìm thấy mô-đun-con"
#, c-format
msgid ""
-"You may try updating the submodules using 'git checkout %s && git submodule "
-"update --init'"
+"You may try updating the submodules using 'git checkout --no-recurse-"
+"submodules %s && git submodule update --init'"
msgstr ""
-"Bạn có thể thử cập nhật các mô-đun-con bằng cách sử dụng 'git checkout %s && "
-"git submodule update --init'"
+"Bạn có thể thử cập nhật các mô-đun-con bằng cách sử dụng 'git checkout --no-"
+"recurse-submodules %s && git submodule update --init'"
#, c-format
msgid "submodule '%s': cannot create branch '%s'"
-msgstr "mô-Ä‘un-con “%sâ€: không thể tạo nhánh “%sâ€"
+msgstr "mô-đun-con '%s': không thể tạo nhánh '%s'"
#, c-format
-msgid "'%s' is already checked out at '%s'"
-msgstr "“%s†đã được lấy ra tại “%s†rồi"
-
-#, c-format
-msgid "HEAD of working tree %s is not updated"
-msgstr "HEAD của cây làm việc %s chưa được cập nhật"
+msgid "'%s' is already used by worktree at '%s'"
+msgstr "'%s' đang được sử dụng tại cây làm việc '%s'"
msgid "git add [<options>] [--] <pathspec>..."
-msgstr "git add [<các tùy chá»n>] [--] <pathspec>…"
+msgstr "git add [<các tùy chá»n>] [--] <pathspec>..."
#, c-format
msgid "cannot chmod %cx '%s'"
-msgstr "không thể chmod %cx “%sâ€"
-
-#, c-format
-msgid "unexpected diff status %c"
-msgstr "trạng thái lệnh diff không như mong đợi %c"
-
-msgid "updating files failed"
-msgstr "cập nhật tập tin gặp lỗi"
-
-#, c-format
-msgid "remove '%s'\n"
-msgstr "gỡ bỠ“%sâ€\n"
+msgstr "không thể chmod %cx '%s'"
msgid "Unstaged changes after refreshing the index:"
-msgstr ""
-"ÄÆ°a ra khá»i bệ phóng các thay đổi sau khi làm tÆ°Æ¡i má»›i lại bảng mục lục:"
+msgstr "ÄÆ°a ra khá»i bệ phóng các thay đổi sau khi làm má»›i lại chỉ mục:"
-msgid "Could not read the index"
-msgstr "Không thể Ä‘á»c bảng mục lục"
+msgid ""
+"the add.interactive.useBuiltin setting has been removed!\n"
+"See its entry in 'git help config' for details."
+msgstr ""
+"mục cài đặt add.interactive.useBuiltin đã không còn!\n"
+"Xem mục tin của nó trong 'git help config' để biết chi tiết."
-msgid "Could not write patch"
-msgstr "Không thể ghi ra miếng vá"
+msgid "could not read the index"
+msgstr "Không thể Ä‘á»c chỉ mục"
msgid "editing patch failed"
-msgstr "gặp lỗi khi sửa miếng vá"
+msgstr "gặp lỗi khi sửa bản vá"
#, c-format
-msgid "Could not stat '%s'"
-msgstr "Không thể lấy thông tin thống kê vỠ“%sâ€"
+msgid "could not stat '%s'"
+msgstr "không thể stat '%s'"
-msgid "Empty patch. Aborted."
-msgstr "Miếng vá trống rỗng. Nên bỠqua."
+msgid "empty patch. aborted"
+msgstr "bản vá trống rá»—ng. huá»· bá»"
#, c-format
-msgid "Could not apply '%s'"
-msgstr "Không thể áp dụng miếng vá “%sâ€"
+msgid "could not apply '%s'"
+msgstr "không thể áp dụng bản vá '%s'"
msgid "The following paths are ignored by one of your .gitignore files:\n"
msgstr ""
-"Các Ä‘Æ°á»ng dẫn theo sau đây sẽ bị lá» Ä‘i bởi má»™t trong các tập tin .gitignore "
+"Các Ä‘Æ°á»ng dẫn theo sau đây sẽ bị bá» qua bởi má»™t trong các tập tin .gitignore "
"của bạn:\n"
msgid "dry run"
@@ -1752,7 +1813,7 @@ msgid "interactive picking"
msgstr "sửa bằng cách tương tác"
msgid "select hunks interactively"
-msgstr "chá»n “hunks†theo kiểu tÆ°Æ¡ng tác"
+msgstr "chá»n 'hunks' theo kiểu tÆ°Æ¡ng tác"
msgid "edit current diff and apply"
msgstr "sửa diff hiện nay và áp dụng nó"
@@ -1764,22 +1825,19 @@ msgid "update tracked files"
msgstr "cập nhật các tập tin được theo dõi"
msgid "renormalize EOL of tracked files (implies -u)"
-msgstr "thÆ°á»ng hóa lại EOL của các tập tin được theo dõi (ý là -u)"
+msgstr "thÆ°á»ng hóa lại EOL của các tập tin được theo dõi (ngụ ý -u)"
msgid "record only the fact that the path will be added later"
msgstr "chỉ ghi lại sá»± việc mà Ä‘Æ°á»ng dẫn sẽ được thêm vào sau"
msgid "add changes from all tracked and untracked files"
-msgstr ""
-"thêm các thay đổi từ tất cả các tập tin có cũng như không được theo dõi dấu "
-"vết"
+msgstr "thêm các thay đổi từ tất cả các tập tin dù được theo dõi hay không"
msgid "ignore paths removed in the working tree (same as --no-all)"
-msgstr ""
-"lá» Ä‘i các Ä‘Æ°á»ng dẫn bị gỡ bá» trong cây thÆ° mục làm việc (giống vá»›i --no-all)"
+msgstr "bá» qua các Ä‘Æ°á»ng dẫn bị xoá bá» trong cây làm việc (giống vá»›i --no-all)"
msgid "don't add, only refresh the index"
-msgstr "không thêm, chỉ làm tươi mới bảng mục lục"
+msgstr "không thêm, chỉ làm mới chỉ mục"
msgid "just skip files which cannot be added because of errors"
msgstr "chie bỠqua những tập tin mà nó không thể được thêm vào bởi vì gặp lỗi"
@@ -1789,10 +1847,11 @@ msgstr ""
"kiểm tra xem - thậm chí thiếu - tập tin bị bỠqua trong quá trình chạy thử"
msgid "allow updating entries outside of the sparse-checkout cone"
-msgstr "cho phép cập nhật các mục ở ngoài “sparse-checkout coneâ€"
+msgstr ""
+"cho phép cập nhật các mục ở ngoài 'sparse-checkout cone' (nón checkout thưa)"
msgid "override the executable bit of the listed files"
-msgstr "ghi đè lên bít thi hành của các tập tin được liệt kê"
+msgstr "ghi đè lên executable bit (bít thực thi) của các tập tin được liệt kê"
msgid "warn when adding an embedded repository"
msgstr "cảnh báo khi thêm một kho nhúng"
@@ -1820,8 +1879,8 @@ msgstr ""
"\n"
"\tgit submodule add <url> %s\n"
"\n"
-"Nếu bạn đã thêm miếng vá này chỉ là sai sót, bạn có thể xóa bá»\n"
-"nó khá»i mục lục bằng:\n"
+"Nếu bạn đã thêm bản vá này chỉ là sai sót, bạn có thể xóa bá»\n"
+"nó khá»i chỉ mục bằng:\n"
"\n"
"\tgit rm --cached %s\n"
"\n"
@@ -1831,21 +1890,15 @@ msgstr ""
msgid "adding embedded git repository: %s"
msgstr "thêm cần một kho git nhúng: %s"
-msgid ""
-"Use -f if you really want to add them.\n"
-"Turn this message off by running\n"
-"\"git config advice.addIgnoredFile false\""
-msgstr ""
-"Sử dụng -f nếu bạn thực sự muốn thêm chúng.\n"
-"Tắt thông báo này bằng cách chạy lệnh\n"
-"\"git config advice.addIgnoredFile false\""
+msgid "Use -f if you really want to add them."
+msgstr "Dùng -f nếu bạn thực sự muốn thêm chúng"
msgid "adding files failed"
msgstr "thêm tập tin gặp lỗi"
#, c-format
msgid "--chmod param '%s' must be either -x or +x"
-msgstr "--chmod tham số “%s†phải hoặc là -x hay +x"
+msgstr "--chmod tham số '%s' phải hoặc là -x hay +x"
#, c-format
msgid "'%s' and pathspec arguments cannot be used together"
@@ -1855,21 +1908,18 @@ msgstr "'%s' và các tham số đặc tả Ä‘Æ°á»ng dẫn không thể dùng c
msgid "Nothing specified, nothing added.\n"
msgstr "Không có gì được chỉ ra, không có gì được thêm vào.\n"
-msgid ""
-"Maybe you wanted to say 'git add .'?\n"
-"Turn this message off by running\n"
-"\"git config advice.addEmptyPathspec false\""
-msgstr ""
-"Có lẽ bạn muốn chạy “git add .�\n"
-"Tắt thông báo này bằng cách chạy lệnh\n"
-"\"git config advice.addEmptyPathspec false\""
+msgid "Maybe you wanted to say 'git add .'?"
+msgstr "Có lẽ là bạn muốn dùng 'git add .'?"
msgid "index file corrupt"
-msgstr "tập tin ghi bảng mục lục bị há»ng"
+msgstr "tập tin ghi chỉ mục bị há»ng"
+
+msgid "unable to write new index file"
+msgstr "không thể ghi tập tin chỉ mục mới"
#, c-format
msgid "bad action '%s' for '%s'"
-msgstr "thao tác sai “%s†cho “%sâ€"
+msgstr "thao tác sai '%s' cho '%s'"
#, c-format
msgid "invalid value for '%s': '%s'"
@@ -1877,44 +1927,44 @@ msgstr "giá trị không hợp lệ cho '%s': '%s'"
#, c-format
msgid "could not read '%s'"
-msgstr "không thể Ä‘á»c “%sâ€"
+msgstr "không thể Ä‘á»c '%s'"
msgid "could not parse author script"
-msgstr "không thể phân tích cú pháp văn lệnh tác giả"
+msgstr "không hiểu cú pháp author script"
#, c-format
msgid "could not parse %s"
-msgstr "không thể phân tích cú pháp %s"
+msgstr "không hiểu cú pháp %s"
#, c-format
msgid "'%s' was deleted by the applypatch-msg hook"
-msgstr "“%s†bị xóa bởi móc applypatch-msg"
+msgstr "'%s' bị xóa bởi móc applypatch-msg"
#, c-format
msgid "Malformed input line: '%s'."
-msgstr "Dòng đầu vào dị hình: “%sâ€."
+msgstr "Dòng đầu vào sai quy cách: '%s'."
#, c-format
msgid "Failed to copy notes from '%s' to '%s'"
-msgstr "Gặp lá»—i khi sao chép ghi chú (note) từ “%s†tá»›i “%sâ€"
+msgstr "Gặp lỗi khi sao chép ghi chú (note) từ '%s' tới '%s'"
msgid "fseek failed"
msgstr "fseek gặp lỗi"
#, c-format
msgid "could not open '%s' for reading"
-msgstr "không thể mở “%s†để Ä‘á»c"
+msgstr "không thể mở '%s' để Ä‘á»c"
#, c-format
msgid "could not open '%s' for writing"
-msgstr "không thể mở “%s†để ghi"
+msgstr "không thể mở '%s' để ghi"
#, c-format
msgid "could not parse patch '%s'"
-msgstr "không thể phân tích cú pháp “%sâ€"
+msgstr "không hiểu cú pháp '%s'"
msgid "Only one StGIT patch series can be applied at once"
-msgstr "Chỉ có một sê-ri miếng vá StGIT được áp dụng một lúc"
+msgstr "Chỉ có một sê-ri bản vá StGIT được áp dụng một lúc"
msgid "invalid timestamp"
msgstr "dấu thá»i gian không hợp lệ"
@@ -1926,29 +1976,30 @@ msgid "invalid timezone offset"
msgstr "độ lệch múi giỠkhông hợp lệ"
msgid "Patch format detection failed."
-msgstr "Dò tìm định dạng miếng vá gặp lỗi."
+msgstr "Dò tìm định dạng bản vá gặp lỗi."
#, c-format
msgid "failed to create directory '%s'"
msgstr "tạo thư mục \"%s\" gặp lỗi"
msgid "Failed to split patches."
-msgstr "Gặp lỗi khi chia nhỠcác miếng vá."
+msgstr "Gặp lỗi khi chia nhỠcác bản vá."
#, c-format
-msgid "When you have resolved this problem, run \"%s --continue\"."
-msgstr "Khi bạn đã giải quyết xong trục trặc này, hãy chạy \"%s --continue\"."
+msgid "When you have resolved this problem, run \"%s --continue\".\n"
+msgstr ""
+"Sau khi bạn đã giải quyết xong vấn Ä‘á», hãy chạy lệnh\"%s --continue\".\n"
#, c-format
-msgid "If you prefer to skip this patch, run \"%s --skip\" instead."
-msgstr ""
-"Nếu bạn muốn bỠqua miếng vá này, hãy chạy lệnh \"%s --skip\" để thay thế."
+msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n"
+msgstr "Nếu bạn muốn bỠqua bản vá này, hãy chạy lệnh \"%s --skip\".\n"
#, c-format
-msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"."
+msgid ""
+"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"
msgstr ""
-"Äể ghi má»™t miếng vá trống rá»—ng nhÆ° má»™t lần chuyển giao rông, \"%s --allow-"
-"empty\"."
+"Äể ghi lại lần chuyển giao rá»—ng ứng vá»›i má»™t bản vá rá»—ng, hãy chạy \"%s --"
+"allow-empty\".\n"
#, c-format
msgid "To restore the original branch and stop patching, run \"%s --abort\"."
@@ -1956,7 +2007,7 @@ msgstr "Äể phục hồi lại nhánh gốc và dừng vá, hãy chạy \"%s -
msgid "Patch sent with format=flowed; space at the end of lines might be lost."
msgstr ""
-"Miếng vá được gửi với format=flowed; khoảng trống ở cuối của các dòng có thể "
+"bản vá được gửi với format=flowed; khoảng trống ở cuối của các dòng có thể "
"bị mất."
#, c-format
@@ -1969,24 +2020,24 @@ msgstr "dòng định danh không hợp lệ: %.*s"
#, c-format
msgid "unable to parse commit %s"
-msgstr "không thể phân tích lần chuyển giao “%sâ€"
+msgstr "không thể Ä‘á»c lần chuyển giao '%s'"
msgid "Repository lacks necessary blobs to fall back on 3-way merge."
-msgstr "Kho thiếu đối tượng blob cần thiết để thá»±c hiện “3-way mergeâ€."
+msgstr "Kho thiếu đối tượng blob cần thiết để thực hiện '3-way merge'."
msgid "Using index info to reconstruct a base tree..."
msgstr ""
-"Sử dụng thông tin trong bảng mục lục để cấu trúc lại một cây (tree) cơ sở…"
+"Sử dụng thông tin trong chỉ mục để cấu trúc lại một cây (tree) cơ sở..."
msgid ""
"Did you hand edit your patch?\n"
"It does not apply to blobs recorded in its index."
msgstr ""
-"Bạn đã sửa miếng vá của mình bằng cách thủ công à?\n"
-"Nó không thể áp dụng các blob đã được ghi lại trong bảng mục lục của nó."
+"Bạn đã sửa bản vá của mình bằng cách thủ công à?\n"
+"Nó không thể áp dụng các blob đã được ghi lại trong chỉ mục của nó."
msgid "Falling back to patching base and 3-way merge..."
-msgstr "Äang dùng phÆ°Æ¡ng án dá»± phòng: vá bản cÆ¡ sở và “hòa trá»™n 3-Ä‘Æ°á»ngâ€â€¦"
+msgstr "Äang dùng phÆ°Æ¡ng án dá»± phòng: vá bản cÆ¡ sở và 'hòa trá»™n 3-Ä‘Æ°á»ng'..."
msgid "Failed to merge in the changes."
msgstr "Gặp lỗi khi trộn vào các thay đổi."
@@ -2018,11 +2069,12 @@ msgstr ""
"cả [a]: "
msgid "unable to write index file"
-msgstr "không thể ghi tập tin lưu mục lục"
+msgstr "không thể ghi tập tin chỉ mục"
#, c-format
msgid "Dirty index: cannot apply patches (dirty: %s)"
-msgstr "Bảng mục lục bẩn: không thể áp dụng các miếng vá (bẩn: %s)"
+msgstr ""
+"chỉ mục không sạch sẽ: không thể áp dụng các bản vá (còn không sạch: %s)"
#, c-format
msgid "Skipping: %.*s"
@@ -2033,21 +2085,21 @@ msgid "Creating an empty commit: %.*s"
msgstr "Äang tạo má»™t lần chuyển giao trống rá»—ng: %.*s"
msgid "Patch is empty."
-msgstr "Miếng vá trống rỗng."
+msgstr "bản vá trống rỗng."
#, c-format
msgid "Applying: %.*s"
msgstr "Ãp dụng: %.*s"
msgid "No changes -- Patch already applied."
-msgstr "Không thay đổi gì cả -- Miếng vá đã được áp dụng rồi."
+msgstr "Không thay đổi gì cả -- bản vá đã được áp dụng rồi."
#, c-format
msgid "Patch failed at %s %.*s"
msgstr "Gặp lỗi khi vá tại %s %.*s"
msgid "Use 'git am --show-current-patch=diff' to see the failed patch"
-msgstr "Dùng “git am --show-current-patch=diff†để xem miếng vá bị lỗi"
+msgstr "Dùng 'git am --show-current-patch=diff' để xem bản vá bị lỗi"
msgid "No changes - recorded it as an empty commit."
msgstr "Không có thay đổi nào - được ghi thành một lần chuyển giao rỗng."
@@ -2057,7 +2109,7 @@ msgid ""
"If there is nothing left to stage, chances are that something else\n"
"already introduced the same changes; you might want to skip this patch."
msgstr ""
-"Không có thay đổi nào - bạn đã quên sử dụng lệnh “git add†à?\n"
+"Không có thay đổi nào - bạn đã quên sử dụng lệnh 'git add' à?\n"
"Nếu ở đây không có gì còn lại stage, tình cỠlà có một số thứ khác\n"
"đã sẵn được đưa vào với cùng nội dung thay đổi; bạn có lẽ muốn bỠqua miếng "
"vá này."
@@ -2069,38 +2121,31 @@ msgid ""
"You might run `git rm` on a file to accept \"deleted by them\" for it."
msgstr ""
"Bạn vẫn có những Ä‘Æ°á»ng dẫn chÆ°a hòa trá»™n trong chỉ mục của bạn.\n"
-"Bạn nên “git add†từng tập tin với các xung đột đã được giải quyết để đánh "
+"Bạn nên 'git add' từng tập tin với các xung đột đã được giải quyết để đánh "
"dấu chúng là thế.\n"
-"Bạn có lẽ muốn chạy “git rm“ trên má»™t tập tin để chấp nhận \"được xóa bởi há»"
-"\" cho nó."
-
-msgid "unable to write new index file"
-msgstr "không thể ghi tập tin lưu bảng mục lục mới"
+"Bạn có lẽ muốn chạy 'git rm' trên một tập tin để chấp nhận \"được xóa bởi "
+"há»\" cho nó."
#, c-format
msgid "Could not parse object '%s'."
-msgstr "Không thể phân tích đối tượng “%sâ€."
+msgstr "Không thể Ä‘á»c đối tượng '%s'."
msgid "failed to clean index"
-msgstr "gặp lá»—i khi dá»n bảng mục lục"
+msgstr "gặp lá»—i khi dá»n chỉ mục"
msgid ""
"You seem to have moved HEAD since the last 'am' failure.\n"
"Not rewinding to ORIG_HEAD"
msgstr ""
-"Bạn có lẽ đã có HEAD đã bị di chuyển đi kể từ lần “am†thất bại cuối cùng.\n"
+"Bạn có lẽ đã có HEAD đã bị di chuyển đi kể từ lần 'am' thất bại cuối cùng.\n"
"Không thể chuyển tới ORIG_HEAD"
#, c-format
msgid "failed to read '%s'"
-msgstr "gặp lá»—i khi Ä‘á»c “%sâ€"
-
-#, c-format
-msgid "options '%s=%s' and '%s=%s' cannot be used together"
-msgstr "tùy chá»n '%s=%s' và '%s=%s' không thể dùng cùng nhau"
+msgstr "gặp lá»—i khi Ä‘á»c '%s'"
msgid "git am [<options>] [(<mbox> | <Maildir>)...]"
-msgstr "git am [<các tùy chá»n>] [(<mbox>|<Maildir>)…]"
+msgstr "git am [<các tùy chá»n>] [(<mbox>|<Maildir>)...]"
msgid "git am [<options>] (--continue | --skip | --abort)"
msgstr "git am [<các tùy chá»n>] (--continue | --skip | --abort)"
@@ -2108,11 +2153,14 @@ msgstr "git am [<các tùy chá»n>] (--continue | --skip | --abort)"
msgid "run interactively"
msgstr "chạy kiểu tương tác"
+msgid "bypass pre-applypatch and applypatch-msg hooks"
+msgstr "bỠqua hook pre-applypatch và applypatch-msg"
+
msgid "historical option -- no-op"
-msgstr "tùy chá»n lịch sá»­ -- không-toán-tá»­"
+msgstr "tùy chá»n cÅ© -- không làm gì cả"
msgid "allow fall back on 3way merging if needed"
-msgstr "cho phép quay trở lại để hòa trộn kiểu “3way†nếu cần"
+msgstr "cho phép quay trở lại để hòa trộn kiểu 3way nếu cần"
msgid "be quiet"
msgstr "im lặng"
@@ -2135,10 +2183,6 @@ msgstr "chuyển cỠ-m cho git-mailinfo"
msgid "pass --keep-cr flag to git-mailsplit for mbox format"
msgstr "chuyển cỠ--keep-cr cho git-mailsplit với định dạng mbox"
-msgid "do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"
-msgstr ""
-"đừng chuyển cỠ--keep-cr cho git-mailsplit không phụ thuộc vào am.keepcr"
-
msgid "strip everything before a scissors line"
msgstr "cắt má»i thứ trÆ°á»›c dòng scissors"
@@ -2155,31 +2199,31 @@ msgid "format"
msgstr "định dạng"
msgid "format the patch(es) are in"
-msgstr "định dạng (các) miếng vá theo"
+msgstr "định dạng (các) bản vá theo"
msgid "override error message when patch failure occurs"
msgstr "đè lên các lá»i nhắn lá»—i khi xảy ra lá»—i vá nghiêm trá»ng"
msgid "continue applying patches after resolving a conflict"
-msgstr "tiếp tục áp dụng các miếng vá sau khi giải quyết xung đột"
+msgstr "tiếp tục áp dụng các bản vá sau khi giải quyết xung đột"
msgid "synonyms for --continue"
msgstr "đồng nghĩa với --continue"
msgid "skip the current patch"
-msgstr "bỠqua miếng vá hiện hành"
+msgstr "bỠqua bản vá hiện hành"
msgid "restore the original branch and abort the patching operation"
-msgstr "phục hồi lại nhánh gốc và loại bỠthao tác vá"
+msgstr "phục hồi lại nhánh gốc và huỷ thao tác vá"
msgid "abort the patching operation but keep HEAD where it is"
-msgstr "bỠqua thao tác vá nhưng vẫn giữ HEAD nơi nó chỉ đến"
+msgstr "huỷ thao tác vá nhưng vẫn giữ HEAD nơi nó chỉ đến"
msgid "show the patch being applied"
-msgstr "hiển thị miếng vá đã được áp dụng rồi"
+msgstr "hiển thị bản vá đã được áp dụng rồi"
msgid "record the empty patch as an empty commit"
-msgstr "ghi lại miếng vá trống rỗng như là một lần chuyển giao trống"
+msgstr "ghi lại bản vá trống rỗng như là một lần chuyển giao trống"
msgid "lie about committer date"
msgstr "nói dối vỠngày chuyển giao"
@@ -2194,7 +2238,7 @@ msgid "GPG-sign commits"
msgstr "Các lần chuyển giao ký-GPG"
msgid "how to handle empty patches"
-msgstr "xử lý các miếng vá trống rỗng như thế nào"
+msgstr "xử lý các bản vá trống rỗng như thế nào"
msgid "(internal use for git-rebase)"
msgstr "(dùng nội bộ cho git-rebase)"
@@ -2204,10 +2248,10 @@ msgid ""
"it will be removed. Please do not use it anymore."
msgstr ""
"Tùy chá»n -b/--binary đã không dùng từ lâu rồi, và\n"
-"nó sẽ được bỠđi. Xin đừng sử dụng nó thêm nữa."
+"nó sẽ được bỠđi. Xin đừng sử dụng nó nữa."
msgid "failed to read the index"
-msgstr "gặp lá»—i Ä‘á»c bảng mục lục"
+msgstr "gặp lá»—i Ä‘á»c chỉ mục"
#, c-format
msgid "previous rebase directory %s still exists but mbox given."
@@ -2222,16 +2266,16 @@ msgstr ""
"Dùng \"git am --abort\" để loại bỠnó đi."
msgid "Resolve operation not in progress, we are not resuming."
-msgstr "Thao tác phân giải không được tiến hành, chúng ta không phục hồi lại."
+msgstr "Thao tác phân giải không được tiến hành, sẽ không phục hồi lại."
msgid "interactive mode requires patches on the command line"
-msgstr "chế độ tương tác yêu cầu có các miếng vá trên dòng lệnh"
+msgstr "chế độ tương tác yêu cầu có các bản vá trên dòng lệnh"
msgid "git apply [<options>] [<patch>...]"
-msgstr "git apply [<các tùy chá»n>] [<miếng-vá>…]"
+msgstr "git apply [<các tùy chá»n>] [<miếng-vá>...]"
msgid "could not redirect output"
-msgstr "không thể chuyển hướng kết xuất"
+msgstr "không thể chuyển hướng đầu ra"
msgid "git archive: Remote with no URL"
msgstr "git archive: Máy chủ không có địa chỉ URL"
@@ -2247,58 +2291,53 @@ msgid "git archive: protocol error"
msgstr "git archive: lỗi giao thức"
msgid "git archive: expected a flush"
-msgstr "git archive: cần một flush (đẩy dữ liệu lên đĩa)"
-
-msgid "git bisect--helper --bisect-reset [<commit>]"
-msgstr "git bisect--helper --bisect-reset [<lần_chuyển_giao>]"
+msgstr "git archive: cần flush dữ liệu"
msgid ""
-"git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}"
-"=<term>] [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] "
-"[<paths>...]"
+"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-"
+"checkout] [--first-parent] [<bad> [<good>...]] [--] [<pathspec>...]"
msgstr ""
-"git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}"
-"=<term>] [--no-checkout] [--first-parent] [<bad> [<good>…]] [--] [</các/"
-"Ä‘Æ°á»ng/dẫn>…]"
+"git bisect start [--term-(new|bad)=<term> --term-(old|good)=<term>] [--no-"
+"checkout] [--first-parent] [<bad> [<good>...]] [--] [<Ä‘Æ°á»ng/dẫn>...]"
-msgid "git bisect--helper --bisect-state (bad|new) [<rev>]"
-msgstr "git bisect--helper --bisect-state (bad|new) [<lần_chuyển_giao>]"
+msgid "git bisect (good|bad) [<rev>...]"
+msgstr "git bisect (good|bad) [<rev>...]"
-msgid "git bisect--helper --bisect-state (good|old) [<rev>...]"
-msgstr "git bisect--helper --bisect-state (good|old) [<lần_chuyển_giao>…]"
+msgid "git bisect skip [(<rev>|<range>)...]"
+msgstr "git bisect skip [(<rev>|<vùng>)...]"
-msgid "git bisect--helper --bisect-replay <filename>"
-msgstr "git bisect--helper --bisect-replay <tên_tập_tin>"
+msgid "git bisect reset [<commit>]"
+msgstr "git bisect reset [<lần_chuyển_giao>]"
-msgid "git bisect--helper --bisect-skip [(<rev>|<range>)...]"
-msgstr "git bisect--helper --bisect-skip [(<rev>|<vùng>)…]"
+msgid "git bisect replay <logfile>"
+msgstr "git bisect replay <tên_tập tin>"
-msgid "git bisect--helper --bisect-run <cmd>..."
-msgstr "git bisect--helper --bisect-run <lệnh>…"
+msgid "git bisect run <cmd> [<arg>...]"
+msgstr "git bisect run <lệnh> [<đối_số>]..."
#, c-format
msgid "cannot open file '%s' in mode '%s'"
-msgstr "không thể mở tập tin “%s†ở chế Ä‘á»™ “%sâ€"
+msgstr "không thể mở tập tin '%s' ở chế độ '%s'"
#, c-format
msgid "could not write to file '%s'"
-msgstr "không thể ghi vào tập tin “%sâ€"
+msgstr "không thể ghi vào tập tin '%s'"
#, c-format
msgid "cannot open file '%s' for reading"
-msgstr "không thể mở tập tin “%s†để Ä‘á»c"
+msgstr "không thể mở tập tin '%s' để Ä‘á»c"
#, c-format
msgid "'%s' is not a valid term"
-msgstr "“%s†không phải má»™t thá»i hạn hợp lệ"
+msgstr "'%s' không phải má»™t thá»i hạn hợp lệ"
#, c-format
msgid "can't use the builtin command '%s' as a term"
-msgstr "không thể dùng lệnh tích hợp “%s†nhÆ° là má»™t thá»i kỳ"
+msgstr "không thể dùng lệnh tích hợp '%s' nhÆ° là má»™t thá»i kỳ"
#, c-format
msgid "can't change the meaning of the term '%s'"
-msgstr "không thể thay đổi nghÄ©a của thá»i kỳ “%sâ€"
+msgstr "không thể thay đổi nghÄ©a của thá»i kỳ '%s'"
msgid "please use two different terms"
msgstr "vui lòng dùng hai thá»i kỳ khác nhau"
@@ -2309,14 +2348,14 @@ msgstr "Chúng tôi đang không bisect.\n"
#, c-format
msgid "'%s' is not a valid commit"
-msgstr "“%s†không phải một lần chuyển giao hợp lệ"
+msgstr "'%s' không phải một lần chuyển giao hợp lệ"
#, c-format
msgid ""
"could not check out original HEAD '%s'. Try 'git bisect reset <commit>'."
msgstr ""
-"không thể lấy ra HEAD nguyên thủy của “%sâ€. Hãy thá»­ “git bisect reset <lần-"
-"chuyển-giao>â€."
+"không thể checkout HEAD nguyên thủy của '%s'. Hãy thử 'git bisect reset <lần-"
+"chuyển-giao>'."
#, c-format
msgid "Bad bisect_write argument: %s"
@@ -2324,11 +2363,11 @@ msgstr "Äối số bisect_write sai: %s"
#, c-format
msgid "couldn't get the oid of the rev '%s'"
-msgstr "không thể lấy oid của Ä‘iểm xét duyệt “%sâ€"
+msgstr "không thể lấy oid của điểm xét duyệt '%s'"
#, c-format
msgid "couldn't open the file '%s'"
-msgstr "không thể mở tập tin “%sâ€"
+msgstr "không thể mở tập tin '%s'"
#, c-format
msgid "Invalid command: you're currently in a %s/%s bisect"
@@ -2393,7 +2432,7 @@ msgid ""
"invalid argument %s for 'git bisect terms'.\n"
"Supported options are: --term-good|--term-old and --term-bad|--term-new."
msgstr ""
-"tham số không hợp lệ %s cho “git bisect termsâ€.\n"
+"tham số không hợp lệ %s cho 'git bisect terms'.\n"
"Các tùy chá»n há»— trợ là: --term-good|--term-old và --term-bad|--term-new."
msgid "revision walk setup failed\n"
@@ -2401,35 +2440,32 @@ msgstr "gặp lỗi cài đặt việc di chuyển qua các điểm xét duyệt
#, c-format
msgid "could not open '%s' for appending"
-msgstr "không thể mở “%s†để nối thêm"
+msgstr "không thể mở '%s' để nối thêm"
msgid "'' is not a valid term"
-msgstr "†không phải má»™t thá»i hạn hợp lệ"
+msgstr "'' không phải term hợp lệ"
#, c-format
msgid "unrecognized option: '%s'"
-msgstr "tùy chá»n không được thừa nhận: “%sâ€"
+msgstr "không nhận ra tuỳ chá»n: '%s'"
#, c-format
msgid "'%s' does not appear to be a valid revision"
-msgstr "“%s†không có vẻ như là một điểm xét duyệt hợp lệ"
+msgstr "'%s' không có vẻ như là một điểm xét duyệt hợp lệ"
msgid "bad HEAD - I need a HEAD"
msgstr "sai HEAD - Tôi cần một HEAD"
#, c-format
msgid "checking out '%s' failed. Try 'git bisect start <valid-branch>'."
-msgstr "lấy ra “%s†ra gặp lỗi. Hãy thử \"git bisect reset <nhánh_hợp_lệ>\"."
-
-msgid "won't bisect on cg-seek'ed tree"
-msgstr "sẽ không di chuyển nửa bước trên cây được cg-seek"
+msgstr "checkout '%s' ra gặp lỗi. Hãy thử \"git bisect reset <nhánh_hợp_lệ>\"."
msgid "bad HEAD - strange symbolic ref"
msgstr "sai HEAD - tham chiếu má»m kỳ lạ"
#, c-format
msgid "invalid ref: '%s'"
-msgstr "refspec không hợp lệ: “%sâ€"
+msgstr "refspec không hợp lệ: '%s'"
msgid "You need to start by \"git bisect start\"\n"
msgstr "Bạn cần khởi đầu bằng \"git bisect start\"\n"
@@ -2442,11 +2478,11 @@ msgid "Do you want me to do it for you [Y/n]? "
msgstr "Bạn có muốn tôi thá»±c hiện Ä‘iá»u này cho bạn không [Y/n]? "
msgid "Please call `--bisect-state` with at least one argument"
-msgstr "Hãy gá»i “--bisect-state†vá»›i ít nhất má»™t đối số"
+msgstr "Hãy gá»i '--bisect-state' vá»›i ít nhất má»™t đối số"
#, c-format
msgid "'git bisect %s' can take only one argument."
-msgstr "“git bisect %s†có thể lấy chỉ một đối số."
+msgstr "'git bisect %s' có thể lấy chỉ một đối số."
#, c-format
msgid "Bad rev input: %s"
@@ -2461,11 +2497,11 @@ msgstr "Chúng tôi không bisect."
#, c-format
msgid "'%s'?? what are you talking about?"
-msgstr "“%s�? bạn đang nói gì thế?"
+msgstr "'%s'?? bạn đang nói gì thế?"
#, c-format
msgid "cannot read file '%s' for replaying"
-msgstr "không thể Ä‘á»c tập tin “%s†để thao diá»…n lại"
+msgstr "không thể Ä‘á»c tập tin '%s' để thao diá»…n lại"
#, c-format
msgid "running %s\n"
@@ -2475,97 +2511,68 @@ msgid "bisect run failed: no command provided."
msgstr "bisect chạy gặp lỗi: không đưa ra lệnh."
#, c-format
-msgid "unable to verify '%s' on good revision"
-msgstr "không thể xác nhận “%s†trên điểm xét duyệt tốt"
+msgid "unable to verify %s on good revision"
+msgstr "không thể xác nhận '%s' trên điểm xét duyệt tốt"
#, c-format
msgid "bogus exit code %d for good revision"
-msgstr "mã thoát giả %d cho điểm xét duyệt tốt"
+msgstr "mã trả vá» %d bất thÆ°á»ng cho Ä‘iểm xét duyệt tốt"
#, c-format
-msgid "bisect run failed: exit code %d from '%s' is < 0 or >= 128"
-msgstr "chạy bisect gặp lỗi: mã trả vỠ%d từ lệnh “%s†là < 0 hoặc >= 128"
+msgid "bisect run failed: exit code %d from %s is < 0 or >= 128"
+msgstr "bisect gặp lỗi: mã trả vỠ%d từ lệnh '%s' < 0 hoặc >= 128"
#, c-format
msgid "cannot open file '%s' for writing"
-msgstr "không thể mở “%s†để ghi"
+msgstr "không thể mở '%s' để ghi"
msgid "bisect run cannot continue any more"
-msgstr "bisect không thể tiếp tục thêm được nữa"
+msgstr "không thể tiếp tục bisect thêm được nữa"
-#, c-format
msgid "bisect run success"
-msgstr "bisect chạy thành công"
+msgstr "bisect thành công"
-#, c-format
msgid "bisect found first bad commit"
msgstr "bisect tìm thấy lần chuyển giao sai đầu tiên"
#, c-format
-msgid ""
-"bisect run failed: 'git bisect--helper --bisect-state %s' exited with error "
-"code %d"
-msgstr ""
-"chạy bisect gặp lỗi: “git bisect--helper --bisect-state %s†đã thoát ra với "
-"mã lỗi %d"
-
-msgid "reset the bisection state"
-msgstr "đặt lại trạng di chuyển nửa bước"
-
-msgid "check whether bad or good terms exist"
-msgstr "kiểm tra xem các thá»i Ä‘iểm xấu/tốt có tồn tại không"
-
-msgid "print out the bisect terms"
-msgstr "in ra các thá»i Ä‘iểm di chuyển ná»­a bÆ°á»›c"
-
-msgid "start the bisect session"
-msgstr "bắt đầu phiên di chuyển nửa bước"
-
-msgid "find the next bisection commit"
-msgstr "tìm lần chuyển giao không di chuyển phân đôi"
-
-msgid "mark the state of ref (or refs)"
-msgstr "đánh dấu trạng thái ref (hoặc refs)"
-
-msgid "list the bisection steps so far"
-msgstr "liệt kê các bước bisection đi quá xa"
-
-msgid "replay the bisection process from the given file"
-msgstr "phát lại quá trình bisection từ tệp đã cho"
-
-msgid "skip some commits for checkout"
-msgstr "bỠqua một số lần chuyển giao để lấy ra"
+msgid "bisect run failed: 'git bisect %s' exited with error code %d"
+msgstr "bisect gặp lỗi: 'git bisect %s' đã thoát với mã lỗi %d"
-msgid "visualize the bisection"
-msgstr "trực quan việc di chuyển nửa bước"
-
-msgid "use <cmd>... to automatically bisect"
-msgstr "dùng <cmd>… để bisect một cách tự động"
+#, c-format
+msgid "'%s' requires either no argument or a commit"
+msgstr "'%s' không nhận đối số hay lần chuyển giao"
-msgid "no log for BISECT_WRITE"
-msgstr "không có nhật ký cho BISECT_WRITE"
+#, c-format
+msgid "'%s' requires 0 or 1 argument"
+msgstr "%s cần 0 hoặc 1 tham số"
-msgid "--bisect-reset requires either no argument or a commit"
-msgstr ""
-"--bisect-reset requires không nhận đối số cũng không nhận lần chuyển giao"
+#, c-format
+msgid "'%s' requires 0 arguments"
+msgstr "%s không cần tham số"
-msgid "--bisect-terms requires 0 or 1 argument"
-msgstr "--bisect-terms cần 0 hoặc 1 tham số"
+msgid "no logfile given"
+msgstr "chưa chỉ ra tập tin ghi nhật ký"
-msgid "--bisect-next requires 0 arguments"
-msgstr "--bisect-next cần 0 tham số"
+#, c-format
+msgid "'%s' failed: no command provided."
+msgstr "'%s' gặp lỗi: không chỉ ra lệnh."
-msgid "--bisect-log requires 0 arguments"
-msgstr "--bisect-log cần 0 tham số"
+msgid "need a command"
+msgstr "cần chỉ ra lệnh"
-msgid "no logfile given"
-msgstr "chưa chỉ ra tập tin ghi nhật ký"
+#, c-format
+msgid "unknown command: '%s'"
+msgstr "không hiểu câu lệnh: '%s'"
msgid "git blame [<options>] [<rev-opts>] [<rev>] [--] <file>"
msgstr "git blame [<các tùy chá»n>] [<rev-opts>] [<rev>] [--] <tập-tin>"
+msgid "git annotate [<options>] [<rev-opts>] [<rev>] [--] <file>"
+msgstr "git annotate [<các tùy chá»n>] [<rev-opts>] [<rev>] [--] <tập-tin>"
+
msgid "<rev-opts> are documented in git-rev-list(1)"
-msgstr "<rev-opts> được mô tả trong tài liệu git-rev-list(1)"
+msgstr "<rev-opts> được mô tả trong git-rev-list(1)"
#, c-format
msgid "expecting a color: %s"
@@ -2576,10 +2583,10 @@ msgstr "phải kết thúc bằng một màu"
#, c-format
msgid "cannot find revision %s to ignore"
-msgstr "không thể tìm thấy điểm xét duyệt %s để mà bỠqua"
+msgstr "không thể tìm thấy điểm xét duyệt %s để bỠqua"
msgid "show blame entries as we find them, incrementally"
-msgstr "hiển thị các mục “blame†như là chúng ta thấy chúng, tăng dần"
+msgstr "hiển thị các mục 'blame' theo thá»i gian, tăng dần"
msgid "do not show object names of boundary commits (Default: off)"
msgstr ""
@@ -2593,10 +2600,10 @@ msgid "show work cost statistics"
msgstr "hiển thị thống kê công sức làm việc"
msgid "force progress reporting"
-msgstr "ép buộc báo cáo tiến triển công việc"
+msgstr "ép buộc báo cáo tiến độ công việc"
msgid "show output score for blame entries"
-msgstr "hiển thị kết xuất Ä‘iểm số cho các mục tin “blameâ€"
+msgstr "hiển thị kết xuất điểm số cho các mục tin 'blame'"
msgid "show original filename (Default: auto)"
msgstr "hiển thị tên tập tin gốc (Mặc định: auto)"
@@ -2608,7 +2615,7 @@ msgid "show in a format designed for machine consumption"
msgstr "hiển thị ở định dạng đã thiết kế cho dùng bằng máy"
msgid "show porcelain format with per-line commit information"
-msgstr "hiển thị định dạng “porcelain†với thông tin chuyển giao mỗi dòng"
+msgstr "hiển thị định dạng 'porcelain' với thông tin chuyển giao mỗi dòng"
msgid "use the same output mode as git-annotate (Default: off)"
msgstr "dùng cùng chế độ xuất ra với git-annotate (Mặc định: off)"
@@ -2648,7 +2655,7 @@ msgstr "tiêu thụ thêm năng tài nguyên máy móc để tìm kiếm tốt h
msgid "use revisions from <file> instead of calling git-rev-list"
msgstr ""
-"sá»­ dụng các Ä‘iểm xét duyệt (revision) từ <tập tin> thay vì gá»i “git-rev-listâ€"
+"sá»­ dụng các Ä‘iểm xét duyệt (revision) từ <tập tin> thay vì gá»i 'git-rev-list'"
msgid "use <file>'s contents as the final image"
msgstr "sử dụng nội dung của <tập tin> như là ảnh cuối cùng"
@@ -2681,7 +2688,7 @@ msgstr ""
#. columns.
#.
msgid "4 years, 11 months ago"
-msgstr "4 năm, 11 tháng trước"
+msgstr "11 tháng, 28 ngày trước"
#, c-format
msgid "file %s has only %lu line"
@@ -2705,7 +2712,7 @@ msgid "git branch [<options>] [-l] [<pattern>...]"
msgstr "git branch [<các tùy chá»n>] [-l] [<mẫu>...]"
msgid "git branch [<options>] [-r] (-d | -D) <branch-name>..."
-msgstr "git branch [<các tùy chá»n>] [-r] (-d | -D) <tên-nhánh> …"
+msgstr "git branch [<các tùy chá»n>] [-r] (-d | -D) <tên-nhánh> ..."
msgid "git branch [<options>] (-m | -M) [<old-branch>] <new-branch>"
msgstr "git branch [<các tùy chá»n>] (-m | -M) [<nhánh-cÅ©>] <nhánh-má»›i>"
@@ -2722,51 +2729,56 @@ msgstr "git branch [<các tùy chá»n>] [-r | -a] [--format]"
#, c-format
msgid ""
"deleting branch '%s' that has been merged to\n"
-" '%s', but not yet merged to HEAD."
+" '%s', but not yet merged to HEAD"
msgstr ""
-"đang xóa nhánh “%s†mà nó lại đã được hòa trộn vào\n"
-" “%sâ€, nhÆ°ng vẫn chÆ°a được hòa trá»™n vào HEAD."
+"đang xóa nhánh '%s' đã được hòa trộn vào\n"
+" '%s', nhưng vẫn chưa được hòa trộn vào HEAD."
#, c-format
msgid ""
"not deleting branch '%s' that is not yet merged to\n"
-" '%s', even though it is merged to HEAD."
+" '%s', even though it is merged to HEAD"
msgstr ""
-"không xóa nhánh “%s†cái mà chưa được hòa trộn vào\n"
-" “%sâ€, cho dù là nó đã được hòa trá»™n vào HEAD."
+"không xóa nhánh '%s' chưa được hòa trộn vào\n"
+" '%s', dù đã được hòa trộn vào HEAD."
#, c-format
-msgid "Couldn't look up commit object for '%s'"
-msgstr "Không thể tìm kiếm đối tượng chuyển giao cho “%sâ€"
+msgid "couldn't look up commit object for '%s'"
+msgstr "Không thể tìm kiếm đối tượng chuyển giao cho '%s'"
#, c-format
-msgid ""
-"The branch '%s' is not fully merged.\n"
-"If you are sure you want to delete it, run 'git branch -D %s'."
-msgstr ""
-"Nhánh “%s†không được trộn một cách đầy đủ.\n"
-"Nếu bạn thá»±c sá»± muốn xóa nó, thì chạy lệnh “git branch -D %sâ€."
+msgid "the branch '%s' is not fully merged"
+msgstr "nhánh '%s' chưa được hoà trộn."
+
+#, c-format
+msgid "If you are sure you want to delete it, run 'git branch -D %s'"
+msgstr "Nếu bạn thực sự muốn xóa nó, hãy chạy lệnh 'git branch -D %s'."
-msgid "Update of config-file failed"
-msgstr "Cập nhật tập tin cấu hình gặp lỗi"
+msgid "update of config-file failed"
+msgstr "cập nhật tập tin cấu hình gặp lỗi"
msgid "cannot use -a with -d"
msgstr "không thể dùng tùy chá»n -a vá»›i -d"
-msgid "Couldn't look up commit object for HEAD"
-msgstr "Không thể tìm kiếm đối tượng chuyển giao cho HEAD"
+#, c-format
+msgid "cannot delete branch '%s' used by worktree at '%s'"
+msgstr "chông thể xóa nhánh '%s' đang được sử dụng tại cây làm việc '%s'"
#, c-format
-msgid "Cannot delete branch '%s' checked out at '%s'"
-msgstr "Không thể xóa nhánh “%s†đã được lấy ra tại “%sâ€"
+msgid "remote-tracking branch '%s' not found"
+msgstr "không tìm thấy nhánh theo dõi máy chủ '%s'."
#, c-format
-msgid "remote-tracking branch '%s' not found."
-msgstr "không tìm thấy nhánh theo dõi máy chủ “%sâ€."
+msgid ""
+"branch '%s' not found.\n"
+"Did you forget --remote?"
+msgstr ""
+"không tìm thấy nhánh '%s'.\n"
+"Bạn có quên dùng --remote không?"
#, c-format
-msgid "branch '%s' not found."
-msgstr "không tìm thấy nhánh “%sâ€."
+msgid "branch '%s' not found"
+msgstr "không tìm thấy nhánh '%s'."
#, c-format
msgid "Deleted remote-tracking branch %s (was %s).\n"
@@ -2774,10 +2786,10 @@ msgstr "Äã xóa nhánh theo dõi máy chủ \"%s\" (từng là %s).\n"
#, c-format
msgid "Deleted branch %s (was %s).\n"
-msgstr "Nhánh “%s†đã bị xóa (từng là %s)\n"
+msgstr "Nhánh '%s' đã bị xóa (từng là %s)\n"
msgid "unable to parse format string"
-msgstr "không thể phân tích chuỗi định dạng"
+msgstr "không thể Ä‘á»c chuá»—i định dạng"
msgid "could not resolve HEAD"
msgstr "không thể phân giải HEAD"
@@ -2787,56 +2799,62 @@ msgid "HEAD (%s) points outside of refs/heads/"
msgstr "HEAD (%s) chỉ bên ngoài của refs/heads/"
#, c-format
-msgid "Branch %s is being rebased at %s"
-msgstr "Nhánh %s đang được cải tổ lại tại %s"
+msgid "branch %s is being rebased at %s"
+msgstr "Nhánh %s đang được cải tổ tại %s"
+
+#, c-format
+msgid "branch %s is being bisected at %s"
+msgstr "Nhánh %s đang được bisect tại %s"
#, c-format
-msgid "Branch %s is being bisected at %s"
-msgstr "Nhánh %s đang được di chuyển phân đôi (bisect) tại %s"
+msgid "HEAD of working tree %s is not updated"
+msgstr "HEAD của cây làm việc %s chưa được cập nhật"
-msgid "cannot copy the current branch while not on any."
-msgstr "không thể sao chép nhánh hiện hành trong khi nó chẳng ở đâu cả."
+#, c-format
+msgid "invalid branch name: '%s'"
+msgstr "tên nhánh không hợp lệ: '%s'"
-msgid "cannot rename the current branch while not on any."
-msgstr "không thể đổi tên nhánh hiện hành trong khi nó chẳng ở đâu cả."
+#, c-format
+msgid "no commit on branch '%s' yet"
+msgstr "vẫn chưa chuyển giao trên nhánh '%s'."
#, c-format
-msgid "Invalid branch name: '%s'"
-msgstr "Tên nhánh không hợp lệ: “%sâ€"
+msgid "no branch named '%s'"
+msgstr "không có nhánh nào có tên '%s'."
-msgid "Branch rename failed"
-msgstr "Gặp lỗi khi đổi tên nhánh"
+msgid "branch rename failed"
+msgstr "gặp lỗi khi đổi tên nhánh"
-msgid "Branch copy failed"
-msgstr "Gặp lỗi khi sao chép nhánh"
+msgid "branch copy failed"
+msgstr "gặp lỗi khi sao chép nhánh"
#, c-format
-msgid "Created a copy of a misnamed branch '%s'"
-msgstr "Äã tạo má»™t bản sao của nhánh khuyết danh “%sâ€"
+msgid "created a copy of a misnamed branch '%s'"
+msgstr "đã tạo một bản sao của nhánh khuyết danh '%s'"
#, c-format
-msgid "Renamed a misnamed branch '%s' away"
-msgstr "Äã đổi tên nhánh khuyết danh “%s†đi"
+msgid "renamed a misnamed branch '%s' away"
+msgstr "đã đổi tên nhánh khuyết danh '%s'"
#, c-format
-msgid "Branch renamed to %s, but HEAD is not updated!"
-msgstr "Nhánh bị đổi tên thành %s, nhưng HEAD lại không được cập nhật!"
+msgid "branch renamed to %s, but HEAD is not updated"
+msgstr "đã đổi tên nhánh thành %s, nhưng HEAD không được cập nhật"
-msgid "Branch is renamed, but update of config-file failed"
-msgstr "Nhánh bị đổi tên, nhưng cập nhật tập tin cấu hình gặp lỗi"
+msgid "branch is renamed, but update of config-file failed"
+msgstr "đã đổi tên nhánh, nhưng cập nhật tập tin cấu hình gặp lỗi"
-msgid "Branch is copied, but update of config-file failed"
-msgstr "Nhánh đã được sao chép, nhưng cập nhật tập tin cấu hình gặp lỗi"
+msgid "branch is copied, but update of config-file failed"
+msgstr "đã sao chép nhánh, nhưng cập nhật tập tin cấu hình gặp lỗi"
#, c-format
msgid ""
"Please edit the description for the branch\n"
" %s\n"
-"Lines starting with '%c' will be stripped.\n"
+"Lines starting with '%s' will be stripped.\n"
msgstr ""
-"Viết các ghi chú cho nhánh:\n"
+"Viết các ghi chú cho nhánh\n"
" %s\n"
-"Những dòng được bắt đầu bằng “%c†sẽ được cắt bá».\n"
+"Những dòng được bắt đầu bằng '%s' sẽ được cắt bá».\n"
msgid "Generic options"
msgstr "Tùy chá»n chung"
@@ -2866,7 +2884,7 @@ msgid "use colored output"
msgstr "tô màu kết xuất"
msgid "act on remote-tracking branches"
-msgstr "thao tác trên nhánh “remote-trackingâ€"
+msgstr "thao tác trên nhánh 'remote-tracking'"
msgid "print only branches that contain the commit"
msgstr "chỉ hiển thị những nhánh mà nó chứa lần chuyển giao"
@@ -2878,7 +2896,7 @@ msgid "Specific git-branch actions:"
msgstr "Hành động git-branch:"
msgid "list both remote-tracking and local branches"
-msgstr "liệt kê cả nhánh “remote-tracking†và nội bộ"
+msgstr "liệt kê cả nhánh 'remote-tracking' và nội bộ"
msgid "delete fully merged branch"
msgstr "xóa một toàn bộ nhánh đã hòa trộn"
@@ -2892,6 +2910,9 @@ msgstr "di chuyển hay đổi tên một nhánh và reflog của nó"
msgid "move/rename a branch, even if target exists"
msgstr "di chuyển hoặc đổi tên một nhánh ngay cả khi đích đã có sẵn"
+msgid "do not output a newline after empty formatted refs"
+msgstr "không in ra ký tự xuống dòng sau tham chiếu rỗng"
+
msgid "copy a branch and its reflog"
msgstr "sao chép một nhánh và reflog của nó"
@@ -2937,8 +2958,8 @@ msgstr "đệ quy xuyên qua mô-đun con"
msgid "format to use for the output"
msgstr "định dạng sẽ dùng cho đầu ra"
-msgid "Failed to resolve HEAD as a valid ref."
-msgstr "Gặp lỗi khi phân giải HEAD như là một tham chiếu hợp lệ."
+msgid "failed to resolve HEAD as a valid ref"
+msgstr "gặp lỗi khi phân giải HEAD thành một tham chiếu hợp lệ."
msgid "HEAD not found below refs/heads!"
msgstr "Không tìm thấy HEAD ở dưới refs/heads!"
@@ -2956,22 +2977,20 @@ msgstr "--recurse-submodules chỉ có thể được sử dụng để tạo ra
msgid "branch name required"
msgstr "cần chỉ ra tên nhánh"
-msgid "Cannot give description to detached HEAD"
-msgstr "Không thể Ä‘Æ°a ra mô tả HEAD đã tách rá»i"
+msgid "cannot give description to detached HEAD"
+msgstr "không thể Ä‘Æ°a ra mô tả cho HEAD đã tách rá»i"
msgid "cannot edit description of more than one branch"
msgstr "không thể sá»­a mô tả cho nhiá»u hÆ¡n má»™t nhánh"
-#, c-format
-msgid "No commit on branch '%s' yet."
-msgstr "Vẫn chÆ°a chuyển giao trên nhánh “%sâ€."
+msgid "cannot copy the current branch while not on any"
+msgstr "không thể sao chép nhánh hiện hành khi đang không ở trên nhánh nào."
-#, c-format
-msgid "No branch named '%s'."
-msgstr "Không có nhánh nào có tên “%sâ€."
+msgid "cannot rename the current branch while not on any"
+msgstr "không thể đổi tên nhánh hiện hành khi đang không ở trên nhánh nào."
msgid "too many branches for a copy operation"
-msgstr "quá nhiá»u nhánh dành cho thao tác sao chép"
+msgstr "quá nhiá»u nhánh cho thao tác sao chép"
msgid "too many arguments for a rename operation"
msgstr "quá nhiá»u tham số cho thao tác đổi tên"
@@ -2981,50 +3000,48 @@ msgstr "quá nhiá»u tham số để đặt thượng nguồn má»›i"
#, c-format
msgid ""
-"could not set upstream of HEAD to %s when it does not point to any branch."
+"could not set upstream of HEAD to %s when it does not point to any branch"
msgstr ""
-"không thể đặt thượng nguồn của HEAD thành %s khi mà nó chẳng chỉ đến nhánh "
-"nào cả."
+"không thể đặt thượng nguồn của HEAD thành %s khi nó không chỉ đến nhánh nào."
#, c-format
msgid "no such branch '%s'"
-msgstr "không có nhánh nào nhÆ° thế “%sâ€"
+msgstr "không có nhánh nào tên '%s'"
#, c-format
msgid "branch '%s' does not exist"
-msgstr "chÆ°a có nhánh “%sâ€"
+msgstr "chưa có nhánh '%s'"
msgid "too many arguments to unset upstream"
msgstr "quá nhiá»u tham số để bỠđặt thượng nguồn"
-msgid "could not unset upstream of HEAD when it does not point to any branch."
-msgstr "không thể bỠđặt thượng nguồn của HEAD không chỉ đến một nhánh nào cả."
+msgid "could not unset upstream of HEAD when it does not point to any branch"
+msgstr "không thể bỠđặt thượng nguồn của HEAD khi nó không chỉ đến nhánh nào."
#, c-format
-msgid "Branch '%s' has no upstream information"
-msgstr "Nhánh “%s†không có thông tin thượng nguồn"
+msgid "branch '%s' has no upstream information"
+msgstr "nhánh '%s' không có thông tin thượng nguồn"
msgid ""
-"The -a, and -r, options to 'git branch' do not take a branch name.\n"
+"the -a, and -r, options to 'git branch' do not take a branch name.\n"
"Did you mean to use: -a|-r --list <pattern>?"
msgstr ""
-"Hai tùy chá»n -a và -r áp dụng cho lệnh “git branch†không nhận má»™t tên "
-"nhánh.\n"
-"Có phải ý bạn là dùng: -a|-r --list <mẫu>?"
+"Hai tùy chá»n -a, và -r, cho lệnh 'git branch' không nhận má»™t tên nhánh.\n"
+"Có phải ý bạn là: -a|-r --list <mẫu>?"
msgid ""
"the '--set-upstream' option is no longer supported. Please use '--track' or "
-"'--set-upstream-to' instead."
+"'--set-upstream-to' instead"
msgstr ""
-"tùy chá»n --set-upstream đã không còn được há»— trợ nữa. Vui lòng dùng “--"
-"track†hoặc “--set-upstream-to†để thay thế."
+"tùy chá»n --set-upstream đã không còn được há»— trợ nữa. Vui lòng dùng '--"
+"track' hoặc '--set-upstream-to'"
msgid "git version:\n"
msgstr "phiên bản git:\n"
#, c-format
msgid "uname() failed with error '%s' (%d)\n"
-msgstr "uname() gặp lỗi “%s†(%d)\n"
+msgstr "uname() gặp lỗi '%s' (%d)\n"
msgid "compiler info: "
msgstr "thông tin trình biên dịch: "
@@ -3033,11 +3050,16 @@ msgid "libc info: "
msgstr "thông tin libc: "
msgid "not run from a git repository - no hooks to show\n"
-msgstr "không chạy từ một kho git - nên chẳng có móc nào để mà hiển thị cả\n"
+msgstr "không chạy từ một kho git - nên chẳng có móc nào để hiển thị cả\n"
-msgid "git bugreport [-o|--output-directory <file>] [-s|--suffix <format>]"
+msgid ""
+"git bugreport [(-o | --output-directory) <path>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
+" [--diagnose[=<mode>]]"
msgstr ""
-"git bugreport [-o|--output-directory <tập_tin>] [-s|--suffix <định_dạng>]"
+"git bugreport [(-o | --output-directory) <Ä‘Æ°á»ng dẫn>]\n"
+" [(-s | --suffix) <định dạng> | --no-suffix]\n"
+" [--diagnose[=<chế độ>]]"
msgid ""
"Thank you for filling out a Git bug report!\n"
@@ -3059,29 +3081,45 @@ msgstr ""
"Cảm ơn bạn đã tạo một báo cáo lỗi Git!\n"
"Vui lòng trả lá»i các câu há»i sau để giúp chúng tôi hiểu vấn Ä‘á» của bạn.\n"
"\n"
-"Bạn đã làm gì trước khi lỗi xảy ra? (Các bước để tái tạo sự cố của bạn)\n"
+"Bạn đã làm gì trước khi lỗi xảy ra? (Các bước để tái hiện sự cố của bạn)\n"
"\n"
"Äiá»u bạn mong muốn xảy ra? (Hành vi dá»± kiến)\n"
"\n"
-"Äiá»u gì đã xảy ra thay thế? (Hành vi thá»±c tế)\n"
+"Äiá»u gì đã xảy ra? (Hành vi thá»±c tế)\n"
"\n"
"Có gì khác biệt giữa những gì bạn mong đợi và những gì thực sự xảy ra?\n"
"\n"
-"Bất kỳ thứ gì khác bạn muốn thêm:\n"
+"Những thứ khác bạn muốn thêm:\n"
"\n"
-"Vui lòng xen xét phần còn lại của báo cáo lỗi bên dưới.\n"
+"Vui lòng xem xét phần còn lại của báo cáo lỗi bên dưới.\n"
"Bạn có thể xóa bất kỳ dòng nào bạn không muốn chia sẻ.\n"
-msgid "specify a destination for the bugreport file"
-msgstr "chỉ định thư mục định để tạo tập tin báo cáo lỗi"
+msgid "mode"
+msgstr "chế độ"
-msgid "specify a strftime format suffix for the filename"
+msgid ""
+"create an additional zip archive of detailed diagnostics (default 'stats')"
+msgstr ""
+"tạo thêm tập tin nén zip của bản báo cáo chi tiết hơn (mặc định 'stats')"
+
+msgid "specify a destination for the bugreport file(s)"
+msgstr "chỉ định thư mục đích để tạo tập tin báo cáo lỗi"
+
+msgid "specify a strftime format suffix for the filename(s)"
msgstr ""
"chỉ định chuá»—i định dạng thá»i gian strftime dùng làm hậu tố cho tên tập tin"
#, c-format
+msgid "unknown argument `%s'"
+msgstr "không hiểu đối số: '%s'"
+
+#, c-format
msgid "could not create leading directories for '%s'"
-msgstr "không thể tạo các thÆ° mục dẫn đầu cho “%sâ€"
+msgstr "không thể tạo các thư mục cha cho '%s'"
+
+#, c-format
+msgid "unable to create diagnostics archive %s"
+msgstr "không thể tạo bản báo cáo %s"
msgid "System Info"
msgstr "Thông tin hệ thống"
@@ -3095,34 +3133,41 @@ msgstr "không thể ghi vào %s"
#, c-format
msgid "Created new report at '%s'.\n"
-msgstr "Äã tạo báo cáo má»›i tại “%sâ€\n"
+msgstr "Äã tạo báo cáo má»›i tại '%s'\n"
-msgid "git bundle create [<options>] <file> <git-rev-list args>"
-msgstr "git bundle create [<các tùy chá»n>] <tập_tin> <git-rev-list args>"
+msgid ""
+"git bundle create [-q | --quiet | --progress]\n"
+" [--version=<version>] <file> <git-rev-list-args>"
+msgstr ""
+"git bundle create [-q | --quiet | --progress]\n"
+" [--version=<phiên_bản>] <tập tin> <đối-số-git-rev-list>"
-msgid "git bundle verify [<options>] <file>"
-msgstr "git bundle verify [<các tùy chá»n>] <tập-tin>"
+msgid "git bundle verify [-q | --quiet] <file>"
+msgstr "git bundle verify [-q | --quiet] <tập-tin>"
msgid "git bundle list-heads <file> [<refname>...]"
-msgstr "git bundle list-heads <tập tin> [<tên tham chiếu>…]"
+msgstr "git bundle list-heads <tập tin> [<tên tham chiếu>...]"
+
+msgid "git bundle unbundle [--progress] <file> [<refname>...]"
+msgstr "git bundle unbundle [--progress] <tập tin> [<tên tham chiếu>...]"
-msgid "git bundle unbundle <file> [<refname>...]"
-msgstr "git bundle unbundle <tập tin> [<tên tham chiếu>…]"
+msgid "need a <file> argument"
+msgstr "cần tham số <tập_tin>"
msgid "do not show progress meter"
-msgstr "không hiển thị bộ đo tiến trình"
+msgstr "không hiển thị thanh đo tiến độ"
msgid "show progress meter"
-msgstr "hiển thị bộ đo tiến trình"
+msgstr "hiển thị thanh đo tiến độ"
-msgid "show progress meter during object writing phase"
-msgstr "hiển thị bộ đo tiến triển trong suốt pha ghi đối tượng"
+msgid "historical; same as --progress"
+msgstr "tuỳ chá»n cÅ©; giống nhÆ° --progress"
-msgid "similar to --all-progress when progress meter is shown"
-msgstr "tương tự --all-progress khi bộ đo tiến trình được xuất hiện"
+msgid "historical; does nothing"
+msgstr "tuỳ chá»n cÅ©; không làm gì cả"
msgid "specify bundle format version"
-msgstr "chỉ điịnh định dạng cho bundle"
+msgstr "chỉ định phiên bản định dạng bundle"
msgid "Need a repository to create a bundle."
msgstr "Cần một kho chứa để có thể tạo một bundle."
@@ -3132,7 +3177,7 @@ msgstr "không hiển thị chi tiết bundle (bó)"
#, c-format
msgid "%s is okay\n"
-msgstr "“%s†tốt\n"
+msgstr "%s tốt\n"
msgid "Need a repository to unbundle."
msgstr "Cần một kho chứa để có thể giải nén một bundle."
@@ -3141,12 +3186,8 @@ msgid "Unbundling objects"
msgstr "Tháo rá»i các đối tượng"
#, c-format
-msgid "Unknown subcommand: %s"
-msgstr "Không hiểu câu lệnh con: %s"
-
-#, c-format
msgid "cannot read object %s '%s'"
-msgstr "không thể Ä‘á»c đối tượng %s “%sâ€"
+msgstr "không thể Ä‘á»c đối tượng %s '%s'"
msgid "flush is only for --buffer mode"
msgstr "flush chỉ dành cho chế độ --buffer"
@@ -3166,10 +3207,6 @@ msgstr "%s cần các tham số"
msgid "%s takes no arguments"
msgstr "%s không nhận tham số"
-#, c-format
-msgid "unknown command: '%s'"
-msgstr "không hiểu câu lệnh: '%s'"
-
msgid "only one batch option may be specified"
msgstr "chỉ má»™t tùy chá»n batch được chỉ ra"
@@ -3183,22 +3220,22 @@ msgid "git cat-file (-t | -s) [--allow-unknown-type] <object>"
msgstr "git cat-file (-t | -s) [--allow-unknown-type] <đối_tượng>"
msgid ""
+"git cat-file (--textconv | --filters)\n"
+" [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"
+msgstr ""
+"git cat-file (--textconv | --filters)\n"
+" [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"
+
+msgid ""
"git cat-file (--batch | --batch-check | --batch-command) [--batch-all-"
"objects]\n"
" [--buffer] [--follow-symlinks] [--unordered]\n"
-" [--textconv | --filters]"
+" [--textconv | --filters] [-Z]"
msgstr ""
"git cat-file (--batch | --batch-check | --batch-command) [--batch-all-"
"objects]\n"
" [--buffer] [--follow-symlinks] [--unordered]\n"
-" [--textconv | --filters]"
-
-msgid ""
-"git cat-file (--textconv | --filters)\n"
-" [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"
-msgstr ""
-"git cat-file (--textconv | --filters)\n"
-" [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"
+" [--textconv | --filters] [-Z]"
msgid "Check object existence or emit object contents"
msgstr "Kiểm tra đối tượng có sẵn hay không hoặc phát nội dung của đối tượng"
@@ -3223,10 +3260,11 @@ msgstr "hiển thị kích thước đối tượng"
msgid "allow -s and -t to work with broken/corrupt objects"
msgstr "cho phép -s và -t để làm việc vá»›i các đối tượng sai/há»ng"
+msgid "use mail map file"
+msgstr "sử dụng tập tin ánh xạ thư"
+
msgid "Batch objects requested on stdin (or --batch-all-objects)"
-msgstr ""
-"Äã yêu cầu các đối tượng batch trên đầu vào tiêu chuẩn stdin (hoặc --batch-"
-"all-objects)"
+msgstr "Äã yêu cầu các đối tượng batch trên stdin (hoặc --batch-all-objects)"
msgid "show full <object> or <rev> contents"
msgstr "hiển thị đầy đủ nội dung <object> hay <rev>"
@@ -3234,13 +3272,17 @@ msgstr "hiển thị đầy đủ nội dung <object> hay <rev>"
msgid "like --batch, but don't emit <contents>"
msgstr "giống --batch, nhưng không phát ra <contents>"
+msgid "stdin is NUL-terminated"
+msgstr "stdin được kết thúc bởi NUL"
+
+msgid "stdin and stdout is NUL-terminated"
+msgstr "stdin và stdout được kết thúc bởi NUL"
+
msgid "read commands from stdin"
-msgstr "Ä‘á»c các lệnh từ đầu vào tiêu chuẩn"
+msgstr "Ä‘á»c các lệnh từ stdin"
msgid "with --batch[-check]: ignores stdin, batches all known objects"
-msgstr ""
-"vá»›i --batch[-check]: bá» qua đầu vào tiêu chuẩn stdin, batch má»i đối tượng đã "
-"biết"
+msgstr "vá»›i --batch[-check]: bá» qua stdin, batch má»i đối tượng đã biết"
msgid "Change or optimize batch output"
msgstr "Thay đổi hay tối ưu hóa đầu ra batch"
@@ -3283,11 +3325,11 @@ msgstr "path|tree-ish"
#, c-format
msgid "'%s' requires a batch mode"
-msgstr "“%s†cần một chế độ batch"
+msgstr "'%s' cần một chế độ batch"
#, c-format
msgid "'-%c' is incompatible with batch mode"
-msgstr "'-%c' là xung khắc với chế độ batch"
+msgstr "'-%c' không tương thích với chế độ batch"
msgid "batch modes take no arguments"
msgstr "chế độ batch không nhận các đối số"
@@ -3300,30 +3342,39 @@ msgstr "cần <rev> với '%s'"
msgid "<object> required with '-%c'"
msgstr "cần <object> với '-%c'"
-msgid "too many arguments"
-msgstr "có quá nhiá»u đối số"
-
#, c-format
msgid "only two arguments allowed in <type> <object> mode, not %d"
msgstr "chỉ hai đối số được phép trong chế độ <type> <object>, không phải %d"
-msgid "git check-attr [-a | --all | <attr>...] [--] <pathname>..."
-msgstr "git check-attr [-a | --all | <attr>…] [--] tên-Ä‘Æ°á»ng-dẫn…"
+msgid ""
+"git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] "
+"<pathname>..."
+msgstr ""
+"git check-attr [--source <tree-ish>] [-a | --all | <attr>...] [--] <tên-"
+"Ä‘Æ°á»ng-dẫn>..."
-msgid "git check-attr --stdin [-z] [-a | --all | <attr>...]"
-msgstr "git check-attr --stdin [-z] [-a | --all | <attr>…]"
+msgid ""
+"git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]"
+msgstr ""
+"git check-attr --stdin [-z] [--source <tree-ish>] [-a | --all | <attr>...]"
msgid "report all attributes set on file"
-msgstr "báo cáo tất cả các thuộc tính đặt trên tập tin"
+msgstr "liệt kê tất cả các thuộc tính đặt trên tập tin"
msgid "use .gitattributes only from the index"
-msgstr "chỉ dùng .gitattributes từ bảng mục lục"
+msgstr "chỉ dùng .gitattributes từ chỉ mục"
msgid "read file names from stdin"
-msgstr "Ä‘á»c tên tập tin từ đầu vào tiêu chuẩn"
+msgstr "Ä‘á»c tên tập tin từ stdin"
msgid "terminate input and output records by a NUL character"
-msgstr "chấm dứt các bản ghi vào và ra bằng ký tự NULL"
+msgstr "kết thúc các bản ghi vào và ra bằng ký tự NULL"
+
+msgid "<tree-ish>"
+msgstr "<tree-ish>"
+
+msgid "which tree-ish to check attributes at"
+msgstr "kiểm tra thuộc tính từ tree-ish nào"
msgid "suppress progress reporting"
msgstr "chặn các báo cáo tiến trình hoạt động"
@@ -3332,7 +3383,7 @@ msgid "show non-matching input paths"
msgstr "hiển thị những Ä‘Æ°á»ng dẫn đầu vào không khá»›p vá»›i mẫu"
msgid "ignore index when checking"
-msgstr "bỠqua mục lục khi kiểm tra"
+msgstr "bỠqua chỉ mục khi kiểm tra"
msgid "cannot specify pathnames with --stdin"
msgstr "không thể chỉ định các tên Ä‘Æ°á»ng dẫn vá»›i --stdin"
@@ -3353,14 +3404,14 @@ msgid "--non-matching is only valid with --verbose"
msgstr "tùy-chá»n --non-matching chỉ hợp lệ khi dùng vá»›i --verbose"
msgid "git check-mailmap [<options>] <contact>..."
-msgstr "git check-mailmap [<các tùy chá»n>] <danh-bạ>…"
+msgstr "git check-mailmap [<các tùy chá»n>] <danh-bạ>..."
msgid "also read contacts from stdin"
-msgstr "đồng thá»i Ä‘á»c các danh bạ từ đầu vào tiêu chuẩn"
+msgstr "đồng thá»i Ä‘á»c các danh bạ từ stdin"
#, c-format
msgid "unable to parse contact: %s"
-msgstr "không thể phân tích danh bạ: “%sâ€"
+msgstr "không thể Ä‘á»c danh bạ: '%s'"
msgid "no contacts specified"
msgstr "chưa chỉ ra danh bạ"
@@ -3375,13 +3426,13 @@ msgid "when creating files, prepend <string>"
msgstr "khi tạo các tập tin, nối thêm <chuỗi>"
msgid "git checkout-index [<options>] [--] [<file>...]"
-msgstr "git checkout-index [<các tùy chá»n>] [--] [<tập-tin>…]"
+msgstr "git checkout-index [<các tùy chá»n>] [--] [<tập-tin>...]"
msgid "stage should be between 1 and 3 or all"
msgstr "stage nên giữa 1 và 3 hay all"
msgid "check out all files in the index"
-msgstr "lấy ra toàn bộ các tập tin trong bảng mục lục"
+msgstr "checkout toàn bộ các tập tin trong chỉ mục"
msgid "do not skip files with skip-worktree set"
msgstr "đừng bỠqua các tập tin với skip-worktree được đặt"
@@ -3390,17 +3441,16 @@ msgid "force overwrite of existing files"
msgstr "ép buộc ghi đè lên tập tin đã sẵn có từ trước"
msgid "no warning for existing files and files not in index"
-msgstr ""
-"không cảnh báo cho những tập tin tồn tại và không có trong bảng mục lục"
+msgstr "không cảnh báo cho những tập tin tồn tại và không có trong chỉ mục"
msgid "don't checkout new files"
msgstr "không checkout các tập tin mới"
msgid "update stat information in the index file"
-msgstr "cập nhật thông tin thống kê trong tập tin lưu bảng mục lục mới"
+msgstr "cập nhật thông tin thống kê trong tập tin chỉ mục mới"
msgid "read list of paths from the standard input"
-msgstr "Ä‘á»c danh sách Ä‘Æ°á»ng dẫn từ đầu vào tiêu chuẩn"
+msgstr "Ä‘á»c danh sách Ä‘Æ°á»ng dẫn từ stdin"
msgid "write the content to temporary files"
msgstr "ghi nội dung vào tập tin tạm"
@@ -3412,37 +3462,37 @@ msgid "git checkout [<options>] <branch>"
msgstr "git checkout [<các tùy chá»n>] <nhánh>"
msgid "git checkout [<options>] [<branch>] -- <file>..."
-msgstr "git checkout [<các tùy chá»n>] [<nhánh>] -- <tập-tin>…"
+msgstr "git checkout [<các tùy chá»n>] [<nhánh>] -- <tập-tin>..."
msgid "git switch [<options>] [<branch>]"
msgstr "git switch [<các tùy chá»n>] [<nhánh>]"
msgid "git restore [<options>] [--source=<branch>] <file>..."
-msgstr "git restore [<các tùy chá»n>] [--source=<nhánh>] <tập tin>…"
+msgstr "git restore [<các tùy chá»n>] [--source=<nhánh>] <tập tin>..."
#, c-format
msgid "path '%s' does not have our version"
-msgstr "Ä‘Æ°á»ng dẫn “%s†không có các phiên bản của chúng ta"
+msgstr "Ä‘Æ°á»ng dẫn '%s' không có các phiên bản của ta"
#, c-format
msgid "path '%s' does not have their version"
-msgstr "Ä‘Æ°á»ng dẫn “%s†không có các phiên bản của chúng"
+msgstr "Ä‘Æ°á»ng dẫn '%s' không có các phiên bản của há»"
#, c-format
msgid "path '%s' does not have all necessary versions"
-msgstr "Ä‘Æ°á»ng dẫn “%s†không có tất cả các phiên bản cần thiết"
+msgstr "Ä‘Æ°á»ng dẫn '%s' không có tất cả các phiên bản cần thiết"
#, c-format
msgid "path '%s' does not have necessary versions"
-msgstr "Ä‘Æ°á»ng dẫn “%s†không có các phiên bản cần thiết"
+msgstr "Ä‘Æ°á»ng dẫn '%s' không có các phiên bản cần thiết"
#, c-format
msgid "path '%s': cannot merge"
-msgstr "Ä‘Æ°á»ng dẫn “%sâ€: không thể hòa trá»™n"
+msgstr "Ä‘Æ°á»ng dẫn '%s': không thể hòa trá»™n"
#, c-format
msgid "Unable to add merge result for '%s'"
-msgstr "Không thể thêm kết quả hòa trá»™n cho “%sâ€"
+msgstr "Không thể thêm kết quả hòa trộn cho '%s'"
#, c-format
msgid "Recreated %d merge conflict"
@@ -3457,35 +3507,43 @@ msgstr[0] "Äã cập nhật Ä‘Æ°á»ng dẫn %d từ %s"
#, c-format
msgid "Updated %d path from the index"
msgid_plural "Updated %d paths from the index"
-msgstr[0] "Äã cập nhật Ä‘Æ°á»ng dẫn %d từ mục lục"
+msgstr[0] "Äã cập nhật Ä‘Æ°á»ng dẫn %d từ chỉ mục"
#, c-format
msgid "'%s' cannot be used with updating paths"
-msgstr "không được dùng “%s†vá»›i các Ä‘Æ°á»ng dẫn cập nhật"
+msgstr "không được dùng '%s' vá»›i các Ä‘Æ°á»ng dẫn cập nhật"
#, c-format
msgid "Cannot update paths and switch to branch '%s' at the same time."
msgstr ""
-"Không thể cập nhật các Ä‘Æ°á»ng dẫn và chuyển đến nhánh “%s†cùng má»™t lúc."
+"Không thể cập nhật các Ä‘Æ°á»ng dẫn và chuyển đến nhánh '%s' cùng má»™t lúc."
#, c-format
msgid "neither '%s' or '%s' is specified"
-msgstr "không chỉ định “%s†cÅ©ng không “%sâ€"
+msgstr "không chỉ định '%s' cũng không '%s'"
#, c-format
msgid "'%s' must be used when '%s' is not specified"
-msgstr "phải có “%s†khi không chỉ định “%sâ€"
+msgstr "phải có '%s' khi không chỉ định '%s'"
#, c-format
msgid "'%s' or '%s' cannot be used with %s"
-msgstr "“%s†hay “%s†không thể được sử dụng với %s"
+msgstr "'%s' hay '%s' không thể được sử dụng với %s"
+
+#, c-format
+msgid "'%s', '%s', or '%s' cannot be used when checking out of a tree"
+msgstr "'%s', '%s', hay '%s' không thể được sử dụng khi checkout cây làm việc"
#, c-format
msgid "path '%s' is unmerged"
-msgstr "Ä‘Æ°á»ng dẫn “%s†không được hòa trá»™n"
+msgstr "Ä‘Æ°á»ng dẫn '%s' không được hòa trá»™n"
+
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr "không thể Ä‘á»c cây (%s)"
msgid "you need to resolve your current index first"
-msgstr "bạn cần phải giải quyết bảng mục lục hiện tại của bạn trước đã"
+msgstr "bạn cần phải giải quyết chỉ mục hiện tại của bạn trước đã"
#, c-format
msgid ""
@@ -3498,7 +3556,7 @@ msgstr ""
#, c-format
msgid "Can not do reflog for '%s': %s\n"
-msgstr "Không thể thá»±c hiện reflog cho “%sâ€: %s\n"
+msgstr "Không thể thực hiện reflog cho '%s': %s\n"
msgid "HEAD is now at"
msgstr "HEAD hiện giỠtại"
@@ -3508,27 +3566,27 @@ msgstr "không thể cập nhật HEAD"
#, c-format
msgid "Reset branch '%s'\n"
-msgstr "Äặt lại nhánh “%sâ€\n"
+msgstr "Äặt lại nhánh '%s'\n"
#, c-format
msgid "Already on '%s'\n"
-msgstr "Äã sẵn sàng trên “%sâ€\n"
+msgstr "Äã sẵn sàng trên '%s'\n"
#, c-format
msgid "Switched to and reset branch '%s'\n"
-msgstr "Äã chuyển tá»›i và đặt lại nhánh “%sâ€\n"
+msgstr "Äã chuyển tá»›i và đặt lại nhánh '%s'\n"
#, c-format
msgid "Switched to a new branch '%s'\n"
-msgstr "Äã chuyển đến nhánh má»›i “%sâ€\n"
+msgstr "Äã chuyển đến nhánh má»›i '%s'\n"
#, c-format
msgid "Switched to branch '%s'\n"
-msgstr "Äã chuyển đến nhánh “%sâ€\n"
+msgstr "Äã chuyển đến nhánh '%s'\n"
#, c-format
msgid " ... and %d more.\n"
-msgstr " … và nhiá»u hÆ¡n %d.\n"
+msgstr " ... và nhiá»u hÆ¡n %d.\n"
#, c-format
msgid ""
@@ -3582,7 +3640,7 @@ msgid ""
"'%s' could be both a local file and a tracking branch.\n"
"Please use -- (and optionally --no-guess) to disambiguate"
msgstr ""
-"“%s†không thể là cả tập tin nội bộ và một nhánh theo dõi.\n"
+"'%s' không thể là cả tập tin nội bộ và một nhánh theo dõi.\n"
"Vui long dùng -- (và tùy chá»n thêm --no-guess) để tránh lẫn lá»™n"
msgid ""
@@ -3595,18 +3653,18 @@ msgid ""
"one remote, e.g. the 'origin' remote, consider setting\n"
"checkout.defaultRemote=origin in your config."
msgstr ""
-"Nếu ý bạn là lấy ra nhánh máy chủ được theo dõi, ví dụ “originâ€,\n"
+"Nếu ý bạn là checkout nhánh máy chủ được theo dõi, ví dụ 'origin',\n"
"bạn có thể làm nhÆ° vậy bằng cách chỉ định đầy đủ tên vá»›i tùy chá»n --track:\n"
"\n"
" git checkout --track origin/<tên>\n"
"\n"
-"Nếu bạn muốn luôn lấy ra từ một <tên> một máy chủ ưa thích\n"
-"chÆ°a rõ ràng, ví dụ máy chủ “originâ€, cân nhắc cài đặt\n"
+"Nếu bạn muốn luôn checkout từ một <tên> một máy chủ ưa thích\n"
+"chưa rõ ràng, ví dụ máy chủ 'origin', cân nhắc cài đặt\n"
"checkout.defaultRemote=origin trong cấu hình của bạn."
#, c-format
msgid "'%s' matched multiple (%d) remote tracking branches"
-msgstr "“%s†khá»›p vá»›i nhiá»u (%d) nhánh máy chủ được theo dõi"
+msgstr "'%s' khá»›p vá»›i nhiá»u (%d) nhánh máy chủ được theo dõi"
msgid "only one reference expected"
msgstr "chỉ cần một tham chiếu"
@@ -3625,19 +3683,19 @@ msgstr "tham chiếu không phải là một cây:%s"
#, c-format
msgid "a branch is expected, got tag '%s'"
-msgstr "cần má»™t nhánh, nhÆ°ng lại nhận được thẻ “%sâ€"
+msgstr "cần một nhánh, nhưng lại có thẻ '%s'"
#, c-format
msgid "a branch is expected, got remote branch '%s'"
-msgstr "cần má»™t nhánh, nhÆ°ng lại nhận được nhánh máy phục vụ “%sâ€"
+msgstr "cần một nhánh, nhưng lại có nhánh máy chủ '%s'"
#, c-format
msgid "a branch is expected, got '%s'"
-msgstr "cần má»™t nhánh, nhÆ°ng lại nhận được “%sâ€"
+msgstr "cần một nhánh, nhưng lại có '%s'"
#, c-format
msgid "a branch is expected, got commit '%s'"
-msgstr "cần má»™t nhánh, nhÆ°ng lại nhận được “%sâ€"
+msgstr "cần một nhánh, nhưng lại có '%s'"
msgid ""
"If you want to detach HEAD at the commit, try again with the --detach option."
@@ -3650,35 +3708,35 @@ msgid ""
"Consider \"git merge --quit\" or \"git worktree add\"."
msgstr ""
"không thể chuyển nhánh trong khi đang hòa trộn\n"
-"Cân nhắc dung \"git merge --quit\" hoặc \"git worktree add\"."
+"Thử dung \"git merge --quit\" hoặc \"git worktree add\"."
msgid ""
"cannot switch branch in the middle of an am session\n"
"Consider \"git am --quit\" or \"git worktree add\"."
msgstr ""
"không thể chuyển nhanh ở giữa một phiên am\n"
-"Cân nhắc dùng \"git am --quit\" hoặc \"git worktree add\"."
+"Thử dùng \"git am --quit\" hoặc \"git worktree add\"."
msgid ""
"cannot switch branch while rebasing\n"
"Consider \"git rebase --quit\" or \"git worktree add\"."
msgstr ""
"không thể chuyển nhánh trong khi cải tổ\n"
-"Cân nhắc dùng \"git rebase --quit\" hay \"git worktree add\"."
+"Thử dùng \"git rebase --quit\" hay \"git worktree add\"."
msgid ""
"cannot switch branch while cherry-picking\n"
"Consider \"git cherry-pick --quit\" or \"git worktree add\"."
msgstr ""
-"không thể chuyển nhánh trong khi cherry-picking\n"
-"Cân nhắc dùng \"git cherry-pick --quit\" hay \"git worktree add\"."
+"không thể chuyển nhánh trong khi cherry-pick\n"
+"Hãy dùng \"git cherry-pick --quit\" hay \"git worktree add\"."
msgid ""
"cannot switch branch while reverting\n"
"Consider \"git revert --quit\" or \"git worktree add\"."
msgstr ""
"không thể chuyển nhánh trong khi hoàn nguyên\n"
-"Cân nhắc dùng \"git revert --quit\" hoặc \"git worktree add\"."
+"Thử dùng \"git revert --quit\" hoặc \"git worktree add\"."
msgid "you are switching branch while bisecting"
msgstr ""
@@ -3690,23 +3748,27 @@ msgstr "các Ä‘Æ°á»ng dẫn không thể dùng cùng vá»›i các nhánh chuyển
#, c-format
msgid "'%s' cannot be used with switching branches"
-msgstr "“%s†không thể được sử dụng với các nhánh chuyển"
+msgstr "'%s' không thể được sử dụng với các nhánh chuyển"
#, c-format
msgid "'%s' cannot be used with '%s'"
-msgstr "“%s†không thể được dùng vá»›i “%sâ€"
+msgstr "'%s' không thể được dùng với '%s'"
#, c-format
msgid "'%s' cannot take <start-point>"
-msgstr "“%s†không thể nhận <điểm-đầu>"
+msgstr "'%s' không thể nhận <điểm-đầu>"
#, c-format
msgid "Cannot switch branch to a non-commit '%s'"
-msgstr "Không thể chuyển nhánh đến má»™t thứ không phải là lần chuyển giao “%sâ€"
+msgstr "Không thể chuyển nhánh đến một thứ không phải là lần chuyển giao '%s'"
msgid "missing branch or commit argument"
msgstr "thiếu tham số là nhánh hoặc lần chuyển giao"
+#, c-format
+msgid "unknown conflict style '%s'"
+msgstr "không hiểu kiểu hiển thị xung đột '%s'"
+
msgid "perform a 3-way merge with the new branch"
msgstr "thực hiện hòa trộn kiểu 3-way với nhánh mới"
@@ -3720,13 +3782,13 @@ msgid "detach HEAD at named commit"
msgstr "rá»i bá» HEAD tại lần chuyển giao theo tên"
msgid "force checkout (throw away local modifications)"
-msgstr "ép buộc lấy ra (bỠđi những thay đổi nội bộ)"
+msgstr "ép buộc checkout (bỠđi những thay đổi nội bộ)"
msgid "new-branch"
msgstr "nhánh-mới"
-msgid "new unparented branch"
-msgstr "nhánh không cha mới"
+msgid "new unborn branch"
+msgstr "nhánh chưa sinh mới"
msgid "update ignored files (default)"
msgstr "cập nhật các tập tin bị bỠqua (mặc định)"
@@ -3735,15 +3797,13 @@ msgid "do not check if another worktree is holding the given ref"
msgstr "không kiểm tra nếu cây làm việc khác đang giữ tham chiếu đã cho"
msgid "checkout our version for unmerged files"
-msgstr ""
-"lấy ra (checkout) phiên bản của chúng ta cho các tập tin chưa được hòa trộn"
+msgstr "checkout phiên bản của ta cho các tập tin chưa được hòa trộn"
msgid "checkout their version for unmerged files"
-msgstr ""
-"lấy ra (checkout) phiên bản của chúng hỠcho các tập tin chưa được hòa trộn"
+msgstr "checkout phiên bản của hỠcho các tập tin chưa được hòa trộn"
msgid "do not limit pathspecs to sparse entries only"
-msgstr "không giá»›i hạn đặc tả Ä‘Æ°á»ng dẫn thành chỉ các mục rải rác"
+msgstr "không giá»›i hạn đặc tả Ä‘Æ°á»ng dẫn chỉ trong các mục sparse (thÆ°a)"
#, c-format
msgid "options '-%c', '-%c', and '%s' cannot be used together"
@@ -3758,7 +3818,7 @@ msgstr "thiếu tên nhánh; hãy thử -%c"
#, c-format
msgid "could not resolve %s"
-msgstr "không thể phân giải “%sâ€"
+msgstr "không thể phân giải '%s'"
msgid "invalid path specification"
msgstr "Ä‘Æ°á»ng dẫn đã cho không hợp lệ"
@@ -3766,19 +3826,19 @@ msgstr "Ä‘Æ°á»ng dẫn đã cho không hợp lệ"
#, c-format
msgid "'%s' is not a commit and a branch '%s' cannot be created from it"
msgstr ""
-"“%s†không phải là một lần chuyển giao và một nhánh'%s†không thể được tạo "
+"'%s' không phải là một lần chuyển giao và một nhánh'%s' không thể được tạo "
"từ đó"
#, c-format
msgid "git checkout: --detach does not take a path argument '%s'"
-msgstr "git checkout: --detach không nhận má»™t đối số Ä‘Æ°á»ng dẫn “%sâ€"
+msgstr "git checkout: --detach không nhận má»™t đối số Ä‘Æ°á»ng dẫn '%s'"
msgid ""
"git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
"checking out of the index."
msgstr ""
"git checkout: --ours/--theirs, --force và --merge là xung khắc với nhau khi\n"
-"checkout bảng mục lục (index)."
+"checkout chỉ mục (index)."
msgid "you must specify path(s) to restore"
msgstr "bạn phải chỉ định các thư mục muốn hồi phục"
@@ -3796,7 +3856,7 @@ msgid "create reflog for new branch"
msgstr "tạo reflog cho nhánh mới"
msgid "second guess 'git checkout <no-such-branch>' (default)"
-msgstr "gợi ý thứ hai “git checkout <không-nhánh-nào-như-vậy>†(mặc định)"
+msgstr "gợi ý thứ hai 'git checkout <không-nhánh-nào-như-vậy>' (mặc định)"
msgid "use overlay mode (default)"
msgstr "dùng chế độ che phủ (mặc định)"
@@ -3814,10 +3874,10 @@ msgid "throw away local modifications"
msgstr "vứt bỠcác sửa đổi địa phương"
msgid "which tree-ish to checkout from"
-msgstr "lấy ra từ tree-ish nào"
+msgstr "checkout từ tree-ish nào"
msgid "restore the index"
-msgstr "phục hồi bảng mục lục"
+msgstr "phục hồi chỉ mục"
msgid "restore the working tree (default)"
msgstr "phục hồi cây làm việc (mặc định)"
@@ -3829,18 +3889,18 @@ msgid "use overlay mode"
msgstr "dùng chế độ che phủ"
msgid ""
-"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] "
+"[<pathspec>...]"
msgstr ""
-"git clean [-d] [-f] [-i] [-n] [-q] [-e <mẫu>] [-x | -X] [--] </các/Ä‘Æ°á»ng/"
-"dẫn>…"
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <mẫu>] [-x | -X] [--][<Ä‘Æ°á»ng/dẫn>...]"
#, c-format
msgid "Removing %s\n"
-msgstr "Äang gỡ bá» %s\n"
+msgstr "Äang xoá %s\n"
#, c-format
msgid "Would remove %s\n"
-msgstr "Có thể gỡ bỠ%s\n"
+msgstr "Sẽ xoá %s\n"
#, c-format
msgid "Skipping repository %s\n"
@@ -3852,17 +3912,17 @@ msgstr "Nên bỠqua kho chứa %s\n"
#, c-format
msgid "failed to remove %s"
-msgstr "gặp lỗi khi gỡ bỠ%s"
+msgstr "gặp lỗi khi xoá %s"
#, c-format
msgid "could not lstat %s\n"
-msgstr "không thể lấy thông tin thống kê đầy đủ của %s\n"
+msgstr "không thể lstat %s\n"
msgid "Refusing to remove current working directory\n"
-msgstr "Từ chối gỡ bỠthư mục làm việc hiện tại\n"
+msgstr "Từ chối xoá thư mục làm việc hiện tại\n"
msgid "Would refuse to remove current working directory\n"
-msgstr "Nên từ chối gỡ bỠthư mục làm việc hiện tại\n"
+msgstr "Sẽ từ chối xoá bỠthư mục làm việc hiện tại\n"
#, c-format
msgid ""
@@ -3892,17 +3952,17 @@ msgstr ""
"3-5 - chá»n má»™t vùng\n"
"2-3,6-9 - chá»n nhiá»u vùng\n"
"foo - chá»n mục dá»±a trên tiá»n tố duy nhất\n"
-"-… - không chá»n các mục đã chỉ ra\n"
+"-... - không chá»n các mục đã chỉ ra\n"
"* - chá»n tất\n"
" - (để trống) kết thúc việc chá»n\n"
-#, c-format, perl-format
+#, c-format
msgid "Huh (%s)?\n"
msgstr "Hả (%s)?\n"
#, c-format
msgid "Input ignore patterns>> "
-msgstr "Mẫu để lá»c các tập tin đầu vào cần lá» Ä‘i>> "
+msgstr "Mẫu để lá»c các tập tin đầu vào cần bá» qua>> "
#, c-format
msgid "WARNING: Cannot find items matched by: %s"
@@ -3914,7 +3974,7 @@ msgstr "Chá»n mục muốn xóa"
#. TRANSLATORS: Make sure to keep [y/N] as is
#, c-format
msgid "Remove %s [y/N]? "
-msgstr "Xóa bỠ“%s†[y/N]? "
+msgstr "Xóa bỠ'%s' [y/N]? "
msgid ""
"clean - start cleaning\n"
@@ -3935,7 +3995,7 @@ msgstr ""
msgid "Would remove the following item:"
msgid_plural "Would remove the following items:"
-msgstr[0] "Có muốn gỡ bỠ(các) mục sau đây không:"
+msgstr[0] "Có muốn xoá (các) mục sau đây không:"
msgid "No more files to clean, exiting."
msgstr "Không còn tập-tin nào để dá»n dẹp, Ä‘ang thoát ra."
@@ -3950,13 +4010,13 @@ msgid "interactive cleaning"
msgstr "dá»n bằng kiểu tÆ°Æ¡ng tác"
msgid "remove whole directories"
-msgstr "gỡ bỠtoàn bộ thư mục"
+msgstr "xoá toàn bộ thư mục"
msgid "pattern"
msgstr "mẫu"
msgid "add <pattern> to ignore rules"
-msgstr "thêm <mẫu> vào trong qui tắc bỠqua"
+msgstr "thêm <mẫu> vào trong quy tắc bỠqua"
msgid "remove ignored files, too"
msgstr "đồng thá»i gỡ bá» cả các tập tin bị bá» qua"
@@ -3964,22 +4024,10 @@ msgstr "đồng thá»i gỡ bá» cả các tập tin bị bá» qua"
msgid "remove only ignored files"
msgstr "chỉ gỡ bỠnhững tập tin bị bỠqua"
-msgid ""
-"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to "
-"clean"
-msgstr ""
-"clean.requireForce được đặt thành true và không Ä‘Æ°a ra tùy chá»n -i, -n mà "
-"cÅ©ng không -f; từ chối lệnh dá»n dẹp (clean)"
-
-msgid ""
-"clean.requireForce defaults to true and neither -i, -n, nor -f given; "
-"refusing to clean"
+msgid "clean.requireForce is true and -f not given: refusing to clean"
msgstr ""
-"clean.requireForce mặc định được đặt là true và không Ä‘Æ°a ra tùy chá»n -i, -n "
-"mà cÅ©ng không -f; từ chối lệnh dá»n dẹp (clean)"
-
-msgid "-x and -X cannot be used together"
-msgstr "-x và -X không thể dùng cùng nhau"
+"clean.requireForce được đặt thành true và không có tuỳ chá»n -f; từ chối dá»n "
+"dẹp"
msgid "git clone [<options>] [--] <repo> [<dir>]"
msgstr "git clone [<các tùy chá»n>] [--] <kho> [<t.mục>]"
@@ -3991,10 +4039,10 @@ msgid "don't create a checkout"
msgstr "không tạo một checkout"
msgid "create a bare repository"
-msgstr "tạo kho thuần"
+msgstr "tạo kho bare"
-msgid "create a mirror repository (implies bare)"
-msgstr "tạo kho bản sao (ý là kho thuần)"
+msgid "create a mirror repository (implies --bare)"
+msgstr "tạo kho bản sao (ngụ ý --bare)"
msgid "to clone from a local repository"
msgstr "để nhân bản từ kho nội bộ"
@@ -4030,10 +4078,10 @@ msgid "name"
msgstr "tên"
msgid "use <name> instead of 'origin' to track upstream"
-msgstr "dùng <tên> thay cho “origin†để theo dõi thượng nguồn"
+msgstr "dùng <tên> thay cho 'origin' để theo dõi thượng nguồn"
msgid "checkout <branch> instead of the remote's HEAD"
-msgstr "lấy ra <nhánh> thay cho HEAD của máy chủ"
+msgstr "checkout <nhánh> thay cho HEAD của máy chủ"
msgid "path to git-upload-pack on the remote"
msgstr "Ä‘Æ°á»ng dẫn đến git-upload-pack trên máy chủ"
@@ -4044,9 +4092,6 @@ msgstr "độ-sâu"
msgid "create a shallow clone of that depth"
msgstr "tạo bản sao không đầy đủ cho mức sâu đã cho"
-msgid "time"
-msgstr "thá»i-gian"
-
msgid "create a shallow clone since a specific time"
msgstr "tạo bản sao không đầy đủ từ thá»i Ä‘iểm đã cho"
@@ -4073,6 +4118,9 @@ msgstr "gitdir"
msgid "separate git dir from working tree"
msgstr "không dùng chung thư mục dành riêng cho git và thư mục làm việc"
+msgid "specify the reference format to use"
+msgstr "dùng định dạng tham chiếu nào cho các lần chuyển giao"
+
msgid "key=value"
msgstr "khóa=giá_trị"
@@ -4085,40 +4133,48 @@ msgstr "đặc-tả-máy-phục-vụ"
msgid "option to transmit"
msgstr "tùy chá»n để chuyển giao"
-msgid "use IPv4 addresses only"
-msgstr "chỉ dùng địa chỉ IPv4"
-
-msgid "use IPv6 addresses only"
-msgstr "chỉ dùng địa chỉ IPv6"
-
msgid "apply partial clone filters to submodules"
msgstr "áp dụng các bá»™ lá»c nhân bản má»™t phần cho mô-Ä‘un-con"
msgid "any cloned submodules will use their remote-tracking branch"
-msgstr "má»i mô-Ä‘un-con nhân bản sẽ dung nhánh theo dõi máy chủ của chúng"
+msgstr "má»i mô-Ä‘un-con được nhân bản sẽ dùng nhánh theo dõi máy chủ của chúng"
msgid "initialize sparse-checkout file to include only files at root"
msgstr "khởi tạo tập tin sparse-checkout để bao gồm chỉ các tập tin ở gốc"
+msgid "uri"
+msgstr "uri"
+
+msgid "a URI for downloading bundles before fetching from origin remote"
+msgstr "URI để tải xuống bundle trước khi lấy vỠtừ máy chủ origin"
+
#, c-format
msgid "info: Could not add alternate for '%s': %s\n"
-msgstr "thông tin: không thể thêm thay thế cho “%sâ€: %s\n"
+msgstr "thông tin: không thể thêm thay thế cho '%s': %s\n"
#, c-format
msgid "failed to stat '%s'"
-msgstr "gặp lá»—i khi lấy thống kê vỠ“%sâ€"
+msgstr "gặp lỗi khi stat '%s'"
#, c-format
msgid "%s exists and is not a directory"
msgstr "%s có tồn tại nhưng lại không phải là một thư mục"
#, c-format
+msgid "'%s' is a symlink, refusing to clone with --local"
+msgstr "'%s' là liên kết má»m, từ chối sao chép vá»›i --local"
+
+#, c-format
msgid "failed to start iterator over '%s'"
-msgstr "gặp lá»—i khi bắt đầu lặp qua “%sâ€"
+msgstr "gặp lỗi khi bắt đầu lặp qua '%s'"
+
+#, c-format
+msgid "symlink '%s' exists, refusing to clone with --local"
+msgstr "liên kết má»m '%s' đã tồn tại, từ chối sao chép vá»›i --local"
#, c-format
msgid "failed to unlink '%s'"
-msgstr "gặp lá»—i khi bá» liên kết (unlink) “%sâ€"
+msgstr "gặp lỗi khi unlink '%s'"
#, c-format
msgid "failed to create link '%s'"
@@ -4126,11 +4182,11 @@ msgstr "gặp lá»—i khi tạo được liên kết má»m %s"
#, c-format
msgid "failed to copy file to '%s'"
-msgstr "gặp lá»—i khi sao chép tập tin và “%sâ€"
+msgstr "gặp lỗi khi sao chép tập tin và '%s'"
#, c-format
msgid "failed to iterate over '%s'"
-msgstr "gặp lá»—i khi lặp qua “%sâ€"
+msgstr "gặp lỗi khi lặp qua '%s'"
#, c-format
msgid "done.\n"
@@ -4142,8 +4198,8 @@ msgid ""
"and retry with 'git restore --source=HEAD :/'\n"
msgstr ""
"Việc nhân bản thành công, nhưng checkout gặp lỗi.\n"
-"Bạn kiểm tra kỹ xem cái gì được lấy ra bằng lệnh “git statusâ€\n"
-"và thá»­ lấy ra vá»›i lệnh “git restore --source=HEAD :/â€\n"
+"Kiểm tra xem cái gì đã được checkout bằng lệnh 'git status'\n"
+"và thử lại với lệnh 'git restore --source=HEAD :/'\n"
#, c-format
msgid "Could not find remote branch %s to clone."
@@ -4159,11 +4215,11 @@ msgstr "không thể cập nhật %s"
msgid "failed to initialize sparse-checkout"
msgstr "gặp lỗi khi khởi tạo sparse-checkout"
-msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n"
-msgstr "refers HEAD máy chủ chỉ đến ref không tồn tại, không thể lấy ra.\n"
+msgid "remote HEAD refers to nonexistent ref, unable to checkout"
+msgstr "HEAD ở máy chủ chỉ đến ref không tồn tại, không thể checkout"
msgid "unable to checkout working tree"
-msgstr "không thể lấy ra (checkout) cây làm việc"
+msgstr "không thể checkout cây làm việc"
msgid "unable to write parameters to config file"
msgstr "không thể ghi các tham số vào tập tin cấu hình"
@@ -4175,18 +4231,18 @@ msgid "cannot unlink temporary alternates file"
msgstr "không thể bá» liên kết tập tin thay thế tạm thá»i"
msgid "Too many arguments."
-msgstr "Có quá nhiá»u đối số."
+msgstr "Quá nhiá»u đối số."
msgid "You must specify a repository to clone."
-msgstr "Bạn phải chỉ định một kho để mà nhân bản (clone)."
+msgstr "Bạn phải chỉ định một kho để nhân bản."
#, c-format
-msgid "options '%s' and '%s %s' cannot be used together"
-msgstr "tùy chá»n '%s', và '%s %s' không thể dùng cùng nhau"
+msgid "unknown ref storage format '%s'"
+msgstr "Không hiểu định dạng lưu tham chiếu '%s'"
#, c-format
msgid "repository '%s' does not exist"
-msgstr "kho chứa “%s†chưa tồn tại"
+msgstr "kho chứa '%s' chưa tồn tại"
#, c-format
msgid "depth %s is not a positive number"
@@ -4194,32 +4250,32 @@ msgstr "độ sâu %s không phải là một số nguyên dương"
#, c-format
msgid "destination path '%s' already exists and is not an empty directory."
-msgstr "Ä‘Æ°á»ng dẫn đích “%s†đã có từ trÆ°á»›c và không phải là má»™t thÆ° mục rá»—ng."
+msgstr "Ä‘Æ°á»ng dẫn đích '%s' đã có từ trÆ°á»›c và không phải là má»™t thÆ° mục rá»—ng."
#, c-format
msgid "repository path '%s' already exists and is not an empty directory."
msgstr ""
-"Ä‘Æ°á»ng dẫn kho chứa “%s†đã có từ trÆ°á»›c và không phải là má»™t thÆ° mục rá»—ng."
+"Ä‘Æ°á»ng dẫn kho chứa '%s' đã có từ trÆ°á»›c và không phải là má»™t thÆ° mục rá»—ng."
#, c-format
msgid "working tree '%s' already exists."
-msgstr "cây làm việc “%s†đã sẵn tồn tại rồi."
+msgstr "cây làm việc '%s' đã sẵn tồn tại rồi."
#, c-format
msgid "could not create leading directories of '%s'"
-msgstr "không thể tạo các thÆ° mục dẫn đầu của “%sâ€"
+msgstr "không thể tạo các thư mục dẫn đầu của '%s'"
#, c-format
msgid "could not create work tree dir '%s'"
-msgstr "không thể tạo cây thÆ° mục làm việc dir “%sâ€"
+msgstr "không thể tạo cây làm việc dir '%s'"
#, c-format
msgid "Cloning into bare repository '%s'...\n"
-msgstr "Äang nhân bản thành kho chứa bare “%sâ€â€¦\n"
+msgstr "Äang nhân bản thành kho chứa bare '%s'...\n"
#, c-format
msgid "Cloning into '%s'...\n"
-msgstr "Äang nhân bản thành “%sâ€â€¦\n"
+msgstr "Äang nhân bản thành '%s'...\n"
msgid ""
"clone --recursive is not compatible with both --reference and --reference-if-"
@@ -4230,24 +4286,25 @@ msgstr ""
#, c-format
msgid "'%s' is not a valid remote name"
-msgstr "“%s†không phải tên máy chủ hợp lệ"
+msgstr "'%s' không phải tên máy chủ hợp lệ"
msgid "--depth is ignored in local clones; use file:// instead."
-msgstr "--depth bị lỠđi khi nhân bản nội bộ; hãy sử dụng file:// để thay thế."
+msgstr ""
+"--depth bị bỠqua khi nhân bản nội bộ; hãy sử dụng file:// để thay thế."
msgid "--shallow-since is ignored in local clones; use file:// instead."
msgstr ""
-"--shallow-since bị lỠđi khi nhân bản nội bộ; hãy sử dụng file:// để thay "
+"--shallow-since bị bỠqua khi nhân bản nội bộ; hãy sử dụng file:// để thay "
"thế."
msgid "--shallow-exclude is ignored in local clones; use file:// instead."
msgstr ""
-"--shallow-exclude bị lỠđi khi nhân bản nội bộ; hãy sử dụng file:// để thay "
+"--shallow-exclude bị bỠqua khi nhân bản nội bộ; hãy sử dụng file:// để thay "
"thế."
msgid "--filter is ignored in local clones; use file:// instead."
msgstr ""
-"--filter bị lỠđi khi nhân bản nội bộ; hãy sử dụng file:// để thay thế."
+"--filter bị bỠqua khi nhân bản nội bộ; hãy sử dụng file:// để thay thế."
msgid "source repository is shallow, reject to clone."
msgstr "kho nguồn là nông, nên bỠtừ chối nhân bản."
@@ -4256,13 +4313,23 @@ msgid "source repository is shallow, ignoring --local"
msgstr "kho nguồn là nông, nên bỠqua --local"
msgid "--local is ignored"
-msgstr "--local bị lỠđi"
+msgstr "--local bị bỠqua"
msgid "cannot clone from filtered bundle"
msgstr "không thể nhân bản từ bundle được lá»c ra"
+msgid "failed to initialize the repo, skipping bundle URI"
+msgstr "khởi tạo kho chứa thất bại, đang bỠqua URI bundle"
+
+#, c-format
+msgid "failed to fetch objects from bundle URI '%s'"
+msgstr "lấy vỠđối tượng từ URI bundle '%s' thất bại"
+
+msgid "failed to fetch advertised bundles"
+msgstr "lấy vỠbundle thất bại"
+
msgid "remote transport reported error"
-msgstr "vận chuyển máy mạng đã báo cáo lỗi"
+msgstr "trình vận chuyển đã báo lỗi"
#, c-format
msgid "Remote branch %s not found in upstream %s"
@@ -4292,38 +4359,50 @@ msgstr "chèn thêm khoảng trắng vào bên phải"
msgid "padding space between columns"
msgstr "chèn thêm khoảng trắng giữa các cột"
+#, c-format
+msgid "%s must be non-negative"
+msgstr "%s phải không âm"
+
msgid "--command must be the first argument"
msgstr "--command phải là đối số đầu tiên"
msgid ""
-"git commit-graph verify [--object-dir <objdir>] [--shallow] [--[no-]progress]"
+"git commit-graph verify [--object-dir <dir>] [--shallow] [--[no-]progress]"
msgstr ""
"git commit-graph verify [--object-dir </thư/mục/đối/tượng>] [--shallow] [--"
"[no-]progress]"
msgid ""
-"git commit-graph write [--object-dir <objdir>] [--append] [--"
-"split[=<strategy>]] [--reachable|--stdin-packs|--stdin-commits] [--changed-"
-"paths] [--[no-]max-new-filters <n>] [--[no-]progress] <split options>"
+"git commit-graph write [--object-dir <dir>] [--append]\n"
+" [--split[=<strategy>]] [--reachable | --stdin-packs | "
+"--stdin-commits]\n"
+" [--changed-paths] [--[no-]max-new-filters <n>] [--"
+"[no-]progress]\n"
+" <split-options>"
msgstr ""
-"git commit-graph write [--object-dir </thư/mục/đối/tượng>] [--append][--"
-"split[=<chiến lược>]] [--reachable|--stdin-packs|--stdin-commits][--changed-"
-"paths] [--[no-]max-new-filters <n>] [--[no-]progress] <các tùy chá»n chia "
-"tách>"
+"git commit-graph write [--object-dir </thư/mục/đối/tượng>] [--append]\n"
+" [--split[=<chiến lược>]] [--reachable | --stdin-packs "
+"| --stdin-commits]\n"
+" [--changed-paths] [--[no-]max-new-filters <n>] [--"
+"[no-]progress]\n"
+" <các tùy chá»n chia tách>"
msgid "dir"
-msgstr "tmục"
+msgstr "thư mục"
msgid "the object directory to store the graph"
msgstr "thư mục đối tượng để lưu đồ thị"
msgid "if the commit-graph is split, only verify the tip file"
-msgstr ""
-"nếu đồ-thị-các-lần-chuyển-giao bị chia cắt, thì chỉ thẩm tra tập tin đỉnh"
+msgstr "nếu đồ-thị-chuyển-giao bị chia cắt, thì chỉ thẩm tra tập tin đỉnh"
#, c-format
msgid "Could not open commit-graph '%s'"
-msgstr "Không thể mở đồ thị chuyển giao “%sâ€"
+msgstr "Không thể mở đồ thị chuyển giao '%s'"
+
+#, c-format
+msgid "could not open commit-graph chain '%s'"
+msgstr "Không thể mở dãy đồ thị chuyển giao '%s'"
#, c-format
msgid "unrecognized --split argument, %s"
@@ -4331,7 +4410,7 @@ msgstr "đối số --split không được thừa nhận, %s"
#, c-format
msgid "unexpected non-hex object ID: %s"
-msgstr "nhận được ID đối tượng không phải dạng hex không cần: %s"
+msgstr "nhận được ID đối tượng không phải dạng hex bất thÆ°á»ng %s"
#, c-format
msgid "invalid object: %s"
@@ -4339,24 +4418,19 @@ msgstr "đối tượng không hợp lệ: %s"
#, c-format
msgid "option `%s' expects a numerical value"
-msgstr "tùy chá»n “%s†cần má»™t giá trị bằng số"
+msgstr "tùy chá»n '%s' cần má»™t giá trị bằng số"
msgid "start walk at all refs"
msgstr "bắt đầu di chuyển tại má»i tham chiếu"
msgid "scan pack-indexes listed by stdin for commits"
-msgstr ""
-"quét dó các mục lục gói được liệt kê bởi đầu vào tiêu chuẩn cho các lần "
-"chuyển giao"
+msgstr "quét dó các chỉ mục gói được liệt kê bởi stdin cho các lần chuyển giao"
msgid "start walk at commits listed by stdin"
-msgstr ""
-"bắt đầu di chuyển tại các lần chuyển giao được liệt kê bởi đầu vào tiêu chuẩn"
+msgstr "bắt đầu di chuyển tại các lần chuyển giao được liệt kê bởi stdin"
msgid "include all commits already in the commit-graph file"
-msgstr ""
-"bao gồm má»i lần chuyển giao đã sẵn có trongÆ°á»i tập tin đồ-thị-các-lần-chuyển-"
-"giao"
+msgstr "bao gồm má»i lần chuyển giao đã sẵn có trong tập tin đồ-thị-chuyển-giao"
msgid "enable computation for changed paths"
msgstr "cho phép tính toán các Ä‘Æ°á»ng dẫn đã bị thay đổi"
@@ -4366,11 +4440,11 @@ msgstr "cho phép ghi má»™t tập tin đồ há»a các lần chuyển giao lá»›n
msgid "maximum number of commits in a non-base split commit-graph"
msgstr ""
-"số lượng tối đa của các lần chuyển giao trong một đồ-thị-các-lần-chuyển-giao "
-"chia cắt không-cơ-sở"
+"số lượng tối đa của các lần chuyển giao trong một đồ-thị-chuyển-giao chia "
+"cắt không-cơ-sở"
msgid "maximum ratio between two levels of a split commit-graph"
-msgstr "tỷ lệ tối đa giữa hai mức của một đồ-thị-các-lần-chuyển-giao chia cắt"
+msgstr "tỉ lệ tối đa giữa hai mức của một đồ-thị-chuyển-giao chia cắt"
msgid "only expire files older than a given date-time"
msgstr "chỉ làm hết hạn các tập tin khi nó cÅ© hÆ¡n khoảng <thá»i gian> Ä‘Æ°a ra"
@@ -4385,16 +4459,15 @@ msgstr ""
msgid "Collecting commits from input"
msgstr "Sưu tập các lần chuyển giao từ đầu vào"
-#, c-format
-msgid "unrecognized subcommand: %s"
-msgstr "không hiểu câu lệnh con: %s"
+msgid "git commit-tree <tree> [(-p <parent>)...]"
+msgstr "git commit-tree <cây> [(-p <cha>)...]"
msgid ""
-"git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...] [(-F "
-"<file>)...] <tree>"
+"git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]\n"
+" [(-F <file>)...] <tree>"
msgstr ""
-"git commit-tree [(-p <cha>)…] [-S[<keyid>]] [(-m <ghi chú>)…] [(-F <tập tin>)"
-"…] <cây>"
+"git commit-tree [(-p <cha>)...] [-S[<keyid>]] [(-m <ghi chú>)...]\n"
+" [(-F <tập tin>)...] <cây>"
#, c-format
msgid "duplicate parent %s ignored"
@@ -4402,15 +4475,15 @@ msgstr "cha mẹ bị trùng lặp %s đã bị bỠqua"
#, c-format
msgid "not a valid object name %s"
-msgstr "không phải là tên đối tượng hợp lệ “%sâ€"
+msgstr "không phải là tên đối tượng hợp lệ '%s'"
#, c-format
msgid "git commit-tree: failed to read '%s'"
-msgstr "git commit-tree: gặp lá»—i khi Ä‘á»c “%sâ€"
+msgstr "git commit-tree: gặp lá»—i khi Ä‘á»c '%s'"
#, c-format
msgid "git commit-tree: failed to close '%s'"
-msgstr "git commit-tree: gặp lá»—i khi đóng “%sâ€"
+msgstr "git commit-tree: gặp lỗi khi đóng '%s'"
msgid "parent"
msgstr "cha-mẹ"
@@ -4436,22 +4509,38 @@ msgstr "phải đưa ra chính xác một cây"
msgid "git commit-tree: failed to read"
msgstr "git commit-tree: gặp lá»—i khi Ä‘á»c"
-msgid "git commit [<options>] [--] <pathspec>..."
-msgstr "git commit [<các tùy chá»n>] [--] <pathspec>…"
+msgid ""
+"git commit [-a | --interactive | --patch] [-s] [-v] [-u<mode>] [--amend]\n"
+" [--dry-run] [(-c | -C | --squash) <commit> | --fixup [(amend|"
+"reword):]<commit>)]\n"
+" [-F <file> | -m <msg>] [--reset-author] [--allow-empty]\n"
+" [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n"
+" [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n"
+" [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
+" [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n"
+" [--] [<pathspec>...]"
+msgstr ""
+"git commit [-a | --interactive | --patch] [-s] [-v] [-u<chế-độ>] [--amend]\n"
+" [--dry-run] [(-c | -C | --squash) <lần chuyển giao> | --fixup "
+"[(amend|reword):]<lần chuyển giao>)]\n"
+" [-F <tập tin> | -m <ghi chú>] [--reset-author] [--allow-empty]\n"
+" [--allow-empty-message] [--no-verify] [-e] [--author=<tác giả>]\n"
+" [--date=<ngày tháng>] [--cleanup=<chế-độ>] [--[no-]status]\n"
+" [-i | -o] [--pathspec-from-file=<tập-tin> [--pathspec-file-nul]]\n"
+" [(--trailer <thẻ>[(=|:)<giá-trị>])...] [-S[<keyid>]]\n"
+" [--] [<pathspec>...]"
-msgid "git status [<options>] [--] <pathspec>..."
-msgstr "git status [<các tùy chá»n>] [--] <pathspec>…"
+msgid "git status [<options>] [--] [<pathspec>...]"
+msgstr "git status [<các tùy chá»n>] [--] <pathspec>..."
msgid ""
"You asked to amend the most recent commit, but doing so would make\n"
"it empty. You can repeat your command with --allow-empty, or you can\n"
"remove the commit entirely with \"git reset HEAD^\".\n"
msgstr ""
-"Bạn đã yêu cầu amend (“tu bổâ€) phần lá»›n các lần chuyển giao gần đây, nhÆ°ng "
-"làm như thế\n"
-"có thể làm cho nó trở nên trống rỗng. Bạn có thể lặp lại lệnh của mình bằng "
-"--allow-empty,\n"
-"hoặc là bạn gỡ bỠcác lần chuyển giao một cách hoàn toàn bằng lệnh:\n"
+"Bạn đã yêu cầu amend ('tu bổ') lần chuyển giao gần nhất, nhưng làm vậy\n"
+"sẽ làm cho nó trở nên rỗng. Bạn có thể lặp lại lệnh với --allow-empty,\n"
+"hoặc là bạn gỡ bỠlần chuyển giao một cách hoàn toàn bằng lệnh:\n"
"\"git reset HEAD^\".\n"
msgid ""
@@ -4461,18 +4550,17 @@ msgid ""
" git commit --allow-empty\n"
"\n"
msgstr ""
-"Lần cherry-pick trước hiện nay trống rỗng, có lẽ là bởi vì sự phân giải xung "
-"Ä‘á»™t.\n"
+"Lần cherry-pick trước hiện nay trống rỗng, có lẽ là do giải quyết xung đột.\n"
"Nếu bạn vẫn muốn chuyển giao nó cho dù thế nào đi nữa, hãy dùng:\n"
"\n"
" git commit --allow-empty\n"
"\n"
msgid "Otherwise, please use 'git rebase --skip'\n"
-msgstr "Nếu không được thì dùng lệnh \"git rebase --skip\"\n"
+msgstr "Nếu không thì dùng lệnh \"git rebase --skip\"\n"
msgid "Otherwise, please use 'git cherry-pick --skip'\n"
-msgstr "Nếu không được thì dùng lệnh \"git cherry-pick --skip\"\n"
+msgstr "Nếu không thì dùng lệnh \"git cherry-pick --skip\"\n"
msgid ""
"and then use:\n"
@@ -4489,12 +4577,15 @@ msgstr ""
"\n"
" git cherry-pick --continue\n"
"\n"
-"để lại tiếp tục cherry-picking các lần chuyển giao còn lại.\n"
+"để lại tiếp tục cherry-pick các lần chuyển giao còn lại.\n"
"Nếu bạn muốn bỠqua lần chuyển giao này thì dùng:\n"
"\n"
" git cherry-pick --skip\n"
"\n"
+msgid "updating files failed"
+msgstr "cập nhật tập tin gặp lỗi"
+
msgid "failed to unpack HEAD tree object"
msgstr "gặp lỗi khi tháo dỡ HEAD đối tượng cây"
@@ -4502,20 +4593,17 @@ msgid "No paths with --include/--only does not make sense."
msgstr "Không Ä‘Æ°á»ng dẫn vá»›i các tùy chá»n --include/--only không hợp lý."
msgid "unable to create temporary index"
-msgstr "không thể tạo bảng mục lục tạm thá»i"
+msgstr "không thể tạo chỉ mục tạm thá»i"
msgid "interactive add failed"
msgstr "gặp lỗi khi thêm bằng cách tương"
msgid "unable to update temporary index"
-msgstr "không thể cập nhật bảng mục lục tạm thá»i"
+msgstr "không thể cập nhật chỉ mục tạm thá»i"
msgid "Failed to update main cache tree"
msgstr "Gặp lỗi khi cập nhật cây bộ nhớ đệm"
-msgid "unable to write new_index file"
-msgstr "không thể ghi tập tin lưu bảng mục lục mới (new_index)"
-
msgid "cannot do a partial commit during a merge."
msgstr ""
"không thể thực hiện việc chuyển giao cục bộ trong khi đang được hòa trộn."
@@ -4529,21 +4617,21 @@ msgstr ""
"không thể thực hiện việc chuyển giao cục bộ trong khi đang thực hiện cải tổ."
msgid "cannot read the index"
-msgstr "không Ä‘á»c được bảng mục lục"
+msgstr "không Ä‘á»c được chỉ mục"
msgid "unable to write temporary index file"
-msgstr "không thể ghi tập tin lÆ°u bảng mục lục tạm thá»i"
+msgstr "không thể ghi tập tin chỉ mục tạm thá»i"
#, c-format
msgid "commit '%s' lacks author header"
-msgstr "lần chuyển giao “%s†thiếu phần tác giả ở đầu"
+msgstr "lần chuyển giao '%s' thiếu phần tác giả ở đầu"
#, c-format
msgid "commit '%s' has malformed author line"
-msgstr "lần chuyển giao “%s†có phần tác giả ở đầu dị dạng"
+msgstr "lần chuyển giao '%s' có phần tác giả ở đầu dị dạng"
msgid "malformed --author parameter"
-msgstr "đối số cho --author bị dị hình"
+msgstr "đối số cho --author bị sai quy cách"
#, c-format
msgid "invalid date format: %s"
@@ -4557,19 +4645,19 @@ msgstr ""
"trong phần ghi chú hiện tại"
#, c-format
-msgid "could not lookup commit %s"
-msgstr "không thể tìm kiếm commit (lần chuyển giao) %s"
+msgid "could not lookup commit '%s'"
+msgstr "không thể tìm kiếm lần chuyển giao '%s'"
#, c-format
msgid "(reading log message from standard input)\n"
-msgstr "(Ä‘ang Ä‘á»c thông Ä‘iệp nhật ký từ đầu vào tiêu chuẩn)\n"
+msgstr "(Ä‘ang Ä‘á»c thông Ä‘iệp nhật ký từ stdin)\n"
msgid "could not read log from standard input"
-msgstr "không thể Ä‘á»c nhật ký từ đầu vào tiêu chuẩn"
+msgstr "không thể Ä‘á»c nhật ký từ stdin"
#, c-format
msgid "could not read log file '%s'"
-msgstr "không Ä‘á»c được tệp nhật ký “%sâ€"
+msgstr "không Ä‘á»c được tập nhật ký '%s'"
#, c-format
msgid "options '%s' and '%s:%s' cannot be used together"
@@ -4583,7 +4671,7 @@ msgstr "không thể Ä‘á»c MERGE_MSG"
#, c-format
msgid "could not open '%s'"
-msgstr "không thể mở “%sâ€"
+msgstr "không thể mở '%s'"
msgid "could not write commit template"
msgstr "không thể ghi mẫu chuyển giao"
@@ -4591,39 +4679,39 @@ msgstr "không thể ghi mẫu chuyển giao"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored.\n"
+"with '%s' will be ignored.\n"
msgstr ""
"Hãy nhập vào các thông tin để giải thích các thay đổi của bạn. Những\n"
-"dòng được bắt đầu bằng “%c†sẽ được bỠqua.\n"
+"dòng được bắt đầu bằng '%s' sẽ được bỠqua.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored, and an empty message aborts the commit.\n"
+"with '%s' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
"Hãy nhập vào các thông tin để giải thích các thay đổi của bạn. Những dòng "
"được\n"
-"bắt đầu bằng “%c†sẽ được bỠqua, nếu phần chú thích rỗng sẽ hủy bỠlần "
+"bắt đầu bằng '%s' sẽ được bỠqua, nếu phần chú thích rỗng sẽ hủy bỠlần "
"chuyển giao.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
msgstr ""
"Hãy nhập vào các thông tin để giải thích các thay đổi của bạn. Những dòng "
"được\n"
-"bắt đầu bằng “%c†sẽ được bỠqua; bạn có thể xóa chúng đi nếu muốn thế.\n"
+"bắt đầu bằng '%s' sẽ được bỠqua; bạn có thể xóa chúng đi nếu muốn thế.\n"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
"Hãy nhập vào các thông tin để giải thích các thay đổi của bạn. Những dòng "
"được\n"
-"bắt đầu bằng “%c†sẽ được bỠqua; bạn có thể xóa chúng đi nếu muốn thế.\n"
+"bắt đầu bằng '%s' sẽ được bỠqua; bạn có thể xóa chúng đi nếu muốn thế.\n"
"Phần chú thích này nếu trống rỗng sẽ hủy bỠlần chuyển giao.\n"
msgid ""
@@ -4665,10 +4753,10 @@ msgid "%sCommitter: %.*s <%.*s>"
msgstr "%sNgÆ°á»i chuyển giao: %.*s <%.*s>"
msgid "Cannot read index"
-msgstr "Không Ä‘á»c được bảng mục lục"
+msgstr "Không Ä‘á»c được chỉ mục"
msgid "unable to pass trailers to --trailers"
-msgstr "không thể chuyển phần Ä‘uôi cho “--trailersâ€"
+msgstr "không thể chuyển phần đuôi cho '--trailers'"
msgid "Error building trees"
msgstr "Gặp lỗi khi xây dựng cây"
@@ -4680,25 +4768,25 @@ msgstr "Xin hãy cung cấp lá»i chú giải hoặc là dùng tùy chá»n -m ho
#, c-format
msgid "--author '%s' is not 'Name <email>' and matches no existing author"
msgstr ""
-"--author “%s†không phải là “HỠvà tên <thư điện tửl>†và không khớp bất kỳ "
-"tác giả nào sẵn có"
+"--author '%s' không phải là 'Há»-và-tên <email>' và không khá»›p bất kỳ tác giả "
+"nào sẵn có"
#, c-format
msgid "Invalid ignored mode '%s'"
-msgstr "Chế Ä‘á»™ bá» qua không hợp lệ “%sâ€"
+msgstr "Chế độ bỠqua không hợp lệ '%s'"
#, c-format
msgid "Invalid untracked files mode '%s'"
-msgstr "Chế Ä‘á»™ cho các tập tin chÆ°a được theo dõi không hợp lệ “%sâ€"
+msgstr "Chế độ cho các tập tin chưa được theo dõi không hợp lệ '%s'"
msgid "You are in the middle of a merge -- cannot reword."
msgstr ""
-"Bạn Ä‘ang ở giữa của quá trình hòa trá»™n -- không thể thá»±c hiện việc “rewordâ€."
+"Bạn đang ở giữa của quá trình hòa trộn -- không thể thực hiện việc 'reword'."
msgid "You are in the middle of a cherry-pick -- cannot reword."
msgstr ""
"Bạn đang ở giữa của quá trình cherry-pick -- không thể thực hiện việc "
-"“rewordâ€."
+"'reword'."
#, c-format
msgid "reword option of '%s' and path '%s' cannot be used together"
@@ -4710,20 +4798,20 @@ msgid "reword option of '%s' and '%s' cannot be used together"
msgstr "không thể tổ hợp tùy chá»n \"reword\" của '%s' vá»›i '%s' cùng nhau"
msgid "You have nothing to amend."
-msgstr "Không có gì để mà “tu bổ†cả."
+msgstr "Không có gì để 'tu bổ' cả."
msgid "You are in the middle of a merge -- cannot amend."
msgstr ""
-"Bạn Ä‘ang ở giữa của quá trình hòa trá»™n -- không thể thá»±c hiện việc “tu bổâ€."
+"Bạn đang ở giữa của quá trình hòa trộn -- không thể thực hiện việc 'tu bổ'."
msgid "You are in the middle of a cherry-pick -- cannot amend."
msgstr ""
-"Bạn đang ở giữa của quá trình cherry-pick -- không thể thực hiện việc “tu "
-"bổâ€."
+"Bạn đang ở giữa của quá trình cherry-pick -- không thể thực hiện việc 'tu "
+"bổ'."
msgid "You are in the middle of a rebase -- cannot amend."
msgstr ""
-"Bạn Ä‘ang ở giữa của quá trình cải tổ -- nên không thể thá»±c hiện việc “tu bổâ€."
+"Bạn đang ở giữa của quá trình cải tổ -- nên không thể thực hiện việc 'tu bổ'."
msgid "--reset-author can be used only with -C, -c or --amend."
msgstr ""
@@ -4735,7 +4823,7 @@ msgstr "không hiểu tùy chá»n: --fixup=%s:%s"
#, c-format
msgid "paths '%s ...' with -a does not make sense"
-msgstr "các Ä‘Æ°á»ng dẫn “%s …†vá»›i tùy chá»n -a không hợp lý"
+msgstr "các Ä‘Æ°á»ng dẫn '%s ...' vá»›i tùy chá»n -a không hợp lý"
msgid "show status concisely"
msgstr "hiển thị trạng thái ở dạng súc tích"
@@ -4747,7 +4835,7 @@ msgid "show stash information"
msgstr "hiển thị thông tin vỠtạm cất"
msgid "compute full ahead/behind values"
-msgstr "tính đầy đủ giá trị trước/sau"
+msgstr "tính đầy đủ giá trị dẫn trước/sau"
msgid "version"
msgstr "phiên bản"
@@ -4759,10 +4847,7 @@ msgid "show status in long format (default)"
msgstr "hiển thị trạng thái ở định dạng dài (mặc định)"
msgid "terminate entries with NUL"
-msgstr "chấm dứt các mục bằng NUL"
-
-msgid "mode"
-msgstr "chế độ"
+msgstr "kết thúc các mục bằng NUL"
msgid "show untracked files, optional modes: all, normal, no. (Default: all)"
msgstr ""
@@ -4790,20 +4875,19 @@ msgid "list untracked files in columns"
msgstr "hiển thị danh sách các tập-tin chưa được theo dõi trong các cột"
msgid "do not detect renames"
-msgstr "không dò tìm các tên thay đổi"
+msgstr "không dò tìm các lần đổi tên"
msgid "detect renames, optionally set similarity index"
-msgstr "dò các tên thay đổi, tùy ý đặt mục lục tương tự"
+msgstr "tìm và phát hiện các lần đổi tên, có thể đánh chỉ số tương tự"
msgid "Unsupported combination of ignored and untracked-files arguments"
-msgstr ""
-"Không hỗ trỡ tổ hợp các tham số các tập tin bị bỠqua và không được theo dõi"
+msgstr "Không hỗ trợ cùng lúc tham số tập tin bị bỠqua và không được theo dõi"
msgid "suppress summary after successful commit"
msgstr "không hiển thị tổng kết sau khi chuyển giao thành công"
msgid "show diff in commit message template"
-msgstr "hiển thị sự khác biệt trong mẫu tin nhắn chuyển giao"
+msgstr "hiển thị diff trong mẫu tin nhắn chuyển giao"
msgid "Commit message options"
msgstr "Các tùy chá»n ghi chú commit"
@@ -4878,7 +4962,7 @@ msgid "commit all changed files"
msgstr "chuyển giao tất cả các tập tin có thay đổi"
msgid "add specified files to index for commit"
-msgstr "thêm các tập tin đã chỉ ra vào bảng mục lục để chuyển giao"
+msgstr "thêm các tập tin đã chỉ ra vào chỉ mục để chuyển giao"
msgid "interactively add files"
msgstr "thêm các tập-tin bằng tương tác"
@@ -4896,7 +4980,7 @@ msgid "show what would be committed"
msgstr "hiển thị xem cái gì có thể được chuyển giao"
msgid "amend previous commit"
-msgstr "“tu bổ†(amend) lần commit trước"
+msgstr "'tu bổ' (amend) lần commit trước"
msgid "bypass post-rewrite hook"
msgstr "vòng qua móc (hook) post-rewrite"
@@ -4908,7 +4992,7 @@ msgid "ok to record a change with an empty message"
msgstr "ok để ghi các thay đổi vá»›i lá»i nhắn trống rá»—ng"
msgid "could not parse HEAD commit"
-msgstr "không thể phân tích commit (lần chuyển giao) HEAD"
+msgstr "không thể Ä‘á»c commit (lần chuyển giao) HEAD"
#, c-format
msgid "Corrupt MERGE_HEAD file (%s)"
@@ -4923,27 +5007,26 @@ msgstr "không thể Ä‘á»c phần chú thích (message) của lần chuyển gi
#, c-format
msgid "Aborting commit due to empty commit message.\n"
-msgstr "Bãi bỠviệc chuyển giao bởi vì phần chú thích của nó trống rỗng.\n"
+msgstr "Huỷ bỠlệnh chuyển giao bởi vì phần chú thích của nó trống rỗng.\n"
#, c-format
msgid "Aborting commit; you did not edit the message.\n"
msgstr ""
-"Äang bá» qua việc chuyển giao; bạn đã không biên soạn phần chú thích "
-"(message).\n"
+"Huỷ bỠlệnh chuyển giao; bạn đã không biên soạn phần chú thích (message).\n"
#, c-format
msgid "Aborting commit due to empty commit message body.\n"
msgstr ""
-"Bãi bỠviệc chuyển giao bởi vì phần thân chú thích của nó trống rỗng.\n"
+"Huỷ bỠlệnh chuyển giao bởi vì phần thân chú thích của nó trống rỗng.\n"
msgid ""
"repository has been updated, but unable to write\n"
-"new_index file. Check that disk is not full and quota is\n"
+"new index file. Check that disk is not full and quota is\n"
"not exceeded, and then \"git restore --staged :/\" to recover."
msgstr ""
"kho chứa đã được cập nhật, nhưng không thể ghi vào\n"
-"tập tin new_index (bảng mục lục mới). Hãy kiểm tra xem đĩa\n"
-"có bị đầy quá hay quota (hạn nghạch đĩa cứng) bị vượt quá,\n"
+"tập tin chỉ mục mới. Hãy kiểm tra xem đĩa\n"
+"có bị đầy quá hay hạn nghạch đĩa (quota) bị vượt quá hay không,\n"
"và sau đó \"git restore --staged :/\" để khắc phục."
msgid "git config [<options>]"
@@ -5017,7 +5100,7 @@ msgid "list all"
msgstr "liệt kê tất"
msgid "use string equality when comparing values to 'value-pattern'"
-msgstr "sá»­ dụng so sánh bằng chuá»—i khi so sánh các giá trị vá»›i “value-patternâ€"
+msgstr "sử dụng so sánh bằng chuỗi khi so sánh các giá trị với 'value-pattern'"
msgid "open an editor"
msgstr "mở một trình biên soạn"
@@ -5059,7 +5142,7 @@ msgid "Other"
msgstr "Khác"
msgid "terminate values with NUL byte"
-msgstr "chấm dứt giá trị với byte NUL"
+msgstr "kết thúc giá trị với byte NUL"
msgid "show variable names only"
msgstr "chỉ hiển thị các tên biến"
@@ -5068,9 +5151,7 @@ msgid "respect include directives on lookup"
msgstr "tôn trá»ng kể cà các hÆ°á»›ng trong tìm kiếm"
msgid "show origin of config (file, standard input, blob, command line)"
-msgstr ""
-"hiển thị nguyên gốc của cấu hình (tập tin, đầu vào tiêu chuẩn, blob, dòng "
-"lệnh)"
+msgstr "hiển thị nguồn gốc của cấu hình (tập tin, stdin, blob, dòng lệnh)"
msgid "show scope of config (worktree, local, global, system, command)"
msgstr ""
@@ -5083,6 +5164,9 @@ msgstr "giá trị"
msgid "with --get, use default value when missing entry"
msgstr "với --get, dùng giá trị mặc định khi thiếu mục tin"
+msgid "human-readable comment string (# will be prepended as needed)"
+msgstr "ghi chú cho ngÆ°á»i Ä‘á»c được (tá»± Ä‘á»™ng thêm # vào trÆ°á»›c nếu cần)"
+
#, c-format
msgid "wrong number of arguments, should be %d"
msgstr "sai số lượng tham số, phải là %d"
@@ -5105,16 +5189,16 @@ msgstr "gặp lỗi khi định dạng giá trị cấu hình mặc định: %s"
#, c-format
msgid "cannot parse color '%s'"
-msgstr "không thể phân tích màu “%sâ€"
+msgstr "không thể Ä‘á»c màu '%s'"
msgid "unable to parse default color value"
-msgstr "không thể phân tích giá trị màu mặc định"
+msgstr "không thể Ä‘á»c giá trị màu mặc định"
msgid "not in a git directory"
msgstr "không trong thư mục git"
msgid "writing to stdin is not supported"
-msgstr "việc ghi ra đầu ra tiêu chuẩn là không được hỗ trợ"
+msgstr "việc ghi ra stdin là không được hỗ trợ"
msgid "writing config blobs is not supported"
msgstr "không hỗ trợ ghi cấu hình các blob"
@@ -5176,25 +5260,28 @@ msgstr ""
msgid "--default is only applicable to --get"
msgstr "--default chỉ được áp dụng cho --get"
+msgid "--comment is only applicable to add/set/replace operations"
+msgstr "--comment chỉ được áp dụng cho thao tác add/set/replace"
+
msgid "--fixed-value only applies with 'value-pattern'"
-msgstr "--fixed-value chỉ áp dụng vá»›i “value-patternâ€"
+msgstr "--fixed-value chỉ áp dụng với 'value-pattern'"
#, c-format
msgid "unable to read config file '%s'"
-msgstr "không thể Ä‘á»c tập tin cấu hình “%sâ€"
+msgstr "không thể Ä‘á»c tập tin cấu hình '%s'"
msgid "error processing config file(s)"
msgstr "gặp lỗi khi xử lý các tập tin cấu hình"
msgid "editing stdin is not supported"
-msgstr "sửa chữa đầu ra tiêu chuẩn là không được hỗ trợ"
+msgstr "sửa chữa stdin là không được hỗ trợ"
msgid "editing blobs is not supported"
msgstr "việc sửa chữa các blob là không được hỗ trợ"
#, c-format
msgid "cannot create configuration file %s"
-msgstr "không thể tạo tập tin cấu hình “%sâ€"
+msgstr "không thể tạo tập tin cấu hình '%s'"
#, c-format
msgid ""
@@ -5219,12 +5306,12 @@ msgid ""
"\tchmod 0700 %s"
msgstr ""
"Quyá»n hạn trên thÆ° mục gói mạng của bạn không chính xác; ngÆ°á»i dùng\n"
-"khác có lẽ có thể Ä‘á»c được chứng thÆ° được lÆ°u đệm của bạn. Cân nhắc chạy:\n"
+"khác có lẽ có thể Ä‘á»c được chứng thÆ° được lÆ°u đệm của bạn. Thá»­ chạy:\n"
"\n"
"\tchmod 0700 %s"
msgid "print debugging messages to stderr"
-msgstr "in thông tin gỡ lỗi ra đầu ra lỗi tiêu chuẩn"
+msgstr "in thông tin gỡ lỗi ra stderr"
msgid "credential-cache--daemon unavailable; no unix socket support"
msgstr "credential-cache--daemon không sẵn có; không hỗ trợ unix socket"
@@ -5236,17 +5323,24 @@ msgstr "credential-cache không sẵn có; không hỗ trợ unix socket"
msgid "unable to get credential storage lock in %d ms"
msgstr "không thể lấy khóa lưu trữ ủy nhiệm %d ms"
-msgid "git describe [<options>] [<commit-ish>...]"
-msgstr "git describe [<các tùy chá»n>] <commit-ish>*"
+msgid ""
+"git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]"
+msgstr ""
+"git describe [--all] [--tags] [--contains] [--abbrev=<n>] [<commit-ish>...]"
+
+msgid ""
+"git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]"
+msgstr ""
+"git describe [--all] [--tags] [--contains] [--abbrev=<n>] --dirty[=<mark>]"
-msgid "git describe [<options>] --dirty"
-msgstr "git describe [<các tùy chá»n>] --dirty"
+msgid "git describe <blob>"
+msgstr "git describe <blob>"
msgid "head"
-msgstr "phía trước"
+msgstr "head"
msgid "lightweight"
-msgstr "hạng nhẹ"
+msgstr "nhẹ"
msgid "annotated"
msgstr "có diễn giải"
@@ -5257,11 +5351,11 @@ msgstr "thẻ đã được ghi chú %s không sẵn để dùng"
#, c-format
msgid "tag '%s' is externally known as '%s'"
-msgstr "ở bên ngoài, thẻ “%s†đã được biết đến là “%sâ€"
+msgstr "ở bên ngoài, thẻ '%s' đã được biết đến là '%s'"
#, c-format
msgid "no tag exactly matches '%s'"
-msgstr "không có thẻ nào khá»›p chính xác vá»›i “%sâ€"
+msgstr "không có thẻ nào khớp chính xác với '%s'"
#, c-format
msgid "No exact match on refs or tags, searching to describe\n"
@@ -5276,7 +5370,7 @@ msgid ""
"No annotated tags can describe '%s'.\n"
"However, there were unannotated tags: try --tags."
msgstr ""
-"Không có thẻ được chú giải nào được mô tả là “%sâ€.\n"
+"Không có thẻ được chú giải nào được mô tả là '%s'.\n"
"Tuy nhiên, ở đây có những thẻ không được chú giải: hãy thử --tags."
#, c-format
@@ -5284,7 +5378,7 @@ msgid ""
"No tags can describe '%s'.\n"
"Try --always, or create some tags."
msgstr ""
-"Không có thẻ có thể mô tả “%sâ€.\n"
+"Không có thẻ có thể mô tả '%s'.\n"
"Hãy thử --always, hoặc tạo một số thẻ."
#, c-format
@@ -5315,13 +5409,13 @@ msgid "find the tag that comes after the commit"
msgstr "tìm các thẻ mà nó đến trước lần chuyển giao"
msgid "debug search strategy on stderr"
-msgstr "chiến lược tìm kiếm gỡ lỗi trên đầu ra lỗi chuẩn stderr"
+msgstr "gỡ lỗi chiến lược tìm kiếm ra stderr"
msgid "use any ref"
msgstr "dùng ref bất kỳ"
msgid "use any tag, even unannotated"
-msgstr "dùng thẻ bất kỳ, cả khi “unannotatedâ€"
+msgstr "dùng thẻ bất kỳ, cả khi 'unannotated'"
msgid "always use long format"
msgstr "luôn dùng định dạng dài"
@@ -5333,39 +5427,60 @@ msgid "only output exact matches"
msgstr "chỉ xuất những gì khớp chính xác"
msgid "consider <n> most recent tags (default: 10)"
-msgstr "coi như <n> thẻ gần đây nhất (mặc định: 10)"
+msgstr "chá»n trong <n> thẻ gần đây nhất (mặc định: 10)"
msgid "only consider tags matching <pattern>"
-msgstr "chỉ cân nhắc đến những thẻ khớp với <mẫu>"
+msgstr "chỉ chá»n những thẻ khá»›p vá»›i <mẫu>"
msgid "do not consider tags matching <pattern>"
-msgstr "không coi rằng các thẻ khớp với <mẫu>"
+msgstr "không chá»n những thẻ khá»›p vá»›i <mẫu>"
msgid "show abbreviated commit object as fallback"
-msgstr "hiển thị đối tượng chuyển giao vắn tắt như là fallback"
+msgstr "hiển thị vắn tắt đối tượng chuyển giao để thay thế"
msgid "mark"
msgstr "dấu"
msgid "append <mark> on dirty working tree (default: \"-dirty\")"
-msgstr "thêm <dấu> trên cây thư mục làm việc bẩn (mặc định \"-dirty\")"
+msgstr "thêm <dấu> trên cây làm việc không sạch (mặc định \"-dirty\")"
msgid "append <mark> on broken working tree (default: \"-broken\")"
-msgstr "thêm <dấu> trên cây thÆ° mục làm việc bị há»ng (mặc định \"-broken\")"
+msgstr "thêm <dấu> trên cây làm việc bị há»ng (mặc định \"-broken\")"
msgid "No names found, cannot describe anything."
-msgstr "Không tìm thấy các tên, không thể mô tả gì cả."
+msgstr "Không tìm thấy tên, không thể mô tả gì cả."
#, c-format
msgid "option '%s' and commit-ishes cannot be used together"
msgstr "tùy chá»n '%s' và commit-ishes không thể dùng cùng nhau"
+msgid ""
+"git diagnose [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+" [--mode=<mode>]"
+msgstr ""
+"git diagnose [(-o | --output-directory) <tập tin>] [(-s | --suffix) <định "
+"dạng>]\n"
+" [--mode=<chế độ>]"
+
+msgid "specify a destination for the diagnostics archive"
+msgstr "chỉ định thư mục đích để tạo bản báo cáo"
+
+msgid "specify a strftime format suffix for the filename"
+msgstr ""
+"chỉ định chuá»—i định dạng thá»i gian strftime dùng làm hậu tố cho tên tập tin"
+
+msgid "specify the content of the diagnostic archive"
+msgstr "chỉ định nội dung bản báo cáo"
+
msgid "--merge-base only works with two commits"
msgstr "--merge-base chỉ hoạt động với hai lần chuyển giao"
#, c-format
msgid "'%s': not a regular file or symlink"
-msgstr "“%sâ€: không phải tập tin bình thÆ°á»ng hay liên kết má»m"
+msgstr "'%s': không phải tập tin bình thÆ°á»ng hay liên kết má»m"
+
+msgid "no merge given, only parents."
+msgstr "không có lần hoà trộn, chỉ có các lần chuyển giao cha"
#, c-format
msgid "invalid option: %s"
@@ -5373,31 +5488,31 @@ msgstr "tùy chá»n không hợp lệ: %s"
#, c-format
msgid "%s...%s: no merge base"
-msgstr "%s…%s: không có cơ sở hòa trộn"
+msgstr "%s...%s: không có gốc hòa trộn"
msgid "Not a git repository"
msgstr "Không phải là kho git"
#, c-format
msgid "invalid object '%s' given."
-msgstr "đối tượng đã cho “%s†không hợp lệ."
+msgstr "đối tượng đã cho '%s' không hợp lệ."
#, c-format
msgid "more than two blobs given: '%s'"
-msgstr "đã cho nhiá»u hÆ¡n hai đối tượng blob: “%sâ€"
+msgstr "đã cho nhiá»u hÆ¡n hai đối tượng blob: '%s'"
#, c-format
msgid "unhandled object '%s' given."
-msgstr "đã cho đối tượng không thể nắm giữ “%sâ€."
+msgstr "đã cho đối tượng không thể xử lý '%s'."
#, c-format
msgid "%s...%s: multiple merge bases, using %s"
-msgstr "%s…%s: có nhiá»u cÆ¡ sở để hòa trá»™n, nên dùng %s"
+msgstr "%s...%s: có nhiá»u gốc hòa trá»™n, sẽ dùng %s"
msgid "git difftool [<options>] [<commit> [<commit>]] [--] [<path>...]"
msgstr ""
"git difftool [<các tùy chá»n>] [<lần_chuyển_giao> [<lần_chuyển_giao>]] [--] </"
-"Ä‘Æ°á»ng/dẫn>…]"
+"Ä‘Æ°á»ng/dẫn>...]"
#, c-format
msgid "could not read symlink %s"
@@ -5415,23 +5530,23 @@ msgid ""
"combined diff formats ('-c' and '--cc') are not supported in\n"
"directory diff mode ('-d' and '--dir-diff')."
msgstr ""
-"các định dạng diff tổ hợp(“-c†và “--ccâ€) chÆ°a được há»— trợ trong\n"
-"chế Ä‘á»™ diff thÆ° mục(“-d†và “--dir-diffâ€)."
+"các định dạng diff tổ hợp('-c' và '--cc') chưa được hỗ trợ trong\n"
+"chế độ diff thư mục('-d' và '--dir-diff')."
#, c-format
msgid "both files modified: '%s' and '%s'."
-msgstr "cả hai tập tin đã bị sá»­a: “%s†và “%sâ€."
+msgstr "cả hai tập tin đã bị sửa: '%s' và '%s'."
msgid "working tree file has been left."
msgstr "cây làm việc ở bên trái."
#, c-format
msgid "could not copy '%s' to '%s'"
-msgstr "không thể chép “%s†sang “%sâ€"
+msgstr "không thể chép '%s' sang '%s'"
#, c-format
msgid "temporary files exist in '%s'."
-msgstr "các tập tin tạm đã sẵn có trong “%sâ€."
+msgstr "các tập tin tạm đã sẵn có trong '%s'."
msgid "you may want to cleanup or recover these."
msgstr "bạn có lẽ muốn dá»n dẹp hay phục hồi ở đây."
@@ -5441,7 +5556,7 @@ msgid "failed: %d"
msgstr "gặp lỗi: %d"
msgid "use `diff.guitool` instead of `diff.tool`"
-msgstr "dùng “diff.guitool“ thay vì dùng “diff.tool“"
+msgstr "dùng 'diff.guitool' thay vì dùng 'diff.tool'"
msgid "perform a full-directory diff"
msgstr "thực hiện một diff toàn thư mục"
@@ -5459,18 +5574,18 @@ msgid "use the specified diff tool"
msgstr "dùng công cụ diff đã cho"
msgid "print a list of diff tools that may be used with `--tool`"
-msgstr "in ra danh sách các công cụ dif cái mà có thẻ dùng với “--tool“"
+msgstr "in ra danh sách các công cụ dif cái mà có thẻ dùng với '--tool'"
msgid ""
"make 'git-difftool' exit when an invoked diff tool returns a non-zero exit "
"code"
-msgstr "làm cho “git-difftool†thoát khi gá»i công cụ diff trả vá» mã khác không"
+msgstr "làm cho 'git-difftool' thoát khi gá»i công cụ diff trả vá» mã khác không"
msgid "specify a custom command for viewing diffs"
msgstr "chỉ định một lệnh tùy ý để xem diff"
msgid "passed to `diff`"
-msgstr "chuyển cho “diffâ€"
+msgstr "chuyển cho 'diff'"
msgid "difftool requires worktree or --no-index"
msgstr "difftool cần cây làm việc hoặc --no-index"
@@ -5481,28 +5596,6 @@ msgstr "chưa đưa ra <công_cụ> cho --tool=<công_cụ>"
msgid "no <cmd> given for --extcmd=<cmd>"
msgstr "chưa đưa ra <lệnh> cho --extcmd=<lệnh>"
-msgid "git env--helper --type=[bool|ulong] <options> <env-var>"
-msgstr "git env--helper --type=[bool|ulong] <các tùy chá»n> <env-var>"
-
-msgid "default for git_env_*(...) to fall back on"
-msgstr "mặc định cho git_env_*(…) để quay vá»"
-
-msgid "be quiet only use git_env_*() value as exit code"
-msgstr "im lặng chỉ khi dung giá trị git_env_*() làm mã thoát"
-
-#, c-format
-msgid "option `--default' expects a boolean value with `--type=bool`, not `%s`"
-msgstr ""
-"tùy chá»n “--default†cần má»™t giá trị logic vá»›i “--type=bool“, không phải “%s“"
-
-#, c-format
-msgid ""
-"option `--default' expects an unsigned long value with `--type=ulong`, not `"
-"%s`"
-msgstr ""
-"tùy chá»n “--default†cần má»™t giá trị số nguyên dài không dấu vá»›i “--"
-"type=ulong“, không phải “%s“"
-
msgid "git fast-export [<rev-list-opts>]"
msgstr "git fast-export [<rev-list-opts>]"
@@ -5541,7 +5634,7 @@ msgid "output full tree for each commit"
msgstr "xuất ra toàn bộ cây cho mỗi lần chuyển giao"
msgid "use the done feature to terminate the stream"
-msgstr "sử dụng tính năng done để chấm dứt luồng dữ liệu"
+msgstr "sử dụng tính năng done để kết thúc luồng dữ liệu"
msgid "skip output of blob data"
msgstr "bỠqua kết xuất của dữ liệu blob"
@@ -5574,40 +5667,40 @@ msgstr "gắn thẻ với các mã ID đánh dấu"
#, c-format
msgid "Missing from marks for submodule '%s'"
-msgstr "Thiếu các đánh dấu cho mô-Ä‘un-con “%sâ€"
+msgstr "Thiếu các đánh dấu cho mô-đun-con '%s'"
#, c-format
msgid "Missing to marks for submodule '%s'"
-msgstr "Thiếu đánh dấu cho mô-Ä‘un-con “%sâ€"
+msgstr "Thiếu đánh dấu cho mô-đun-con '%s'"
#, c-format
msgid "Expected 'mark' command, got %s"
-msgstr "Cần lệnh “markâ€, nhÆ°ng lại nhận được %s"
+msgstr "Cần lệnh 'mark', nhưng lại có %s"
#, c-format
msgid "Expected 'to' command, got %s"
-msgstr "Cần lệnh “toâ€, nhÆ°ng lại nhận được %s"
+msgstr "Cần lệnh 'to', nhưng lại có %s"
msgid "Expected format name:filename for submodule rewrite option"
-msgstr "Cần định dạng tên:tên_tập_tin cho tùy chá»n ghi lại mô-Ä‘un-con"
+msgstr "Cần định dạng tên:tên_tập tin cho tùy chá»n ghi lại mô-Ä‘un-con"
#, c-format
msgid "feature '%s' forbidden in input without --allow-unsafe-features"
msgstr ""
-"tính năng “%s†bị cấm chỉ trong đầu vào mà không có --allow-unsafe-features"
+"tính năng '%s' bị cấm chỉ trong đầu vào mà không có --allow-unsafe-features"
#, c-format
msgid "Lockfile created but not reported: %s"
msgstr "Tập tin khóa đã được tạo nhưng chưa được báo cáo: %s"
msgid "git fetch [<options>] [<repository> [<refspec>...]]"
-msgstr "git fetch [<các tùy chá»n>] [<kho-chứa> [<refspec>…]]"
+msgstr "git fetch [<các tùy chá»n>] [<kho-chứa> [<refspec>...]]"
msgid "git fetch [<options>] <group>"
msgstr "git fetch [<các tùy chá»n>] [<nhóm>"
msgid "git fetch --multiple [<options>] [(<repository> | <group>)...]"
-msgstr "git fetch --multiple [<các tùy chá»n>] [(<kho> | <nhóm>)…]"
+msgstr "git fetch --multiple [<các tùy chá»n>] [(<kho> | <nhóm>)...]"
msgid "git fetch --all [<options>]"
msgstr "git fetch --all [<các tùy chá»n>]"
@@ -5615,118 +5708,14 @@ msgstr "git fetch --all [<các tùy chá»n>]"
msgid "fetch.parallel cannot be negative"
msgstr "fetch.parallel không thể âm"
-msgid "fetch from all remotes"
-msgstr "lấy vỠtừ tất cả các máy chủ"
-
-msgid "set upstream for git pull/fetch"
-msgstr "đặt thượng nguồn cho git pull/fetch"
-
-msgid "append to .git/FETCH_HEAD instead of overwriting"
-msgstr "nối thêm vào .git/FETCH_HEAD thay vì ghi đè lên nó"
-
-msgid "use atomic transaction to update references"
-msgstr "sử dụng giao dịch hạt nhân bên phía máy chủ"
-
-msgid "path to upload pack on remote end"
-msgstr "Ä‘Æ°á»ng dẫn đến gói tải lên trên máy chủ cuối"
-
-msgid "force overwrite of local reference"
-msgstr "ép buộc ghi đè lên tham chiếu nội bộ"
-
-msgid "fetch from multiple remotes"
-msgstr "lấy từ nhiá»u máy chủ cùng lúc"
-
-msgid "fetch all tags and associated objects"
-msgstr "lấy tất cả các thẻ cùng với các đối tượng liên quan đến nó"
-
-msgid "do not fetch all tags (--no-tags)"
-msgstr "không lấy tất cả các thẻ (--no-tags)"
-
-msgid "number of submodules fetched in parallel"
-msgstr "số lượng mô-Ä‘un-con được lấy đồng thá»i"
-
-msgid "modify the refspec to place all refs within refs/prefetch/"
-msgstr ""
-"sá»­a đặc tả Ä‘Æ°á»ng dẫn cho các tham chiếu má»i chá»— có trong refs/prefetch/"
-
-msgid "prune remote-tracking branches no longer on remote"
-msgstr ""
-"cắt cụt (prune) các nhánh “remote-tracking†không còn tồn tại trên máy chủ "
-"nữa"
-
-msgid "prune local tags no longer on remote and clobber changed tags"
-msgstr "cắt xém các thẻ nội bộ không còn ở máy chủ và xóa các thẻ đã thay đổi"
-
-msgid "on-demand"
-msgstr "khi-cần"
-
-msgid "control recursive fetching of submodules"
-msgstr "Ä‘iá»u khiển việc lấy vỠđệ quy trong các mô-Ä‘un-con"
-
-msgid "write fetched references to the FETCH_HEAD file"
-msgstr "ghi các tham chiếu lấy vỠvào tập tin FETCH_HEAD"
-
-msgid "keep downloaded pack"
-msgstr "giữ lại gói đã tải vá»"
-
-msgid "allow updating of HEAD ref"
-msgstr "cho phép cập nhật th.chiếu HEAD"
-
-msgid "deepen history of shallow clone"
-msgstr "làm sâu hơn lịch sử của bản sao"
-
-msgid "deepen history of shallow repository based on time"
-msgstr "làm sâu hÆ¡n lịch sá»­ của kho bản sao shallow dá»±a trên thá»i gian"
-
-msgid "convert to a complete repository"
-msgstr "chuyển đổi hoàn toàn sang kho git"
-
-msgid "re-fetch without negotiating common commits"
-msgstr "re-fetch mà không dàn xếp các lần chuyển giao chung"
-
-msgid "prepend this to submodule path output"
-msgstr "soạn sẵn cái này cho kết xuất Ä‘Æ°á»ng dẫn mô-Ä‘un-con"
-
-msgid ""
-"default for recursive fetching of submodules (lower priority than config "
-"files)"
-msgstr ""
-"mặc định cho việc lấy đệ quy các mô-đun-con (có mức ưu tiên thấp hơn các tập "
-"tin cấu hình config)"
-
-msgid "accept refs that update .git/shallow"
-msgstr "chấp nhận tham chiếu cập nhật .git/shallow"
-
-msgid "refmap"
-msgstr "refmap"
-
-msgid "specify fetch refmap"
-msgstr "chỉ ra refmap cần lấy vá»"
-
-msgid "report that we have only objects reachable from this object"
-msgstr ""
-"báo cáo rằng chúng ta chỉ có các đối tượng tiếp cận được từ đối tượng này"
-
-msgid "do not fetch a packfile; instead, print ancestors of negotiation tips"
-msgstr ""
-"không lấy vỠmột packfile; thay vào đó, hãy in tổ tiên của đỉnh đàm phán"
-
-msgid "run 'maintenance --auto' after fetching"
-msgstr "chạy “maintenance --auto†sau khi lấy vá»"
-
-msgid "check for forced-updates on all updated branches"
-msgstr "kiểm cho các-cập-nhật-bắt-buá»™c trên má»i nhánh đã cập nhật"
-
-msgid "write the commit-graph after fetching"
-msgstr "ghi ra đồ thị các lần chuyển giao sau khi lấy vá»"
-
-msgid "accept refspecs from stdin"
-msgstr "chấp nhận tham chiếu từ đầu vào tiêu chuẩn"
-
msgid "couldn't find remote ref HEAD"
msgstr "không thể tìm thấy HEAD tham chiếu máy chủ"
#, c-format
+msgid "From %.*s\n"
+msgstr "Từ %.*s\n"
+
+#, c-format
msgid "object %s not found"
msgstr "không tìm thấy đối tượng %s"
@@ -5736,11 +5725,8 @@ msgstr "[đã cập nhật]"
msgid "[rejected]"
msgstr "[Bị từ chối]"
-msgid "can't fetch in current branch"
-msgstr "không thể fetch (lấy) vỠnhánh hiện hành"
-
-msgid "checked out in another worktree"
-msgstr "lấy ra trong cây làm việc khác"
+msgid "can't fetch into checked-out branch"
+msgstr "không thể fetch vỠnhánh đã checkout"
msgid "[tag update]"
msgstr "[cập nhật thẻ]"
@@ -5768,7 +5754,7 @@ msgstr "không-phải-chuyển-tiếp-nhanh"
#, c-format
msgid "cannot open '%s'"
-msgstr "không mở được “%sâ€"
+msgstr "không mở được '%s'"
msgid ""
"fetch normally indicates which branches had a forced update,\n"
@@ -5777,7 +5763,7 @@ msgid ""
msgstr ""
"việc lấy vá» thÆ°á»ng chỉ ra các nhánh buá»™c phải cập nhật,\n"
"nhÆ°ng lá»±a chá»n bị tắt; để kích hoạt lại, sá»­ dụng cá»\n"
-"“--show-forced-updates†hoặc chạy “git config fetch.showForcedUpdates trueâ€."
+"'--show-forced-updates' hoặc chạy 'git config fetch.showForcedUpdates true'."
#, c-format
msgid ""
@@ -5787,8 +5773,8 @@ msgid ""
"to avoid this check\n"
msgstr ""
"việc này cần %.2f giây để kiểm tra các cập nhật ép buộc; bạn có thể dùng\n"
-"“--no-show-forced-updates†hoặc chạy “git config fetch.showForcedUpdates "
-"falseâ€\n"
+"'--no-show-forced-updates' hoặc chạy 'git config fetch.showForcedUpdates "
+"false'\n"
"để tránh kiểm tra này\n"
#, c-format
@@ -5800,16 +5786,12 @@ msgid "rejected %s because shallow roots are not allowed to be updated"
msgstr "từ chối %s bởi vì các gốc nông thì không được phép cập nhật"
#, c-format
-msgid "From %.*s\n"
-msgstr "Từ %.*s\n"
-
-#, c-format
msgid ""
"some local refs could not be updated; try running\n"
" 'git remote prune %s' to remove any old, conflicting branches"
msgstr ""
"một số tham chiếu nội bộ không thể được cập nhật; hãy thử chạy\n"
-" “git remote prune %s†để bỠđi những nhánh cũ, hay bị xung đột"
+" 'git remote prune %s' để bỠđi những nhánh cũ, hay bị xung đột"
#, c-format
msgid " (%s will become dangling)"
@@ -5827,7 +5809,7 @@ msgstr "(không)"
#, c-format
msgid "refusing to fetch into branch '%s' checked out at '%s'"
-msgstr "từ chối lấy vá» vào nhánh “%s†đã được lấy ra tại “%sâ€"
+msgstr "từ chối lấy vỠvào nhánh '%s' đã được checkout tại '%s'"
#, c-format
msgid "option \"%s\" value \"%s\" is not valid for %s"
@@ -5843,7 +5825,7 @@ msgstr "%s không phải là một đối tượng hợp lệ"
#, c-format
msgid "the object %s does not exist"
-msgstr "đối tượng “%s†không tồn tại"
+msgstr "đối tượng '%s' không tồn tại"
msgid "multiple branches detected, incompatible with --set-upstream"
msgstr "phát hiện nhiá»u nhánh, không tÆ°Æ¡ng thích vá»›i --set-upstream"
@@ -5874,15 +5856,15 @@ msgstr ""
#, c-format
msgid "Fetching %s\n"
-msgstr "Äang lấy “%s†vá»\n"
+msgstr "Äang lấy '%s' vá»\n"
#, c-format
msgid "could not fetch %s"
-msgstr "không thể lấy “%s†vá»"
+msgstr "không thể lấy '%s' vá»"
#, c-format
msgid "could not fetch '%s' (exit code: %d)\n"
-msgstr "không thể lấy “%s†(mã thoát: %d)\n"
+msgstr "không thể lấy '%s' (mã thoát: %d)\n"
msgid ""
"no remote repository specified; please specify either a URL or a\n"
@@ -5894,6 +5876,113 @@ msgstr ""
msgid "you need to specify a tag name"
msgstr "bạn cần chỉ định một tên thẻ"
+msgid "fetch from all remotes"
+msgstr "lấy vỠtừ tất cả các máy chủ"
+
+msgid "set upstream for git pull/fetch"
+msgstr "đặt thượng nguồn cho git pull/fetch"
+
+msgid "append to .git/FETCH_HEAD instead of overwriting"
+msgstr "nối thêm vào .git/FETCH_HEAD thay vì ghi đè lên nó"
+
+msgid "use atomic transaction to update references"
+msgstr "sử dụng giao dịch hạt nhân bên phía máy chủ"
+
+msgid "path to upload pack on remote end"
+msgstr "Ä‘Æ°á»ng dẫn đến gói tải lên trên máy chủ cuối"
+
+msgid "force overwrite of local reference"
+msgstr "ép buộc ghi đè lên tham chiếu nội bộ"
+
+msgid "fetch from multiple remotes"
+msgstr "lấy từ nhiá»u máy chủ cùng lúc"
+
+msgid "fetch all tags and associated objects"
+msgstr "lấy tất cả các thẻ cùng với các đối tượng liên quan đến nó"
+
+msgid "do not fetch all tags (--no-tags)"
+msgstr "không lấy tất cả các thẻ (--no-tags)"
+
+msgid "number of submodules fetched in parallel"
+msgstr "số lượng mô-Ä‘un-con được lấy đồng thá»i"
+
+msgid "modify the refspec to place all refs within refs/prefetch/"
+msgstr ""
+"sá»­a đặc tả Ä‘Æ°á»ng dẫn cho các tham chiếu má»i chá»— có trong refs/prefetch/"
+
+msgid "prune remote-tracking branches no longer on remote"
+msgstr ""
+"cắt (prune) các nhánh 'remote-tracking' không còn tồn tại trên máy chủ nữa"
+
+msgid "prune local tags no longer on remote and clobber changed tags"
+msgstr ""
+"xoá (prune) các thẻ nội bộ không còn ở máy chủ và xóa các thẻ đã thay đổi"
+
+msgid "on-demand"
+msgstr "khi-cần"
+
+msgid "control recursive fetching of submodules"
+msgstr "Ä‘iá»u khiển việc lấy vỠđệ quy trong các mô-Ä‘un-con"
+
+msgid "write fetched references to the FETCH_HEAD file"
+msgstr "ghi các tham chiếu lấy vỠvào tập tin FETCH_HEAD"
+
+msgid "keep downloaded pack"
+msgstr "giữ lại gói đã tải vá»"
+
+msgid "allow updating of HEAD ref"
+msgstr "cho phép cập nhật th.chiếu HEAD"
+
+msgid "deepen history of shallow clone"
+msgstr "làm sâu hơn lịch sử của bản sao"
+
+msgid "deepen history of shallow repository based on time"
+msgstr "làm sâu hÆ¡n lịch sá»­ của kho bản sao shallow dá»±a trên thá»i gian"
+
+msgid "convert to a complete repository"
+msgstr "chuyển đổi hoàn toàn sang kho git"
+
+msgid "re-fetch without negotiating common commits"
+msgstr "re-fetch mà không dàn xếp các lần chuyển giao chung"
+
+msgid "prepend this to submodule path output"
+msgstr "soạn sẵn cái này cho kết xuất Ä‘Æ°á»ng dẫn mô-Ä‘un-con"
+
+msgid ""
+"default for recursive fetching of submodules (lower priority than config "
+"files)"
+msgstr ""
+"mặc định cho việc lấy đệ quy các mô-đun-con (có mức ưu tiên thấp hơn các tập "
+"tin cấu hình config)"
+
+msgid "accept refs that update .git/shallow"
+msgstr "chấp nhận tham chiếu cập nhật .git/shallow"
+
+msgid "refmap"
+msgstr "refmap"
+
+msgid "specify fetch refmap"
+msgstr "chỉ ra refmap cần lấy vá»"
+
+msgid "report that we have only objects reachable from this object"
+msgstr "báo rằng ta chỉ có các đối tượng tiếp cận được từ đối tượng này"
+
+msgid "do not fetch a packfile; instead, print ancestors of negotiation tips"
+msgstr ""
+"không lấy vỠmột packfile; thay vào đó, hãy in tổ tiên của đỉnh đàm phán"
+
+msgid "run 'maintenance --auto' after fetching"
+msgstr "chạy 'maintenance --auto' sau khi lấy vá»"
+
+msgid "check for forced-updates on all updated branches"
+msgstr "kiểm cho các-cập-nhật-bắt-buá»™c trên má»i nhánh đã cập nhật"
+
+msgid "write the commit-graph after fetching"
+msgstr "ghi ra đồ thị các lần chuyển giao sau khi lấy vá»"
+
+msgid "accept refspecs from stdin"
+msgstr "chấp nhận tham chiếu từ stdin"
+
msgid "--negotiate-only needs one or more --negotiation-tip=*"
msgstr "--negotiate-only cần má»™t hay nhiá»u --negotiation-tip=* hÆ¡n"
@@ -5903,6 +5992,10 @@ msgstr "mức sâu là số âm trong --deepen là không được hỗ trợ"
msgid "--unshallow on a complete repository does not make sense"
msgstr "--unshallow trên kho hoàn chỉnh là không hợp lý"
+#, c-format
+msgid "failed to fetch bundles from '%s'"
+msgstr "gặp lỗi khi lấy vỠbundle từ '%s'"
+
msgid "fetch --all does not take a repository argument"
msgstr "lệnh lấy vỠ\"fetch --all\" không lấy đối số kho chứa"
@@ -5942,16 +6035,16 @@ msgstr ""
"tin>]"
msgid "populate log with at most <n> entries from shortlog"
-msgstr "gắn nhật ký vá»›i ít nhất <n> mục từ lệnh “shortlogâ€"
+msgstr "gắn nhật ký với ít nhất <n> mục từ lệnh 'shortlog'"
msgid "alias for --log (deprecated)"
-msgstr "bí danh cho --log (không được dùng)"
+msgstr "bí danh cho --log (đã lạc hậu)"
msgid "text"
msgstr "văn bản"
msgid "use <text> as start of message"
-msgstr "dùng <văn bản thÆ°á»ng> để bắt đầu ghi chú"
+msgstr "dùng <văn bản> để bắt đầu ghi chú"
msgid "use <name> instead of the real target branch"
msgstr "dùng <tên> thay cho nhánh đích thật"
@@ -5976,16 +6069,16 @@ msgstr ""
"chuyển-giao>]]"
msgid "quote placeholders suitably for shells"
-msgstr "trích dẫn để phù hợp cho hệ vỠ(shell)"
+msgstr "trích dẫn dạng phù hợp cho shell"
msgid "quote placeholders suitably for perl"
-msgstr "trích dẫn để phù hợp cho perl"
+msgstr "trích dẫn dạng phù hợp cho perl"
msgid "quote placeholders suitably for python"
-msgstr "trích dẫn để phù hợp cho python"
+msgstr "trích dẫn dạng phù hợp cho python"
msgid "quote placeholders suitably for Tcl"
-msgstr "trích dẫn để phù hợp cho Tcl"
+msgstr "trích dẫn dạng phù hợp cho Tcl"
msgid "show only <n> matched refs"
msgstr "hiển thị chỉ <n> tham chiếu khớp"
@@ -6008,8 +6101,17 @@ msgstr "chỉ hiển thị những tham chiếu mà nó chứa lần chuyển gi
msgid "print only refs which don't contain the commit"
msgstr "chỉ hiển thị những tham chiếu mà nó không chứa lần chuyển giao"
-msgid "git for-each-repo --config=<config> <command-args>"
-msgstr "git for-each-repo --config=<config> <command-args>"
+msgid "read reference patterns from stdin"
+msgstr "Ä‘á»c các mẫu tham chiếu từ stdin"
+
+msgid "also include HEAD ref and pseudorefs"
+msgstr "bao gồm tham chiếu HEAD và giả tham chiếu"
+
+msgid "unknown arguments supplied with --stdin"
+msgstr "đối số không rõ được chỉ định cùng với --stdin"
+
+msgid "git for-each-repo --config=<config> [--] <arguments>"
+msgstr "git for-each-repo --config=<tùy chá»n> [--] <đối số>"
msgid "config"
msgstr "config"
@@ -6020,6 +6122,10 @@ msgstr "khóa cấu hình lÆ°u trữ danh sách Ä‘Æ°á»ng dẫn kho lÆ°u trữ"
msgid "missing --config=<config>"
msgstr "thiếu --config=<config>"
+#, c-format
+msgid "got bad config --config=%s"
+msgstr "cấu hình sai --config=%s"
+
msgid "unknown"
msgstr "không hiểu"
@@ -6068,11 +6174,11 @@ msgstr "không thể tạo lost-found"
#, c-format
msgid "could not write '%s'"
-msgstr "không thể ghi “%sâ€"
+msgstr "không thể ghi '%s'"
#, c-format
msgid "could not finish '%s'"
-msgstr "không thể hoàn thành “%sâ€"
+msgstr "không thể hoàn thành '%s'"
#, c-format
msgid "Checking %s"
@@ -6087,7 +6193,7 @@ msgid "Checking %s %s"
msgstr "Äang kiểm tra %s %s"
msgid "broken links"
-msgstr "các liên kết bị gẫy"
+msgstr "liên kết há»ng"
#, c-format
msgid "root %s"
@@ -6107,7 +6213,7 @@ msgstr "%s: mục reflog không hợp lệ %s"
#, c-format
msgid "Checking reflog %s->%s"
-msgstr "Äang kiểm tra việc đổi tên của “%s†thành “%sâ€"
+msgstr "Äang kiểm tra việc đổi tên của '%s' thành '%s'"
#, c-format
msgid "%s: invalid sha1 pointer %s"
@@ -6130,11 +6236,11 @@ msgstr "%s: thiếu đối tượng hoặc há»ng: %s"
#, c-format
msgid "%s: object is of unknown type '%s': %s"
-msgstr "%s: đối tượng có kiểu chÆ°a biết “%sâ€: %s"
+msgstr "%s: đối tượng có kiểu chưa biết '%s': %s"
#, c-format
msgid "%s: object could not be parsed: %s"
-msgstr "%s: không thể phân tích cú đối tượng: %s"
+msgstr "%s: không thể Ä‘á»c cú đối tượng: %s"
#, c-format
msgid "bad sha1 file: %s"
@@ -6166,36 +6272,57 @@ msgstr "%s: HEAD đã tách rá»i không chỉ vào đâu cả"
msgid "notice: %s points to an unborn branch (%s)"
msgstr "chú ý: %s chỉ đến một nhánh chưa sinh (%s)"
-msgid "Checking cache tree"
-msgstr "Äang kiểm tra cây nhá»› tạm"
+#, c-format
+msgid "Checking cache tree of %s"
+msgstr "Äang kiểm tra cây nhá»› tạm của %s"
#, c-format
-msgid "%s: invalid sha1 pointer in cache-tree"
-msgstr "%s: con trỠsha1 không hợp lệ trong cache-tree"
+msgid "%s: invalid sha1 pointer in cache-tree of %s"
+msgstr "%s: con trỠsha1 không hợp lệ trong cây nhớ tạm của %s"
msgid "non-tree in cache-tree"
msgstr "non-tree trong cache-tree"
-msgid "git fsck [<options>] [<object>...]"
-msgstr "git fsck [<các tùy chá»n>] [<đối-tượng>…]"
+#, c-format
+msgid "%s: invalid sha1 pointer in resolve-undo of %s"
+msgstr "%s: con trỠsha1 không hợp lệ trong resolve-undo của %s"
+
+#, c-format
+msgid "unable to load rev-index for pack '%s'"
+msgstr "không thể tải pack-index cho gói '%s'"
+
+#, c-format
+msgid "invalid rev-index for pack '%s'"
+msgstr "giá trị rev-index cho gói '%s' không hợp lệ"
+
+msgid ""
+"git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
+" [--[no-]full] [--strict] [--verbose] [--lost-found]\n"
+" [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n"
+" [--[no-]name-objects] [<object>...]"
+msgstr ""
+"git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]\n"
+" [--[no-]full] [--strict] [--verbose] [--lost-found]\n"
+" [--[no-]dangling] [--[no-]progress] [--connectivity-only]\n"
+" [--[no-]name-objects] [<đối tượng>...]"
msgid "show unreachable objects"
-msgstr "hiển thị các đối tượng không thể Ä‘á»c được"
+msgstr "hiển thị các đối tượng không thể tới được"
msgid "show dangling objects"
msgstr "hiển thị các đối tượng không được quản lý"
msgid "report tags"
-msgstr "báo cáo các thẻ"
+msgstr "liệt kê các thẻ"
msgid "report root nodes"
-msgstr "báo cáo node gốc"
+msgstr "liệt kê node gốc"
msgid "make index objects head nodes"
-msgstr "tạo “index objects head nodesâ€"
+msgstr "tạo 'index objects head nodes'"
msgid "make reflogs head nodes (default)"
-msgstr "tạo “reflogs head nodes†(mặc định)"
+msgstr "tạo 'reflogs head nodes' (mặc định)"
msgid "also consider packs and alternate objects"
msgstr "cũng cân nhắc đến các đối tượng gói và thay thế"
@@ -6224,7 +6351,7 @@ msgstr "%s: thiếu đối tượng"
#, c-format
msgid "invalid parameter: expected sha1, got '%s'"
-msgstr "tham số không hợp lệ: cần sha1, nhÆ°ng lại nhận được “%sâ€"
+msgstr "tham số không hợp lệ: cần sha1, nhưng lại có '%s'"
msgid "git fsmonitor--daemon start [<options>]"
msgstr "git fsmonitor--daemon start [<các tùy chá»n>]"
@@ -6232,15 +6359,9 @@ msgstr "git fsmonitor--daemon start [<các tùy chá»n>]"
msgid "git fsmonitor--daemon run [<options>]"
msgstr "git fsmonitor--daemon run [<các tùy chá»n>]"
-msgid "git fsmonitor--daemon stop"
-msgstr "git fsmonitor--daemon stop"
-
-msgid "git fsmonitor--daemon status"
-msgstr "git fsmonitor--daemon status"
-
#, c-format
msgid "value of '%s' out of range: %d"
-msgstr "siá trị '%s' ngoài phạm vi cho phép: %d"
+msgstr "giá trị '%s' ngoài phạm vi cho phép: %d"
#, c-format
msgid "value of '%s' not bool or int: %d"
@@ -6256,7 +6377,7 @@ msgstr "fsmonitor-daemon hiện không theo dõi '%s'\n"
#, c-format
msgid "could not create fsmonitor cookie '%s'"
-msgstr "không thể tạo fsmonitor cookie “%sâ€"
+msgstr "không thể tạo fsmonitor cookie '%s'"
#, c-format
msgid "fsmonitor: cookie_result '%d' != SEEN"
@@ -6264,24 +6385,23 @@ msgstr "fsmonitor: cookie_result '%d' != SEEN"
#, c-format
msgid "could not start IPC thread pool on '%s'"
-msgstr "không thể khởi chạy bể tiến trình IPC trêm “%sâ€"
+msgstr "không thể khởi chạy pool tiến trình IPC trên '%s'"
msgid "could not start fsmonitor listener thread"
-msgstr "không thể lấy thông tin thống kê vỠtuyến trình lắng nghe fsmonitor"
+msgstr "không thể khởi chạy fsmonitor listener thread"
msgid "could not start fsmonitor health thread"
-msgstr ""
-"không thể lấy thông tin thống kê vá» tuyến trình theo dõi sức khá»e fsmonitor"
+msgstr "không thể khởi chạy fsmonitor health thread"
msgid "could not initialize listener thread"
-msgstr "không thể khởi tạo tuyến trình lắng nghe"
+msgstr "không thể khởi tạo listener thread"
msgid "could not initialize health thread"
-msgstr "không thể khởi tạo tuyến trình sức "
+msgstr "không thể khởi tạo health thread"
#, c-format
msgid "could not cd home '%s'"
-msgstr "không thể chuyển đến thÆ° mục cá nhân “%sâ€"
+msgstr "không thể cd home '%s'"
#, c-format
msgid "fsmonitor--daemon is already running '%s'"
@@ -6293,7 +6413,7 @@ msgstr "chạy fsmonitor-daemon trong '%s'\n"
#, c-format
msgid "starting fsmonitor-daemon in '%s'\n"
-msgstr "Ä‘ang khởi chạy fsmonitor-daemon trong “%sâ€\n"
+msgstr "đang khởi chạy fsmonitor-daemon trong '%s'\n"
msgid "daemon failed to start"
msgstr "gặp lỗi khi khởi chạy dịch vụ chạy ngầm"
@@ -6329,15 +6449,15 @@ msgstr "git gc [<các tùy chá»n>]"
#, c-format
msgid "Failed to fstat %s: %s"
-msgstr "Gặp lỗi khi lấy thông tin thống kê vỠtập tin %s: %s"
+msgstr "Gặp lỗi khi fstat %s: %s"
#, c-format
msgid "failed to parse '%s' value '%s'"
-msgstr "gặp lá»—i khi phân tích “%s†giá trị “%sâ€"
+msgstr "gặp lá»—i khi Ä‘á»c '%s' giá trị '%s'"
#, c-format
msgid "cannot stat '%s'"
-msgstr "không thể lấy thông tin thống kê vỠ“%sâ€"
+msgstr "không thể stat '%s'"
#, c-format
msgid ""
@@ -6359,6 +6479,9 @@ msgstr "xóa bỠcác đối tượng không được tham chiếu"
msgid "pack unreferenced objects separately"
msgstr "đóng gói riêng các đối tượng không được tham chiếu"
+msgid "with --cruft, limit the size of new cruft packs"
+msgstr "vá»›i tuỳ chá»n --cruft, giá»›i hạn kích thÆ°á»›c pack cruft má»›i"
+
msgid "be more thorough (increased runtime)"
msgstr "cẩn thận hÆ¡n nữa (tăng thá»i gian chạy)"
@@ -6373,11 +6496,11 @@ msgstr "đóng gói lại tất cả các gói khác ngoại trừ gói lớn nh
#, c-format
msgid "failed to parse gc.logExpiry value %s"
-msgstr "gặp lỗi khi phân tích giá trị gc.logExpiry %s"
+msgstr "gặp lá»—i khi Ä‘á»c giá trị gc.logExpiry %s"
#, c-format
msgid "failed to parse prune expiry value %s"
-msgstr "gặp lỗi khi phân tích giá trị prune %s"
+msgstr "gặp lá»—i khi Ä‘á»c giá trị prune %s"
#, c-format
msgid "Auto packing the repository in background for optimum performance.\n"
@@ -6397,13 +6520,13 @@ msgstr "Xem \"git help gc\" để có hÆ°á»›ng dẫn cụ thể vá» cách dá»n
msgid ""
"gc is already running on machine '%s' pid %<PRIuMAX> (use --force if not)"
msgstr ""
-"gc đang được thực hiện trên máy “%s†pid %<PRIuMAX> (dùng --force nếu không "
+"gc đang được thực hiện trên máy '%s' pid %<PRIuMAX> (dùng --force nếu không "
"phải thế)"
msgid ""
"There are too many unreachable loose objects; run 'git prune' to remove them."
msgstr ""
-"Có quá nhiá»u đối tượng tá»± do không được dùng đến; hãy chạy lệnh “git prune†"
+"Có quá nhiá»u đối tượng tá»± do không được dùng đến; hãy chạy lệnh 'git prune' "
"để xóa bỠchúng đi."
msgid ""
@@ -6425,19 +6548,19 @@ msgid "failed to prefetch remotes"
msgstr "gặp lỗi khi tải trước các máy chủ"
msgid "failed to start 'git pack-objects' process"
-msgstr "gặp lá»—i khi lấy thông tin thống kê vá» tiến trình “git pack-objectsâ€"
+msgstr "gặp lỗi khi khởi chạy tiến trình 'git pack-objects'"
msgid "failed to finish 'git pack-objects' process"
-msgstr "gặp lá»—i khi hoàn tất tiến trình “git pack-objectsâ€"
+msgstr "gặp lỗi khi hoàn tất tiến trình 'git pack-objects'"
msgid "failed to write multi-pack-index"
msgstr "gặp lỗi khi ghi multi-pack-index"
msgid "'git multi-pack-index expire' failed"
-msgstr "gặp lá»—i khi chạy “git multi-pack-index expireâ€"
+msgstr "gặp lỗi khi chạy 'git multi-pack-index expire'"
msgid "'git multi-pack-index repack' failed"
-msgstr "gặp lá»—i khi chạy “git multi-pack-index repackâ€"
+msgstr "gặp lỗi khi chạy 'git multi-pack-index repack'"
msgid ""
"skipping incremental-repack task because core.multiPackIndex is disabled"
@@ -6445,19 +6568,19 @@ msgstr "bỠqua tác vụ incremental-repack vì core.multiPackIndex bị vô h
#, c-format
msgid "lock file '%s' exists, skipping maintenance"
-msgstr "đã có khóa của tập tin “%sâ€, bá» qua bảo trì"
+msgstr "đã có khóa của tập tin '%s', bỠqua bảo trì"
#, c-format
msgid "task '%s' failed"
-msgstr "gặp lá»—i khi thá»±c hiện nhiệm vụ “%sâ€"
+msgstr "gặp lỗi khi thực hiện nhiệm vụ '%s'"
#, c-format
msgid "'%s' is not a valid task"
-msgstr "“%s†không phải một nhiệm vụ hợp lệ"
+msgstr "'%s' không phải một nhiệm vụ hợp lệ"
#, c-format
msgid "task '%s' cannot be selected multiple times"
-msgstr "nhiệm vụ “%s†không được chá»n nhiá»u lần"
+msgstr "nhiệm vụ '%s' không được chá»n nhiá»u lần"
msgid "run tasks based on the state of the repository"
msgstr "chạy nhiệm vụ dựa trên trạng thái của kho chứa"
@@ -6469,7 +6592,7 @@ msgid "run tasks based on frequency"
msgstr "chạy nhiệm vụ dựa trên tần suất"
msgid "do not report progress or other information over stderr"
-msgstr "đừng báo cáo diễn tiến hay các thông tin khác ra đầu lỗi tiêu chuẩn"
+msgstr "đừng báo cáo tiến độ hay các thông tin khác ra stderr"
msgid "task"
msgstr "tác vụ"
@@ -6480,12 +6603,24 @@ msgstr "chạy một nhiệm vụ cụ thể"
msgid "use at most one of --auto and --schedule=<frequency>"
msgstr "dùng nhiá»u nhất là má»™t trong --auto và --schedule=<frequency>"
-msgid "failed to run 'git config'"
-msgstr "gặp lá»—i khi chạy “git configâ€"
+#, c-format
+msgid "unable to add '%s' value of '%s'"
+msgstr "không thể thêm giá trị '%s' của '%s'"
+
+msgid "return success even if repository was not registered"
+msgstr "trả vỠthành công kể cả khi kho chứa chưa được ghi nhận"
+
+#, c-format
+msgid "unable to unset '%s' value of '%s'"
+msgstr "không thể bỠđặt giá trị '%s' của '%s'"
+
+#, c-format
+msgid "repository '%s' is not registered"
+msgstr "kho chứa '%s' chưa tồn tại"
#, c-format
msgid "failed to expand path '%s'"
-msgstr "gặp lá»—i khi khai triển Ä‘Æ°á»ng dẫn “%sâ€"
+msgstr "gặp lá»—i khi khai triển Ä‘Æ°á»ng dẫn '%s'"
msgid "failed to start launchctl"
msgstr "gặp lỗi khi khởi chạy launchctl"
@@ -6502,38 +6637,41 @@ msgid "failed to create temp xml file"
msgstr "gặp lá»—i khi tạo tập tin xml tạm thá»i"
msgid "failed to start schtasks"
-msgstr "gặp lỗi khi lấy thông tin thống kê vỠschtasks"
+msgstr "gặp lỗi khi khởi chạy schtasks"
msgid "failed to run 'crontab -l'; your system might not support 'cron'"
msgstr ""
-"gặp lá»—i khi chạy “crontab -lâ€; hệ thống của bạn có thể không há»— trợ “cronâ€"
+"gặp lỗi khi chạy 'crontab -l'; hệ thống của bạn có thể không hỗ trợ 'cron'"
-msgid "failed to run 'crontab'; your system might not support 'cron'"
-msgstr "gặp lá»—i khi chạy “crontabâ€; hiển thị của bạn có lẽ không há»— trợ “cronâ€"
+msgid "failed to create crontab temporary file"
+msgstr "không thể tạo tập tin tạm thá»i crontab"
-msgid "failed to open stdin of 'crontab'"
-msgstr "gặp lá»—i khi mở đầu vào tiêu chuẩn của “crontabâ€"
+msgid "failed to open temporary file"
+msgstr "không thể mở tập tin tạm thá»i"
-msgid "'crontab' died"
-msgstr "“crontab†đã chết"
-
-msgid "failed to start systemctl"
-msgstr "gặp lỗi khi khởi chạy systemctl"
+msgid "failed to run 'crontab'; your system might not support 'cron'"
+msgstr "gặp lỗi khi chạy 'crontab'; hệ thống của bạn có lẽ không hỗ trợ 'cron'"
-msgid "failed to run systemctl"
-msgstr "gặp lỗi khi chạy systemctl"
+msgid "'crontab' died"
+msgstr "'crontab' đã chết"
#, c-format
msgid "failed to delete '%s'"
-msgstr "gặp lá»—i khi xóa “%sâ€"
+msgstr "gặp lỗi khi xóa '%s'"
#, c-format
msgid "failed to flush '%s'"
-msgstr "gặp lỗi khi đẩy dữ liệu “%s†lên đĩa"
+msgstr "gặp lỗi khi đẩy dữ liệu '%s' lên đĩa"
+
+msgid "failed to start systemctl"
+msgstr "gặp lỗi khi khởi chạy systemctl"
+
+msgid "failed to run systemctl"
+msgstr "gặp lỗi khi chạy systemctl"
#, c-format
msgid "unrecognized --scheduler argument '%s'"
-msgstr "đối số --scheduler không được thừa nhận “%sâ€"
+msgstr "đối số --scheduler không được thừa nhận '%s'"
msgid "neither systemd timers nor crontab are available"
msgstr "hoặc là bộ lập lịch systemd hoặc là crontab không sẵn có"
@@ -6554,18 +6692,17 @@ msgstr "bộ lên lịch"
msgid "scheduler to trigger git maintenance run"
msgstr "bộ lên lịch để kích hoạt chạy chương trình bảo trì git"
+msgid "failed to set up maintenance schedule"
+msgstr "gặp lỗi khi lên lịch bảo trì"
+
msgid "failed to add repo to global config"
msgstr "gặp lỗi khi thêm cấu hình toàn cục"
msgid "git maintenance <subcommand> [<options>]"
msgstr "git maintenance run <lệnh_con> [<các tùy chá»n>]"
-#, c-format
-msgid "invalid subcommand: %s"
-msgstr "lện con không hợp lệ: %s"
-
msgid "git grep [<options>] [-e] <pattern> [<rev>...] [[--] <path>...]"
-msgstr "git grep [<các tùy chá»n>] [-e] <mẫu> [<rev>…] [[--] </Ä‘Æ°á»ng/dẫn>…]"
+msgstr "git grep [<các tùy chá»n>] [-e] <mẫu> [<rev>...] [[--] </Ä‘Æ°á»ng/dẫn>...]"
#, c-format
msgid "grep: failed to create thread: %s"
@@ -6585,8 +6722,8 @@ msgid "no threads support, ignoring %s"
msgstr "không hỗ trợ đa tuyến, bỠqua %s"
#, c-format
-msgid "unable to read tree (%s)"
-msgstr "không thể Ä‘á»c cây (%s)"
+msgid "unable to read tree %s"
+msgstr "không thể Ä‘á»c cây %s"
#, c-format
msgid "unable to grep from object of type %s"
@@ -6594,10 +6731,10 @@ msgstr "không thể thá»±c hiện lệnh grep (lá»c tìm) từ đối tượng
#, c-format
msgid "switch `%c' expects a numerical value"
-msgstr "chuyển đến “%c†cần một giá trị bằng số"
+msgstr "chuyển đến '%c' cần một giá trị bằng số"
msgid "search in index instead of in the work tree"
-msgstr "tìm trong bảng mục lục thay vì trong cây làm việc"
+msgstr "tìm trong chỉ mục thay vì trong cây làm việc"
msgid "find in contents not managed by git"
msgstr "tìm trong nội dung không được quản lý bởi git"
@@ -6606,7 +6743,7 @@ msgid "search in both tracked and untracked files"
msgstr "tìm kiếm các tập tin được và chưa được theo dõi dấu vết"
msgid "ignore files specified via '.gitignore'"
-msgstr "các tập tin bị bá» qua được chỉ định thông qua “.gitignoreâ€"
+msgstr "các tập tin bị bỠqua được chỉ định thông qua '.gitignore'"
msgid "recursively search in each submodule"
msgstr "tìm kiếm đệ quy trong từng mô-đun-con"
@@ -6627,16 +6764,16 @@ msgid "don't match patterns in binary files"
msgstr "không khớp mẫu trong các tập tin nhị phân"
msgid "process binary files with textconv filters"
-msgstr "xá»­ lý tập tin nhị phân vá»›i các bá»™ lá»c “textconvâ€"
+msgstr "xá»­ lý tập tin nhị phân vá»›i các bá»™ lá»c 'textconv'"
msgid "search in subdirectories (default)"
msgstr "tìm kiếm trong thư mục con (mặc định)"
-msgid "descend at most <depth> levels"
-msgstr "hạ xuống ít nhất là mức <sâu>"
+msgid "descend at most <n> levels"
+msgstr "hạ xuống tối đa <n> mức"
msgid "use extended POSIX regular expressions"
-msgstr "dùng biểu thức chính qui POSIX có mở rộng"
+msgstr "dùng biểu thức chính quy POSIX có mở rộng"
msgid "use basic POSIX regular expressions (default)"
msgstr "sử dụng biểu thức chính quy kiểu POSIX (mặc định)"
@@ -6684,7 +6821,7 @@ msgid "highlight matches"
msgstr "tô sáng phần khớp mẫu"
msgid "print empty line between matches from different files"
-msgstr "hiển thị dòng trống giữa các lần khớp từ các tập tin khác biệt"
+msgstr "hiển thị dòng trống giữa các lần khớp từ các tập tin khác nhau"
msgid "show filename only once above matches from same file"
msgstr ""
@@ -6735,6 +6872,9 @@ msgstr "hiển thị các tập tin khớp trong trang giấy"
msgid "allow calling of grep(1) (ignored by this build)"
msgstr "cho phép gá»i grep(1) (bị bá» qua bởi lần dịch này)"
+msgid "maximum number of results per file"
+msgstr "số lượng kết quả tối đa trên mỗi tập tin"
+
msgid "no pattern given"
msgstr "chưa chỉ ra mẫu"
@@ -6768,11 +6908,14 @@ msgid "both --cached and trees are given"
msgstr "cả hai --cached và các cây phải được chỉ ra"
msgid ""
-"git hash-object [-t <type>] [-w] [--path=<file> | --no-filters] [--stdin] "
-"[--] <file>..."
+"git hash-object [-t <type>] [-w] [--path=<file> | --no-filters]\n"
+" [--stdin [--literally]] [--] <file>..."
msgstr ""
-"git hash-object [-t <kiểu>] [-w] [--path=<tập-tin> | --no-filters] [--stdin] "
-"[--] <tập-tin>…"
+"git hash-object [-t <kiểu>] [-w] [--path=<tập-tin> | --no-filters]\n"
+" [--stdin [--literally]] [--] <tập-tin>..."
+
+msgid "git hash-object [-t <type>] [-w] --stdin-paths [--no-filters]"
+msgstr "git hash-object [-t <kiểu>] [-w] --stdin-paths [--no-filters] "
msgid "object type"
msgstr "kiểu đối tượng"
@@ -6781,14 +6924,14 @@ msgid "write the object into the object database"
msgstr "ghi đối tượng vào dữ liệu đối tượng"
msgid "read the object from stdin"
-msgstr "Ä‘á»c đối tượng từ đầu vào tiêu chuẩn stdin"
+msgstr "Ä‘á»c đối tượng từ stdin"
msgid "store file as is without filters"
msgstr "lÆ°u các tập tin mà nó không có các bá»™ lá»c"
msgid ""
"just hash any random garbage to create corrupt objects for debugging Git"
-msgstr "chỉ cần băm rác ngẫu nhiên để tạo má»™t đối tượng há»ng để mà gỡ lá»—i Git"
+msgstr "chỉ cần băm rác ngẫu nhiên để tạo má»™t đối tượng há»ng để gỡ lá»—i Git"
msgid "process file as it were from this path"
msgstr "xử lý tập tin như là nó đang ở thư mục này"
@@ -6820,49 +6963,55 @@ msgstr "hiển thị mô tả lệnh"
msgid "print list of useful guides"
msgstr "hiển thị danh sách các hướng dẫn hữu dụng"
+msgid "print list of user-facing repository, command and file interfaces"
+msgstr "hiển thị các giao diện cho ngÆ°á»i dùng"
+
+msgid "print list of file formats, protocols and other developer interfaces"
+msgstr "hiển thị các giao diện cho lập trình viên"
+
msgid "print all configuration variable names"
msgstr "in ra tất cả các tên biến cấu hình"
-msgid "git help [[-i|--info] [-m|--man] [-w|--web]] [<command>]"
-msgstr "git help [[-i|--info] [-m|--man] [-w|--web]] [<lệnh>]"
+msgid "git help [[-i|--info] [-m|--man] [-w|--web]] [<command>|<doc>]"
+msgstr "git help [[-i|--info] [-m|--man] [-w|--web]] [<lệnh>|<tài liệu>]"
#, c-format
msgid "unrecognized help format '%s'"
-msgstr "không nhận ra định dạng trợ giúp “%sâ€"
+msgstr "không nhận ra định dạng trợ giúp '%s'"
msgid "Failed to start emacsclient."
msgstr "Gặp lỗi khi khởi chạy emacsclient."
msgid "Failed to parse emacsclient version."
-msgstr "Gặp lỗi khi phân tích phiên bản emacsclient."
+msgstr "Gặp lá»—i khi Ä‘á»c phiên bản emacsclient."
#, c-format
msgid "emacsclient version '%d' too old (< 22)."
-msgstr "phiên bản của emacsclient “%d†quá cũ (< 22)."
+msgstr "phiên bản của emacsclient '%d' quá cũ (< 22)."
#, c-format
msgid "failed to exec '%s'"
-msgstr "gặp lá»—i khi thá»±c thi “%sâ€"
+msgstr "gặp lỗi khi thực thi '%s'"
#, c-format
msgid ""
"'%s': path for unsupported man viewer.\n"
"Please consider using 'man.<tool>.cmd' instead."
msgstr ""
-"“%sâ€: Ä‘Æ°á»ng dẫn không há»— trợ bá»™ trình chiếu man.\n"
-"Hãy cân nhắc đến việc sử dụng “man.<tool>.cmd†để thay thế."
+"'%s': Ä‘Æ°á»ng dẫn không há»— trợ bá»™ trình chiếu man.\n"
+"Hãy cân nhắc đến việc sử dụng 'man.<tool>.cmd' để thay thế."
#, c-format
msgid ""
"'%s': cmd for supported man viewer.\n"
"Please consider using 'man.<tool>.path' instead."
msgstr ""
-"“%sâ€: cmd (lệnh) há»— trợ bá»™ trình chiếu man.\n"
-"Hãy cân nhắc đến việc sử dụng “man.<tool>.path†để thay thế."
+"'%s': cmd (lệnh) hỗ trợ bộ trình chiếu man.\n"
+"Hãy cân nhắc đến việc sử dụng 'man.<tool>.path' để thay thế."
#, c-format
msgid "'%s': unknown man viewer."
-msgstr "“%sâ€: không rõ chÆ°Æ¡ng trình xem man."
+msgstr "'%s': không rõ chương trình xem man."
msgid "no man viewer handled the request"
msgstr "không có trình xem trợ giúp dạng manpage tiếp hợp với yêu cầu"
@@ -6872,7 +7021,7 @@ msgstr "không có trình xem trợ giúp dạng info tiếp hợp vá»›i yêu cá
#, c-format
msgid "'%s' is aliased to '%s'"
-msgstr "“%s†được đặt bí danh thành “%sâ€"
+msgstr "'%s' được đặt bí danh thành '%s'"
#, c-format
msgid "bad alias.%s string: %s"
@@ -6893,13 +7042,20 @@ msgid "usage: %s%s"
msgstr "cách dùng: %s%s"
msgid "'git help config' for more information"
-msgstr "Chạy lệnh “git help config†để có thêm thông tin"
+msgstr "Chạy lệnh 'git help config' để có thêm thông tin"
-msgid "git hook run [--ignore-missing] <hook-name> [-- <hook-args>]"
-msgstr "git hook run [--ignore-missing] <tên-móc> [-- <các tham số cho móc>]"
+msgid ""
+"git hook run [--ignore-missing] [--to-stdin=<path>] <hook-name> [-- <hook-"
+"args>]"
+msgstr ""
+"git hook run [--ignore-missing] [--to-stdin=</Ä‘Æ°á»ng/dẫn/>] <tên-móc> [-- "
+"<các tham số cho móc>]"
msgid "silently ignore missing requested <hook-name>"
-msgstr "bỠqua âm thầm các <hook-name> đã yêu cầu còn thiếu"
+msgstr "âm thầm bỠqua các <hook-name> đã yêu cầu còn thiếu"
+
+msgid "file to read into hooks' stdin"
+msgstr "tập tin để đưa vào stdin của hook"
#, c-format
msgid "object type mismatch at %s"
@@ -6911,7 +7067,7 @@ msgstr "không thể lấy vỠđối tượng cần %s"
#, c-format
msgid "object %s: expected type %s, found %s"
-msgstr "đối tượng %s: cần kiểu %s nhưng lại nhận được %s"
+msgstr "đối tượng %s: cần kiểu %s nhưng lại có %s"
#, c-format
msgid "cannot fill %d byte"
@@ -6947,13 +7103,13 @@ msgstr "gói có đối tượng sai tại khoảng bù %<PRIuMAX>: %s"
#, c-format
msgid "inflate returned %d"
-msgstr "xả nén trả vỠ%d"
+msgstr "giải nén trả vỠ%d"
msgid "offset value overflow for delta base object"
msgstr "tràn giá trị khoảng bù cho đối tượng delta cơ sở"
msgid "delta base offset is out of bound"
-msgstr "khoảng bù cơ sở cho delta nằm ngoài phạm vi"
+msgstr "khoảng bù cơ sở cho delta nằm ngoài biên"
#, c-format
msgid "unknown object type %d"
@@ -6968,17 +7124,13 @@ msgid_plural "premature end of pack file, %<PRIuMAX> bytes missing"
msgstr[0] "tập tin gói bị kết thúc sớm, thiếu %<PRIuMAX> byte"
msgid "serious inflate inconsistency"
-msgstr "sá»± mâu thuẫn xả nén nghiêm trá»ng"
+msgstr "sá»± mâu thuẫn giải nén nghiêm trá»ng"
#, c-format
msgid "SHA1 COLLISION FOUND WITH %s !"
msgstr "Sá»° VA CHẠM SHA1 ÄÃ XẢY RA VỚI %s!"
#, c-format
-msgid "unable to read %s"
-msgstr "không thể Ä‘á»c %s"
-
-#, c-format
msgid "cannot read existing object info %s"
msgstr "không thể Ä‘á»c thông tin đối tượng sẵn có %s"
@@ -7004,13 +7156,13 @@ msgid "Receiving objects"
msgstr "Äang nhận vá» các đối tượng"
msgid "Indexing objects"
-msgstr "Các đối tượng bảng mục lục"
+msgstr "Các đối tượng chỉ mục"
msgid "pack is corrupted (SHA1 mismatch)"
msgstr "gói bị sai há»ng (SHA1 không khá»›p)"
msgid "cannot fstat packfile"
-msgstr "không thể lấy thông tin thống kê packfile"
+msgstr "không thể fstat packfile"
msgid "pack has junk at the end"
msgstr "pack có phần thừa ở cuối"
@@ -7035,7 +7187,7 @@ msgstr[0] "đầy đủ với %d đối tượng nội bộ"
#, c-format
msgid "Unexpected tail checksum for %s (disk corruption?)"
-msgstr "Gặp tổng kiểm tra tail không cần cho %s (Ä‘Ä©a há»ng?)"
+msgstr "Gặp tổng kiểm tra tail bất thÆ°á»ng cho %s (Ä‘Ä©a há»ng?)"
#, c-format
msgid "pack has %d unresolved delta"
@@ -7044,7 +7196,7 @@ msgstr[0] "gói có %d delta chưa được giải quyết"
#, c-format
msgid "unable to deflate appended object (%d)"
-msgstr "không thể xả nén đối tượng nối thêm (%d)"
+msgstr "không thể giải nén đối tượng nối thêm (%d)"
#, c-format
msgid "local object %s is corrupt"
@@ -7052,19 +7204,19 @@ msgstr "đối tượng ná»™i bá»™ %s bị há»ng"
#, c-format
msgid "packfile name '%s' does not end with '.%s'"
-msgstr "tên tập tin tập tin gói “%s†không được kết thúc “.%sâ€"
+msgstr "tên tập tin tập tin gói '%s' không được kết thúc '.%s'"
#, c-format
msgid "cannot write %s file '%s'"
-msgstr "không thể ghi %s tập tin “%sâ€"
+msgstr "không thể ghi %s tập tin '%s'"
#, c-format
msgid "cannot close written %s file '%s'"
-msgstr "không thể đóng tập tin được ghi %s “%sâ€"
+msgstr "không thể đóng tập tin được ghi %s '%s'"
#, c-format
msgid "unable to rename temporary '*.%s' file to '%s'"
-msgstr "không thể đổi tên tập tin tạm thá»i “*.%s†thành “%sâ€"
+msgstr "không thể đổi tên tập tin tạm thá»i '*.%s' thành '%s'"
msgid "error while closing pack file"
msgstr "gặp lỗi trong khi đóng tập tin gói"
@@ -7075,11 +7227,11 @@ msgstr "sai pack.indexVersion=%<PRIu32>"
#, c-format
msgid "Cannot open existing pack file '%s'"
-msgstr "Không thể mở tập tin gói đã sẵn có “%sâ€"
+msgstr "Không thể mở tập tin gói đã sẵn có '%s'"
#, c-format
msgid "Cannot open existing pack idx file for '%s'"
-msgstr "Không thể mở tập tin idx của gói cho “%sâ€"
+msgstr "Không thể mở tập tin idx của gói cho '%s'"
#, c-format
msgid "non delta: %d object"
@@ -7089,10 +7241,10 @@ msgstr[0] "không delta: %d đối tượng"
#, c-format
msgid "chain length = %d: %lu object"
msgid_plural "chain length = %d: %lu objects"
-msgstr[0] "chiá»u dài xích = %d: %lu đối tượng"
+msgstr[0] "chiá»u dài chuá»—i = %d: %lu đối tượng"
msgid "Cannot come back to cwd"
-msgstr "Không thể quay lại cwd"
+msgstr "Không thể quay lại thư mục hiện hành"
#, c-format
msgid "bad %s"
@@ -7100,7 +7252,7 @@ msgstr "%s sai"
#, c-format
msgid "unknown hash algorithm '%s'"
-msgstr "không hiểu thuật toán băm dữ liệu “%sâ€"
+msgstr "không hiểu thuật toán băm dữ liệu '%s'"
msgid "--stdin requires a git repository"
msgstr "--stdin cần một kho git"
@@ -7111,83 +7263,18 @@ msgstr "dùng tùy chá»n --verify mà không Ä‘Æ°a ra tên packfile"
msgid "fsck error in pack objects"
msgstr "lỗi fsck trong các đối tượng gói"
-#, c-format
-msgid "cannot stat template '%s'"
-msgstr "không thể lấy thông tin thống kê vá» mẫu “%sâ€"
-
-#, c-format
-msgid "cannot opendir '%s'"
-msgstr "không thể opendir() “%sâ€"
-
-#, c-format
-msgid "cannot readlink '%s'"
-msgstr "không thể readlink “%sâ€"
-
-#, c-format
-msgid "cannot symlink '%s' '%s'"
-msgstr "không thể tạo liên kết má»m (symlink) “%s†“%sâ€"
-
-#, c-format
-msgid "cannot copy '%s' to '%s'"
-msgstr "không thể sao chép “%s†sang “%sâ€"
-
-#, c-format
-msgid "ignoring template %s"
-msgstr "Ä‘ang lá» Ä‘i mẫu “%sâ€"
-
-#, c-format
-msgid "templates not found in %s"
-msgstr "các mẫu không được tìm thấy trong %s"
-
-#, c-format
-msgid "not copying templates from '%s': %s"
-msgstr "không sao chép các mẫu từ “%sâ€: %s"
-
-#, c-format
-msgid "invalid initial branch name: '%s'"
-msgstr "tên nhánh khởi tạo không hợp lệ: “%sâ€"
-
-#, c-format
-msgid "unable to handle file type %d"
-msgstr "không thể xử lý (handle) tập tin kiểu %d"
-
-#, c-format
-msgid "unable to move %s to %s"
-msgstr "không di chuyển được %s vào %s"
-
-msgid "attempt to reinitialize repository with different hash"
-msgstr "cố để khởi tạo lại một kho với kiểu băm dữ liệu khác"
-
-#, c-format
-msgid "%s already exists"
-msgstr "%s đã có từ trước rồi"
-
-#, c-format
-msgid "re-init: ignored --initial-branch=%s"
-msgstr "re-init: --initial-branch=%s bị bỠqua"
-
-#, c-format
-msgid "Reinitialized existing shared Git repository in %s%s\n"
-msgstr "Äã khởi tạo lại kho Git chia sẻ sẵn có trong %s%s\n"
-
-#, c-format
-msgid "Reinitialized existing Git repository in %s%s\n"
-msgstr "Äã khởi tạo lại kho Git sẵn có trong %s%s\n"
-
-#, c-format
-msgid "Initialized empty shared Git repository in %s%s\n"
-msgstr "Äã khởi tạo lại kho Git chia sẻ trống rá»—ng sẵn có trong %s%s\n"
-
-#, c-format
-msgid "Initialized empty Git repository in %s%s\n"
-msgstr "Äã khởi tạo lại kho Git trống rá»—ng sẵn có trong %s%s\n"
-
msgid ""
-"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--"
-"shared[=<permissions>]] [<directory>]"
+"git init [-q | --quiet] [--bare] [--template=<template-directory>]\n"
+" [--separate-git-dir <git-dir>] [--object-format=<format>]\n"
+" [--ref-format=<format>]\n"
+" [-b <branch-name> | --initial-branch=<branch-name>]\n"
+" [--shared[=<permissions>]] [<directory>]"
msgstr ""
-"git init [-q | --quiet] [--bare] [--template=<thư-mục-tạm>] [--shared[=<các-"
-"quyá»n>]] [thÆ°-mục]"
+"git init [-q | --quiet] [--bare] [--template=<thư mục mẫu>]\n"
+" [--separate-git-dir <thư mục git>] [--object-format=<định dạng>]\n"
+" [--ref-format=<định dạng>]\n"
+" [-b <tên nhánh> | --initial-branch=<tên nhánh>]\n"
+" [--shared[=<quyá»n hạn>]] [<thÆ° mục>]"
msgid "permissions"
msgstr "các quyá»n"
@@ -7222,23 +7309,54 @@ msgstr ""
#, c-format
msgid "Cannot access work tree '%s'"
-msgstr "Không thể truy cập cây (tree) làm việc “%sâ€"
+msgstr "Không thể truy cập cây làm việc '%s'"
msgid "--separate-git-dir incompatible with bare repository"
-msgstr "--separate-git-dir xung khắc với kho thuần"
+msgstr "--separate-git-dir không tương thích với kho bare"
msgid ""
-"git interpret-trailers [--in-place] [--trim-empty] [(--trailer "
-"<token>[(=|:)<value>])...] [<file>...]"
+"git interpret-trailers [--in-place] [--trim-empty]\n"
+" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
+" [--parse] [<file>...]"
msgstr ""
-"git interpret-trailers [--in-place] [--trim-empty] [(--trailer "
-"<thẻ>[(=|:)<giá-trị>])…] [<tập-tin>…]"
+"git interpret-trailers [--in-place] [--trim-empty]\n"
+" [(--trailer (<key>|<key-alias>)[(=|:)<giá-trị>])...]\n"
+" [--parse] [<tập-tin>...]"
+
+#, c-format
+msgid "could not stat %s"
+msgstr "không thể stat %s"
+
+#, c-format
+msgid "file %s is not a regular file"
+msgstr "\"%s\" không phải là tập tin bình thÆ°á»ng"
+
+#, c-format
+msgid "file %s is not writable by user"
+msgstr "tập tin %s ngÆ°á»i dùng không thể ghi được"
+
+msgid "could not open temporary file"
+msgstr "không thể tạo tập tin tạm thá»i"
+
+#, c-format
+msgid "could not read input file '%s'"
+msgstr "không Ä‘á»c được tập tin đầu vào '%s'"
+
+msgid "could not read from stdin"
+msgstr "không thể Ä‘á»c từ stdin"
+
+#, c-format
+msgid "could not rename temporary file to %s"
+msgstr "không thể đổi tên tập tin tạm thá»i thành %s"
msgid "edit files in place"
msgstr "sửa các tập tin tại chỗ"
msgid "trim empty trailers"
-msgstr "bộ dò vết cắt bỠphần trống rỗng"
+msgstr "cắt bỠphần trống thừa ở đuôi"
+
+msgid "placement"
+msgstr "vị trí"
msgid "where to place the new trailer"
msgstr "đặt phần đuôi mới ở đâu"
@@ -7252,20 +7370,20 @@ msgstr "thao tác khi thiếu phần đuôi"
msgid "output only the trailers"
msgstr "chỉ xuất phần đuôi"
-msgid "do not apply config rules"
-msgstr "đừng áp dụng các quy tắc cấu hình"
+msgid "do not apply trailer.* configuration variables"
+msgstr "không áp dụng các biến cấu hình trailer.*"
-msgid "join whitespace-continued values"
-msgstr "nối các giá trị khoảng-trắng-liên-tiếp"
+msgid "reformat multiline trailer values as single-line values"
+msgstr "định dạng lại giá trị đuôi thành giá trị trên một dòng"
-msgid "set parsing options"
-msgstr "đặt các tùy chá»n phân tích cú pháp"
+msgid "alias for --only-trailers --only-input --unfold"
+msgstr "viết tắt cho --only-trailers --only-input --unfold"
-msgid "do not treat --- specially"
-msgstr "không coi --- là đặc biệt"
+msgid "do not treat \"---\" as the end of input"
+msgstr "không coi \"---\" là kết thúc đầu vào"
msgid "trailer(s) to add"
-msgstr "bộ dò vết cần thêm"
+msgstr "phần đuôi cần thêm"
msgid "--trailer with --only-input does not make sense"
msgstr "--trailer cùng với --only-input không hợp lý"
@@ -7274,10 +7392,10 @@ msgid "no input file given for in-place editing"
msgstr "không đưa ra tập tin đầu vào để sửa tại-chỗ"
msgid "git log [<options>] [<revision-range>] [[--] <path>...]"
-msgstr "git log [<các tùy chá»n>] [<vùng-xem-xét>] [[--] </Ä‘Æ°á»ng/dẫn>…]"
+msgstr "git log [<các tùy chá»n>] [<vùng-xem-xét>] [[--] </Ä‘Æ°á»ng/dẫn>...]"
msgid "git show [<options>] <object>..."
-msgstr "git show [<các tùy chá»n>] <đối-tượng>…"
+msgstr "git show [<các tùy chá»n>] <đối-tượng>..."
#, c-format
msgid "invalid --decorate option: %s"
@@ -7289,8 +7407,8 @@ msgstr "chặn má»i kết xuất từ diff"
msgid "show source"
msgstr "hiển thị mã nguồn"
-msgid "use mail map file"
-msgstr "sử dụng tập tin ánh xạ thư"
+msgid "clear all previously-defined decoration filters"
+msgstr "xoá các bá»™ lá»c decorate đã định nghÄ©a từ trÆ°á»›c"
msgid "only decorate refs that match <pattern>"
msgstr "chỉ tô sáng các tham chiếu khớp với <mẫu>"
@@ -7299,21 +7417,21 @@ msgid "do not decorate refs that match <pattern>"
msgstr "không tô sáng các tham chiếu khớp với <mẫu>"
msgid "decorate options"
-msgstr "các tùy chá»n trang trí"
+msgstr "các tùy chá»n decorate"
msgid ""
"trace the evolution of line range <start>,<end> or function :<funcname> in "
"<file>"
msgstr ""
-"theo dõi sự tiến hóa của phạm vi <start><end> dòng, hoặc chức năng:"
-"<funcname> trong <file>"
+"theo vết sự tiến hóa của phạm vi dòng <start>,<end>, hoặc hàm :<tên hàm> "
+"trong <tập tin>"
#, c-format
msgid "unrecognized argument: %s"
msgstr "đối số không được thừa nhận: %s"
msgid "-L<range>:<file> cannot be used with pathspec"
-msgstr "-L<vùng>:<tập_tin> không thể được sá»­ dụng vá»›i đặc tả Ä‘Æ°á»ng dẫn"
+msgstr "-L<vùng>:<tập tin> không thể được sá»­ dụng vá»›i đặc tả Ä‘Æ°á»ng dẫn"
#, c-format
msgid "Final output: %d %s\n"
@@ -7343,7 +7461,7 @@ msgstr "format.headers không có giá trị cụ thể"
#, c-format
msgid "cannot open patch file %s"
-msgstr "không thể mở tập tin miếng vá: %s"
+msgstr "không thể mở tập tin bản vá: %s"
msgid "need exactly one range"
msgstr "cần chính xác một vùng"
@@ -7351,8 +7469,12 @@ msgstr "cần chính xác một vùng"
msgid "not a range"
msgstr "không phải là một vùng"
+#, c-format
+msgid "unable to read branch description file '%s'"
+msgstr "không thể Ä‘á»c tập tin cấu hình nhánh '%s'"
+
msgid "cover letter needs email format"
-msgstr "“cover letter†cần cho định dạng thư"
+msgstr "cover letter cần định dạng thư"
msgid "failed to create cover-letter file"
msgstr "gặp lỗi khi tạo các tập tin cover-letter"
@@ -7373,10 +7495,10 @@ msgstr "không hiểu lần chuyển giao %s"
#, c-format
msgid "failed to resolve '%s' as a valid ref"
-msgstr "gặp lỗi khi phân giải “%s†như là một tham chiếu hợp lệ"
+msgstr "gặp lỗi khi phân giải '%s' thành một tham chiếu hợp lệ"
msgid "could not find exact merge base"
-msgstr "không tìm thấy ná»n hòa trá»™n chính xác"
+msgstr "không tìm thấy gốc hòa trộn chính xác"
msgid ""
"failed to get upstream, if you want to record base commit automatically,\n"
@@ -7389,7 +7511,7 @@ msgstr ""
"\"--base=<base-commit-id>\" một cách thủ công"
msgid "failed to find exact merge base"
-msgstr "gặp lá»—i khi tìm ná»n hòa trá»™n chính xác"
+msgstr "gặp lỗi khi tìm gốc hòa trộn chính xác"
msgid "base commit should be the ancestor of revision list"
msgstr "lần chuyển giao ná»n không là tổ tiên của danh sách Ä‘iểm xét duyệt"
@@ -7398,7 +7520,7 @@ msgid "base commit shouldn't be in revision list"
msgstr "lần chuyển giao ná»n không được trong danh sách Ä‘iểm xét duyệt"
msgid "cannot get patch id"
-msgstr "không thể lấy mã miếng vá"
+msgstr "không thể lấy mã bản vá"
msgid "failed to infer range-diff origin of current series"
msgstr ""
@@ -7406,70 +7528,73 @@ msgstr ""
#, c-format
msgid "using '%s' as range-diff origin of current series"
-msgstr "dùng “%s†như là gốc range-diff của sê-ri hiện tại"
+msgstr "dùng '%s' làm gốc range-diff của sê-ri hiện tại"
msgid "use [PATCH n/m] even with a single patch"
-msgstr "dùng [PATCH n/m] ngay cả với miếng vá đơn"
+msgstr "dùng [PATCH n/m] ngay cả với bản vá đơn"
msgid "use [PATCH] even with multiple patches"
-msgstr "dùng [VÃ] ngay cả vá»›i các miếng vá phức tạp"
+msgstr "dùng [PATCH] ngay cả vá»›i các bản vá nhiá»u phần"
msgid "print patches to standard out"
-msgstr "hiển thị miếng vá ra đầu ra chuẩn"
+msgstr "hiển thị bản vá ra stdout"
msgid "generate a cover letter"
msgstr "tạo bì thư"
msgid "use simple number sequence for output file names"
-msgstr "sử dụng chỗi dãy số dạng đơn giản cho tên tập-tin xuất ra"
+msgstr "sử dụng chuỗi dãy số dạng đơn giản cho tên tập-tin xuất ra"
msgid "sfx"
-msgstr "sfx"
+msgstr "hậu-tố"
msgid "use <sfx> instead of '.patch'"
-msgstr "sá»­ dụng <sfx> thay cho “.patchâ€"
+msgstr "sử dụng <hậu-tố> thay cho '.patch'"
msgid "start numbering patches at <n> instead of 1"
-msgstr "bắt đầu đánh số miếng vá từ <n> thay vì 1"
+msgstr "bắt đầu đánh số bản vá từ <n> thay vì 1"
msgid "reroll-count"
-msgstr "đếm reroll"
+msgstr "số-lần-chạy-lại"
msgid "mark the series as Nth re-roll"
-msgstr "đánh dấu chuỗi nối tiếp dạng thứ-N re-roll"
+msgstr "đánh dấu chuỗi là lần chạy lại thứ N"
msgid "max length of output filename"
msgstr "chiá»u dài tên tập tin đầu ra tối Ä‘a"
msgid "use [RFC PATCH] instead of [PATCH]"
-msgstr "dùng [Và RFC] thay cho [VÃ]"
+msgstr "dùng [RFC PATCH] thay cho [PATCH]"
msgid "cover-from-description-mode"
msgstr "cover-from-description-mode"
msgid "generate parts of a cover letter based on a branch's description"
-msgstr "tạo ra các phần của một lá thư bao gồm dựa trên mô tả của nhánh"
+msgstr "tạo ra phần bìa thư dựa trên mô tả của nhánh"
+
+msgid "use branch description from file"
+msgstr "dùng mô tả nhánh từ tập tin"
msgid "use [<prefix>] instead of [PATCH]"
-msgstr "dùng [<tiá»n-tố>] thay cho [VÃ]"
+msgstr "dùng [<tiá»n-tố>] thay cho [PATCH]"
msgid "store resulting files in <dir>"
-msgstr "lưu các tập tin kết quả trong <t.mục>"
+msgstr "lưu các tập tin kết quả trong <thư mục>"
msgid "don't strip/add [PATCH]"
-msgstr "không strip/add [VÃ]"
+msgstr "không loại bá»/thêm [PATCH]"
msgid "don't output binary diffs"
-msgstr "không kết xuất diff (những khác biệt) nhị phân"
+msgstr "không kết xuất diff nhị phân"
msgid "output all-zero hash in From header"
msgstr "xuất má»i mã băm all-zero trong phần đầu From"
msgid "don't include a patch matching a commit upstream"
-msgstr "không bao gồm miếng vá khớp với một lần chuyển giao thượng nguồn"
+msgstr "không bao gồm bản vá khớp với một lần chuyển giao thượng nguồn"
msgid "show patch format instead of default (patch + stat)"
-msgstr "hiển thị định dạng miếng vá thay vì mặc định (miếng vá + thống kê)"
+msgstr "hiển thị định dạng bản vá thay vì mặc định (bản vá + thống kê)"
msgid "Messaging"
msgstr "Lá»i nhắn"
@@ -7490,11 +7615,10 @@ msgid "add Cc: header"
msgstr "thêm Cc: đầu đỠthư"
msgid "ident"
-msgstr "thụt lá»"
+msgstr "ident"
msgid "set From address to <ident> (or committer ident if absent)"
-msgstr ""
-"đặt “Äịa chỉ gá»­i†thành <thụ lá»> (hoặc thụt lá» ngÆ°á»i commit nếu bá» quên)"
+msgstr "đặt 'Äịa chỉ gá»­i' thành <ident> (hoặc ngÆ°á»i commit nếu bá» quên)"
msgid "message-id"
msgstr "message-id"
@@ -7506,13 +7630,13 @@ msgid "boundary"
msgstr "ranh giá»›i"
msgid "attach the patch"
-msgstr "đính kèm miếng vá"
+msgstr "đính kèm bản vá"
msgid "inline the patch"
-msgstr "dùng miếng vá làm nội dung"
+msgstr "dùng bản vá làm nội dung"
msgid "enable message threading, styles: shallow, deep"
-msgstr "cho phép luồng lá»i nhắn, kiểu: “shallowâ€, “deepâ€"
+msgstr "cho phép luồng lá»i nhắn, kiểu: 'shallow', 'deep'"
msgid "signature"
msgstr "chữ ký"
@@ -7524,28 +7648,31 @@ msgid "base-commit"
msgstr "lần_chuyển_giao_ná»n"
msgid "add prerequisite tree info to the patch series"
-msgstr "add trÆ°á»›c hết đòi há»i thông tin cây tá»›i sê-ri miếng vá"
+msgstr "add trÆ°á»›c hết đòi há»i thông tin cây tá»›i sê-ri bản vá"
msgid "add a signature from a file"
msgstr "thêm chữ ký từ một tập tin"
msgid "don't print the patch filenames"
-msgstr "không hiển thị các tên tập tin của miếng vá"
+msgstr "không hiển thị các tên tập tin của bản vá"
msgid "show progress while generating patches"
-msgstr "hiển thị bộ đo tiến triển trong khi tạo các miếng vá"
+msgstr "hiển thị bộ đo tiến triển trong khi tạo các bản vá"
msgid "show changes against <rev> in cover letter or single patch"
msgstr ""
-"hiển thị các thay đổi dá»±a trên <rev> trong các chữ bao bá»c hoặc miếng vá Ä‘Æ¡n"
+"hiển thị các thay đổi dá»±a trên <rev> trong các chữ bao bá»c hoặc bản vá Ä‘Æ¡n"
msgid "show changes against <refspec> in cover letter or single patch"
msgstr ""
-"hiển thị các thay đổi dá»±a trên <refspec> trong các chữ bao bá»c hoặc miếng vá "
+"hiển thị các thay đổi dá»±a trên <refspec> trong các chữ bao bá»c hoặc bản vá "
"Ä‘Æ¡n"
msgid "percentage by which creation is weighted"
-msgstr "tỷ lệ phần trăm theo cái tạo là weighted"
+msgstr "tỉ lệ phần trăm theo cái tạo là weighted"
+
+msgid "show in-body From: even if identical to the e-mail header"
+msgstr "hiện mục From: trong phần thân kể cả khi giống với phần tiêu đỠe-mail"
#, c-format
msgid "invalid ident line: %s"
@@ -7565,7 +7692,7 @@ msgstr "--remerge-diff không hợp lý"
#, c-format
msgid "could not create directory '%s'"
-msgstr "không thể tạo thÆ° mục “%sâ€"
+msgstr "không thể tạo thư mục '%s'"
msgid "--interdiff requires --cover-letter or single patch"
msgstr "--interdiff cần --cover-letter hoặc vá đơn"
@@ -7578,7 +7705,7 @@ msgid "Interdiff against v%d:"
msgstr "Interdiff dựa trên v%d:"
msgid "--range-diff requires --cover-letter or single patch"
-msgstr "--range-diff yêu cầu --cover-letter hoặc miếng vá đơn"
+msgstr "--range-diff yêu cầu --cover-letter hoặc bản vá đơn"
msgid "Range-diff:"
msgstr "Range-diff:"
@@ -7589,10 +7716,10 @@ msgstr "Range-diff dựa trên v%d:"
#, c-format
msgid "unable to read signature file '%s'"
-msgstr "không thể Ä‘á»c tập tin chữ ký “%sâ€"
+msgstr "không thể Ä‘á»c tập tin chữ ký '%s'"
msgid "Generating patches"
-msgstr "Äang tạo các miếng vá"
+msgstr "Äang tạo các bản vá"
msgid "failed to create output files"
msgstr "gặp lỗi khi tạo các tập tin kết xuất"
@@ -7607,8 +7734,12 @@ msgstr ""
"Không tìm thấy nhánh mạng được theo dõi, hãy chỉ định <thượng-nguồn> một "
"cách thủ công.\n"
+#, c-format
+msgid "could not get object info about '%s'"
+msgstr "không thể lấy thông tin đối tượng vỠ'%s'"
+
msgid "git ls-files [<options>] [<file>...]"
-msgstr "git ls-files [<các tùy chá»n>] [<tập-tin>…]"
+msgstr "git ls-files [<các tùy chá»n>] [<tập-tin>...]"
msgid "separate paths with the NUL character"
msgstr "các Ä‘Æ°á»ng dẫn được ngăn cách bởi ký tá»± NULL"
@@ -7618,11 +7749,11 @@ msgstr "nhận dạng các trạng thái tập tin với thẻ"
msgid "use lowercase letters for 'assume unchanged' files"
msgstr ""
-"dùng chữ cái viết thÆ°á»ng cho các tập tin “assume unchanged†(giả định không "
+"dùng chữ cái viết thÆ°á»ng cho các tập tin 'assume unchanged' (giả định không "
"thay đổi)"
msgid "use lowercase letters for 'fsmonitor clean' files"
-msgstr "dùng chữ cái viết thÆ°á»ng cho các tập tin “fsmonitor cleanâ€"
+msgstr "dùng chữ cái viết thÆ°á»ng cho các tập tin 'fsmonitor clean'"
msgid "show cached files in the output (default)"
msgstr "hiển thị các tập tin được nhớ tạm vào đầu ra (mặc định)"
@@ -7646,7 +7777,7 @@ msgid "show files on the filesystem that need to be removed"
msgstr "hiển thị các tập tin trên hệ thống tập tin mà nó cần được gỡ bá»"
msgid "show 'other' directories' names only"
-msgstr "chỉ hiển thị tên của các thÆ° mục “khácâ€"
+msgstr "chỉ hiển thị tên của các thư mục 'khác'"
msgid "show line endings of files"
msgstr "hiển thị kết thúc dòng của các tập tin"
@@ -7676,7 +7807,7 @@ msgid "make the output relative to the project top directory"
msgstr "làm cho kết xuất liên quan đến thư mục ở mức cao nhất (gốc) của dự án"
msgid "if any <file> is not in the index, treat this as an error"
-msgstr "nếu <tập tin> bất kỳ không ở trong bảng mục lục, xử lý nó như một lỗi"
+msgstr "nếu <tập tin> bất kỳ không ở trong chỉ mục, xử lý nó như một lỗi"
msgid "tree-ish"
msgstr "tree-ish"
@@ -7692,16 +7823,23 @@ msgid "suppress duplicate entries"
msgstr "chặn các mục tin trùng lặp"
msgid "show sparse directories in the presence of a sparse index"
-msgstr "hiển thị thư mục \"sparse\" trong sự có mặt của mục lục \"sparse\""
+msgstr "hiển thị thư mục thưa trong sự có mặt của chỉ mục thưa"
+
+msgid ""
+"--format cannot be used with -s, -o, -k, -t, --resolve-undo, --deduplicate, "
+"--eol"
+msgstr ""
+"--format không thể được dùng với -s, -o, -k, -t, --resolve-undo,--"
+"deduplicate, --eol"
msgid ""
"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
-" [-q | --quiet] [--exit-code] [--get-url]\n"
-" [--symref] [<repository> [<refs>...]]"
+" [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n"
+" [--symref] [<repository> [<patterns>...]]"
msgstr ""
"git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
-" [-q | --quiet] [--exit-code] [--get-url]\n"
-" [--symref] [<kho> [<các tham chiếu>…]]"
+" [-q | --quiet] [--exit-code] [--get-url] [--sort=<key>]\n"
+" [--symref] [<kho> [<mẫu>...]]"
msgid "do not print remote URL"
msgstr "không hiển thị URL máy chủ"
@@ -7731,23 +7869,7 @@ msgid "show underlying ref in addition to the object pointed by it"
msgstr "hiển thị tham chiếu nằm dưới để thêm vào đối tượng được chỉ bởi nó"
msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
-msgstr "git ls-tree [<các tùy chá»n>] <tree-ish> [</Ä‘Æ°á»ng/dẫn>…]"
-
-#, c-format
-msgid "could not get object info about '%s'"
-msgstr "không thể lấy thông tin đối tượng vỠ“%sâ€"
-
-#, c-format
-msgid "bad ls-tree format: element '%s' does not start with '('"
-msgstr "định dạng ls-tree sai: phần tá»­ “%s†không bắt đầu bằng “(â€"
-
-#, c-format
-msgid "bad ls-tree format: element '%s' does not end in ')'"
-msgstr "định dạng ls-tree sai: phần tá»­ “%s†không bắt kết thúc bằng “)â€"
-
-#, c-format
-msgid "bad ls-tree format: %%%.*s"
-msgstr "định dạng ls-tree sai: %%%.*s"
+msgstr "git ls-tree [<các tùy chá»n>] <tree-ish> [</Ä‘Æ°á»ng/dẫn>...]"
msgid "only show trees"
msgstr "chỉ hiển thị các tree"
@@ -7759,7 +7881,7 @@ msgid "show trees when recursing"
msgstr "hiển thị cây khi đệ quy"
msgid "terminate entries with NUL byte"
-msgstr "chấm dứt mục tin với byte NUL"
+msgstr "kết thúc mục tin với byte NUL"
msgid "include object size"
msgstr "gồm cả kích thước đối tượng"
@@ -7818,38 +7940,38 @@ msgid "use headers in message's body"
msgstr "sử dụng phần đầu trong nội dung thư"
msgid "reading patches from stdin/tty..."
-msgstr "Ä‘á»c các miếng vá từ đầu vào tiêu chuẩn stdin/tty..."
+msgstr "Ä‘á»c các bản vá từ stdin/tty..."
#, c-format
msgid "empty mbox: '%s'"
-msgstr "mbox trống rá»—ng: “%sâ€"
+msgstr "mbox trống rỗng: '%s'"
msgid "git merge-base [-a | --all] <commit> <commit>..."
-msgstr "git merge-base [-a | --all] <lần_chuyển_giao> <lần_chuyển_giao>…"
+msgstr "git merge-base [-a | --all] <lần_chuyển_giao> <lần_chuyển_giao>..."
msgid "git merge-base [-a | --all] --octopus <commit>..."
-msgstr "git merge-base [-a | --all] --octopus <lần_chuyển_giao>…"
-
-msgid "git merge-base --independent <commit>..."
-msgstr "git merge-base --independent <lần_chuyển_giao>…"
+msgstr "git merge-base [-a | --all] --octopus <lần_chuyển_giao>..."
msgid "git merge-base --is-ancestor <commit> <commit>"
msgstr "git merge-base --is-ancestor <commit> <lần_chuyển_giao>"
+msgid "git merge-base --independent <commit>..."
+msgstr "git merge-base --independent <lần_chuyển_giao>..."
+
msgid "git merge-base --fork-point <ref> [<commit>]"
msgstr "git merge-base --fork-point <tham-chiếu> [<lần_chuyển_giao>]"
msgid "output all common ancestors"
-msgstr "xuất ra tất cả các ông bà, tổ tiên chung"
+msgstr "xuất ra tất cả các ông bà tổ tiên chung"
msgid "find ancestors for a single n-way merge"
msgstr "tìm tổ tiên của hòa trộn n-way đơn"
msgid "list revs not reachable from others"
-msgstr "liệt kê các “rev†mà nó không thể Ä‘á»c được từ cái khác"
+msgstr "liệt kê các 'rev' không thể tới được từ cái còn lại"
msgid "is the first one ancestor of the other?"
-msgstr "là cha mẹ đầu tiên của cái khác?"
+msgstr "có phải cái trước là tổ tiên của cái sau?"
msgid "find where <commit> forked from reflog of <ref>"
msgstr "tìm xem <commit> được rẽ nhánh ở đâu từ reflog của <th.chiếu>"
@@ -7861,8 +7983,18 @@ msgstr ""
"git merge-file [<các tùy chá»n>] [-L <tên1> [-L <gốc> [-L <tên2>]]] <tập-"
"tin1> <tập-tin-gốc> <tập-tin2>"
+msgid ""
+"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
+"\"histogram\""
+msgstr ""
+"tùy chá»n diff-algorithm chấp nhận \"myers\", \"minimal\", \"patience\" và "
+"\"histogram\""
+
msgid "send results to standard output"
-msgstr "gửi kết quả vào đầu ra tiêu chuẩn"
+msgstr "gửi kết quả ra stdout"
+
+msgid "use object IDs instead of filenames"
+msgstr "dùng ID đối tượng thay vì tên tập tin"
msgid "use a diff3 based merge"
msgstr "dùng kiểu hòa dựa trên diff3"
@@ -7871,16 +8003,22 @@ msgid "use a zealous diff3 based merge"
msgstr "dùng kiểu hòa trộn dựa trên 'zealous diff3'"
msgid "for conflicts, use our version"
-msgstr "để tránh xung đột, sử dụng phiên bản của chúng ta"
+msgstr "nếu xung đột, sử dụng phiên bản của ta"
msgid "for conflicts, use their version"
-msgstr "để tránh xung Ä‘á»™t, sá»­ dụng phiên bản của há»"
+msgstr "nếu xung Ä‘á»™t, sá»­ dụng phiên bản của há»"
msgid "for conflicts, use a union version"
-msgstr "để tránh xung đột, sử dụng phiên bản kết hợp"
+msgstr "nếu xung đột, sử dụng phiên bản kết hợp"
+
+msgid "<algorithm>"
+msgstr "<thuật toán>"
+
+msgid "choose a diff algorithm"
+msgstr "chá»n thuật toán diff"
msgid "for conflicts, use this marker size"
-msgstr "để tránh xung đột, hãy sử dụng kích thước bộ tạo này"
+msgstr "nếu xung đột, hãy sử dụng kích thước bộ tạo này"
msgid "do not warn about conflicts"
msgstr "không cảnh báo vỠcác xung đột xảy ra"
@@ -7889,12 +8027,19 @@ msgid "set labels for file1/orig-file/file2"
msgstr "đặt nhãn cho tập-tin-1/tập-tin-gốc/tập-tin-2"
#, c-format
+msgid "object '%s' does not exist"
+msgstr "đối tượng '%s' không tồn tại"
+
+msgid "Could not write object file"
+msgstr "Không thể ghi vào tập tin"
+
+#, c-format
msgid "unknown option %s"
msgstr "không hiểu tùy chá»n %s"
#, c-format
msgid "could not parse object '%s'"
-msgstr "không thể phân tích đối tượng “%sâ€"
+msgstr "không thể Ä‘á»c đối tượng '%s'"
#, c-format
msgid "cannot handle more than %d base. Ignoring %s."
@@ -7912,33 +8057,94 @@ msgstr "không thể phân giải tham chiếu %s"
msgid "Merging %s with %s\n"
msgstr "Äang hòa trá»™n %s vá»›i %s\n"
+#, c-format
+msgid "could not parse as tree '%s'"
+msgstr "không hiểu cú pháp cây '%s'"
+
+msgid "not something we can merge"
+msgstr "không phải là thứ gì đó mà chúng tôi có thể hòa trộn"
+
+msgid "refusing to merge unrelated histories"
+msgstr "từ chối hòa trộn lịch sử không liên quan"
+
+msgid "failure to merge"
+msgstr "gặp lỗi khi hoà trộn"
+
+msgid "git merge-tree [--write-tree] [<options>] <branch1> <branch2>"
+msgstr "git merge-tree [--write-tree] [<tuỳ chá»n>] <nhánh 1> <nhánh 2>"
+
+msgid "git merge-tree [--trivial-merge] <base-tree> <branch1> <branch2>"
+msgstr "git merge-tree [--trivial-merge] <cây gốc> <nhánh 1> <nhánh 2>"
+
+msgid "do a real merge instead of a trivial merge"
+msgstr "hoà trộn đúng chuẩn thay vì đơn giản"
+
+msgid "do a trivial merge only"
+msgstr "chỉ hoà trộn đơn giản"
+
+msgid "also show informational/conflict messages"
+msgstr "hiển thị thông báo chú thích/xung đột"
+
+msgid "list filenames without modes/oids/stages"
+msgstr "liệt kê tên tập tin không kèm chế độ/oid/stage"
+
+msgid "allow merging unrelated histories"
+msgstr "cho phép hòa trộn lịch sử không liên quan"
+
+msgid "perform multiple merges, one per line of input"
+msgstr "thá»±c hiện hoà trá»™n nhiá»u lần, vá»›i từng dòng đầu vào"
+
+msgid "specify a merge-base for the merge"
+msgstr "chỉ định gốc hoà trộn để hòa trộn"
+
+msgid "option=value"
+msgstr "tùy_chá»n=giá_trị"
+
+msgid "option for selected merge strategy"
+msgstr "tùy chá»n cho chiến lược hòa trá»™n đã chá»n"
+
+msgid "--trivial-merge is incompatible with all other options"
+msgstr "--trivial-merge không tÆ°Æ¡ng thích vá»›i các tùy chá»n khác"
+
+#, c-format
+msgid "unknown strategy option: -X%s"
+msgstr "không hiểu chiến lược: -X%s"
+
+#, c-format
+msgid "malformed input line: '%s'."
+msgstr "dòng đầu vào sai quy cách: '%s'."
+
+#, c-format
+msgid "merging cannot continue; got unclean result of %d"
+msgstr "không thể tiếp tục hoà trộn; kết quả không hoàn toàn %d"
+
msgid "git merge [<options>] [<commit>...]"
-msgstr "git merge [<các tùy chá»n>] [<commit>…]"
+msgstr "git merge [<các tùy chá»n>] [<commit>...]"
msgid "switch `m' requires a value"
-msgstr "switch “m†yêu cầu một giá trị"
+msgstr "tuỳ chá»n 'm' yêu cầu má»™t giá trị"
#, c-format
msgid "option `%s' requires a value"
-msgstr "tùy chá»n “%s†yêu cầu má»™t giá trị"
+msgstr "tùy chá»n '%s' yêu cầu má»™t giá trị"
#, c-format
msgid "Could not find merge strategy '%s'.\n"
-msgstr "Không tìm thấy chiến lược hòa trá»™n “%sâ€.\n"
+msgstr "Không tìm thấy chiến lược hòa trộn '%s'.\n"
#, c-format
msgid "Available strategies are:"
-msgstr "Các chiến lược sẵn sàng là:"
+msgstr "Các chiến lược khả dụng là:"
#, c-format
msgid "Available custom strategies are:"
-msgstr "Các chiến lược tùy chỉnh sẵn sàng là:"
+msgstr "Các chiến lược tùy chỉnh khả dụng là:"
msgid "do not show a diffstat at the end of the merge"
-msgstr "không hiển thị thống kê khác biệt tại cuối của lần hòa trộn"
+msgstr "không hiển thị diffstat (thống kê khác biệt) phía dưới hòa trộn"
msgid "show a diffstat at the end of the merge"
-msgstr "hiển thị thống kê khác biệt tại cuối của hòa trộn"
+msgstr "hiển thị diffstat (thống kê khác biệt) phía dưới hòa trộn"
msgid "(synonym to --stat)"
msgstr "(đồng nghĩa với --stat)"
@@ -7947,7 +8153,7 @@ msgid "add (at most <n>) entries from shortlog to merge commit message"
msgstr "thêm (ít nhất <n>) mục từ shortlog cho ghi chú chuyển giao hòa trộn"
msgid "create a single commit instead of doing a merge"
-msgstr "tạo một lần chuyển giao đưon thay vì thực hiện việc hòa trộn"
+msgstr "tạo một lần chuyển giao đơn thay vì thực hiện việc hòa trộn"
msgid "perform a commit if the merge succeeds (default)"
msgstr "thực hiện chuyển giao nếu hòa trộn thành công (mặc định)"
@@ -7959,7 +8165,7 @@ msgid "allow fast-forward (default)"
msgstr "cho phép chuyển-tiếp-nhanh (mặc định)"
msgid "abort if fast-forward is not possible"
-msgstr "bỠqua nếu chuyển-tiếp-nhanh không thể được"
+msgstr "huỷ lệnh nếu không thể chuyển-tiếp-nhanh"
msgid "verify that the named commit has a valid GPG signature"
msgstr "thẩm tra xem lần chuyển giao có tên đó có chữ ký GPG hợp lệ hay không"
@@ -7970,12 +8176,6 @@ msgstr "chiến lược"
msgid "merge strategy to use"
msgstr "chiến lược hòa trộn sẽ dùng"
-msgid "option=value"
-msgstr "tùy_chá»n=giá_trị"
-
-msgid "option for selected merge strategy"
-msgstr "tùy chá»n cho chiến lược hòa trá»™n đã chá»n"
-
msgid "merge commit message (for a non-fast-forward merge)"
msgstr ""
"hòa trộn ghi chú của lần chuyển giao (dành cho hòa trộn không-chuyển-tiếp-"
@@ -7985,17 +8185,14 @@ msgid "use <name> instead of the real target"
msgstr "dùng <tên> thay cho đích thật"
msgid "abort the current in-progress merge"
-msgstr "bãi bỠquá trình hòa trộn hiện tại đang thực hiện"
+msgstr "huỷ bỠquá trình hòa trộn hiện đang thực hiện"
msgid "--abort but leave index and working tree alone"
-msgstr "--abort nhưng để lại bảng mục lục và cây làm việc"
+msgstr "--abort nhưng để lại chỉ mục và cây làm việc"
msgid "continue the current in-progress merge"
msgstr "tiếp tục quá trình hòa trộn hiện tại đang thực hiện"
-msgid "allow merging unrelated histories"
-msgstr "cho phép hòa trộn lịch sử không liên quan"
-
msgid "bypass pre-merge-commit and commit-msg hooks"
msgstr "vòng qua móc (hook) pre-merge-commit và commit-msg"
@@ -8028,34 +8225,30 @@ msgstr "Không có lá»i chú thích hòa trá»™n -- nên không cập nhật HEA
#, c-format
msgid "'%s' does not point to a commit"
-msgstr "“%s†không chỉ đến một lần chuyển giao nào cả"
+msgstr "'%s' không chỉ đến một lần chuyển giao nào cả"
#, c-format
msgid "Bad branch.%s.mergeoptions string: %s"
msgstr "Chuá»—i branch.%s.mergeoptions sai: %s"
msgid "Unable to write index."
-msgstr "Không thể ghi bảng mục lục."
+msgstr "Không thể ghi chỉ mục."
msgid "Not handling anything other than two heads merge."
msgstr "Không cầm nắm gì ngoài hai head hòa trộn."
#, c-format
-msgid "unknown strategy option: -X%s"
-msgstr "không hiểu chiến lược: -X%s"
-
-#, c-format
msgid "unable to write %s"
msgstr "không thể ghi %s"
#, c-format
msgid "Could not read from '%s'"
-msgstr "Không thể Ä‘á»c từ “%sâ€"
+msgstr "Không thể Ä‘á»c từ '%s'"
#, c-format
msgid "Not committing merge; use 'git commit' to complete the merge.\n"
msgstr ""
-"Vẫn chưa hòa trộn các lần chuyển giao; sử dụng lệnh “git commit†để hoàn tất "
+"Vẫn chưa hòa trộn các lần chuyển giao; sử dụng lệnh 'git commit' để hoàn tất "
"việc hòa trộn.\n"
msgid ""
@@ -8074,10 +8267,10 @@ msgstr "Nếu phần chú thích rỗng sẽ hủy bỠlần chuyển giao.\n"
#, c-format
msgid ""
-"Lines starting with '%c' will be ignored, and an empty message aborts\n"
+"Lines starting with '%s' will be ignored, and an empty message aborts\n"
"the commit.\n"
msgstr ""
-"Những dòng được bắt đầu bằng “%c†sẽ được bỠqua, và nếu phần chú\n"
+"Những dòng được bắt đầu bằng '%s' sẽ được bỠqua, và nếu phần chú\n"
"thích rỗng sẽ hủy bỠlần chuyển giao.\n"
msgid "Empty commit message."
@@ -8108,19 +8301,16 @@ msgstr "Không nhánh mạng theo dõi cho %s từ %s"
#, c-format
msgid "Bad value '%s' in environment '%s'"
-msgstr "Giá trị sai “%s†trong biến môi trÆ°á»ng “%sâ€"
+msgstr "Giá trị sai '%s' trong biến môi trÆ°á»ng '%s'"
#, c-format
msgid "could not close '%s'"
-msgstr "không thể đóng “%sâ€"
+msgstr "không thể đóng '%s'"
#, c-format
msgid "not something we can merge in %s: %s"
msgstr "không phải là một thứ gì đó mà chúng tôi có thể hòa trộn trong %s: %s"
-msgid "not something we can merge"
-msgstr "không phải là thứ gì đó mà chúng tôi có thể hòa trộn"
-
msgid "--abort expects no arguments"
msgstr "--abort không nhận các đối số"
@@ -8172,16 +8362,22 @@ msgid "Can merge only exactly one commit into empty head"
msgstr ""
"Không thể hòa trộn một cách đúng đắn một lần chuyển giao vào một head rỗng"
-msgid "refusing to merge unrelated histories"
-msgstr "từ chối hòa trộn lịch sử không liên quan"
-
#, c-format
msgid "Updating %s..%s\n"
msgstr "Äang cập nhật %s..%s\n"
#, c-format
+msgid ""
+"Your local changes to the following files would be overwritten by merge:\n"
+" %s"
+msgstr ""
+"Các thay đổi nội bộ của bạn với các tập tin sau đây sẽ bị ghi đè bởi lệnh "
+"hòa trộn:\n"
+" %s"
+
+#, c-format
msgid "Trying really trivial in-index merge...\n"
-msgstr "Äang thá»­ hòa trá»™n kiểu “trivial in-indexâ€â€¦\n"
+msgstr "Äang thá»­ hòa trá»™n kiểu 'trivial in-index'...\n"
#, c-format
msgid "Nope.\n"
@@ -8189,15 +8385,15 @@ msgstr "Không.\n"
#, c-format
msgid "Rewinding the tree to pristine...\n"
-msgstr "Äang tua lại cây thành thá»i xa xÆ°a…\n"
+msgstr "Äang tua lại cây thành thá»i xa xÆ°a...\n"
#, c-format
msgid "Trying merge strategy %s...\n"
-msgstr "Äang thá»­ chiến lược hòa trá»™n %s…\n"
+msgstr "Äang thá»­ chiến lược hòa trá»™n %s...\n"
#, c-format
msgid "No merge strategy handled the merge.\n"
-msgstr "Không có chiến lược hòa trộn nào được nắm giữ (handle) sự hòa trộn.\n"
+msgstr "Không có chiến lược hòa trộn nào có thể xử lý việc hòa trộn.\n"
#, c-format
msgid "Merge with strategy %s failed.\n"
@@ -8209,9 +8405,12 @@ msgstr "Sử dụng chiến lược %s để chuẩn bị giải quyết bằng
#, c-format
msgid "Automatic merge went well; stopped before committing as requested\n"
+msgstr "Hòa trộn tự động đã xong; dừng trước khi chuyển giao như đã yêu cầu\n"
+
+#, c-format
+msgid "When finished, apply stashed changes with `git stash pop`\n"
msgstr ""
-"Hòa trộn tự động đã trở nên tốt; bị dừng trước khi việc chuyển giao được yêu "
-"cầu\n"
+"Sau khi hoàn thành, áp dụng các thay đổi trong stash với `git stash pop` \n"
#, c-format
msgid "warning: tag input does not pass fsck: %s"
@@ -8219,11 +8418,11 @@ msgstr "cảnh báo: đầu vào thẻ không qua kiểm tra fsck: %s"
#, c-format
msgid "error: tag input does not pass fsck: %s"
-msgstr "lỗi: đầu vào thẻ không vượt qua fsck: %s"
+msgstr "lỗi: đầu vào thẻ không qua kiểm tra fsck: %s"
#, c-format
msgid "%d (FSCK_IGNORE?) should never trigger this callback"
-msgstr "%d (FSCK_IGNORE?) không bao giá» nên kích hoạt cuá»™c gá»i ngược này"
+msgstr "%d (FSCK_IGNORE?) không bao giỠnên kích hoạt callback này"
#, c-format
msgid "could not read tagged object '%s'"
@@ -8231,24 +8430,20 @@ msgstr "không thể Ä‘á»c đối tượng được đánh thẻ %s"
#, c-format
msgid "object '%s' tagged as '%s', but is a '%s' type"
-msgstr "đối tượng %s được đánh thẻ là %s, không phải là kiểu %s"
-
-msgid "could not read from stdin"
-msgstr "không thể Ä‘á»c từ đầu vào tiêu chuẩn"
+msgstr "đối tượng '%s' được đánh thẻ là '%s', nhưng là kiểu '%s'"
msgid "tag on stdin did not pass our strict fsck check"
msgstr ""
"thẻ trên stdin đã không vượt qua kiểm tra fsck nghiêm ngặt của chúng tôi"
msgid "tag on stdin did not refer to a valid object"
-msgstr ""
-"thẻ trên đầu vào tiêu chuẩn không chỉ đến một lần chuyển giao hợp lệ nào cả"
+msgstr "thẻ trên stdin không chỉ đến một đối tượng hợp lệ"
msgid "unable to write tag file"
-msgstr "không thể ghi vào tập tin lưu thẻ"
+msgstr "không thể ghi vào tập tin thẻ"
msgid "input is NUL terminated"
-msgstr "đầu vào được chấm dứt bởi NUL"
+msgstr "đầu vào được kết thúc bởi NUL"
msgid "allow missing objects"
msgstr "cho phép thiếu đối tượng"
@@ -8288,7 +8483,7 @@ msgid "write multi-pack bitmap"
msgstr "ghi multi-pack bitmap"
msgid "write multi-pack index containing only given indexes"
-msgstr "ghi mục lục multi-pack chỉ chứa các mục lục đã cho"
+msgstr "ghi chỉ mục multi-pack chỉ chứa các chỉ mục đã cho"
msgid "refs snapshot for selecting bitmap commits"
msgstr "ảnh chụp nhanh refs để chá»n các lần chuyển giao ánh xạ"
@@ -8301,11 +8496,11 @@ msgstr ""
"vào một bó cái mà lớn hơn kích thước này"
msgid "git mv [<options>] <source>... <destination>"
-msgstr "git mv [<các tùy chá»n>] <nguồn>… <đích>"
+msgstr "git mv [<các tùy chá»n>] <nguồn>... <đích>"
#, c-format
msgid "Directory %s is in index and no submodule?"
-msgstr "Thư mục “%s†có ở trong chỉ mục mà không có mô-đun con?"
+msgstr "Thư mục '%s' có ở trong chỉ mục mà không có mô-đun con?"
msgid "Please stage your changes to .gitmodules or stash them to proceed"
msgstr ""
@@ -8313,7 +8508,7 @@ msgstr ""
#, c-format
msgid "%.*s is in index"
-msgstr "%.*s trong bảng mục lục"
+msgstr "%.*s trong chỉ mục"
msgid "force move/rename even if target exists"
msgstr "ép buộc di chuyển hay đổi tên thậm chí cả khi đích đã tồn tại"
@@ -8323,20 +8518,23 @@ msgstr "bỠqua các lỗi liên quan đến di chuyển, đổi tên"
#, c-format
msgid "destination '%s' is not a directory"
-msgstr "có đích “%s†nhưng đây không phải là một thư mục"
+msgstr "có đích '%s' nhưng đây không phải là một thư mục"
#, c-format
msgid "Checking rename of '%s' to '%s'\n"
-msgstr "Äang kiểm tra việc đổi tên của “%s†thành “%sâ€\n"
+msgstr "Äang kiểm tra việc đổi tên của '%s' thành '%s'\n"
msgid "bad source"
msgstr "nguồn sai"
+msgid "destination exists"
+msgstr "đích đã tồn tại sẵn rồi"
+
msgid "can not move directory into itself"
msgstr "không thể di chuyển một thư mục vào trong chính nó được"
-msgid "cannot move directory over file"
-msgstr "không di chuyển được thư mục thông qua tập tin"
+msgid "destination already exists"
+msgstr "đích đã tồn tại sẵn rồi"
msgid "source directory is empty"
msgstr "thư mục nguồn là trống rỗng"
@@ -8347,12 +8545,9 @@ msgstr "không nằm dưới sự quản lý mã nguồn"
msgid "conflicted"
msgstr "bị xung đột"
-msgid "destination exists"
-msgstr "đích đã tồn tại sẵn rồi"
-
#, c-format
msgid "overwriting '%s'"
-msgstr "Ä‘ang ghi đè lên “%sâ€"
+msgstr "đang ghi đè lên '%s'"
msgid "Cannot overwrite"
msgstr "Không thể ghi đè"
@@ -8363,6 +8558,9 @@ msgstr "nhiá»u nguồn cho cùng má»™t đích"
msgid "destination directory does not exist"
msgstr "thư mục đích không tồn tại"
+msgid "destination exists in the index"
+msgstr "đích đã tồn tại sẵn trong chỉ mục"
+
#, c-format
msgid "%s, source=%s, destination=%s"
msgstr "%s, nguồn=%s, đích=%s"
@@ -8373,10 +8571,10 @@ msgstr "Äổi tên %s thành %s\n"
#, c-format
msgid "renaming '%s' failed"
-msgstr "gặp lá»—i khi đổi tên “%sâ€"
+msgstr "gặp lỗi khi đổi tên '%s'"
msgid "git name-rev [<options>] <commit>..."
-msgstr "git name-rev [<các tùy chá»n>] <commit>…"
+msgstr "git name-rev [<các tùy chá»n>] <commit>..."
msgid "git name-rev [<options>] --all"
msgstr "git name-rev [<các tùy chá»n>] --all"
@@ -8404,33 +8602,37 @@ msgid "deprecated: use --annotate-stdin instead"
msgstr "đã lạc hậu: hãy dùng --annotate-stdin để thay thế"
msgid "annotate text from stdin"
-msgstr "chú giải chữ từ đầu vào tiêu chuẩn stdin"
+msgstr "chú giải chữ từ stdin"
msgid "allow to print `undefined` names (default)"
-msgstr "cho phép in các tên “chưa định nghĩa†(mặc định)"
+msgstr "cho phép in các tên `chưa định nghĩa` (mặc định)"
msgid "dereference tags in the input (internal use)"
-msgstr "bãi bỠtham chiếu các thẻ trong đầu vào (dùng nội bộ)"
+msgstr "giải tham chiếu các thẻ trong đầu vào (dùng nội bộ)"
msgid "git notes [--ref <notes-ref>] [list [<object>]]"
msgstr "git notes [--ref <notes-ref>] [list [<đối-tượng>]]"
msgid ""
-"git notes [--ref <notes-ref>] add [-f] [--allow-empty] [-m <msg> | -F <file> "
-"| (-c | -C) <object>] [<object>]"
+"git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--[no-]separator|--"
+"separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c "
+"| -C) <object>] [<object>]"
msgstr ""
-"git notes [--ref <notes-ref>] add [-f] [--allow-empty] [-m <lá»i-nhắn> | -F "
-"<tập-tin> | (-c | -C) <đối-tượng>] [<đối-tượng>]"
+"git notes [--ref <notes-ref>] add [-f] [--allow-empty] [--[no-]separator|--"
+"separator=<paragraph-break>] [--[no-]stripspace] [-m <lá»i-nhắn> | -F <tập-"
+"tin> | (-c | -C) <đối-tượng>] [<đối-tượng>]"
msgid "git notes [--ref <notes-ref>] copy [-f] <from-object> <to-object>"
msgstr "git notes [--ref <notes-ref>] copy [-f] <từ-đối-tượng> <đến-đối-tượng>"
msgid ""
-"git notes [--ref <notes-ref>] append [--allow-empty] [-m <msg> | -F <file> | "
-"(-c | -C) <object>] [<object>]"
+"git notes [--ref <notes-ref>] append [--allow-empty] [--[no-]separator|--"
+"separator=<paragraph-break>] [--[no-]stripspace] [-m <msg> | -F <file> | (-c "
+"| -C) <object>] [<object>]"
msgstr ""
-"git notes [--ref <notes-ref>] append [--allow-empty] [-m <lá»i-nhắn> | -F "
-"<tập-tin> | (-c | -C) <đối-tượng>] [<đối-tượng>]"
+"git notes [--ref <notes-ref>] append [--allow-empty] [--[no-]separator|--"
+"separator=<paragraph-break>] [--[no-]stripspace] [-m <lá»i-nhắn> | -F <tập-"
+"tin> | (-c | -C) <đối-tượng>] [<đối-tượng>]"
msgid "git notes [--ref <notes-ref>] edit [--allow-empty] [<object>]"
msgstr "git notes [--ref <notes-ref>] edit [--allow-empty] [<đối-tượng>]"
@@ -8444,7 +8646,7 @@ msgstr ""
"git notes [--ref <notes-ref>] merge [-v | -q] [-s <chiến-lược> ] <notes-ref>"
msgid "git notes [--ref <notes-ref>] remove [<object>...]"
-msgstr "git notes [--ref <notes-ref>] remove [<đối-tượng>…]"
+msgstr "git notes [--ref <notes-ref>] remove [<đối-tượng>...]"
msgid "git notes [--ref <notes-ref>] prune [-n] [-v]"
msgstr "git notes [--ref <notes-ref>] prune [-n] [-v]"
@@ -8462,7 +8664,7 @@ msgid "git notes copy [<options>] <from-object> <to-object>"
msgstr "git notes copy [<các tùy chá»n>] <từ-đối-tượng> <đến-đối-tượng>"
msgid "git notes copy --stdin [<from-object> <to-object>]..."
-msgstr "git notes copy --stdin [<từ-đối-tượng> <đến-đối-tượng>]…"
+msgstr "git notes copy --stdin [<từ-đối-tượng> <đến-đối-tượng>]..."
msgid "git notes append [<options>] [<object>]"
msgstr "git notes append [<các tùy chá»n>] [<đối-tượng>]"
@@ -8491,16 +8693,12 @@ msgstr "git notes prune [<các tùy chá»n>]"
msgid "Write/edit the notes for the following object:"
msgstr "Ghi hay sửa ghi chú cho đối tượng sau đây:"
-#, c-format
-msgid "unable to start 'show' for object '%s'"
-msgstr "không thể khởi chạy “show†cho đối tượng “%sâ€"
-
msgid "could not read 'show' output"
-msgstr "không thể Ä‘á»c kết xuất “showâ€"
+msgstr "không thể Ä‘á»c kết xuất 'show'"
#, c-format
msgid "failed to finish 'show' for object '%s'"
-msgstr "gặp lá»—i khi hoàn thành “show†cho đối tượng “%sâ€"
+msgstr "gặp lỗi khi hoàn thành 'show' cho đối tượng '%s'"
msgid "please supply the note contents using either -m or -F option"
msgstr ""
@@ -8515,27 +8713,23 @@ msgstr "nội dung ghi chú còn lại %s"
#, c-format
msgid "could not open or read '%s'"
-msgstr "không thể mở hay Ä‘á»c “%sâ€"
+msgstr "không thể mở hay Ä‘á»c '%s'"
#, c-format
msgid "failed to resolve '%s' as a valid ref."
-msgstr "gặp lỗi khi phân giải “%s†như là một tham chiếu hợp lệ."
+msgstr "gặp lỗi khi phân giải '%s' thành một tham chiếu hợp lệ."
#, c-format
msgid "failed to read object '%s'."
-msgstr "gặp lá»—i khi Ä‘á»c đối tượng “%sâ€."
+msgstr "gặp lá»—i khi Ä‘á»c đối tượng '%s'."
#, c-format
msgid "cannot read note data from non-blob object '%s'."
-msgstr "không thể Ä‘á»c dữ liệu ghi chú từ đối tượng không-blob “%sâ€."
-
-#, c-format
-msgid "malformed input line: '%s'."
-msgstr "dòng đầu vào dị hình: “%sâ€."
+msgstr "không thể Ä‘á»c dữ liệu ghi chú từ đối tượng không-blob '%s'."
#, c-format
msgid "failed to copy notes from '%s' to '%s'"
-msgstr "gặp lá»—i khi sao chép ghi chú (note) từ “%s†sang “%sâ€"
+msgstr "gặp lỗi khi sao chép ghi chú (note) từ '%s' sang '%s'"
#. TRANSLATORS: the first %s will be replaced by a git
#. notes command: 'add', 'merge', 'remove', etc.
@@ -8566,13 +8760,22 @@ msgstr "cho lưu trữ ghi chú trống rỗng"
msgid "replace existing notes"
msgstr "thay thế ghi chú trước"
+msgid "<paragraph-break>"
+msgstr "<dấu ngắt đoạn>"
+
+msgid "insert <paragraph-break> between paragraphs"
+msgstr "chèn <dấu ngắt đoạn> giữa các đoạn văn"
+
+msgid "remove unnecessary whitespace"
+msgstr "Xóa bỠcác khoảng trắng không cần thiết"
+
#, c-format
msgid ""
"Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite "
"existing notes"
msgstr ""
"Không thể thêm các ghi chú. Äã tìm thấy các ghi chú đã có sẵn cho đối tượng "
-"%s. Sá»­ dụng tùy chá»n “-f†để ghi đè lên các ghi chú cÅ©"
+"%s. Sá»­ dụng tùy chá»n '-f' để ghi đè lên các ghi chú cÅ©"
#, c-format
msgid "Overwriting existing notes for object %s\n"
@@ -8583,10 +8786,10 @@ msgid "Removing note for object %s\n"
msgstr "Äang gỡ bá» ghi chú (note) cho đối tượng %s\n"
msgid "read objects from stdin"
-msgstr "Ä‘á»c các đối tượng từ đầu vào tiêu chuẩn"
+msgstr "Ä‘á»c các đối tượng từ stdin"
msgid "load rewriting config for <command> (implies --stdin)"
-msgstr "tải cấu hình chép lại cho <lệnh> (ngầm định là --stdin)"
+msgstr "tải cấu hình chép lại cho <lệnh> (ngụ ý --stdin)"
msgid "too few arguments"
msgstr "quá ít đối số"
@@ -8597,7 +8800,7 @@ msgid ""
"existing notes"
msgstr ""
"Không thể sao chép các ghi chú. Äã tìm thấy các ghi chú đã có sẵn cho đối "
-"tượng %s. Sá»­ dụng tùy chá»n “-f†để ghi đè lên các ghi chú cÅ©"
+"tượng %s. Sá»­ dụng tùy chá»n '-f' để ghi đè lên các ghi chú cÅ©"
#, c-format
msgid "missing notes on source object %s. Cannot copy."
@@ -8608,8 +8811,8 @@ msgid ""
"The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n"
"Please use 'git notes add -f -m/-F/-c/-C' instead.\n"
msgstr ""
-"Các tùy chá»n -m/-F/-c/-C đã cổ không còn dùng nữa cho lệnh con “editâ€.\n"
-"Xin hãy sá»­ dụng lệnh sau để thay thế: “git notes add -f -m/-F/-c/-Câ€.\n"
+"Các tùy chá»n -m/-F/-c/-C đã không còn dùng cho lệnh con 'edit'.\n"
+"Xin hãy sử dụng lệnh sau để thay thế: 'git notes add -f -m/-F/-c/-C'.\n"
msgid "failed to delete ref NOTES_MERGE_PARTIAL"
msgstr "gặp lỗi khi xóa tham chiếu NOTES_MERGE_PARTIAL"
@@ -8618,7 +8821,7 @@ msgid "failed to delete ref NOTES_MERGE_REF"
msgstr "gặp lỗi khi xóa tham chiếu NOTES_MERGE_REF"
msgid "failed to remove 'git notes merge' worktree"
-msgstr "gặp lá»—i khi gỡ bá» cây làm việc “git notes mergeâ€"
+msgstr "gặp lỗi khi gỡ bỠcây làm việc 'git notes merge'"
msgid "failed to read ref NOTES_MERGE_PARTIAL"
msgstr "gặp lá»—i khi Ä‘á»c tham chiếu NOTES_MERGE_PARTIAL"
@@ -8627,7 +8830,7 @@ msgid "could not find commit from NOTES_MERGE_PARTIAL."
msgstr "không thể tìm thấy lần chuyển giao từ NOTES_MERGE_PARTIAL."
msgid "could not parse commit from NOTES_MERGE_PARTIAL."
-msgstr "không thể phân tích cú pháp lần chuyển giao từ NOTES_MERGE_PARTIAL."
+msgstr "không hiểu cú pháp lần chuyển giao từ NOTES_MERGE_PARTIAL."
msgid "failed to resolve NOTES_MERGE_REF"
msgstr "gặp lỗi khi phân giải NOTES_MERGE_REF"
@@ -8649,7 +8852,7 @@ msgid ""
"resolve notes conflicts using the given strategy (manual/ours/theirs/union/"
"cat_sort_uniq)"
msgstr ""
-"phân giải các xung đột “notes†sử dụng chiến lược đã đưa ra (manual/ours/"
+"phân giải các xung đột 'notes' sử dụng chiến lược đã đưa ra (manual/ours/"
"theirs/union/cat_sort_uniq)"
msgid "Committing unmerged notes"
@@ -8691,49 +8894,48 @@ msgid ""
"abort'.\n"
msgstr ""
"Gặp lỗi khi hòa trộn các ghi chú tự động. Sửa các xung đột này trong %s và "
-"chuyển giao kết quả bằng “git notes merge --commitâ€, hoặc bãi bá» việc hòa "
-"trá»™n bằng “git notes merge --abortâ€.\n"
+"chuyển giao kết quả bằng 'git notes merge --commit', hoặc huỷ bỠviệc hòa "
+"trộn bằng 'git notes merge --abort'.\n"
#, c-format
msgid "Failed to resolve '%s' as a valid ref."
-msgstr "Gặp lỗi khi phân giải “%s†như là một tham chiếu hợp lệ."
+msgstr "Gặp lỗi khi phân giải '%s' thành một tham chiếu hợp lệ."
#, c-format
msgid "Object %s has no note\n"
msgstr "Äối tượng %s không có ghi chú (note)\n"
msgid "attempt to remove non-existent note is not an error"
-msgstr "cố gắng gỡ bỠmột note chưa từng tồn tại không phải là một lỗi"
+msgstr "việc gỡ bỠmột note không tồn tại không phải là lỗi"
msgid "read object names from the standard input"
-msgstr "Ä‘á»c tên đối tượng từ thiết bị nhập chuẩn"
+msgstr "Ä‘á»c tên đối tượng từ stdin"
msgid "do not remove, show only"
msgstr "không gỡ bá», chỉ hiển thị"
msgid "report pruned notes"
-msgstr "báo cáo các đối tượng đã prune"
+msgstr "liệt kê các đối tượng đã prune"
msgid "notes-ref"
msgstr "notes-ref"
msgid "use notes from <notes-ref>"
-msgstr "dùng “notes†từ <notes-ref>"
+msgstr "dùng 'notes' từ <notes-ref>"
#, c-format
-msgid "unknown subcommand: %s"
-msgstr "không hiểu câu lệnh con: %s"
+msgid "unknown subcommand: `%s'"
+msgstr "không hiểu câu lệnh con: `%s'"
-msgid ""
-"git pack-objects --stdout [<options>...] [< <ref-list> | < <object-list>]"
+msgid "git pack-objects --stdout [<options>] [< <ref-list> | < <object-list>]"
msgstr ""
-"git pack-objects --stdout [các tùy chá»n…] [< <danh-sách-tham-chiếu> | < "
+"git pack-objects --stdout [<các tùy chá»n>] [< <danh-sách-tham-chiếu> | < "
"<danh-sách-đối-tượng>]"
msgid ""
-"git pack-objects [<options>...] <base-name> [< <ref-list> | < <object-list>]"
+"git pack-objects [<options>] <base-name> [< <ref-list> | < <object-list>]"
msgstr ""
-"git pack-objects [các tùy chá»n…] <base-name> [< <danh-sách-ref> | < <danh-"
+"git pack-objects [<các tùy chá»n>] <base-name> [< <danh-sách-ref> | < <danh-"
"sách-đối-tượng>]"
#, c-format
@@ -8772,14 +8974,14 @@ msgstr "Äang ghi lại các đối tượng"
#, c-format
msgid "failed to stat %s"
-msgstr "gặp lỗi khi lấy thông tin thống kê vỠ%s"
+msgstr "gặp lỗi khi stat %s"
#, c-format
msgid "failed utime() on %s"
-msgstr "gặp lá»—i utime() trên “%sâ€"
+msgstr "gặp lỗi utime() trên '%s'"
msgid "failed to write bitmap index"
-msgstr "gặp lỗi khi ghi mục lục ánh xạ"
+msgstr "gặp lỗi khi ghi chỉ mục ánh xạ"
#, c-format
msgid "wrote %<PRIu32> objects while expecting %<PRIu32>"
@@ -8805,7 +9007,7 @@ msgstr "không thể lấy kích cỡ của %s"
#, c-format
msgid "unable to parse object header of %s"
-msgstr "không thể phân tích phần đầu đối tượng của “%sâ€"
+msgstr "không thể Ä‘á»c phần đầu đối tượng của '%s'"
#, c-format
msgid "object %s cannot be read"
@@ -8826,11 +9028,11 @@ msgstr "Nén delta dùng tới %d tuyến trình"
#, c-format
msgid "unable to pack objects reachable from tag %s"
-msgstr "không thể đóng gói các đối tượng tiếp cận được từ thẻ “%sâ€"
+msgstr "không thể đóng gói các đối tượng tiếp cận được từ thẻ '%s'"
#, c-format
msgid "unable to get type of object %s"
-msgstr "không thể lấy kiểu của đối tượng “%sâ€"
+msgstr "không thể lấy kiểu của đối tượng '%s'"
msgid "Compressing objects"
msgstr "Äang nén các đối tượng"
@@ -8839,27 +9041,31 @@ msgid "inconsistency with delta count"
msgstr "mâu thuẫn với số lượng delta"
#, c-format
+msgid "invalid pack.allowPackReuse value: '%s'"
+msgstr "giá trị pack.allowPackReuse không hợp lệ: '%s'"
+
+#, c-format
msgid ""
"value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-"
"hash> <uri>' (got '%s')"
msgstr ""
-"giá trị của uploadpack.blobpackfileuri phải có dạng “<object-hash> <pack-"
-"hash> <uri>†(nhận “%sâ€)"
+"giá trị của uploadpack.blobpackfileuri phải có dạng '<object-hash> <pack-"
+"hash> <uri>' (nhận '%s')"
#, c-format
msgid ""
"object already configured in another uploadpack.blobpackfileuri (got '%s')"
msgstr ""
"đối tượng đã được cấu hình trong một uploadpack.blobpackfileuri khác (đã "
-"nhận “%sâ€)"
+"nhận '%s')"
#, c-format
msgid "could not get type of object %s in pack %s"
-msgstr "không thể lấy kiểu của đối tượng “%s†trong gói “%sâ€"
+msgstr "không thể lấy kiểu của đối tượng '%s' trong gói '%s'"
#, c-format
msgid "could not find pack '%s'"
-msgstr "không thể tìm thấy gói “%sâ€"
+msgstr "không thể tìm thấy gói '%s'"
#, c-format
msgid "packfile %s cannot be accessed"
@@ -8879,7 +9085,7 @@ msgid ""
"expected edge object ID, got garbage:\n"
" %s"
msgstr ""
-"cần ID đối tượng cạnh, nhận được rác:\n"
+"cần ID đối tượng cạnh, có rác:\n"
" %s"
#, c-format
@@ -8887,14 +9093,14 @@ msgid ""
"expected object ID, got garbage:\n"
" %s"
msgstr ""
-"cần ID đối tượng, nhận được rác:\n"
+"cần ID đối tượng, có rác:\n"
" %s"
msgid "could not load cruft pack .mtimes"
msgstr "không thể tải cruft pack .mtimes"
msgid "cannot open pack index"
-msgstr "không thể mở mục lục của gói"
+msgstr "không thể mở chỉ mục của gói"
#, c-format
msgid "loose object at %s could not be examined"
@@ -8905,31 +9111,37 @@ msgstr "không thể buộc mất đối tượng"
#, c-format
msgid "not a rev '%s'"
-msgstr "không phải má»™t rev “%sâ€"
+msgstr "không phải một rev '%s'"
#, c-format
msgid "bad revision '%s'"
-msgstr "Ä‘iểm xem xét sai “%sâ€"
+msgstr "điểm xem xét sai '%s'"
msgid "unable to add recent objects"
msgstr "không thể thêm các đối tượng mới dùng"
#, c-format
msgid "unsupported index version %s"
-msgstr "phiên bản mục lục không được hỗ trợ %s"
+msgstr "phiên bản chỉ mục không được hỗ trợ %s"
#, c-format
msgid "bad index version '%s'"
-msgstr "phiên bản mục lục sai “%sâ€"
+msgstr "phiên bản chỉ mục sai '%s'"
+
+msgid "show progress meter during object writing phase"
+msgstr "hiển thị bộ đo tiến triển trong suốt pha ghi đối tượng"
+
+msgid "similar to --all-progress when progress meter is shown"
+msgstr "tương tự --all-progress khi bộ đo tiến trình được xuất hiện"
msgid "<version>[,<offset>]"
msgstr "<phiên bản>[,offset]"
msgid "write the pack index file in the specified idx format version"
-msgstr "ghi tập tin bảng mục lục gói (pack) ở phiên bản định dạng idx đã cho"
+msgstr "ghi tập tin chỉ mục gói (pack) ở phiên bản định dạng idx đã cho"
msgid "maximum size of each output pack file"
-msgstr "kcíh thước tối đa cho tập tin gói được tạo"
+msgstr "kích thước tối đa cho tập tin gói được tạo"
msgid "ignore borrowed objects from alternate object store"
msgstr "bỠqua các đối tượng vay mượn từ kho đối tượng thay thế"
@@ -8944,7 +9156,7 @@ msgid "limit pack window by memory in addition to object limit"
msgstr "giới hạn cửa sổ đóng gói theo bộ nhớ cộng thêm với giới hạn đối tượng"
msgid "maximum length of delta chain allowed in the resulting pack"
-msgstr "độ dài tối đa của chuỗi móc xích “delta†được phép trong gói kết quả"
+msgstr "độ dài tối đa của chuỗi móc xích 'delta' được phép trong gói kết quả"
msgid "reuse existing deltas"
msgstr "dùng lại các delta sẵn có"
@@ -8962,7 +9174,7 @@ msgid "do not create an empty pack output"
msgstr "không thể tạo kết xuất gói trống rỗng"
msgid "read revision arguments from standard input"
-msgstr "Ä‘á»c tham số “revision†từ thiết bị nhập chuẩn"
+msgstr "Ä‘á»c tham số 'revision' từ stdin"
msgid "limit the objects to those that are not yet packed"
msgstr "giới hạn các đối tượng thành những cái mà chúng vẫn chưa được đóng gói"
@@ -8974,13 +9186,13 @@ msgid "include objects referred by reflog entries"
msgstr "bao gồm các đối tượng được tham chiếu bởi các mục reflog"
msgid "include objects referred to by the index"
-msgstr "bao gồm các đối tượng được tham chiếu bởi mục lục"
+msgstr "bao gồm các đối tượng được tham chiếu bởi chỉ mục"
msgid "read packs from stdin"
-msgstr "Ä‘á»c các gói từ đầu vào tiêu chuẩn"
+msgstr "Ä‘á»c các gói từ stdin"
msgid "output pack to stdout"
-msgstr "xuất gói ra đầu ra tiêu chuẩn"
+msgstr "xuất gói ra stdout"
msgid "include tag objects that refer to objects to be packed"
msgstr "bao gồm các đối tượng tham chiếu đến các đối tượng được đóng gói"
@@ -8993,16 +9205,16 @@ msgstr "pack mất các đối tượng không thể Ä‘á»c được"
msgid "unpack unreachable objects newer than <time>"
msgstr ""
-"xả nén (gỡ khá»i gói) các đối tượng không thể Ä‘á»c được má»›i hÆ¡n <thá»i-gian>"
+"giải nén (gỡ khá»i gói) các đối tượng không thể Ä‘á»c được má»›i hÆ¡n <thá»i-gian>"
msgid "create a cruft pack"
msgstr "tạo gói cruft"
msgid "expire cruft objects older than <time>"
-msgstr "các đối tượng cruft hết hạn cÅ© hÆ¡n khoảng <thá»i gian>"
+msgstr "các đối tượng cruft hết hạn cÅ© hÆ¡n <mốc thá»i gian>"
msgid "use the sparse reachability algorithm"
-msgstr "sá»­ dụng thuật toán “sparse reachabilityâ€"
+msgstr "sử dụng thuật toán 'sparse reachability'"
msgid "create thin packs"
msgstr "tạo gói nhẹ"
@@ -9020,25 +9232,25 @@ msgid "pack compression level"
msgstr "mức nén gói"
msgid "do not hide commits by grafts"
-msgstr "không ẩn các lần chuyển giao bởi “graftsâ€"
+msgstr "không ẩn các lần chuyển giao bởi 'grafts'"
msgid "use a bitmap index if available to speed up counting objects"
-msgstr "dùng mục lục ánh xạ nếu có thể được để nâng cao tốc độ đếm đối tượng"
+msgstr "dùng chỉ mục ánh xạ nếu có thể được để nâng cao tốc độ đếm đối tượng"
msgid "write a bitmap index together with the pack index"
-msgstr "ghi một mục lục ánh xạ cùng với mục lục gói"
+msgstr "ghi một chỉ mục ánh xạ cùng với chỉ mục gói"
msgid "write a bitmap index if possible"
-msgstr "ghi mục lục ánh xạ nếu được"
+msgstr "ghi chỉ mục ánh xạ nếu được"
msgid "handling for missing objects"
msgstr "xử lý cho thiếu đối tượng"
msgid "do not pack objects in promisor packfiles"
-msgstr "không thể đóng gói các đối tượng trong các tập tin gói hứa hẹn"
+msgstr "không thể đóng gói các đối tượng trong các tập tin gói promisor"
msgid "respect islands during delta compression"
-msgstr "tôn trá»ng island trong suốt quá trình nén “deltaâ€"
+msgstr "tôn trá»ng island trong suốt quá trình nén 'delta'"
msgid "protocol"
msgstr "giao thức"
@@ -9048,7 +9260,7 @@ msgstr "loại trừ bất kỳ cấu hình uploadpack.blobpackfileuri với gia
#, c-format
msgid "delta chain depth %d is too deep, forcing %d"
-msgstr "mức sau xích delta %d là quá sâu, buộc dùng %d"
+msgstr "mức delta chain %d là quá sâu, buộc dùng %d"
#, c-format
msgid "pack.deltaCacheLimit is too high, forcing %d"
@@ -9066,36 +9278,30 @@ msgid "minimum pack size limit is 1 MiB"
msgstr "giới hạn kích thước tối thiểu của gói là 1 MiB"
msgid "--thin cannot be used to build an indexable pack"
-msgstr "--thin không thể được dùng để xây dựng gói đánh mục lục được"
-
-msgid "cannot use --filter without --stdout"
-msgstr "không thể dùng tùy chá»n --filter mà không có --stdout"
+msgstr "không thể dùng --thin để xây dựng gói đánh chỉ mục được"
msgid "cannot use --filter with --stdin-packs"
msgstr "không thể dùng tùy chá»n --filter vá»›i --stdin-packs"
msgid "cannot use internal rev list with --stdin-packs"
-msgstr "không thể dùng danh sách rev bên trong với --stdin-packs"
+msgstr "không thể dùng danh sách rev nội bộ với --stdin-packs"
msgid "cannot use internal rev list with --cruft"
-msgstr "không thể dùng danh sách rev bên trong với --cruft"
+msgstr "không thể dùng danh sách rev nội bộ với --cruft"
msgid "cannot use --stdin-packs with --cruft"
-msgstr "không thể dùng tùy chá»n --stdin-packs vá»›i --cruft"
-
-msgid "cannot use --max-pack-size with --cruft"
-msgstr "không thể dùng tùy chá»n --max-pack-size vá»›i --cruft"
+msgstr "không thể dùng tùy chá»n --stdin-packs vá»›i --cruft"
msgid "Enumerating objects"
-msgstr "Äánh số các đối tượng"
+msgstr "Duyệt các đối tượng"
#, c-format
msgid ""
"Total %<PRIu32> (delta %<PRIu32>), reused %<PRIu32> (delta %<PRIu32>), pack-"
-"reused %<PRIu32>"
+"reused %<PRIu32> (from %<PRIuMAX>)"
msgstr ""
-"Tổng %<PRIu32> (delta %<PRIu32>), dùng lại %<PRIu32> (delta %<PRIu32>), pack-"
-"reused %<PRIu32>"
+"Tổng %<PRIu32> (delta %<PRIu32>), dùng lại %<PRIu32> (delta %<PRIu32>),dùng "
+"lại pack %<PRIu32> (trong số %<PRIuMAX>)"
msgid ""
"'git pack-redundant' is nominated for removal.\n"
@@ -9104,14 +9310,21 @@ msgid ""
"and let us know you still use it by sending an e-mail\n"
"to <git@vger.kernel.org>. Thanks.\n"
msgstr ""
-"“git pack-redundant†được Ä‘á» cá»­ để loại bá».\n"
-"Nếu bạn vẫn sử dụng lệnh này, vui lòng bổ sung\n"
-"thêm má»™t tùy chá»n, “--i-still-use-thisâ€, trên dòng lệnh\n"
+"'git pack-redundant' đã được Ä‘á» cá»­ để loại bá».\n"
+"Nếu bạn vẫn còn sử dụng lệnh này, vui lòng bổ sung\n"
+"thêm má»™t tùy chá»n, '--i-still-use-this', trên dòng lệnh\n"
"và cho chúng tôi biết bạn vẫn sử dụng nó bằng cách gửi e-mail\n"
-"đến <git@vger.kernel.org>. Cảm ơn.\n"
+"đến <git@vger.kernel.org>. Xin cảm ơn.\n"
+
+msgid "refusing to run without --i-still-use-this"
+msgstr "từ chối chạy lệnh này mà không có --i-still-use-this"
-msgid "git pack-refs [<options>]"
-msgstr "git pack-refs [<các tùy chá»n>]"
+msgid ""
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
+"<pattern>]"
+msgstr ""
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
+"<pattern>]"
msgid "pack everything"
msgstr "đóng gói má»i thứ"
@@ -9119,23 +9332,45 @@ msgstr "đóng gói má»i thứ"
msgid "prune loose refs (default)"
msgstr "prune (cắt cụt) những tham chiếu bị mất (mặc định)"
+msgid "auto-pack refs as needed"
+msgstr "tự động pack tham chiếu nếu cần"
+
+msgid "references to include"
+msgstr "bao gồm các tham chiếu"
+
+msgid "references to exclude"
+msgstr "loại trừ các tham chiếu"
+
+msgid "git patch-id [--stable | --unstable | --verbatim]"
+msgstr "git patch-id [--stable | --unstable | --verbatim]"
+
+msgid "use the unstable patch-id algorithm"
+msgstr "sử dụng thuật toán patch-id unstable"
+
+msgid "use the stable patch-id algorithm"
+msgstr "sử dụng thuật toán patch-id stable"
+
+msgid "don't strip whitespace from the patch"
+msgstr "không lược bỠkhoảng trắng thừa từ bản vá"
+
msgid "git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>...]"
-msgstr "git prune [-n] [-v] [--progress] [--expire <thá»i-gian>] [--] [<head>…]"
+msgstr ""
+"git prune [-n] [-v] [--progress] [--expire <thá»i-gian>] [--] [<head>...]"
msgid "report pruned objects"
-msgstr "báo cáo các đối tượng đã prune"
+msgstr "liệt kê các đối tượng đã prune"
msgid "expire objects older than <time>"
msgstr "các đối tượng hết hạn cÅ© hÆ¡n khoảng <thá»i gian>"
msgid "limit traversal to objects outside promisor packfiles"
-msgstr "giới hạn giao đến các đối tượng nằm ngoài các tập tin gói hứa hẹn"
+msgstr "giới hạn giao đến các đối tượng nằm ngoài các tập tin gói promisor"
msgid "cannot prune in a precious-objects repo"
msgstr "không thể tỉa bớt trong một kho đối_tượng_vĩ_đại"
msgid "git pull [<options>] [<repository> [<refspec>...]]"
-msgstr "git pull [<các tùy chá»n>] [<kho-chứa> [<refspec>…]]"
+msgstr "git pull [<các tùy chá»n>] [<kho-chứa> [<refspec>...]]"
msgid "control for recursive fetching of submodules"
msgstr "Ä‘iá»u khiển việc lấy vỠđệ quy của các mô-Ä‘un-con"
@@ -9164,6 +9399,12 @@ msgstr "ép buộc ghi đè lên nhánh nội bộ"
msgid "number of submodules pulled in parallel"
msgstr "số lượng mô-Ä‘un-con được đẩy lên đồng thá»i"
+msgid "use IPv4 addresses only"
+msgstr "chỉ dùng địa chỉ IPv4"
+
+msgid "use IPv6 addresses only"
+msgstr "chỉ dùng địa chỉ IPv6"
+
msgid ""
"There is no candidate for rebasing against among the refs that you just "
"fetched."
@@ -9181,9 +9422,9 @@ msgid ""
"Generally this means that you provided a wildcard refspec which had no\n"
"matches on the remote end."
msgstr ""
-"Äại thể Ä‘iá»u này có nghÄ©a là bạn đã cung cấp đặc tả Ä‘Æ°á»ng dẫn dạng dùng ký "
+"Äại khái Ä‘iá»u này có nghÄ©a là bạn đã cung cấp đặc tả Ä‘Æ°á»ng dẫn dạng dùng ký "
"tá»±\n"
-"đại diện mà nó lại không khớp trên điểm cuối máy phục vụ."
+"đại diện mà nó lại không khớp trên điểm cuối máy chủ."
#, c-format
msgid ""
@@ -9191,16 +9432,16 @@ msgid ""
"a branch. Because this is not the default configured remote\n"
"for your current branch, you must specify a branch on the command line."
msgstr ""
-"Bạn yêu cầu pull từ máy dịch vụ “%sâ€, nhÆ°ng lại chÆ°a chỉ định\n"
-"nhánh nào. Bởi vì đây không phải là máy dịch vụ được cấu hình\n"
-"theo mặc định cho nhánh hiện tại của bạn, bạn phải chỉ định\n"
+"Bạn yêu cầu pull từ máy dịch vụ '%s', nhưng lại chưa chỉ định\n"
+"nhánh nào. Bởi vì đây không phải là máy chủ được cấu hình\n"
+"mặc định cho nhánh hiện tại của bạn, bạn phải chỉ định\n"
"một nhánh trên dòng lệnh."
msgid "You are not currently on a branch."
-msgstr "Hiện tại bạn chẳng ở nhánh nào cả."
+msgstr "Hiện tại bạn đang không ở trên nhánh nào."
msgid "Please specify which branch you want to rebase against."
-msgstr "Vui lòng chỉ định nhánh nào bạn muốn cải tổ lại."
+msgstr "Vui lòng chỉ định nhánh bạn muốn cải tổ lại."
msgid "Please specify which branch you want to merge with."
msgstr "Vui lòng chỉ định nhánh nào bạn muốn hòa trộn vào."
@@ -9220,22 +9461,23 @@ msgstr "Ở đây không có thông tin theo dõi cho nhánh hiện hành."
msgid ""
"If you wish to set tracking information for this branch you can do so with:"
msgstr ""
-"Nếu bạn muốn theo dõi thông tin cho nhánh này bạn có thể thực hiện bằng lệnh:"
+"Nếu bạn muốn thiết lập thông tin theo dõi cho nhánh này bạn có thể thực hiện "
+"bằng lệnh:"
#, c-format
msgid ""
"Your configuration specifies to merge with the ref '%s'\n"
"from the remote, but no such ref was fetched."
msgstr ""
-"Các đặc tả cấu hình của bạn để hòa trá»™n vá»›i tham chiếu “%sâ€\n"
-"từ máy dịch vụ, nhÆ°ng không có nhánh nào nhÆ° thế được lấy vá»."
+"Cấu hình của bạn nói cần hòa trộn với tham chiếu '%s'\n"
+"từ máy dịch vụ, nhÆ°ng không có tham chiếu nào nhÆ° thế được lấy vá»."
#, c-format
msgid "unable to access commit %s"
-msgstr "không thể truy cập lần chuyển giao “%sâ€"
+msgstr "không thể truy cập lần chuyển giao '%s'"
msgid "ignoring --verify-signatures for rebase"
-msgstr "bá» qua --verify-signatures khi rebase"
+msgstr "bỠqua --verify-signatures khi cải tổ"
msgid ""
"You have divergent branches and need to specify how to reconcile them.\n"
@@ -9252,31 +9494,30 @@ msgid ""
"or --ff-only on the command line to override the configured default per\n"
"invocation.\n"
msgstr ""
-"Bạn có các nhánh phân kỳ và cần chỉ định cách hòa hợp chúng.\n"
-"Bạn có thể làm như vậy bằng cách chạy một trong những lệnh sau đây\n"
-"thỉnh thoảng trước khi thực hiện lệnh pull tiếp theo của bạn:\n"
+"Bạn có các nhánh phân kỳ và cần chỉ định cách hợp nhất chúng.\n"
+"Bạn có thể làm vậy bằng cách chạy một trong những lệnh sau đây\n"
+"trước khi thực hiện lệnh pull tiếp theo của bạn:\n"
"\n"
-" git config pull.rebase false # merge\n"
-" git config pull.rebase true # rebase\n"
-" git config pull.ff only # chỉ fast-forward\n"
+" git config pull.rebase false # hợp nhất\n"
+" git config pull.rebase true # cải tổ\n"
+" git config pull.ff only # chỉ chuyển tiếp nhanh\n"
"\n"
"Bạn có thể thay thế \"git config\" với \"git config --global\" để thiết lập "
"mặc định\n"
-"ưu tiên cho tất cả các kho. Bạn cũng có thể chuyển qua --rebase, --no-"
-"rebase,\n"
-"hoặc --ff-only trên dòng lệnh để ghi đè các mặc định đã cấu hình cho mỗi\n"
+"ưu tiên cho tất cả các kho. Bạn cũng có thể chỉ định --rebase, --no-rebase,\n"
+"hoặc --ff-only trên dòng lệnh để ghi đè cấu hình mặc định cho từng\n"
"lần gá»i.\n"
msgid "Updating an unborn branch with changes added to the index."
msgstr ""
-"Äang cập nhật má»™t nhánh chÆ°a được sinh ra vá»›i các thay đổi được thêm vào "
-"bảng mục lục."
+"Äang cập nhật má»™t nhánh chÆ°a được sinh ra từ các thay đổi được thêm vào mục "
+"lục."
msgid "pull with rebase"
msgstr "pull vá»›i rebase"
-msgid "please commit or stash them."
-msgstr "xin hãy chuyển giao hoặc tạm cất (stash) chúng."
+msgid "Please commit or stash them."
+msgstr "Xin hãy chuyển giao hoặc tạm cất chúng."
#, c-format
msgid ""
@@ -9286,7 +9527,7 @@ msgid ""
msgstr ""
"fetch đã cập nhật head nhánh hiện tại.\n"
"đang chuyển-tiếp-nhanh cây làm việc của bạn từ\n"
-"lần chuyển giaot %s."
+"lần chuyển giao %s."
#, c-format
msgid ""
@@ -9299,30 +9540,29 @@ msgid ""
msgstr ""
"Không thể chuyển tiếp nhanh cây làm việc của bạn.\n"
"Sau khi chắc chắn rằng mình đã ghi lại má»i thứ\n"
-"quý báu từ kết xuất của lệnh\n"
+"quan trá»ng từ đầu ra của lệnh\n"
"$ git diff %s\n"
"chạy\n"
"$ git reset --hard\n"
-"để khôi phục lại."
+"để khôi phục."
msgid "Cannot merge multiple branches into empty head."
-msgstr "Không thể hòa trá»™n nhiá»u nhánh vào trong má»™t head trống rá»—ng."
+msgstr "Không thể hòa trá»™n nhiá»u nhánh vào má»™t head trống rá»—ng."
msgid "Cannot rebase onto multiple branches."
-msgstr "Không thể thá»±c hiện lệnh rebase (cải tổ) trên nhiá»u nhánh."
+msgstr "Không thể thá»±c hiện lệnh cải tổ trên nhiá»u nhánh."
msgid "Cannot fast-forward to multiple branches."
msgstr "Không thể thá»±c hiện chuyển tiếp nhanh trên nhiá»u nhánh."
msgid "Need to specify how to reconcile divergent branches."
-msgstr "Caanfchir định làm thế nào để giải quyết các nhánh phân kỳ."
+msgstr "Cần chỉ định làm thế nào để giải quyết các nhánh phân kỳ."
msgid "cannot rebase with locally recorded submodule modifications"
-msgstr ""
-"không thể cải tổ với các thay đổi mô-đun-con được ghi lại một cách cục bộ"
+msgstr "không thể cải tổ với các thay đổi submodule cục bộ"
msgid "git push [<options>] [<repository> [<refspec>...]]"
-msgstr "git push [<các tùy chá»n>] [<kho-chứa> [<refspec>…]]"
+msgstr "git push [<các tùy chá»n>] [<kho-chứa> [<refspec>...]]"
msgid "tag shorthand without <tag>"
msgstr "dùng tốc ký thẻ không có <thẻ>"
@@ -9335,14 +9575,13 @@ msgid ""
"To choose either option permanently, see push.default in 'git help config'.\n"
msgstr ""
"\n"
-"Äể chá»n má»—i tùy chá»n má»™t cách cố định, xem push.default trong “git help "
-"configâ€.\n"
+"Äể chá»n má»—i tùy chá»n má»™t cách cố định, xem push.default trong 'git help "
+"config'.\n"
msgid ""
"\n"
-"To avoid automatically configuring upstream branches when their name\n"
-"doesn't match the local branch, see option 'simple' of branch."
-"autoSetupMerge\n"
+"To avoid automatically configuring an upstream branch when its name\n"
+"won't match the local branch, see option 'simple' of branch.autoSetupMerge\n"
"in 'git help config'.\n"
msgstr ""
"\n"
@@ -9407,8 +9646,7 @@ msgid ""
"%s"
msgstr ""
"Nhánh hiện tại %s không có nhánh thượng nguồn nào.\n"
-"Äể push (đẩy lên) nhánh hiện tại và đặt máy chủ này làm thượng nguồn "
-"(upstream), sử dụng\n"
+"Äể đẩy lên nhánh hiện tại và đặt máy chủ này làm thượng nguồn, sá»­ dụng\n"
"\n"
" git push --set-upstream %s %s\n"
"%s"
@@ -9420,8 +9658,8 @@ msgstr "Nhánh hiện tại %s có nhiá»u nhánh thượng nguồn, từ chối
msgid ""
"You didn't specify any refspecs to push, and push.default is \"nothing\"."
msgstr ""
-"Bạn đã không chỉ ra một refspecs nào để đẩy lên, và push.default là \"không "
-"là gì cả\"."
+"Bạn đã không chỉ ra một refspecs nào để đẩy lên, và push.default "
+"là\"nothing\"."
#, c-format
msgid ""
@@ -9429,48 +9667,46 @@ msgid ""
"your current branch '%s', without telling me what to push\n"
"to update which remote branch."
msgstr ""
-"Bạn Ä‘ang push (đẩy lên) máy chủ “%sâ€, mà nó không phải là thượng nguồn "
-"(upstream) của\n"
-"nhánh hiện tại “%s†của bạn, mà không báo cho tôi biết là cái gì được push\n"
-"để cập nhật nhánh máy chủ nào."
+"Bạn đang đẩy lên máy chủ '%s', không phải là thượng nguồn của\n"
+"nhánh hiện tại '%s' của bạn, mà không báo cho tôi biết là cần đẩy lên\n"
+"nhánh nào để cập nhật nhánh nào."
msgid ""
"Updates were rejected because the tip of your current branch is behind\n"
-"its remote counterpart. Integrate the remote changes (e.g.\n"
-"'git pull ...') before pushing again.\n"
+"its remote counterpart. If you want to integrate the remote changes,\n"
+"use 'git pull' before pushing again.\n"
"See the 'Note about fast-forwards' in 'git push --help' for details."
msgstr ""
-"Việc cập nhật bị từ chối bởi vì đầu mút của nhánh hiện tại của bạn nằm đằng\n"
-"sau bộ phận tương ứng của máy chủ. Hòa trộn với các thay đổi từ máy chủ\n"
-"(v.d. \"git pull …\") trước khi đẩy lên lần nữa.\n"
-"Xem “Note about fast-forwards†trong “git push --help†để có thông tin chi "
+"Việc cập nhật bị từ chối bởi vì đỉnh của nhánh hiện tại của bạn đứng sau\n"
+"nhánh tương ứng của máy chủ. Nếu bạn cần hòa trộn với các thay đổi từ\n"
+"máy chủ, hãy chạy 'git pull' trước khi đẩy lên.\n"
+"Xem 'Note about fast-forwards' trong 'git push --help' để biết thông tin chi "
"tiết."
msgid ""
"Updates were rejected because a pushed branch tip is behind its remote\n"
-"counterpart. Check out this branch and integrate the remote changes\n"
-"(e.g. 'git pull ...') before pushing again.\n"
+"counterpart. If you want to integrate the remote changes, use 'git pull'\n"
+"before pushing again.\n"
"See the 'Note about fast-forwards' in 'git push --help' for details."
msgstr ""
-"Việc cập nhật bị từ chối bởi vì đầu mút của nhánh đã đẩy lên nằm đằng sau "
-"bá»™\n"
-"phận tương ứng của máy chủ. Checkou nhánh này và hòa trộn với các thay đổi\n"
-"từ máy chủ (v.d. “git pull …â€) trÆ°á»›c khi lại push lần nữa.\n"
-"Xem “Note about fast-forwards†trong “git push --help†để có thông tin chi "
+"Việc cập nhật bị từ chối bởi vì đỉnh của nhánh đã đẩy lên đứng sau\n"
+"nhánh tương ứng của máy chủ. Nếu bạn cần hòa trộn với các thay đổi từ\n"
+"máy chủ, hãy chạy 'git pull' trước khi đẩy lên.\n"
+"Xem 'Note about fast-forwards' trong 'git push --help' để biết thông tin chi "
"tiết."
msgid ""
-"Updates were rejected because the remote contains work that you do\n"
-"not have locally. This is usually caused by another repository pushing\n"
-"to the same ref. You may want to first integrate the remote changes\n"
-"(e.g., 'git pull ...') before pushing again.\n"
+"Updates were rejected because the remote contains work that you do not\n"
+"have locally. This is usually caused by another repository pushing to\n"
+"the same ref. If you want to integrate the remote changes, use\n"
+"'git pull' before pushing again.\n"
"See the 'Note about fast-forwards' in 'git push --help' for details."
msgstr ""
-"Việc cập nhật bị từ chối bởi vì máy chủ có chứa công việc mà bạn không\n"
-"có ở máy ná»™i bá»™ của mình. Lá»—i này thÆ°á»ng có nguyên nhân bởi kho khác đẩy\n"
-"dữ liệu lên cùng một tham chiếu. Bạn có lẽ muốn hòa trộn với các thay đổi\n"
-"từ máy chủ (v.d. “git pull…â€) trÆ°á»›c khi lại push lần nữa.\n"
-"Xem “Note about fast-forwards†trong “git push --help†để có thông tin chi "
+"Việc cập nhật bị từ chối bởi vì máy chủ có chứa thay đổi mà bạn không\n"
+"có ở nhánh của mình. Lá»—i này thÆ°á»ng xảy ra khi kho khác đẩy dữ liệu\n"
+"lên cùng một tham chiếu. Nếu bạn cần hòa trộn với các thay đổi từ\n"
+"máy chủ, hãy chạy 'git pull' trước khi đẩy lên.\n"
+"Xem 'Note about fast-forwards' trong 'git push --help' để biết thông tin chi "
"tiết."
msgid "Updates were rejected because the tag already exists in the remote."
@@ -9481,22 +9717,22 @@ msgid ""
"or update a remote ref to make it point at a non-commit object,\n"
"without using the '--force' option.\n"
msgstr ""
-"Không thể cập nhật một tham chiếu trên máy chủ mà nó chỉ đến đối tượng "
-"không\n"
-"phải là lần chuyển giao, hoặc cập nhật một tham chiếu máy chủ để nó chỉ đến "
-"đối tượng\n"
-"không phải chuyển giao, mà không sá»­ dụng tùy chá»n “--forceâ€.\n"
+"Không thể cập nhật tham chiếu trên máy chủ đang chỉ đến đối tượng không\n"
+"phải là lần chuyển giao, hoặc cập nhật tham chiếu trên máy chủ để nó\n"
+"chỉ đến đối tượng không phải lần chuyển giao, mà không sử dụng\n"
+"tùy chá»n '--force'.\n"
msgid ""
-"Updates were rejected because the tip of the remote-tracking\n"
-"branch has been updated since the last checkout. You may want\n"
-"to integrate those changes locally (e.g., 'git pull ...')\n"
-"before forcing an update.\n"
+"Updates were rejected because the tip of the remote-tracking branch has\n"
+"been updated since the last checkout. If you want to integrate the\n"
+"remote changes, use 'git pull' before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
msgstr ""
-"Việc cập nhật bị từ chối bởi vì đầu mút của nhánh theo dõi máy chủ\n"
-"đã được cập nhật kể từ sau lần lấy ra cuối cùng. Bạn có lẽ muốn\n"
-"tích hợp các thay đổi này một cách cục bộ (v.d. \"git pull …\")\n"
-"trước khi ép buộc một cập nhật.\n"
+"Việc cập nhật bị từ chối bởi vì đỉnh của nhánh theo dõi máy chủ đã được\n"
+"cập nhật sau lần checkout trước. Nếu bạn cần hòa trộn với các thay đổi từ\n"
+"máy chủ, hãy chạy 'git pull' trước khi đẩy lên.\n"
+"Xem 'Note about fast-forwards' trong 'git push --help' để biết thông tin chi "
+"tiết."
#, c-format
msgid "Pushing to %s\n"
@@ -9504,7 +9740,13 @@ msgstr "Äang đẩy lên %s\n"
#, c-format
msgid "failed to push some refs to '%s'"
-msgstr "gặp lá»—i khi đẩy tá»›i má»™t số tham chiếu đến “%sâ€"
+msgstr "gặp lỗi khi đẩy tới một số tham chiếu đến '%s'"
+
+msgid ""
+"recursing into submodule with push.recurseSubmodules=only; using on-demand "
+"instead"
+msgstr ""
+"đệ quy vào mô-đun con với push.recurseSubmodules=only; thay bằng on-demand"
#, c-format
msgid "invalid value for '%s'"
@@ -9513,17 +9755,17 @@ msgstr "giá trị cho '%s' không hợp lệ"
msgid "repository"
msgstr "kho"
-msgid "push all refs"
-msgstr "đẩy tất cả các tham chiếu"
+msgid "push all branches"
+msgstr "đẩy tất cả các nhánh"
msgid "mirror all refs"
-msgstr "mirror tất cả các tham chiếu"
+msgstr "sao tất cả các tham chiếu"
msgid "delete refs"
msgstr "xóa các tham chiếu"
-msgid "push tags (can't be used with --all or --mirror)"
-msgstr "đẩy các thẻ (không dùng cùng với --all hay --mirror)"
+msgid "push tags (can't be used with --all or --branches or --mirror)"
+msgstr "đẩy các thẻ (không dùng cùng với --all hay --branches hay --mirror)"
msgid "force updates"
msgstr "ép buộc cập nhật"
@@ -9538,7 +9780,7 @@ msgid "require remote updates to be integrated locally"
msgstr "yêu cầu máy chủ cập nhật để thích hợp với máy cục bộ"
msgid "control recursive pushing of submodules"
-msgstr "Ä‘iá»u khiển việc đẩy lên (push) đệ qui của mô-Ä‘un-con"
+msgstr "Ä‘iá»u khiển việc đẩy lên (push) đệ quy của mô-Ä‘un-con"
msgid "use thin pack"
msgstr "tạo gói nhẹ"
@@ -9569,7 +9811,7 @@ msgstr "--delete không hợp lý nếu không có bất kỳ tham chiếu nào"
#, c-format
msgid "bad repository '%s'"
-msgstr "repository (kho) sai “%sâ€"
+msgstr "repository (kho) sai '%s'"
msgid ""
"No configured push destination.\n"
@@ -9605,7 +9847,7 @@ msgstr ""
"git range-diff [<các tùy chá»n>] <old-base>..<old-tip> <new-base>..<new-tip>"
msgid "git range-diff [<options>] <old-tip>...<new-tip>"
-msgstr "git range-diff [<các tùy chá»n>] <old-tip>…<new-tip>"
+msgstr "git range-diff [<các tùy chá»n>] <old-tip>...<new-tip>"
msgid "git range-diff [<options>] <base> <old-tip> <new-tip>"
msgstr "git range-diff [<các tùy chá»n>] <base> <old-tip> <new-tip>"
@@ -9617,7 +9859,7 @@ msgid "notes"
msgstr "ghi chú"
msgid "passed to 'git log'"
-msgstr "chuyển cho “git logâ€"
+msgstr "chuyển cho 'git log'"
msgid "only emit output related to the first range"
msgstr "chỉ phát ra kết xuất liên quan đến vùng đầu tiên"
@@ -9626,29 +9868,36 @@ msgid "only emit output related to the second range"
msgstr "chỉ phát ra kết xuất liên quan đến vùng thứ hai"
#, c-format
+msgid "not a revision: '%s'"
+msgstr "không phải một revision '%s'"
+
+#, c-format
msgid "not a commit range: '%s'"
-msgstr "không phải là vùng chuyển giao: “%sâ€"
+msgstr "không phải là vùng chuyển giao: '%s'"
-msgid "single arg format must be symmetric range"
-msgstr "định dạng đối số đơn phải là một vùng đối xứng"
+#, c-format
+msgid "not a symmetric range: '%s'"
+msgstr "không phải là vùng tương xứng: '%s'"
msgid "need two commit ranges"
-msgstr "cần hai vùng lần chuyển giao"
+msgstr "cần hai vùng chuyển giao"
msgid ""
-"git read-tree [(-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>) "
-"[-u | -i]] [--no-sparse-checkout] [--index-output=<file>] (--empty | <tree-"
-"ish1> [<tree-ish2> [<tree-ish3>]])"
-msgstr ""
"git read-tree [(-m [--trivial] [--aggressive] | --reset | --"
-"prefix=<tiá»n_tố>) [-u | -i]] [--no-sparse-checkout] [--index-"
-"output=<tập_tin>] (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])"
+"prefix=<prefix>)\n"
+" [-u | -i]] [--index-output=<file>] [--no-sparse-checkout]\n"
+" (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])"
+msgstr ""
+"git read-tree [(-m [--trivial] [--aggressive] | --reset | --prefix=<tiá»n "
+"tố>)\n"
+" [-u | -i]] [--index-output=<tập tin>] [--no-sparse-checkout]\n"
+" (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])"
msgid "write resulting index to <file>"
-msgstr "ghi mục lục kết quả vào <tập-tin>"
+msgstr "ghi chỉ mục kết quả vào <tập-tin>"
msgid "only empty the index"
-msgstr "chỉ với bảng mục lục trống rỗng"
+msgstr "chỉ với chỉ mục trống rỗng"
msgid "Merging"
msgstr "Hòa trộn"
@@ -9658,10 +9907,10 @@ msgstr "thá»±c hiện má»™t hòa trá»™n thêm vào việc Ä‘á»c"
msgid "3-way merge if no file level merging required"
msgstr ""
-"hòa trộn kiểu “3-way†nếu không có tập tin mức hòa trộn nào được yêu cầu"
+"hòa trộn kiểu '3-way' nếu không có tập tin mức hòa trộn nào được yêu cầu"
msgid "3-way merge in presence of adds and removes"
-msgstr "hòa trá»™n 3-way trong sá»± hiện diện của “adds†và “removesâ€"
+msgstr "hòa trộn 3-way trong sự hiện diện của 'adds' và 'removes'"
msgid "same as -m, but discard unmerged entries"
msgstr "giống với -m, nhưng bỠqua các mục chưa được hòa trộn"
@@ -9670,7 +9919,7 @@ msgid "<subdirectory>/"
msgstr "<thư-mục-con>/"
msgid "read the tree into the index under <subdirectory>/"
-msgstr "Ä‘á»c cây vào trong bảng mục lục dÆ°á»›i <thÆ°_mục_con>/"
+msgstr "Ä‘á»c cây vào trong chỉ mục dÆ°á»›i <thÆ°_mục_con>/"
msgid "update working tree with merge result"
msgstr "cập nhật cây làm việc với kết quả hòa trộn"
@@ -9679,25 +9928,25 @@ msgid "gitignore"
msgstr "gitignore"
msgid "allow explicitly ignored files to be overwritten"
-msgstr "cho phép các tập tin rõ ràng bị lỠđi được ghi đè"
+msgstr "cho phép các tập tin rõ ràng bị bỠqua được ghi đè"
msgid "don't check the working tree after merging"
msgstr "không kiểm tra cây làm việc sau hòa trộn"
msgid "don't update the index or the work tree"
-msgstr "không cập nhật bảng mục lục hay cây làm việc"
+msgstr "không cập nhật chỉ mục hay cây làm việc"
msgid "skip applying sparse checkout filter"
-msgstr "bá» qua áp dụng bá»™ lá»c lấy ra (checkout) thÆ°a thá»›t"
+msgstr "bá» qua áp dụng bá»™ lá»c sparse checkout (checkout thÆ°a)"
msgid "debug unpack-trees"
-msgstr "gỡ lá»—i “unpack-treesâ€"
+msgstr "gỡ lỗi 'unpack-trees'"
msgid "suppress feedback messages"
msgstr "không xuất các thông tin phản hồi"
msgid "You need to resolve your current index first"
-msgstr "Bạn cần phải giải quyết bảng mục lục hiện tại của bạn trước đã"
+msgstr "Bạn cần phải giải quyết chỉ mục hiện tại của bạn trước đã"
msgid ""
"git rebase [-i] [options] [--exec <cmd>] [--onto <newbase> | --keep-base] "
@@ -9714,7 +9963,7 @@ msgstr ""
#, c-format
msgid "could not read '%s'."
-msgstr "không thể Ä‘á»c “%sâ€."
+msgstr "không thể Ä‘á»c '%s'."
#, c-format
msgid "could not create temporary %s"
@@ -9734,34 +9983,20 @@ msgid "%s requires the merge backend"
msgstr "%s cần một ứng dụng hòa trộn chạy phía sau"
#, c-format
-msgid "could not get 'onto': '%s'"
-msgstr "không thể đặt lấy “ontoâ€: “%sâ€"
+msgid "invalid onto: '%s'"
+msgstr "onto không hợp lệ: '%s'"
#, c-format
msgid "invalid orig-head: '%s'"
-msgstr "orig-head không hợp lệ: “%sâ€"
+msgstr "orig-head không hợp lệ: '%s'"
#, c-format
msgid "ignoring invalid allow_rerere_autoupdate: '%s'"
-msgstr "Ä‘ang bá» qua allow_rerere_autoupdate không hợp lệ: “%sâ€"
+msgstr "đang bỠqua allow_rerere_autoupdate không hợp lệ: '%s'"
#, c-format
msgid "could not remove '%s'"
-msgstr "không thể gỡ bỠ“%sâ€"
-
-msgid ""
-"Resolve all conflicts manually, mark them as resolved with\n"
-"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
-"You can instead skip this commit: run \"git rebase --skip\".\n"
-"To abort and get back to the state before \"git rebase\", run \"git rebase --"
-"abort\"."
-msgstr ""
-"Giải quyết vấn đỠnày thủ công, hãy đanh dấu chúng đã được giải quyết bằng\n"
-"hãy chạy lệnh \"git add/rm <các_tập_tin_xung_đột>\", sau đó chạy \"git "
-"rebase --continue\".\n"
-"Bạn có thể bỠqua miếng vá, chạy \"git rebase --skip\".\n"
-"Äể bãi bá» và quay trở lại trạng thái trÆ°á»›c \"git rebase\", chạy \"git rebase "
-"--abort\"."
+msgstr "không thể gỡ bỠ'%s'"
#, c-format
msgid ""
@@ -9774,24 +10009,44 @@ msgid ""
"As a result, git cannot rebase them."
msgstr ""
"\n"
-"git chạm trán một lỗi trong khi đang chuẩn bị các miếng vá để diễn lại\n"
+"git gặp phải một lỗi trong khi đang chuẩn bị các bản vá để diễn lại\n"
"những điểm xét duyệt này:\n"
"\n"
" %s\n"
"\n"
-"Kết quả là git không thể cải tổ lại chúng."
+"Kết quả là, git không thể cải tổ lại chúng."
+
+#, c-format
+msgid "Unknown rebase-merges mode: %s"
+msgstr "Không hiểu chế độ cải tổ: %s"
#, c-format
msgid "could not switch to %s"
msgstr "không thể chuyển đến %s"
+msgid "apply options and merge options cannot be used together"
+msgstr ""
+"không thể tổ hợp các tùy chá»n áp dụng vá»›i các tùy chá»n hòa trá»™n vá»›i nhau"
+
+msgid "--empty=ask is deprecated; use '--empty=stop' instead."
+msgstr "không cho dùng --empty=ask nữa; hãy thay thế bằng '--empty=stop'."
+
#, c-format
msgid ""
-"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and \"ask"
-"\"."
+"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
+"\"stop\"."
msgstr ""
-"kiểu rá»—ng không được nhận dạng “%sâ€; giá trị hợp lệ là \"drop\", \"keep\", "
-"và \"ask\"."
+"kiểu rỗng không được nhận dạng '%s'; giá trị hợp lệ là \"drop\", \"keep\", "
+"và \"stop\"."
+
+msgid ""
+"--rebase-merges with an empty string argument is deprecated and will stop "
+"working in a future version of Git. Use --rebase-merges without an argument "
+"instead, which does the same thing."
+msgstr ""
+"--rebase-merges vá»›i tham số xâu rá»—ng được coi là lá»—i thá»i và sẽ không còn "
+"hoạt động trong Git tương lai. Thay vào đó dùng --rebase-merges không có "
+"tham số, cho kết quả như nhau."
#, c-format
msgid ""
@@ -9803,10 +10058,10 @@ msgid ""
"\n"
msgstr ""
"%s\n"
-"Vui lòng chỉ định nhánh nào bạn muốn cải tổ dựa vào.\n"
+"Vui lòng chỉ định nhánh nào bạn muốn cải tổ lên.\n"
"Xem git-rebase(1) để biết thêm chi tiết.\n"
"\n"
-" git rebase “<nhánh>â€\n"
+" git rebase '<nhánh>'\n"
"\n"
#, c-format
@@ -9816,7 +10071,7 @@ msgid ""
" git branch --set-upstream-to=%s/<branch> %s\n"
"\n"
msgstr ""
-"Nếu bạn muốn theo dõi thông tin cho nhánh này bạn có thể thực hiện bằng "
+"Nếu bạn muốn đặt thông tin theo dõi cho nhánh này bạn có thể thực hiện bằng "
"lệnh:\n"
"\n"
" git branch --set-upstream-to=%s/<nhánh> %s\n"
@@ -9832,17 +10087,16 @@ msgid "rebase onto given branch instead of upstream"
msgstr "cải tổ vào nhánh đã cho thay cho thượng nguồn"
msgid "use the merge-base of upstream and branch as the current base"
-msgstr ""
-"sử dụng các cơ sở hòa trộn của thượng nguồn và nhánh như là cơ sở hiện tại"
+msgstr "sử dụng gốc hòa trộn của thượng nguồn và nhánh làm gốc hiện tại"
msgid "allow pre-rebase hook to run"
msgstr "cho phép móc (hook) pre-rebase được chạy"
msgid "be quiet. implies --no-stat"
-msgstr "hãy im lặng. ý là --no-stat"
+msgstr "im lặng. ngụ ý --no-stat"
msgid "display a diffstat of what changed upstream"
-msgstr "hiển thị một diffstat của những thay đổi thượng nguồn"
+msgstr "hiển thị diffstat của những thay đổi thượng nguồn"
msgid "do not show diffstat of what changed upstream"
msgstr "đừng hiển thị diffstat của những thay đổi thượng nguồn"
@@ -9860,10 +10114,10 @@ msgid "synonym of --reset-author-date"
msgstr "đồng nghĩa với --reset-author-date"
msgid "passed to 'git apply'"
-msgstr "chuyển cho “git applyâ€"
+msgstr "chuyển cho 'git apply'"
msgid "ignore changes in whitespace"
-msgstr "lỠđi sự thay đổi do khoảng trắng gây ra"
+msgstr "bỠqua sự thay đổi do khoảng trắng gây ra"
msgid "cherry-pick all commits, even if unchanged"
msgstr ""
@@ -9873,19 +10127,19 @@ msgid "continue"
msgstr "tiếp tục"
msgid "skip current patch and continue"
-msgstr "bỠqua miếng vá hiện hành và tiếp tục"
+msgstr "bỠqua bản vá hiện hành và tiếp tục"
msgid "abort and check out the original branch"
-msgstr "bãi bỠvà lấy ra nhánh nguyên thủy"
+msgstr "huỷ bỠvà checkout nhánh gốc"
msgid "abort but keep HEAD where it is"
-msgstr "bãi bỠnhưng vẫn vẫn giữ HEAD chỉ đến nó"
+msgstr "huỷ bỠnhưng vẫn vẫn giữ nguyên HEAD"
msgid "edit the todo list during an interactive rebase"
-msgstr "sửa danh sách cần làm trong quá trình “rebase†(cải tổ) tương tác"
+msgstr "sửa danh sách cần làm trong quá trình 'rebase' (cải tổ) tương tác"
msgid "show the patch file being applied or merged"
-msgstr "hiển thị miếng vá đã được áp dụng hay hòa trộn"
+msgstr "hiển thị bản vá đã được áp dụng hay hòa trộn"
msgid "use apply strategies to rebase"
msgstr "dùng chiến lược áp dụng để cải tổ"
@@ -9908,6 +10162,9 @@ msgstr "bỠqua các lần chuyển giao mà nó bắt đầu trống rỗng"
msgid "move commits that begin with squash!/fixup! under -i"
msgstr "di chuyển các lần chuyển giao mà bắt đầu bằng squash!/fixup! dưới -i"
+msgid "update branches that point to commits that are being rebased"
+msgstr "cập nhật các nhánh trỠđến commit đang được cải tổ"
+
msgid "add exec lines after each commit of the editable list"
msgstr "thêm các dòng thực thi sau từng lần chuyển giao của danh sách sửa được"
@@ -9918,7 +10175,7 @@ msgid "try to rebase merges instead of skipping them"
msgstr "cố thử cải tổ các hòa trộn thay vì bỠqua chúng"
msgid "use 'merge-base --fork-point' to refine upstream"
-msgstr "dùng “merge-base --fork-point†để định nghĩa lại thượng nguồn"
+msgstr "dùng 'merge-base --fork-point' để định nghĩa lại thượng nguồn"
msgid "use the given merge strategy"
msgstr "dùng chiến lược hòa trộn đã cho"
@@ -9933,7 +10190,7 @@ msgid "rebase all reachable commits up to the root(s)"
msgstr "cải tổ tất các các lần chuyển giao cho đến root"
msgid "automatically re-schedule any `exec` that fails"
-msgstr "lập lịch lại một cách tự động bất kỳ “exec“ bị lỗi"
+msgstr "lập lịch lại một cách tự động bất kỳ 'exec' bị lỗi"
msgid "apply all changes, even those already present upstream"
msgstr ""
@@ -9941,7 +10198,7 @@ msgstr ""
msgid "It looks like 'git am' is in progress. Cannot rebase."
msgstr ""
-"Hình nhÆ° Ä‘ang trong quá trình thá»±c hiện lệnh “git amâ€. Không thể rebase."
+"Hình như đang trong quá trình thực hiện lệnh 'git am'. Không thể rebase."
msgid ""
"`rebase --preserve-merges` (-p) is no longer supported.\n"
@@ -9949,7 +10206,7 @@ msgid ""
"Or downgrade to v2.33, or earlier, to complete the rebase."
msgstr ""
"`rebase --preserve-merges` (-p) không còn được hỗ trợ nữa.\n"
-"Dùng `git rebase --abort` để chấm dứt việc cải tổ hiện tại.\n"
+"Dùng `git rebase --abort` để kết thúc việc cải tổ hiện tại.\n"
"Hoặc là hạ phiên bản phần má»m xuống v2.33,\n"
"hoặc trước nữa, để hoàn thành việc cải tổ."
@@ -9963,12 +10220,12 @@ msgstr ""
"'preserve',\n"
"cái mà giỠkhông còn được hỗ trợ nữa; dùng 'merges' để thay thế"
-msgid "No rebase in progress?"
-msgstr "Không có tiến trình rebase nào phải không?"
+msgid "no rebase in progress"
+msgstr "không có cải tổ đang được thực hiện"
msgid "The --edit-todo action can only be used during interactive rebase."
msgstr ""
-"Hành động “--edit-todo†chỉ có thể dùng trong quá trình “rebase†(sửa lịch "
+"Hành động '--edit-todo' chỉ có thể dùng trong quá trình 'rebase' (sửa lịch "
"sử) tương tác."
msgid "Cannot read HEAD"
@@ -10000,67 +10257,67 @@ msgid ""
"valuable there.\n"
msgstr ""
"Hình như là ở đây sẵn có một thư mục %s, và\n"
-"Tôi tá»± há»i có phải bạn Ä‘ang ở giữa má»™t lệnh rebase khác. Nếu đúng là\n"
+"có lẽ bạn đang ở giữa một lệnh rebase khác. Nếu đúng là\n"
"như vậy, xin hãy thử\n"
"\t%s\n"
"Nếu không phải thế, hãy thử\n"
"\t%s\n"
-"và chạy TÔI lần nữa. TÔI dừng lại trong trÆ°á»ng hợp bạn vẫn\n"
-"có một số thứ quý giá ở đây.\n"
+"và chạy TÔI lần nữa. TÔI sẽ dừng lại vì có khả năng bạn vẫn\n"
+"còn má»™t số thứ quan trá»ng ở đây.\n"
msgid "switch `C' expects a numerical value"
-msgstr "tùy chá»n “%c†cần má»™t giá trị bằng số"
-
-#, c-format
-msgid "Unknown mode: %s"
-msgstr "Không hiểu chế độ: %s"
+msgstr "tùy chá»n '%c' cần má»™t giá trị bằng số"
-msgid "--strategy requires --merge or --interactive"
-msgstr "--strategy cần --merge hay --interactive"
+msgid ""
+"apply options are incompatible with rebase.rebaseMerges. Consider adding --"
+"no-rebase-merges"
+msgstr ""
+"tuỳ chá»n apply không tÆ°Æ¡ng thích vá»›i rebase.rebaseMerges. Cân nhắc dùng --no-"
+"rebase-merges"
-msgid "apply options and merge options cannot be used together"
+msgid ""
+"apply options are incompatible with rebase.updateRefs. Consider adding --no-"
+"update-refs"
msgstr ""
-"không thể tổ hợp các tùy chá»n áp dụng vá»›i các tùy chá»n hòa trá»™n vá»›i nhau"
+"tuỳ chá»n apply không tÆ°Æ¡ng thích vá»›i rebase.updateRefs. Cân nhắc dùng --no-"
+"update-refs"
#, c-format
msgid "Unknown rebase backend: %s"
-msgstr "Không hiểu ứng dụng chạy phía sau lệnh cải tổ: %s"
+msgstr "Không hiểu backend cải tổ: %s"
msgid "--reschedule-failed-exec requires --exec or --interactive"
msgstr "--reschedule-failed-exec cần --exec hay --interactive"
#, c-format
msgid "invalid upstream '%s'"
-msgstr "thượng nguồn không hợp lệ “%sâ€"
+msgstr "thượng nguồn không hợp lệ '%s'"
msgid "Could not create new root commit"
msgstr "Không thể tạo lần chuyển giao gốc mới"
#, c-format
msgid "no such branch/commit '%s'"
-msgstr "không có nhánh/lần chuyển giao “%s†như thế"
+msgstr "không có nhánh/lần chuyển giao '%s' như thế"
#, c-format
msgid "No such ref: %s"
msgstr "Không có tham chiếu nào như thế: %s"
-msgid "Could not resolve HEAD to a revision"
-msgstr "Không thể phân giải lần chuyển giao HEAD đến một điểm xét duyệt"
+msgid "Could not resolve HEAD to a commit"
+msgstr "không thể phân giải HEAD thành tên lần chuyển giao"
#, c-format
msgid "'%s': need exactly one merge base with branch"
-msgstr "“%sâ€: cần chính xác má»™t cÆ¡ sở hòa trá»™n vá»›i nhánh"
+msgstr "'%s': cần chính xác một gốc hòa trộn với nhánh"
#, c-format
msgid "'%s': need exactly one merge base"
-msgstr "“%sâ€: cần chính xác má»™t cÆ¡ sở hòa trá»™n"
+msgstr "'%s': cần chính xác một gốc hòa trộn"
#, c-format
msgid "Does not point to a valid commit '%s'"
-msgstr "Không chỉ đến má»™t lần chuyển giao không hợp lệ “%sâ€"
-
-msgid "Please commit or stash them."
-msgstr "Xin hãy chuyển giao hoặc tạm cất (stash) chúng."
+msgstr "Không chỉ đến một lần chuyển giao không hợp lệ '%s'"
msgid "HEAD is up to date."
msgstr "HEAD đã cập nhật."
@@ -10090,7 +10347,7 @@ msgstr "Thay đổi từ %s thành %s:\n"
#, c-format
msgid "First, rewinding head to replay your work on top of it...\n"
msgstr ""
-"Trước tiên, di chuyển head để xem lại các công việc trên đỉnh của nó…\n"
+"Trước tiên, di chuyển head để xem lại các công việc trên đỉnh của nó...\n"
msgid "Could not detach HEAD"
msgstr "Không thể tách rá»i HEAD"
@@ -10117,19 +10374,19 @@ msgid ""
"To squelch this message and still keep the default behaviour, set\n"
"'receive.denyCurrentBranch' configuration variable to 'refuse'."
msgstr ""
-"Theo mặc định, việc cập nhật nhánh hiện tại trong một kho không-thuần\n"
+"Theo mặc định, việc cập nhật nhánh hiện tại trong một kho không bare\n"
"bị từ chối, bởi vì nó sẽ làm cho chỉ mục và cây làm việc mâu thuẫn với\n"
-"cái mà bạn đẩy lên, và sẽ yêu cầu lệnh “git reset --hard†để mà làm\n"
+"cái mà bạn đẩy lên, và sẽ yêu cầu lệnh 'git reset --hard' để làm\n"
"cho cây làm việc khớp với HEAD.\n"
"\n"
-"Bạn có thể đặt biến cấu hình “receive.denyCurrentBranch†thành\n"
-"“ignore†hay “warn†trong kho máy chủ để cho phép đẩy lên nhánh\n"
+"Bạn có thể đặt biến cấu hình 'receive.denyCurrentBranch' thành\n"
+"'ignore' hay 'warn' trong kho máy chủ để cho phép đẩy lên nhánh\n"
"hiện tại của nó; tuy nhiên, không nên làm như thế trừ phi bạn\n"
"sắp đặt để cập nhật cây làm việc của nó tương ứng với cái mà bạn đẩy\n"
"lên theo cách nào đó.\n"
"\n"
-"Äể chấm dứt lá»i nhắn này và vẫn giữ cách ứng xá»­ mặc định, hãy đặt\n"
-"biến cấu hình “receive.denyCurrentBranch†thành “refuseâ€."
+"Äể tắt lá»i nhắn này và vẫn giữ hành vi mặc định, hãy đặt\n"
+"biến cấu hình 'receive.denyCurrentBranch' thành 'refuse'."
msgid ""
"By default, deleting the current branch is denied, because the next\n"
@@ -10142,14 +10399,14 @@ msgid ""
"To squelch this message, you can set it to 'refuse'."
msgstr ""
"Theo mặc định, việc cập xóa nhánh hiện tại bị từ chối, bởi vì\n"
-"lệnh “git clone†tiếp theo sẽ không có tác dụng trong việc lấy\n"
+"lệnh 'git clone' tiếp theo sẽ không có tác dụng trong việc lấy\n"
"ra bất kỳ tập tin nào, dẫn đến hỗn loạn\n"
"\n"
-"Bạn có thể đặt biến cấu hình “receive.denyDeleteCurrent†thành\n"
-"“warn†hay “ignore†trong kho máy chủ để cho phép đẩy xóa nhánh\n"
+"Bạn có thể đặt biến cấu hình 'receive.denyDeleteCurrent' thành\n"
+"'warn' hay 'ignore' trong kho máy chủ để cho phép đẩy xóa nhánh\n"
"hiện tại của nó có hoặc không cảnh báo.\n"
"\n"
-"Äể chấm dứt lá»i nhắn này, bạn hãy đặt nó thành “refuseâ€."
+"Äể tắt lá»i nhắn này, bạn hãy đặt nó thành 'refuse'."
msgid "quiet"
msgstr "im lặng"
@@ -10160,6 +10417,9 @@ msgstr "bạn phải chỉ định thư mục"
msgid "git reflog [show] [<log-options>] [<ref>]"
msgstr "git reflog [show] [<các tùy chá»n>] [<tham chiếu>]"
+msgid "git reflog list"
+msgstr "git reflog list"
+
msgid ""
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
" [--rewrite] [--updateref] [--stale-fix]\n"
@@ -10185,6 +10445,10 @@ msgstr "git reflog exists <tham_chiếu>"
msgid "invalid timestamp '%s' given to '--%s'"
msgstr "dấu vết thá»i gian không hợp lệ '%s' Ä‘Æ°a cho '--%s'"
+#, c-format
+msgid "%s does not accept arguments: '%s'"
+msgstr "%s không nhận các đối số: '%s'"
+
msgid "do not actually prune any entries"
msgstr "thực tế không cắt ngắn bất kỳ mục tin nào"
@@ -10222,7 +10486,7 @@ msgstr "giới hạn xử lý với reflogs chỉ từ thư mục làm việc hi
#, c-format
msgid "Marking reachable objects..."
-msgstr "Äánh dấu các đối tượng tiếp cận được…"
+msgstr "Äánh dấu các đối tượng tiếp cận được..."
#, c-format
msgid "%s points nowhere!"
@@ -10260,10 +10524,10 @@ msgstr "git remote prune [-n | --dry-run] <tên>"
msgid ""
"git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]"
msgstr ""
-"git remote [-v | --verbose] update [-p | --prune] [(<nhóm> | <máy-chủ>)…]"
+"git remote [-v | --verbose] update [-p | --prune] [(<nhóm> | <máy-chủ>)...]"
msgid "git remote set-branches [--add] <name> <branch>..."
-msgstr "git remote set-branches [--add] <tên> <nhánh>…"
+msgstr "git remote set-branches [--add] <tên> <nhánh>..."
msgid "git remote get-url [--push] [--all] <name>"
msgstr "git remote set-url [--push] [--all] <tên>"
@@ -10281,10 +10545,10 @@ msgid "git remote add [<options>] <name> <url>"
msgstr "git remote add [<các tùy chá»n>] <tên> <url>"
msgid "git remote set-branches <name> <branch>..."
-msgstr "git remote set-branches <tên> <nhánh>…"
+msgstr "git remote set-branches <tên> <nhánh>..."
msgid "git remote set-branches --add <name> <branch>..."
-msgstr "git remote set-branches --add <tên> <nhánh>…"
+msgstr "git remote set-branches --add <tên> <nhánh>..."
msgid "git remote show [<options>] <name>"
msgstr "git remote show [<các tùy chá»n>] <tên>"
@@ -10293,7 +10557,7 @@ msgid "git remote prune [<options>] <name>"
msgstr "git remote prune [<các tùy chá»n>] <tên>"
msgid "git remote update [<options>] [<group> | <remote>]..."
-msgstr "git remote update [<các tùy chá»n>] [<nhóm> | <máy-chủ>]…"
+msgstr "git remote update [<các tùy chá»n>] [<nhóm> | <máy-chủ>]..."
#, c-format
msgid "Updating %s"
@@ -10301,27 +10565,28 @@ msgstr "Äang cập nhật %s"
#, c-format
msgid "Could not fetch %s"
-msgstr "Không thể lấy“%s†vá»"
+msgstr "Không thể lấy'%s' vá»"
msgid ""
"--mirror is dangerous and deprecated; please\n"
"\t use --mirror=fetch or --mirror=push instead"
msgstr ""
-"--mirror nguy hiểm và không dùng nữa; xin hãy\n"
+"--mirror nguy hiểm và không được dùng nữa; xin hãy\n"
"\t sá»­ dụng tùy chá»n --mirror=fetch hoặc --mirror=push để thay thế"
#, c-format
-msgid "unknown mirror argument: %s"
-msgstr "không hiểu tham số máy bản sao (mirror): %s"
+msgid "unknown --mirror argument: %s"
+msgstr "không hiểu tham số --mirror: %s"
msgid "fetch the remote branches"
msgstr "lấy vỠcác nhánh từ máy chủ"
-msgid "import all tags and associated objects when fetching"
-msgstr "nhập vào tất cả các đối tượng thẻ và thành phần liên quan khi lấy vá»"
-
-msgid "or do not fetch any tag at all (--no-tags)"
-msgstr "hoặc không lấy vỠbất kỳ thẻ nào (--no-tags)"
+msgid ""
+"import all tags and associated objects when fetching\n"
+"or do not fetch any tag at all (--no-tags)"
+msgstr ""
+"nhập vào tất cả các thẻ và đối tượng liên quan khi lấy vá»\n"
+"hoặc không nhận vỠmột thẻ nào cả (--no-tags)"
msgid "branch(es) to track"
msgstr "các nhánh để theo dõi"
@@ -10336,7 +10601,7 @@ msgid "specifying a master branch makes no sense with --mirror"
msgstr "Ä‘ang chỉ định má»™t nhánh master không hợp lý vá»›i tùy chá»n --mirror"
msgid "specifying branches to track makes sense only with fetch mirrors"
-msgstr "chỉ định những nhánh để theo dõi chỉ hợp lý vá»›i các “fetch mirrorâ€"
+msgstr "chỉ định những nhánh để theo dõi chỉ hợp lý với các 'fetch mirror'"
#, c-format
msgid "remote %s already exists."
@@ -10344,7 +10609,7 @@ msgstr "máy chủ %s đã tồn tại rồi."
#, c-format
msgid "Could not setup master '%s'"
-msgstr "Không thể cài đặt nhánh master “%sâ€"
+msgstr "Không thể cài đặt nhánh master '%s'"
#, c-format
msgid "more than one %s"
@@ -10352,7 +10617,7 @@ msgstr "nhiá»u hÆ¡n má»™t %s"
#, c-format
msgid "unhandled branch.%s.rebase=%s; assuming 'true'"
-msgstr "nhánh chÆ°a được quản lý.%s.rebase=%s; giả định là “trueâ€"
+msgstr "nhánh chưa được quản lý.%s.rebase=%s; giả định là 'true'"
#, c-format
msgid "Could not get fetch map for refspec %s"
@@ -10366,11 +10631,11 @@ msgstr "(xóa)"
#, c-format
msgid "could not set '%s'"
-msgstr "không thể đặt “%sâ€"
+msgstr "không thể đặt '%s'"
#, c-format
msgid "could not unset '%s'"
-msgstr "không thể thôi đặt “%sâ€"
+msgstr "không thể thôi đặt '%s'"
#, c-format
msgid ""
@@ -10380,15 +10645,15 @@ msgid ""
msgstr ""
"Cấu hình %s remote.pushDefault trong:\n"
"\t%s:%d\n"
-"bây giá» tên trên máy chủ không tồn tại “%sâ€"
+"bây giỠtên trên máy chủ không tồn tại '%s'"
#, c-format
msgid "No such remote: '%s'"
-msgstr "Không có máy chủ nào nhÆ° vậy: “%sâ€"
+msgstr "Không có máy chủ nào như vậy: '%s'"
#, c-format
msgid "Could not rename config section '%s' to '%s'"
-msgstr "Không thể đổi tên phần của cấu hình từ “%s†thành “%sâ€"
+msgstr "Không thể đổi tên phần của cấu hình từ '%s' thành '%s'"
#, c-format
msgid ""
@@ -10396,20 +10661,20 @@ msgid ""
"\t%s\n"
"\tPlease update the configuration manually if necessary."
msgstr ""
-"Không cập nhật “non-default fetch respecâ€\n"
+"Không cập nhật tham chiếu fetch không mặc định\n"
"\t%s\n"
-"\tXin hãy cập nhật phần cấu hình một cách thủ công nếu thấy cần thiết."
+"\tXin hãy cập nhật phần cấu hình một cách thủ công nếu cần."
msgid "Renaming remote references"
msgstr "Äổi tên các tham chiếu máy chủ"
#, c-format
msgid "deleting '%s' failed"
-msgstr "gặp lá»—i khi xóa “%sâ€"
+msgstr "gặp lỗi khi xóa '%s'"
#, c-format
msgid "creating '%s' failed"
-msgstr "gặp lá»—i khi tạo “%sâ€"
+msgstr "gặp lỗi khi tạo '%s'"
msgid ""
"Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
@@ -10424,7 +10689,7 @@ msgstr[0] ""
#, c-format
msgid "Could not remove config section '%s'"
-msgstr "Không thể gỡ bá» phần cấu hình “%sâ€"
+msgstr "Không thể gỡ bỠphần cấu hình '%s'"
#, c-format
msgid " new (next fetch will store in remotes/%s)"
@@ -10433,8 +10698,11 @@ msgstr " mới (lần lấy vỠtiếp theo sẽ lưu trong remotes/%s)"
msgid " tracked"
msgstr " được theo dõi"
+msgid " skipped"
+msgstr " được bỠqua"
+
msgid " stale (use 'git remote prune' to remove)"
-msgstr " cÅ© rích (dùng “git remote prune†để gỡ bá»)"
+msgstr " đã cÅ© (dùng 'git remote prune' để xoá bá»)"
msgid " ???"
msgstr " ???"
@@ -10546,15 +10814,15 @@ msgstr " (trạng thái không được yêu cầu)"
msgid " Local branch configured for 'git pull':"
msgid_plural " Local branches configured for 'git pull':"
-msgstr[0] " Những nhánh ná»™i bá»™ đã được cấu hình cho lệnh “git pullâ€:"
+msgstr[0] " Những nhánh nội bộ đã được cấu hình cho lệnh 'git pull':"
msgid " Local refs will be mirrored by 'git push'"
-msgstr " refs ná»™i bá»™ sẽ được phản chiếu bởi lệnh “git pushâ€"
+msgstr " refs nội bộ sẽ được phản chiếu bởi lệnh 'git push'"
#, c-format
msgid " Local ref configured for 'git push'%s:"
msgid_plural " Local refs configured for 'git push'%s:"
-msgstr[0] " Những tham chiếu ná»™i bá»™ được cấu hình cho lệnh “git pushâ€%s:"
+msgstr[0] " Những tham chiếu nội bộ được cấu hình cho lệnh 'git push'%s:"
msgid "set refs/remotes/<name>/HEAD according to remote"
msgstr "đặt refs/remotes/<tên>/HEAD cho phù hợp với máy chủ"
@@ -10609,7 +10877,7 @@ msgstr "cắt máy chủ sau khi lấy vá»"
#, c-format
msgid "No such remote '%s'"
-msgstr "Không có máy chủ nào có tên “%sâ€"
+msgstr "Không có máy chủ nào có tên '%s'"
msgid "add branch"
msgstr "thêm nhánh"
@@ -10625,10 +10893,10 @@ msgstr "trả vá» má»i URL"
#, c-format
msgid "no URLs configured for remote '%s'"
-msgstr "không có URL nào được cấu hình cho nhánh “%sâ€"
+msgstr "không có URL nào được cấu hình cho nhánh '%s'"
msgid "manipulate push URLs"
-msgstr "đẩy các “URL†bằng tay"
+msgstr "đẩy các 'URL' bằng tay"
msgid "add URL"
msgstr "thêm URL"
@@ -10665,35 +10933,45 @@ msgstr ""
msgid "could not start pack-objects to repack promisor objects"
msgstr ""
-"không thể lấy thông tin thống kê pack-objects để mà đóng gói lại các đối "
-"tượng hứa hẹn"
+"không thể lấy thông tin thống kê pack-objects để đóng gói lại các đối tượng "
+"promisor"
+
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "gặp lỗi khi đưa promisor object cho pack-objects"
msgid "repack: Expecting full hex object ID lines only from pack-objects."
msgstr ""
-"repack: Äang chỉ cần các dòng ID đối tượng dạng thập lục phân đầy dủ từ pack-"
-"objects."
+"repack: Äang chỉ cần các dòng ID đối tượng dạng hexa đầy đủ từ pack-objects."
msgid "could not finish pack-objects to repack promisor objects"
-msgstr "không thể hoàn tất pack-objects để đóng gói các đối tượng hứa hẹn"
+msgstr "không thể hoàn tất pack-objects để đóng gói các đối tượng promisor"
#, c-format
msgid "cannot open index for %s"
-msgstr "không thể mở mục lục cho “%sâ€"
+msgstr "không thể mở chỉ mục cho %s"
#, c-format
msgid "pack %s too large to consider in geometric progression"
-msgstr "gói %s là quá lá»›n để được xem là trong tiến trình hình há»c"
+msgstr "gói %s quá lớn để xem xét cấp số nhân"
#, c-format
msgid "pack %s too large to roll up"
-msgstr "gói %s là quá lớn để được cuộn lại"
+msgstr "gói %s quá lớn để cuộn lại"
#, c-format
msgid "could not open tempfile %s for writing"
msgstr "không thể mở tập tin tạm %s để ghi"
msgid "could not close refs snapshot tempfile"
-msgstr "không thể đóng tập tin tạm thá»i chụp nhanh các tham chiếu"
+msgstr "không thể đóng tập tin snapshot các tham chiếu"
+
+#, c-format
+msgid "could not remove stale bitmap: %s"
+msgstr "không thể xoá bỠbitmap đã cũ: %s"
+
+#, c-format
+msgid "pack prefix %s does not begin with objdir %s"
+msgstr "tiá»n tố gói '%s' không được bắt đầu vá»›i objdir '.%s'"
msgid "pack everything in a single pack"
msgstr "đóng gói má»i thứ trong má»™t gói Ä‘Æ¡n"
@@ -10708,8 +10986,8 @@ msgstr ""
msgid "approxidate"
msgstr "ngày ước tính"
-msgid "with -C, expire objects older than this"
-msgstr "với -C, các đối tượng hết hạn cũ hơn khoảng này"
+msgid "with --cruft, expire objects older than this"
+msgstr "với --cruft, đánh dấu hết hạn các đối tượng cũ hơn khoảng này"
msgid "remove redundant packs, and run git-prune-packed"
msgstr "xóa bỠcác gói dư thừa, và chạy git-prune-packed"
@@ -10727,7 +11005,7 @@ msgid "pass --local to git-pack-objects"
msgstr "chuyển --local cho git-pack-objects"
msgid "write bitmap index"
-msgstr "ghi mục lục ánh xạ"
+msgstr "ghi chỉ mục ánh xạ"
msgid "pass --delta-islands to git-pack-objects"
msgstr "chuyển --delta-islands cho git-pack-objects"
@@ -10739,7 +11017,7 @@ msgid "with -a, repack unreachable objects"
msgstr "vá»›i -a, đóng gói lại các đối tượng không thể Ä‘á»c được"
msgid "size of the window used for delta compression"
-msgstr "kích thÆ°á»›c cá»­a sổ được dùng cho nén “deltaâ€"
+msgstr "kích thước cửa sổ được dùng cho nén 'delta'"
msgid "bytes"
msgstr "byte"
@@ -10748,7 +11026,7 @@ msgid "same as the above, but limit memory size instead of entries count"
msgstr "giống như trên, nhưng giới hạn kích thước bộ nhớ hay vì số lượng"
msgid "limits the maximum delta depth"
-msgstr "giá»›i hạn Ä‘á»™ sâu tối Ä‘a của “deltaâ€"
+msgstr "giới hạn độ sâu tối đa của 'delta'"
msgid "limits the maximum number of threads"
msgstr "giới hạn số lượng tối đa tuyến trình"
@@ -10766,25 +11044,35 @@ msgid "find a geometric progression with factor <N>"
msgstr "tìm má»™t tiến trình hình há»c vá»›i hệ số <N>"
msgid "write a multi-pack index of the resulting packs"
-msgstr "ghi mục lục “multi-pack†của các gói kết quả"
+msgstr "ghi chỉ mục 'multi-pack' của các gói kết quả"
+
+msgid "pack prefix to store a pack containing pruned objects"
+msgstr "tiá»n tố của gói để lÆ°u gói gồm những đối tượng đã loại bá»"
+
+msgid "pack prefix to store a pack containing filtered out objects"
+msgstr "tiá»n tố của gói để lÆ°u gói gồm những đối tượng đã lá»c bá»"
msgid "cannot delete packs in a precious-objects repo"
-msgstr "không thể xóa các gói trong một kho đối_tượng_vĩ_đại"
+msgstr "không thể xóa các gói trong một kho đối tượng cần thiết"
+
+#, c-format
+msgid "option '%s' can only be used along with '%s'"
+msgstr "tuỳ chá»n '%s' chỉ có thể được dùng vá»›i '%s'"
msgid "Nothing new to pack."
-msgstr "Không có gì mới để mà đóng gói."
+msgstr "Không có gì mới để đóng gói."
#, c-format
-msgid "pack prefix %s does not begin with objdir %s"
-msgstr "tiá»n tố gói “%s†không được bắt đầu vá»›i objdir “.%sâ€"
+msgid "renaming pack to '%s' failed"
+msgstr "gặp lỗi khi đổi tên gói thành '%s'"
#, c-format
-msgid "missing required file: %s"
-msgstr "thiếu tập tin cần thiết: %s"
+msgid "pack-objects did not write a '%s' file for pack %s-%s"
+msgstr "pack-objects không ghi tập tin '%s' cho gói %s-%s"
#, c-format
msgid "could not unlink: %s"
-msgstr "không thể bỠliên kết: %s"
+msgstr "không thể unlink: %s"
msgid "git replace [-f] <object> <replacement>"
msgstr "git replace [-f] <đối-tượng> <thay-thế>"
@@ -10793,37 +11081,37 @@ msgid "git replace [-f] --edit <object>"
msgstr "git replace [-f] --edit <đối tượng>"
msgid "git replace [-f] --graft <commit> [<parent>...]"
-msgstr "git replace [-f] --graft <lần_chuyển_giao> [<cha_mẹ>…]"
+msgstr "git replace [-f] --graft <lần_chuyển_giao> [<cha_mẹ>...]"
msgid "git replace -d <object>..."
-msgstr "git replace -d <đối tượng>…"
+msgstr "git replace -d <đối tượng>..."
msgid "git replace [--format=<format>] [-l [<pattern>]]"
-msgstr "git replace [--format=<định_dạng>] [-l [<mẫu>]]"
+msgstr "git replace [--format=<định dạng>] [-l [<mẫu>]]"
#, c-format
msgid ""
"invalid replace format '%s'\n"
"valid formats are 'short', 'medium' and 'long'"
msgstr ""
-"định dạng thay thế không hợp lệ “%sâ€\n"
-"định dạng hợp lệ là “shortâ€, “medium†và “longâ€"
+"định dạng thay thế không hợp lệ '%s'\n"
+"định dạng hợp lệ là 'short', 'medium' và 'long'"
#, c-format
msgid "replace ref '%s' not found"
-msgstr "không tìm thấy tham chiếu thay thế “%sâ€"
+msgstr "không tìm thấy tham chiếu thay thế '%s'"
#, c-format
msgid "Deleted replace ref '%s'"
-msgstr "Äã xóa tham chiếu thay thế “%sâ€"
+msgstr "Äã xóa tham chiếu thay thế '%s'"
#, c-format
msgid "'%s' is not a valid ref name"
-msgstr "“%s†không phải tên tham chiếu hợp lệ"
+msgstr "'%s' không phải tên tham chiếu hợp lệ"
#, c-format
msgid "replace ref '%s' already exists"
-msgstr "tham chiếu thay thế “%s†đã tồn tại rồi"
+msgstr "tham chiếu thay thế '%s' đã tồn tại rồi"
#, c-format
msgid ""
@@ -10832,19 +11120,19 @@ msgid ""
"while '%s' points to a replacement object of type '%s'."
msgstr ""
"Các đối tượng phải cùng kiểu.\n"
-"“%s†chỉ đến đối tượng thay thế của kiểu “%sâ€\n"
-"trong khi “%s†chỉ đến đối tượng tham chiếu của kiểu “%sâ€."
+"'%s' chỉ đến đối tượng thay thế của kiểu '%s'\n"
+"trong khi '%s' chỉ đến đối tượng tham chiếu của kiểu '%s'."
#, c-format
msgid "unable to open %s for writing"
-msgstr "không thể mở “%s†để ghi"
+msgstr "không thể mở '%s' để ghi"
msgid "cat-file reported failure"
-msgstr "cat-file đã báo cáo gặp lá»—i nghiêm trá»ng"
+msgstr "cat-file đã báo nghiêm trá»ng"
#, c-format
msgid "unable to open %s for reading"
-msgstr "không thể mở “%s†để Ä‘á»c"
+msgstr "không thể mở '%s' để Ä‘á»c"
msgid "unable to spawn mktree"
msgstr "không thể sinh tiến trình con mktree"
@@ -10853,7 +11141,7 @@ msgid "unable to read from mktree"
msgstr "không thể Ä‘á»c từ mktree"
msgid "mktree reported failure"
-msgstr "mktree đã báo cáo gặp lá»—i nghiêm trá»ng"
+msgstr "mktree đã báo lá»—i nghiêm trá»ng"
msgid "mktree did not return an object name"
msgstr "mktree đã không trả vỠmột tên đối tượng"
@@ -10874,46 +11162,46 @@ msgstr "việc sửa tập tin đối tượng gặp lỗi"
#, c-format
msgid "new object is the same as the old one: '%s'"
-msgstr "đối tượng má»›i là giống vá»›i cái cÅ©: “%sâ€"
+msgstr "đối tượng mới là giống với cái cũ: '%s'"
#, c-format
msgid "could not parse %s as a commit"
-msgstr "không thể phân tích %s như là một lần chuyển giao"
+msgstr "không thể Ä‘á»c %s nhÆ° là má»™t lần chuyển giao"
#, c-format
msgid "bad mergetag in commit '%s'"
-msgstr "thẻ hòa trá»™n sai trong lần chuyển giao “%sâ€"
+msgstr "thẻ hòa trộn sai trong lần chuyển giao '%s'"
#, c-format
msgid "malformed mergetag in commit '%s'"
-msgstr "thẻ hòa trá»™n không đúng dạng ở lần chuyển giao “%sâ€"
+msgstr "thẻ hòa trá»™n bất thÆ°á»ng dạng ở lần chuyển giao '%s'"
#, c-format
msgid ""
"original commit '%s' contains mergetag '%s' that is discarded; use --edit "
"instead of --graft"
msgstr ""
-"lần chuyển giao gốc “%s†có chứa thẻ hòa trá»™n “%s†cái mà bị loại bá»; dùng "
-"tùy chá»n --edit thay cho --graft"
+"lần chuyển giao gốc '%s' có chứa thẻ hòa trá»™n '%s' đã bị loại bá»; dùng tùy "
+"chá»n --edit thay cho --graft"
#, c-format
msgid "the original commit '%s' has a gpg signature"
-msgstr "lần chuyển giao gốc “%s†có chữ ký GPG"
+msgstr "lần chuyển giao gốc '%s' có chữ ký GPG"
msgid "the signature will be removed in the replacement commit!"
msgstr "chữ ký sẽ được bỠđi trong lần chuyển giao thay thế!"
#, c-format
msgid "could not write replacement commit for: '%s'"
-msgstr "không thể ghi lần chuyển giao thay thế cho: “%sâ€"
+msgstr "không thể ghi lần chuyển giao thay thế cho: '%s'"
#, c-format
msgid "graft for '%s' unnecessary"
-msgstr "graft cho “%s†không cần thiết"
+msgstr "graft cho '%s' không cần thiết"
#, c-format
msgid "new commit is the same as the old one: '%s'"
-msgstr "lần chuyển giao má»›i là giống vá»›i cái cÅ©: “%sâ€"
+msgstr "lần chuyển giao mới là giống với cái cũ: '%s'"
#, c-format
msgid ""
@@ -10974,19 +11262,85 @@ msgstr "--convert-graft-file không nhận đối số"
msgid "only one pattern can be given with -l"
msgstr "chỉ má»™t mẫu được chỉ ra vá»›i tùy chá»n -l"
-msgid "git rerere [clear | forget <path>... | status | remaining | diff | gc]"
+msgid "need some commits to replay"
+msgstr "cần các chuyển giao để phát lại"
+
+msgid "--onto and --advance are incompatible"
+msgstr "--onto và --advance xung khắc"
+
+msgid "all positive revisions given must be references"
+msgstr "má»i Ä‘iểm xét duyệt cá»™ng thêm phải là tên tham chiếu"
+
+msgid "argument to --advance must be a reference"
+msgstr "tham số cho --advance phải là tham chiếu"
+
+msgid ""
+"cannot advance target with multiple sources because ordering would be ill-"
+"defined"
+msgstr "không thể đẩy nhánh vá»›i nhiá»u nguồn vì thứ tá»± không xác định"
+
+msgid ""
+"cannot implicitly determine whether this is an --advance or --onto operation"
+msgstr "không thể tự xác định là thực hiện --advance hay --onto"
+
+msgid ""
+"cannot advance target with multiple source branches because ordering would "
+"be ill-defined"
+msgstr "không thể đẩy nhánh vá»›i nhiá»u nhánh nguồn vì thứ tá»± không xác định"
+
+msgid "cannot implicitly determine correct base for --onto"
+msgstr "không thể tự xác định gốc thực hiện --onto"
+
+msgid ""
+"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
+"<branch>) <revision-range>..."
+msgstr ""
+"(TRONG QUà TRÌNH THỬ NGHIỆM!) git replay ([--contained] --onto <gốc mới> | "
+"--advance <nhánh>) <khoảng-xét-duyệt>..."
+
+msgid "make replay advance given branch"
+msgstr "đẩy nhánh này trong khi phát lại"
+
+msgid "replay onto given commit"
+msgstr "phát lại vào commit này"
+
+msgid "advance all branches contained in revision-range"
+msgstr "đẩy tất cả các nhánh có trong khoảng-xét-duyệt "
+
+msgid "option --onto or --advance is mandatory"
+msgstr "tuỳ chá»n --onto hoặc --advance là bắt buá»™c"
+
+#, c-format
+msgid ""
+"some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
+"will be forced"
+msgstr ""
+"má»™t số tuỳ chá»n duyệt qua Ä‘iểm xét duyệt sẽ bị bá» qua do bit '%s' trong "
+"'struct rev_info' bị ép bật/tắt"
+
+msgid "error preparing revisions"
+msgstr "gặp lỗi khi chuẩn bị các điểm xét duyệt"
+
+msgid "replaying down to root commit is not supported yet!"
+msgstr "chưa hỗ trợ phát lại đến lần chuyển giao gốc!"
+
+msgid "replaying merge commits is not supported yet!"
+msgstr "chưa hỗ trợ phát lại các lần hoà trộn!"
+
+msgid ""
+"git rerere [clear | forget <pathspec>... | diff | status | remaining | gc]"
msgstr ""
-"git rerere [clear | forget <Ä‘Æ°á»ng dẫn>… | status | remaining | diff | gc]"
+"git rerere [clear | forget <Ä‘Æ°á»ng dẫn>... | diff | status | remaining | gc]"
msgid "register clean resolutions in index"
-msgstr "sổ ghi dá»n sạch các phân giải trong bản mục lục"
+msgstr "ghi lại các lần giải quyết ổn thoả xung đột trong chỉ mục"
msgid "'git rerere forget' without paths is deprecated"
-msgstr "“git rerere forget†mà không có các Ä‘Æ°á»ng dẫn là đã lạc hậu"
+msgstr "không còn dùng 'git rerere forget' mà không có các Ä‘Æ°á»ng dẫn"
#, c-format
msgid "unable to generate diff for '%s'"
-msgstr "không thể tạo khác biệt cho “%sâ€"
+msgstr "không thể tạo diff cho '%s'"
msgid ""
"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"
@@ -10994,7 +11348,7 @@ msgstr ""
"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"
msgid "git reset [-q] [<tree-ish>] [--] <pathspec>..."
-msgstr "git reset [-q] [<tree-ish>] [--] <đặc/tả/Ä‘Æ°á»ng/dẫn>…"
+msgstr "git reset [-q] [<tree-ish>] [--] <đặc/tả/Ä‘Æ°á»ng/dẫn>..."
msgid ""
"git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]"
@@ -11002,7 +11356,7 @@ msgstr ""
"git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]"
msgid "git reset --patch [<tree-ish>] [--] [<pathspec>...]"
-msgstr "git reset --patch [<tree-ish>] [--] [<đặc/tả/Ä‘Æ°á»ng/dẫn>…]"
+msgstr "git reset --patch [<tree-ish>] [--] [<đặc/tả/Ä‘Æ°á»ng/dẫn>...]"
msgid "mixed"
msgstr "pha trá»™n"
@@ -11041,16 +11395,16 @@ msgid "be quiet, only report errors"
msgstr "làm việc ở chế độ im lặng, chỉ hiển thị khi có lỗi"
msgid "skip refreshing the index after reset"
-msgstr "bỠqua làm tươi mục lục sau khi đặt lại"
+msgstr "bỠqua làm mới chỉ mục sau khi reset"
msgid "reset HEAD and index"
-msgstr "đặt lại (reset) HEAD và bảng mục lục"
+msgstr "đặt lại HEAD và chỉ mục"
msgid "reset only HEAD"
-msgstr "chỉ đặt lại (reset) HEAD"
+msgstr "chỉ đặt lại HEAD"
msgid "reset HEAD, index and working tree"
-msgstr "đặt lại HEAD, bảng mục lục và cây làm việc"
+msgstr "đặt lại HEAD, chỉ mục và cây làm việc"
msgid "reset HEAD but keep local changes"
msgstr "đặt lại HEAD nhưng giữ lại các thay đổi nội bộ"
@@ -11060,16 +11414,16 @@ msgstr "chỉ ghi lại những Ä‘Æ°á»ng dẫn thá»±c sá»± sẽ được thêm
#, c-format
msgid "Failed to resolve '%s' as a valid revision."
-msgstr "Gặp lỗi khi phân giải “%s†như là điểm xét duyệt hợp lệ."
+msgstr "Gặp lỗi khi phân giải '%s' thành điểm xét duyệt hợp lệ."
#, c-format
msgid "Failed to resolve '%s' as a valid tree."
-msgstr "Gặp lỗi khi phân giải “%s†như là một cây (tree) hợp lệ."
+msgstr "Gặp lỗi khi phân giải '%s' như là một cây (tree) hợp lệ."
msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
msgstr ""
-"--mixed vá»›i các Ä‘Æ°á»ng dẫn không còn dùng nữa; hãy thay thế bằng lệnh “git "
-"reset -- </các/Ä‘Æ°á»ng/dẫn>â€."
+"không cho dùng --mixed vá»›i các Ä‘Æ°á»ng dẫn nữa; hãy thay thế bằng lệnh 'git "
+"reset -- </các/Ä‘Æ°á»ng/dẫn>'."
#, c-format
msgid "Cannot do %s reset with paths."
@@ -11077,7 +11431,7 @@ msgstr "Không thể thá»±c hiện lệnh %s reset vá»›i các Ä‘Æ°á»ng dẫn."
#, c-format
msgid "%s reset is not allowed in a bare repository"
-msgstr "%s reset không được phép trên kho thuần"
+msgstr "%s reset không được phép trên kho chứa bare"
msgid "Unstaged changes after reset:"
msgstr "Những thay đổi được Ä‘Æ°a ra khá»i bệ phóng sau khi reset:"
@@ -11087,21 +11441,25 @@ msgid ""
"It took %.2f seconds to refresh the index after reset. You can use\n"
"'--no-refresh' to avoid this."
msgstr ""
-"Việc này cần %.2f giây để làm tươi mới mục lục sau khi đặt lại. Bạn có thể "
+"Việc này cần %.2f giây để làm tươi mới chỉ mục sau khi đặt lại. Bạn có thể "
"sử dụng\n"
-"“--no-refresh†tránh Ä‘iá»u này."
+"'--no-refresh' tránh Ä‘iá»u này."
#, c-format
msgid "Could not reset index file to revision '%s'."
-msgstr "Không thể đặt lại (reset) bảng mục lục thành Ä‘iểm xét duyệt “%sâ€."
+msgstr "Không thể đặt lại (reset) chỉ mục thành điểm xét duyệt '%s'."
msgid "Could not write new index file."
-msgstr "Không thể ghi tập tin lưu bảng mục lục mới."
+msgstr "Không thể ghi tập tin chỉ mục mới."
#, c-format
msgid "unable to get disk usage of %s"
msgstr "không thể dung lượng đĩa đã dùng của %s"
+#, c-format
+msgid "invalid value for '%s': '%s', the only allowed format is '%s'"
+msgstr "giá trị không hợp lệ cho '%s': '%s', chỉ cho phép định dạng là '%s'"
+
msgid "rev-list does not support display of notes"
msgstr "rev-list không hỗ trợ hiển thị các ghi chú"
@@ -11110,22 +11468,25 @@ msgid "marked counting and '%s' cannot be used together"
msgstr "đánh dấu để đếm và '%s' không thể dùng cùng nhau"
msgid "git rev-parse --parseopt [<options>] -- [<args>...]"
-msgstr "git rev-parse --parseopt [<các tùy chá»n>] -- [<các tham số>…]"
+msgstr "git rev-parse --parseopt [<các tùy chá»n>] -- [<các tham số>...]"
msgid "keep the `--` passed as an arg"
-msgstr "giữ lại “--†chuyển sang làm tham số"
+msgstr "giữ lại '--' chuyển sang làm tham số"
msgid "stop parsing after the first non-option argument"
-msgstr "dừng phân tích sau đối số đầu tiên không có tùy chá»n"
+msgstr "dừng Ä‘á»c sau đối số đầu tiên không có tùy chá»n"
msgid "output in stuck long form"
msgstr "kết xuất trong định dạng gậy dài"
msgid "premature end of input"
-msgstr "đầu vào chấm dứt bất thÆ°á»ng"
+msgstr "đầu vào kết thúc bất thÆ°á»ng"
msgid "no usage string given before the `--' separator"
-msgstr "không có chuá»—i cách dùng nào được Ä‘Æ°a ra trÆ°á»›c dấu phân cách “--â€"
+msgstr "không có chuỗi cách dùng nào được đưa ra trước dấu phân cách '--'"
+
+msgid "missing opt-spec before option flags"
+msgstr "thiếu opt-spec trÆ°á»›c các tuỳ chá»n"
msgid "Needed a single revision"
msgstr "Cần một điểm xét duyệt đơn"
@@ -11137,9 +11498,9 @@ msgid ""
"\n"
"Run \"git rev-parse --parseopt -h\" for more information on the first usage."
msgstr ""
-"git rev-parse --parseopt [<các tùy chá»n>] -- [<các đối số>…]\n"
-" hoặc: git rev-parse --sq-quote [<đ.số>…]\n"
-" hoặc: git rev-parse [<các tùy chá»n>] [<Ä‘.số>…]\n"
+"git rev-parse --parseopt [<các tùy chá»n>] -- [<các đối số>...]\n"
+" hoặc: git rev-parse --sq-quote [<đ.số>...]\n"
+" hoặc: git rev-parse [<các tùy chá»n>] [<Ä‘.số>...]\n"
"\n"
"Chạy lệnh \"git rev-parse --parseopt -h\" để có thêm thông tin vỠcách dùng."
@@ -11148,7 +11509,7 @@ msgstr "--resolve-git-dir cần một tham số"
#, c-format
msgid "not a gitdir '%s'"
-msgstr "không phải má»™t thÆ° mục git “%sâ€"
+msgstr "không phải một thư mục git '%s'"
msgid "--git-path requires an argument"
msgstr "--git-path cần một tham số"
@@ -11169,6 +11530,13 @@ msgstr "--default cần một tham số"
msgid "--prefix requires an argument"
msgstr "--prefix cần một tham số"
+msgid "no object format specified"
+msgstr "không chỉ ra định dạng đối tượng"
+
+#, c-format
+msgid "unsupported object format: %s"
+msgstr "không hỗ trợ định dạng đối tượng: %s"
+
#, c-format
msgid "unknown mode for --abbrev-ref: %s"
msgstr "không hiểu chế độ cho --abbrev-ref: %s"
@@ -11176,25 +11544,36 @@ msgstr "không hiểu chế độ cho --abbrev-ref: %s"
msgid "this operation must be run in a work tree"
msgstr "thao tác này phải được thực hiện trong thư mục làm việc"
+msgid "Could not read the index"
+msgstr "Không thể Ä‘á»c chỉ mục"
+
#, c-format
msgid "unknown mode for --show-object-format: %s"
msgstr "không hiểu chế độ cho --show-object-format: %s"
-msgid "git revert [<options>] <commit-ish>..."
-msgstr "git revert [<các tùy chá»n>] <commit-ish>…"
+msgid ""
+"git revert [--[no-]edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] "
+"<commit>..."
+msgstr ""
+"git revert [--[no-]edit] [-n] [-m <parent-number>] [-s] [-S[<keyid>]] "
+"<commit>..."
-msgid "git revert <subcommand>"
-msgstr "git revert <lệnh-con>"
+msgid "git revert (--continue | --skip | --abort | --quit)"
+msgstr "git revert (--continue | --skip | --abort | --quit)"
-msgid "git cherry-pick [<options>] <commit-ish>..."
-msgstr "git cherry-pick [<các tùy chá»n>] <commit-ish>…"
+msgid ""
+"git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]\n"
+" [-S[<keyid>]] <commit>..."
+msgstr ""
+"git cherry-pick [--edit] [-n] [-m <parent-number>] [-s] [-x] [--ff]\n"
+" [-S[<keyid>]] <commit>..."
-msgid "git cherry-pick <subcommand>"
-msgstr "git cherry-pick <lệnh-con>"
+msgid "git cherry-pick (--continue | --skip | --abort | --quit)"
+msgstr "git cherry-pick (--continue | --skip | --abort | --quit)"
#, c-format
msgid "option `%s' expects a number greater than zero"
-msgstr "tùy chá»n “%s†cần má»™t giá trị bằng số lá»›n hÆ¡n không"
+msgstr "tùy chá»n '%s' cần má»™t giá trị bằng số lá»›n hÆ¡n không"
#, c-format
msgid "%s: %s cannot be used with %s"
@@ -11239,8 +11618,8 @@ msgstr "cấm khởi tạo lần chuyển giao trống rỗng"
msgid "allow commits with empty messages"
msgstr "chấp nhận chuyển giao mà không ghi chú gì"
-msgid "keep redundant, empty commits"
-msgstr "giữ lại các lần chuyển giao dư thừa, rỗng"
+msgid "deprecated: use --empty=keep instead"
+msgstr "đã lạc hậu: hãy dùng --empty=keep"
msgid "use the 'reference' format to refer to commits"
msgstr "dùng định dạng 'tham chiếu' để quy cho các lần chuyển giao"
@@ -11251,8 +11630,14 @@ msgstr "hoàn nguyên gặp lỗi"
msgid "cherry-pick failed"
msgstr "cherry-pick gặp lỗi"
-msgid "git rm [<options>] [--] <file>..."
-msgstr "git rm [<các tùy chá»n>] [--] <tập-tin>…"
+msgid ""
+"git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch]\n"
+" [--quiet] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
+" [--] [<pathspec>...]"
+msgstr ""
+"git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch]\n"
+" [--quiet] [--pathspec-from-file=<tập tin> [--pathspec-file-nul]]\n"
+" [--] [<đặc/tả/Ä‘Æ°á»ng/dẫn>...]]"
msgid ""
"the following file has staged content different from both the\n"
@@ -11273,7 +11658,7 @@ msgstr ""
msgid "the following file has changes staged in the index:"
msgid_plural "the following files have changes staged in the index:"
-msgstr[0] "các tập tin sau đây có thay đổi trạng thái trong bảng mục lục:"
+msgstr[0] "các tập tin sau đây có thay đổi trạng thái trong chỉ mục:"
msgid ""
"\n"
@@ -11290,13 +11675,13 @@ msgid "do not list removed files"
msgstr "không liệt kê các tập tin đã gỡ bá»"
msgid "only remove from the index"
-msgstr "chỉ gỡ bỠtừ mục lục"
+msgstr "chỉ gỡ bỠtừ chỉ mục"
msgid "override the up-to-date check"
msgstr "ghi đè lên kiểm tra cập nhật"
msgid "allow recursive removal"
-msgstr "cho phép gỡ bỠđệ qui"
+msgstr "cho phép gỡ bỠđệ quy"
msgid "exit with a zero status even if nothing matched"
msgstr "thoát ra với trạng thái khác không thậm chí nếu không có gì khớp"
@@ -11310,7 +11695,7 @@ msgstr ""
#, c-format
msgid "not removing '%s' recursively without -r"
-msgstr "không thể gỡ bỠ“%s†má»™t cách đệ qui mà không có tùy chá»n -r"
+msgstr "không thể gỡ bá» '%s' má»™t cách đệ quy mà không có tùy chá»n -r"
#, c-format
msgid "git rm: unable to remove %s"
@@ -11320,37 +11705,43 @@ msgid ""
"git send-pack [--mirror] [--dry-run] [--force]\n"
" [--receive-pack=<git-receive-pack>]\n"
" [--verbose] [--thin] [--atomic]\n"
+" [--[no-]signed | --signed=(true|false|if-asked)]\n"
" [<host>:]<directory> (--all | <ref>...)"
msgstr ""
"git send-pack [--mirror] [--dry-run] [--force]\n"
" [--receive-pack=<git-receive-pack>]\n"
" [--verbose] [--thin] [--atomic]\n"
-" [<host>:]<thư mục> (--all | <tham chiếu>…)"
+" [--[no-]signed | --signed=(true|false|if-asked)]\n"
+" [<host>:]<thư mục> (--all | <tham chiếu>...)"
msgid "remote name"
msgstr "tên máy dịch vụ"
+msgid "push all refs"
+msgstr "đẩy tất cả các tham chiếu"
+
msgid "use stateless RPC protocol"
msgstr "dùng giao thức RPC không ổn định"
msgid "read refs from stdin"
-msgstr "Ä‘á»c tham chiếu từ đầu vào tiêu chuẩn"
+msgstr "Ä‘á»c tham chiếu từ stdin"
msgid "print status from remote helper"
msgstr "in các trạng thái từ phần hướng dẫn trên máy dịch vụ"
msgid "git shortlog [<options>] [<revision-range>] [[--] <path>...]"
-msgstr "git shortlog [<các tùy chá»n>] [<vùng-xét-duyệt>] [[--] [<Ä‘Æ°á»ng/dẫn>…]]"
+msgstr ""
+"git shortlog [<các tùy chá»n>] [<vùng-xét-duyệt>] [[--] [<Ä‘Æ°á»ng/dẫn>...]]"
msgid "git log --pretty=short | git shortlog [<options>]"
msgstr "git log --pretty=short | git shortlog [<các tùy chá»n>]"
msgid "using multiple --group options with stdin is not supported"
-msgstr ""
-"việc dùng nhiá»u tùy chá»n --group vá»›i đầu ra tiêu chuẩn là không được há»— trợ"
+msgstr "việc dùng nhiá»u tùy chá»n --group vá»›i stdin là không được há»— trợ"
-msgid "using --group=trailer with stdin is not supported"
-msgstr "việc dùng --group=trailer với đầu ra tiêu chuẩn là không được hỗ trợ"
+#, c-format
+msgid "using %s with stdin is not supported"
+msgstr "không hỗ trợ dùng %s cùng stdin"
#, c-format
msgid "unknown group type: %s"
@@ -11387,15 +11778,17 @@ msgid ""
"git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n"
" [--current] [--color[=<when>] | --no-color] [--sparse]\n"
" [--more=<n> | --list | --independent | --merge-base]\n"
-" [--no-name | --sha1-name] [--topics] [(<rev> | <glob>)...]"
+" [--no-name | --sha1-name] [--topics]\n"
+" [(<rev> | <glob>)...]"
msgstr ""
"git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n"
" [--current] [--color[=<when>] | --no-color] [--sparse]\n"
" [--more=<n> | --list | --independent | --merge-base]\n"
-" [--no-name | --sha1-name] [--topics] [(<rev> | <glob>)…]"
+" [--no-name | --sha1-name] [--topics]\n"
+" [(<rev> | <glob>)...]"
msgid "git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]"
-msgstr "git show-branch (-g | --reflog)[=<n>[,<ná»n>]] [--list] [<ref>]"
+msgstr "git show-branch (-g | --reflog)[=<n>[,<base>]] [--list] [<ref>]"
#, c-format
msgid "ignoring %s; cannot handle more than %d ref"
@@ -11413,7 +11806,7 @@ msgid "show remote-tracking branches"
msgstr "hiển thị các nhánh remote-tracking"
msgid "color '*!+-' corresponding to the branch"
-msgstr "màu “*!+-†tương ứng với nhánh"
+msgstr "màu '*!+-' tương ứng với nhánh"
msgid "show <n> more commits after the common ancestor"
msgstr "hiển thị thêm <n> lần chuyển giao sau cha mẹ chung"
@@ -11431,7 +11824,7 @@ msgid "name commits with their object names"
msgstr "đặt tên các lần chuyển giao bằng các tên của đối tượng của chúng"
msgid "show possible merge bases"
-msgstr "hiển thị má»i cÆ¡ sở có thể dùng để hòa trá»™n"
+msgstr "hiển thị má»i gốc hòa trá»™n khả dụng"
msgid "show refs unreachable from any other ref"
msgstr "hiển thị các tham chiếu không thể được Ä‘á»c bởi bất kỳ tham chiếu khác"
@@ -11443,7 +11836,7 @@ msgid "show only commits not on the first branch"
msgstr "chỉ hiển thị các lần chuyển giao không nằm trên nhánh đầu tiên"
msgid "show merges reachable from only one tip"
-msgstr "hiển thị các lần hòa trá»™n có thể Ä‘á»c được chỉ từ má»™t đầu mút"
+msgstr "hiển thị các lần hòa trá»™n có thể Ä‘á»c được chỉ từ má»™t đỉnh"
msgid "topologically sort, maintaining date order where possible"
msgstr "sắp xếp hình thái há»c, bảo trì thứ tá»± ngày nếu có thể"
@@ -11452,7 +11845,7 @@ msgid "<n>[,<base>]"
msgstr "<n>[,<cơ_sở>]"
msgid "show <n> most recent ref-log entries starting at base"
-msgstr "hiển thị <n> các mục “ref-log†gần nhất kể từ ná»n (base)"
+msgstr "hiển thị <n> các mục 'ref-log' gần nhất kể từ ná»n (base)"
msgid "no branches given, and HEAD is not valid"
msgstr "chưa đưa ra nhánh, và HEAD không hợp lệ"
@@ -11476,7 +11869,7 @@ msgstr[0] "không thể xá»­ lý nhiá»u hÆ¡n %d Ä‘iểm xét duyệt."
#, c-format
msgid "'%s' is not a valid ref."
-msgstr "“%s†không phải tham chiếu hợp lệ."
+msgstr "'%s' không phải tham chiếu hợp lệ."
#, c-format
msgid "cannot find commit %s (%s)"
@@ -11489,61 +11882,83 @@ msgid "Unknown hash algorithm"
msgstr "Không hiểu thuật toán băm dữ liệu"
msgid ""
-"git show-ref [-q | --quiet] [--verify] [--head] [-d | --dereference] [-s | --"
-"hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [<pattern>...]"
+"git show-ref [--head] [-d | --dereference]\n"
+" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n"
+" [--heads] [--] [<pattern>...]"
msgstr ""
-"git show-ref [-q | --quiet] [--verify] [--head] [-d | --dereference] [-s | --"
-"hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [<mẫu>…]"
+"git show-ref [--head] [-d | --dereference]\n"
+" [-s | --hash[=<n>]] [--abbrev[=<n>]] [--tags]\n"
+" [--heads] [--] [<mẫu>...]"
+
+msgid ""
+"git show-ref --verify [-q | --quiet] [-d | --dereference]\n"
+" [-s | --hash[=<n>]] [--abbrev[=<n>]]\n"
+" [--] [<ref>...]"
+msgstr ""
+"git show-ref --verify [-q | --quiet] [-d | --dereference]\n"
+" [-s | --hash[=<n>]] [--abbrev[=<n>]]\n"
+" [--] [<mẫu>...]"
msgid "git show-ref --exclude-existing[=<pattern>]"
msgstr "git show-ref --exclude-existing[=<mẫu>]"
+msgid "git show-ref --exists <ref>"
+msgstr "git show-ref --exists <tham_chiếu>"
+
+msgid "reference does not exist"
+msgstr "tham chiếu không tồn tại"
+
+msgid "failed to look up reference"
+msgstr "gặp lỗi khi tìm tham chiếu"
+
msgid "only show tags (can be combined with heads)"
msgstr "chỉ hiển thị thẻ (có thể tổ hợp cùng với đầu)"
msgid "only show heads (can be combined with tags)"
msgstr "chỉ hiển thị đầu (có thể tổ hợp cùng với thẻ)"
+msgid "check for reference existence without resolving"
+msgstr "kiểm tra tồn tại tham chiếu nhưng không phân giải"
+
msgid "stricter reference checking, requires exact ref path"
-msgstr ""
-"việc kiểm tra tham chiếu chính xác, đòi há»i chính xác Ä‘Æ°á»ng dẫn tham chiếu"
+msgstr "kiểm tra tham chiếu chính xác, đòi há»i chính xác Ä‘Æ°á»ng dẫn tham chiếu"
msgid "show the HEAD reference, even if it would be filtered out"
msgstr "hiển thị tham chiếu HEAD, ngay cả khi nó đã được lá»c ra"
msgid "dereference tags into object IDs"
-msgstr "bãi bỠtham chiếu các thẻ thành ra các ID đối tượng"
+msgstr "giải tham chiếu các thẻ thành các ID đối tượng"
msgid "only show SHA1 hash using <n> digits"
msgstr "chỉ hiển thị mã băm SHA1 sử dụng <n> chữ số"
msgid "do not print results to stdout (useful with --verify)"
-msgstr ""
-"không hiển thị kết quả ra đầu ra chuẩn (stdout) (chỉ hữu dụng với --verify)"
+msgstr "không hiển thị kết quả ra stdout (hữu dụng khi dùng cùng --verify)"
msgid "show refs from stdin that aren't in local repository"
-msgstr ""
-"hiển thị các tham chiếu từ đầu vào tiêu chuẩn (stdin) cái mà không ở kho nội "
-"bá»™"
+msgstr "hiển thị các tham chiếu từ stdin mà không ở kho nội bộ"
-msgid "git sparse-checkout (init|list|set|add|reapply|disable) <options>"
-msgstr "git sparse-checkout (init|list|set|add|reapply|disable) <các-tùy-chá»n>"
+msgid ""
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<options>]"
+msgstr ""
+"git sparse-checkout (init | list | set | add | reapply | disable | check-"
+"rules) [<các-tùy-chá»n>]"
msgid "this worktree is not sparse"
-msgstr "cây làm việc này không phải là sparse"
+msgstr "cây làm việc này không thưa"
msgid "this worktree is not sparse (sparse-checkout file may not exist)"
msgstr ""
-"không thể phân tích cú pháp cây làm việc này (tập tin sparse-checkout có lẽ "
-"không tồn tại)"
+"cây làm việc này không thưa (tập tin sparse-checkout có lẽ không tồn tại)"
#, c-format
msgid ""
"directory '%s' contains untracked files, but is not in the sparse-checkout "
"cone"
msgstr ""
-"thư mục “%s†có chứa các tập tin chưa được theo dõi, nhưng lại không trong "
-"“sparse-checkout coneâ€"
+"thư mục '%s' có chứa các tập tin chưa được theo dõi, nhưng không nằm trong "
+"'sparse-checkout cone' (vùng checkout thưa)"
#, c-format
msgid "failed to remove directory '%s'"
@@ -11556,35 +11971,35 @@ msgid "failed to initialize worktree config"
msgstr "gặp lỗi khi khởi tạo cấu hình cây làm việc"
msgid "failed to modify sparse-index config"
-msgstr "gặp lỗi khi sửa cấu hình \"sparse-index\""
+msgstr "gặp lỗi khi sửa cấu hình sparse-index"
msgid "initialize the sparse-checkout in cone mode"
msgstr "khởi tạo sparse-checkout trong chế độ nón"
msgid "toggle the use of a sparse index"
-msgstr "bật tắt việc sử dụng một \"sparse index\""
+msgstr "bật tắt việc sử dụng sparse index"
#, c-format
msgid "unable to create leading directories of %s"
-msgstr "không thể tạo các thÆ° mục dẫn đầu của “%sâ€"
+msgstr "không thể tạo các thư mục dẫn đầu của '%s'"
#, c-format
msgid "failed to open '%s'"
-msgstr "gặp lá»—i khi mở “%sâ€"
+msgstr "gặp lỗi khi mở '%s'"
#, c-format
msgid "could not normalize path %s"
-msgstr "không thể thÆ°á»ng hóa Ä‘Æ°á»ng dẫn “%sâ€"
+msgstr "không thể thÆ°á»ng hóa Ä‘Æ°á»ng dẫn '%s'"
#, c-format
msgid "unable to unquote C-style string '%s'"
-msgstr "không thể bá» trích dẫn chuá»—i kiểu C “%sâ€"
+msgstr "không thể bỠtrích dẫn chuỗi kiểu C '%s'"
msgid "unable to load existing sparse-checkout patterns"
msgstr "không thể tải các mẫu sparse-checkout"
msgid "existing sparse-checkout patterns do not use cone mode"
-msgstr "đặt các mẫu sparse-checkout sẵn có không sử dụng chế độ cone"
+msgstr "các mẫu sparse-checkout sẵn có không sử dụng chế độ cone"
msgid "please run from the toplevel directory in non-cone mode"
msgstr "vui lòng chạy từ thư mục mức cao nhất trong chế độ non-cone"
@@ -11619,8 +12034,8 @@ msgid ""
"pass a leading slash before paths such as '%s' if you want a single file "
"(see NON-CONE PROBLEMS in the git-sparse-checkout manual)."
msgstr ""
-"chuyển má»™t dấu xổ chéo dẫn đầu Ä‘Æ°á»ng dẫn nhÆ° là '%s' nếu bạn muốn má»™t tập "
-"tin đơn (xem NON-CONE PROBLEMS trong hướng dẫn sử dụng git-sparse-checkout)."
+"dùng dấu gạch chéo dẫn đầu trÆ°á»›c Ä‘Æ°á»ng dẫn nhÆ° '%s' nếu bạn muốn má»™t tập tin "
+"đơn lẻ (xem NON-CONE PROBLEMS trong hướng dẫn sử dụng git-sparse-checkout)."
msgid "git sparse-checkout add [--skip-checks] (--stdin | <patterns>)"
msgstr "git sparse-checkout add [--skip-checks] (--stdin | <các mẫu>)"
@@ -11628,11 +12043,11 @@ msgstr "git sparse-checkout add [--skip-checks] (--stdin | <các mẫu>)"
msgid ""
"skip some sanity checks on the given paths that might give false positives"
msgstr ""
-"bá» qua má»™t số kiểm tra đúng mục trên Ä‘Æ°á»ng dẫn đã cho cái mà có thể Ä‘Æ°a ra "
-"xác thực sai"
+"bá» qua má»™t số tiá»n kiểm tra có thể không cho kết quả đúng trên các Ä‘Æ°á»ng dẫn "
+"đã cho"
msgid "read patterns from standard in"
-msgstr "Ä‘á»c các mẫu từ đầu vào tiêu chuẩn"
+msgstr "Ä‘á»c các mẫu từ stdin"
msgid "no sparse-checkout to add to"
msgstr "không có sparse-checkout để thêm vào"
@@ -11645,76 +12060,82 @@ msgstr ""
"(--stdin | <các mẫu>)"
msgid "must be in a sparse-checkout to reapply sparsity patterns"
-msgstr "phải trong một sparse-checkout để áp dụng lại các mẫu sparse"
+msgstr "phải trong sparse-checkout để áp dụng lại các mẫu sparse"
msgid "error while refreshing working directory"
msgstr "gặp lá»—i khi Ä‘á»c lại thÆ° mục làm việc"
-msgid "git stash list [<options>]"
-msgstr "git stash list [<các tùy chá»n>]"
+msgid ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <file>]"
+msgstr ""
+"git sparse-checkout check-rules [-z] [--skip-checks][--[no-]cone] [--rules-"
+"file <tập tin>]"
-msgid "git stash show [<options>] [<stash>]"
-msgstr "git stash show [<các tùy chá»n>] <stash>"
+msgid "terminate input and output files by a NUL character"
+msgstr "kết thúc các bản ghi vào và ra bằng ký tự NULL"
-msgid "git stash drop [-q|--quiet] [<stash>]"
-msgstr "git stash drop [-q|--quiet] [<stash>]"
+msgid "when used with --rules-file interpret patterns as cone mode patterns"
+msgstr "khi dùng với --rules-file, dùng mẫu ở chế độ cone"
-msgid "git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]"
-msgstr "git stash ( pop | apply ) [--index] [-q|--quiet] [<stash>]"
+msgid "use patterns in <file> instead of the current ones."
+msgstr "dùng mẫu từ <tập tin> thay vì các mẫu hiện tại"
-msgid "git stash branch <branchname> [<stash>]"
-msgstr "git stash branch <tên-nhánh> [<stash>]"
+msgid "git stash list [<log-options>]"
+msgstr "git stash list [<các tùy chá»n>]"
msgid ""
-"git stash [push [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-q|--"
-"quiet]\n"
-" [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
-" [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
-" [--] [<pathspec>...]]"
+"git stash show [-u | --include-untracked | --only-untracked] [<diff-"
+"options>] [<stash>]"
msgstr ""
-"git stash [push [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-q|--"
-"quiet]\n"
-" [-u|--include-untracked] [-a|--all] [-m|--message <ghi chú>]\n"
-" [--pathspec-from-file=<tập_tin> [--pathspec-file-nul]]\n"
-" [--] [<đặc/tả/Ä‘Æ°á»ng/dẫn>…]]"
+"git stash show [-u | --include-untracked | --only-untracked] [<diff-"
+"options>] [<stash>]"
-msgid ""
-"git stash save [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-q|--"
-"quiet]\n"
-" [-u|--include-untracked] [-a|--all] [<message>]"
-msgstr ""
-"git stash save [-p|--patch] [-S|--staged] [-k|--[no-]keep-index] [-q|--"
-"quiet]\n"
-" [-u|--include-untracked] [-a|--all] [<ghi chú>]"
+msgid "git stash drop [-q | --quiet] [<stash>]"
+msgstr "git stash drop [-q | --quiet] [<stash>]"
+
+msgid "git stash pop [--index] [-q | --quiet] [<stash>]"
+msgstr "git stash pop [--index] [-q | --quiet] [<stash>]"
-msgid "git stash pop [--index] [-q|--quiet] [<stash>]"
-msgstr "git stash pop [--index] [-q|--quiet] [<stash>]"
+msgid "git stash apply [--index] [-q | --quiet] [<stash>]"
+msgstr "git stash apply [--index] [-q | --quiet] [<stash>]"
-msgid "git stash apply [--index] [-q|--quiet] [<stash>]"
-msgstr "git stash apply [--index] [-q|--quiet] [<stash>]"
+msgid "git stash branch <branchname> [<stash>]"
+msgstr "git stash branch <tên-nhánh> [<stash>]"
-msgid "git stash store [-m|--message <message>] [-q|--quiet] <commit>"
-msgstr "git stash store [-m|--message <ghi chú>] [-q|--quiet] <commit>"
+msgid "git stash store [(-m | --message) <message>] [-q | --quiet] <commit>"
+msgstr "git stash store [(-m | --message) <ghi chú>] [-q | --quiet] <commit>"
msgid ""
-"git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
-" [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
+"git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q "
+"| --quiet]\n"
+" [-u | --include-untracked] [-a | --all] [(-m | --message) "
+"<message>]\n"
+" [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
" [--] [<pathspec>...]]"
msgstr ""
-"git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
-" [-u|--include-untracked] [-a|--all] [-m|--message <lá»i nhắn>]\n"
-" [--] [<đặc/tả/Ä‘Æ°á»ng/dẫn>…]]"
+"git stash [push [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q "
+"| --quiet]\n"
+" [-u | --include-untracked] [-a | --all] [(-m | --message) <ghi "
+"chú>]\n"
+" [--pathspec-from-file=<tập tin> [--pathspec-file-nul]]\n"
+" [--] [<đặc/tả/Ä‘Æ°á»ng/dẫn>...]]"
msgid ""
-"git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
-" [-u|--include-untracked] [-a|--all] [<message>]"
+"git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | "
+"--quiet]\n"
+" [-u | --include-untracked] [-a | --all] [<message>]"
msgstr ""
-"git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
-" [-u|--include-untracked] [-a|--all] [<ghi chú>]"
+"git stash save [-p | --patch] [-S | --staged] [-k | --[no-]keep-index] [-q | "
+"--quiet]\n"
+" [-u | --include-untracked] [-a | --all] [<ghi chú>]"
+
+msgid "git stash create [<message>]"
+msgstr "git stash create [<ghi chú>]"
#, c-format
msgid "'%s' is not a stash-like commit"
-msgstr "“%s†không phải là lần chuyển giao kiểu-stash (cất đi)"
+msgstr "'%s' không phải là lần chuyển giao kiểu-stash"
#, c-format
msgid "Too many revisions specified:%s"
@@ -11725,10 +12146,10 @@ msgstr "Không tìm thấy các mục tạm cất (stash) nào."
#, c-format
msgid "%s is not a valid reference"
-msgstr "“%s†không phải một tham chiếu hợp lệ"
+msgstr "'%s' không phải một tham chiếu hợp lệ"
msgid "git stash clear with arguments is unimplemented"
-msgstr "git stash clear với các tham số là chưa được thực hiện"
+msgstr "git stash clear với các tham số là chưa được hỗ trợ"
#, c-format
msgid ""
@@ -11736,7 +12157,8 @@ msgid ""
" %s -> %s\n"
" to make room.\n"
msgstr ""
-"CẢNH BÃO: Tệp chÆ°a được theo dõi theo cách của tệp được theo dõi! Äổi tên\n"
+"CẢNH BÃO: tập tin chÆ°a được theo dõi chắn Ä‘Æ°á»ng tập tin được theo dõi! Äổi "
+"tên\n"
" %s -> %s\n"
" để nhÆ°á»ng chá»—.\n"
@@ -11748,7 +12170,7 @@ msgid "could not generate diff %s^!."
msgstr "không thể tạo diff %s^!."
msgid "conflicts in index. Try without --index."
-msgstr "xung Ä‘á»™t trong bảng mục lục. Hãy thá»­ mà không dùng tùy chá»n --index."
+msgstr "xung Ä‘á»™t trong chỉ mục. Hãy thá»­ mà không dùng tùy chá»n --index."
msgid "could not save index tree"
msgstr "không thể ghi lại cây chỉ mục"
@@ -11758,13 +12180,13 @@ msgid "Merging %s with %s"
msgstr "Äang hòa trá»™n %s vá»›i %s"
msgid "Index was not unstashed."
-msgstr "Bảng mục lục đã không được bỠstash."
+msgstr "chỉ mục đã không được bỠstash."
msgid "could not restore untracked files from stash"
msgstr "không thể phục hồi các tập tin chưa theo dõi từ mục cất đi (stash)"
msgid "attempt to recreate the index"
-msgstr "gặp lá»—i Ä‘á»c bảng mục lục"
+msgstr "gặp lá»—i Ä‘á»c chỉ mục"
#, c-format
msgid "Dropped %s (%s)"
@@ -11776,7 +12198,7 @@ msgstr "%s: Không thể xóa bỠmục stash"
#, c-format
msgid "'%s' is not a stash reference"
-msgstr "â€%s†không phải tham chiếu đến stash"
+msgstr "'%s' không phải tham chiếu đến stash"
msgid "The stash entry is kept in case you need it again."
msgstr "Các mục tạm cất (stash) được giữ trong trÆ°á»ng hợp bạn lại cần nó."
@@ -11785,7 +12207,7 @@ msgid "No branch name specified"
msgstr "Chưa chỉ ra tên của nhánh"
msgid "failed to parse tree"
-msgstr "gặp lỗi khi phân tích cây"
+msgstr "gặp lá»—i khi Ä‘á»c cây"
msgid "failed to unpack trees"
msgstr "gặp lỗi khi tháo dỡ cây"
@@ -11816,7 +12238,7 @@ msgid "You do not have the initial commit yet"
msgstr "Bạn chưa còn có lần chuyển giao khởi tạo"
msgid "Cannot save the current index state"
-msgstr "Không thể ghi lại trạng thái bảng mục lục hiện hành"
+msgstr "Không thể ghi lại trạng thái chỉ mục hiện hành"
msgid "Cannot save the untracked files"
msgstr "Không thể ghi lại các tập tin chưa theo dõi"
@@ -11837,7 +12259,7 @@ msgid "Can't use --staged and --include-untracked or --all at the same time"
msgstr "Không thể dùng --staged và --include-untracked hay --all cùng một lúc"
msgid "Did you forget to 'git add'?"
-msgstr "Có lẽ bạn đã quên “git add †phải không?"
+msgstr "Có lẽ bạn đã quên 'git add'?"
msgid "No local changes to save"
msgstr "Không có thay đổi nội bộ nào được ghi lại"
@@ -11850,19 +12272,19 @@ msgstr "Không thể ghi lại trạng thái hiện hành"
#, c-format
msgid "Saved working directory and index state %s"
-msgstr "Äã ghi lại thÆ° mục làm việc và trạng thái mục lục %s"
+msgstr "Äã ghi lại thÆ° mục làm việc và trạng thái chỉ mục %s"
msgid "Cannot remove worktree changes"
msgstr "Không thể gỡ bỠcác thay đổi cây-làm-việc"
msgid "keep index"
-msgstr "giữ nguyên bảng mục lục"
+msgstr "giữ nguyên chỉ mục"
msgid "stash staged changes only"
msgstr "chỉ tạm cất đi các thay đổi đã đưa lên bệ phóng"
msgid "stash in patch mode"
-msgstr "cất đi ở chế độ miếng vá"
+msgstr "cất đi ở chế độ vá"
msgid "quiet mode"
msgstr "chế độ im lặng"
@@ -11881,29 +12303,27 @@ msgstr "treo trước ký tự ghi chú và ký tự khoảng trắng cho từng
#, c-format
msgid "Expecting a full ref name, got %s"
-msgstr "Cần tên tham chiếu dạng đầy đủ, nhưng lại nhận được %s"
+msgstr "Cần tên tham chiếu dạng đầy đủ, nhưng lại có %s"
+
+#, c-format
+msgid "could not get a repository handle for submodule '%s'"
+msgstr "không thể lấy thẻ quản kho cho mô-đun-con '%s'"
#, c-format
msgid ""
"could not look up configuration '%s'. Assuming this repository is its own "
"authoritative upstream."
msgstr ""
-"không thể tìm thấy cấu hình “%sâ€. Coi rằng đây là kho thượng nguồn có quyá»n "
+"không thể tìm thấy cấu hình '%s'. Coi rằng đây là kho thượng nguồn có quyá»n "
"sở hữu chính nó."
-msgid "alternative anchor for relative paths"
-msgstr "Ä‘iểm neo thay thế cho các Ä‘Æ°á»ng dẫn tÆ°Æ¡ng đối"
-
-msgid "git submodule--helper list [--prefix=<path>] [<path>...]"
-msgstr "git submodule--helper list [--prefix=</Ä‘Æ°á»ng/dẫn>] [</Ä‘Æ°á»ng/dẫn>…]"
-
#, c-format
msgid "No url found for submodule path '%s' in .gitmodules"
-msgstr "Không tìm thấy url cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%s†trong .gitmodules"
+msgstr "Không tìm thấy url cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s' trong .gitmodules"
#, c-format
msgid "Entering '%s'\n"
-msgstr "Äang vào “%sâ€\n"
+msgstr "Äang vào '%s'\n"
#, c-format
msgid ""
@@ -11929,44 +12349,44 @@ msgstr "chặn kết xuất của từng lệnh mô-đun-con"
msgid "recurse into nested submodules"
msgstr "đệ quy vào trong mô-đun-con lồng nhau"
-msgid "git submodule--helper foreach [--quiet] [--recursive] [--] <command>"
-msgstr "git submodule--helper foreach [--quiet] [--recursive] [--] <lệnh>"
+msgid "git submodule foreach [--quiet] [--recursive] [--] <command>"
+msgstr "git submodule foreach [--quiet] [--recursive] [--] <lệnh>"
#, c-format
msgid "Failed to register url for submodule path '%s'"
-msgstr "Gặp lá»—i khi đăng ký url cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
+msgstr "Gặp lá»—i khi đăng ký url cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'"
#, c-format
msgid "Submodule '%s' (%s) registered for path '%s'\n"
-msgstr "Mô-Ä‘un-con “%s†(%s) được đăng ký cho Ä‘Æ°á»ng dẫn “%sâ€\n"
+msgstr "Mô-Ä‘un-con '%s' (%s) được đăng ký cho Ä‘Æ°á»ng dẫn '%s'\n"
#, c-format
msgid "warning: command update mode suggested for submodule '%s'\n"
-msgstr "cảnh báo: chế Ä‘á»™ lệnh cập nhật được gợi ý cho mô-Ä‘un-con “%sâ€\n"
+msgstr "cảnh báo: chế độ lệnh cập nhật được gợi ý cho mô-đun-con '%s'\n"
#, c-format
msgid "Failed to register update mode for submodule path '%s'"
-msgstr "Gặp lá»—i khi đăng ký chế Ä‘á»™ cập nhật cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
+msgstr "Gặp lá»—i khi đăng ký chế Ä‘á»™ cập nhật cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'"
msgid "suppress output for initializing a submodule"
msgstr "chặn kết xuất của khởi tạo một mô-đun-con"
-msgid "git submodule--helper init [<options>] [<path>]"
-msgstr "git submodule--helper init [<các tùy chá»n>] [</Ä‘Æ°á»ng/dẫn>]"
+msgid "git submodule init [<options>] [<path>]"
+msgstr "git submodule init [<các tùy chá»n>] [</Ä‘Æ°á»ng/dẫn>]"
#, c-format
msgid "no submodule mapping found in .gitmodules for path '%s'"
msgstr ""
"không tìm thấy ánh xạ (mapping) mô-Ä‘un-con trong .gitmodules cho Ä‘Æ°á»ng dẫn "
-"“%sâ€"
+"'%s'"
#, c-format
msgid "could not resolve HEAD ref inside the submodule '%s'"
-msgstr "không thể phân giải tham chiếu HEAD bên trong mô-Ä‘un-con “%sâ€"
+msgstr "không thể phân giải tham chiếu HEAD bên trong mô-đun-con '%s'"
#, c-format
msgid "failed to recurse into submodule '%s'"
-msgstr "gặp lá»—i khi đệ quy vào trong mô-Ä‘un-con “%sâ€"
+msgstr "gặp lỗi khi đệ quy vào trong mô-đun-con '%s'"
msgid "suppress submodule status output"
msgstr "chặn kết xuất vỠtình trạng mô-đun-con"
@@ -11975,15 +12395,12 @@ msgid ""
"use commit stored in the index instead of the one stored in the submodule "
"HEAD"
msgstr ""
-"dùng lần chuyển giao lưu trong mục lục thay cho cái được lưu trong HEAD mô-"
+"dùng lần chuyển giao lưu trong chỉ mục thay cho cái được lưu trong HEAD mô-"
"Ä‘un-con"
msgid "git submodule status [--quiet] [--cached] [--recursive] [<path>...]"
msgstr ""
-"git submodule status [--quiet] [--cached] [--recursive] [</Ä‘Æ°á»ng/dẫn>…]"
-
-msgid "git submodule--helper name <path>"
-msgstr "git submodule--helper name </Ä‘Æ°á»ng/dẫn>"
+"git submodule status [--quiet] [--cached] [--recursive] [</Ä‘Æ°á»ng/dẫn>...]"
#, c-format
msgid "* %s %s(blob)->%s(submodule)"
@@ -12001,61 +12418,57 @@ msgstr "%s"
#, c-format
msgid "couldn't hash object from '%s'"
-msgstr "không thể băm đối tượng từ “%sâ€"
+msgstr "không thể băm đối tượng từ '%s'"
#, c-format
msgid "unexpected mode %o\n"
msgstr "gặp chế độ không như mong chỠ%o\n"
msgid "use the commit stored in the index instead of the submodule HEAD"
-msgstr "hùng lần chuyển giao đã lưu trong mục lục thay cho HEAD mô-đun-con"
+msgstr "hùng lần chuyển giao đã lưu trong chỉ mục thay cho HEAD mô-đun-con"
msgid "compare the commit in the index with that in the submodule HEAD"
-msgstr "để so sánh lần trong mục lục với cái trong HEAD mô-đun-con"
+msgstr "để so sánh lần trong chỉ mục với cái trong HEAD mô-đun-con"
msgid "skip submodules with 'ignore_config' value set to 'all'"
msgstr ""
-"bá» qua các mô-Ä‘un-con vá»›i giá trị của “ignore_config†được đặt thành “allâ€"
+"bỠqua các mô-đun-con với giá trị của 'ignore_config' được đặt thành 'all'"
msgid "limit the summary size"
msgstr "giới hạn kích cỡ tổng hợp"
-msgid "git submodule--helper summary [<options>] [<commit>] [--] [<path>]"
+msgid "git submodule summary [<options>] [<commit>] [--] [<path>]"
msgstr ""
-"git submodule--helper summary [<các tùy chá»n>] [<lần_chuyển_giao>] [--] [</"
-"Ä‘Æ°á»ng/dẫn>]"
+"git submodule summary [<các tùy chá»n>] [<lần_chuyển_giao>] [--] [</Ä‘Æ°á»ng/"
+"dẫn>]"
msgid "could not fetch a revision for HEAD"
msgstr "không thể lấy vỠmột điểm xem xét cho HEAD"
#, c-format
msgid "Synchronizing submodule url for '%s'\n"
-msgstr "Url mô-Ä‘un-con đồng bá»™ hóa cho “%sâ€\n"
+msgstr "Url mô-đun-con đồng bộ hóa cho '%s'\n"
#, c-format
msgid "failed to register url for submodule path '%s'"
-msgstr "gặp lá»—i khi đăng ký url cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
-
-#, c-format
-msgid "failed to get the default remote for submodule '%s'"
-msgstr "gặp lá»—i khi lấy máy chủ mặc định cho mô-Ä‘un-con “%sâ€"
+msgstr "gặp lá»—i khi đăng ký url cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'"
#, c-format
msgid "failed to update remote for submodule '%s'"
-msgstr "gặp lá»—i khi cập nhật cho mô-Ä‘un-con “%sâ€"
+msgstr "gặp lỗi khi cập nhật cho mô-đun-con '%s'"
msgid "suppress output of synchronizing submodule url"
msgstr "chặn kết xuất của url mô-đun-con đồng bộ"
-msgid "git submodule--helper sync [--quiet] [--recursive] [<path>]"
-msgstr "git submodule--helper sync [--quiet] [--recursive] [</Ä‘Æ°á»ng/dẫn>]"
+msgid "git submodule sync [--quiet] [--recursive] [<path>]"
+msgstr "git submodule sync [--quiet] [--recursive] [</Ä‘Æ°á»ng/dẫn>]"
#, c-format
msgid ""
"Submodule work tree '%s' contains a .git directory. This will be replaced "
"with a .git file by using absorbgitdirs."
msgstr ""
-"Cây làm việc mô-đun-con “%s†có chứa thư mục .git. Việc này sẽ được thay thế "
+"Cây làm việc mô-đun-con '%s' có chứa thư mục .git. Việc này sẽ được thay thế "
"với một tập tin .git bằng các sử dụng absorbgitdirs."
#, c-format
@@ -12063,24 +12476,24 @@ msgid ""
"Submodule work tree '%s' contains local modifications; use '-f' to discard "
"them"
msgstr ""
-"Cây làm việc mô-đun-con “%s†chứa các thay đổi nội bộ; hãy dùng “-f†để loại "
+"Cây làm việc mô-đun-con '%s' chứa các thay đổi nội bộ; hãy dùng '-f' để loại "
"bỠchúng đi"
#, c-format
msgid "Cleared directory '%s'\n"
-msgstr "Äã xóa thÆ° mục “%sâ€\n"
+msgstr "Äã xóa thÆ° mục '%s'\n"
#, c-format
msgid "Could not remove submodule work tree '%s'\n"
-msgstr "Không thể gỡ bá» cây làm việc mô-Ä‘un-con “%sâ€\n"
+msgstr "Không thể gỡ bỠcây làm việc mô-đun-con '%s'\n"
#, c-format
msgid "could not create empty submodule directory %s"
-msgstr "không thể tạo thÆ° mục mô-Ä‘un-con rá»—ng “%sâ€"
+msgstr "không thể tạo thư mục mô-đun-con rỗng '%s'"
#, c-format
msgid "Submodule '%s' (%s) unregistered for path '%s'\n"
-msgstr "Mô-Ä‘un-con “%s†(%s) được đăng ký cho Ä‘Æ°á»ng dẫn “%sâ€\n"
+msgstr "Mô-Ä‘un-con '%s' (%s) được đăng ký cho Ä‘Æ°á»ng dẫn '%s'\n"
msgid "remove submodule working trees even if they contain local changes"
msgstr "gỡ bỠcây làm việc của mô-đun-con ngay cả khi nó có thay đổi nội bộ"
@@ -12091,10 +12504,11 @@ msgstr "bỠđăng ký tất cả các trong mô-đun-con"
msgid ""
"git submodule deinit [--quiet] [-f | --force] [--all | [--] [<path>...]]"
msgstr ""
-"git submodule deinit [--quiet] [-f | --force] [--all | [--] [</Ä‘Æ°á»ng/dẫn>…]]"
+"git submodule deinit [--quiet] [-f | --force] [--all | [--] [</Ä‘Æ°á»ng/"
+"dẫn>...]]"
msgid "Use '--all' if you really want to deinitialize all submodules"
-msgstr "Dùng “--all†nếu bạn thá»±c sá»± muốn hủy khởi tạo má»i mô-Ä‘un-con"
+msgstr "Dùng '--all' nếu bạn thá»±c sá»± muốn hủy khởi tạo má»i mô-Ä‘un-con"
msgid ""
"An alternate computed from a superproject's alternate is invalid.\n"
@@ -12102,41 +12516,48 @@ msgid ""
"submodule.alternateErrorStrategy to 'info' or, equivalently, clone with\n"
"'--reference-if-able' instead of '--reference'."
msgstr ""
-"Một cái thay thế được tính toán từ một thay thế của siêu dự án là không hợp "
+"Một cái thay thế được tính toán từ một thay thế của project cha là không hợp "
"lệ.\n"
"Äể cho Git thá»±c hiện nhân bản mà không có cái thay thế nhÆ° trong trÆ°á»ng hợp "
"này, đặt\n"
-"submodule.alternateErrorStrategy thành “info†hoặc, tương đương, nhân bản "
+"submodule.alternateErrorStrategy thành 'info' hoặc, tương đương, nhân bản "
"bằng\n"
-"“--reference-if-able†thay vì dùng “--referenceâ€."
+"'--reference-if-able' thay vì dùng '--reference'."
+
+#, c-format
+msgid "could not get a repository handle for gitdir '%s'"
+msgstr "không thể lấy thẻ quản kho cho gitdir '%s'"
#, c-format
msgid "submodule '%s' cannot add alternate: %s"
-msgstr "mô-đun-con “%s†không thể thêm thay thế: %s"
+msgstr "mô-đun-con '%s' không thể thêm thay thế: %s"
#, c-format
msgid "Value '%s' for submodule.alternateErrorStrategy is not recognized"
-msgstr "Giá trị “%s†cho submodule.alternateErrorStrategy không được thừa nhận"
+msgstr "Giá trị '%s' cho submodule.alternateErrorStrategy không được thừa nhận"
#, c-format
msgid "Value '%s' for submodule.alternateLocation is not recognized"
-msgstr "Giá trị “%s†cho submodule.alternateLocation không được thừa nhận"
+msgstr "Giá trị '%s' cho submodule.alternateLocation không được thừa nhận"
#, c-format
msgid "refusing to create/use '%s' in another submodule's git dir"
-msgstr "từ chối tạo/dùng “%s†trong một thư mục git của mô đun con"
+msgstr "từ chối tạo/dùng '%s' trong một thư mục git của mô đun con"
#, c-format
msgid "clone of '%s' into submodule path '%s' failed"
-msgstr "việc sao “%s†vào Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%s†gặp lá»—i"
+msgstr "việc sao '%s' vào Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s' gặp lá»—i"
#, c-format
msgid "directory not empty: '%s'"
-msgstr "thÆ° mục không trống: “%sâ€"
+msgstr "thư mục không trống: '%s'"
#, c-format
msgid "could not get submodule directory for '%s'"
-msgstr "không thể lấy thÆ° mục mô-Ä‘un-con cho “%sâ€"
+msgstr "không thể lấy thư mục mô-đun-con cho '%s'"
+
+msgid "alternative anchor for relative paths"
+msgstr "Ä‘iểm neo thay thế cho các Ä‘Æ°á»ng dẫn tÆ°Æ¡ng đối"
msgid "where the new submodule will be cloned to"
msgstr "nhân bản mô-đun-con mới vào chỗ nào"
@@ -12166,20 +12587,16 @@ msgstr ""
"spec>] --url <url> --path </Ä‘Æ°á»ng/dẫn>"
#, c-format
-msgid "Invalid update mode '%s' for submodule path '%s'"
-msgstr "Chế Ä‘á»™ cập nhật “%s†không hợp lệ cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
-
-#, c-format
msgid "Invalid update mode '%s' configured for submodule path '%s'"
msgstr ""
-"Chế Ä‘á»™ cập nhật “%s†không hợp lệ được cấu hình cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
+"Chế Ä‘á»™ cập nhật '%s' không hợp lệ được cấu hình cho Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'"
#, c-format
msgid "Submodule path '%s' not initialized"
-msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con “%s†chÆ°a được khởi tạo"
+msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con '%s' chÆ°a được khởi tạo"
msgid "Maybe you want to use 'update --init'?"
-msgstr "Có lẽ bạn là bạn muốn dùng \"update --init\" phải không?"
+msgstr "Có lẽ bạn muốn dùng 'update --init'?"
#, c-format
msgid "Skipping unmerged submodule %s"
@@ -12187,93 +12604,97 @@ msgstr "BỠqua các mô-đun-con chưa được hòa trộn %s"
#, c-format
msgid "Skipping submodule '%s'"
-msgstr "Bá» qua mô-Ä‘un-con “%sâ€"
+msgstr "BỠqua mô-đun-con '%s'"
+
+#, c-format
+msgid "cannot clone submodule '%s' without a URL"
+msgstr "không thể nhân bản mô-đun-con '%s' nếu không có URL"
#, c-format
msgid "Failed to clone '%s'. Retry scheduled"
-msgstr "Gặp lá»—i khi nhân bản “%sâ€. Thá»­ lại lịch trình"
+msgstr "Gặp lá»—i khi nhân bản '%s'. Äã lên lịch thá»­ lại"
#, c-format
msgid "Failed to clone '%s' a second time, aborting"
-msgstr "Gặp lá»—i khi nhân bản “%s†lần thứ hai nên bãi bá»"
+msgstr "Gặp lá»—i khi nhân bản '%s' lần thứ hai, huá»· bá»"
#, c-format
msgid "Unable to checkout '%s' in submodule path '%s'"
-msgstr "Không thể lấy ra “%s†trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
+msgstr "Không thể checkout '%s' trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'"
#, c-format
msgid "Unable to rebase '%s' in submodule path '%s'"
-msgstr "Không thể cải tổ “%s†trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
+msgstr "Không thể cải tổ '%s' trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'"
#, c-format
msgid "Unable to merge '%s' in submodule path '%s'"
-msgstr "Không thể hòa trá»™n (merge) “%s†trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
+msgstr "Không thể hòa trá»™n (merge) '%s' trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'"
#, c-format
msgid "Execution of '%s %s' failed in submodule path '%s'"
msgstr ""
-"Thá»±c hiện không thành công lệnh “%s %s†trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
+"Thá»±c hiện không thành công lệnh '%s %s' trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'"
#, c-format
msgid "Submodule path '%s': checked out '%s'\n"
-msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con “%sâ€: đã checkout “%sâ€\n"
+msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con '%s': đã checkout '%s'\n"
#, c-format
msgid "Submodule path '%s': rebased into '%s'\n"
-msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con “%sâ€: được rebase vào trong “%sâ€\n"
+msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con '%s': được rebase vào trong '%s'\n"
#, c-format
msgid "Submodule path '%s': merged in '%s'\n"
-msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con “%sâ€: được hòa trá»™n vào “%sâ€\n"
+msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con '%s': được hòa trá»™n vào '%s'\n"
#, c-format
msgid "Submodule path '%s': '%s %s'\n"
-msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con “%sâ€: “%s %sâ€\n"
+msgstr "ÄÆ°á»ng dẫn mô-Ä‘un-con '%s': '%s %s'\n"
#, c-format
msgid "Unable to fetch in submodule path '%s'; trying to directly fetch %s:"
msgstr ""
-"Không thể lấy vá» trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€; thá»­ lấy vá» trá»±c tiếp %s:"
+"Không thể lấy vá» trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'; thá»­ lấy vá» trá»±c tiếp %s:"
#, c-format
msgid ""
"Fetched in submodule path '%s', but it did not contain %s. Direct fetching "
"of that commit failed."
msgstr ""
-"Äã lấy vá» từ Ä‘Æ°á»ng dẫn mô-Ä‘un con “%sâ€, nhÆ°ng nó không chứa %s. Lấy vá» trá»±c "
+"Äã lấy vá» từ Ä‘Æ°á»ng dẫn mô-Ä‘un con '%s', nhÆ°ng nó không chứa %s. Lấy vá» trá»±c "
"tiếp lần chuyển giao gặp lỗi đó."
#, c-format
+msgid "could not initialize submodule at path '%s'"
+msgstr "Không thể khởi tạo mô-Ä‘un-con tại Ä‘Æ°á»ng dẫn '%s'"
+
+#, c-format
msgid ""
"Submodule (%s) branch configured to inherit branch from superproject, but "
"the superproject is not on any branch"
msgstr ""
-"Nhánh mô-đun-con (%s) được cấu hình kế thừa nhánh từ siêu dự án, nhưng siêu "
-"dự án lại không trên bất kỳ nhánh nào"
-
-#, c-format
-msgid "could not get a repository handle for submodule '%s'"
-msgstr "không thể lấy thẻ quản kho cho mô-Ä‘un-con “%sâ€"
+"Nhánh mô-đun-con (%s) được cấu hình kế thừa nhánh từ project cha, nhưng "
+"project cha lại không trên bất kỳ nhánh nào"
#, c-format
msgid "Unable to find current revision in submodule path '%s'"
msgstr ""
-"Không tìm thấy Ä‘iểm xét duyệt hiện hành trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
+"Không tìm thấy Ä‘iểm xét duyệt hiện hành trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'"
#, c-format
msgid "Unable to fetch in submodule path '%s'"
-msgstr "Không thể lấy vá» trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
+msgstr "Không thể lấy vá» trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'"
#, c-format
msgid "Unable to find %s revision in submodule path '%s'"
-msgstr "Không tìm thấy Ä‘iểm xét duyệt %s trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
+msgstr "Không tìm thấy Ä‘iểm xét duyệt %s trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'"
#, c-format
msgid "Failed to recurse into submodule path '%s'"
-msgstr "Gặp lá»—i khi đệ quy vào trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “%sâ€"
+msgstr "Gặp lá»—i khi đệ quy vào trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con '%s'"
msgid "force checkout updates"
-msgstr "ép buộc lấy ra các cập nhật"
+msgstr "ép buộc checkout các cập nhật"
msgid "initialize uninitialized submodules before update"
msgstr "khởi tạo mô-đun-con chưa khởi tạo trước khi cập nhật"
@@ -12287,14 +12708,14 @@ msgstr "đi theo mô-đun con một cách đệ quy"
msgid "don't fetch new objects from the remote site"
msgstr "đừng lấy các đối tượng mới từ địa chỉ trên mạng"
-msgid "path into the working tree"
-msgstr "Ä‘Æ°á»ng dẫn đến cây làm việc"
+msgid "use the 'checkout' update strategy (default)"
+msgstr "dùng chiến lược hòa trộn 'checkout' (mặc định)"
-msgid "path into the working tree, across nested submodule boundaries"
-msgstr "Ä‘Æ°á»ng dẫn đến cây làm việc, chéo biên giá»›i mô-Ä‘un-con lồng nhau"
+msgid "use the 'merge' update strategy"
+msgstr "dùng chiến lược hòa trộn 'merge'"
-msgid "rebase, merge, checkout or none"
-msgstr "rebase, merge, checkout hoặc không làm gì cả"
+msgid "use the 'rebase' update strategy"
+msgstr "dùng chiến lược hòa trộn 'rebase'"
msgid "create a shallow clone truncated to the specified number of revisions"
msgstr ""
@@ -12309,6 +12730,9 @@ msgstr "nhân bản lần đầu có nên theo khuyến nghị là nông hay khÃ
msgid "don't print cloning progress"
msgstr "đừng in tiến trình nhân bản"
+msgid "disallow cloning into non-empty directory, implies --init"
+msgstr "không cho phép nhân bản vào thư mục trống, ngụ ý --init"
+
msgid ""
"git submodule [--quiet] update [--init [--filter=<filter-spec>]] [--remote] "
"[-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-"
@@ -12320,35 +12744,17 @@ msgstr ""
"shallow] [--reference <kho>] [--recursive] [--[no-]single-branch] [--] [</"
"Ä‘Æ°á»ng/dẫn/>...]"
-msgid "bad value for update parameter"
-msgstr "giá trị cho tham số cập nhật bị sai"
-
-msgid "recurse into submodules"
-msgstr "đệ quy vào trong mô-đun-con"
-
-msgid "git submodule--helper absorb-git-dirs [<options>] [<path>...]"
-msgstr "git submodule--helper absorb-git-dirs [<các tùy chá»n>] [</Ä‘Æ°á»ng/dẫn>…]"
-
-msgid "check if it is safe to write to the .gitmodules file"
-msgstr "chá»n nếu nó là an toàn để ghi vào tập tin .gitmodules"
-
-msgid "unset the config in the .gitmodules file"
-msgstr "bỠđặt cấu hình trong tập tin .gitmodules"
-
-msgid "git submodule--helper config <name> [<value>]"
-msgstr "git submodule--helper config <tên> [<giá trị>]"
-
-msgid "git submodule--helper config --unset <name>"
-msgstr "git submodule--helper config --unset <tên>"
+msgid "Failed to resolve HEAD as a valid ref."
+msgstr "Gặp lỗi khi phân giải HEAD như là một tham chiếu hợp lệ."
-msgid "please make sure that the .gitmodules file is in the working tree"
-msgstr "hãy đảm bảo rằng tập tin .gitmodules có trong cây làm việc"
+msgid "git submodule absorbgitdirs [<options>] [<path>...]"
+msgstr "git submodule absorbgitdirs [<các tùy chá»n>] [</Ä‘Æ°á»ng/dẫn>...]"
msgid "suppress output for setting url of a submodule"
-msgstr "chặn kết xuất cho cài đặt url của một mô-đun-con"
+msgstr "chặn đầu ra cho việc đặt url của một mô-đun-con"
-msgid "git submodule--helper set-url [--quiet] <path> <newurl>"
-msgstr "git submodule--helper set-url [--quiet] </Ä‘Æ°á»ng/dẫn> <url_má»›i>"
+msgid "git submodule set-url [--quiet] <path> <newurl>"
+msgstr "git submodule set-url [--quiet] </Ä‘Æ°á»ng/dẫn> <url_má»›i>"
msgid "set the default tracking branch to master"
msgstr "đặt nhánh theo dõi mặc định thành master"
@@ -12356,15 +12762,12 @@ msgstr "đặt nhánh theo dõi mặc định thành master"
msgid "set the default tracking branch"
msgstr "đặt nhánh theo dõi mặc định"
-msgid "git submodule--helper set-branch [-q|--quiet] (-d|--default) <path>"
-msgstr ""
-"git submodule--helper set-branch [-q|--quiet](-d|--default)</Ä‘Æ°á»ng/dẫn>"
+msgid "git submodule set-branch [-q|--quiet] (-d|--default) <path>"
+msgstr "git submodule set-branch [-q|--quiet](-d|--default)</Ä‘Æ°á»ng/dẫn>"
-msgid ""
-"git submodule--helper set-branch [-q|--quiet] (-b|--branch) <branch> <path>"
+msgid "git submodule set-branch [-q|--quiet] (-b|--branch) <branch> <path>"
msgstr ""
-"git submodule--helper set-branch [-q|--quiet] (-b|--branch) <nhánh> </Ä‘Æ°á»ng/"
-"dẫn>"
+"git submodule set-branch [-q|--quiet] (-b|--branch) <nhánh> </Ä‘Æ°á»ng/dẫn>"
msgid "--branch or --default required"
msgstr "cần --branch hoặc --default"
@@ -12387,19 +12790,19 @@ msgstr ""
#, c-format
msgid "creating branch '%s'"
-msgstr "Ä‘ang tạo nhánh “%sâ€"
+msgstr "đang tạo nhánh '%s'"
#, c-format
msgid "Adding existing repo at '%s' to the index\n"
-msgstr "Äang thêm repo có sẵn tại “%s†vào bảng mục lục\n"
+msgstr "Äang thêm repo có sẵn tại '%s' vào chỉ mục\n"
#, c-format
msgid "'%s' already exists and is not a valid git repo"
-msgstr "“%s†đã tồn tại từ trước và không phải là một kho git hợp lệ"
+msgstr "'%s' đã tồn tại từ trước và không phải là một kho git hợp lệ"
#, c-format
msgid "A git directory for '%s' is found locally with remote(s):\n"
-msgstr "Thư mục git cho “%s†được tìm thấy một cách cục bộ với các máy chủ:\n"
+msgstr "Thư mục git cho '%s' được tìm thấy một cách cục bộ với các máy chủ:\n"
#, c-format
msgid ""
@@ -12413,39 +12816,41 @@ msgstr ""
"Nếu bạn muốn sử dụng lại thư mục git nội bộ này thay vì nhân bản lại lần nữa "
"từ\n"
" %s\n"
-"dùng tùy chá»n “--forceâ€. Nếu thÆ° mục git ná»™i bá»™ không phải là má»™t kho đúng "
+"dùng tùy chá»n '--force'. Nếu thÆ° mục git ná»™i bá»™ không phải là má»™t kho đúng "
"hoặc\n"
-"là bạn không chắc chắn Ä‘iá»u đó nghÄ©a là gì thì chá»n tên khác vá»›i tùy chá»n “--"
-"nameâ€."
+"là bạn không chắc chắn Ä‘iá»u đó nghÄ©a là gì thì chá»n tên khác vá»›i tùy chá»n '--"
+"name'."
#, c-format
msgid "Reactivating local git directory for submodule '%s'\n"
-msgstr "Phục hồi sá»± hoạt Ä‘á»™ng của thÆ° mục git ná»™i bá»™ cho mô-Ä‘un-con “%sâ€.\n"
+msgstr "Phục hồi sự hoạt động của thư mục git nội bộ cho mô-đun-con '%s'.\n"
#, c-format
msgid "unable to checkout submodule '%s'"
-msgstr "không thể lấy ra mô-Ä‘un-con “%sâ€"
+msgstr "không thể checkout mô-đun-con '%s'"
+
+msgid "please make sure that the .gitmodules file is in the working tree"
+msgstr "hãy đảm bảo rằng tập tin .gitmodules có trong cây làm việc"
#, c-format
msgid "Failed to add submodule '%s'"
-msgstr "Gặp lá»—i khi thêm mô-Ä‘un-con “%sâ€"
+msgstr "Gặp lỗi khi thêm mô-đun-con '%s'"
#, c-format
msgid "Failed to register submodule '%s'"
-msgstr "Gặp lá»—i khi đăng ký mô-Ä‘un-con “%sâ€"
+msgstr "Gặp lỗi khi đăng ký mô-đun-con '%s'"
#, c-format
msgid "'%s' already exists in the index"
-msgstr "â€%s†thá»±c sá»± đã tồn tại ở bảng mục lục rồi"
+msgstr "'%s' thực sự đã tồn tại ở chỉ mục rồi"
#, c-format
msgid "'%s' already exists in the index and is not a submodule"
-msgstr ""
-"â€%s†thá»±c sá»± đã tồn tại ở bảng mục lục rồi và không phải là má»™t mô-Ä‘un-con"
+msgstr "'%s' thực sự đã tồn tại ở chỉ mục rồi và không phải là một mô-đun-con"
#, c-format
msgid "'%s' does not have a commit checked out"
-msgstr "“%s†không có một lần chuyển giao nào được lấy ra"
+msgstr "'%s' không có một lần chuyển giao nào được checkout"
msgid "branch of repository to add as submodule"
msgstr "nhánh của kho để thêm như là mô-đun-con"
@@ -12462,8 +12867,8 @@ msgid ""
msgstr ""
"đặt tên của mô-Ä‘un-con bằng chuá»—i đã cho thay vì mặc định là Ä‘Æ°á»ng dẫn của nó"
-msgid "git submodule--helper add [<options>] [--] <repository> [<path>]"
-msgstr "git submodule--helper add [<các tùy chá»n>] [--] <kho> [</Ä‘Æ°á»ng/dẫn>]"
+msgid "git submodule add [<options>] [--] <repository> [<path>]"
+msgstr "git submodule add [<các tùy chá»n>] [--] <kho> [</Ä‘Æ°á»ng/dẫn>]"
msgid "Relative path can only be used from the toplevel of the working tree"
msgstr ""
@@ -12472,28 +12877,26 @@ msgstr ""
#, c-format
msgid "repo URL: '%s' must be absolute or begin with ./|../"
-msgstr "repo URL: “%s†phải là Ä‘Æ°á»ng dẫn tuyệt đối hoặc là bắt đầu bằng ./|../"
+msgstr "repo URL: '%s' phải là Ä‘Æ°á»ng dẫn tuyệt đối hoặc là bắt đầu bằng ./|../"
#, c-format
msgid "'%s' is not a valid submodule name"
-msgstr "“%s†không phải là một tên mô-đun-con hợp lệ"
+msgstr "'%s' không phải là một tên mô-đun-con hợp lệ"
-#, c-format
-msgid "%s doesn't support --super-prefix"
-msgstr "%s không hỗ trợ --super-prefix"
+msgid "git submodule--helper <command>"
+msgstr "git submodule--helper <lệnh>"
-#, c-format
-msgid "'%s' is not a valid submodule--helper subcommand"
-msgstr "“%s†không phải là lệnh con submodule--helper hợp lệ"
+msgid "git symbolic-ref [-m <reason>] <name> <ref>"
+msgstr "git symbolic-ref [-m <lý do>] <tên> <tham chiếu>"
-msgid "git symbolic-ref [<options>] <name> [<ref>]"
-msgstr "git symbolic-ref [<các tùy chá»n>] <tên> [<t.chiếu>]"
+msgid "git symbolic-ref [-q] [--short] [--no-recurse] <name>"
+msgstr "git symbolic-ref [-q] [--short] [--no-recurse] <tên>"
-msgid "git symbolic-ref -d [-q] <name>"
-msgstr "git symbolic-ref -d [-q] <tên>"
+msgid "git symbolic-ref --delete [-q] <name>"
+msgstr "git symbolic-ref --delete [-q] <tên>"
msgid "suppress error message for non-symbolic (detached) refs"
-msgstr "chặn các thông tin lá»—i cho các tham chiếu “không-má»m†(bị tách ra)"
+msgstr "chặn các thông tin lá»—i cho các tham chiếu 'không-má»m' (bị tách ra)"
msgid "delete symbolic ref"
msgstr "xóa tham chiếu má»m"
@@ -12501,6 +12904,9 @@ msgstr "xóa tham chiếu má»m"
msgid "shorten ref output"
msgstr "làm ngắn kết xuất ref (tham chiếu)"
+msgid "recursively dereference (default)"
+msgstr "chế độ giải tham chiếu đệ quy (mặc định)"
+
msgid "reason"
msgstr "lý do"
@@ -12508,61 +12914,63 @@ msgid "reason of the update"
msgstr "lý do cập nhật"
msgid ""
-"git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]\n"
-" <tagname> [<head>]"
+"git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n"
+" <tagname> [<commit> | <object>]"
msgstr ""
-"git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <tập-tin>]\n"
-" <tên-thẻ> [<head>]"
+"git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <tập-tin>] [-e]\n"
+" <tên-thẻ> [<lần chuyển giao> | <đối tượng> ]"
msgid "git tag -d <tagname>..."
-msgstr "git tag -d <tên-thẻ>…"
+msgstr "git tag -d <tên-thẻ>..."
msgid ""
-"git tag -l [-n[<num>]] [--contains <commit>] [--no-contains <commit>] [--"
-"points-at <object>]\n"
-" [--format=<format>] [--merged <commit>] [--no-merged <commit>] "
-"[<pattern>...]"
+"git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]\n"
+" [--points-at <object>] [--column[=<options>] | --no-column]\n"
+" [--create-reflog] [--sort=<key>] [--format=<format>]\n"
+" [--merged <commit>] [--no-merged <commit>] [<pattern>...]"
msgstr ""
-"git tag -l [-n[<số>]] [--contains <lần_chuyển_giao>] [--no-contains "
-"<lần_chuyển_giao>] [--points-at <đối-tượng>]\n"
-" [--format=<định_dạng>] [--merged <lần_chuyển_giao>] [--no-merged "
-"[<lần_chuyển_giao>]] [<mẫu>…]"
+"git tag [-n[<số>]] -l [--contains <lần_chuyển_giao>] [--no-contains "
+"<lần_chuyển_giao>]\n"
+" [--points-at <đối-tượng>] [--column[=<options>] | --no-column]\n"
+" [--create-reflog] [--sort=<key>] [--format=<định dạng>]\n"
+" [--merged <lần_chuyển_giao>] [--no-merged <lần_chuyển_giao>] "
+"[<mẫu>...]"
msgid "git tag -v [--format=<format>] <tagname>..."
-msgstr "git tag -v [--format=<định_dạng>] <tên-thẻ>…"
+msgstr "git tag -v [--format=<định dạng>] <tên-thẻ>..."
#, c-format
msgid "tag '%s' not found."
-msgstr "không tìm thấy tìm thấy thẻ “%sâ€."
+msgstr "không tìm thấy thẻ '%s'."
#, c-format
msgid "Deleted tag '%s' (was %s)\n"
-msgstr "Thẻ đã bị xóa “%s†(từng là %s)\n"
+msgstr "Thẻ đã bị xóa '%s' (từng là %s)\n"
#, c-format
msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be ignored.\n"
+"Lines starting with '%s' will be ignored.\n"
msgstr ""
"\n"
"Viết các ghi chú cho thẻ:\n"
" %s\n"
-"Những dòng được bắt đầu bằng “%c†sẽ được bỠqua.\n"
+"Những dòng được bắt đầu bằng '%s' sẽ được bỠqua.\n"
#, c-format
msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be kept; you may remove them yourself if you "
+"Lines starting with '%s' will be kept; you may remove them yourself if you "
"want to.\n"
msgstr ""
"\n"
"Viết các ghi chú cho thẻ:\n"
" %s\n"
-"Những dòng được bắt đầu bằng “%c†sẽ được giữ lại; bạn có thể xóa chúng đi "
+"Những dòng được bắt đầu bằng '%s' sẽ được giữ lại; bạn có thể xóa chúng đi "
"nếu muốn.\n"
msgid "unable to sign the tag"
@@ -12647,17 +13055,20 @@ msgstr "chỉ hiển thị những thẻ mà nó không được hòa trộn"
msgid "print only tags of the object"
msgstr "chỉ hiển thị các thẻ của đối tượng"
+msgid "could not start 'git column'"
+msgstr "không thể chạy 'git column'"
+
#, c-format
msgid "the '%s' option is only allowed in list mode"
msgstr "tùy chá»n '%s' chỉ cho phép dùng trong chế Ä‘á»™ liệt kê"
#, c-format
msgid "'%s' is not a valid tag name."
-msgstr "“%s†không phải thẻ hợp lệ."
+msgstr "'%s' không phải thẻ hợp lệ."
#, c-format
msgid "tag '%s' already exists"
-msgstr "thẻ “%s†đã tồn tại rồi"
+msgstr "thẻ '%s' đã tồn tại rồi"
#, c-format
msgid "Invalid cleanup mode %s"
@@ -12665,11 +13076,21 @@ msgstr "Chế Ä‘á»™ dá»n dẹp không hợp lệ %s"
#, c-format
msgid "Updated tag '%s' (was %s)\n"
-msgstr "Äã cập nhật thẻ “%s†(trÆ°á»›c là %s)\n"
+msgstr "Äã cập nhật thẻ '%s' (trÆ°á»›c là %s)\n"
msgid "pack exceeds maximum allowed size"
msgstr "gói đã vượt quá cỡ tối đa được phép"
+msgid "failed to write object in stream"
+msgstr "gặp lá»—i khi Ä‘á»c đối tượng trong stream"
+
+#, c-format
+msgid "inflate returned (%d)"
+msgstr "inflate trả vỠ(%d)"
+
+msgid "invalid blob object from stream"
+msgstr "đối tượng blob không hợp lệ trong stream"
+
msgid "Unpacking objects"
msgstr "Äang giải nén các đối tượng"
@@ -12687,7 +13108,7 @@ msgstr "gặp lỗi khi xóa thư mục %s"
#, c-format
msgid "Testing mtime in '%s' "
-msgstr "Äang kiểm thá»­ mtime trong “%s†"
+msgstr "Äang kiểm thá»­ mtime trong '%s' "
msgid "directory stat info does not change after adding a new file"
msgstr "thông tin thống kê thư mục không thay đổi sau khi thêm tập tin mới"
@@ -12713,38 +13134,37 @@ msgid " OK"
msgstr " Äồng ý"
msgid "git update-index [<options>] [--] [<file>...]"
-msgstr "git update-index [<các tùy chá»n>] [--] [<tập-tin>…]"
+msgstr "git update-index [<các tùy chá»n>] [--] [<tập-tin>...]"
msgid "continue refresh even when index needs update"
-msgstr "tiếp tục làm mới ngay cả khi bảng mục lục cần được cập nhật"
+msgstr "tiếp tục làm mới ngay cả khi chỉ mục cần được cập nhật"
msgid "refresh: ignore submodules"
-msgstr "refresh: lỠđi mô-đun-con"
+msgstr "refresh: bỠqua mô-đun-con"
msgid "do not ignore new files"
msgstr "không bỠqua các tập tin mới tạo"
msgid "let files replace directories and vice-versa"
-msgstr "để các tập tin thay thế các thÆ° mục và “vice-versaâ€"
+msgstr "để các tập tin thay thế các thư mục và 'vice-versa'"
msgid "notice files missing from worktree"
msgstr "thông báo các tập-tin thiếu trong thư-mục làm việc"
msgid "refresh even if index contains unmerged entries"
-msgstr ""
-"làm tươi mới thậm chí khi bảng mục lục chứa các mục tin chưa được hòa trộn"
+msgstr "làm tươi mới thậm chí khi chỉ mục chứa các mục tin chưa được hòa trộn"
msgid "refresh stat information"
msgstr "lấy lại thông tin thống kê"
msgid "like --refresh, but ignore assume-unchanged setting"
-msgstr "giống --refresh, nhÆ°ng bá» qua các cài đặt “assume-unchangedâ€"
+msgstr "giống --refresh, nhưng bỠqua các cài đặt 'assume-unchanged'"
msgid "<mode>,<object>,<path>"
msgstr "<chế_Ä‘á»™>,<đối_tượng>,<Ä‘Æ°á»ng_dẫn>"
msgid "add the specified entry to the index"
-msgstr "thêm các tập tin đã chỉ ra vào bảng mục lục"
+msgstr "thêm các tập tin đã chỉ ra vào chỉ mục"
msgid "mark files as \"not changing\""
msgstr "đánh dấu các tập tin là \"không thay đổi\""
@@ -12753,7 +13173,7 @@ msgid "clear assumed-unchanged bit"
msgstr "xóa bít assumed-unchanged (giả định là không thay đổi)"
msgid "mark files as \"index-only\""
-msgstr "đánh dấu các tập tin là “chỉ-Ä‘á»câ€"
+msgstr "đánh dấu các tập tin là 'chỉ-Ä‘á»c'"
msgid "clear skip-worktree bit"
msgstr "xóa bít skip-worktree"
@@ -12762,8 +13182,7 @@ msgid "do not touch index-only entries"
msgstr "đừng động vào các mục index-only"
msgid "add to index only; do not add content to object database"
-msgstr ""
-"chỉ thêm vào bảng mục lục; không thêm nội dung vào cơ sở dữ liệu đối tượng"
+msgstr "chỉ thêm vào chỉ mục; không thêm nội dung vào cơ sở dữ liệu đối tượng"
msgid "remove named paths even if present in worktree"
msgstr ""
@@ -12771,13 +13190,13 @@ msgstr ""
"làm việc"
msgid "with --stdin: input lines are terminated by null bytes"
-msgstr "vá»›i tùy chá»n --stdin: các dòng đầu vào được chấm dứt bởi ký tá»± null"
+msgstr "vá»›i tùy chá»n --stdin: các dòng đầu vào được kết thúc bởi ký tá»± null"
msgid "read list of paths to be updated from standard input"
-msgstr "Ä‘á»c danh sách Ä‘Æ°á»ng dẫn cần cập nhật từ đầu vào tiêu chuẩn"
+msgstr "Ä‘á»c danh sách Ä‘Æ°á»ng dẫn cần cập nhật từ stdin"
msgid "add entries from standard input to the index"
-msgstr "không thể Ä‘á»c các mục từ đầu vào tiêu chuẩn vào bảng mục lục"
+msgstr "không thể Ä‘á»c các mục từ stdin vào chỉ mục"
msgid "repopulate stages #2 and #3 for the listed paths"
msgstr "phục hồi các trạng thái #2 và #3 cho các Ä‘Æ°á»ng dẫn được liệt kê"
@@ -12789,16 +13208,19 @@ msgid "ignore files missing from worktree"
msgstr "bỠqua các tập-tin thiếu trong thư-mục làm việc"
msgid "report actions to standard output"
-msgstr "báo cáo các thao tác ra thiết bị xuất chuẩn"
+msgstr "ghi các thao tác ra stdout"
msgid "(for porcelains) forget saved unresolved conflicts"
-msgstr "(cho “porcelainsâ€) quên các xung Ä‘á»™t chÆ°a được giải quyết đã ghi"
+msgstr "(cho 'porcelains') quên các xung đột chưa được giải quyết đã ghi"
msgid "write index in this format"
-msgstr "ghi mục lục ở định dạng này"
+msgstr "ghi chỉ mục ở định dạng này"
+
+msgid "report on-disk index format version"
+msgstr "cho biết phiên bản định dạng chỉ mục trên đĩa"
msgid "enable or disable split index"
-msgstr "bật/tắt chia cắt bảng mục lục"
+msgstr "bật/tắt chia cắt chỉ mục"
msgid "enable/disable untracked cache"
msgstr "bật/tắt bộ đệm không theo vết"
@@ -12810,7 +13232,7 @@ msgid "enable untracked cache without testing the filesystem"
msgstr "bật bộ đệm không theo vết mà không kiểm tra hệ thống tập tin"
msgid "write out the index even if is not flagged as changed"
-msgstr "ghi ra mục lục ngay cả khi không được đánh cỠlà có thay đổi"
+msgstr "ghi ra chỉ mục ngay cả khi không được đánh cỠlà có thay đổi"
msgid "enable or disable file system monitor"
msgstr "bật/tắt theo dõi hệ thống tập tin"
@@ -12821,19 +13243,27 @@ msgstr "đánh dấu các tập tin là hợp lệ fsmonitor"
msgid "clear fsmonitor valid bit"
msgstr "xóa bít hợp lệ fsmonitor"
+#, c-format
+msgid "%d\n"
+msgstr "%d\n"
+
+#, c-format
+msgid "index-version: was %d, set to %d"
+msgstr "index-version: đang là %d, đặt vỠ%d"
+
msgid ""
"core.splitIndex is set to false; remove or change it, if you really want to "
"enable split index"
msgstr ""
"core.splitIndex được đặt là sai; xóa bỠhay thay đổi nó, nếu bạn thực sự "
-"muốn bật chia tách mục lục"
+"muốn bật chia tách chỉ mục"
msgid ""
"core.splitIndex is set to true; remove or change it, if you really want to "
"disable split index"
msgstr ""
"core.splitIndex được đặt là đúng; xóa bỠhay thay đổi nó, nếu bạn thực sự "
-"muốn tắt chia tách mục lục"
+"muốn tắt chia tách chỉ mục"
msgid ""
"core.untrackedCache is set to true; remove or change it, if you really want "
@@ -12854,7 +13284,7 @@ msgstr ""
#, c-format
msgid "Untracked cache enabled for '%s'"
-msgstr "Nhá»› đệm không theo vết được bật cho “%sâ€"
+msgstr "Nhớ đệm không theo vết được bật cho '%s'"
msgid "core.fsmonitor is unset; set it if you really want to enable fsmonitor"
msgstr ""
@@ -12873,11 +13303,11 @@ msgstr ""
msgid "fsmonitor disabled"
msgstr "fsmonitor bị tắt"
-msgid "git update-ref [<options>] -d <refname> [<old-val>]"
-msgstr "git update-ref [<các tùy chá»n>] -d <refname> [<biến-cÅ©>]"
+msgid "git update-ref [<options>] -d <refname> [<old-oid>]"
+msgstr "git update-ref [<các tùy chá»n>] -d <refname> [<oid-cÅ©>]"
-msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]"
-msgstr "git update-ref [<các tùy chá»n>] <refname> <biến-má»›i> [<biến-cÅ©>]"
+msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]"
+msgstr "git update-ref [<các tùy chá»n>] <refname> <oid-má»›i> [<oid-cÅ©>]"
msgid "git update-ref [<options>] --stdin [-z]"
msgstr "git update-ref [<các tùy chá»n>] --stdin [-z]"
@@ -12889,19 +13319,23 @@ msgid "update <refname> not the one it points to"
msgstr "cập nhật <tên-tham-chiếu> không phải cái nó chỉ tới"
msgid "stdin has NUL-terminated arguments"
-msgstr "đầu vào tiêu chuẩn có các đối số được chấm dứt bởi NUL"
+msgstr "stdin có các đối số được kết thúc bởi NUL"
msgid "read updates from stdin"
-msgstr "Ä‘á»c cập nhật từ đầu vào tiêu chuẩn"
+msgstr "Ä‘á»c cập nhật từ stdin"
msgid "update the info files from scratch"
msgstr "cập nhật các tập tin thông tin từ điểm xuất phát"
-msgid "git upload-pack [<options>] <dir>"
-msgstr "git upload-pack [<các tùy chá»n>] </Ä‘Æ°á»ng/dẫn>"
+msgid ""
+"git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n"
+" [--advertise-refs] <directory>"
+msgstr ""
+"git-upload-pack [--[no-]strict] [--timeout=<n>] [--stateless-rpc]\n"
+" [--advertise-refs] <thư mục>"
msgid "quit after a single request/response exchange"
-msgstr "thoát sau khi má»™t trao đổi yêu cầu hay trả lá»i Ä‘Æ¡n"
+msgstr "thoát sau má»™t trao đổi yêu cầu/trả lá»i"
msgid "serve up the info/refs for git-http-backend"
msgstr "phục vụ info/refs (thông tin/tham chiếu) cho git-http-backend"
@@ -12912,8 +13346,8 @@ msgstr "đừng thử <thư_mục>/.git/ nếu <thư_mục> không phải là th
msgid "interrupt transfer after <n> seconds of inactivity"
msgstr "ngắt truyá»n thông sau <n> giây không hoạt Ä‘á»™ng"
-msgid "git verify-commit [-v | --verbose] <commit>..."
-msgstr "git verify-commit [-v | --verbose] <lần_chuyển_giao>…"
+msgid "git verify-commit [-v | --verbose] [--raw] <commit>..."
+msgstr "git verify-commit [-v | --verbose] [--raw] <lần_chuyển_giao>..."
msgid "print commit contents"
msgstr "hiển thị nội dung của lần chuyển giao"
@@ -12921,8 +13355,8 @@ msgstr "hiển thị nội dung của lần chuyển giao"
msgid "print raw gpg status output"
msgstr "in kết xuất trạng thái gpg dạng thô"
-msgid "git verify-pack [-v | --verbose] [-s | --stat-only] <pack>..."
-msgstr "git verify-pack [-v | --verbose] [-s | --stat-only] <gói>…"
+msgid "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <pack>.idx..."
+msgstr "git verify-pack [-v | --verbose] [-s | --stat-only] [--] <gói>.idx..."
msgid "verbose"
msgstr "chi tiết"
@@ -12930,69 +13364,106 @@ msgstr "chi tiết"
msgid "show statistics only"
msgstr "chỉ hiển thị thống kê"
-msgid "git verify-tag [-v | --verbose] [--format=<format>] <tag>..."
-msgstr "git verify-tag [-v | --verbose] [--format=<định_dạng>] <thẻ>…"
+msgid "git verify-tag [-v | --verbose] [--format=<format>] [--raw] <tag>..."
+msgstr ""
+"git verify-tag [-v | --verbose] [--format=<định dạng>] [--raw] <thẻ>..."
msgid "print tag contents"
msgstr "hiển thị nội dung của thẻ"
-msgid "git worktree add [<options>] <path> [<commit-ish>]"
-msgstr "git worktree add [<các tùy chá»n>] </Ä‘Æ°á»ng/dẫn> [<commit-ish>]"
+msgid ""
+"git worktree add [-f] [--detach] [--checkout] [--lock [--reason <string>]]\n"
+" [--orphan] [(-b | -B) <new-branch>] <path> [<commit-ish>]"
+msgstr ""
+"git worktree add [-f] [--detach] [--checkout] [--lock [--reason <lý do>]]\n"
+" [--orphan] [(-b | -B) <nhánh-má»›i>] <Ä‘Æ°á»ng/dẫn> [<commit-"
+"ish>]"
-msgid "git worktree list [<options>]"
-msgstr "git worktree list [<các tùy chá»n>]"
+msgid "git worktree list [-v | --porcelain [-z]]"
+msgstr "git worktree list [-v | --porcelain [-z]]"
-msgid "git worktree lock [<options>] <path>"
-msgstr "git worktree lock [<các tùy chá»n>] </Ä‘Æ°á»ng/dẫn>"
+msgid "git worktree lock [--reason <string>] <worktree>"
+msgstr "git worktree lock [--reason <lý do>] <cây làm việc>"
msgid "git worktree move <worktree> <new-path>"
-msgstr "git worktree move <worktree> </Ä‘Æ°á»ng/dẫn/má»›i>"
+msgstr "git worktree move <cây làm việc> </Ä‘Æ°á»ng/dẫn/má»›i>"
-msgid "git worktree prune [<options>]"
-msgstr "git worktree prune [<các tùy chá»n>]"
+msgid "git worktree prune [-n] [-v] [--expire <expire>]"
+msgstr "git worktree prune [-n] [-v] [--expire <khi nào hết hạn>]"
-msgid "git worktree remove [<options>] <worktree>"
-msgstr "git worktree remove [<các tùy chá»n>] <worktree>"
+msgid "git worktree remove [-f] <worktree>"
+msgstr "git worktree remove [-f] <cây làm việc>"
msgid "git worktree repair [<path>...]"
msgstr "git worktree repair [</Ä‘Æ°á»ng/dẫn/>...]"
-msgid "git worktree unlock <path>"
-msgstr "git worktree unlock </Ä‘Æ°á»ng/dẫn>"
+msgid "git worktree unlock <worktree>"
+msgstr "git worktree unlock <cây làm việc>"
+
+msgid "No possible source branch, inferring '--orphan'"
+msgstr "Không có nhánh gốc, đoán là --orphan"
+
+#, c-format
+msgid ""
+"If you meant to create a worktree containing a new unborn branch\n"
+"(branch with no commits) for this repository, you can do so\n"
+"using the --orphan flag:\n"
+"\n"
+" git worktree add --orphan -b %s %s\n"
+msgstr ""
+"Nếu bạn muốn tạo cây làm việc với nhánh chưa sinh\n"
+"(nhánh chưa có lần chuyển giao) cho kho chứa này, bạn có thể dùng\n"
+"tuỳ chá»n --orphan:\n"
+"\n"
+" git worktree add --orphan -b %s %s\n"
+
+#, c-format
+msgid ""
+"If you meant to create a worktree containing a new unborn branch\n"
+"(branch with no commits) for this repository, you can do so\n"
+"using the --orphan flag:\n"
+"\n"
+" git worktree add --orphan %s\n"
+msgstr ""
+"Nếu bạn muốn tạo cây làm việc với nhánh chưa sinh\n"
+"(nhánh chưa có lần chuyển giao) cho kho chứa này, bạn có thể dùng\n"
+"tuỳ chá»n --orphan:\n"
+"\n"
+" git worktree add --orphan %s\n"
#, c-format
msgid "Removing %s/%s: %s"
msgstr "Äang xóa %s/%s: %s"
msgid "report pruned working trees"
-msgstr "báo cáo các cây làm việc đã prune"
+msgstr "liệt kê các cây làm việc đã prune"
msgid "expire working trees older than <time>"
msgstr "các cây làm việc hết hạn cÅ© hÆ¡n khoảng <thá»i gian>"
#, c-format
msgid "'%s' already exists"
-msgstr "“%s†đã có từ trước rồi"
+msgstr "'%s' đã có từ trước rồi"
#, c-format
msgid "unusable worktree destination '%s'"
-msgstr "đích cây làm việc không sá»­ dụng được “%sâ€"
+msgstr "đích cây làm việc không sử dụng được '%s'"
#, c-format
msgid ""
"'%s' is a missing but locked worktree;\n"
"use '%s -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear"
msgstr ""
-"“%s†bị mất nhưng cây làm việc bị khóa;\n"
-"dùng “%s -f -f†để ghi đè, hoặc “unlock†và “prune†hay “remove†để xóa"
+"'%s' bị mất nhưng cây làm việc bị khóa;\n"
+"dùng '%s -f -f' để ghi đè, hoặc 'unlock' và 'prune' hay 'remove' để xóa"
#, c-format
msgid ""
"'%s' is a missing but already registered worktree;\n"
"use '%s -f' to override, or 'prune' or 'remove' to clear"
msgstr ""
-"“%s†bị mất nhưng cây làm việc đã được đăng ký;\n"
-"dùng “%s -f†để ghi đè, hoặc “prune†hay “remove†để xóa"
+"'%s' bị mất nhưng cây làm việc đã được đăng ký;\n"
+"dùng '%s -f' để ghi đè, hoặc 'prune' hay 'remove' để xóa"
#, c-format
msgid "failed to copy '%s' to '%s'; sparse-checkout may not work correctly"
@@ -13000,37 +13471,62 @@ msgstr "gặp lỗi khi sao chép '%s' sang '%s'; không thể làm việc đún
#, c-format
msgid "failed to copy worktree config from '%s' to '%s'"
-msgstr "gặp lá»—i khi sao chép cấu hình cây làm việc từ “%s†sang “%sâ€"
+msgstr "gặp lỗi khi sao chép cấu hình cây làm việc từ '%s' sang '%s'"
#, c-format
msgid "failed to unset '%s' in '%s'"
-msgstr "gặp lá»—i bỠđặt “%s†trong “%sâ€"
+msgstr "gặp lỗi bỠđặt '%s' trong '%s'"
#, c-format
msgid "could not create directory of '%s'"
-msgstr "không thể tạo thÆ° mục của “%sâ€"
+msgstr "không thể tạo thư mục của '%s'"
msgid "initializing"
msgstr "khởi tạo"
#, c-format
+msgid "could not find created worktree '%s'"
+msgstr "không tìm thấy cây làm việc '%s'"
+
+#, c-format
msgid "Preparing worktree (new branch '%s')"
-msgstr "Äang chuẩn bị cây làm việc (nhánh má»›i “%sâ€)"
+msgstr "Äang chuẩn bị cây làm việc (nhánh má»›i '%s')"
#, c-format
msgid "Preparing worktree (resetting branch '%s'; was at %s)"
-msgstr "Äang chuẩn bị cây làm việc (Ä‘ang cài đặt nhánh “%sâ€, trÆ°á»›c đây tại %s)"
+msgstr "Äang chuẩn bị cây làm việc (Ä‘ang tái đặt nhánh '%s'; trÆ°á»›c đây tại %s)"
#, c-format
msgid "Preparing worktree (checking out '%s')"
-msgstr "Äang chuẩn bị cây làm việc (Ä‘ang lấy ra “%sâ€)"
+msgstr "Äang chuẩn bị cây làm việc (Ä‘ang checkout '%s')"
+
+#, c-format
+msgid "unreachable: invalid reference: %s"
+msgstr "không tham chiếu được: tham chiếu không hợp lệ: %s"
#, c-format
msgid "Preparing worktree (detached HEAD %s)"
-msgstr "Äang chuẩn bị cây làm việc (HEAD đã tách rá»i “%sâ€)"
+msgstr "Äang chuẩn bị cây làm việc (HEAD đã tách rá»i '%s')"
+
+#, c-format
+msgid ""
+"HEAD points to an invalid (or orphaned) reference.\n"
+"HEAD path: '%s'\n"
+"HEAD contents: '%s'"
+msgstr ""
+"HEAD trỠđến tham chiếu sai (hoặc mồ côi).\n"
+"ÄÆ°á»ng dẫn HEAD: '%s'\n"
+"Ná»™i dung HEAD: '%s'"
+
+msgid ""
+"No local or remote refs exist despite at least one remote\n"
+"present, stopping; use 'add -f' to override or fetch a remote first"
+msgstr ""
+"Không tồn tại tham chiếu cục bộ hay trên máy chủ mặc dù có cấu hình\n"
+"máy chủ, dừng lại; hãy dùng 'add -f' để ép buộc hoặc thực hiện kéo vỠtrước"
msgid "checkout <branch> even if already checked out in other worktree"
-msgstr "lấy ra <nhánh> ngay cả khi nó đã được lấy ra ở cây làm việc khác"
+msgstr "checkout <nhánh> ngay cả khi nó đã được checkout ở cây làm việc khác"
msgid "create a new branch"
msgstr "tạo nhánh mới"
@@ -13038,11 +13534,14 @@ msgstr "tạo nhánh mới"
msgid "create or reset a branch"
msgstr "tạo hay đặt lại một nhánh"
+msgid "create unborn branch"
+msgstr "tạo nhánh chưa sinh"
+
msgid "populate the new working tree"
msgstr "di chuyển cây làm việc mới"
msgid "keep the new working tree locked"
-msgstr "giữ cây làm việc mới bị khóa"
+msgstr "tiếp tục khoá cây làm việc mới"
msgid "reason for locking"
msgstr "lý do khóa"
@@ -13057,6 +13556,10 @@ msgstr "có khá»›p tên tên nhánh má»›i vá»›i má»™t nhánh theo dõi máy chá»
msgid "options '%s', '%s', and '%s' cannot be used together"
msgstr "tùy chá»n '%s', '%s' và '%s' không thể dùng cùng nhau"
+#, c-format
+msgid "option '%s' and commit-ish cannot be used together"
+msgstr "tùy chá»n '%s' và commit-ish không thể dùng cùng nhau"
+
msgid "added with --lock"
msgstr "được thêm với --lock"
@@ -13068,30 +13571,30 @@ msgstr "hiển thị chú thích và lý do mở rộng, nếu có"
msgid "add 'prunable' annotation to worktrees older than <time>"
msgstr ""
-"thêm chú thích kiểu “prunable†cho các cây làm việc hết hạn cũ hơn khoảng "
+"thêm chú thích kiểu 'prunable' cho các cây làm việc hết hạn cũ hơn khoảng "
"<thá»i gian>"
msgid "terminate records with a NUL character"
-msgstr "chấm dứt các bản ghi bằng ký tự NULL"
+msgstr "kết thúc các bản ghi bằng ký tự NULL"
#, c-format
msgid "'%s' is not a working tree"
msgstr "%s không phải là cây làm việc"
msgid "The main working tree cannot be locked or unlocked"
-msgstr "Cây thư mục làm việc chính không thể khóa hay bỠkhóa được"
+msgstr "Cây làm việc chính không thể khóa hay bỠkhóa được"
#, c-format
msgid "'%s' is already locked, reason: %s"
-msgstr "“%s†đã được khóa rồi, lý do: %s"
+msgstr "'%s' đã được khóa rồi, lý do: %s"
#, c-format
msgid "'%s' is already locked"
-msgstr "“%s†đã được khóa rồi"
+msgstr "'%s' đã được khóa rồi"
#, c-format
msgid "'%s' is not locked"
-msgstr "“%s†chưa bị khóa"
+msgstr "'%s' chưa bị khóa"
msgid "working trees containing submodules cannot be moved or removed"
msgstr "cây làm việc có chứa mô-Ä‘un-con không thể di chuyển hay xóa bá»"
@@ -13101,11 +13604,11 @@ msgstr "ép buộc ngay cả khi cây làm việc đang bẩn hay bị khóa"
#, c-format
msgid "'%s' is a main working tree"
-msgstr "“%s†là cây làm việc chính"
+msgstr "'%s' là cây làm việc chính"
#, c-format
msgid "could not figure out destination name from '%s'"
-msgstr "không thể phác há»a ra tên đích đến “%sâ€"
+msgstr "không thể phác há»a ra tên đích đến '%s'"
#, c-format
msgid ""
@@ -13113,14 +13616,14 @@ msgid ""
"use 'move -f -f' to override or unlock first"
msgstr ""
"không thể di chuyển một cây-làm-việc bị khóa, khóa vì: %s\n"
-"dùng “move -f -f†để ghi đè hoặc mở khóa trước đã"
+"dùng 'move -f -f' để ghi đè hoặc mở khóa trước đã"
msgid ""
"cannot move a locked working tree;\n"
"use 'move -f -f' to override or unlock first"
msgstr ""
"không thể di chuyển một cây-làm-việc bị khóa;\n"
-"dùng “move -f -f†để ghi đè hoặc mở khóa trước đã"
+"dùng 'move -f -f' để ghi đè hoặc mở khóa trước đã"
#, c-format
msgid "validation failed, cannot move working tree: %s"
@@ -13128,21 +13631,21 @@ msgstr "thẩm tra gặp lỗi, không thể di chuyển một cây-làm-việc:
#, c-format
msgid "failed to move '%s' to '%s'"
-msgstr "gặp lá»—i khi chuyển “%s†sang “%sâ€"
+msgstr "gặp lỗi khi chuyển '%s' sang '%s'"
#, c-format
msgid "failed to run 'git status' on '%s'"
-msgstr "gặp lá»—i khi chạy “git status†vào “%sâ€"
+msgstr "gặp lỗi khi chạy 'git status' vào '%s'"
#, c-format
msgid "'%s' contains modified or untracked files, use --force to delete it"
msgstr ""
-"“%s†có chứa các tập tin đã bị sửa chữa hoặc chưa được theo dõi, hãy dùng --"
+"'%s' có chứa các tập tin đã bị sửa chữa hoặc chưa được theo dõi, hãy dùng --"
"force để xóa nó"
#, c-format
msgid "failed to run 'git status' on '%s', code %d"
-msgstr "gặp lá»—i khi chạy “git status†trong “%sâ€, mã %d"
+msgstr "gặp lỗi khi chạy 'git status' trong '%s', mã %d"
msgid "force removal even if worktree is dirty or locked"
msgstr "ép buộc di chuyển thậm chí cả khi cây làm việc đang bẩn hay bị khóa"
@@ -13153,14 +13656,14 @@ msgid ""
"use 'remove -f -f' to override or unlock first"
msgstr ""
"không thể xóa bỠmột cây-làm-việc bị khóa, khóa vì: %s\n"
-"dùng “remove -f -f†để ghi đè hoặc mở khóa trước đã"
+"dùng 'remove -f -f' để ghi đè hoặc mở khóa trước đã"
msgid ""
"cannot remove a locked working tree;\n"
"use 'remove -f -f' to override or unlock first"
msgstr ""
"không thể xóa bỠmột cây-làm-việc bị khóa;\n"
-"dùng “remove -f -f†để ghi đè hoặc mở khóa trước đã"
+"dùng 'remove -f -f' để ghi đè hoặc mở khóa trước đã"
#, c-format
msgid "validation failed, cannot remove working tree: %s"
@@ -13186,17 +13689,73 @@ msgstr "ghi đối tượng cây (tree) cho <tiá»n tố> thÆ° mục con"
msgid "only useful for debugging"
msgstr "chỉ hữu ích khi cần gỡ lỗi"
+msgid "core.fsyncMethod = batch is unsupported on this platform"
+msgstr "core.fsyncMethod = batch không được há»— trợ trên ná»n tảng này"
+
+#, c-format
+msgid "could not parse bundle list key %s with value '%s'"
+msgstr "không thể Ä‘á»c danh sách bundle khoá %s giá trị '%s'"
+
+#, c-format
+msgid "bundle list at '%s' has no mode"
+msgstr "bundle list at '%s' has no mode"
+
+msgid "failed to create temporary file"
+msgstr "không thể tạo tập tin tạm thá»i"
+
+msgid "insufficient capabilities"
+msgstr "không đủ quyá»n hạn"
+
+#, c-format
+msgid "file downloaded from '%s' is not a bundle"
+msgstr "tập tin lấy vỠtừ '%s' không phải là bundle"
+
+msgid "failed to store maximum creation token"
+msgstr "gặp lỗi khi lưu token tạo tối đa"
+
+#, c-format
+msgid "unrecognized bundle mode from URI '%s'"
+msgstr "không nhận ra định dạng bundle từ URI '%s'"
+
+#, c-format
+msgid "exceeded bundle URI recursion limit (%d)"
+msgstr "vượt quá giới hạn đệ quy URI (%d)"
+
+#, c-format
+msgid "failed to download bundle from URI '%s'"
+msgstr "gặp lỗi khi tải bundle từ URI '%s'"
+
+#, c-format
+msgid "file at URI '%s' is not a bundle or bundle list"
+msgstr "tập tin ở URI '%s' không phải bundle hay danh sách bundle"
+
+#, c-format
+msgid "bundle-uri: unexpected argument: '%s'"
+msgstr "bundle-uri: không nhận ra đối số: '%s'"
+
+msgid "bundle-uri: expected flush after arguments"
+msgstr "bundle-uri: cần flush dữ liệu sau các tham số"
+
+msgid "bundle-uri: got an empty line"
+msgstr "bundle-uri: nhận được dòng trống"
+
+msgid "bundle-uri: line is not of the form 'key=value'"
+msgstr "bundle-uri: dòng không có dạng 'key=value'"
+
+msgid "bundle-uri: line has empty key or value"
+msgstr "bundle-uri: dòng có key trống hoặc value trống"
+
#, c-format
msgid "unrecognized bundle hash algorithm: %s"
-msgstr "không hiểu thuật toán băm dữ liệu bundle: %s"
+msgstr "không hiểu thuật toán băm bundle: %s"
#, c-format
msgid "unknown capability '%s'"
-msgstr "không hiểu dung lượng “%sâ€"
+msgstr "không hiểu dung lượng '%s'"
#, c-format
msgid "'%s' does not look like a v2 or v3 bundle file"
-msgstr "“%s†không giống như tập tin v2 hay v3 bundle (định dạng dump của git)"
+msgstr "'%s' không giống như tập tin bundle v2 hay v3 (định dạng dump của git)"
#, c-format
msgid "unrecognized header: %s%s (%d)"
@@ -13208,6 +13767,13 @@ msgstr "Kho chứa thiếu những lần chuyển giao tiên quyết này:"
msgid "need a repository to verify a bundle"
msgstr "cần một kho chứa để thẩm tra một bundle"
+msgid ""
+"some prerequisite commits exist in the object store, but are not connected "
+"to the repository's history"
+msgstr ""
+"một số lần chuyển giao tiên quyết tồn tại trong object store, nhưng không "
+"nằm trong lịch sử của kho chứa"
+
#, c-format
msgid "The bundle contains this ref:"
msgid_plural "The bundle contains these %<PRIuMAX> refs:"
@@ -13221,18 +13787,26 @@ msgid "The bundle requires this ref:"
msgid_plural "The bundle requires these %<PRIuMAX> refs:"
msgstr[0] "Lệnh bundle yêu cầu %<PRIuMAX> tham chiếu này:"
+#, c-format
+msgid "The bundle uses this hash algorithm: %s"
+msgstr "Lệnh bundle dùng thuật toán băm sau: %s"
+
+#, c-format
+msgid "The bundle uses this filter: %s"
+msgstr "Lệnh bundle dùng bá»™ lá»c sau: %s"
+
msgid "unable to dup bundle descriptor"
-msgstr "không thể nhân đôi bộ mô tả bundle"
+msgstr "không thể dup bundle descriptor"
msgid "Could not spawn pack-objects"
-msgstr "Không thể sản sinh đối tượng gói"
+msgstr "Không thể spawn pack-objects"
msgid "pack-objects died"
-msgstr "đối tượng gói đã chết"
+msgstr "pack-objects đã chết"
#, c-format
msgid "ref '%s' is excluded by the rev-list options"
-msgstr "th.chiếu “%s†bị loại trừ bởi các tùy chá»n rev-list"
+msgstr "th.chiếu '%s' bị loại trừ bởi các tùy chá»n rev-list"
#, c-format
msgid "unsupported bundle version %d"
@@ -13247,25 +13821,29 @@ msgstr "Từ chối tạo một bó dữ liệu trống rỗng."
#, c-format
msgid "cannot create '%s'"
-msgstr "không thể tạo “%sâ€"
+msgstr "không thể tạo '%s'"
msgid "index-pack died"
-msgstr "mục lục gói đã chết"
+msgstr "index-pack đã chết"
msgid "terminating chunk id appears earlier than expected"
-msgstr "mã mảnh kết thúc sá»›m hÆ¡n bình thÆ°á»ng"
+msgstr "id chunk kết thúc sá»›m hÆ¡n bình thÆ°á»ng"
+
+#, c-format
+msgid "chunk id %<PRIx32> not %d-byte aligned"
+msgstr "id chunk %<PRIx32> không thẳng %d-byte"
#, c-format
msgid "improper chunk offset(s) %<PRIx64> and %<PRIx64>"
-msgstr "bù mảnh không đúng cách %<PRIx64> và %<PRIx64>"
+msgstr "chunk offset bất thÆ°á»ng %<PRIx64> và %<PRIx64>"
#, c-format
msgid "duplicate chunk ID %<PRIx32> found"
-msgstr "tìm thấy ID của mảnh bị trùng lặp %<PRIx32>"
+msgstr "tìm thấy ID của chunk bị trùng lặp %<PRIx32>"
#, c-format
msgid "final chunk has non-zero id %<PRIx32>"
-msgstr "mảnh cuối cùng có id không bằng không %<PRIx32>"
+msgstr "chunk cuối cùng có id không bằng không %<PRIx32>"
msgid "invalid hash version"
msgstr "phiên bản băm không hợp lệ"
@@ -13275,7 +13853,7 @@ msgid "invalid color value: %.*s"
msgstr "giá trị màu không hợp lệ: %.*s"
msgid "Add file contents to the index"
-msgstr "Thêm nội dung tập tin vào bảng mục lục"
+msgstr "Thêm nội dung tập tin vào chỉ mục"
msgid "Apply a series of patches from a mailbox"
msgstr "Ãp dụng má»™t chuá»—i các miếng và từ má»™t mailbox"
@@ -13284,8 +13862,7 @@ msgid "Annotate file lines with commit information"
msgstr "Các dòng diễn giải tập tin với thông tin chuyển giao"
msgid "Apply a patch to files and/or to the index"
-msgstr ""
-"Ãp dụng má»™t miếng vá cho các tập tin đã chỉ ra và/hoặc vào bảng mục lục"
+msgstr "Ãp dụng má»™t bản vá cho các tập tin đã chỉ ra và/hoặc vào chỉ mục"
msgid "Import a GNU Arch repository into Git"
msgstr "Nhập một kho GNU Arch vào một kho Git"
@@ -13310,8 +13887,8 @@ msgstr "SÆ°u tập thông tin ngÆ°á»i dùng để báo cáo lá»—i"
msgid "Move objects and refs by archive"
msgstr "Di chuyển các đối tượng và tham chiếu theo kho lưu"
-msgid "Provide content or type and size information for repository objects"
-msgstr "Cung cấp nội dung hoặc thông tin vỠkiểu và cỡ cho các đối tượng kho"
+msgid "Provide contents or details of repository objects"
+msgstr "Cung cấp nội dung hoặc thông tin vỠcác đối tượng kho"
msgid "Display gitattributes information"
msgstr "Hiển thị thông tin gitattributes"
@@ -13326,13 +13903,13 @@ msgid "Ensures that a reference name is well formed"
msgstr "Äảm bảo rằng má»™t tên tham chiếu ở dạng thức tốt"
msgid "Switch branches or restore working tree files"
-msgstr "Chuyển các nhánh hoặc phục hồi lại các tập tin cây làm việc"
+msgstr "Chuyển các nhánh hoặc phục hồi lại các tập tin trong cây làm việc"
msgid "Copy files from the index to the working tree"
-msgstr "Sao chép các tập tin từ mục lục ra cây làm việc"
+msgstr "Sao chép các tập tin từ chỉ mục ra cây làm việc"
msgid "Find commits yet to be applied to upstream"
-msgstr "Tìm những lần chuyển giao còn chưa được áp dụng lên thượng nguồn"
+msgstr "Tìm những lần chuyển giao chưa được đẩy lên thượng nguồn"
msgid "Apply the changes introduced by some existing commits"
msgstr "Ãp dụng các thay đổi được Ä‘Æ°a ra bởi má»™t số lần chuyển giao sẵn có"
@@ -13369,13 +13946,13 @@ msgid "Retrieve and store user credentials"
msgstr "Nhận và lÆ°u chứng nhận của ngÆ°á»i dùng"
msgid "Helper to temporarily store passwords in memory"
-msgstr "Bá»™ há»— trợ để lÆ°u mật khẩu tạm thá»i trong bá»™ nhá»›"
+msgstr "helper để lÆ°u mật khẩu tạm thá»i trong bá»™ nhá»›"
msgid "Helper to store credentials on disk"
-msgstr "Bộ hỗ trợ để lưu chứng nhận vào đĩa"
+msgstr "helper để lưu chứng nhận vào đĩa"
msgid "Export a single commit to a CVS checkout"
-msgstr "Xuất một lần chuyển giao thành một lần lấy ra CVS"
+msgstr "Xuất một lần chuyển giao thành một lần checkout CVS"
msgid "Salvage your data out of another SCM people love to hate"
msgstr "Xem xét giá trị dữ liệu của bạn khá»i ngÆ°á»i khác yêu SCM để ghét"
@@ -13384,23 +13961,26 @@ msgid "A CVS server emulator for Git"
msgstr "Má»™t bá»™ mô phá»ng máy dịch vụ CVS cho Git"
msgid "A really simple server for Git repositories"
-msgstr "Một máy phục vụ thực sự đơn giản dành cho kho Git"
+msgstr "Một máy chủ thực sự đơn giản dành cho kho Git"
msgid "Give an object a human readable name based on an available ref"
msgstr ""
"ÄÆ°a ra má»™t đối tượng dá»±a trên má»™t tên ở dạng con ngÆ°á»i Ä‘á»c được trên má»™t "
"tham chiếu sẵn có"
+msgid "Generate a zip archive of diagnostic information"
+msgstr "tạo tập tin nén zip của bản báo cáo"
+
msgid "Show changes between commits, commit and working tree, etc"
msgstr ""
"Hiển thị các thay đổi giữa những lần chuyển giao, giữa một lần chuyển giao "
"và cây làm việc, v.v.."
msgid "Compares files in the working tree and the index"
-msgstr "So sánh các tập tin trong cây làm việc và bảng mục lục"
+msgstr "So sánh các tập tin trong cây làm việc và chỉ mục"
msgid "Compare a tree to the working tree or index"
-msgstr "So sánh các cây trong cây làm việc hoặc bảng mục lục"
+msgstr "So sánh các cây trong cây làm việc hoặc chỉ mục"
msgid "Compares the content and mode of blobs found via two tree objects"
msgstr ""
@@ -13434,7 +14014,7 @@ msgid "Run a Git command on a list of repositories"
msgstr "Chạy lệnh Git trên danh sách các kho chứa"
msgid "Prepare patches for e-mail submission"
-msgstr "Chuẩn bị các miếng vá để gửi qua thư điện tử"
+msgstr "Chuẩn bị các bản vá để gửi qua thư điện tử"
msgid "Verifies the connectivity and validity of the objects in the database"
msgstr ""
@@ -13454,8 +14034,8 @@ msgstr "In ra những dòng khớp với một mẫu"
msgid "A portable graphical interface to Git"
msgstr "Má»™t giao diện đồ há»a khả chuyển cho Git"
-msgid "Compute object ID and optionally creates a blob from a file"
-msgstr "Tính toán ID đối tượng và tùy chá»n là tạo má»™t blob từ má»™t tập tin"
+msgid "Compute object ID and optionally create an object from a file"
+msgstr "Tính toán ID đối tượng và tùy tạo một object từ một tập tin"
msgid "Display help information about Git"
msgstr "Hiển thị thông tin trợ giúp vỠGit"
@@ -13464,7 +14044,7 @@ msgid "Run git hooks"
msgstr "Chạy các móc git"
msgid "Server side implementation of Git over HTTP"
-msgstr "Thi hành phía máy chủ của Git qua HTTP"
+msgstr "Hỗ trợ phía máy chủ của Git qua HTTP"
msgid "Download from a remote Git repository via HTTP"
msgstr "Tải vỠtừ một kho chứa Git trên mạng thông qua HTTP"
@@ -13473,11 +14053,10 @@ msgid "Push objects over HTTP/DAV to another repository"
msgstr "Äẩy các đối tượng lên thông qua HTTP/DAV đến kho chứa khác"
msgid "Send a collection of patches from stdin to an IMAP folder"
-msgstr ""
-"Gửi một bộ sưu tập các miếng vá từ đầu vào tiêu chuẩn đến một thư mục IMAP"
+msgstr "Gửi một bộ sưu tập các bản vá từ stdin đến một thư mục IMAP"
msgid "Build pack index file for an existing packed archive"
-msgstr "Xây dựng tập tin mục lục gói cho một kho nén đã đóng gói sẵn có"
+msgstr "Xây dựng tập tin chỉ mục gói cho một kho nén đã đóng gói sẵn có"
msgid "Create an empty Git repository or reinitialize an existing one"
msgstr "Tạo một kho git mới hay khởi tạo lại một kho đã tồn tại từ trước"
@@ -13486,13 +14065,13 @@ msgid "Instantly browse your working repository in gitweb"
msgstr "Duyệt ngay kho làm việc của bạn trong gitweb"
msgid "Add or parse structured information in commit messages"
-msgstr "Thêm hay phân tích thông tin cấu trúc trong ghi chú lần chuyển giao"
+msgstr "Thêm hay Ä‘á»c thông tin cấu trúc trong ghi chú lần chuyển giao"
msgid "Show commit logs"
msgstr "Hiển thị nhật ký các lần chuyển giao"
msgid "Show information about files in the index and the working tree"
-msgstr "Hiển thị thông tin vỠcác tập tin trong bảng mục lục và cây làm việc"
+msgstr "Hiển thị thông tin vỠcác tập tin trong chỉ mục và cây làm việc"
msgid "List references in a remote repository"
msgstr "Liệt kê các tham chiếu trong một kho chứa trên mạng"
@@ -13516,7 +14095,7 @@ msgid "Find as good common ancestors as possible for a merge"
msgstr "Tìm các tổ tiên chung tốt có thể được cho hòa trộn"
msgid "Run a three-way file merge"
-msgstr "Chạy má»™t hòa trá»™n tập tin “3-Ä‘Æ°á»ngâ€"
+msgstr "Chạy má»™t hòa trá»™n tập tin '3-Ä‘Æ°á»ng'"
msgid "Run a merge for files needing merging"
msgstr "Chạy một hòa trộn cho các tập tin cần hòa trộn"
@@ -13524,13 +14103,12 @@ msgstr "Chạy một hòa trộn cho các tập tin cần hòa trộn"
msgid "The standard helper program to use with git-merge-index"
msgstr "Một chương trình hỗ trợ tiêu chuẩn dùng với git-merge-index"
-msgid "Show three-way merge without touching index"
-msgstr "Hiển thị hòa trá»™n ba-Ä‘Æ°á»ng mà không đụng chạm đến mục lục"
+msgid "Perform merge without touching index or working tree"
+msgstr "Ãp dụng má»™t bản vá mà không Ä‘á»™ng chạm đến cây làm việc"
msgid "Run merge conflict resolution tools to resolve merge conflicts"
msgstr ""
-"Chạy công cụ phân giải xung đột hòa trộn để mà giải quyết các xung đột hòa "
-"trá»™n"
+"Chạy công cụ phân giải xung đột hòa trộn để giải quyết các xung đột hòa trộn"
msgid "Creates a tag object with extra validation"
msgstr "Tạo một đối tượng thẻ với kiểm tra mở rộng"
@@ -13563,7 +14141,7 @@ msgid "Pack heads and tags for efficient repository access"
msgstr "Äóng gói các phần đầu và thẻ để truy cập kho hiệu quả hÆ¡n"
msgid "Compute unique ID for a patch"
-msgstr "Tính toán ID duy nhất cho một miếng vá"
+msgstr "Tính toán ID duy nhất cho một bản vá"
msgid "Prune all unreachable objects from the object database"
msgstr ""
@@ -13579,16 +14157,16 @@ msgid "Update remote refs along with associated objects"
msgstr "Cập nhật th.chiếu máy chủ cùng với các đối tượng liên quan đến nó"
msgid "Applies a quilt patchset onto the current branch"
-msgstr "Ấp dụng một bộ miếng vá quilt vào trong nhánh hiện hành"
+msgstr "Ấp dụng một bộ bản vá quilt vào trong nhánh hiện hành"
msgid "Compare two commit ranges (e.g. two versions of a branch)"
msgstr "So sánh hai vùng chuyển giao (vd: hai phiên bản của một nhánh)"
msgid "Reads tree information into the index"
-msgstr "Äá»c thông tin cây vào trong mục lục"
+msgstr "Äá»c thông tin cây vào trong chỉ mục"
msgid "Reapply commits on top of another base tip"
-msgstr "Thu hoạch các lần chuyển giao trên đỉnh của đầu mút cơ sở khác"
+msgstr "Thu hoạch các lần chuyển giao trên đỉnh của đỉnh cơ sở khác"
msgid "Receive what is pushed into the repository"
msgstr "Nhận cái mà được đẩy vào trong kho"
@@ -13605,6 +14183,11 @@ msgstr "Äóng gói các đối tượng chÆ°a đóng gói ở má»™t kho chứa"
msgid "Create, list, delete refs to replace objects"
msgstr "Tạo, liệt kê, xóa các tham chiếu để thay thế các đối tượng"
+msgid "EXPERIMENTAL: Replay commits on a new base, works with bare repos too"
+msgstr ""
+"ÄANG TRONG QUà TRÃŒNH THỬ NGHIỆM: Phát lại lần chuyển giao vào gốc má»›i, dùng "
+"được trong kho chứa bare"
+
msgid "Generates a summary of pending changes"
msgstr "Tạo ra một tóm tắt các thay đổi còn treo"
@@ -13627,10 +14210,10 @@ msgid "Revert some existing commits"
msgstr "Hoàn lại một số lần chuyển giao sẵn có"
msgid "Remove files from the working tree and from the index"
-msgstr "Gỡ bỠcác tập tin từ cây làm việc và từ bảng mục lục"
+msgstr "Gỡ bỠcác tập tin từ cây làm việc và từ chỉ mục"
msgid "Send a collection of patches as emails"
-msgstr "Gửi một tập hợp của các miếng vá ở dạng thư điện tử"
+msgstr "Gửi một tập hợp của các bản vá ở dạng thư điện tử"
msgid "Push objects over Git protocol to another repository"
msgstr "Äẩy các đối tượng lên thông qua giao thức Git đến kho chứa khác"
@@ -13645,7 +14228,7 @@ msgid "Restricted login shell for Git-only SSH access"
msgstr "Hệ vỠđăng nhập có hạn chế cho truy cập SSH chỉ-Git"
msgid "Summarize 'git log' output"
-msgstr "Kết xuất “git log†dạng tóm tắt"
+msgstr "Kết xuất 'git log' dạng tóm tắt"
msgid "Show various types of objects"
msgstr "Hiển thị các kiểu khác nhau của các đối tượng"
@@ -13698,7 +14281,7 @@ msgid "Unpack objects from a packed archive"
msgstr "Gỡ các đối tượng khá»i má»™t kho lÆ°u đã đóng gói"
msgid "Register file contents in the working tree to the index"
-msgstr "Äăng ký ná»™i dung tập tin từ cây làm việc đến bảng mục lục"
+msgstr "Äăng ký ná»™i dung tập tin từ cây làm việc đến chỉ mục"
msgid "Update the object name stored in a ref safely"
msgstr "Cập nhật tên đối tượng được lưu trong một tham chiếu một cách an toàn"
@@ -13724,20 +14307,23 @@ msgstr "Kiểm tra lại các tập tin kho (lưu trữ, nén) Git đã được
msgid "Check the GPG signature of tags"
msgstr "Kiểm tra chữ ký GPG của các thẻ"
-msgid "Show logs with difference each commit introduces"
-msgstr "Hiển thị các nhật ký với từng lần chuyển giao khác nhau đưa ra"
+msgid "Display version information about Git"
+msgstr "Hiển thị thông tin vỠphiên bản Git"
+
+msgid "Show logs with differences each commit introduces"
+msgstr "Hiển thị nhật ký với thay đổi của từng lần chuyển giao"
msgid "Manage multiple working trees"
msgstr "Quản lý nhiá»u cây làm việc"
msgid "Create a tree object from the current index"
-msgstr "Tạo một đối tượng cây từ đầu vào tiêu chuẩn stdin hiện tại"
+msgstr "Tạo một đối tượng cây từ chỉ mục hiện tại"
msgid "Defining attributes per path"
msgstr "Äịnh nghÄ©a các thuá»™c tính cho má»—i Ä‘Æ°á»ng dẫn"
msgid "Git command-line interface and conventions"
-msgstr "Giao diện dòng lệnh Git và quy ước"
+msgstr "Giao diện dòng lệnh Git và các quy ước"
msgid "A Git core tutorial for developers"
msgstr "Hướng dẫn Git cơ bản cho nhà phát triển"
@@ -13752,22 +14338,40 @@ msgid "Tweaking diff output"
msgstr "Chỉnh kết xuất diff"
msgid "A useful minimum set of commands for Everyday Git"
-msgstr "Một tập hợp lệnh hữu dụng tối thiểu để dùng Git hàng ngày"
+msgstr "Tập hợp lệnh hữu dụng tối thiểu để dùng Git hàng ngày"
msgid "Frequently asked questions about using Git"
msgstr "Các câu há»i thÆ°á»ng gặp vá» cách sá»­ dụng Git"
+msgid "The bundle file format"
+msgstr "Äịnh dạng tập tin bundle"
+
+msgid "Chunk-based file formats"
+msgstr "Äịnh dạng tập tin dạng khúc"
+
+msgid "Git commit-graph format"
+msgstr "Äịnh dạng đồ-thị-chuyển-giao"
+
+msgid "Git index format"
+msgstr "Äịnh dạng chỉ mục"
+
+msgid "Git pack format"
+msgstr "Äịnh dạng pack"
+
+msgid "Git cryptographic signature formats"
+msgstr "Äịnh dạng chữ ký bảo mật Git"
+
msgid "A Git Glossary"
msgstr "Thuật ngữ chuyên môn Git"
msgid "Hooks used by Git"
-msgstr "Các móc được sử dụng bởi Git"
+msgstr "Các hook được sử dụng bởi Git"
msgid "Specifies intentionally untracked files to ignore"
msgstr "Chỉ định các tập tin không cần theo dõi"
msgid "The Git repository browser"
-msgstr "Bộ duyện kho Git"
+msgstr "Bộ duyệt kho Git"
msgid "Map author/committer names and/or E-Mail addresses"
msgstr "Ãnh xạ tên tác giả/ngÆ°á»i chuyển giao và/hoặc địa chỉ E-Mail"
@@ -13778,8 +14382,23 @@ msgstr "Äịnh nghÄ©a thuá»™c tính mô-Ä‘un-con"
msgid "Git namespaces"
msgstr "Không gian tên Git"
+msgid "Protocol v0 and v1 capabilities"
+msgstr "Capabilities của giao thức v0 và v1"
+
+msgid "Things common to various protocols"
+msgstr "Những thứ chung cho các giao thức"
+
+msgid "Git HTTP-based protocols"
+msgstr "Những giao thức Git dựa trên HTTP"
+
+msgid "How packs are transferred over-the-wire"
+msgstr "Gói được truyá»n thá»±c tế (over-the-wire) nhÆ° thế nào"
+
+msgid "Git Wire Protocol, Version 2"
+msgstr "Git Wire Protocol, Version 2"
+
msgid "Helper programs to interact with remote repositories"
-msgstr "Các chương trình hỗ trợ để tương tác với các kho chứa trên máy chủ"
+msgstr "Các chương trình helper để tương tác với các kho chứa trên máy chủ"
msgid "Git Repository Layout"
msgstr "Bố cục kho Git"
@@ -13802,44 +14421,90 @@ msgstr "Giao diện Git trên ná»n web (ứng dụng web chạy trên kho Git)"
msgid "An overview of recommended workflows with Git"
msgstr "Tổng quan vỠluồng công việc khuyến nghị nên dùng với Git"
+msgid "A tool for managing large Git repositories"
+msgstr "Công cụ quản lý các kho Git lớn"
+
msgid "commit-graph file is too small"
-msgstr "tập tin đồ-thị-các-lần-chuyển-giao quá nhá»"
+msgstr "tập tin đồ-thị-chuyển-giao quá nhá»"
+
+msgid "commit-graph oid fanout chunk is wrong size"
+msgstr "đồ-thị-chuyển-giao có kích cỡ oid fanout chunk không đúng"
+
+msgid "commit-graph fanout values out of order"
+msgstr "đồ-thị-chuyển-giao có giá trị fanout không đúng"
+
+msgid "commit-graph OID lookup chunk is the wrong size"
+msgstr "đồ-thị-chuyển-giao có kích cỡ OID lookup chunk không đúng"
+
+msgid "commit-graph commit data chunk is wrong size"
+msgstr "đồ-thị-chuyển-giao có kích cỡ commit data chunk không đúng"
+
+msgid "commit-graph generations chunk is wrong size"
+msgstr "đồ-thị-chuyển-giao có kích cỡ generations chunk không đúng"
+
+msgid "commit-graph changed-path index chunk is too small"
+msgstr "đồ-thị-chuyển-giao có changed-path index chunk quá nhá»"
+
+#, c-format
+msgid ""
+"ignoring too-small changed-path chunk (%<PRIuMAX> < %<PRIuMAX>) in commit-"
+"graph file"
+msgstr ""
+"bá» qua chunk thay-đổi-Ä‘Æ°á»ng-dẫn quá nhá» (%<PRIuMAX> < %<PRIuMAX>) trong tập "
+"tin đồ-thị-chuyển-giao"
#, c-format
msgid "commit-graph signature %X does not match signature %X"
-msgstr "chữ ký đồ-thị-các-lần-chuyển-giao %X không khớp chữ ký %X"
+msgstr "chữ ký đồ-thị-chuyển-giao %X không khớp chữ ký %X"
#, c-format
msgid "commit-graph version %X does not match version %X"
-msgstr "phiên bản đồ-thị-các-lần-chuyển-giao %X không khớp phiên bản %X"
+msgstr "phiên bản đồ-thị-chuyển-giao %X không khớp phiên bản %X"
#, c-format
msgid "commit-graph hash version %X does not match version %X"
-msgstr "phiên bản đồ-thị-các-lần-chuyển-giao %X không khớp phiên bản %X"
+msgstr "phiên bản đồ-thị-chuyển-giao %X không khớp phiên bản %X"
#, c-format
msgid "commit-graph file is too small to hold %u chunks"
-msgstr "tập tin đồ-thị-các-lần-chuyển-giao quá nhỠđể giữ %u mảnh dữ liệu"
+msgstr "tập tin đồ-thị-chuyển-giao quá nhỠđể giữ %u chunk"
+
+msgid "commit-graph required OID fanout chunk missing or corrupted"
+msgstr "đồ-thị-chuyển-giao thiếu chunk OID fanout cần thiết hoặc bị há»ng"
+
+msgid "commit-graph required OID lookup chunk missing or corrupted"
+msgstr "đồ-thị-chuyển-giao thiếu chunk OID lookup cần thiết hoặc bị há»ng"
+
+msgid "commit-graph required commit data chunk missing or corrupted"
+msgstr "đồ-thị-chuyển-giao thiếu chunk commit data cần thiết hoặc bị há»ng"
msgid "commit-graph has no base graphs chunk"
-msgstr "đồ-thị-các-lần-chuyển-giao có không có mảnh các đồ há»a cÆ¡ sở"
+msgstr "đồ thị chuyển giao không có chunk đồ thị cơ sở"
+
+msgid "commit-graph base graphs chunk is too small"
+msgstr "đồ thị chuyển giao có chunk đồ thị cÆ¡ sở quá nhá»"
msgid "commit-graph chain does not match"
-msgstr "móc xích đồ-thị-các-lần-chuyển-giao không khớp"
+msgstr "chuỗi đồ-thị-chuyển-giao không khớp"
+
+#, c-format
+msgid "commit count in base graph too high: %<PRIuMAX>"
+msgstr "số lần chuyển giao trong đồ thị cơ sở quá lớn: %<PRIuMAX>"
+
+msgid "commit-graph chain file too small"
+msgstr "tập tin chuá»—i đồ-thị-chuyển-giao quá nhá»"
#, c-format
msgid "invalid commit-graph chain: line '%s' not a hash"
msgstr ""
-"móc xích đồ-thị-các-lần-chuyển-giao không hợp lệ: dòng “%s†không phải là "
-"một mã băm"
+"chuỗi đồ-thị-chuyển-giao không hợp lệ: dòng '%s' không phải là một mã băm"
msgid "unable to find all commit-graph files"
-msgstr "không thể tìm thấy tất cả các tập tin đồ-thị-các-lần-chuyển-giao"
+msgstr "không thể tìm thấy tất cả các tập tin đồ-thị-chuyển-giao"
msgid "invalid commit position. commit-graph is likely corrupt"
msgstr ""
-"vị trí lần chuyển giao không hợp lệ. đồ-thị-các-lần-chuyển-giao có vẻ như đã "
-"bị há»ng"
+"vị trí lần chuyển giao không hợp lệ. đồ-thị-chuyển-giao có vẻ nhÆ° đã bị há»ng"
#, c-format
msgid "could not find commit %s"
@@ -13848,6 +14513,12 @@ msgstr "không thể tìm thấy lần chuyển giao %s"
msgid "commit-graph requires overflow generation data but has none"
msgstr "commit-graph yêu cầu dữ liệu tạo tràn nhưng không có"
+msgid "commit-graph overflow generation data is too small"
+msgstr "commit-graph yêu cầu dữ liệu tạo tràn nhÆ°ng quá nhá»"
+
+msgid "commit-graph extra-edges pointer out of bounds"
+msgstr "con trỠextra-edge của đồ thị chuyển giao nằm ngoài biên"
+
msgid "Loading known commits in commit graph"
msgstr "Äang tải các lần chuyển giao chÆ°a biết trong đồ thị lần chuyển giao"
@@ -13883,7 +14554,7 @@ msgstr "gặp lỗi thêm gói %s"
#, c-format
msgid "error opening index for %s"
-msgstr "gặp lá»—i khi mở mục lục cho “%sâ€"
+msgstr "gặp lỗi khi mở chỉ mục cho '%s'"
msgid "Finding commits for commit graph among packed objects"
msgstr ""
@@ -13901,7 +14572,7 @@ msgstr "không thể tạo lá»›p sÆ¡ đồ tạm thá»i"
#, c-format
msgid "unable to adjust shared permissions for '%s'"
-msgstr "không thể chỉnh sá»­a quyá»n chia sẻ thành “%sâ€"
+msgstr "không thể chỉnh sá»­a quyá»n chia sẻ thành '%s'"
#, c-format
msgid "Writing out commit graph in %d pass"
@@ -13912,20 +14583,28 @@ msgid "unable to open commit-graph chain file"
msgstr "không thể mở tập tin mắt xích đồ thị chuyển giao"
msgid "failed to rename base commit-graph file"
-msgstr "gặp lỗi khi đổi tên tập tin đồ-thị-các-lần-chuyển-giao"
+msgstr "gặp lỗi khi đổi tên tập tin đồ-thị-chuyển-giao"
msgid "failed to rename temporary commit-graph file"
-msgstr "gặp lá»—i khi đổi tên tập tin đồ-thị-các-lần-chuyển-giao tạm thá»i"
+msgstr "gặp lá»—i khi đổi tên tập tin đồ-thị-chuyển-giao tạm thá»i"
+
+#, c-format
+msgid "cannot merge graphs with %<PRIuMAX>, %<PRIuMAX> commits"
+msgstr "không thể kết hợp đồ thị với %<PRIuMAX>, %<PRIuMAX> lần chuyển giao"
+
+#, c-format
+msgid "cannot merge graph %s, too many commits: %<PRIuMAX>"
+msgstr "không thể kết hợp đồ thị %s, quá nhiá»u lần chuyển giao: %<PRIuMAX>"
msgid "Scanning merged commits"
msgstr "Äang quét các lần chuyển giao đã hòa trá»™n"
msgid "Merging commit-graph"
-msgstr "Äang hòa trá»™n đồ-thị-các-lần-chuyển-giao"
+msgstr "Äang hòa trá»™n đồ-thị-chuyển-giao"
msgid "attempting to write a commit-graph, but 'core.commitGraph' is disabled"
msgstr ""
-"cố gắng để ghi một đồ thị các lần chuyển giao, nhưng “core.commitGraph†bị "
+"cố gắng để ghi một đồ thị các lần chuyển giao, nhưng 'core.commitGraph' bị "
"vô hiệu hóa"
msgid "too many commits to write graph"
@@ -13933,78 +14612,70 @@ msgstr "có quá nhiá»u lần chuyển giao để ghi đồ thị"
msgid "the commit-graph file has incorrect checksum and is likely corrupt"
msgstr ""
-"tập tin đồ-thị-các-lần-chuyển-giao có tổng kiểm không đúng và có vẻ như là "
-"đã há»ng"
+"tập tin đồ-thị-chuyển-giao có tổng kiểm không đúng và có vẻ nhÆ° là đã há»ng"
#, c-format
msgid "commit-graph has incorrect OID order: %s then %s"
-msgstr "đồ-thị-các-lần-chuyển-giao có thứ tự OID không đúng: %s sau %s"
+msgstr "đồ-thị-chuyển-giao có thứ tự OID không đúng: %s sau %s"
#, c-format
msgid "commit-graph has incorrect fanout value: fanout[%d] = %u != %u"
-msgstr ""
-"đồ-thị-các-lần-chuyển-giao có giá trị fanout không đúng: fanout[%d] = %u != "
-"%u"
+msgstr "đồ-thị-chuyển-giao có giá trị fanout không đúng: fanout[%d] = %u != %u"
#, c-format
msgid "failed to parse commit %s from commit-graph"
-msgstr "gặp lỗi khi phân tích lần chuyển giao từ %s đồ-thị-các-lần-chuyển-giao"
-
-msgid "Verifying commits in commit graph"
-msgstr "Äang thẩm tra các lần chuyển giao trong đồ thị lần chuyển giao"
+msgstr "gặp lá»—i khi Ä‘á»c lần chuyển giao từ %s đồ-thị-chuyển-giao"
#, c-format
msgid "failed to parse commit %s from object database for commit-graph"
msgstr ""
-"gặp lỗi khi phân tích lần chuyển giao %s từ cơ sở dữ liệu đối tượng cho đồ "
-"thị lần chuyển giao"
+"gặp lá»—i khi Ä‘á»c lần chuyển giao %s từ cÆ¡ sở dữ liệu đối tượng cho đồ thị lần "
+"chuyển giao"
#, c-format
msgid "root tree OID for commit %s in commit-graph is %s != %s"
msgstr ""
-"OID cây gốc cho lần chuyển giao %s trong đồ-thị-các-lần-chuyển-giao là %s != "
-"%s"
+"OID cây gốc cho lần chuyển giao %s trong đồ-thị-chuyển-giao là %s != %s"
#, c-format
msgid "commit-graph parent list for commit %s is too long"
-msgstr ""
-"danh sách cha mẹ đồ-thị-các-lần-chuyển-giao cho lần chuyển giao %s là quá dài"
+msgstr "danh sách cha mẹ đồ-thị-chuyển-giao cho lần chuyển giao %s là quá dài"
#, c-format
msgid "commit-graph parent for %s is %s != %s"
-msgstr "cha mẹ đồ-thị-các-lần-chuyển-giao cho %s là %s != %s"
+msgstr "cha mẹ đồ-thị-chuyển-giao cho %s là %s != %s"
#, c-format
msgid "commit-graph parent list for commit %s terminates early"
msgstr ""
-"danh sách cha mẹ đồ-thị-các-lần-chuyển-giao cho lần chuyển giao %s bị chấm "
-"dứt quá sớm"
+"danh sách cha mẹ đồ-thị-chuyển-giao cho lần chuyển giao %s bị chấm dứt quá "
+"sá»›m"
#, c-format
-msgid ""
-"commit-graph has generation number zero for commit %s, but non-zero elsewhere"
+msgid "commit-graph generation for commit %s is %<PRIuMAX> < %<PRIuMAX>"
msgstr ""
-"đồ-thị-các-lần-chuyển-giao có con số không lần tạo cho lần chuyển giao %s, "
-"nhưng không phải số không ở chỗ khác"
+"tạo đồ-thị-chuyển-giao cho lần chuyển giao %s là %<PRIuMAX> < %<PRIuMAX>"
#, c-format
-msgid ""
-"commit-graph has non-zero generation number for commit %s, but zero elsewhere"
+msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>"
msgstr ""
-"đồ-thị-các-lần-chuyển-giao có con số không phải không lần tạo cho lần chuyển "
-"giao %s, nhưng số không ở chỗ khác"
+"ngày chuyển giao cho lần chuyển giao %s trong đồ-thị-chuyển-giao là "
+"%<PRIuMAX> != %<PRIuMAX>"
#, c-format
-msgid "commit-graph generation for commit %s is %<PRIuMAX> < %<PRIuMAX>"
+msgid ""
+"commit-graph has both zero and non-zero generations (e.g., commits '%s' and "
+"'%s')"
msgstr ""
-"tạo đồ-thị-các-lần-chuyển-giao cho lần chuyển giao %s là %<PRIuMAX> < "
-"%<PRIuMAX>"
+"đồ-thị-chuyển-giao có số thế hệ không và khác không (v.d. lần chuyển giao "
+"'%s' và '%s')"
+
+msgid "Verifying commits in commit graph"
+msgstr "Äang thẩm tra các lần chuyển giao trong đồ thị lần chuyển giao"
#, c-format
-msgid "commit date for commit %s in commit-graph is %<PRIuMAX> != %<PRIuMAX>"
-msgstr ""
-"ngày chuyển giao cho lần chuyển giao %s trong đồ-thị-các-lần-chuyển-giao là "
-"%<PRIuMAX> != %<PRIuMAX>"
+msgid "could not parse commit %s"
+msgstr "không thể Ä‘á»c lần chuyển giao %s"
#, c-format
msgid "%s %s is not a commit!"
@@ -14020,7 +14691,7 @@ msgid ""
"Turn this message off by running\n"
"\"git config advice.graftFileDeprecated false\""
msgstr ""
-"Việc hỗ trợ cho <GIT_DIR>/info/grafts đã lạc hậu\n"
+"Hỗ trợ cho <GIT_DIR>/info/grafts đã không còn\n"
"và sẽ bị xóa bỠở phiên bản Git tương lai.\n"
"\n"
"Vui lòng dùng \"git replace --convert-graft-file\"\n"
@@ -14030,6 +14701,12 @@ msgstr ""
"\"git config advice.graftFileDeprecated false\""
#, c-format
+msgid "commit %s exists in commit-graph but not in the object database"
+msgstr ""
+"commit %s tồn tại trong đồ-thị-chuyển-giao nhưng không có trong cơ sở dữ "
+"liệu đối tượng"
+
+#, c-format
msgid "Commit %s has an untrusted GPG signature, allegedly by %s."
msgstr ""
"Lần chuyển giao %s có một chữ ký GPG không đáng tin, được cho là bởi %s."
@@ -14062,6 +14739,14 @@ msgid "no libc information available\n"
msgstr "không có thông tin vỠlibc\n"
#, c-format
+msgid "could not determine free disk size for '%s'"
+msgstr "không thể dò tìm chỗ trống trên đĩa cho '%s'"
+
+#, c-format
+msgid "could not get info for '%s'"
+msgstr "không thể lấy thông tin cho '%s'"
+
+#, c-format
msgid "[GLE %ld] health thread could not open '%ls'"
msgstr "[GLE %ld] không thể mở tuyến trình sức khá»e '%ls'"
@@ -14085,6 +14770,10 @@ msgstr "có trÆ°á»ng hợp không được xá»­ lý trong 'has_worktree_moved'
msgid "health thread wait failed [GLE %ld]"
msgstr "gặp lá»—i khi chá» tiến trình sức khá»e [GLE %ld]"
+#, c-format
+msgid "Invalid path: %s"
+msgstr "Ä‘Æ°á»ng dẫn không hợp lệ: %s"
+
msgid "Unable to create FSEventStream."
msgstr "Không thể tạo FSEventStream."
@@ -14116,6 +14805,30 @@ msgid "could not read directory changes [GLE %ld]"
msgstr "không thể Ä‘á»c các thay đổi thÆ° mục [GLE %ld]"
#, c-format
+msgid "opendir('%s') failed"
+msgstr "opendir('%s') gặp lỗi"
+
+#, c-format
+msgid "lstat('%s') failed"
+msgstr "lstat('%s') gặp lỗi"
+
+#, c-format
+msgid "strbuf_readlink('%s') failed"
+msgstr "strbuf_readlink('%s') gặp lỗi"
+
+#, c-format
+msgid "closedir('%s') failed"
+msgstr "closedir('%s') gặp lỗi"
+
+#, c-format
+msgid "[GLE %ld] unable to open for read '%ls'"
+msgstr "[GLE %ld] không thể mở hay Ä‘á»c '%ls'"
+
+#, c-format
+msgid "[GLE %ld] unable to get protocol information for '%ls'"
+msgstr "[GLE %ld] không thể lấy thông tin giao thức cho '%ls'"
+
+#, c-format
msgid "failed to copy SID (%ld)"
msgstr "gặp lỗi khi sao chép SID (%ld)"
@@ -14154,7 +14867,7 @@ msgid "Unmatched ( or \\("
msgstr "ChÆ°a khá»›p ( hay \\("
msgid "Unmatched \\{"
-msgstr "ChÆ°a khá»›p cặp “\\{â€"
+msgstr "Chưa khớp cặp '\\{'"
msgid "Invalid content of \\{\\}"
msgstr "Nội dung của \\{\\} không hợp lệ"
@@ -14188,11 +14901,11 @@ msgstr "không thể Ä‘á»c đáp ứng IPC"
#, c-format
msgid "could not start accept_thread '%s'"
-msgstr "không thể khởi chạy accept_thread “%sâ€"
+msgstr "không thể khởi chạy accept_thread '%s'"
#, c-format
msgid "could not start worker[0] for '%s'"
-msgstr "không thể khởi chạy bá»™ làm việc worker[0] cho “%sâ€"
+msgstr "không thể khởi chạy bộ làm việc worker[0] cho '%s'"
#, c-format
msgid "ConnectNamedPipe failed for '%s' (%lu)"
@@ -14204,11 +14917,11 @@ msgstr "không thể tạo mô tả tập tin từ Ä‘Æ°á»ng ống cho '%s'"
#, c-format
msgid "could not start thread[0] for '%s'"
-msgstr "không thể khởi chạy tiến trình[0] cho “%sâ€"
+msgstr "không thể khởi chạy tiến trình[0] cho '%s'"
#, c-format
msgid "wait for hEvent failed for '%s'"
-msgstr "chá» cho hEvent gặp lá»—i vá»›i “%sâ€"
+msgstr "chỠcho hEvent gặp lỗi với '%s'"
msgid "cannot resume in the background, please use 'fg' to resume"
msgstr ""
@@ -14234,7 +14947,7 @@ msgstr ""
#, c-format
msgid "could not expand include path '%s'"
-msgstr "không thể khai triển Ä‘Æ°á»ng dẫn “%sâ€"
+msgstr "không thể khai triển Ä‘Æ°á»ng dẫn '%s'"
msgid "relative config includes must come from files"
msgstr "các bao gồm cấu hình liên quan phải đến từ các tập tin"
@@ -14246,7 +14959,7 @@ msgid ""
"remote URLs cannot be configured in file directly or indirectly included by "
"includeIf.hasconfig:remote.*.url"
msgstr ""
-"các URL máy chủ không thể được cấu hình trong tệp trực tiếp hoặc gián tiếp "
+"các URL máy chủ không thể được cấu hình trong tập trực tiếp hoặc gián tiếp "
"được bao gồm bởi includeIf.hasconfig:remote.*.url"
#, c-format
@@ -14255,11 +14968,11 @@ msgstr "định dạng cấu hình không hợp lệ: %s"
#, c-format
msgid "missing environment variable name for configuration '%.*s'"
-msgstr "thiếu tên biến môi trÆ°á»ng cho cấu hình “%.*sâ€"
+msgstr "thiếu tên biến môi trÆ°á»ng cho cấu hình '%.*s'"
#, c-format
msgid "missing environment variable '%s' for configuration '%.*s'"
-msgstr "thiếu biến môi trÆ°á»ng “%s†cho cấu hình “%.*sâ€"
+msgstr "thiếu biến môi trÆ°á»ng '%s' cho cấu hình '%.*s'"
#, c-format
msgid "key does not contain a section: %s"
@@ -14271,7 +14984,7 @@ msgstr "khóa không chứa bất kỳ một tên biến nào: %s"
#, c-format
msgid "invalid key: %s"
-msgstr "khóa không đúng: %s"
+msgstr "khóa không hợp lệ: %s"
#, c-format
msgid "invalid key (newline): %s"
@@ -14298,11 +15011,11 @@ msgstr "quá nhiá»u mục tin trong %s"
#, c-format
msgid "missing config key %s"
-msgstr "thiếu khóa cấu hình “%sâ€"
+msgstr "thiếu khóa cấu hình '%s'"
#, c-format
msgid "missing config value %s"
-msgstr "thiếu giá trị cấu hình “%sâ€"
+msgstr "thiếu giá trị cấu hình '%s'"
#, c-format
msgid "bad config line %d in blob %s"
@@ -14314,7 +15027,7 @@ msgstr "cấu hình sai tại dòng %d trong tập tin %s"
#, c-format
msgid "bad config line %d in standard input"
-msgstr "cấu hình sai tại dòng %d trong đầu vào tiêu chuẩn"
+msgstr "cấu hình sai tại dòng %d từ stdin"
#, c-format
msgid "bad config line %d in submodule-blob %s"
@@ -14336,33 +15049,32 @@ msgstr "đơn vị không hợp lệ"
#, c-format
msgid "bad numeric config value '%s' for '%s': %s"
-msgstr "sai giá trị bằng số của cấu hình “%s†cho “%sâ€: %s"
+msgstr "sai giá trị bằng số của cấu hình '%s' cho '%s': %s"
#, c-format
msgid "bad numeric config value '%s' for '%s' in blob %s: %s"
-msgstr "sai giá trị bằng số của cấu hình “%s†cho “%s†trong blob %s: %s"
+msgstr "sai giá trị bằng số của cấu hình '%s' cho '%s' trong blob %s: %s"
#, c-format
msgid "bad numeric config value '%s' for '%s' in file %s: %s"
-msgstr "sai giá trị bằng số của cấu hình “%s†cho “%s†trong tập tin %s: %s"
+msgstr "sai giá trị bằng số của cấu hình '%s' cho '%s' trong tập tin %s: %s"
#, c-format
msgid "bad numeric config value '%s' for '%s' in standard input: %s"
-msgstr ""
-"sai giá trị bằng số của cấu hình “%s†cho “%s†trong đầu vào tiêu chuẩn: %s"
+msgstr "sai giá trị bằng số của cấu hình '%s' cho '%s' trong stdin: %s"
#, c-format
msgid "bad numeric config value '%s' for '%s' in submodule-blob %s: %s"
msgstr ""
-"sai giá trị bằng số của cấu hình “%s†cho “%s†trong submodule-blob %s: %s"
+"sai giá trị bằng số của cấu hình '%s' cho '%s' trong submodule-blob %s: %s"
#, c-format
msgid "bad numeric config value '%s' for '%s' in command line %s: %s"
-msgstr "sai giá trị bằng số của cấu hình “%s†cho “%s†trong dòng lệnh %s: %s"
+msgstr "sai giá trị bằng số của cấu hình '%s' cho '%s' trong dòng lệnh %s: %s"
#, c-format
msgid "bad numeric config value '%s' for '%s' in %s: %s"
-msgstr "sai giá trị bằng số của cấu hình “%s†cho “%s†trong %s: %s"
+msgstr "sai giá trị bằng số của cấu hình '%s' cho '%s' trong %s: %s"
#, c-format
msgid "invalid value for variable %s"
@@ -14374,15 +15086,15 @@ msgstr "bỠqua thành phần core.fsync chưa biết '%s'"
#, c-format
msgid "bad boolean config value '%s' for '%s'"
-msgstr "sai giá trị kiểu lô-gíc của cấu hình “%s†cho “%sâ€"
+msgstr "sai giá trị kiểu boolean của cấu hình '%s' cho '%s'"
#, c-format
msgid "failed to expand user dir in: '%s'"
-msgstr "gặp lá»—i mở rá»™ng thÆ° mục ngÆ°á»i dùng trong: “%sâ€"
+msgstr "gặp lá»—i mở rá»™ng thÆ° mục ngÆ°á»i dùng trong: '%s'"
#, c-format
msgid "'%s' for '%s' is not a valid timestamp"
-msgstr "“%s†dành cho “%s†không phải là dấu vết thá»i gian hợp lệ"
+msgstr "'%s' dành cho '%s' không phải là dấu vết thá»i gian hợp lệ"
#, c-format
msgid "abbrev length out of range: %d"
@@ -14392,8 +15104,13 @@ msgstr "chiá»u dài abbrev nằm ngoài phạm vi: %d"
msgid "bad zlib compression level %d"
msgstr "mức nén zlib %d là sai"
-msgid "core.commentChar should only be one character"
-msgstr "core.commentChar chỉ được có một ký tự"
+#, c-format
+msgid "%s cannot contain newline"
+msgstr "%s không thể chứa ký tự xuống dòng"
+
+#, c-format
+msgid "%s must have at least one character"
+msgstr "%s phải có ít nhất một ký tự"
#, c-format
msgid "ignoring unknown core.fsyncMethod value '%s'"
@@ -14419,45 +15136,41 @@ msgstr "phải là một trong số nothing, matching, simple, upstream hay curr
#, c-format
msgid "unable to load config blob object '%s'"
-msgstr "không thể tải đối tượng blob cấu hình “%sâ€"
+msgstr "không thể tải đối tượng blob cấu hình '%s'"
#, c-format
msgid "reference '%s' does not point to a blob"
-msgstr "tham chiếu “%s†không chỉ đến một blob nào cả"
+msgstr "tham chiếu '%s' không chỉ đến một blob nào cả"
#, c-format
msgid "unable to resolve config blob '%s'"
-msgstr "không thể phân giải Ä‘iểm xét duyệt “%sâ€"
-
-#, c-format
-msgid "failed to parse %s"
-msgstr "gặp lỗi khi phân tích cú pháp %s"
+msgstr "không thể phân giải điểm xét duyệt '%s'"
msgid "unable to parse command-line config"
-msgstr "không thể phân tích cấu hình dòng lệnh"
+msgstr "không thể Ä‘á»c cấu hình dòng lệnh"
msgid "unknown error occurred while reading the configuration files"
msgstr "đã có lá»—i chÆ°a biết xảy ra trong khi Ä‘á»c các tập tin cấu hình"
#, c-format
msgid "Invalid %s: '%s'"
-msgstr "%s không hợp lệ: “%sâ€"
+msgstr "%s không hợp lệ: '%s'"
#, c-format
msgid "splitIndex.maxPercentChange value '%d' should be between 0 and 100"
-msgstr "giá trị splitIndex.maxPercentChange “%d†phải nằm giữa 0 và 100"
+msgstr "giá trị splitIndex.maxPercentChange '%d' phải nằm giữa 0 và 100"
#, c-format
msgid "unable to parse '%s' from command-line config"
-msgstr "không thể phân tích “%s†từ cấu hình dòng lệnh"
+msgstr "không thể Ä‘á»c '%s' từ cấu hình dòng lệnh"
#, c-format
msgid "bad config variable '%s' in file '%s' at line %d"
-msgstr "sai biến cấu hình “%s†trong tập tin “%s†tại dòng %d"
+msgstr "sai biến cấu hình '%s' trong tập tin '%s' tại dòng %d"
#, c-format
msgid "invalid section name '%s'"
-msgstr "tên của phần không hợp lệ “%sâ€"
+msgstr "tên của phần không hợp lệ '%s'"
#, c-format
msgid "%s has multiple values"
@@ -14465,7 +15178,11 @@ msgstr "%s có đa giá trị"
#, c-format
msgid "failed to write new configuration file %s"
-msgstr "gặp lá»—i khi ghi tập tin cấu hình “%sâ€"
+msgstr "gặp lỗi khi ghi tập tin cấu hình '%s'"
+
+#, c-format
+msgid "no multi-line comment allowed: '%s'"
+msgstr "không cho phép ghi chú nhiá»u dòng: '%s'"
#, c-format
msgid "could not lock config file %s"
@@ -14473,11 +15190,11 @@ msgstr "không thể khóa tập tin cấu hình %s"
#, c-format
msgid "opening %s"
-msgstr "Ä‘ang mở “%sâ€"
+msgstr "đang mở '%s'"
#, c-format
msgid "invalid config file %s"
-msgstr "tập tin cấu hình “%s†không hợp lệ"
+msgstr "tập tin cấu hình '%s' không hợp lệ"
#, c-format
msgid "fstat on %s failed"
@@ -14485,7 +15202,7 @@ msgstr "fstat trên %s gặp lỗi"
#, c-format
msgid "unable to mmap '%s'%s"
-msgstr "không thể mmap “%sâ€%s"
+msgstr "không thể mmap '%s'%s"
#, c-format
msgid "chmod on %s failed"
@@ -14493,19 +15210,23 @@ msgstr "chmod trên %s gặp lỗi"
#, c-format
msgid "could not write config file %s"
-msgstr "không thể ghi tập tin cấu hình “%sâ€"
+msgstr "không thể ghi tập tin cấu hình '%s'"
#, c-format
msgid "could not set '%s' to '%s'"
-msgstr "không thể đặt “%s†thành “%sâ€"
+msgstr "không thể đặt '%s' thành '%s'"
#, c-format
msgid "invalid section name: %s"
msgstr "tên của phần không hợp lệ: %s"
#, c-format
+msgid "refusing to work with overly long line in '%s' on line %<PRIuMAX>"
+msgstr "từ chối làm việc với dòng quá dài '%s' trên dòng %<PRIuMAX>"
+
+#, c-format
msgid "missing value for '%s'"
-msgstr "thiếu giá trị cho cho “%sâ€"
+msgstr "thiếu giá trị cho cho '%s'"
msgid "the remote end hung up upon initial contact"
msgstr "máy chủ bị treo trên lần tiếp xúc đầu tiên"
@@ -14523,25 +15244,25 @@ msgstr ""
#, c-format
msgid "server doesn't support '%s'"
-msgstr "máy chủ không há»— trợ “%sâ€"
+msgstr "máy chủ không hỗ trợ '%s'"
#, c-format
msgid "server doesn't support feature '%s'"
-msgstr "máy chủ không há»— trợ tính năng “%sâ€"
+msgstr "máy chủ không hỗ trợ tính năng '%s'"
msgid "expected flush after capabilities"
msgstr "cần đẩy dữ liệu lên đĩa sau các capabilities"
#, c-format
msgid "ignoring capabilities after first line '%s'"
-msgstr "bá» qua capabilities sau dòng đầu tiên “%sâ€"
+msgstr "bỠqua capabilities sau dòng đầu tiên '%s'"
msgid "protocol error: unexpected capabilities^{}"
-msgstr "lỗi giao thức: không cần capabilities^{}"
+msgstr "lá»—i giao thức: capabilities^{} bất thÆ°á»ng"
#, c-format
msgid "protocol error: expected shallow sha-1, got '%s'"
-msgstr "lá»—i giao thức: cần sha-1 shallow, nhÆ°ng lại nhận được “%sâ€"
+msgstr "lỗi giao thức: cần sha-1 shallow, nhưng lại có '%s'"
msgid "repository on the other end cannot be shallow"
msgstr "kho đã ở điểm cuối khoác nên không thể được shallow"
@@ -14551,11 +15272,21 @@ msgstr "gói không hợp lệ"
#, c-format
msgid "protocol error: unexpected '%s'"
-msgstr "lá»—i giao thức: không cần “%sâ€"
+msgstr "lá»—i giao thức: '%s' bất thÆ°á»ng"
#, c-format
msgid "unknown object format '%s' specified by server"
-msgstr "không hiểu định dạng đối tượng “%s†được chỉ định bởi máy phục vụ"
+msgstr "không hiểu định dạng đối tượng '%s' được chỉ định bởi máy chủ"
+
+#, c-format
+msgid "error on bundle-uri response line %d: %s"
+msgstr "lỗi trên dòng phản hồi bundle-uri thứ %d: %s"
+
+msgid "expected flush after bundle-uri listing"
+msgstr "cần đẩy dữ liệu lên đĩa sau khi liệt kê bundle-uri"
+
+msgid "expected response end packet after ref listing"
+msgstr "cần nhận được trả lá»i là kết thúc gói sau khi liệt kê tham chiếu"
#, c-format
msgid "invalid ls-refs response: %s"
@@ -14564,19 +15295,16 @@ msgstr "trả vỠcủa ls-refs không hợp lệ: %s"
msgid "expected flush after ref listing"
msgstr "cần đẩy dữ liệu lên đĩa sau khi liệt kê tham chiếu"
-msgid "expected response end packet after ref listing"
-msgstr "cần nhận được trả lá»i là kết thúc gói sau khi liệt kê tham chiếu"
-
#, c-format
msgid "protocol '%s' is not supported"
-msgstr "giao thức “%s†chưa được hỗ trợ"
+msgstr "giao thức '%s' chưa được hỗ trợ"
msgid "unable to set SO_KEEPALIVE on socket"
msgstr "không thể đặt SO_KEEPALIVE trên ổ cắm"
#, c-format
msgid "Looking up %s ... "
-msgstr "Äang tìm kiếm %s … "
+msgstr "Äang tìm kiếm %s ... "
#, c-format
msgid "unable to look up %s (port %s) (%s)"
@@ -14589,7 +15317,7 @@ msgid ""
"Connecting to %s (port %s) ... "
msgstr ""
"xong.\n"
-"Äang kết nối đến %s (cổng %s) … "
+"Äang kết nối đến %s (cổng %s) ... "
#, c-format
msgid ""
@@ -14613,221 +15341,46 @@ msgstr "không hiểu cổng %s"
#, c-format
msgid "strange hostname '%s' blocked"
-msgstr "đã khóa tên máy lạ “%sâ€"
+msgstr "đã khóa tên máy lạ '%s'"
#, c-format
msgid "strange port '%s' blocked"
-msgstr "đã khóa cổng lạ “%sâ€"
+msgstr "đã khóa cổng lạ '%s'"
#, c-format
msgid "cannot start proxy %s"
-msgstr "không thể khởi chạy ủy nhiệm “%sâ€"
+msgstr "không thể khởi chạy ủy nhiệm '%s'"
msgid "no path specified; see 'git help pull' for valid url syntax"
-msgstr "chÆ°a chỉ định Ä‘Æ°á»ng dẫn; xem'git help pull†để biết cú pháp url hợp lệ"
+msgstr "chÆ°a chỉ định Ä‘Æ°á»ng dẫn; xem'git help pull' để biết cú pháp url hợp lệ"
msgid "newline is forbidden in git:// hosts and repo paths"
-msgstr "newline bị cấm trong các git:// máy chủ và Ä‘Æ°á»ng dẫn repo"
+msgstr "ký tá»± xuống dòng bị cấm trong các git:// máy chủ và Ä‘Æ°á»ng dẫn repo"
msgid "ssh variant 'simple' does not support -4"
-msgstr "ssh biến thể “simple†không hỗ trợ -4"
+msgstr "ssh biến thể 'simple' không hỗ trợ -4"
msgid "ssh variant 'simple' does not support -6"
-msgstr "ssh biến thể “simple†không hỗ trợ -6"
+msgstr "ssh biến thể 'simple' không hỗ trợ -6"
msgid "ssh variant 'simple' does not support setting port"
-msgstr "ssh biến thể “simple†không hỗ trợ đặt cổng"
+msgstr "ssh biến thể 'simple' không hỗ trợ đặt cổng"
#, c-format
msgid "strange pathname '%s' blocked"
-msgstr "đã khóa tên Ä‘Æ°á»ng dẫn lạ “%sâ€"
+msgstr "đã khóa tên Ä‘Æ°á»ng dẫn lạ '%s'"
msgid "unable to fork"
msgstr "không thể rẽ nhánh tiến trình con"
msgid "Could not run 'git rev-list'"
-msgstr "Không thể chạy “git rev-listâ€"
+msgstr "Không thể chạy 'git rev-list'"
msgid "failed write to rev-list"
msgstr "gặp lỗi khi ghi vào rev-list"
msgid "failed to close rev-list's stdin"
-msgstr "gặp lỗi khi đóng đầu vào chuẩn stdin của rev-list"
-
-#, c-format
-msgid "'%s' does not exist"
-msgstr "\"%s\" không tồn tại"
-
-msgid "need a working directory"
-msgstr "cần một thư mục làm việc"
-
-msgid "could not find enlistment root"
-msgstr "không tìm thấy gốc enlistment"
-
-#, c-format
-msgid "could not switch to '%s'"
-msgstr "không thể chuyển đến '%s'"
-
-#, c-format
-msgid "could not configure %s=%s"
-msgstr "không thể đóng cấu hình %s=%s"
-
-msgid "could not configure log.excludeDecoration"
-msgstr "không thể cấu hình log.excludeDecoration"
-
-msgid "Scalar enlistments require a worktree"
-msgstr "'Scalar enlistments' cần một cây làm việc"
-
-#, c-format
-msgid "could not open directory '%s'"
-msgstr "không thể mở thÆ° mục “%sâ€"
-
-#, c-format
-msgid "skipping '%s', which is neither file nor directory"
-msgstr ""
-"Ä‘ang bá» qua “%sâ€, cái không phải là má»™t tập tin, cÅ©ng không phải thÆ° mục"
-
-#, c-format
-msgid "could not determine free disk size for '%s'"
-msgstr "không thể dò tìm chá»— trống trên Ä‘Ä©a cho “%sâ€"
-
-#, c-format
-msgid "could not get info for '%s'"
-msgstr "không thể lấy thông tin cho “%sâ€"
-
-#, c-format
-msgid "remote HEAD is not a branch: '%.*s'"
-msgstr "HEAD của máy chủ không phải một nhánh: '%.*s'"
-
-msgid "failed to get default branch name from remote; using local default"
-msgstr "gặp lỗi khi lấy tên nhánh mặc định từ máy chủ; sử dụng mặc định nội bộ"
-
-msgid "failed to get default branch name"
-msgstr "gặp lỗi khi lấy tên nhánh mặc định"
-
-msgid "failed to unregister repository"
-msgstr "gặp lỗi khi hủy đăng ký kho chứa"
-
-msgid "failed to delete enlistment directory"
-msgstr "gặp lỗi khi xóa thư mục dành được"
-
-msgid "branch to checkout after clone"
-msgstr "nhánh để lấy ra sau khi nhân bản"
-
-msgid "when cloning, create full working directory"
-msgstr "khi nhân bản, tạo đầy đủ thư mục làm việc"
-
-msgid "only download metadata for the branch that will be checked out"
-msgstr "chỉ siêu dữ liệu tải vỠcho nhánh mà sẽ được lấy ra"
-
-msgid "scalar clone [<options>] [--] <repo> [<dir>]"
-msgstr "scalar clone [<các tùy chá»n>] [--] <kho> [<t.mục>]"
-
-#, c-format
-msgid "cannot deduce worktree name from '%s'"
-msgstr "không thể suy diễn tên cây làm việc từ '%s'"
-
-#, c-format
-msgid "directory '%s' exists already"
-msgstr "thư mục '%s' đã sẵn có"
-
-#, c-format
-msgid "failed to get default branch for '%s'"
-msgstr "gặp lỗi khi lấy nhánh mặc định cho '%s'"
-
-#, c-format
-msgid "could not configure remote in '%s'"
-msgstr "không thể cấu hình máy chủ trong '%s'"
-
-#, c-format
-msgid "could not configure '%s'"
-msgstr "không thể cấu hình '%s'"
-
-msgid "partial clone failed; attempting full clone"
-msgstr "nhân bản từng phần gặp lỗi; đang cố thử nhân bản đầy đủ"
-
-msgid "could not configure for full clone"
-msgstr "không thể cấu hình cho nhân bản đầy đủ"
-
-msgid "scalar diagnose [<enlistment>]"
-msgstr "scalar diagnose [<enlistment>]"
-
-#, c-format
-msgid "could not create directory for '%s'"
-msgstr "không thể tạo thÆ° mục cho “%sâ€"
-
-msgid "could not duplicate stdout"
-msgstr "không thể nhân đôi đầu vào tiêu chuẩn"
-
-msgid "failed to write archive"
-msgstr "gặp lỗi khi khi kho nén"
-
-msgid "`scalar list` does not take arguments"
-msgstr "`scalar list` không nhận các tham số"
-
-msgid "scalar register [<enlistment>]"
-msgstr "scalar register [<enlistment>]"
-
-msgid "reconfigure all registered enlistments"
-msgstr "cấu hình má»i enlistments đã đăng ký"
-
-msgid "scalar reconfigure [--all | <enlistment>]"
-msgstr "scalar reconfigure [--all | <enlistment>]"
-
-msgid "--all or <enlistment>, but not both"
-msgstr "--all hoặc <enlistment>, không thể là cả hai"
-
-#, c-format
-msgid "git repository gone in '%s'"
-msgstr "kho git ra Ä‘i trong '%s'"
-
-msgid ""
-"scalar run <task> [<enlistment>]\n"
-"Tasks:\n"
-msgstr ""
-"scalar run <task> [<enlistment>]\n"
-"Nhiệm vụ:\n"
-
-#, c-format
-msgid "no such task: '%s'"
-msgstr "không có nhiệm vụ nào nhÆ° thế: “%sâ€"
-
-msgid "scalar unregister [<enlistment>]"
-msgstr "scalar unregister [<enlistment>]"
-
-msgid "scalar delete <enlistment>"
-msgstr "scalar delete <enlistment>"
-
-msgid "refusing to delete current working directory"
-msgstr "từ chối gỡ bỠthư mục làm việc hiện tại"
-
-msgid "include Git version"
-msgstr "bao gồm phiên bản Git"
-
-msgid "include Git's build options"
-msgstr "bao gồm các tùy chá»n biên dịch của Git"
-
-msgid "scalar verbose [-v | --verbose] [--build-options]"
-msgstr "scalar verbose [-v | --verbose] [--build-options]"
-
-msgid "-C requires a <directory>"
-msgstr "-C cần một <thư_mục>"
-
-#, c-format
-msgid "could not change to '%s'"
-msgstr "không thể chuyển sang “%sâ€"
-
-msgid "-c requires a <key>=<value> argument"
-msgstr "-c cần một tham số <key>=<value>"
-
-msgid ""
-"scalar [-C <directory>] [-c <key>=<value>] <command> [<options>]\n"
-"\n"
-"Commands:\n"
-msgstr ""
-"scalar [-C </thÆ°/mục/>] [-c <khóa>=<giá trị>] <lệnh> [<các tùy chá»n>]\n"
-"\n"
-"Các lệnh:\n"
+msgstr "gặp lỗi khi đóng stdin của rev-list"
#, c-format
msgid "illegal crlf_action %d"
@@ -14859,55 +15412,55 @@ msgstr ""
#, c-format
msgid "BOM is prohibited in '%s' if encoded as %s"
-msgstr "BOM bị cấm trong “%s†nếu được mã hóa là %s"
+msgstr "BOM bị cấm trong '%s' nếu được mã hóa là %s"
#, c-format
msgid ""
"The file '%s' contains a byte order mark (BOM). Please use UTF-%.*s as "
"working-tree-encoding."
msgstr ""
-"Tập tin “%s†có chứa ký hiệu thứ tự byte (BOM). Vui lòng dùng UTF-%.*s như "
+"Tập tin '%s' có chứa ký hiệu thứ tự byte (BOM). Vui lòng dùng UTF-%.*s như "
"là bảng mã cây làm việc."
#, c-format
msgid "BOM is required in '%s' if encoded as %s"
-msgstr "BOM là bắt buộc trong “%s†nếu được mã hóa là %s"
+msgstr "BOM là bắt buộc trong '%s' nếu được mã hóa là %s"
#, 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 ""
-"Tập tin “%s†còn thiếu ký hiệu thứ tự byte (BOM). Vui lòng dùng UTF-%sBE hay "
+"Tập tin '%s' còn thiếu ký hiệu thứ tự byte (BOM). Vui lòng dùng UTF-%sBE hay "
"UTF-%sLE (còn phục thuộc vào thứ tự byte) như là bảng mã cây làm việc."
#, c-format
msgid "failed to encode '%s' from %s to %s"
-msgstr "gặp lá»—i khi mã hóa “%s†từ “%s†sang “%sâ€"
+msgstr "gặp lỗi khi mã hóa '%s' từ '%s' sang '%s'"
#, c-format
msgid "encoding '%s' from %s to %s and back is not the same"
-msgstr "mã hóa “%s†từ %s thành %s và ngược trở lại không phải là cùng"
+msgstr "mã hóa '%s' từ %s thành %s và ngược trở lại không phải là cùng"
#, c-format
msgid "cannot fork to run external filter '%s'"
-msgstr "không thể rẽ nhánh tiến trình để chạy bá»™ lá»c bên ngoài “%sâ€"
+msgstr "không thể rẽ nhánh tiến trình để chạy bá»™ lá»c bên ngoài '%s'"
#, c-format
msgid "cannot feed the input to external filter '%s'"
-msgstr "không thể cấp đầu vào cho bá»™ lá»c bên ngoài “%sâ€"
+msgstr "không thể cấp đầu vào cho bá»™ lá»c bên ngoài '%s'"
#, c-format
msgid "external filter '%s' failed %d"
-msgstr "chạy bá»™ lá»c bên ngoài “%s†gặp lá»—i %d"
+msgstr "chạy bá»™ lá»c bên ngoài '%s' gặp lá»—i %d"
#, c-format
msgid "read from external filter '%s' failed"
-msgstr "Ä‘á»c từ bá»™ lá»c bên ngoài “%s†gặp lá»—i"
+msgstr "Ä‘á»c từ bá»™ lá»c bên ngoài '%s' gặp lá»—i"
#, c-format
msgid "external filter '%s' failed"
-msgstr "gặp lá»—i khi chạy bá»™ lá»c bên ngoài “%sâ€"
+msgstr "gặp lá»—i khi chạy bá»™ lá»c bên ngoài '%s'"
msgid "unexpected filter type"
msgstr "gặp kiểu bá»™ lá»c thừa"
@@ -14920,23 +15473,23 @@ msgid ""
"external filter '%s' is not available anymore although not all paths have "
"been filtered"
msgstr ""
-"bá»™ lá»c bên ngoài “%s†không sẵn sàng nữa mặc dù không phải tất cả các Ä‘Æ°á»ng "
-"dẫn đã được lá»c"
+"bá»™ lá»c ngoài '%s' không còn nữa mặc dù không phải tất cả các Ä‘Æ°á»ng dẫn đã "
+"được lá»c"
msgid "true/false are no valid working-tree-encodings"
-msgstr "true/false là không phải bảng-mã-cây-làm-việc hợp lệ"
+msgstr "true/false không phải là bảng mã cây làm việc hợp lệ"
#, c-format
msgid "%s: clean filter '%s' failed"
-msgstr "%s: gặp lá»—i khi xóa bá»™ lá»c “%sâ€"
+msgstr "%s: bá»™ lá»c clean '%s' gặp lá»—i"
#, c-format
msgid "%s: smudge filter %s failed"
-msgstr "%s: smudge bá»™ lá»c %s gặp lá»—i"
+msgstr "%s: bá»™ lá»c smudge %s gặp lá»—i"
#, c-format
msgid "skipping credential lookup for key: credential.%s"
-msgstr "bỠqua tìm kiếm giấy chứng chực cho khóa: credential.%s"
+msgstr "bỠqua tìm kiếm giấy chứng thực cho khóa: credential.%s"
msgid "refusing to work with credential missing host field"
msgstr "từ chối làm việc vá»›i giấy chứng thá»±c thiếu trÆ°á»ng máy chủ"
@@ -14954,10 +15507,10 @@ msgstr "url không có lược đồ: %s"
#, c-format
msgid "credential url cannot be parsed: %s"
-msgstr "không thể phân tích cú pháp giấy chứng thực url: %s"
+msgstr "không hiểu cú pháp giấy chứng thực url: %s"
msgid "in the future"
-msgstr "ở thá»i tÆ°Æ¡ng lai"
+msgstr "ở tương lai"
#, c-format
msgid "%<PRIuMAX> second ago"
@@ -15010,35 +15563,64 @@ msgstr "Äang lan truyá»n các đánh dấu island"
#, c-format
msgid "bad tree object %s"
-msgstr "đối tượng cây sai “%sâ€"
+msgstr "đối tượng cây sai '%s'"
#, c-format
msgid "failed to load island regex for '%s': %s"
-msgstr "gặp lá»—i khi tải biểu thức chính quy island cho “%sâ€: %s"
+msgstr "gặp lỗi khi tải biểu thức chính quy island cho '%s': %s"
#, c-format
msgid "island regex from config has too many capture groups (max=%d)"
msgstr ""
-"biểu thức chính quy island từ cấu hình có quá nhiá»u nhóm chụp (tối Ä‘a=%d)"
+"biểu thức chính quy island từ cấu hình có quá nhiá»u nhóm chá»n (tối Ä‘a=%d)"
#, c-format
msgid "Marked %d islands, done.\n"
msgstr "Äã đánh dấu %d island, xong.\n"
-msgid "--merge-base does not work with ranges"
-msgstr "--merge-base không hoạt động với phạm vi"
+#, c-format
+msgid "invalid --%s value '%s'"
+msgstr "giá trị --%s không hợp lệ: '%s'"
-msgid "--merge-base only works with commits"
-msgstr "--merge-base chỉ hoạt động với các lần chuyển giao"
+#, c-format
+msgid "could not archive missing directory '%s'"
+msgstr "không thể nén thư mục '%s' không còn tồn tại"
+
+#, c-format
+msgid "could not open directory '%s'"
+msgstr "không thể mở thư mục '%s'"
+
+#, c-format
+msgid "skipping '%s', which is neither file nor directory"
+msgstr "đang bỠqua '%s', không phải là một tập tin hay thư mục"
+
+msgid "could not duplicate stdout"
+msgstr "không thể nhân bản stdout"
+
+#, c-format
+msgid "could not add directory '%s' to archiver"
+msgstr "không thể thêm thư mục '%s' vào kho nén"
+
+msgid "failed to write archive"
+msgstr "gặp lỗi khi ghi kho nén"
+
+msgid "--merge-base does not work with ranges"
+msgstr "--merge-base không thể dùng với chỉ vùng"
msgid "unable to get HEAD"
msgstr "không thể lấy HEAD"
msgid "no merge base found"
-msgstr "không tìm thấy cơ sở để hòa trộn"
+msgstr "không tìm thấy gốc hòa trộn"
msgid "multiple merge bases found"
-msgstr "có nhiá»u cÆ¡ sở để hòa trá»™n"
+msgstr "có nhiá»u hÆ¡n má»™t gốc hòa trá»™n"
+
+msgid "cannot compare stdin to a directory"
+msgstr "không thể so sánh stdin và thư mục"
+
+msgid "cannot compare a named pipe to a directory"
+msgstr "không thể so sánh pipe có tên và thư mục"
msgid "git diff --no-index [<options>] <path> <path>"
msgstr "git diff --no-index [<các tùy chá»n>] </Ä‘Æ°á»ng/dẫn> </Ä‘Æ°á»ng/dẫn>"
@@ -15048,54 +15630,65 @@ msgid ""
"tree"
msgstr ""
"Không phải là má»™t thÆ° mục git. Dùng --no-index để so sánh hai Ä‘Æ°á»ng dẫn bên "
-"ngoài một cây làm việc"
+"ngoài cây làm việc"
#, c-format
msgid " Failed to parse dirstat cut-off percentage '%s'\n"
-msgstr " Gặp lá»—i khi phân tích dirstat cắt bá» phần trăm “%sâ€\n"
+msgstr " Gặp lá»—i khi Ä‘á»c phần trăm cắt bá» dirstat '%s'\n"
#, c-format
msgid " Unknown dirstat parameter '%s'\n"
-msgstr " Không hiểu đối số dirstat “%sâ€\n"
+msgstr " Không hiểu đối số dirstat '%s'\n"
msgid ""
"color moved setting must be one of 'no', 'default', 'blocks', 'zebra', "
"'dimmed-zebra', 'plain'"
msgstr ""
-"cài đặt màu đã di chuyển phải là má»™t trong “noâ€, “defaultâ€, “blocksâ€, "
-"“zebraâ€, “dimmed-zebraâ€, “plainâ€"
+"cài đặt color moved phải là một trong 'no', 'default', 'blocks', 'zebra', "
+"'dimmed-zebra', 'plain'"
#, 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 ""
-"không hiểu chế Ä‘á»™ color-moved-ws “%sâ€, các giá trị có thể là “ignore-space-"
-"changeâ€, “ignore-space-at-eolâ€, “ignore-all-spaceâ€, “allow-indentation-"
-"changeâ€"
+"không hiểu chế độ color-moved-ws '%s', các giá trị có thể là 'ignore-space-"
+"change', 'ignore-space-at-eol', 'ignore-all-space', 'allow-indentation-"
+"change'"
msgid ""
"color-moved-ws: allow-indentation-change cannot be combined with other "
"whitespace modes"
msgstr ""
-"color-moved-ws: allow-indentation-change không thể tổ hợp cùng với các chế "
+"color-moved-ws: allow-indentation-change không thể kết hợp cùng với các chế "
"độ khoảng trắng khác"
#, c-format
msgid "Unknown value for 'diff.submodule' config variable: '%s'"
-msgstr "Không hiểu giá trị cho biến cấu hình “diff.submoduleâ€: “%sâ€"
+msgstr "Không hiểu giá trị cho biến cấu hình 'diff.submodule': '%s'"
+
+#, c-format
+msgid "unknown value for config '%s': %s"
+msgstr "không hiểu giá trị cho cho cấu hình '%s': %s"
#, c-format
msgid ""
"Found errors in 'diff.dirstat' config variable:\n"
"%s"
msgstr ""
-"Tìm thấy các lá»—i trong biến cấu hình “diff.dirstatâ€:\n"
+"Tìm thấy các lỗi trong biến cấu hình 'diff.dirstat':\n"
"%s"
#, c-format
msgid "external diff died, stopping at %s"
-msgstr "phần má»m diff ở bên ngoài đã chết, dừng tại %s"
+msgstr "phần má»m diff ở bên ngoài đã thoát, dừng tại %s"
+
+msgid "--follow requires exactly one pathspec"
+msgstr "--follow cần đúng má»™t đặc tả Ä‘Æ°á»ng dẫn"
+
+#, c-format
+msgid "pathspec magic not supported by --follow: %s"
+msgstr "đặc tả Ä‘Æ°á»ng dẫn đặc biệt chÆ°a được há»— trợ bởi --follow: %s"
#, c-format
msgid "options '%s', '%s', '%s', and '%s' cannot be used together"
@@ -15111,28 +15704,25 @@ msgid ""
msgstr ""
"tùy chá»n '%s' và '%s' không thể dùng cùng nhau, dùng '%s' vá»›i '%s' và '%s'"
-msgid "--follow requires exactly one pathspec"
-msgstr "--follow cần chính xác má»™t đặc tả Ä‘Æ°á»ng dẫn"
-
#, c-format
msgid "invalid --stat value: %s"
-msgstr "giá trị --stat không hợp lệ: “%sâ€"
+msgstr "giá trị --stat không hợp lệ: '%s'"
#, c-format
msgid "%s expects a numerical value"
-msgstr "tùy chá»n “%s†cần má»™t giá trị bằng số"
+msgstr "tùy chá»n '%s' cần má»™t giá trị số"
#, c-format
msgid ""
"Failed to parse --dirstat/-X option parameter:\n"
"%s"
msgstr ""
-"Gặp lá»—i khi phân tích đối số tùy chá»n --dirstat/-X:\n"
+"Gặp lá»—i khi Ä‘á»c đối số tùy chá»n --dirstat/-X:\n"
"%s"
#, c-format
msgid "unknown change class '%c' in --diff-filter=%s"
-msgstr "không hiểu lớp thay đổi “%c†trong --diff-filter=%s"
+msgstr "không hiểu change class '%c' trong --diff-filter=%s"
#, c-format
msgid "unknown value after ws-error-highlight=%.*s"
@@ -15140,7 +15730,7 @@ msgstr "không hiểu giá trị sau ws-error-highlight=%.*s"
#, c-format
msgid "unable to resolve '%s'"
-msgstr "không thể phân giải “%sâ€"
+msgstr "không thể phân giải '%s'"
#, c-format
msgid "%s expects <n>/<m> form"
@@ -15148,7 +15738,7 @@ msgstr "%s cần dạng <n>/<m>"
#, c-format
msgid "%s expects a character, got '%s'"
-msgstr "%s cần má»™t ký tá»±, nhÆ°ng lại nhận được “%sâ€"
+msgstr "%s cần một ký tự, nhưng lại có '%s'"
#, c-format
msgid "bad --color-moved argument: %s"
@@ -15156,14 +15746,7 @@ msgstr "đối số --color-moved sai: %s"
#, c-format
msgid "invalid mode '%s' in --color-moved-ws"
-msgstr "chế độ “%s†không hợp lệ trong --color-moved-ws"
-
-msgid ""
-"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
-"\"histogram\""
-msgstr ""
-"tùy chá»n diff-algorithm chấp nhận \"myers\", \"minimal\", \"patience\" và "
-"\"histogram\""
+msgstr "chế độ '%s' không hợp lệ trong --color-moved-ws"
#, c-format
msgid "invalid argument to %s"
@@ -15171,11 +15754,11 @@ msgstr "tham số cho %s không hợp lệ"
#, c-format
msgid "invalid regex given to -I: '%s'"
-msgstr "Ä‘Æ°a cho -I biểu thức chính quy không hợp lệ: “%sâ€"
+msgstr "đưa cho -I biểu thức chính quy không hợp lệ: '%s'"
#, c-format
msgid "failed to parse --submodule option parameter: '%s'"
-msgstr "gặp lá»—i khi phân tích đối số tùy chá»n --submodule: “%sâ€"
+msgstr "gặp lá»—i khi Ä‘á»c đối số tùy chá»n --submodule: '%s'"
#, c-format
msgid "bad --word-diff argument: %s"
@@ -15185,7 +15768,7 @@ msgid "Diff output format options"
msgstr "Các tùy chá»n định dạng khi xuất các khác biệt"
msgid "generate patch"
-msgstr "tạo miếng vá"
+msgstr "tạo bản vá"
msgid "<n>"
msgstr "<n>"
@@ -15197,10 +15780,10 @@ msgid "generate the diff in raw format"
msgstr "tạo khác biệt ở định dạng thô"
msgid "synonym for '-p --raw'"
-msgstr "đồng nghÄ©a vá»›i “-p --rawâ€"
+msgstr "đồng nghĩa với '-p --raw'"
msgid "synonym for '-p --stat'"
-msgstr "đồng nghÄ©a vá»›i “-p --statâ€"
+msgstr "đồng nghĩa với '-p --stat'"
msgid "machine friendly --stat"
msgstr "--stat thuận tiện cho máy Ä‘á»c"
@@ -15208,8 +15791,8 @@ msgstr "--stat thuận tiện cho máy Ä‘á»c"
msgid "output only the last line of --stat"
msgstr "chỉ xuất những dòng cuối của --stat"
-msgid "<param1,param2>..."
-msgstr "<tham_số_1,tham_số_2>…"
+msgid "<param1>,<param2>..."
+msgstr "<tham_số_1>,<tham_số_2>..."
msgid ""
"output the distribution of relative amount of changes for each sub-directory"
@@ -15218,8 +15801,8 @@ msgstr "đầu ra phân phối của số lượng thay đổi tương đối ch
msgid "synonym for --dirstat=cumulative"
msgstr "đồng nghĩa với --dirstat=cumulative"
-msgid "synonym for --dirstat=files,param1,param2..."
-msgstr "đồng nghĩa với --dirstat=files,param1,param2…"
+msgid "synonym for --dirstat=files,<param1>,<param2>..."
+msgstr "đồng nghĩa với --dirstat=files,<tham_số_1>,<tham_số_2>..."
msgid "warn if changes introduce conflict markers or whitespace errors"
msgstr ""
@@ -15266,8 +15849,8 @@ msgstr "xuất ra má»™t khác biệt dạng nhị phân cái mà có thể Ä‘Æ°á
msgid "show full pre- and post-image object names on the \"index\" lines"
msgstr ""
-"hiển thị đầy đủ các tên đối tượng pre- và post-image trên các dòng \"mục lục"
-"\""
+"hiển thị đầy đủ các tên đối tượng pre- và post-image trên các dòng \"mục "
+"lục\""
msgid "show colored diff"
msgstr "hiển thị thay đổi được tô màu"
@@ -15279,7 +15862,7 @@ msgid ""
"highlight whitespace errors in the 'context', 'old' or 'new' lines in the "
"diff"
msgstr ""
-"tô sáng các lá»—i vá» khoảng trắng trong các dòng “contextâ€, “old†và “new†"
+"tô sáng các lỗi vỠkhoảng trắng trong các dòng 'context', 'old' và 'new' "
"trong khác biệt"
msgid ""
@@ -15290,7 +15873,7 @@ msgstr ""
"trong --raw hay --numstat"
msgid "<prefix>"
-msgstr "<tiá»n_tố>"
+msgstr "<tiá»n tố>"
msgid "show the given source prefix instead of \"a/\""
msgstr "hiển thị tiá»n tố nguồn đã cho thay cho \"a/\""
@@ -15304,6 +15887,9 @@ msgstr "treo vào trÆ°á»›c má»™t tiá»n tố bổ sung cho má»—i dòng kết xuá
msgid "do not show any source or destination prefix"
msgstr "đừng hiển thị bất kỳ tiá»n tố nguồn hay đích"
+msgid "use default prefixes a/ and b/"
+msgstr "dùng tiá»n tố mặc định a/ và b/"
+
msgid "show context between diff hunks up to the specified number of lines"
msgstr ""
"hiển thị ngữ cảnh giữa các khúc khác biệt khi đạt đến số lượng dòng đã chỉ "
@@ -15313,13 +15899,13 @@ msgid "<char>"
msgstr "<ký_tự>"
msgid "specify the character to indicate a new line instead of '+'"
-msgstr "chỉ định má»™t ký tá»± để biểu thị má»™t dòng được thêm má»›i thay cho “+â€"
+msgstr "chỉ định một ký tự để biểu thị một dòng được thêm mới thay cho '+'"
msgid "specify the character to indicate an old line instead of '-'"
-msgstr "chỉ định má»™t ký tá»± để biểu thị má»™t dòng đã cÅ© thay cho “-â€"
+msgstr "chỉ định một ký tự để biểu thị một dòng đã cũ thay cho '-'"
msgid "specify the character to indicate a context instead of ' '"
-msgstr "chỉ định má»™t ký tá»± để biểu thị má»™t ngữ cảnh thay cho “â€"
+msgstr "chỉ định một ký tự để biểu thị một ngữ cảnh thay cho ''"
msgid "Diff rename options"
msgstr "Tùy chá»n khác biệt đổi tên"
@@ -15365,13 +15951,13 @@ msgid "produce the smallest possible diff"
msgstr "sản sinh khác biệt ít nhất có thể"
msgid "ignore whitespace when comparing lines"
-msgstr "lỠđi sự thay đổi do khoảng trắng gây ra khi so sánh các dòng"
+msgstr "bỠqua sự thay đổi do khoảng trắng gây ra khi so sánh các dòng"
msgid "ignore changes in amount of whitespace"
-msgstr "lỠđi sự thay đổi do số lượng khoảng trắng gây ra"
+msgstr "bỠqua sự thay đổi do số lượng khoảng trắng gây ra"
msgid "ignore changes in whitespace at EOL"
-msgstr "lỠđi sự thay đổi do khoảng trắng gây ra khi ở cuối dòng EOL"
+msgstr "bỠqua sự thay đổi do khoảng trắng gây ra khi ở cuối dòng EOL"
msgid "ignore carrier-return at the end of line"
msgstr "bỠqua ký tự vỠđầu dòng tại cuối dòng"
@@ -15394,12 +15980,6 @@ msgstr "tạo khác biệt sử dung thuật toán \"patience diff\""
msgid "generate diff using the \"histogram diff\" algorithm"
msgstr "tạo khác biệt sử dung thuật toán \"histogram diff\""
-msgid "<algorithm>"
-msgstr "<thuật toán>"
-
-msgid "choose a diff algorithm"
-msgstr "chá»n má»™t thuật toán khác biệt"
-
msgid "<text>"
msgstr "<văn bản>"
@@ -15446,7 +16026,7 @@ msgid "disable all output of the program"
msgstr "tắt má»i kết xuất của chÆ°Æ¡ng trình"
msgid "allow an external diff helper to be executed"
-msgstr "cho phép mộ bộ hỗ trợ xuất khác biệt ở bên ngoài được phép thực thi"
+msgstr "cho phép mộ helper xuất khác biệt ở bên ngoài được phép thực thi"
msgid "run external text conversion filters when comparing binary files"
msgstr ""
@@ -15466,10 +16046,10 @@ msgid "specify how differences in submodules are shown"
msgstr "chi định khác biệt bao nhiêu trong các mô đun con được hiển thị"
msgid "hide 'git add -N' entries from the index"
-msgstr "ẩn các mục “git add -N†từ bảng mục lục"
+msgstr "ẩn các mục 'git add -N' từ chỉ mục"
msgid "treat 'git add -N' entries as real in the index"
-msgstr "coi các mục “git add -N†như là có thật trong bảng mục lục"
+msgstr "coi các mục 'git add -N' như là có thật trong chỉ mục"
msgid "<string>"
msgstr "<chuá»—i>"
@@ -15492,19 +16072,19 @@ msgid "show all changes in the changeset with -S or -G"
msgstr "hiển thị tất cả các thay đổi trong một bộ các thay đổi với -S hay -G"
msgid "treat <string> in -S as extended POSIX regular expression"
-msgstr "coi <chuỗi> trong -S như là biểu thức chính qui POSIX có mở rộng"
+msgstr "coi <chuỗi> trong -S là biểu thức chính quy POSIX mở rộng"
msgid "control the order in which files appear in the output"
-msgstr "Ä‘iá»u khiển thứ tá»± xuát hiện các tập tin trong kết xuất"
+msgstr "Ä‘iá»u khiển thứ tá»± xuất hiện các tập tin trong đầu ra"
msgid "<path>"
msgstr "<Ä‘Æ°á»ng-dẫn>"
msgid "show the change in the specified path first"
-msgstr "hiển thị các thay đổi trong Ä‘Æ°á»ng dẫn đã cho đầu tiên"
+msgstr "hiển thị các thay đổi trong Ä‘Æ°á»ng dẫn đã cho ở đầu"
msgid "skip the output to the specified path"
-msgstr "bá» qua đầu ra đến Ä‘Æ°á»ng dẫn đã cho"
+msgstr "bá» qua đầu ra vá»›i Ä‘Æ°á»ng dẫn đã cho"
msgid "<object-id>"
msgstr "<mã-số-đối-tượng>"
@@ -15512,42 +16092,38 @@ msgstr "<mã-số-đối-tượng>"
msgid ""
"look for differences that change the number of occurrences of the specified "
"object"
-msgstr ""
-"tìm các khác biệt cái mà thay đổi số lượng xảy ra của các phát sinh của đối "
-"tượng được chỉ ra"
+msgstr "tìm các diff có thay đổi số lượng xuất hiện của đối tượng"
msgid "[(A|C|D|M|R|T|U|X|B)...[*]]"
-msgstr "[(A|C|D|M|R|T|U|X|B)…[*]]"
+msgstr "[(A|C|D|M|R|T|U|X|B)...[*]]"
msgid "select files by diff type"
msgstr "chá»n các tập tin theo kiểu khác biệt"
msgid "<file>"
-msgstr "<tập_tin>"
+msgstr "<tập tin>"
msgid "output to a specific file"
-msgstr "xuất ra một tập tin cụ thể"
+msgstr "xuất ra tập tin này"
msgid "exhaustive rename detection was skipped due to too many files."
-msgstr "nhận thấy đổi tên toàn diện đã bị bá» qua bởi có quá nhiá»u tập tin."
+msgstr "bá» tìm tất cả các lần đổi tên vì có quá nhiá»u tập tin."
msgid "only found copies from modified paths due to too many files."
msgstr ""
-"chỉ tìm thấy các bản sao từ Ä‘Æ°á»ng dẫn đã sá»­a đổi bởi vì có quá nhiá»u tập tin."
+"chỉ tìm các lần sao chép từ Ä‘Æ°á»ng dẫn đã sá»­a đổi vì có quá nhiá»u tập tin."
#, c-format
msgid ""
"you may want to set your %s variable to at least %d and retry the command."
-msgstr ""
-"bạn có lẽ muốn đặt biến %s của bạn thành ít nhất là %d và thử lại lệnh lần "
-"nữa."
+msgstr "bạn có lẽ muốn đặt biến %s của bạn thành ít nhất là %d và thử lại."
#, c-format
msgid "failed to read orderfile '%s'"
-msgstr "gặp lá»—i khi Ä‘á»c tập-tin-thứ-tá»± “%sâ€"
+msgstr "gặp lá»—i khi Ä‘á»c orderfile '%s'"
msgid "Performing inexact rename detection"
-msgstr "Äang thá»±c hiện dò tìm đổi tên không chính xác"
+msgstr "Äang thá»±c hiện inexact rename detection (tìm sÆ¡ bá»™ các lần đổi tên)"
#, c-format
msgid "No such path '%s' in the diff"
@@ -15555,43 +16131,43 @@ msgstr "Không có Ä‘Æ°á»ng dẫn %s trong diff"
#, c-format
msgid "pathspec '%s' did not match any file(s) known to git"
-msgstr "đặc tả Ä‘Æ°á»ng dẫn “%s†không khá»›p vá»›i bất kỳ tập tin nào mà git biết"
+msgstr "đặc tả Ä‘Æ°á»ng dẫn '%s' không khá»›p vá»›i bất kỳ tập tin nào mà git biết"
#, c-format
msgid "unrecognized pattern: '%s'"
-msgstr "mẫu không được thừa nhận: “%sâ€"
+msgstr "không hiểu mẫu: '%s'"
#, c-format
msgid "unrecognized negative pattern: '%s'"
-msgstr "mẫu âm không được thừa nhận: “%sâ€"
+msgstr "không hiểu mẫu loại trừ: '%s'"
#, c-format
msgid "your sparse-checkout file may have issues: pattern '%s' is repeated"
-msgstr "tập tin sparse-checkout của bạn có lẽ gặp lỗi: mẫu “%s†đã bị lặp lại"
+msgstr "tập tin sparse-checkout của bạn có lẽ gặp lỗi: mẫu '%s' đã bị lặp lại"
msgid "disabling cone pattern matching"
-msgstr "vô hiệu khớp mẫu nón"
+msgstr "vô hiệu cone pattern matching (khớp mẫu nón)"
#, c-format
msgid "cannot use %s as an exclude file"
-msgstr "không thể dùng %s như là một tập tin loại trừ"
+msgstr "không thể dùng %s như là tập tin loại trừ"
msgid "failed to get kernel name and information"
-msgstr "gặp lỗi khi lấy tên và thông tin của nhân"
+msgstr "gặp lỗi khi lấy tên và thông tin của kernel"
msgid "untracked cache is disabled on this system or location"
-msgstr "bộ nhớ tạm không theo vết bị tắt trên hệ thống hay vị trí này"
+msgstr "bộ nhớ tạm không theo vết bị vô hiệu trên hệ thống hay vị trí này"
msgid ""
"No directory name could be guessed.\n"
"Please specify a directory on the command line"
msgstr ""
"Không đoán được thư mục tên là gì.\n"
-"Vui lòng chỉ định tên một thư mục trên dòng lệnh"
+"Vui lòng chỉ định tên thư mục trên dòng lệnh"
#, c-format
msgid "index file corrupt in repo %s"
-msgstr "tập tin ghi bảng mục lục bị há»ng trong kho %s"
+msgstr "tập tin ghi chỉ mục bị há»ng trong kho %s"
#, c-format
msgid "could not create directories for %s"
@@ -15599,18 +16175,26 @@ msgstr "không thể tạo thư mục cho %s"
#, c-format
msgid "could not migrate git directory from '%s' to '%s'"
-msgstr "không thể di dá»i thÆ° mục git từ “%s†sang “%sâ€"
+msgstr "không thể di dá»i thÆ° mục git từ '%s' sang '%s'"
#, c-format
msgid "hint: Waiting for your editor to close the file...%c"
-msgstr "gợi ý: ChỠtrình biên soạn của bạn đóng tập tin…%c"
+msgstr "gợi ý: ChỠtrình biên soạn của bạn đóng tập tin...%c"
+
+#, c-format
+msgid "could not write to '%s'"
+msgstr "không thể ghi vào '%s'"
+
+#, c-format
+msgid "could not edit '%s'"
+msgstr "không thể sửa '%s'"
msgid "Filtering content"
msgstr "Ná»™i dung lá»c"
#, c-format
msgid "could not stat file '%s'"
-msgstr "không thể lấy thống kê tập tin “%sâ€"
+msgstr "không thể lấy thống kê tập tin '%s'"
#, c-format
msgid "bad git namespace path \"%s\""
@@ -15624,17 +16208,20 @@ msgid "git fetch-pack: expected shallow list"
msgstr "git fetch-pack: cần danh sách shallow"
msgid "git fetch-pack: expected a flush packet after shallow list"
-msgstr "git fetch-pack: cần một gói đẩy sau danh sách shallow"
+msgstr "git fetch-pack: cần một gói flush sau danh sách shallow"
msgid "git fetch-pack: expected ACK/NAK, got a flush packet"
msgstr "git fetch-pack: cần ACK/NAK, nhưng lại nhận được một gói flush"
#, c-format
msgid "git fetch-pack: expected ACK/NAK, got '%s'"
-msgstr "git fetch-pack: cần ACK/NAK, nhÆ°ng lại nhận được “%sâ€"
+msgstr "git fetch-pack: cần ACK/NAK, nhưng lại nhận được '%s'"
msgid "unable to write to remote"
-msgstr "không thể ghi lên máy phục vụ"
+msgstr "không thể ghi lên máy chủ"
+
+msgid "Server supports filter"
+msgstr "Máy chủ há»— trợ bá»™ lá»c"
#, c-format
msgid "invalid shallow line: %s"
@@ -15658,7 +16245,7 @@ msgstr "không tìm shallow nào: %s"
#, c-format
msgid "expected shallow/unshallow, got %s"
-msgstr "cần shallow/unshallow, nhưng lại nhận được %s"
+msgstr "cần shallow/unshallow, nhưng lại có %s"
#, c-format
msgid "got %s %d %s"
@@ -15741,28 +16328,25 @@ msgstr "các thuật toán không khớp nhau: máy khách %s; máy chủ %s"
#, c-format
msgid "the server does not support algorithm '%s'"
-msgstr "máy chủ không há»— trợ thuật toán “%sâ€"
+msgstr "máy chủ không hỗ trợ thuật toán '%s'"
msgid "Server does not support shallow requests"
msgstr "Máy chủ không hỗ trợ yêu cầu shallow"
-msgid "Server supports filter"
-msgstr "Máy chủ há»— trợ bá»™ lá»c"
-
msgid "unable to write request to remote"
-msgstr "không thể ghi các yêu cầu lên máy phục vụ"
+msgstr "không thể ghi các yêu cầu lên máy chủ"
#, c-format
msgid "expected '%s', received '%s'"
-msgstr "cần “%sâ€, nhÆ°ng lại nhận “%sâ€"
+msgstr "cần '%s', nhưng lại nhận '%s'"
#, c-format
msgid "expected '%s'"
-msgstr "cần “%sâ€"
+msgstr "cần '%s'"
#, c-format
msgid "unexpected acknowledgment line: '%s'"
-msgstr "gặp dòng không được thừa nhận: “%sâ€"
+msgstr "gặp dòng không được thừa nhận: '%s'"
#, c-format
msgid "error processing acks: %d"
@@ -15773,14 +16357,14 @@ msgstr "gặp lá»—i khi xá»­ lý tín hiệu trả lá»i: %d"
#.
#, c-format
msgid "expected packfile to be sent after '%s'"
-msgstr "cần tập tin gói để gá»­i sau “%sâ€"
+msgstr "cần tập tin gói để gửi sau '%s'"
#. TRANSLATORS: The parameter will be 'ready', a protocol
#. keyword.
#.
#, c-format
msgid "expected no other sections to be sent after no '%s'"
-msgstr "không cần thêm phần nào để gá»­i sau không “%sâ€"
+msgstr "không có phần nào để gửi khi không có '%s'"
#, c-format
msgid "error processing shallow info: %d"
@@ -15788,11 +16372,11 @@ msgstr "lỗi xử lý thông tin shallow: %d"
#, c-format
msgid "expected wanted-ref, got '%s'"
-msgstr "cần wanted-ref, nhÆ°ng lại nhận được “%sâ€"
+msgstr "cần wanted-ref, nhưng lại nhận được '%s'"
#, c-format
msgid "unexpected wanted-ref: '%s'"
-msgstr "wanted-ref không được mong đợi: “%sâ€"
+msgstr "wanted-ref không được mong đợi: '%s'"
#, c-format
msgid "error processing wanted refs: %d"
@@ -15805,7 +16389,7 @@ msgid "no matching remote head"
msgstr "không khớp phần đầu máy chủ"
msgid "unexpected 'ready' from remote"
-msgstr "gặp “ready†đột xuất từ máy chủ"
+msgstr "gặp 'ready' đột xuất từ máy chủ"
#, c-format
msgid "no such remote ref %s"
@@ -15813,8 +16397,7 @@ msgstr "không có máy chủ tham chiếu nào như %s"
#, c-format
msgid "Server does not allow request for unadvertised object %s"
-msgstr ""
-"Máy phục vụ không cho phép yêu cầu cho đối tượng không được báo trước %s"
+msgstr "máy chủ không cho phép yêu cầu cho đối tượng không được báo trước %s"
#, c-format
msgid "fsmonitor_ipc__send_query: invalid path '%s'"
@@ -15833,7 +16416,7 @@ msgstr "không thể gửi lệnh '%s' đến fsmonitor--daemon"
#, c-format
msgid "bare repository '%s' is incompatible with fsmonitor"
-msgstr "kho thuần '%s' là không tương thích với fsmonitor"
+msgstr "kho bare '%s' là không tương thích với fsmonitor"
#, c-format
msgid "repository '%s' is incompatible with fsmonitor due to errors"
@@ -15849,8 +16432,11 @@ msgstr "kho ảo '%s' là không tương thích với fsmonitor"
#, c-format
msgid ""
-"repository '%s' is incompatible with fsmonitor due to lack of Unix sockets"
-msgstr "kho '%s' là không tương thích với fsmonitor bởi vì thiếu Unix sockets"
+"socket directory '%s' is incompatible with fsmonitor due to lack of Unix "
+"sockets support"
+msgstr ""
+"thư mục socket '%s' không tương thích với fsmonitor bởi vì thiếu hỗ trợ Unix "
+"socket"
msgid ""
"git [-v | --version] [-h | --help] [-C <path>] [-c <name>=<value>]\n"
@@ -15858,18 +16444,16 @@ msgid ""
" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--"
"bare]\n"
" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
-" [--super-prefix=<path>] [--config-env=<name>=<envvar>]\n"
-" <command> [<args>]"
+" [--config-env=<name>=<envvar>] <command> [<args>]"
msgstr ""
-"git [--version] [-h | --help] [-C </Ä‘Æ°á»ng/dẫn/>] [-c <tên>=<giá trị>]\n"
+"git [-v | --version] [-h | --help] [-C </Ä‘Æ°á»ng/dẫn/>] [-c <tên>=<giá trị>]\n"
" [--exec-path[=</Ä‘Æ°á»ng/dẫn/>]] [--html-path] [--man-path] [--info-"
"path]\n"
" [-p | --paginate | -P --no-pager] [--no-replace-objects] [--"
"bare]\n"
" [--git-dir=</Ä‘Æ°á»ng/dẫn/>] [--work-tree=</Ä‘Æ°á»ng/dẫn/>] [--"
"namespace=<tên>]\n"
-" [--super-prefix=</Ä‘Æ°á»ng/dẫn/>] [--config-env=<tên>=<envvar>]\n"
-" <lệnh> [<các tham số>]"
+" [--config-env=<tên>=<envvar>] <lệnh> [<các tham số>]"
msgid ""
"'git help -a' and 'git help -g' list available subcommands and some\n"
@@ -15877,14 +16461,14 @@ msgid ""
"to read about a specific subcommand or concept.\n"
"See 'git help git' for an overview of the system."
msgstr ""
-"“git help -a†và “git help -g†liệt kê các câu lệnh con sẵn có và một số\n"
-"hÆ°á»›ng dẫn vá» khái niệm. Xem “git help <lệnh>†hay “git help <khái-niệm>â€\n"
+"'git help -a' và 'git help -g' liệt kê các câu lệnh con sẵn có và một số\n"
+"hướng dẫn vỠkhái niệm. Xem 'git help <lệnh>' hay 'git help <khái-niệm>'\n"
"để xem các đặc tả cho lệnh hay khái niệm cụ thể.\n"
-"Xem “git help git†để biết tổng quan của hệ thống."
+"Xem 'git help git' để biết tổng quan của hệ thống."
#, c-format
msgid "unsupported command listing type '%s'"
-msgstr "không há»— trợ liệt kê lệnh kiểu “%sâ€"
+msgstr "không hỗ trợ liệt kê lệnh kiểu '%s'"
#, c-format
msgid "no directory given for '%s' option\n"
@@ -15895,10 +16479,6 @@ msgid "no namespace given for --namespace\n"
msgstr "chưa đưa ra không gian làm việc cho --namespace\n"
#, c-format
-msgid "no prefix given for --super-prefix\n"
-msgstr "chÆ°a Ä‘Æ°a ra tiá»n tố cho --super-prefix\n"
-
-#, c-format
msgid "-c expects a configuration string\n"
msgstr "-c cần một chuỗi cấu hình\n"
@@ -15907,20 +16487,24 @@ msgid "no config key given for --config-env\n"
msgstr "không đưa ra khóa cấu hình cho --config-env\n"
#, c-format
+msgid "no attribute source given for --attr-source\n"
+msgstr "không đưa ra nguồn thuộc tính cho --attr-source\n"
+
+#, c-format
msgid "unknown option: %s\n"
msgstr "không hiểu tùy chá»n: %s\n"
#, c-format
msgid "while expanding alias '%s': '%s'"
-msgstr "trong khi triển khai bí danh “%sâ€: “%sâ€"
+msgstr "trong khi triển khai bí danh '%s': '%s'"
#, c-format
msgid ""
"alias '%s' changes environment variables.\n"
"You can use '!git' in the alias to do this"
msgstr ""
-"bí danh “%s†thay đổi biến môi trÆ°á»ng.\n"
-"Bạn có thể sử dụng “!git†trong đặt bí danh để làm việc này"
+"bí danh '%s' thay đổi biến môi trÆ°á»ng.\n"
+"Bạn có thể sử dụng '!git' trong đặt bí danh để làm việc này"
#, c-format
msgid "empty alias for %s"
@@ -15931,22 +16515,22 @@ msgid "recursive alias: %s"
msgstr "đệ quy các bí danh: %s"
msgid "write failure on standard output"
-msgstr "lỗi ghi nghiêm trong trên đầu ra tiêu chuẩn"
+msgstr "lá»—i khi ghi ra stdout"
msgid "unknown write failure on standard output"
-msgstr "lá»—i nghiêm trá»ng chÆ°a biết khi ghi ra đầu ra tiêu chuẩn"
+msgstr "lỗi không rõ khi ghi ra stdout"
msgid "close failed on standard output"
-msgstr "gặp lỗi khi đóng đầu ra tiêu chuẩn"
+msgstr "lỗi khi đóng stdout"
#, c-format
msgid "alias loop detected: expansion of '%s' does not terminate:%s"
msgstr ""
-"dò tìm thấy các bí danh quẩn tròn: biểu thức của “%s†không có điểm kết:%s"
+"dò tìm thấy các bí danh quẩn tròn: biểu thức của '%s' không có điểm kết:%s"
#, c-format
msgid "cannot handle %s as a builtin"
-msgstr "không thể xử lý %s như là một phần bổ sung"
+msgstr "không thể xử lý %s như là builtin"
#, c-format
msgid ""
@@ -15958,18 +16542,18 @@ msgstr ""
#, c-format
msgid "expansion of alias '%s' failed; '%s' is not a git command\n"
-msgstr "gặp lá»—i khi khai triển bí danh “%sâ€; “%s†không phải là lệnh git\n"
+msgstr "gặp lỗi khi khai triển bí danh '%s'; '%s' không phải là lệnh git\n"
#, c-format
msgid "failed to run command '%s': %s\n"
-msgstr "gặp lá»—i khi chạy lệnh “%sâ€: %s\n"
+msgstr "gặp lỗi khi chạy lệnh '%s': %s\n"
msgid "could not create temporary file"
msgstr "không thể tạo tập tin tạm thá»i"
#, c-format
msgid "failed writing detached signature to '%s'"
-msgstr "gặp lá»—i khi ghi chữ ký đính kèm vào “%sâ€"
+msgstr "gặp lỗi khi ghi chữ ký đính kèm vào '%s'"
msgid ""
"gpg.ssh.allowedSignersFile needs to be configured and exist for ssh "
@@ -15991,11 +16575,11 @@ msgstr "tập tin thu hồi chữ ký ssh đã được cấu hình nhưng khôn
#, c-format
msgid "bad/incompatible signature '%s'"
-msgstr "chữ sai / không tÆ°Æ¡ng thích “%sâ€"
+msgstr "chữ sai / không tương thích '%s'"
#, c-format
msgid "failed to get the ssh fingerprint for key '%s'"
-msgstr "gặp lá»—i khi lấy dấu vân tay ssh cho khóa “%sâ€"
+msgstr "gặp lỗi khi lấy dấu vân tay ssh cho khóa '%s'"
msgid ""
"either user.signingkey or gpg.ssh.defaultKeyCommand needs to be configured"
@@ -16011,19 +16595,24 @@ msgstr ""
msgid "gpg.ssh.defaultKeyCommand failed: %s %s"
msgstr "gpg.ssh.defaultKeyCommand gặp lỗi: %s %s"
-msgid "gpg failed to sign the data"
-msgstr "gpg gặp lỗi khi ký dữ liệu"
+#, c-format
+msgid ""
+"gpg failed to sign the data:\n"
+"%s"
+msgstr ""
+"gpg gặp lỗi khi ký dữ liệu:\n"
+"%s"
msgid "user.signingKey needs to be set for ssh signing"
msgstr "user.signingKey cần được đặt cho ký ssh"
#, c-format
msgid "failed writing ssh signing key to '%s'"
-msgstr "gặp lá»—i khi ghi chìa khóa ký ssh vào “%sâ€"
+msgstr "gặp lỗi khi ghi chìa khóa ký ssh vào '%s'"
#, c-format
msgid "failed writing ssh signing key buffer to '%s'"
-msgstr "gặp lá»—i khi ghi bá»™ đệm chìa khóa ký ssh vào “%sâ€"
+msgstr "gặp lỗi khi ghi bộ đệm chìa khóa ký ssh vào '%s'"
msgid ""
"ssh-keygen -Y sign is needed for ssh signing (available in openssh version "
@@ -16034,11 +16623,11 @@ msgstr ""
#, c-format
msgid "failed reading ssh signing data buffer from '%s'"
-msgstr "gặp lá»—i khi Ä‘á»c bá»™ đệm dữ liệu chữ ký ssh từ “%sâ€"
+msgstr "gặp lá»—i khi Ä‘á»c bá»™ đệm dữ liệu chữ ký ssh từ '%s'"
#, c-format
msgid "ignored invalid color '%.*s' in log.graphColors"
-msgstr "bỠqua màu không hợp lệ “%.*s†trong log.graphColors"
+msgstr "bỠqua màu không hợp lệ '%.*s' trong log.graphColors"
msgid ""
"given pattern contains NULL byte (via -f <file>). This is only supported "
@@ -16049,11 +16638,11 @@ msgstr ""
#, c-format
msgid "'%s': unable to read %s"
-msgstr "“%sâ€: không thể Ä‘á»c %s"
+msgstr "'%s': không thể Ä‘á»c %s"
#, c-format
msgid "'%s': short read"
-msgstr "“%sâ€: Ä‘á»c ngắn"
+msgstr "'%s': Ä‘á»c ngắn"
msgid "start a working area (see also: git help tutorial)"
msgstr "bắt đầu một vùng làm việc (xem thêm: git help tutorial)"
@@ -16094,9 +16683,15 @@ msgstr "Lệnh/Äồng bá»™ kho ở mức thấp"
msgid "Low-level Commands / Internal Helpers"
msgstr "Lệnh/Hỗ trợ nội tại ở mức thấp"
+msgid "User-facing repository, command and file interfaces"
+msgstr "Các giao diện kho, lệnh và tập tin hÆ°á»›ng ngÆ°á»i dùng"
+
+msgid "Developer-facing file formats, protocols and other interfaces"
+msgstr "Các giao diện tập tin, giao thức và khác cho lập trình viên"
+
#, c-format
msgid "available git commands in '%s'"
-msgstr "các lệnh git sẵn có trong thÆ° mục “%sâ€:"
+msgstr "các lệnh git sẵn có trong thư mục '%s':"
msgid "git commands available from elsewhere on your $PATH"
msgstr "các lệnh git sẵn có từ một nơi khác trong $PATH của bạn"
@@ -16107,6 +16702,12 @@ msgstr "Có các lệnh Git chung được sử dụng trong các tình huống
msgid "The Git concept guides are:"
msgstr "Các chỉ dẫn khái niệm vỠGit là:"
+msgid "User-facing repository, command and file interfaces:"
+msgstr "Các giao diện kho, lệnh và tập tin hÆ°á»›ng ngÆ°á»i dùng"
+
+msgid "File formats, protocols and other developer interfaces:"
+msgstr "Các giao diện tập tin, giao thức và khác cho lập trình viên"
+
msgid "External commands"
msgstr "Các lệnh bên ngoài"
@@ -16114,38 +16715,38 @@ msgid "Command aliases"
msgstr "Các bí danh lệnh"
msgid "See 'git help <command>' to read about a specific subcommand"
-msgstr "Xem “git help <lệnh>†để Ä‘á»c các đặc tả của lệnh con"
+msgstr "Xem 'git help <lệnh>' để Ä‘á»c các đặc tả của lệnh con"
#, 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†trông như là một lệnh git, nhưng chúng tôi không\n"
+"'%s' trông như là một lệnh git, nhưng chúng tôi không\n"
"thể thá»±c thi nó. Có lẽ là lệnh git-%s đã bị há»ng?"
#, c-format
msgid "git: '%s' is not a git command. See 'git --help'."
-msgstr "git: “%s†không phải là má»™t lệnh của git. Xem “git --helpâ€."
+msgstr "git: '%s' không phải là một lệnh của git. Xem 'git --help'."
msgid "Uh oh. Your system reports no Git commands at all."
msgstr "á»i chà. Hệ thống của bạn báo rằng chẳng có lệnh Git nào cả."
#, c-format
msgid "WARNING: You called a Git command named '%s', which does not exist."
-msgstr "CẢNH BÃO: Bạn đã gá»i lệnh Git có tên “%sâ€, mà nó lại không có sẵn."
+msgstr "CẢNH BÃO: Bạn đã gá»i lệnh Git có tên '%s', mà nó lại không có sẵn."
#, c-format
msgid "Continuing under the assumption that you meant '%s'."
-msgstr "Tiếp tục và coi rằng ý bạn là “%sâ€."
+msgstr "Tiếp tục và coi rằng ý bạn là '%s'."
#, c-format
msgid "Run '%s' instead [y/N]? "
-msgstr "Chạy “%s†để thay thế? (y/N)? "
+msgstr "Chạy '%s' để thay thế? (y/N)? "
#, c-format
msgid "Continuing in %0.1f seconds, assuming that you meant '%s'."
-msgstr "Tiếp tục trong %0.1f giây,và coi rằng ý bạn là “%sâ€."
+msgstr "Tiếp tục trong %0.1f giây,và coi rằng ý bạn là '%s'."
msgid ""
"\n"
@@ -16157,8 +16758,8 @@ msgstr[0] ""
"\n"
"Những lệnh giống nhất là"
-msgid "git version [<options>]"
-msgstr "git version [<các tùy chá»n>]"
+msgid "git version [--build-options]"
+msgstr "git version [--build-options]"
#, c-format
msgid "%s: %s - %s"
@@ -16179,16 +16780,12 @@ 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 ""
-"Móc “%s†bị bỠqua bởi vì nó không thể đặt là thực thi được.\n"
-"Bạn có thể tắt cảnh báo này bằng “git config advice.ignoredHook false“."
-
-#, c-format
-msgid "Couldn't start hook '%s'\n"
-msgstr "Không thể khởi chạy móc “%sâ€\n"
+"Móc '%s' bị bỠqua bởi vì nó không thể đặt là thực thi được.\n"
+"Bạn có thể tắt cảnh báo này bằng 'git config advice.ignoredHook false'."
#, c-format
msgid "argument to --packfile must be a valid hash (got '%s')"
-msgstr "tham số cho --packfile phải là má»™t giá trị băm hợp lệ (nhận được “%sâ€)"
+msgstr "tham số cho --packfile phải là một giá trị băm hợp lệ (có '%s')"
msgid "not a git repository"
msgstr "không phải là kho git"
@@ -16209,18 +16806,18 @@ msgstr "CURLSSLOPT_NO_REVOKE không được hỗ trợ với cURL < 7.44.0"
#, c-format
msgid "Unsupported SSL backend '%s'. Supported SSL backends:"
msgstr ""
-"Không há»— trợ ứng dụng SSL chạy phía sau “%sâ€. Há»— trợ ứng dụng SSL chạy phía "
+"Không hỗ trợ ứng dụng SSL chạy phía sau '%s'. Hỗ trợ ứng dụng SSL chạy phía "
"sau:"
#, c-format
msgid "Could not set SSL backend to '%s': cURL was built without SSL backends"
msgstr ""
-"Không thể đặt ứng dụng chạy SSL phía sau “%sâ€: cURL được biên dịch không có "
+"Không thể đặt ứng dụng chạy SSL phía sau '%s': cURL được biên dịch không có "
"sự hỗ trợ ứng dụng chạy phía sau SSL"
#, c-format
msgid "Could not set SSL backend to '%s': already set"
-msgstr "Không thể đặt ứng dụng chạy sau SSL cho “%sâ€: đã đặt rồi"
+msgstr "Không thể đặt ứng dụng chạy sau SSL cho '%s': đã đặt rồi"
#, c-format
msgid ""
@@ -16268,14 +16865,14 @@ msgstr "không đưa ra địa chỉ thư điện tử và auto-detection bị t
#, c-format
msgid "unable to auto-detect email address (got '%s')"
-msgstr "không thể tá»± dò tìm địa chỉ thÆ° Ä‘iện tá»­ (nhận “%sâ€)"
+msgstr "không thể tự dò tìm địa chỉ thư điện tử (nhận '%s')"
msgid "no name was given and auto-detection is disabled"
msgstr "chưa chỉ ra tên và tự-động-dò-tìm bị tắt"
#, c-format
msgid "unable to auto-detect name (got '%s')"
-msgstr "không thể dò-tìm-tá»± Ä‘á»™ng tên (đã nhận “%sâ€)"
+msgstr "không thể dò-tìm-tự động tên (đã nhận '%s')"
#, c-format
msgid "empty ident name (for <%s>) not allowed"
@@ -16286,22 +16883,22 @@ msgid "name consists only of disallowed characters: %s"
msgstr "tên chỉ được phép bao gồm các ký tự sau: %s"
msgid "expected 'tree:<depth>'"
-msgstr "cần “tree:<depth>â€"
+msgstr "cần 'tree:<depth>'"
msgid "sparse:path filters support has been dropped"
-msgstr "việc há»— trợ bá»™ lá»c sparse:Ä‘Æ°á»ng/dẫn đã bị bá»"
+msgstr "há»— trợ bá»™ lá»c sparse:Ä‘Æ°á»ng/dẫn đã không còn"
#, c-format
msgid "'%s' for 'object:type=<type>' is not a valid object type"
-msgstr "“%s†dành cho “object:type=<type>†không phải là kiểu đối tượng hợp lệ"
+msgstr "'%s' dành cho 'object:type=<type>' không phải là kiểu đối tượng hợp lệ"
#, c-format
msgid "invalid filter-spec '%s'"
-msgstr "đặc tả bá»™ lá»c không hợp lệ “%sâ€"
+msgstr "đặc tả bá»™ lá»c không hợp lệ '%s'"
#, c-format
msgid "must escape char in sub-filter-spec: '%c'"
-msgstr "phải thoát char trong sub-filter-spec: “%câ€"
+msgstr "phải thoát char trong sub-filter-spec: '%c'"
msgid "expected something after combine:"
msgstr "mong đợi một cái gì đó sau khi kết hợp:"
@@ -16320,23 +16917,23 @@ msgstr "lá»c đối tượng"
#, c-format
msgid "unable to access sparse blob in '%s'"
-msgstr "không thể truy cập các blob rải rác trong “%sâ€"
+msgstr "không thể truy cập các blob rải rác trong '%s'"
#, c-format
msgid "unable to parse sparse filter data in %s"
-msgstr "không thể phân tích dữ liệu bá»™ lá»c rải rác trong %s"
+msgstr "không thể Ä‘á»c dữ liệu bá»™ lá»c rải rác trong %s"
#, c-format
msgid "entry '%s' in tree %s has tree mode, but is not a tree"
-msgstr "mục “%s†trong cây %s có nút cây, nhưng không phải là một cây"
+msgstr "mục '%s' trong cây %s có nút cây, nhưng không phải là một cây"
#, c-format
msgid "entry '%s' in tree %s has blob mode, but is not a blob"
-msgstr "mục “%s†trong cây %s có nút blob, nhưng không phải là một blob"
+msgstr "mục '%s' trong cây %s có nút blob, nhưng không phải là một blob"
#, c-format
msgid "unable to load root tree for commit %s"
-msgstr "không thể tải cây gốc cho lần chuyển giao “%sâ€"
+msgstr "không thể tải cây gốc cho lần chuyển giao '%s'"
#, c-format
msgid ""
@@ -16348,21 +16945,29 @@ msgid ""
"may have crashed in this repository earlier:\n"
"remove the file manually to continue."
msgstr ""
-"Không thể tạo “%s.lockâ€: %s.\n"
+"Không thể tạo '%s.lock': %s.\n"
"\n"
"Tiến trình git khác có lẽ đang chạy ở kho này, ví dụ\n"
-"má»™t trình soạn thảo được mở bởi “git commitâ€. Vui lòng chắc chắn\n"
-"rằng má»i tiến trình đã chấm dứt và sau đó thá»­ lại. Nếu vẫn lá»—i,\n"
-"một tiến trình git có lẽ đã đổ vỡ khi thực hiện ở kho này trước đó:\n"
+"một trình soạn thảo được mở bởi 'git commit'. Vui lòng chắc chắn\n"
+"rằng má»i tiến trình đã kết thúc và sau đó thá»­ lại. Nếu vẫn lá»—i,\n"
+"một tiến trình git có lẽ đã crash khi thực hiện ở kho này trước đó:\n"
"gõ bỠtập tin một cách thủ công để tiếp tục."
#, c-format
msgid "Unable to create '%s.lock': %s"
-msgstr "Không thể tạo “%s.lockâ€: %s"
+msgstr "Không thể tạo '%s.lock': %s"
+
+#, c-format
+msgid "could not write loose object index %s"
+msgstr "không thể ghi tập tin đối tượng loose %s"
+
+#, c-format
+msgid "failed to write loose object index %s\n"
+msgstr "ghi chỉ mục đối tượng loose %s thất bại\n"
#, c-format
msgid "unexpected line: '%s'"
-msgstr "dòng không cần: “%sâ€"
+msgstr "dòng bất thÆ°á»ng: '%s'"
msgid "expected flush after ls-refs arguments"
msgstr "cần đẩy dữ liệu lên đĩa sau tham số ls-refs (liệt kê tham chiếu)"
@@ -16371,73 +16976,57 @@ msgid "quoted CRLF detected"
msgstr "phát hiện CRLF được trích dẫn"
#, c-format
-msgid ""
-"Your local changes to the following files would be overwritten by merge:\n"
-" %s"
-msgstr ""
-"Các thay đổi nội bộ của bạn với các tập tin sau đây sẽ bị ghi đè bởi lệnh "
-"hòa trộn:\n"
-" %s"
+msgid "unable to format message: %s"
+msgstr "không thể định dạng thông điệp: %s"
#, c-format
msgid "Failed to merge submodule %s (not checked out)"
-msgstr "Gặp lỗi khi hòa trộn mô-đun-con “%s†(không lấy ra được)"
+msgstr "Gặp lỗi khi hòa trộn mô-đun-con %s (không checkout được)"
+
+#, c-format
+msgid "Failed to merge submodule %s (no merge base)"
+msgstr "Gặp lỗi khi hòa trộn mô-đun-con %s (không có gốc hoà trộn)"
#, c-format
msgid "Failed to merge submodule %s (commits not present)"
-msgstr "Gặp lỗi khi hòa trộn mô-đun-con “%s†(lần chuyển giao không hiện diện)"
+msgstr "Gặp lỗi khi hòa trộn mô-đun-con %s (lần chuyển giao không hiện diện)"
+
+#, c-format
+msgid "Failed to merge submodule %s (repository corrupt)"
+msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con %s (kho chứa há»ng)"
#, c-format
msgid "Failed to merge submodule %s (commits don't follow merge-base)"
msgstr ""
-"Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con “%s†(lần chuyển giao không theo sau ná»n-hòa-"
+"Gặp lỗi khi hòa trộn mô-đun-con %s (lần chuyển giao không theo sau gốc-hòa-"
"trá»™n)"
#, c-format
msgid "Note: Fast-forwarding submodule %s to %s"
-msgstr "Chú ý: Chuyển-tiếp-nhanh mô-Ä‘un-con “%s†sang “%sâ€"
+msgstr "Chú ý: Chuyển-tiếp-nhanh mô-đun-con %s sang %s"
#, c-format
msgid "Failed to merge submodule %s"
-msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con “%sâ€"
+msgstr "Gặp lỗi khi hòa trộn mô-đun-con %s"
#, c-format
msgid ""
-"Failed to merge submodule %s, but a possible merge resolution exists:\n"
-"%s\n"
-msgstr ""
-"Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con “%sâ€, nhÆ°ng có cách giải quyết:\n"
-"%s\n"
-
-#, c-format
-msgid ""
-"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"
-msgstr ""
-"Nếu đây là đúng đơn giản thêm nó vào mục lục ví dụ\n"
-"bằng cách dùng:\n"
-"\n"
-" git update-index --cacheinfo 160000 %s \"%s\"\n"
-"\n"
-"cái mà sẽ chấp nhận gợi ý này.\n"
+"Failed to merge submodule %s, but a possible merge resolution exists: %s"
+msgstr "Gặp lỗi khi hòa trộn mô-đun-con %s, nhưng có cách giải quyết: %s"
#, c-format
msgid ""
"Failed to merge submodule %s, but multiple possible merges exist:\n"
"%s"
msgstr ""
-"Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con “%sâ€, nhÆ°ng có nhiá»u cách giải quyết:\n"
+"Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con %s, nhÆ°ng có nhiá»u cách giải quyết:\n"
"%s"
-msgid "Failed to execute internal merge"
+msgid "failed to execute internal merge"
msgstr "Gặp lỗi khi thực hiện trộn nội bộ"
#, c-format
-msgid "Unable to add %s to database"
+msgid "unable to add %s to database"
msgstr "Không thể thêm %s vào cơ sở dữ liệu"
#, c-format
@@ -16449,16 +17038,16 @@ msgid ""
"CONFLICT (implicit dir rename): Existing file/dir at %s in the way of "
"implicit directory rename(s) putting the following path(s) there: %s."
msgstr ""
-"XUNG ÄỘT: (ngầm đổi tên thÆ° mục): Tập tin/thÆ° mục đã sẵn có tại %s theo cách "
-"của các đổi tên thÆ° mục ngầm đặt (các) Ä‘Æ°á»ng dẫn sau ở đây: %s."
+"XUNG ÄỘT: (ngầm đổi tên thÆ° mục): Tập tin/thÆ° mục đã sẵn có tại %s do việc "
+"đổi tên thÆ° mục sẽ đặt các Ä‘Æ°á»ng dẫn sau ở đó: %s."
#, c-format
msgid ""
"CONFLICT (implicit dir rename): Cannot map more than one path to %s; "
"implicit directory renames tried to put these paths there: %s"
msgstr ""
-"XUNG ÄỘT: (ngầm đổi tên thÆ° mục): Không thể ánh xạ má»™t Ä‘Æ°á»ng dẫn thành %s; "
-"các đổi tên thÆ° mục ngầm cố đặt các Ä‘Æ°á»ng dẫn ở đây: %s"
+"XUNG ÄỘT: (ngầm đổi tên thÆ° mục): Không thể ánh xạ hÆ¡n má»™t Ä‘Æ°á»ng dẫn thành "
+"%s; việc đổi tên thÆ° mục sẽ đặt các Ä‘Æ°á»ng dẫn sau ở đó: %s"
#, c-format
msgid ""
@@ -16466,17 +17055,17 @@ msgid ""
"renamed to multiple other directories, with no destination getting a "
"majority of the files."
msgstr ""
-"XUNG ÄỘT: (thÆ° mục đổi tên chia tách): Không rõ ràng nÆ¡i để đổi tên %s "
-"thành; nó đã bị đổi tên thành nhiá»u thÆ° mục khác, vá»›i không đích đến nhận "
-"má»™t phần nhiá»u của các tập tin."
+"XUNG ÄỘT: (phân hoá đổi tên thÆ° mục): Không rõ đổi tên %s vỠđâu; nó đã bị "
+"đổi tên thành nhiá»u thÆ° mục khác, mà không bên nào nhận phần lá»›n các tập tin "
+"gốc."
#, c-format
msgid ""
"WARNING: Avoiding applying %s -> %s rename to %s, because %s itself was "
"renamed."
msgstr ""
-"CẢNH BÃO: tránh áp dụng %s -> %s đổi thên thành %s, bởi vì bản thân %s cÅ©ng "
-"bị đổi tên."
+"CẢNH BÃO: Tránh áp dụng đổi tên %s -> %s cho %s, bởi vì bản thân %s đã bị "
+"đổi tên."
#, c-format
msgid ""
@@ -16484,7 +17073,7 @@ msgid ""
"moving it to %s."
msgstr ""
"ÄÆ°á»ng dẫn đã được cập nhật: %s được thêm vào trong %s bên trong má»™t thÆ° mục "
-"đã được đổi tên trong %s; di chuyển nó đến %s."
+"đã được đổi tên trong %s; sẽ di chuyển nó đến %s."
#, c-format
msgid ""
@@ -16492,14 +17081,14 @@ msgid ""
"%s; moving it to %s."
msgstr ""
"ÄÆ°á»ng dẫn đã được cập nhật: %s được đổi tên thành %s trong %s, bên trong má»™t "
-"thư mục đã được đổi tên trong %s; di chuyển nó đến %s."
+"thư mục đã được đổi tên trong %s; sẽ di chuyển nó đến %s."
#, c-format
msgid ""
"CONFLICT (file location): %s added in %s inside a directory that was renamed "
"in %s, suggesting it should perhaps be moved to %s."
msgstr ""
-"XUNG ÄỘT (vị trí tệp): %s được thêm vào trong %s trong má»™t thÆ° mục đã được "
+"XUNG ÄỘT (vị trí tập): %s được thêm vào trong %s trong má»™t thÆ° mục đã được "
"đổi tên thành %s, đoán là nó nên được di chuyển đến %s."
#, c-format
@@ -16507,7 +17096,7 @@ msgid ""
"CONFLICT (file location): %s renamed to %s in %s, inside a directory that "
"was renamed in %s, suggesting it should perhaps be moved to %s."
msgstr ""
-"XUNG ÄỘT (vị trí tệp): %s được đổi tên thành %s trong %s, bên trong má»™t thÆ° "
+"XUNG ÄỘT (vị trí tập): %s được đổi tên thành %s trong %s, bên trong má»™t thÆ° "
"mục đã được đổi tên thành %s, đoán là nó nên được di chuyển đến %s."
#, c-format
@@ -16583,13 +17172,43 @@ msgstr ""
"XUNG ÄỘT (sá»­a/xóa): %s bị xóa trong %s và sá»­a trong %s. Phiên bản %s của %s "
"còn lại trong cây (tree)."
+#. TRANSLATORS: This is a line of advice to resolve a merge
+#. conflict in a submodule. The first argument is the submodule
+#. name, and the second argument is the abbreviated id of the
+#. commit that needs to be merged. For example:
+#. - go to submodule (mysubmodule), and either merge commit abc1234"
+#.
+#, c-format
+msgid ""
+" - go to submodule (%s), and either merge commit %s\n"
+" or update to an existing commit which has merged those changes\n"
+msgstr ""
+" - đi tới mô-đun con (%s), và hoà trộn lần chuyển giao %s\n"
+" hoặc cập nhật tới một lần chuyển giao đã có hoà trộn các thay đổi\n"
+
#, c-format
msgid ""
-"Note: %s not up to date and in way of checking out conflicted version; old "
-"copy renamed to %s"
+"Recursive merging with submodules currently only supports trivial cases.\n"
+"Please manually handle the merging of each conflicted submodule.\n"
+"This can be accomplished with the following steps:\n"
+"%s - come back to superproject and run:\n"
+"\n"
+" git add %s\n"
+"\n"
+" to record the above merge or update\n"
+" - resolve any other conflicts in the superproject\n"
+" - commit the resulting index in the superproject\n"
msgstr ""
-"Lưu ý: %s không được cập nhật và theo cách lấy ra phiên bản xung đột; bản "
-"sao cũ được đổi tên thành %s"
+"Hoà trá»™n đệ quy vá»›i mô-Ä‘un con hiện chỉ há»— trợ các trÆ°á»ng hợp Ä‘Æ¡n giản.\n"
+"Vui lòng hoà trộn các mô-đun con có xung đột bằng tay.\n"
+"Bạn có thể thực hiện theo các bước sau:\n"
+"%s - trở vỠproject cha và chạy lệnh:\n"
+"\n"
+" git add %s\n"
+"\n"
+" để ghi lại hoà trộn hoặc cập nhật\n"
+" - giải quyết các xung đột trong project cha\n"
+" - chuyển giao kết quả trong project cha\n"
#. TRANSLATORS: The %s arguments are: 1) tree hash of a merge
#. base, and 2-3) the trees for the two trees we're merging.
@@ -16603,74 +17222,90 @@ msgstr "(commit sai)\n"
#, c-format
msgid "add_cacheinfo failed for path '%s'; merge aborting."
-msgstr "add_cacheinfo gặp lá»—i đối vá»›i Ä‘Æ°á»ng dẫn “%sâ€; việc hòa trá»™n bị bãi bá»."
+msgstr "add_cacheinfo gặp lá»—i đối vá»›i Ä‘Æ°á»ng dẫn '%s'; huá»· bá» việc hòa trá»™n."
#, c-format
msgid "add_cacheinfo failed to refresh for path '%s'; merge aborting."
msgstr ""
-"add_cacheinfo gặp lá»—i khi làm má»›i đối vá»›i Ä‘Æ°á»ng dẫn “%sâ€; việc hòa trá»™n bị "
-"bãi bá»."
+"add_cacheinfo gặp lá»—i khi làm má»›i đối vá»›i Ä‘Æ°á»ng dẫn '%s'; huá»· bá» việc hòa "
+"trá»™n."
#, c-format
msgid "failed to create path '%s'%s"
-msgstr "gặp lá»—i khi tạo Ä‘Æ°á»ng dẫn “%sâ€%s"
+msgstr "gặp lá»—i khi tạo Ä‘Æ°á»ng dẫn '%s'%s"
#, c-format
msgid "Removing %s to make room for subdirectory\n"
msgstr "Gỡ bỠ%s để tạo chỗ (room) cho thư mục con\n"
msgid ": perhaps a D/F conflict?"
-msgstr ": có lẽ là một xung đột D/F?"
+msgstr ": có lẽ là xung đột D/F (tập tin/thư mục)?"
#, c-format
msgid "refusing to lose untracked file at '%s'"
-msgstr "từ chối đóng tập tin không được theo dõi tại “%sâ€"
+msgstr "từ chối đóng tập tin không được theo dõi tại '%s'"
#, c-format
msgid "blob expected for %s '%s'"
-msgstr "mong đợi đối tượng blob cho %s “%sâ€"
+msgstr "mong đợi đối tượng blob cho %s '%s'"
#, c-format
msgid "failed to open '%s': %s"
-msgstr "gặp lá»—i khi mở “%sâ€: %s"
+msgstr "gặp lỗi khi mở '%s': %s"
#, c-format
msgid "failed to symlink '%s': %s"
-msgstr "gặp lá»—i khi tạo liên kết má»m (symlink) “%sâ€: %s"
+msgstr "gặp lá»—i khi tạo liên kết má»m (symlink) '%s': %s"
#, c-format
msgid "do not know what to do with %06o %s '%s'"
-msgstr "không hiểu phải làm gì vá»›i %06o %s “%sâ€"
+msgstr "không hiểu phải làm gì với %06o %s '%s'"
#, c-format
msgid "Fast-forwarding submodule %s to the following commit:"
-msgstr "Chuyển-tiếp-nhanh mô-đun-con “%s†đến lần chuyển giao sau đây:"
+msgstr "Chuyển-tiếp-nhanh mô-đun-con '%s' đến lần chuyển giao sau đây:"
#, c-format
msgid "Fast-forwarding submodule %s"
-msgstr "Chuyển-tiếp-nhanh mô-Ä‘un-con “%sâ€"
+msgstr "Chuyển-tiếp-nhanh mô-đun-con '%s'"
#, c-format
msgid "Failed to merge submodule %s (merge following commits not found)"
msgstr ""
-"Gặp lỗi khi hòa trộn mô-đun-con “%s†(không tìm thấy các lần chuyển giao "
+"Gặp lỗi khi hòa trộn mô-đun-con '%s' (không tìm thấy các lần chuyển giao "
"theo sau hòa trộn)"
#, c-format
msgid "Failed to merge submodule %s (not fast-forward)"
-msgstr "Gặp lỗi khi hòa trộn mô-đun-con “%s†(không chuyển tiếp nhanh được)"
+msgstr "Gặp lỗi khi hòa trộn mô-đun-con '%s' (không chuyển tiếp nhanh được)"
msgid "Found a possible merge resolution for the submodule:\n"
-msgstr "Tìm thấy một giải pháp hòa trộn có thể cho mô-đun-con:\n"
+msgstr "Tìm thấy một giải pháp hòa trộn khả thi cho mô-đun-con:\n"
+
+#, c-format
+msgid ""
+"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"
+msgstr ""
+"Nếu đây là đúng đơn giản thêm nó vào chỉ mục ví dụ\n"
+"bằng cách dùng:\n"
+"\n"
+" git update-index --cacheinfo 160000 %s \"%s\"\n"
+"\n"
+"cái mà sẽ chấp nhận gợi ý này.\n"
#, c-format
msgid "Failed to merge submodule %s (multiple merges found)"
-msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con “%s†(thấy nhiá»u hòa trá»™n Ä‘a trùng)"
+msgstr "Gặp lá»—i khi hòa trá»™n mô-Ä‘un-con '%s' (thấy nhiá»u hòa trá»™n Ä‘a trùng)"
#, c-format
msgid "Error: Refusing to lose untracked file at %s; writing to %s instead."
msgstr ""
-"Lá»—i: từ chối đóng tập tin không được theo dõi tại “%sâ€; thay vào đó ghi vào "
+"Lỗi: từ chối đóng tập tin không được theo dõi tại '%s'; thay vào đó ghi vào "
"%s."
#, c-format
@@ -16713,12 +17348,12 @@ msgstr "đã đổi tên"
#, c-format
msgid "Refusing to lose dirty file at %s"
-msgstr "Từ chối đóng tập tin không được theo dõi tại “%sâ€"
+msgstr "Từ chối đóng tập tin không được theo dõi tại '%s'"
#, c-format
msgid "Refusing to lose untracked file at %s, even though it's in the way."
msgstr ""
-"Từ chối đóng tập tin không được theo dõi tại “%sâ€, ngay cả khi nó ở trên "
+"Từ chối đóng tập tin không được theo dõi tại '%s', ngay cả khi nó ở trên "
"Ä‘Æ°á»ng."
#, c-format
@@ -16733,13 +17368,13 @@ msgstr "%s là một thư mục trong %s thay vào đó thêm vào như là %s"
#, c-format
msgid "Refusing to lose untracked file at %s; adding as %s instead"
msgstr ""
-"Từ chối đóng tập tin không được theo dõi tại “%sâ€; thay vào đó Ä‘ang thêm "
+"Từ chối đóng tập tin không được theo dõi tại '%s'; thay vào đó đang thêm "
"thành %s"
#, c-format
msgid ""
-"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s"
-"\"->\"%s\" in \"%s\"%s"
+"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename "
+"\"%s\"->\"%s\" in \"%s\"%s"
msgstr ""
"XUNG ÄỘT (đổi-tên/đổi-tên): Äổi tên \"%s\"->\"%s\" trong nhánh \"%s\" đổi "
"tên \"%s\"->\"%s\" trong \"%s\"%s"
@@ -16758,9 +17393,9 @@ msgid ""
"directory %s was renamed to multiple other directories, with no destination "
"getting a majority of the files."
msgstr ""
-"XUNG ÄỘT: (thÆ° mục đổi tên chia tách): Không rõ ràng để đặt địa Ä‘iểm %s bởi "
-"vì thÆ° mục %s đã bị đổi tên thành nhiá»u thÆ° mục khác, vá»›i không đích đến "
-"nhận má»™t phần nhiá»u của các tập tin."
+"XUNG ÄỘT: (phân hoá đổi tên thÆ° mục): Không rõ đặt %s ở đâu bởi vì thÆ° mục "
+"%s đã bị đổi tên thành nhiá»u thÆ° mục khác, mà không bên nào nhận phần lá»›n "
+"các tập tin gốc."
#, c-format
msgid ""
@@ -16825,75 +17460,33 @@ msgstr "hòa trộn không trả vỠlần chuyển giao nào"
#, c-format
msgid "Could not parse object '%s'"
-msgstr "Không thể phân tích đối tượng “%sâ€"
+msgstr "Không thể Ä‘á»c đối tượng '%s'"
msgid "failed to read the cache"
msgstr "gặp lá»—i khi Ä‘á»c bá»™ nhá»› đệm"
-msgid "multi-pack-index OID fanout is of the wrong size"
-msgstr "fanout OID nhiá»u gói chỉ mục có kích thÆ°á»›c sai"
-
-#, c-format
-msgid "multi-pack-index file %s is too small"
-msgstr "tập tin đồ thị multi-pack-index %s quá nhá»"
-
-#, c-format
-msgid "multi-pack-index signature 0x%08x does not match signature 0x%08x"
-msgstr "chữ ký multi-pack-index 0x%08x không khớp chữ ký 0x%08x"
-
-#, c-format
-msgid "multi-pack-index version %d not recognized"
-msgstr "không nhận ra phiên bản %d của multi-pack-index"
-
-#, c-format
-msgid "multi-pack-index hash version %u does not match version %u"
-msgstr "phiên bản băm multi-pack-index %u không khớp phiên bản %u"
-
-msgid "multi-pack-index missing required pack-name chunk"
-msgstr "multi-pack-index thiếu mảnh pack-name cần thiết"
-
-msgid "multi-pack-index missing required OID fanout chunk"
-msgstr "multi-pack-index thiếu mảnh OID fanout cần thiết"
-
-msgid "multi-pack-index missing required OID lookup chunk"
-msgstr "multi-pack-index thiếu mảnh OID lookup cần thiết"
-
-msgid "multi-pack-index missing required object offsets chunk"
-msgstr "multi-pack-index thiếu mảnh các khoảng bù đối tượng cần thiết"
-
-#, c-format
-msgid "multi-pack-index pack names out of order: '%s' before '%s'"
-msgstr "các tên gói multi-pack-index không đúng thứ tá»±: “%s†trÆ°á»›c “%sâ€"
-
-#, c-format
-msgid "bad pack-int-id: %u (%u total packs)"
-msgstr "pack-int-id sai: %u (%u các gói tổng)"
-
-msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
-msgstr "multi-pack-index lÆ°u trữ má»™t khoảng bù 64-bít, nhÆ°ng off_t là quá nhá»"
-
#, c-format
msgid "failed to add packfile '%s'"
-msgstr "gặp lá»—i khi thêm tập tin gói “%sâ€"
+msgstr "gặp lỗi khi thêm tập tin gói '%s'"
#, c-format
msgid "failed to open pack-index '%s'"
-msgstr "gặp lá»—i khi mở pack-index “%sâ€"
+msgstr "gặp lỗi khi mở pack-index '%s'"
#, c-format
msgid "failed to locate object %d in packfile"
-msgstr "gặp lỗi khi phân bổ đối tượng “%d†trong tập tin gói"
+msgstr "gặp lỗi khi phân bổ đối tượng '%d' trong tập tin gói"
msgid "cannot store reverse index file"
-msgstr "không thể lưu trữ tập tin ghi mục lục đảo ngược"
+msgstr "không thể lưu trữ tập tin ghi chỉ mục đảo ngược"
#, c-format
msgid "could not parse line: %s"
-msgstr "không thể phân tích cú pháp dòng: %s"
+msgstr "không hiểu cú pháp dòng: %s"
#, c-format
msgid "malformed line: %s"
-msgstr "dòng dị hình: %s"
+msgstr "dòng sai quy cách: %s"
msgid "ignoring existing multi-pack-index; checksum mismatch"
msgstr "bỠqua multi-pack-index sẵn có; tổng kiểm không khớp"
@@ -16903,7 +17496,7 @@ msgstr "không thể tải gói"
#, c-format
msgid "could not open index for %s"
-msgstr "không thể mở mục lục cho %s"
+msgstr "không thể mở chỉ mục cho %s"
msgid "Adding packfiles to multi-pack-index"
msgstr "Äang thêm tập tin gói từ multi-pack-index"
@@ -16918,30 +17511,109 @@ msgstr "không thể chá»n gói Æ°a dùng %s vá»›i không đối tượng nào"
#, c-format
msgid "did not see pack-file %s to drop"
-msgstr "đã không thấy tập tin gói %s để mà xóa"
+msgstr "đã không thấy tập tin gói %s để xóa"
#, c-format
msgid "preferred pack '%s' is expired"
-msgstr "\"preferred pack\" “%s†đã hết hạn"
+msgstr "\"preferred pack\" '%s' đã hết hạn"
msgid "no pack files to index."
-msgstr "không có tập tin gói để đánh mục lục."
+msgstr "không có tập tin gói để đánh chỉ mục."
msgid "refusing to write multi-pack .bitmap without any objects"
-msgstr "từ chối ghi “multi-pack bitmap†mà không có bất kỳ đối tượng nào"
+msgstr "từ chối ghi 'multi-pack bitmap' mà không có bất kỳ đối tượng nào"
msgid "could not write multi-pack bitmap"
-msgstr "không thể ghi “multi-pack bitmapâ€"
+msgstr "không thể ghi 'multi-pack bitmap'"
msgid "could not write multi-pack-index"
-msgstr "không thể ghi “multi-pack-indexâ€"
+msgstr "không thể ghi 'multi-pack-index'"
+
+msgid "Counting referenced objects"
+msgstr "Äang đếm các đối tượng được tham chiếu"
+
+msgid "Finding and deleting unreferenced packfiles"
+msgstr "Äang tìm và xóa các gói không được tham chiếu"
+
+msgid "could not start pack-objects"
+msgstr "không thể khởi chạy pack-objects"
+
+msgid "could not finish pack-objects"
+msgstr "không thể hoàn thiện pack-objects"
+
+msgid "multi-pack-index OID fanout is of the wrong size"
+msgstr "fanout OID multi-pack-index có kích thước sai"
+
+#, c-format
+msgid ""
+"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+msgstr "fanout cũ sai thứ tự: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
+
+msgid "multi-pack-index OID lookup chunk is the wrong size"
+msgstr "OID lookup chunk multi-pack-index có kích thước sai"
+
+msgid "multi-pack-index object offset chunk is the wrong size"
+msgstr "object offset chunk multi-pack-index có kích thước sai"
+
+#, c-format
+msgid "multi-pack-index file %s is too small"
+msgstr "tập tin đồ thị multi-pack-index %s quá nhá»"
+
+#, c-format
+msgid "multi-pack-index signature 0x%08x does not match signature 0x%08x"
+msgstr "chữ ký multi-pack-index 0x%08x không khớp chữ ký 0x%08x"
+
+#, c-format
+msgid "multi-pack-index version %d not recognized"
+msgstr "không nhận ra phiên bản %d của multi-pack-index"
+
+#, c-format
+msgid "multi-pack-index hash version %u does not match version %u"
+msgstr "phiên bản băm multi-pack-index %u không khớp phiên bản %u"
+
+msgid "multi-pack-index required pack-name chunk missing or corrupted"
+msgstr "multi-pack-index thiếu chunk pack-name cần thiết hoặc bị há»ng"
+
+msgid "multi-pack-index required OID fanout chunk missing or corrupted"
+msgstr "multi-pack-index thiếu chunk OID fanout cần thiết hoặc bị há»ng"
+
+msgid "multi-pack-index required OID lookup chunk missing or corrupted"
+msgstr "multi-pack-index thiếu chunk OID lookup cần thiết hoặc bị há»ng"
+
+msgid "multi-pack-index required object offsets chunk missing or corrupted"
+msgstr ""
+"multi-pack-index thiếu chunk các khoảng bù đối tượng cần thiết hoặc bị há»ng"
+
+msgid "multi-pack-index pack-name chunk is too short"
+msgstr "tập tin đồ thị multi-pack-index %s quá nhá»"
+
+#, c-format
+msgid "multi-pack-index pack names out of order: '%s' before '%s'"
+msgstr "các tên gói multi-pack-index không đúng thứ tự: '%s' trước '%s'"
+
+#, c-format
+msgid "bad pack-int-id: %u (%u total packs)"
+msgstr "pack-int-id sai: %u (%u các gói tổng)"
+
+msgid "MIDX does not contain the BTMP chunk"
+msgstr "MIDX không chứa chunk BTMP"
+
+#, c-format
+msgid "could not load bitmapped pack %<PRIu32>"
+msgstr "không thể Ä‘á»c gói bitmap %<PRIu32>"
+
+msgid "multi-pack-index stores a 64-bit offset, but off_t is too small"
+msgstr "multi-pack-index lÆ°u trữ má»™t offset 64-bít, nhÆ°ng off_t là quá nhá»"
+
+msgid "multi-pack-index large offset out of bounds"
+msgstr "multi-pack-index large offset nằm ngoài biên"
#, c-format
msgid "failed to clear multi-pack-index at %s"
msgstr "gặp lỗi khi xóa multi-pack-index tại %s"
msgid "multi-pack-index file exists, but failed to parse"
-msgstr "đã có tập tin multi-pack-index, nhưng gặp lỗi khi phân tích cú pháp"
+msgstr "đã có tập tin multi-pack-index, nhÆ°ng gặp lá»—i khi Ä‘á»c cú pháp"
msgid "incorrect checksum"
msgstr "tổng kiểm không đúng"
@@ -16949,11 +17621,6 @@ msgstr "tổng kiểm không đúng"
msgid "Looking for referenced packfiles"
msgstr "Äang khóa cho các gói bị tham chiếu"
-#, c-format
-msgid ""
-"oid fanout out of order: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-msgstr "fanout cũ sai thứ tự: fanout[%d] = %<PRIx32> > %<PRIx32> = fanout[%d]"
-
msgid "the midx contains no oid"
msgstr "midx chẳng chứa oid nào"
@@ -16983,18 +17650,6 @@ msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>"
msgstr ""
"khoảng bù đối tượng không đúng cho oid[%d] = %s: %<PRIx64> != %<PRIx64>"
-msgid "Counting referenced objects"
-msgstr "Äang đếm các đối tượng được tham chiếu"
-
-msgid "Finding and deleting unreferenced packfiles"
-msgstr "Äang tìm và xóa các gói không được tham chiếu"
-
-msgid "could not start pack-objects"
-msgstr "không thể lấy thông tin thống kê vỠcác đối tượng gói"
-
-msgid "could not finish pack-objects"
-msgstr "không thể hoàn thiện các đối tượng gói"
-
#, c-format
msgid "unable to create lazy_dir thread: %s"
msgstr "không thể tạo tuyến lazy_dir: %s"
@@ -17013,10 +17668,9 @@ msgid ""
"Please, use 'git notes merge --commit' or 'git notes merge --abort' to "
"commit/abort the previous merge before you start a new notes merge."
msgstr ""
-"Bạn đã chưa hoàn tất hòa trộn ghi chú trước đây (%s vẫn còn).\n"
-"Vui lòng dùng “git notes merge --commit†hay “git notes merge --abort†để "
-"chuyển giao hay bãi bỠlần hòa trộn trước đây và bắt đầu một hòa trộn ghi "
-"chú mới."
+"Bạn chưa hoàn tất lần hòa trộn ghi chú trước (%s vẫn còn).\n"
+"Vui lòng dùng 'git notes merge --commit' hay 'git notes merge --abort' để "
+"chuyển giao hay huỷ bỠlần hòa trộn trước và bắt đầu hòa trộn ghi chú mới."
#, c-format
msgid "You have not concluded your notes merge (%s exists)."
@@ -17029,7 +17683,7 @@ msgstr ""
#, c-format
msgid "Bad notes.rewriteMode value: '%s'"
-msgstr "Giá trị notes.rewriteMode sai: “%sâ€"
+msgstr "Giá trị notes.rewriteMode sai: '%s'"
#, c-format
msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
@@ -17041,7 +17695,26 @@ msgstr "Từ chối ghi đè ghi chú trong %s (nằm ngoài refs/notes/)"
#.
#, c-format
msgid "Bad %s value: '%s'"
-msgstr "Giá trị %s sai: “%sâ€"
+msgstr "Giá trị %s sai: '%s'"
+
+msgid "failed to decode tree entry"
+msgstr "giải mã mục cây thất bại"
+
+#, c-format
+msgid "failed to map tree entry for %s"
+msgstr "ánh xạ mục cây cho %s thất bại"
+
+#, c-format
+msgid "bad %s in commit"
+msgstr "ký tự không đúng %s trong lần chuyển giao"
+
+#, c-format
+msgid "unable to map %s %s in commit object"
+msgstr "không thể ánh xạ %s %s trong đối tượng chuyển giao"
+
+#, c-format
+msgid "Failed to convert object from %s to %s"
+msgstr "Chuyển đổi đối tượng từ %s sang %s thất bại"
#, c-format
msgid "object directory %s does not exist; check .git/objects/info/alternates"
@@ -17050,16 +17723,12 @@ msgstr ""
#, c-format
msgid "unable to normalize alternate object path: %s"
-msgstr "không thể thÆ°á»ng hóa Ä‘Æ°á»ng dẫn đối tượng thay thế: “%sâ€"
+msgstr "không thể thÆ°á»ng hóa Ä‘Æ°á»ng dẫn đối tượng thay thế: '%s'"
#, c-format
msgid "%s: ignoring alternate object stores, nesting too deep"
msgstr "%s: đang bỠqua kho đối tượng thay thế, lồng nhau quá sâu"
-#, c-format
-msgid "unable to normalize object directory: %s"
-msgstr "không thể chuẩn hóa thÆ° mục đối tượng: “%sâ€"
-
msgid "unable to fdopen alternates lockfile"
msgstr "không thể fdopen tập tin khóa thay thế"
@@ -17071,31 +17740,31 @@ msgstr "không thể di chuyển tập tin thay thế vào chỗ"
#, c-format
msgid "path '%s' does not exist"
-msgstr "Ä‘Æ°á»ng dẫn “%s†không tồn tại"
+msgstr "Ä‘Æ°á»ng dẫn '%s' không tồn tại"
#, c-format
msgid "reference repository '%s' as a linked checkout is not supported yet."
-msgstr "kho tham chiếu “%s†như là lấy ra liên kết vẫn chưa được hỗ trợ."
+msgstr "kho tham chiếu '%s' như là checkout liên kết vẫn chưa được hỗ trợ."
#, c-format
msgid "reference repository '%s' is not a local repository."
-msgstr "kho tham chiếu “%s†không phải là một kho nội bộ."
+msgstr "kho tham chiếu '%s' không phải là một kho nội bộ."
#, c-format
msgid "reference repository '%s' is shallow"
-msgstr "kho tham chiếu “%s†là nông"
+msgstr "kho tham chiếu '%s' là nông"
#, c-format
msgid "reference repository '%s' is grafted"
-msgstr "kho tham chiếu “%s†bị cấy ghép"
+msgstr "kho tham chiếu '%s' bị cấy ghép"
#, c-format
msgid "could not find object directory matching %s"
-msgstr "không thể tìm thấy thÆ° mục đối tượng khá»›p vá»›i “%sâ€"
+msgstr "không thể tìm thấy thư mục đối tượng khớp với '%s'"
#, c-format
msgid "invalid line while parsing alternate refs: %s"
-msgstr "dòng không hợp lệ trong khi phân tích các tham chiếu thay thế: %s"
+msgstr "dòng không hợp lệ trong khi Ä‘á»c các tham chiếu thay thế: %s"
#, c-format
msgid "attempting to mmap %<PRIuMAX> over limit %<PRIuMAX>"
@@ -17111,15 +17780,19 @@ msgstr "tập tin đối tượng %s trống rỗng"
#, c-format
msgid "corrupt loose object '%s'"
-msgstr "đối tượng mất há»ng “%sâ€"
+msgstr "đối tượng mất há»ng '%s'"
#, c-format
msgid "garbage at end of loose object '%s'"
-msgstr "gặp rác tại cuối của đối tượng bị mất “%sâ€"
+msgstr "gặp rác tại cuối của đối tượng bị mất '%s'"
+
+#, c-format
+msgid "unable to open loose object %s"
+msgstr "không thể mở đối tượng mất %s"
#, c-format
msgid "unable to parse %s header"
-msgstr "không thể phân tích phần đầu của “%sâ€"
+msgstr "không thể Ä‘á»c phần đầu của '%s'"
msgid "invalid object type"
msgstr "kiểu đối tượng không hợp lệ"
@@ -17133,31 +17806,28 @@ msgid "header for %s too long, exceeds %d bytes"
msgstr "phần đầu cho %s quá dài, vượt quá %d byte"
#, c-format
-msgid "failed to read object %s"
-msgstr "gặp lá»—i khi Ä‘á»c đối tượng “%sâ€"
+msgid "loose object %s (stored in %s) is corrupt"
+msgstr "đối tượng mất %s (được lÆ°u trong %s) bị há»ng"
#, c-format
msgid "replacement %s not found for %s"
msgstr "c%s thay thế không được tìm thấy cho %s"
#, c-format
-msgid "loose object %s (stored in %s) is corrupt"
-msgstr "đối tượng mất %s (được lÆ°u trong %s) bị há»ng"
-
-#, c-format
msgid "packed object %s (stored in %s) is corrupt"
msgstr "đối tượng đã đóng gói %s (được lÆ°u trong %s) bị há»ng"
#, c-format
+msgid "missing mapping of %s to %s"
+msgstr "thiếu ánh xạ %s sang %s"
+
+#, c-format
msgid "unable to write file %s"
msgstr "không thể ghi tập tin %s"
#, c-format
msgid "unable to set permission to '%s'"
-msgstr "không thể đặt quyá»n thành “%sâ€"
-
-msgid "file write error"
-msgstr "lỗi ghi tập tin"
+msgstr "không thể đặt quyá»n thành '%s'"
msgid "error when closing loose object file"
msgstr "gặp lỗi trong khi đóng tập tin đối tượng"
@@ -17175,7 +17845,7 @@ msgstr "không thể ghi tập tin đối tượng đã mất"
#, c-format
msgid "unable to deflate new object %s (%d)"
-msgstr "không thể xả nén đối tượng mới %s (%d)"
+msgstr "không thể giải nén đối tượng mới %s (%d)"
#, c-format
msgid "deflateEnd on object %s failed (%d)"
@@ -17186,22 +17856,43 @@ msgid "confused by unstable object source data for %s"
msgstr "chưa rõ ràng baowir dữ liệu nguồn đối tượng không ổn định cho %s"
#, c-format
+msgid "write stream object %ld != %<PRIuMAX>"
+msgstr "đối tượng ghi dòng %ld != %<PRIuMAX>"
+
+#, c-format
+msgid "unable to stream deflate new object (%d)"
+msgstr "không thể stream deflate đối tượng mới (%d)"
+
+#, c-format
+msgid "deflateEnd on stream object failed (%d)"
+msgstr "deflateEnd trên đối tượng stream gặp lỗi (%d)"
+
+#, c-format
+msgid "unable to create directory %s"
+msgstr "tạo thư mục \"%s\" gặp lỗi"
+
+#, c-format
msgid "cannot read object for %s"
msgstr "không thể Ä‘á»c đối tượng cho %s"
-msgid "corrupt commit"
-msgstr "lần chuyển giao sai há»ng"
+#, c-format
+msgid "cannot map object %s to %s"
+msgstr "không thể ánh xạ đối tượng %s sang %s"
+
+#, c-format
+msgid "object fails fsck: %s"
+msgstr "đối tượng không qua fsck (kiểm tra toàn vẹn): %s"
-msgid "corrupt tag"
-msgstr "thẻ sai há»ng"
+msgid "refusing to create malformed object"
+msgstr "Từ chối tạo đối tượng lỗi"
#, c-format
msgid "read error while indexing %s"
-msgstr "gặp lá»—i Ä‘á»c khi đánh mục lục %s"
+msgstr "gặp lá»—i Ä‘á»c khi đánh chỉ mục %s"
#, c-format
msgid "short read while indexing %s"
-msgstr "không Ä‘á»c ngắn khi đánh mục lục %s"
+msgstr "không Ä‘á»c ngắn khi đánh chỉ mục %s"
#, c-format
msgid "%s: failed to insert into database"
@@ -17213,7 +17904,7 @@ msgstr "%s: kiểu tập tin không được hỗ trợ"
#, c-format
msgid "%s is not a valid '%s' object"
-msgstr "%s không phải là một đối tượng “%s†hợp lệ"
+msgstr "%s không phải là một đối tượng '%s' hợp lệ"
#, c-format
msgid "unable to open %s"
@@ -17229,15 +17920,15 @@ msgstr "không thể mmap %s"
#, c-format
msgid "unable to unpack header of %s"
-msgstr "không thể giải gói phần đầu của “%sâ€"
+msgstr "không thể giải gói phần đầu của '%s'"
#, c-format
msgid "unable to parse header of %s"
-msgstr "không thể phân tích phần đầu của “%sâ€"
+msgstr "không thể Ä‘á»c phần đầu của '%s'"
#, c-format
msgid "unable to unpack contents of %s"
-msgstr "không thể giải gói ná»™i dung của “%sâ€"
+msgstr "không thể giải gói nội dung của '%s'"
#. TRANSLATORS: This is a line of ambiguous object
#. output shown when we cannot look up or parse the
@@ -17279,7 +17970,7 @@ msgstr "%s thẻ %s - %s"
#.
#, c-format
msgid "%s [bad tag, could not parse it]"
-msgstr "%s [thẻ sai, không thể phân tích cú pháp nó]"
+msgstr "%s [thẻ sai, không hiểu cú pháp nó]"
#. TRANSLATORS: This is a line of ambiguous <type>
#. object output. E.g. "deadbeef tree".
@@ -17322,65 +18013,64 @@ msgid ""
"examine these refs and maybe delete them. Turn this message off by\n"
"running \"git config advice.objectNameWarning false\""
msgstr ""
-"Git thÆ°á»ng không bao giá» tạo tham chiếu mà nó kết thúc vá»›i 40 ký tá»± hex\n"
-"bởi vì nó sẽ bị bỠqua khi bạn chỉ định 40-hex. Những tham chiếu này\n"
-"có lẽ được tạo ra bởi một sai sót nào đó. Ví dụ,\n"
+"Git thÆ°á»ng không bao giá» tạo tham chiếu kết thúc vá»›i 40 ký tá»± hex\n"
+"bởi vì nó sẽ bị bỠqua khi bạn chỉ định 40 ký tự hex. Những tham chiếu\n"
+"này có lẽ đã được tạo nhầm. Ví dụ,\n"
"\n"
-" git switch -c $br $(git rev-parse …)\n"
+" git switch -c $br $(git rev-parse ...)\n"
"\n"
-"với \"$br\" không hiểu lý do vì sao trống rỗng và một tham chiếu 40-hex được "
-"tạo ra.\n"
-"Xin hãy kiểm tra những tham chiếu này và có thể xóa chúng Ä‘i. Tắt lá»i nhắn "
-"này\n"
-"bằng cách chạy lệnh \"git config advice.objectNameWarning false\""
+"với \"$br\" không hiểu lý do vì sao rỗng và tạo ra tham chiếu 40-hex.\n"
+" Xin hãy kiểm tra những tham chiếu này và xóa chúng đi nếu cần. Tắt\n"
+"lá»i nhắn này bằng cách chạy lệnh \"git config advice.objectNameWarning "
+"false\""
#, c-format
msgid "log for '%.*s' only goes back to %s"
-msgstr "nhật ký cho “%.*s†chỉ trở lại đến %s"
+msgstr "nhật ký cho '%.*s' chỉ kéo dài đến %s"
#, c-format
msgid "log for '%.*s' only has %d entries"
-msgstr "nhật ký cho “%.*s†chỉ có %d mục"
+msgstr "nhật ký cho '%.*s' chỉ có %d mục"
#, c-format
msgid "path '%s' exists on disk, but not in '%.*s'"
-msgstr "Ä‘Æ°á»ng dẫn “%s†có ở trên Ä‘Ä©a, nhÆ°ng không trong “%.*sâ€"
+msgstr "Ä‘Æ°á»ng dẫn '%s' có ở trên Ä‘Ä©a, nhÆ°ng không trong '%.*s'"
#, c-format
msgid ""
"path '%s' exists, but not '%s'\n"
"hint: Did you mean '%.*s:%s' aka '%.*s:./%s'?"
msgstr ""
-"Ä‘Æ°á»ng dẫn “%s†tồn tại, nhÆ°ng không phải “%sâ€\n"
-"gợi ý: Có phải ý bạn là “%.*s:%s†aka “%.*s:./%s�"
+"Ä‘Æ°á»ng dẫn '%s' tồn tại, nhÆ°ng không phải '%s'\n"
+"gợi ý: Có phải ý bạn là '%.*s:%s' aka '%.*s:./%s'?"
#, c-format
msgid "path '%s' does not exist in '%.*s'"
-msgstr "Ä‘Æ°á»ng dẫn “%s†không tồn tại trong “%.*sâ€"
+msgstr "Ä‘Æ°á»ng dẫn '%s' không tồn tại trong '%.*s'"
#, c-format
msgid ""
"path '%s' is in the index, but not at stage %d\n"
"hint: Did you mean ':%d:%s'?"
msgstr ""
-"Ä‘Æ°á»ng dẫn “%s†nằm trong chỉ mục, nhÆ°ng không phải ở giai Ä‘oạn %d\n"
-"gợi ý: Có phải ý bạn là “:%d:%s�"
+"Ä‘Æ°á»ng dẫn '%s' nằm trong chỉ mục, nhÆ°ng không phải ở giai Ä‘oạn %d\n"
+"gợi ý: Có phải ý bạn là ':%d:%s'?"
#, c-format
msgid ""
"path '%s' is in the index, but not '%s'\n"
"hint: Did you mean ':%d:%s' aka ':%d:./%s'?"
msgstr ""
-"Ä‘Æ°á»ng dẫn “%s†nằm trong chỉ mục, nhÆ°ng không phải “%sâ€\n"
-"gợi ý: Có phải ý bạn là “:% d:%s “ aka “:%d:./%s�"
+"Ä‘Æ°á»ng dẫn '%s' nằm trong chỉ mục, nhÆ°ng không phải '%s'\n"
+"gợi ý: Có phải ý bạn là ':% d:%s ' aka ':%d:./%s'?"
#, c-format
msgid "path '%s' exists on disk, but not in the index"
-msgstr "Ä‘Æ°á»ng dẫn “%s†tồn tại trên Ä‘Ä©a, nhÆ°ng không có trong chỉ mục"
+msgstr "Ä‘Æ°á»ng dẫn '%s' tồn tại trên Ä‘Ä©a, nhÆ°ng không có trong chỉ mục"
#, c-format
msgid "path '%s' does not exist (neither on disk nor in the index)"
-msgstr "Ä‘Æ°á»ng dẫn “%s†không tồn tại (không trên Ä‘Ä©a cÅ©ng không trong mục lục)"
+msgstr "Ä‘Æ°á»ng dẫn '%s' không tồn tại (không trên Ä‘Ä©a cÅ©ng không trong chỉ mục)"
msgid "relative path syntax can't be used outside working tree"
msgstr "cú pháp Ä‘Æ°á»ng dẫn tÆ°Æ¡ng đối không thể thể dùng ngoài cây làm việc"
@@ -17391,7 +18081,7 @@ msgstr "<object>:<path> cần cả hai, nhưng chỉ <object> '%s' được đư
#, c-format
msgid "invalid object name '%.*s'."
-msgstr "“%.*s†không phải là tên đối tượng hợp lệ."
+msgstr "'%.*s' không phải là tên đối tượng hợp lệ."
#, c-format
msgid "invalid object type \"%s\""
@@ -17407,26 +18097,134 @@ msgstr "đối tượng %s có mã kiểu %d chưa biết"
#, c-format
msgid "unable to parse object: %s"
-msgstr "không thể phân tích đối tượng: “%sâ€"
+msgstr "không thể Ä‘á»c đối tượng: '%s'"
#, c-format
msgid "hash mismatch %s"
msgstr "mã băm không khớp %s"
+msgid "trying to write commit not in index"
+msgstr "đã thử ghi lần chuyển giao nằm ngoài chỉ mục"
+
+msgid "failed to load bitmap index (corrupted?)"
+msgstr "không thể Ä‘á»c chỉ mục bitmap (bị há»ng?)"
+
+msgid "corrupted bitmap index (too small)"
+msgstr "chỉ mục bitmap bị há»ng (quá nhá»)"
+
+msgid "corrupted bitmap index file (wrong header)"
+msgstr "tập tin chỉ mục bitmap bị há»ng (sai phần đầu)"
+
+#, c-format
+msgid "unsupported version '%d' for bitmap index file"
+msgstr "không hỗ trợ tập tin chỉ mục bitmap phiên bản '%d'"
+
+msgid "corrupted bitmap index file (too short to fit hash cache)"
+msgstr "tập tin chỉ mục bitmap bị há»ng (quá ngắn để chứa bá»™ đệm mã băm)"
+
+msgid "corrupted bitmap index file (too short to fit lookup table)"
+msgstr "tập tin chỉ mục bitmap bị há»ng (quá ngắn để chứa bảng tìm kiếm)"
+
+#, c-format
+msgid "duplicate entry in bitmap index: '%s'"
+msgstr "đối tượng trùng lặp trong bitmap: '%s'"
+
+#, c-format
+msgid "corrupt ewah bitmap: truncated header for entry %d"
+msgstr "ewah bitmap bị há»ng: phần đầu bị cắt ngắn cho mục thứ %d"
+
+#, c-format
+msgid "corrupt ewah bitmap: commit index %u out of range"
+msgstr "ewah bitmap bị há»ng: mục chuyển giao thứ %u nằm ngoài phạm vi"
+
+msgid "corrupted bitmap pack index"
+msgstr "chỉ mục gói bitmap bị há»ng"
+
+msgid "invalid XOR offset in bitmap pack index"
+msgstr "XOR offset không hợp lệ trong chỉ mục gói bitmap"
+
+msgid "cannot fstat bitmap file"
+msgstr "không thể fstat file bitmap"
+
+msgid "checksum doesn't match in MIDX and bitmap"
+msgstr "tổng kiểm ra trong MIDX và bitmap không khớp"
+
msgid "multi-pack bitmap is missing required reverse index"
-msgstr "ánh xạ multi-pack thiếu mục lục để dành cần thiết"
+msgstr "bitmap multi-pack thiếu chỉ mục để dành cần thiết"
#, c-format
msgid "could not open pack %s"
-msgstr "không thể mở gói “%sâ€"
+msgstr "không thể mở gói '%s'"
+
+msgid "could not determine MIDX preferred pack"
+msgstr "không thể xác định gói MIDX ưa dùng"
#, c-format
msgid "preferred pack (%s) is invalid"
-msgstr "\"preferred pack\" (%s) không hợp lệ"
+msgstr "preferred pack (%s) không hợp lệ"
+
+msgid "corrupt bitmap lookup table: triplet position out of index"
+msgstr "bảng tìm kiếm bitmap bị há»ng: vị trí bá»™ ba nằm ngoài chỉ mục"
+
+msgid "corrupt bitmap lookup table: xor chain exceeds entry count"
+msgstr "bảng tìm kiếm bitmap bị há»ng: chuá»—i xor vượt quá số lượng mục"
#, c-format
-msgid "could not find %s in pack %s at offset %<PRIuMAX>"
-msgstr "không thể tìm thấy %s trong gói “%s†tại vị trí %<PRIuMAX>"
+msgid "corrupt bitmap lookup table: commit index %u out of range"
+msgstr "bảng tìm kiếm bitmap bị há»ng: mục chuyển giao thứ %u nằm ngoài phạm vi"
+
+#, c-format
+msgid "corrupt ewah bitmap: truncated header for bitmap of commit \"%s\""
+msgstr ""
+"ewah bitmap bị há»ng: bitmap lần chuyển giao \"%s\" có phần đầu bị cắt ngắn"
+
+#, c-format
+msgid "unable to load pack: '%s', disabling pack-reuse"
+msgstr "không thể Ä‘á»c gói: '%s', vô hiệu sá»­ dụng lại gói"
+
+msgid "unable to compute preferred pack, disabling pack-reuse"
+msgstr "không thể tính giá trị gói ưa dùng, vô hiệu sử dụng lại gói"
+
+#, c-format
+msgid "object '%s' not found in type bitmaps"
+msgstr "không tìm thấy đối tượng '%s' trong type bitmap"
+
+#, c-format
+msgid "object '%s' does not have a unique type"
+msgstr "đối tượng '%s' không có kiểu độc nhất"
+
+#, c-format
+msgid "object '%s': real type '%s', expected: '%s'"
+msgstr "đối tượng '%s': kiểu '%s', cần: '%s'"
+
+#, c-format
+msgid "object not in bitmap: '%s'"
+msgstr "không tìm thấy đối tượng trong bitmap: %s"
+
+msgid "failed to load bitmap indexes"
+msgstr "Ä‘á»c chỉ mục bitmap thất bại"
+
+msgid "you must specify exactly one commit to test"
+msgstr "bạn phải chỉ định các lần chuyển giao muốn kiểm tra"
+
+#, c-format
+msgid "commit '%s' doesn't have an indexed bitmap"
+msgstr "lần chuyển giao '%s' không có chỉ mục bitmap"
+
+msgid "mismatch in bitmap results"
+msgstr "kết quả bitmap không khớp"
+
+#, c-format
+msgid "could not find '%s' in pack '%s' at offset %<PRIuMAX>"
+msgstr "không thể tìm thấy '%s' trong gói '%s' tại vị trí %<PRIuMAX>"
+
+#, c-format
+msgid "unable to get disk usage of '%s'"
+msgstr "không thể lấy dung lượng đĩa đã dùng của %s"
+
+#, c-format
+msgid "bitmap file '%s' has invalid checksum"
+msgstr "file bitmap '%s' có checksum không hợp lệ"
#, c-format
msgid "mtimes file %s is too small"
@@ -17438,7 +18236,7 @@ msgstr "tập tin mtimes %s có chữ ký chưa biết"
#, c-format
msgid "mtimes file %s has unsupported version %<PRIu32>"
-msgstr "tệp mtimes %s có phiên bản không được hỗ trợ %<PRIu32>"
+msgstr "tập mtimes %s có phiên bản không được hỗ trợ %<PRIu32>"
#, c-format
msgid "mtimes file %s has unsupported hash id %<PRIu32>"
@@ -17462,18 +18260,31 @@ msgstr "tập tin reverse-index %s có chữ ký chưa biết"
#, c-format
msgid "reverse-index file %s has unsupported version %<PRIu32>"
-msgstr "tệp chỉ mục ngược %s có phiên bản không được hỗ trợ %<PRIu32>"
+msgstr "tập chỉ mục ngược %s có phiên bản không được hỗ trợ %<PRIu32>"
#, c-format
msgid "reverse-index file %s has unsupported hash id %<PRIu32>"
-msgstr "tệp chỉ mục ngược %s có id mã băm không được hỗ trợ %<PRIu32>"
+msgstr "tập chỉ mục ngược %s có id mã băm không được hỗ trợ %<PRIu32>"
+
+msgid "invalid checksum"
+msgstr "checksum không hợp lệ"
+
+#, c-format
+msgid "invalid rev-index position at %<PRIu64>: %<PRIu32> != %<PRIu32>"
+msgstr "vị trí mục xét duyệt không hợp lệ %<PRIu64>: %<PRIu32> != %<PRIu32>"
+
+msgid "multi-pack-index reverse-index chunk is the wrong size"
+msgstr "chunk chỉ mục ngược của chỉ mục đa gói có kích thước sai"
+
+msgid "could not determine preferred pack"
+msgstr "không thể xác định gói ưa dùng"
msgid "cannot both write and verify reverse index"
-msgstr "không thể cùng lúc Ä‘á»c và xác minh được bảng mục lục đảo ngược"
+msgstr "không thể cùng lúc gh và xác minh chỉ mục ngược"
#, c-format
msgid "could not stat: %s"
-msgstr "không thể lấy thông tin thống kê: %s"
+msgstr "không thể stat: %s"
#, c-format
msgid "failed to make %s readable"
@@ -17481,7 +18292,7 @@ msgstr "gặp lá»—i làm cho %s Ä‘á»c được"
#, c-format
msgid "could not write '%s' promisor file"
-msgstr "không thể ghi tập tin promisor “%sâ€"
+msgstr "không thể ghi tập tin promisor '%s'"
msgid "offset before end of packfile (broken .idx?)"
msgstr "vị trí tÆ°Æ¡ng đối trÆ°á»›c Ä‘iểm kết thúc của tập tin gói (.idx há»ng à?)"
@@ -17492,44 +18303,36 @@ msgstr "tập tin gói %s không thể được ánh xạ %s"
#, c-format
msgid "offset before start of pack index for %s (corrupt index?)"
-msgstr "vị trí tÆ°Æ¡ng đối nằm trÆ°á»›c chỉ mục gói cho %s (mục lục bị há»ng à?)"
+msgstr "vị trí tÆ°Æ¡ng đối nằm trÆ°á»›c chỉ mục gói cho %s (chỉ mục bị há»ng à?)"
#, c-format
msgid "offset beyond end of pack index for %s (truncated index?)"
msgstr ""
-"vị trí tương đối vượt quá cuối của chỉ mục gói cho %s (mục lục bị cắt cụt à?)"
+"vị trí tương đối vượt quá cuối của chỉ mục gói cho %s (chỉ mục bị cắt cụt à?)"
#, c-format
msgid "malformed expiration date '%s'"
-msgstr "ngày tháng hết hạn dị hình “%sâ€"
+msgstr "ngày tháng hết hạn sai quy cách '%s'"
#, c-format
msgid "option `%s' expects \"always\", \"auto\", or \"never\""
-msgstr "tùy chá»n “%s†cần \"always\", \"auto\", hoặc \"never\""
+msgstr "tùy chá»n '%s' cần \"always\", \"auto\", hoặc \"never\""
#, c-format
msgid "malformed object name '%s'"
-msgstr "tên đối tượng dị hình “%sâ€"
+msgstr "tên đối tượng sai quy cách '%s'"
#, c-format
msgid "option `%s' expects \"%s\" or \"%s\""
-msgstr "tùy chá»n “%s†cần \"%s\" hoặc \"%s\""
+msgstr "tùy chá»n '%s' cần \"%s\" hoặc \"%s\""
#, c-format
msgid "%s requires a value"
-msgstr "“%s†yêu cầu một giá trị"
-
-#, c-format
-msgid "%s is incompatible with %s"
-msgstr "%s là xung khắc với %s"
-
-#, c-format
-msgid "%s : incompatible with something else"
-msgstr "%s : xung khắc với các cái khác"
+msgstr "'%s' yêu cầu một giá trị"
#, c-format
msgid "%s takes no value"
-msgstr "%s k nhận giá trị"
+msgstr "%s không nhận giá trị"
#, c-format
msgid "%s isn't available"
@@ -17545,26 +18348,29 @@ msgstr "tùy chá»n chÆ°a rõ rang: %s (nên là --%s%s hay --%s%s)"
#, c-format
msgid "did you mean `--%s` (with two dashes)?"
-msgstr "có phải ý bạn là “--%s“ (với hai dấu gạch ngang)?"
+msgstr "có phải ý bạn là '--%s' (với hai dấu gạch ngang)?"
#, c-format
msgid "alias of --%s"
msgstr "bí danh của --%s"
+msgid "need a subcommand"
+msgstr "cần câu lệnh con"
+
#, c-format
msgid "unknown option `%s'"
-msgstr "không hiểu tùy chá»n “%sâ€"
+msgstr "không hiểu tùy chá»n '%s'"
#, c-format
msgid "unknown switch `%c'"
-msgstr "không hiểu tùy chá»n “%câ€"
+msgstr "không hiểu tùy chá»n '%c'"
#, c-format
msgid "unknown non-ascii option in string: `%s'"
-msgstr "không hiểu tùy chá»n non-ascii trong chuá»—i: “%sâ€"
+msgstr "không hiểu tùy chá»n non-ascii trong chuá»—i: '%s'"
msgid "..."
-msgstr "…"
+msgstr "..."
#, c-format
msgid "usage: %s"
@@ -17607,6 +18413,10 @@ msgstr " %s"
msgid "-NUM"
msgstr "-Sá»"
+#, c-format
+msgid "opposite of --no-%s"
+msgstr "ngược lại với --no-%s"
+
msgid "expiry-date"
msgstr "ngày hết hạn"
@@ -17622,8 +18432,11 @@ msgstr "im lặng hơn nữa"
msgid "use <n> digits to display object names"
msgstr "sử dụng <n> chữ số để hiển thị tên đối tượng"
+msgid "prefixed path to initial superproject"
+msgstr "Ä‘Æ°á»ng dẫn tiá»n tố đến project cha ban đầu"
+
msgid "how to strip spaces and #comments from message"
-msgstr "làm thế nào để cắt bỠkhoảng trắng và #ghichú từ mẩu tin nhắn"
+msgstr "làm thế nào để cắt bỠkhoảng trắng và #ghi-chú từ tin nhắn"
msgid "read pathspec from file"
msgstr "Ä‘á»c đặc tả Ä‘Æ°á»ng dẫn từ tập tin"
@@ -17635,15 +18448,23 @@ msgstr ""
"tá»± NULL"
#, c-format
+msgid "bad boolean environment value '%s' for '%s'"
+msgstr "sai giá trị kiểu boolean của cấu hình '%s' cho '%s'"
+
+#, c-format
+msgid "failed to parse %s"
+msgstr "gặp lá»—i khi Ä‘á»c cú pháp %s"
+
+#, c-format
msgid "Could not make %s writable by group"
msgstr "Không thể làm %s được ghi bởi nhóm"
msgid "Escape character '\\' not allowed as last character in attr value"
msgstr ""
-"Ký tự thoát chuỗi “\\†không được phép là ký tự cuối trong giá trị thuộc tính"
+"Ký tự thoát chuỗi '\\' không được phép là ký tự cuối trong giá trị thuộc tính"
msgid "Only one 'attr:' specification is allowed."
-msgstr "Chỉ có một đặc tả “attr:†là được phép."
+msgstr "Chỉ có một đặc tả 'attr:' là được phép."
msgid "attr spec must not be empty"
msgstr "đặc tả attr phải không được để trống"
@@ -17653,42 +18474,45 @@ msgid "invalid attribute name %s"
msgstr "tên thuộc tính không hợp lệ %s"
msgid "global 'glob' and 'noglob' pathspec settings are incompatible"
-msgstr ""
-"các cài đặt đặc tả Ä‘Æ°á»ng dẫn “glob†và “noglob†toàn cục là xung khắc nhau"
+msgstr "các cài đặt đặc tả Ä‘Æ°á»ng dẫn 'glob' và 'noglob' toàn cục là xung khắc"
msgid ""
"global 'literal' pathspec setting is incompatible with all other global "
"pathspec settings"
msgstr ""
-"cài đặt đặc tả Ä‘Æ°á»ng dẫn “literal†toàn cục là xung khắc vá»›i các cài đặt đặc "
-"tả Ä‘Æ°á»ng dẫn toàn cục khác"
+"cài đặt đặc tả Ä‘Æ°á»ng dẫn 'literal' toàn cục không tÆ°Æ¡ng thích vá»›i các cài "
+"đặt đặc tả Ä‘Æ°á»ng dẫn toàn cục khác"
msgid "invalid parameter for pathspec magic 'prefix'"
-msgstr "tham số không hợp lệ cho “tiá»n tố†màu nhiệm đặc tả Ä‘Æ°á»ng đẫn"
+msgstr "tham số không hợp lệ cho đặc tả Ä‘Æ°á»ng đẫn đặc biệt 'prefix'"
#, c-format
msgid "Invalid pathspec magic '%.*s' in '%s'"
-msgstr "Số màu nhiệm đặc tả Ä‘Æ°á»ng dẫn không hợp lệ “%.*s†trong “%sâ€"
+msgstr "Äặc tả Ä‘Æ°á»ng dẫn không hợp lệ '%.*s' trong '%s'"
#, c-format
msgid "Missing ')' at the end of pathspec magic in '%s'"
-msgstr "Thiếu “)†tại cuối của số màu nhiệm đặc tả Ä‘Æ°á»ng dẫn trong “%sâ€"
+msgstr "Thiếu ')' tại cuối của đặc tả Ä‘Æ°á»ng dẫn trong '%s'"
#, c-format
msgid "Unimplemented pathspec magic '%c' in '%s'"
-msgstr "ChÆ°a viết mã cho số màu nhiệm đặc tả Ä‘Æ°á»ng dẫn “%c†trong “%sâ€"
+msgstr "ChÆ°a há»— trợ đặc tả Ä‘Æ°á»ng dẫn '%c' trong '%s'"
#, c-format
msgid "%s: 'literal' and 'glob' are incompatible"
-msgstr "%s: “literal†và “glob†xung khắc nhau"
+msgstr "%s: 'literal' và 'glob' xung khắc"
+
+#, c-format
+msgid "'%s' is outside the directory tree"
+msgstr "'%s' nằm ngoài cây thư mục"
#, c-format
msgid "%s: '%s' is outside repository at '%s'"
-msgstr "%s: “%s†ngoài má»™t kho chứa tại “%sâ€"
+msgstr "%s: '%s' nằm ngoài một kho chứa tại '%s'"
#, c-format
msgid "'%s' (mnemonic: '%c')"
-msgstr "“%s†(mnemonic: “%câ€)"
+msgstr "'%s' (mnemonic: '%c')"
#, c-format
msgid "%s: pathspec magic not supported by this command: %s"
@@ -17696,7 +18520,7 @@ msgstr "%s: số mầu nhiệm đặc tả Ä‘Æ°á»ng dẫn chÆ°a được há»— t
#, c-format
msgid "pathspec '%s' is beyond a symbolic link"
-msgstr "đặc tả Ä‘Æ°á»ng dẫn “%s†vượt ra ngoài liên kết má»m"
+msgstr "đặc tả Ä‘Æ°á»ng dẫn '%s' vượt ra ngoài liên kết má»m"
#, c-format
msgid "line is badly quoted: %s"
@@ -17746,14 +18570,14 @@ msgid "remote error: %s"
msgstr "lỗi máy chủ: %s"
msgid "Refreshing index"
-msgstr "Làm mới bảng mục lục"
+msgstr "Làm mới chỉ mục"
#, c-format
msgid "unable to create threaded lstat: %s"
-msgstr "không thể tạo tuyến trình lstat: %s"
+msgstr "không thể tạo tiến trình lstat: %s"
msgid "unable to parse --pretty format"
-msgstr "không thể phân tích định dạng --pretty"
+msgstr "không thể Ä‘á»c định dạng --pretty"
msgid "promisor-remote: unable to fork off fetch subprocess"
msgstr "promisor-remote: không thể rẽ nhánh tuyến trình con fetch"
@@ -17762,12 +18586,15 @@ msgid "promisor-remote: could not write to fetch subprocess"
msgstr "promisor-remote: không thể ghi tiến trình con fetch"
msgid "promisor-remote: could not close stdin to fetch subprocess"
-msgstr ""
-"promisor-remote: không thể đóng đầu vào tiêu chuẩn tiến trình con fetch"
+msgstr "promisor-remote: không thể đóng stdin tiến trình con fetch"
#, c-format
msgid "promisor remote name cannot begin with '/': %s"
-msgstr "tên máy chủ hứa hẹn không thể bắt đầu bằng “/â€: %s"
+msgstr "tên máy chủ promisor không thể bắt đầu bằng '/': %s"
+
+#, c-format
+msgid "could not fetch %s from promisor remote"
+msgstr "không thể tải %s từ máy chủ promisor"
msgid "object-info: expected flush after arguments"
msgstr "object-info: cần đẩy dữ liệu lên đĩa sau các tham số"
@@ -17776,38 +18603,44 @@ msgid "Removing duplicate objects"
msgstr "Äang gỡ các đối tượng trùng lặp"
msgid "could not start `log`"
-msgstr "không thể lấy thông tin thống kê vỠ“log“"
+msgstr "không thể khởi chạy `log`"
msgid "could not read `log` output"
-msgstr "không thể Ä‘á»c kết xuất “logâ€"
+msgstr "không thể Ä‘á»c đầu ra `log`"
#, c-format
msgid "could not parse commit '%s'"
-msgstr "không thể phân tích lần chuyển giao “%sâ€"
+msgstr "không thể Ä‘á»c lần chuyển giao '%s'"
#, c-format
msgid ""
"could not parse first line of `log` output: did not start with 'commit ': "
"'%s'"
msgstr ""
-"không thể phân tích cú pháp dòng đầu tiên của đầu ra “logâ€: không bắt đầu "
-"bằng “commit â€: “%sâ€"
+"không hiểu cú pháp dòng đầu tiên của đầu ra 'log': không bắt đầu bằng "
+"'commit ': '%s'"
#, c-format
msgid "could not parse git header '%.*s'"
-msgstr "không thể phân tích cú pháp phần đầu git “%.*sâ€"
+msgstr "không hiểu cú pháp phần đầu git '%.*s'"
msgid "failed to generate diff"
msgstr "gặp lỗi khi tạo khác biệt"
#, c-format
msgid "could not parse log for '%s'"
-msgstr "không thể phân tích nhật ký cho “%sâ€"
+msgstr "không thể Ä‘á»c nhật ký cho '%s'"
+
+#, c-format
+msgid "invalid extra cruft tip: '%s'"
+msgstr "extra cruft tip không hợp lệ: '%s'"
+
+msgid "unable to enumerate additional recent objects"
+msgstr "không thể đếm các đối tượng mới thêm"
#, c-format
msgid "will not add file alias '%s' ('%s' already exists in index)"
-msgstr ""
-"sẽ không thêm các bí danh “%s†(“%s†đã có từ trước trong bảng mục lục)"
+msgstr "sẽ không thêm các bí danh '%s' ('%s' đã có từ trước trong chỉ mục)"
msgid "cannot create an empty blob in the object database"
msgstr "không thể tạo một blob rỗng trong cơ sở dữ liệu đối tượng"
@@ -17819,22 +18652,18 @@ msgstr ""
#, c-format
msgid "unable to index file '%s'"
-msgstr "không thể đánh mục lục tập tin “%sâ€"
+msgstr "không thể đánh chỉ mục tập tin '%s'"
#, c-format
msgid "unable to add '%s' to index"
-msgstr "không thể thêm %s vào bảng mục lục"
-
-#, c-format
-msgid "unable to stat '%s'"
-msgstr "không thể lấy thống kê “%sâ€"
+msgstr "không thể thêm %s vào chỉ mục"
#, c-format
msgid "'%s' appears as both a file and as a directory"
-msgstr "%s có vẻ không phải là tập tin và cũng chẳng phải là một thư mục"
+msgstr "%s có vẻ vừa là tập tin và cũng vừa là thư mục"
msgid "Refresh index"
-msgstr "Làm tươi mới bảng mục lục"
+msgstr "Làm mới chỉ mục"
#, c-format
msgid ""
@@ -17858,37 +18687,37 @@ msgstr "chữ ký sai 0x%08x"
#, c-format
msgid "bad index version %d"
-msgstr "phiên bản mục lục sai %d"
+msgstr "phiên bản chỉ mục sai %d"
msgid "bad index file sha1 signature"
-msgstr "chữ ký dạng sha1 cho tập tin mục lục không đúng"
+msgstr "chữ ký dạng sha1 cho tập tin chỉ mục không đúng"
#, c-format
msgid "index uses %.4s extension, which we do not understand"
-msgstr "mục lục dùng phần mở rộng %.4s, cái mà chúng tôi không hiểu được"
+msgstr "chỉ mục dùng phần mở rộng %.4s, cái mà chúng tôi không hiểu được"
#, c-format
msgid "ignoring %.4s extension"
-msgstr "đang lỠđi phần mở rộng %.4s"
+msgstr "đang bỠqua phần mở rộng %.4s"
#, c-format
msgid "unknown index entry format 0x%08x"
-msgstr "không hiểu định dạng mục lục 0x%08x"
+msgstr "không hiểu định dạng chỉ mục 0x%08x"
#, c-format
msgid "malformed name field in the index, near path '%s'"
-msgstr "trÆ°á»ng tên sai sạng trong mục lục, gần Ä‘Æ°á»ng dẫn “%sâ€"
+msgstr "trÆ°á»ng tên sai sạng trong chỉ mục, gần Ä‘Æ°á»ng dẫn '%s'"
msgid "unordered stage entries in index"
-msgstr "các mục tin stage không đúng thứ tự trong mục lục"
+msgstr "các mục tin stage không đúng thứ tự trong chỉ mục"
#, c-format
msgid "multiple stage entries for merged file '%s'"
-msgstr "nhiá»u mục stage cho tập tin hòa trá»™n “%sâ€"
+msgstr "nhiá»u mục stage cho tập tin hòa trá»™n '%s'"
#, c-format
msgid "unordered stage entries for '%s'"
-msgstr "các mục tin stage không đúng thứ tá»± cho “%sâ€"
+msgstr "các mục tin stage không đúng thứ tự cho '%s'"
#, c-format
msgid "unable to create load_cache_entries thread: %s"
@@ -17900,19 +18729,19 @@ msgstr "không thể gia nhập tuyến load_cache_entries: %s"
#, c-format
msgid "%s: index file open failed"
-msgstr "%s: mở tập tin mục lục gặp lỗi"
+msgstr "%s: mở tập tin chỉ mục gặp lỗi"
#, c-format
msgid "%s: cannot stat the open index"
-msgstr "%s: không thể lấy thống kê bảng mục lục đã mở"
+msgstr "%s: không thể stat chỉ mục đã mở"
#, c-format
msgid "%s: index file smaller than expected"
-msgstr "%s: tập tin mục lục nhỠhơn mong đợi"
+msgstr "%s: tập tin chỉ mục nhỠhơn mong đợi"
#, c-format
msgid "%s: unable to map index file%s"
-msgstr "%s: không thể ánh xạ tập tin mục lục%s"
+msgstr "%s: không thể ánh xạ tập tin chỉ mục%s"
#, c-format
msgid "unable to create load_index_extensions thread: %s"
@@ -17924,46 +18753,50 @@ msgstr "không thể gia nhập tuyến load_index_extensions: %s"
#, c-format
msgid "could not freshen shared index '%s'"
-msgstr "không thể làm tÆ°Æ¡i má»›i mục lục đã chia sẻ “%sâ€"
+msgstr "không thể làm tươi mới chỉ mục đã chia sẻ '%s'"
#, c-format
msgid "broken index, expect %s in %s, got %s"
-msgstr "mục lục bị há»ng, cần %s trong %s, nhÆ°ng lại nhận được %s"
+msgstr "chỉ mục bị há»ng, cần %s trong %s, nhÆ°ng lại có %s"
msgid "cannot write split index for a sparse index"
-msgstr "không thể ghi mục lục chia tách cho \"sparse index\""
+msgstr "không thể ghi chỉ mục chia tách cho \"sparse index\""
msgid "failed to convert to a sparse-index"
msgstr "gặp lỗi khi chuyển đổi sang \"sparse-index\""
#, c-format
-msgid "could not stat '%s'"
-msgstr "không thể lấy thông tin thống kê vỠ“%sâ€"
-
-#, c-format
msgid "unable to open git dir: %s"
msgstr "không thể mở thư mục git: %s"
#, c-format
msgid "unable to unlink: %s"
-msgstr "không thể bá» liên kết (unlink): “%sâ€"
+msgstr "không thể bỠliên kết (unlink): '%s'"
#, c-format
msgid "cannot fix permission bits on '%s'"
-msgstr "không thể sá»­a các bít phân quyá»n trên “%sâ€"
+msgstr "không thể sá»­a các bít phân quyá»n trên '%s'"
#, c-format
msgid "%s: cannot drop to stage #0"
msgstr "%s: không thể xóa bỠstage #0"
+#, c-format
+msgid "unexpected diff status %c"
+msgstr "trạng thái lệnh diff không như mong đợi %c"
+
+#, c-format
+msgid "remove '%s'\n"
+msgstr "gỡ bỠ'%s'\n"
+
msgid ""
"You can fix this with 'git rebase --edit-todo' and then run 'git rebase --"
"continue'.\n"
"Or you can abort the rebase with 'git rebase --abort'.\n"
msgstr ""
-"Bạn có thể sửa nó bằng “git rebase --edit-todo†và sau đó chạy “git rebase --"
-"continueâ€.\n"
-"Hoặc là bạn có thể bãi bá» việc cải tổ bằng “git rebase --abortâ€.\n"
+"Bạn có thể sửa nó bằng 'git rebase --edit-todo' và sau đó chạy 'git rebase --"
+"continue'.\n"
+"Hoặc là bạn có thể huỷ bỠviệc cải tổ bằng 'git rebase --abort'.\n"
#, c-format
msgid ""
@@ -17988,9 +18821,12 @@ msgid ""
"l, label <label> = label current HEAD with a name\n"
"t, reset <label> = reset HEAD to a label\n"
"m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]\n"
-". create a merge commit using the original merge commit's\n"
-". message (or the oneline, if no original merge commit was\n"
-". specified); use -c <commit> to reword the commit message\n"
+" create a merge commit using the original merge commit's\n"
+" message (or the oneline, if no original merge commit was\n"
+" specified); use -c <commit> to reword the commit message\n"
+"u, update-ref <ref> = track a placeholder for the <ref> to be updated\n"
+" to this position in the new commits. The <ref> is\n"
+" updated at the end of the rebase\n"
"\n"
"These lines can be re-ordered; they are executed from top to bottom.\n"
msgstr ""
@@ -17998,7 +18834,7 @@ msgstr ""
"Các lệnh:\n"
"p, pick <commit> = dùng lần chuyển giao\n"
"r, reword <commit> = dùng lần chuyển giao, nhưng sửa lại phần chú thích\n"
-"e, edit <commit> = dùng lần chuyển giao, nhưng dừng lại để tu bổ (amend)\n"
+"e, edit <commit> = dùng lần chuyển giao, nhưng dừng lại để tu bổ\n"
"s, squash <commit> = dùng lần chuyển giao, nhưng trộn vào lần chuyển giao kế "
"trÆ°á»›c\n"
"f, fixup [-C | -c] <commit> = giống như \"squash\", nhưng chỉ giữ lại phần "
@@ -18009,33 +18845,35 @@ msgstr ""
"nhÆ°ng\n"
" mở trình biên soạn\n"
"x, exec <commit> = chạy lệnh (phần còn lại của dòng) dùng hệ vá»\n"
-"b, break = dừng tại đây (tiếp tục cải tổ sau này bằng “git rebase --"
-"continueâ€)\n"
+"b, break = dừng tại đây (tiếp tục cải tổ sau này bằng 'git rebase --"
+"continue')\n"
"d, drop <commit> = xóa bỠlần chuyển giao\n"
-"l, label <label> = đánh nhãn HEAD hiện tại bằng một tên\n"
-"t, reset <label> = đặt lại HEAD thành một nhãn\n"
+"l, label <label> = đánh tên nhãn HEAD hiện tại\n"
+"t, reset <label> = đặt lại HEAD vỠmột nhãn\n"
"m, merge [-C <commit> | -c <commit>] <nhãn> [# <một_dòng>]\n"
". tạo một lần chuyển giao hòa trộn sử dụng chú thích của lần chuyển\n"
". giao hòa trộn gốc (hoặc một_dòng, nếu không chỉ định lần chuyển giao "
"hòa\n"
". trộn gốc). Dùng -c <commit> để reword chú thích của lần chuyển "
"giao.\n"
+"u, update-ref <ref> = track a placeholder for the <ref> to be updated\n"
+" to this position in the new commits. The <ref> is\n"
+" updated at the end of the rebase\n"
"\n"
-"Những dòng này có thể được thay đổi thứ tự; chúng chạy từ trên đỉnh xuống "
-"dưới đáy.\n"
+"Những dòng này có thể được thay đổi thứ tự; chúng được thực thi từ trên "
+"xuống dưới.\n"
#, c-format
msgid "Rebase %s onto %s (%d command)"
msgid_plural "Rebase %s onto %s (%d commands)"
-msgstr[0] "Cải tổ %s vào %s (%d lệnh )"
+msgstr[0] "Cải tổ %s vào %s (%d lệnh)"
msgid ""
"\n"
"Do not remove any line. Use 'drop' explicitly to remove a commit.\n"
msgstr ""
"\n"
-"Äừng xóa bất kỳ dòng nào. Dùng “drop†má»™t cách rõ ràng để xóa bá» má»™t lần "
-"chuyển giao.\n"
+"Äừng xóa bất kỳ dòng nào. Dùng 'drop' để xóa bá» má»™t lần chuyển giao.\n"
msgid ""
"\n"
@@ -18063,12 +18901,12 @@ msgid ""
"\n"
msgstr ""
"\n"
-"Tuy nhiên, nếu bạn xóa bá» má»i thứ, việc cải tổ sẽ bị bãi bá».\n"
+"Tuy nhiên, nếu bạn xóa bá» má»i thứ, việc cải tổ sẽ bị huá»· bá».\n"
"\n"
#, c-format
msgid "could not write '%s'."
-msgstr "không thể ghi “%sâ€."
+msgstr "không thể ghi '%s'."
#, c-format
msgid ""
@@ -18090,29 +18928,37 @@ msgstr ""
"Äể tránh thông báo này, dùng \"drop\" má»™t cách rõ ràng để xóa bá» má»™t lần "
"chuyển giao.\n"
"\n"
-"Dùng “git config rebase.missingCommitsCheck†để thay đổi mức độ của cảnh "
+"Dùng 'git config rebase.missingCommitsCheck' để thay đổi mức độ của cảnh "
"báo.\n"
"Cánh ứng xử có thể là: ignore, warn, error.\n"
"\n"
#, c-format
msgid "%s: 'preserve' superseded by 'merges'"
-msgstr "%s: “preserve†bị cấm bởi “mergesâ€"
+msgstr "%s: 'preserve' bị thay bởi 'merges'"
msgid "gone"
-msgstr "đã ra đi"
+msgstr "đã xoá"
#, c-format
msgid "ahead %d"
-msgstr "phía trước %d"
+msgstr "đứng trước %d"
#, c-format
msgid "behind %d"
-msgstr "đằng sau %d"
+msgstr "đứng sau %d"
#, c-format
msgid "ahead %d, behind %d"
-msgstr "trÆ°á»›c %d, sau %d"
+msgstr "đứng trước %d, đứng sau %d"
+
+#, c-format
+msgid "%%(%.*s) does not take arguments"
+msgstr "%%(%.*s) không nhận các đối số"
+
+#, c-format
+msgid "unrecognized %%(%.*s) argument: %s"
+msgstr "đối số không được thừa nhận %%(%.*s): %s"
#, c-format
msgid "expected format: %%(color:<color>)"
@@ -18131,40 +18977,36 @@ msgid "Integer value expected refname:rstrip=%s"
msgstr "Giá trị nguyên cần tên tham chiếu:rstrip=%s"
#, c-format
-msgid "unrecognized %%(%s) argument: %s"
-msgstr "đối số không được thừa nhận %%(%s): %s"
+msgid "expected %%(trailers:key=<value>)"
+msgstr "cần %%(trailers:key=<giá trị>)"
#, c-format
-msgid "%%(objecttype) does not take arguments"
-msgstr "%%(objecttype) không nhận các đối số"
+msgid "unknown %%(trailers) argument: %s"
+msgstr "không hiểu tham số %%(trailers): %s"
#, c-format
-msgid "%%(deltabase) does not take arguments"
-msgstr "%%(deltabase) không nhận các đối số"
+msgid "positive value expected contents:lines=%s"
+msgstr "cần nội dung mang giá trị dương:lines=%s"
#, c-format
-msgid "%%(body) does not take arguments"
-msgstr "%%(body) không nhận các đối số"
+msgid "argument expected for %s"
+msgstr "cần đối số cho %s"
#, c-format
-msgid "expected %%(trailers:key=<value>)"
-msgstr "cần %%(trailers:key=<giá trị>)"
+msgid "positive value expected %s=%s"
+msgstr "cần giá trị dương %s=%s"
#, c-format
-msgid "unknown %%(trailers) argument: %s"
-msgstr "không hiểu tham số %%(trailers): %s"
+msgid "cannot fully parse %s=%s"
+msgstr "không hiểu %s=%s"
#, c-format
-msgid "positive value expected contents:lines=%s"
-msgstr "cần nội dung mang giá trị dương:lines=%s"
+msgid "value expected %s="
+msgstr "cần %s="
#, c-format
msgid "positive value expected '%s' in %%(%s)"
-msgstr "cần giá trị dương “%s†trong %%(%s)"
-
-#, c-format
-msgid "unrecognized email option: %s"
-msgstr "không nhận ra tùy chá»n thÆ° Ä‘iện tá»­: “%sâ€"
+msgstr "cần giá trị dương '%s' trong %%(%s)"
#, c-format
msgid "expected format: %%(align:<width>,<position>)"
@@ -18179,16 +19021,20 @@ msgid "unrecognized width:%s"
msgstr "chiá»u rá»™ng không được thừa nhận:%s"
#, c-format
+msgid "unrecognized %%(%s) argument: %s"
+msgstr "đối số không được thừa nhận %%(%s): %s"
+
+#, c-format
msgid "positive width expected with the %%(align) atom"
-msgstr "cần giá trị độ rộng dương với nguyên tử %%(align)"
+msgstr "cần giá trị độ rộng dương với atom %%(align)"
#, c-format
-msgid "%%(rest) does not take arguments"
-msgstr "%%(rest) không nhận các đối số"
+msgid "expected format: %%(ahead-behind:<committish>)"
+msgstr "cần định dạng: %%(ahead-behind:<committish>)"
#, c-format
msgid "malformed field name: %.*s"
-msgstr "tên trÆ°á»ng dị hình: %.*s"
+msgstr "tên trÆ°á»ng sai quy cách: %.*s"
#, c-format
msgid "unknown field name: %.*s"
@@ -18198,32 +19044,32 @@ msgstr "không hiểu tên trÆ°á»ng: %.*s"
msgid ""
"not a git repository, but the field '%.*s' requires access to object data"
msgstr ""
-"không phải là má»™t kho git, nhÆ°ng trÆ°á»ng “%.*s†yêu cầu truy cập vào dữ liệu "
+"không phải là má»™t kho git, nhÆ°ng trÆ°á»ng '%.*s' yêu cầu truy cập vào dữ liệu "
"đối tượng"
#, c-format
msgid "format: %%(%s) atom used without a %%(%s) atom"
-msgstr "định dạng: nguyên tử %%(%s) được dùng mà không có nguyên tử %%(%s)"
+msgstr "định dạng: atom %%(%s) được dùng mà không có atom %%(%s)"
#, c-format
msgid "format: %%(then) atom used more than once"
-msgstr "định dạng: nguyên tá»­ %%(then) được dùng nhiá»u hÆ¡n má»™t lần"
+msgstr "định dạng: atom %%(then) được dùng nhiá»u hÆ¡n má»™t lần"
#, c-format
msgid "format: %%(then) atom used after %%(else)"
-msgstr "định dạng: nguyên tử %%(then) được dùng sau %%(else)"
+msgstr "định dạng: atom %%(then) được dùng sau %%(else)"
#, c-format
msgid "format: %%(else) atom used more than once"
-msgstr "định dạng: nguyên tá»­ %%(else) được dùng nhiá»u hÆ¡n má»™t lần"
+msgstr "định dạng: atom %%(else) được dùng nhiá»u hÆ¡n má»™t lần"
#, c-format
msgid "format: %%(end) atom used without corresponding atom"
-msgstr "định dạng: nguyên tử %%(end) được dùng mà không có nguyên tử tương ứng"
+msgstr "định dạng: atom %%(end) được dùng mà không có atom tương ứng"
#, c-format
msgid "malformed format string %s"
-msgstr "chuỗi định dạng dị hình %s"
+msgstr "chuỗi định dạng sai quy cách %s"
#, c-format
msgid "this command reject atom %%(%.*s)"
@@ -18233,6 +19079,9 @@ msgstr "lệnh này từ chối atom %%(%.*s)"
msgid "--format=%.*s cannot be used with --python, --shell, --tcl"
msgstr "--format=%.*s không thể được dùng với --python, --shell, --tcl"
+msgid "failed to run 'describe'"
+msgstr "gặp lỗi khi chạy 'describe'"
+
#, c-format
msgid "(no branch, rebasing %s)"
msgstr "(không nhánh, đang cải tổ %s)"
@@ -18266,27 +19115,27 @@ msgstr "parse_object_buffer gặp lỗi trên %s cho %s"
#, c-format
msgid "malformed object at '%s'"
-msgstr "đối tượng dị hình tại “%sâ€"
+msgstr "đối tượng sai quy cách tại '%s'"
#, c-format
msgid "ignoring ref with broken name %s"
-msgstr "Ä‘ang lá» Ä‘i tham chiếu vá»›i tên há»ng %s"
+msgstr "Ä‘ang bá» qua tham chiếu vá»›i tên há»ng %s"
#, c-format
msgid "ignoring broken ref %s"
-msgstr "Ä‘ang lá» Ä‘i tham chiếu há»ng %s"
+msgstr "Ä‘ang bá» qua tham chiếu há»ng %s"
#, c-format
msgid "format: %%(end) atom missing"
-msgstr "định dạng: thiếu nguyên tử %%(end)"
+msgstr "định dạng: thiếu atom %%(end)"
#, c-format
msgid "malformed object name %s"
-msgstr "tên đối tượng dị hình %s"
+msgstr "tên đối tượng sai quy cách %s"
#, c-format
msgid "option `%s' must point to a commit"
-msgstr "tùy chá»n “%s†phải chỉ đến má»™t lần chuyển giao"
+msgstr "tùy chá»n '%s' phải chỉ đến má»™t lần chuyển giao"
msgid "key"
msgstr "khóa"
@@ -18294,17 +19143,20 @@ msgstr "khóa"
msgid "field name to sort on"
msgstr "tên trÆ°á»ng cần sắp xếp"
+msgid "exclude refs which match pattern"
+msgstr "không bao gồm các tham chiếu khớp với mẫu"
+
#, c-format
msgid "not a reflog: %s"
msgstr "không phải một reflog: %s"
#, c-format
msgid "no reflog for '%s'"
-msgstr "không reflog cho “%sâ€"
+msgstr "không reflog cho '%s'"
#, c-format
msgid "%s does not point to a valid object!"
-msgstr "“%s†không chỉ đến một lần chuyển giao hợp lệ nào cả!"
+msgstr "'%s' không chỉ đến một lần chuyển giao hợp lệ nào cả!"
#, c-format
msgid ""
@@ -18319,20 +19171,20 @@ msgid ""
"\n"
"\tgit branch -m <name>\n"
msgstr ""
-"Sử dụng “%s†làm tên cho nhánh ban đầu. Tên nhánh mặc định này\n"
+"Sử dụng '%s' làm tên cho nhánh ban đầu. Tên nhánh mặc định này\n"
"có thể thay đổi. Äể cấu hình tên nhánh khởi đầu sá»­ dụng trong tất cả\n"
"kho lÆ°u trữ má»›i của bạn, cái mà sẽ ngăn chặn cảnh báo này, gá»i lệnh:\n"
"\n"
"\tgit config --global init.defaultBranch <tên>\n"
"\n"
-"Tên thÆ°á»ng được chá»n thay cho “master†là “mainâ€, “trunk†và\n"
-"“developmentâ€. Nhánh vừa tạo có thể được đổi tên thông qua lệnh:\n"
+"Tên thÆ°á»ng được chá»n thay cho 'master' là 'main', 'trunk' và\n"
+"'development'. Nhánh vừa tạo có thể được đổi tên thông qua lệnh:\n"
"\n"
"\tgit branch -m <tên>\n"
#, c-format
msgid "could not retrieve `%s`"
-msgstr "không thể lấy vỠ“%sâ€"
+msgstr "không thể lấy vỠ'%s'"
#, c-format
msgid "invalid branch name: %s = %s"
@@ -18340,7 +19192,7 @@ msgstr "tên nhánh không hợp lệ: %s = %s"
#, c-format
msgid "ignoring dangling symref %s"
-msgstr "Ä‘ang lá» Ä‘i tham chiếu má»m thừa %s"
+msgstr "Ä‘ang bá» qua tham chiếu má»m thừa %s"
#, c-format
msgid "log for ref %s has gap after %s"
@@ -18356,33 +19208,29 @@ msgstr "nhật ký cho %s trống rỗng"
#, c-format
msgid "refusing to update ref with bad name '%s'"
-msgstr "từ chối cập nhật tham chiếu vá»›i tên sai “%sâ€"
+msgstr "từ chối cập nhật tham chiếu với tên sai '%s'"
#, c-format
msgid "update_ref failed for ref '%s': %s"
-msgstr "update_ref bị lá»—i cho ref “%sâ€: %s"
+msgstr "update_ref bị lỗi cho ref '%s': %s"
#, c-format
msgid "multiple updates for ref '%s' not allowed"
-msgstr "không cho phép Ä‘a cập nhật cho tham chiếu “%sâ€"
+msgstr "không cho phép đa cập nhật cho tham chiếu '%s'"
msgid "ref updates forbidden inside quarantine environment"
msgstr "cập nhật tham chiếu bị cấm trong môi trÆ°á»ng kiểm tra"
msgid "ref updates aborted by hook"
-msgstr "các cập nhật tham chiếu bị bãi bỠbởi móc"
+msgstr "các cập nhật tham chiếu bị huỷ bỠbởi móc"
#, c-format
msgid "'%s' exists; cannot create '%s'"
-msgstr "“%s†sẵn có; không thể tạo “%sâ€"
+msgstr "'%s' sẵn có; không thể tạo '%s'"
#, c-format
msgid "cannot process '%s' and '%s' at the same time"
-msgstr "không thể xử lý “%s†và “%s†cùng một lúc"
-
-#, c-format
-msgid "could not remove reference %s"
-msgstr "không thể gỡ bỠtham chiếu: %s"
+msgstr "không thể xử lý '%s' và '%s' cùng một lúc"
#, c-format
msgid "could not delete reference %s: %s"
@@ -18393,12 +19241,83 @@ msgid "could not delete references: %s"
msgstr "không thể xóa bỠtham chiếu: %s"
#, c-format
+msgid "refname is dangerous: %s"
+msgstr "tên tham chiếu không an toàn: %s"
+
+#, c-format
+msgid "trying to write ref '%s' with nonexistent object %s"
+msgstr "thử ghi tham chiếu '%s' tới đối tượng %s không tồn tại"
+
+#, c-format
+msgid "trying to write non-commit object %s to branch '%s'"
+msgstr "thử ghi đối tượng không phải chuyển giao %s tới nhánh '%s'"
+
+#, c-format
+msgid ""
+"multiple updates for 'HEAD' (including one via its referent '%s') are not "
+"allowed"
+msgstr ""
+"không cho phép đa cập nhật cho tham chiếu HEAD (bao gồm cả thông qua tham "
+"chiếu '%s')"
+
+#, c-format
+msgid "cannot lock ref '%s': unable to resolve reference '%s'"
+msgstr "không thể khoá tham chiếu '%s': không thể phân giải tham chiếu '%s'"
+
+#, c-format
+msgid "cannot lock ref '%s': error reading reference"
+msgstr "không thể khoá tham chiếu '%s': lá»—i khi Ä‘á»c tham chiếu"
+
+#, c-format
+msgid ""
+"multiple updates for '%s' (including one via symref '%s') are not allowed"
+msgstr ""
+"không cho phép đa cập nhật cho tham chiếu '%s' (bao gồm cả thông qua tham "
+"chiếu biểu trưng '%s')"
+
+#, c-format
+msgid "cannot lock ref '%s': reference already exists"
+msgstr "không thể lock tham chiếu '%s': tham chiếu đã tồn tại"
+
+#, c-format
+msgid "cannot lock ref '%s': reference is missing but expected %s"
+msgstr "không thể lock tham chiếu '%s': không tồn tại tham chiếu nhưng cần %s"
+
+#, c-format
+msgid "cannot lock ref '%s': is at %s but expected %s"
+msgstr "không thể lock tham chiếu '%s': đang ở %s nhưng cần %s"
+
+#, c-format
+msgid "reftable: transaction prepare: %s"
+msgstr "reftable: chuẩn bị chuyển giao: %s"
+
+#, c-format
+msgid "reftable: transaction failure: %s"
+msgstr "reftable: chuyển giao thất bại: %s"
+
+#, c-format
+msgid "unable to compact stack: %s"
+msgstr "không thể nén stack: %s"
+
+#, c-format
+msgid "refname %s not found"
+msgstr "không tìm thấy tên tham chiếu %s"
+
+#, c-format
+msgid "refname %s is a symbolic ref, copying it is not supported"
+msgstr "tên tham chiếu %s là tham chiếu biểu trưng, không hỗ trợ sao chép"
+
+#, c-format
msgid "invalid refspec '%s'"
-msgstr "refspec không hợp lệ “%sâ€"
+msgstr "refspec không hợp lệ '%s'"
#, c-format
msgid "invalid quoting in push-option value: '%s'"
-msgstr "sai trích dẫn trong giá trị push-option :“%sâ€"
+msgstr "sai trích dẫn trong giá trị push-option :'%s'"
+
+#, c-format
+msgid "unknown value for object-format: %s"
+msgstr "không hiểu giá trị cho object-format: %s"
#, c-format
msgid "%sinfo/refs not valid: is this a git repository?"
@@ -18406,38 +19325,37 @@ msgstr "%sinfo/refs không hợp lệ: đây có phải là một kho git?"
msgid "invalid server response; expected service, got flush packet"
msgstr ""
-"đáp ứng từ máy phục vụ không hợp lệ; cần dịch vụ, nhưng lại nhận được gói "
-"flush"
+"phản hồi từ máy chủ không hợp lệ; cần dịch vụ, nhưng lại nhận được gói flush"
#, c-format
msgid "invalid server response; got '%s'"
-msgstr "trả vỠcủa máy phục vụ không hợp lệ; nhận được %s"
+msgstr "phản hồi từ máy chủ không hợp lệ; nhận được %s"
#, c-format
msgid "repository '%s' not found"
-msgstr "không tìm thấy kho “%sâ€"
+msgstr "không tìm thấy kho '%s'"
#, c-format
msgid "Authentication failed for '%s'"
-msgstr "Xác thá»±c gặp lá»—i cho “%sâ€"
+msgstr "Xác thực gặp lỗi cho '%s'"
#, c-format
msgid "unable to access '%s' with http.pinnedPubkey configuration: %s"
-msgstr "không thể truy cập “%s†với cấu hình http.pinnedPubkey: %s"
+msgstr "không thể truy cập '%s' với cấu hình http.pinnedPubkey: %s"
#, c-format
msgid "unable to access '%s': %s"
-msgstr "không thể truy cập “%sâ€: %s"
+msgstr "không thể truy cập '%s': %s"
#, c-format
msgid "redirecting to %s"
msgstr "chuyển hướng đến %s"
msgid "shouldn't have EOF when not gentle on EOF"
-msgstr "không nên có EOF khi không gentle trên EOF"
+msgstr "không nên có EOF khi không thể xử lý EOF"
msgid "remote server sent unexpected response end packet"
-msgstr "máy phục vụ gửi gói kết thúc không cần"
+msgstr "máy chủ gá»­i gói kết thúc bất thÆ°á»ng"
msgid "unable to rewind rpc post data - try increasing http.postBuffer"
msgstr "không thể tua lại dữ liệu post rpc - thử tăng http.postBuffer"
@@ -18454,15 +19372,15 @@ msgid "RPC failed; %s"
msgstr "RPC gặp lỗi; %s"
msgid "cannot handle pushes this big"
-msgstr "không thể xử lý đẩy cái lớn này"
+msgstr "không thể xử lý đẩy lớn cỡ này"
#, c-format
msgid "cannot deflate request; zlib deflate error %d"
-msgstr "không thể giải nén yêu cầu; có lỗi khi giải nén của zlib %d"
+msgstr "không thể giải nén yêu cầu; lỗi zlib deflate %d"
#, c-format
msgid "cannot deflate request; zlib end error %d"
-msgstr "không thể giải nén yêu cầu; có lỗi ở cuối %d"
+msgstr "không thể giải nén yêu cầu; lỗi zlib end %d"
#, c-format
msgid "%d bytes of length header were received"
@@ -18483,12 +19401,19 @@ msgstr "không thể lấy vỠbằng sha1 thông qua smart http"
#, c-format
msgid "protocol error: expected sha/ref, got '%s'"
-msgstr "lá»—i giao thức: cần sha/ref, nhÆ°ng lại nhận được “%sâ€"
+msgstr "lỗi giao thức: cần sha/ref, nhưng lại nhận được '%s'"
#, c-format
msgid "http transport does not support %s"
msgstr "vận chuyển http không hỗ trợ %s"
+msgid "protocol error: expected '<url> <path>', missing space"
+msgstr "lỗi giao thức: cần '<url> <path>', thiếu dấu cách"
+
+#, c-format
+msgid "failed to download file at URL '%s'"
+msgstr "gặp lỗi khi tải tập tin tại URL '%s'"
+
msgid "git-http-push failed"
msgstr "git-http-push gặp lỗi"
@@ -18503,11 +19428,11 @@ msgstr "remote-curl: đã cố gắng fetch mà không có kho nội bộ"
#, c-format
msgid "remote-curl: unknown command '%s' from git"
-msgstr "remote-curl: không hiểu lệnh “%s†từ git"
+msgstr "remote-curl: không hiểu lệnh '%s' từ git"
#, c-format
msgid "config remote shorthand cannot begin with '/': %s"
-msgstr "cấu hình viết tắt máy chủ không thể bắt đầu bằng “/â€: %s"
+msgstr "cấu hình viết tắt máy chủ không thể bắt đầu bằng '/': %s"
msgid "more than one receivepack given, using the first"
msgstr "đã Ä‘Æ°a ra nhiá»u hÆ¡n má»™t gói nhận vá», Ä‘ang sá»­ dụng cái đầu tiên"
@@ -18537,19 +19462,19 @@ msgstr "%s theo dõi cả %s và %s"
#, c-format
msgid "key '%s' of pattern had no '*'"
-msgstr "khóa “%s†của mẫu k có “*â€"
+msgstr "khóa '%s' của mẫu k có '*'"
#, c-format
msgid "value '%s' of pattern has no '*'"
-msgstr "giá trị “%s†của mẫu k có “*â€"
+msgstr "giá trị '%s' của mẫu k có '*'"
#, c-format
msgid "src refspec %s does not match any"
-msgstr "refspec %s nguồn không khớp bất kỳ cái gì"
+msgstr "refspec (đặc tả tham chiếu) nguồn %s không khớp bất kỳ cái gì"
#, c-format
msgid "src refspec %s matches more than one"
-msgstr "refspec %s nguồn khá»›p nhiá»u hÆ¡n má»™t"
+msgstr "refspec (đặc tả tham chiếu) nguồn %s khá»›p nhiá»u hÆ¡n má»™t"
#. TRANSLATORS: "matches '%s'%" is the <dst> part of "git push
#. <remote> <src>:<dst>" push, and "being pushed ('%s')" is
@@ -18567,17 +19492,16 @@ msgid ""
"\n"
"Neither worked, so we gave up. You must fully qualify the ref."
msgstr ""
-"Äích bạn đã cung cấp không phải tên tham chiếu đầy đủ (tức là\n"
-"bắt đầu bằng \"refs/\"). Chúng tôi đã cố suy luận rằng ý của bạn là:\n"
+"Äích bạn đã cung cấp không phải tên tham chiếu đầy đủ\n"
+"(bắt đầu bằng \"refs/\"). Chúng tôi đã thử đoán ý của bạn theo hai cách:\n"
"\n"
-"- Tìm kiếm một tham chiếu mà nó khớp “%s†bên phía máy chủ.\n"
-"- Kiểm tra xem <src> được đẩy lên (“%sâ€)\n"
-" là một tham chiếu trong \"refs/{heads,tags}/\". Nếu thế chúng tôi thêm một "
-"tiá»n tố\n"
-" refs/{heads,tags}/ tương ứng bên phía máy chủ.\n"
+"- Tìm kiếm một tham chiếu khớp '%s' bên phía máy chủ.\n"
+"- Kiểm tra xem <nguồn> được đẩy lên ('%s')\n"
+" có là một tham chiếu trong \"refs/{heads,tags}/\", và nếu vậy thêm\n"
+" tiá»n tố refs/{heads,tags}/ tÆ°Æ¡ng ứng bên phía máy chủ.\n"
"\n"
-"Nếu cả hai là không thể, thì chúng tôi cũng chịu thua. Bạn phải dùng tham "
-"chiếu dạng đầy đủ."
+"Vì cả hai Ä‘á»u không thể, chúng tôi chịu. Bạn phải dùng tham chiếu dạng đầy "
+"đủ."
#, c-format
msgid ""
@@ -18585,9 +19509,9 @@ msgid ""
"Did you mean to create a new branch by pushing to\n"
"'%s:refs/heads/%s'?"
msgstr ""
-"Phần <src> của đặc tả Ä‘Æ°á»ng dẫn là má»™t đối tượng lần chuyển giao.\n"
+"Phần <src> của đặc tả tham chiếu là một đối tượng lần chuyển giao.\n"
"Có phải ý bạn là một tạo một nhánh mới bằng cách đẩy lên\n"
-"“%s:refs/heads/%s�"
+"'%s:refs/heads/%s'?"
#, c-format
msgid ""
@@ -18595,9 +19519,9 @@ msgid ""
"Did you mean to create a new tag by pushing to\n"
"'%s:refs/tags/%s'?"
msgstr ""
-"Phần <src> của đặc tả Ä‘Æ°á»ng dẫn là má»™t đối tượng thẻ.\n"
+"Phần <nguồn> của đặc tả tham chiếu là một đối tượng thẻ.\n"
"Có phải ý bạn là một tạo một thẻ mới bằng cách đẩy lên\n"
-"“%s:refs/tags/%s�"
+"'%s:refs/tags/%s'?"
#, c-format
msgid ""
@@ -18605,9 +19529,9 @@ msgid ""
"Did you mean to tag a new tree by pushing to\n"
"'%s:refs/tags/%s'?"
msgstr ""
-"Phần <src> của đặc tả Ä‘Æ°á»ng dẫn là má»™t đối tượng cây.\n"
+"Phần <nguồn> của đặc tả tham chiếu là một đối tượng cây.\n"
"Có phải ý bạn là một tạo một cây mới bằng cách đẩy lên\n"
-"“%s:refs/tags/%s�"
+"'%s:refs/tags/%s'?"
#, c-format
msgid ""
@@ -18615,17 +19539,17 @@ msgid ""
"Did you mean to tag a new blob by pushing to\n"
"'%s:refs/tags/%s'?"
msgstr ""
-"Phần <src> của đặc tả Ä‘Æ°á»ng dẫn là má»™t đối tượng blob.\n"
+"Phần <nguồn> của đặc tả tham chiếu là một đối tượng blob.\n"
"Có phải ý bạn là một tạo một blob mới bằng cách đẩy lên\n"
-"“%s:refs/tags/%s�"
+"'%s:refs/tags/%s'?"
#, c-format
msgid "%s cannot be resolved to branch"
-msgstr "“%s†không thể được phân giải thành nhánh"
+msgstr "'%s' không thể được phân giải thành nhánh"
#, c-format
msgid "unable to delete '%s': remote ref does not exist"
-msgstr "không thể xóa “%sâ€: tham chiếu trên máy chủ không tồn tại"
+msgstr "không thể xóa '%s': tham chiếu trên máy chủ không tồn tại"
#, c-format
msgid "dst refspec %s matches more than one"
@@ -18640,34 +19564,34 @@ msgstr "HEAD không chỉ đến một nhánh nào cả"
#, c-format
msgid "no such branch: '%s'"
-msgstr "không có nhánh nào nhÆ° thế: “%sâ€"
+msgstr "không có nhánh nào như thế: '%s'"
#, c-format
msgid "no upstream configured for branch '%s'"
-msgstr "không có thượng nguồn được cấu hình cho nhánh “%sâ€"
+msgstr "không có thượng nguồn được cấu hình cho nhánh '%s'"
#, c-format
msgid "upstream branch '%s' not stored as a remote-tracking branch"
msgstr ""
-"nhánh thượng nguồn “%s†không được lưu lại như là một nhánh theo dõi máy chủ"
+"nhánh thượng nguồn '%s' không được lưu lại như là một nhánh theo dõi máy chủ"
#, c-format
msgid "push destination '%s' on remote '%s' has no local tracking branch"
-msgstr "đẩy lên đích “%s†trên máy chủ “%s†không có nhánh theo dõi nội bộ"
+msgstr "đẩy lên đích '%s' trên máy chủ '%s' không có nhánh theo dõi nội bộ"
#, c-format
msgid "branch '%s' has no remote for pushing"
-msgstr "nhánh “%s†không có máy chủ để đẩy lên"
+msgstr "nhánh '%s' không có máy chủ để đẩy lên"
#, c-format
msgid "push refspecs for '%s' do not include '%s'"
-msgstr "đẩy refspecs cho “%s†không bao gồm “%sâ€"
+msgstr "đẩy refspecs cho '%s' không bao gồm '%s'"
msgid "push has no destination (push.default is 'nothing')"
-msgstr "đẩy lên mà không có đích (push.default là “nothingâ€)"
+msgstr "đẩy lên mà không có đích (push.default là 'nothing')"
msgid "cannot resolve 'simple' push to a single destination"
-msgstr "không thể phân giải đẩy “đơn giản†đến một đích đơn"
+msgstr "không thể phân giải đẩy 'đơn giản' đến một đích đơn"
#, c-format
msgid "couldn't find remote ref %s"
@@ -18675,23 +19599,23 @@ msgstr "không thể tìm thấy tham chiếu máy chủ %s"
#, c-format
msgid "* Ignoring funny ref '%s' locally"
-msgstr "* Äang bá» qua tham chiếu thú vị ná»™i bá»™ “%sâ€"
+msgstr "* Äang bá» qua tham chiếu thú vị ná»™i bá»™ '%s'"
#, c-format
msgid "Your branch is based on '%s', but the upstream is gone.\n"
msgstr ""
-"Nhánh của bạn dá»±a trên cÆ¡ sở là “%sâ€, nhÆ°ng trên thượng nguồn không còn.\n"
+"Nhánh của bạn dựa trên cơ sở là '%s', nhưng trên thượng nguồn không còn.\n"
msgid " (use \"git branch --unset-upstream\" to fixup)\n"
msgstr " (dùng \" git branch --unset-upstream\" để sửa)\n"
#, c-format
msgid "Your branch is up to date with '%s'.\n"
-msgstr "Nhánh của bạn đã cập nhật vá»›i “%sâ€.\n"
+msgstr "Nhánh của bạn đã cập nhật với '%s'.\n"
#, c-format
msgid "Your branch and '%s' refer to different commits.\n"
-msgstr "Nhánh của bạn và “%s†tham chiếu đến các lần chuyển giao khác nhau.\n"
+msgstr "Nhánh của bạn và '%s' tham chiếu đến các lần chuyển giao khác nhau.\n"
#, c-format
msgid " (use \"%s\" for details)\n"
@@ -18700,7 +19624,7 @@ msgstr " (dùng \"%s\" để biết thêm chi tiết)\n"
#, c-format
msgid "Your branch is ahead of '%s' by %d commit.\n"
msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
-msgstr[0] "Nhánh của bạn đứng trước “%s†%d lần chuyển giao.\n"
+msgstr[0] "Nhánh của bạn đứng trước '%s' %d lần chuyển giao.\n"
msgid " (use \"git push\" to publish your local commits)\n"
msgstr " (dùng \"git push\" để xuất bản các lần chuyển giao nội bộ của bạn)\n"
@@ -18710,8 +19634,8 @@ msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
msgid_plural ""
"Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n"
msgstr[0] ""
-"Nhánh của bạn đứng đằng sau “%s†%d lần chuyển giao, và có thể được chuyển-"
-"tiếp-nhanh.\n"
+"Nhánh của bạn đứng sau '%s' %d lần chuyển giao, và có thể được chuyển-tiếp-"
+"nhanh.\n"
msgid " (use \"git pull\" to update your local branch)\n"
msgstr " (dùng \"git pull\" để cập nhật nhánh nội bộ của bạn)\n"
@@ -18724,22 +19648,21 @@ msgid_plural ""
"Your branch and '%s' have diverged,\n"
"and have %d and %d different commits each, respectively.\n"
msgstr[0] ""
-"Nhánh của bạn và “%s†bị phân kỳ,\n"
-"và có %d và %d lần chuyển giao khác nhau cho từng cái,\n"
-"tương ứng với mỗi lần.\n"
+"Nhánh của bạn và '%s' bị phân kỳ,\n"
+"và tương ứng có %d và %d lần chuyển giao khác nhau cho từng nhánh.\n"
-msgid " (use \"git pull\" to merge the remote branch into yours)\n"
+msgid ""
+" (use \"git pull\" if you want to integrate the remote branch with yours)\n"
msgstr ""
-" (dùng \"git pull\" để hòa trộn nhánh trên máy chủ vào trong nhánh của "
-"bạn)\n"
+" (dùng \"git pull\" để hòa trộn nhánh trên máy chủ vào nhánh của bạn)\n"
#, c-format
msgid "cannot parse expected object name '%s'"
-msgstr "không thể phân tích tên đối tượng mong muốn “%sâ€"
+msgstr "không thể Ä‘á»c tên đối tượng mong muốn '%s'"
#, c-format
msgid "cannot strip one component off url '%s'"
-msgstr "không thể cắt bá» má»™t thành phần ra khá»i “%s†url"
+msgstr "không thể cắt bá» má»™t thành phần ra khá»i '%s' url"
#, c-format
msgid "bad replace ref name: %s"
@@ -18761,65 +19684,61 @@ msgstr "không thể ghi bản ghi rerere"
#, c-format
msgid "there were errors while writing '%s' (%s)"
-msgstr "gặp lá»—i Ä‘á»c khi Ä‘ang ghi “%s†(%s)"
+msgstr "gặp lá»—i Ä‘á»c khi Ä‘ang ghi '%s' (%s)"
#, c-format
msgid "could not parse conflict hunks in '%s'"
-msgstr "không thể phân tích các mảnh xung Ä‘á»™t trong “%sâ€"
+msgstr "không thể Ä‘á»c các khúc xung Ä‘á»™t trong '%s'"
#, c-format
msgid "failed utime() on '%s'"
-msgstr "gặp lá»—i utime() trên “%sâ€"
+msgstr "gặp lỗi utime() trên '%s'"
#, c-format
msgid "writing '%s' failed"
-msgstr "gặp lá»—i khi Ä‘ang ghi “%sâ€"
+msgstr "gặp lỗi khi đang ghi '%s'"
#, c-format
msgid "Staged '%s' using previous resolution."
-msgstr "Äã tạm cất “%s†sá»­ dụng cách phân giải kế trÆ°á»›c."
+msgstr "Äã tạm cất '%s' sá»­ dụng cách phân giải kế trÆ°á»›c."
#, c-format
msgid "Recorded resolution for '%s'."
-msgstr "Cách giải quyết đã ghi lại cho “%sâ€."
+msgstr "Cách giải quyết đã ghi lại cho '%s'."
#, c-format
msgid "Resolved '%s' using previous resolution."
-msgstr "Äã phân giải giải “%s†sá»­ dụng cách giải quyết kế trÆ°á»›c."
+msgstr "Äã phân giải giải '%s' sá»­ dụng cách giải quyết kế trÆ°á»›c."
#, c-format
msgid "cannot unlink stray '%s'"
-msgstr "không thể unlink stray “%sâ€"
+msgstr "không thể unlink stray '%s'"
#, c-format
msgid "Recorded preimage for '%s'"
-msgstr "Preimage đã được ghi lại cho “%sâ€"
+msgstr "Preimage đã được ghi lại cho '%s'"
#, c-format
msgid "failed to update conflicted state in '%s'"
-msgstr "gặp lá»—i khi chạy cập nhật trạng thái bị xung Ä‘á»™t trong “%sâ€"
+msgstr "gặp lỗi khi chạy cập nhật trạng thái bị xung đột trong '%s'"
#, c-format
msgid "no remembered resolution for '%s'"
-msgstr "đừng nhó các giải quyết cho “%sâ€"
-
-#, c-format
-msgid "cannot unlink '%s'"
-msgstr "không thể unlink “%sâ€"
+msgstr "đừng nhó các giải quyết cho '%s'"
#, c-format
msgid "Updated preimage for '%s'"
-msgstr "Äã cập nhật preimage cho “%sâ€"
+msgstr "Äã cập nhật preimage cho '%s'"
#, c-format
msgid "Forgot resolution for '%s'\n"
-msgstr "Quên phân giải cho “%sâ€\n"
+msgstr "Quên phân giải cho '%s'\n"
msgid "unable to open rr-cache directory"
msgstr "không thể mở thư mục rr-cache"
msgid "update the index with reused conflict resolution if possible"
-msgstr "cập nhật bảng mục lục với phân giải xung đột dùng lại nếu được"
+msgstr "cập nhật chỉ mục với phân giải xung đột dùng lại nếu được"
msgid "could not determine HEAD revision"
msgstr "không thể dò tìm điểm xét duyệt HEAD"
@@ -18828,15 +19747,45 @@ msgstr "không thể dò tìm điểm xét duyệt HEAD"
msgid "failed to find tree of %s"
msgstr "gặp lỗi khi tìm cây của %s"
+#, c-format
+msgid "unsupported section for hidden refs: %s"
+msgstr "không hỗ trợ mục cho tham chiếu ẩn: %s"
+
+msgid "--exclude-hidden= passed more than once"
+msgstr "--exclude-hidden= được dùng hơn một lần"
+
+#, c-format
+msgid "resolve-undo records `%s` which is missing"
+msgstr "resolve-undo ghi nhận '%s' bị thiếu"
+
+#, c-format
+msgid "%s exists but is a symbolic ref"
+msgstr "%s có tồn tại nhưng là tham chiếu biểu trưng"
+
+msgid ""
+"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD or REBASE_HEAD"
+msgstr ""
+"--merge yêu cầu tham chiếu ảo MERGE_HEAD, CHERRY_PICK_HEAD, REVERT_HEAD hoặc "
+"REBASE_HEAD"
+
+#, c-format
+msgid "could not get commit for --ancestry-path argument %s"
+msgstr "không tìm thấy lần chuyển giao ứng với đối số --ancestry-path %s"
+
msgid "--unpacked=<packfile> no longer supported"
msgstr "--unpacked=<packfile> không còn được hỗ trợ nữa"
+#, c-format
+msgid "invalid option '%s' in --stdin mode"
+msgstr "tùy chá»n không hợp lệ '%s' trong chế Ä‘á»™ --stdin"
+
msgid "your current branch appears to be broken"
msgstr "nhánh hiện tại của bạn có vẻ nhÆ° bị há»ng"
#, c-format
msgid "your current branch '%s' does not have any commits yet"
-msgstr "nhánh hiện tại của bạn “%s†không có một lần chuyển giao nào cả"
+msgstr "nhánh hiện tại của bạn '%s' không có một lần chuyển giao nào cả"
msgid "object filtering requires --objects"
msgstr "lá»c đối tượng yêu cầu --objects"
@@ -18848,13 +19797,210 @@ msgstr "-L vẫn chưa hỗ trợ định dạng khác biệt nào ngoài -p và
msgid "cannot create async thread: %s"
msgstr "không thể tạo tuyến trình async: %s"
+#, c-format
+msgid "'%s' does not exist"
+msgstr "\"%s\" không tồn tại"
+
+#, c-format
+msgid "could not switch to '%s'"
+msgstr "không thể chuyển đến '%s'"
+
+msgid "need a working directory"
+msgstr "cần một thư mục làm việc"
+
+msgid "Scalar enlistments require a worktree"
+msgstr "'Scalar enlistments' cần một cây làm việc"
+
+#, c-format
+msgid "could not configure %s=%s"
+msgstr "không thể đóng cấu hình %s=%s"
+
+msgid "could not configure log.excludeDecoration"
+msgstr "không thể cấu hình log.excludeDecoration"
+
+msgid "could not add enlistment"
+msgstr "không thể thêm enlistment"
+
+msgid "could not set recommended config"
+msgstr "không thể đặt cấu hình đỠnghị"
+
+msgid "could not turn on maintenance"
+msgstr "không thể bật chế độ bảo trì"
+
+msgid "could not start the FSMonitor daemon"
+msgstr "không thể khởi chạy tiến trình ná»n FSMonitor"
+
+msgid "could not turn off maintenance"
+msgstr "không thể tắt chế độ bảo trì"
+
+msgid "could not remove enlistment"
+msgstr "không thể bỠenlistment"
+
+#, c-format
+msgid "remote HEAD is not a branch: '%.*s'"
+msgstr "HEAD của máy chủ không phải một nhánh: '%.*s'"
+
+msgid "failed to get default branch name from remote; using local default"
+msgstr "gặp lỗi khi lấy tên nhánh mặc định từ máy chủ; sử dụng mặc định nội bộ"
+
+msgid "failed to get default branch name"
+msgstr "gặp lỗi khi lấy tên nhánh mặc định"
+
+msgid "failed to unregister repository"
+msgstr "gặp lỗi khi hủy đăng ký kho chứa"
+
+msgid "failed to stop the FSMonitor daemon"
+msgstr "Gặp lá»—i khi dừng tiến trình ná»n FSMonitor"
+
+msgid "failed to delete enlistment directory"
+msgstr "gặp lỗi khi xóa thư mục enlistment"
+
+msgid "branch to checkout after clone"
+msgstr "nhánh để checkout sau khi nhân bản"
+
+msgid "when cloning, create full working directory"
+msgstr "khi nhân bản, tạo đầy đủ thư mục làm việc"
+
+msgid "only download metadata for the branch that will be checked out"
+msgstr "chỉ siêu dữ liệu tải vỠcho nhánh mà sẽ được checkout"
+
+msgid "create repository within 'src' directory"
+msgstr "tạo kho chứa trong thư mục 'src'"
+
+msgid ""
+"scalar clone [--single-branch] [--branch <main-branch>] [--full-clone]\n"
+"\t[--[no-]src] <url> [<enlistment>]"
+msgstr ""
+"scalar clone [--single-branch] [--branch <nhánh-chính>] [--full-clone]\n"
+"\t[--[no-]src] <url> [<enlistment>]"
+
+#, c-format
+msgid "cannot deduce worktree name from '%s'"
+msgstr "không thể suy diễn tên cây làm việc từ '%s'"
+
+#, c-format
+msgid "directory '%s' exists already"
+msgstr "thư mục '%s' đã sẵn có"
+
+#, c-format
+msgid "failed to get default branch for '%s'"
+msgstr "gặp lỗi khi lấy nhánh mặc định cho '%s'"
+
+#, c-format
+msgid "could not configure remote in '%s'"
+msgstr "không thể cấu hình máy chủ trong '%s'"
+
+#, c-format
+msgid "could not configure '%s'"
+msgstr "không thể cấu hình '%s'"
+
+msgid "partial clone failed; attempting full clone"
+msgstr "nhân bản từng phần gặp lỗi; đang cố thử nhân bản đầy đủ"
+
+msgid "could not configure for full clone"
+msgstr "không thể cấu hình cho nhân bản đầy đủ"
+
+msgid "scalar diagnose [<enlistment>]"
+msgstr "scalar diagnose [<enlistment>]"
+
+msgid "`scalar list` does not take arguments"
+msgstr "`scalar list` không nhận các tham số"
+
+msgid "scalar register [<enlistment>]"
+msgstr "scalar register [<enlistment>]"
+
+msgid "reconfigure all registered enlistments"
+msgstr "cấu hình má»i enlistments đã đăng ký"
+
+msgid "scalar reconfigure [--all | <enlistment>]"
+msgstr "scalar reconfigure [--all | <enlistment>]"
+
+msgid "--all or <enlistment>, but not both"
+msgstr "--all hoặc <enlistment>, không thể là cả hai"
+
+#, c-format
+msgid "could not remove stale scalar.repo '%s'"
+msgstr "không thể xoá scalar.repo đã cũ '%s'"
+
+#, c-format
+msgid "removed stale scalar.repo '%s'"
+msgstr "đã xoá scalar.repo đã cũ '%s'"
+
+#, c-format
+msgid "repository at '%s' has different owner"
+msgstr "kho '%s' thuá»™c quyá»n sở hữu của ngÆ°á»i khác"
+
+#, c-format
+msgid "repository at '%s' has a format issue"
+msgstr "kho '%s' có vấn đỠđịnh dạng"
+
+#, c-format
+msgid "repository not found in '%s'"
+msgstr "không tìm thấy kho trong '%s'"
+
+#, c-format
+msgid ""
+"to unregister this repository from Scalar, run\n"
+"\tgit config --global --unset --fixed-value scalar.repo \"%s\""
+msgstr ""
+"để bỠđăng ký kho này khá»i Scalar, chạy lệnh\n"
+"\tgit config --global --unset --fixed-value scalar.repo \"%s\""
+
+msgid ""
+"scalar run <task> [<enlistment>]\n"
+"Tasks:\n"
+msgstr ""
+"scalar run <task> [<enlistment>]\n"
+"Nhiệm vụ:\n"
+
+#, c-format
+msgid "no such task: '%s'"
+msgstr "không có nhiệm vụ nào như thế: '%s'"
+
+msgid "scalar unregister [<enlistment>]"
+msgstr "scalar unregister [<enlistment>]"
+
+msgid "scalar delete <enlistment>"
+msgstr "scalar delete <enlistment>"
+
+msgid "refusing to delete current working directory"
+msgstr "từ chối gỡ bỠthư mục làm việc hiện tại"
+
+msgid "include Git version"
+msgstr "bao gồm phiên bản Git"
+
+msgid "include Git's build options"
+msgstr "bao gồm các tùy chá»n biên dịch của Git"
+
+msgid "scalar verbose [-v | --verbose] [--build-options]"
+msgstr "scalar verbose [-v | --verbose] [--build-options]"
+
+msgid "-C requires a <directory>"
+msgstr "-C cần một <thư_mục>"
+
+#, c-format
+msgid "could not change to '%s'"
+msgstr "không thể chuyển sang '%s'"
+
+msgid "-c requires a <key>=<value> argument"
+msgstr "-c cần một tham số <key>=<value>"
+
+msgid ""
+"scalar [-C <directory>] [-c <key>=<value>] <command> [<options>]\n"
+"\n"
+"Commands:\n"
+msgstr ""
+"scalar [-C </thÆ°/mục/>] [-c <khóa>=<giá trị>] <lệnh> [<các tùy chá»n>]\n"
+"\n"
+"Các lệnh:\n"
+
msgid "unexpected flush packet while reading remote unpack status"
msgstr ""
-"gặp gói flush không cần trong khi Ä‘á»c tình trạng giải nén gói trên máy chủ"
+"gặp gói flush bất thÆ°á»ng trong khi Ä‘á»c tình trạng giải nén gói trên máy chủ"
#, c-format
msgid "unable to parse remote unpack status: %s"
-msgstr "không thể phân tích tình trạng unpack máy chủ: %s"
+msgstr "không thể Ä‘á»c tình trạng unpack máy chủ: %s"
#, c-format
msgid "remote unpack failed: %s"
@@ -18890,11 +20036,11 @@ msgstr "kết thúc nhận không há»— trợ các tùy chá»n của lệnh push"
#, c-format
msgid "invalid commit message cleanup mode '%s'"
-msgstr "chế Ä‘á»™ dá»n dẹp ghi chú các lần chuyển giao không hợp lệ “%sâ€"
+msgstr "chế Ä‘á»™ dá»n dẹp ghi chú các lần chuyển giao không hợp lệ '%s'"
#, c-format
msgid "could not delete '%s'"
-msgstr "không thể xóa bỠ“%sâ€"
+msgstr "không thể xóa bỠ'%s'"
msgid "revert"
msgstr "hoàn nguyên"
@@ -18910,11 +20056,25 @@ msgid "unknown action: %d"
msgstr "không nhận ra thao tác: %d"
msgid ""
+"Resolve all conflicts manually, mark them as resolved with\n"
+"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
+"You can instead skip this commit: run \"git rebase --skip\".\n"
+"To abort and get back to the state before \"git rebase\", run \"git rebase --"
+"abort\"."
+msgstr ""
+"Giải quyết vấn đỠnày thủ công, hãy đanh dấu chúng đã được giải quyết bằng\n"
+"hãy chạy lệnh \"git add/rm <các_tập tin_xung_đột>\", sau đó chạy \"git "
+"rebase --continue\".\n"
+"Bạn có thể bỠqua bản vá, chạy \"git rebase --skip\".\n"
+"Äể huá»· bá» và quay trở lại trạng thái trÆ°á»›c \"git rebase\", chạy \"git rebase "
+"--abort\"."
+
+msgid ""
"after resolving the conflicts, mark the corrected paths\n"
"with 'git add <paths>' or 'git rm <paths>'"
msgstr ""
"sau khi giải quyết các xung Ä‘á»™t, đánh dấu Ä‘Æ°á»ng dẫn đã sá»­a\n"
-"vá»›i lệnh “git add </các/Ä‘Æ°á»ng/dẫn>†hoặc “git rm </các/Ä‘Æ°á»ng/dẫn>â€"
+"vá»›i lệnh 'git add </các/Ä‘Æ°á»ng/dẫn>' hoặc 'git rm </các/Ä‘Æ°á»ng/dẫn>'"
msgid ""
"After resolving the conflicts, mark them with\n"
@@ -18928,7 +20088,7 @@ msgstr ""
"\"git add/rm <pathspec>\", sai đó chạy\n"
"\"git cherry-pick --continue\".\n"
"Bạn có thể bỠqua lần chuyển giao này với \"git cherry-pick --skip\".\n"
-"Äể bãi bá» và quay trở lại trạng thái trÆ°á»›c khi \"git cherry-pick\",\n"
+"Äể huá»· bá» và quay trở lại trạng thái trÆ°á»›c khi \"git cherry-pick\",\n"
"chạy \"git cherry-pick --abort\"."
msgid ""
@@ -18943,24 +20103,20 @@ msgstr ""
"\"git add/rm <đặc_tả_Ä‘Æ°á»ng_dẫn_xung_Ä‘á»™t>\", sau đó chạy\n"
"\"git revert --continue\".\n"
"Bạn có thể bỠqua lần chuyển giao này với \"git rebase --skip\".\n"
-"Äể bãi bá» và quay trở lại trạng thái trÆ°á»›c \"git revert\",\n"
+"Äể huá»· bá» và quay trở lại trạng thái trÆ°á»›c \"git revert\",\n"
"chạy \"git revert --abort\"."
#, c-format
msgid "could not lock '%s'"
-msgstr "không thể khóa “%sâ€"
-
-#, c-format
-msgid "could not write to '%s'"
-msgstr "không thể ghi vào “%sâ€"
+msgstr "không thể khóa '%s'"
#, c-format
msgid "could not write eol to '%s'"
-msgstr "không thể ghi eol vào “%sâ€"
+msgstr "không thể ghi eol vào '%s'"
#, c-format
msgid "failed to finalize '%s'"
-msgstr "gặp lá»—i khi hoàn thành “%sâ€"
+msgstr "gặp lỗi khi hoàn thành '%s'"
#, c-format
msgid "your local changes would be overwritten by %s."
@@ -18969,16 +20125,12 @@ msgstr "các thay đổi ná»™i bá»™ của bạn có thể bị ghi đè bởi lá
msgid "commit your changes or stash them to proceed."
msgstr "chuyển giao các thay đổi của bạn hay tạm cất (stash) chúng để xử lý."
-#, c-format
-msgid "%s: fast-forward"
-msgstr "%s: chuyển-tiếp-nhanh"
-
#. TRANSLATORS: %s will be "revert", "cherry-pick" or
#. "rebase".
#.
#, c-format
msgid "%s: Unable to write new index file"
-msgstr "%s: Không thể ghi tập tin lưu bảng mục lục mới"
+msgstr "%s: Không thể ghi tập tin chỉ mục mới"
msgid "unable to update cache tree"
msgstr "không thể cập nhật cây bộ nhớ đệm"
@@ -18988,33 +20140,33 @@ msgstr "không thể phân giải lần chuyển giao HEAD"
#, c-format
msgid "no key present in '%.*s'"
-msgstr "không có khóa hiện diện trong “%.*sâ€"
+msgstr "không có khóa hiện diện trong '%.*s'"
#, c-format
msgid "unable to dequote value of '%s'"
-msgstr "không thể giải trích dẫn giá trị của “%sâ€"
+msgstr "không thể giải trích dẫn giá trị của '%s'"
msgid "'GIT_AUTHOR_NAME' already given"
-msgstr "“GIT_AUTHOR_NAME†đã sẵn đưa ra rồi"
+msgstr "'GIT_AUTHOR_NAME' đã sẵn đưa ra rồi"
msgid "'GIT_AUTHOR_EMAIL' already given"
-msgstr "“GIT_AUTHOR_EMAIL†đã sẵn đưa ra rồi"
+msgstr "'GIT_AUTHOR_EMAIL' đã sẵn đưa ra rồi"
msgid "'GIT_AUTHOR_DATE' already given"
-msgstr "“GIT_AUTHOR_DATE†đã sẵn đưa ra rồi"
+msgstr "'GIT_AUTHOR_DATE' đã sẵn đưa ra rồi"
#, c-format
msgid "unknown variable '%s'"
-msgstr "không hiểu biến “%sâ€"
+msgstr "không hiểu biến '%s'"
msgid "missing 'GIT_AUTHOR_NAME'"
-msgstr "thiếu “GIT_AUTHOR_NAMEâ€"
+msgstr "thiếu 'GIT_AUTHOR_NAME'"
msgid "missing 'GIT_AUTHOR_EMAIL'"
-msgstr "thiếu “GIT_AUTHOR_EMAILâ€"
+msgstr "thiếu 'GIT_AUTHOR_EMAIL'"
msgid "missing 'GIT_AUTHOR_DATE'"
-msgstr "thiếu “GIT_AUTHOR_DATEâ€"
+msgstr "thiếu 'GIT_AUTHOR_DATE'"
#, c-format
msgid ""
@@ -19045,7 +20197,7 @@ msgstr ""
" git rebase --continue\n"
msgid "'prepare-commit-msg' hook failed"
-msgstr "móc “prepare-commit-msg†bị lỗi"
+msgstr "móc 'prepare-commit-msg' bị lỗi"
msgid ""
"Your name and email address were configured automatically based\n"
@@ -19108,8 +20260,7 @@ msgid "couldn't look up newly created commit"
msgstr "không thể tìm thấy lần chuyển giao mới hơn đã được tạo"
msgid "could not parse newly created commit"
-msgstr ""
-"không thể phân tích cú pháp của đối tượng chuyển giao mới hơn đã được tạo"
+msgstr "không hiểu cú pháp của đối tượng chuyển giao mới hơn đã được tạo"
msgid "unable to resolve HEAD after creating commit"
msgstr "không thể phân giải HEAD sau khi tạo lần chuyển giao"
@@ -19121,37 +20272,33 @@ msgid " (root-commit)"
msgstr " (root-commit)"
msgid "could not parse HEAD"
-msgstr "không thể phân tích HEAD"
+msgstr "không thể Ä‘á»c HEAD"
#, c-format
msgid "HEAD %s is not a commit!"
msgstr "HEAD %s không phải là một lần chuyển giao!"
msgid "unable to parse commit author"
-msgstr "không thể phân tích tác giả của lần chuyển giao"
+msgstr "không thể Ä‘á»c tác giả của lần chuyển giao"
#, c-format
msgid "unable to read commit message from '%s'"
-msgstr "không thể Ä‘á»c phần chú thích (message) từ “%sâ€"
+msgstr "không thể Ä‘á»c phần chú thích từ '%s'"
#, c-format
msgid "invalid author identity '%s'"
-msgstr "định danh tác giả không hợp lệ “%sâ€"
+msgstr "danh tính tác giả không hợp lệ '%s'"
msgid "corrupt author: missing date information"
-msgstr "tác giả sai há»ng: thiếu thông tin ngày tháng"
+msgstr "há»ng tên tác giả: thiếu thông tin ngày tháng"
#, c-format
msgid "could not update %s"
msgstr "không thể cập nhật %s"
#, c-format
-msgid "could not parse commit %s"
-msgstr "không thể phân tích lần chuyển giao %s"
-
-#, c-format
msgid "could not parse parent commit %s"
-msgstr "không thể phân tích lần chuyển giao cha mẹ “%sâ€"
+msgstr "không thể Ä‘á»c lần chuyển giao mẹ '%s'"
#, c-format
msgid "unknown command: %d"
@@ -19162,14 +20309,14 @@ msgstr "Äây là chú thích cho lần chuyển giao thứ nhất:"
#, c-format
msgid "This is the commit message #%d:"
-msgstr "Äây là chú thích cho lần chuyển giao thứ #%d:"
+msgstr "Äây là chú thích cho lần chuyển giao thứ %d:"
msgid "The 1st commit message will be skipped:"
msgstr "Chú thích cho lần chuyển giao thứ nhất sẽ bị bỠqua:"
#, c-format
msgid "The commit message #%d will be skipped:"
-msgstr "Chú thích cho lần chuyển giao thứ #%d sẽ bị bỠqua:"
+msgstr "Chú thích cho lần chuyển giao thứ %d sẽ bị bỠqua:"
#, c-format
msgid "This is a combination of %d commits."
@@ -19177,7 +20324,7 @@ msgstr "Äây là tổ hợp của %d lần chuyển giao."
#, c-format
msgid "cannot write '%s'"
-msgstr "không thể ghi “%sâ€"
+msgstr "không thể ghi '%s'"
msgid "need a HEAD to fixup"
msgstr "cần một HEAD để sửa"
@@ -19186,21 +20333,22 @@ msgid "could not read HEAD"
msgstr "không thể Ä‘á»c HEAD"
msgid "could not read HEAD's commit message"
-msgstr "không thể Ä‘á»c phần chú thích (message) của HEAD"
+msgstr "không thể Ä‘á»c phần chú thích của HEAD"
#, c-format
msgid "could not read commit message of %s"
-msgstr "không thể Ä‘á»c phần chú thích (message) của %s"
+msgstr "không thể Ä‘á»c phần chú thích của %s"
msgid "your index file is unmerged."
-msgstr "tập tin lưu mục lục của bạn không được hòa trộn."
+msgstr "tập tin chỉ mục của bạn không được hòa trộn."
msgid "cannot fixup root commit"
msgstr "không thể sửa chữa lần chuyển giao gốc"
#, c-format
msgid "commit %s is a merge but no -m option was given."
-msgstr "lần chuyển giao %s là má»™t lần hòa trá»™n nhÆ°ng không Ä‘Æ°a ra tùy chá»n -m."
+msgstr ""
+"lần chuyển giao %s là má»™t lần hòa trá»™n nhÆ°ng lệnh không có tùy chá»n -m."
#, c-format
msgid "commit %s does not have parent %d"
@@ -19214,35 +20362,43 @@ msgstr "không thể lấy ghi chú lần chuyển giao cho %s"
#. "revert" or "pick", the second %s a SHA1.
#, c-format
msgid "%s: cannot parse parent commit %s"
-msgstr "%s: không thể phân tích lần chuyển giao mẹ của %s"
-
-#, c-format
-msgid "could not rename '%s' to '%s'"
-msgstr "không thể đổi tên “%s†thành “%sâ€"
+msgstr "%s: không thể Ä‘á»c lần chuyển giao mẹ của %s"
#, c-format
msgid "could not revert %s... %s"
-msgstr "không thể hoàn nguyên %s… %s"
+msgstr "không thể hoàn nguyên %s... %s"
#, c-format
msgid "could not apply %s... %s"
-msgstr "không thể áp dụng miếng vá %s… %s"
+msgstr "không thể áp dụng bản vá %s... %s"
#, c-format
msgid "dropping %s %s -- patch contents already upstream\n"
-msgstr "xóa %s %s -- vá nội dung thượng nguồn đã có\n"
+msgstr "xóa %s %s -- thượng nguồn đã có bản vá\n"
#, c-format
msgid "git %s: failed to read the index"
-msgstr "git %s: gặp lá»—i Ä‘á»c bảng mục lục"
+msgstr "git %s: gặp lá»—i khi Ä‘á»c chỉ mục"
#, c-format
msgid "git %s: failed to refresh the index"
-msgstr "git %s: gặp lỗi khi làm tươi mới bảng mục lục"
+msgstr "git %s: gặp lỗi khi làm mới chỉ mục"
#, c-format
-msgid "%s does not accept arguments: '%s'"
-msgstr "%s không nhận các đối số: “%sâ€"
+msgid "'%s' is not a valid label"
+msgstr "'%s' không phải một nhãn hợp lệ"
+
+#, c-format
+msgid "'%s' is not a valid refname"
+msgstr "'%s' không phải tên tham chiếu hợp lệ"
+
+#, c-format
+msgid "update-ref requires a fully qualified refname e.g. refs/heads/%s"
+msgstr "update-ref yêu cầu tên tham chiếu đầy đủ v.d. refs/heads/%s"
+
+#, c-format
+msgid "invalid command '%.*s'"
+msgstr "lệnh không hợp lệ '%.*s'"
#, c-format
msgid "missing arguments for %s"
@@ -19250,7 +20406,7 @@ msgstr "thiếu đối số cho %s"
#, c-format
msgid "could not parse '%s'"
-msgstr "không thể phân tích cú pháp “%sâ€"
+msgstr "không thể Ä‘á»c '%s'"
#, c-format
msgid "invalid line %d: %.*s"
@@ -19258,7 +20414,7 @@ msgstr "dòng không hợp lệ %d: %.*s"
#, c-format
msgid "cannot '%s' without a previous commit"
-msgstr "không thể “%s†thể mà không có lần chuyển giao kế trước"
+msgstr "không thể '%s' thể mà không có lần chuyển giao kế trước"
msgid "cancelling a cherry picking in progress"
msgstr "đang hủy bỠthao tác cherry pick đang thực hiện"
@@ -19267,30 +20423,30 @@ msgid "cancelling a revert in progress"
msgstr "đang hủy bỠcác thao tác hoàn nguyên đang thực hiện"
msgid "please fix this using 'git rebase --edit-todo'."
-msgstr "vui lòng sá»­a lá»—i này bằng cách dùng “git rebase --edit-todoâ€."
+msgstr "vui lòng sửa lỗi này bằng cách dùng 'git rebase --edit-todo'."
#, c-format
msgid "unusable instruction sheet: '%s'"
-msgstr "bảng chỉ thị không thể dùng được: %s"
+msgstr "bảng chỉ thị không dùng được: %s"
msgid "no commits parsed."
-msgstr "không có lần chuyển giao nào được phân tích."
+msgstr "không Ä‘á»c được lần chuyển giao nào."
msgid "cannot cherry-pick during a revert."
-msgstr "không thể cherry-pick trong khi hoàn nguyên."
+msgstr "không thể cherry-pick trong khi đang hoàn nguyên."
msgid "cannot revert during a cherry-pick."
-msgstr "không thể thực hiện việc hoàn nguyên trong khi đang cherry-pick."
+msgstr "không thể hoàn nguyên trong khi đang cherry-pick."
msgid "unusable squash-onto"
-msgstr "squash-onto không dùng được"
+msgstr "không dùng được squash-onto"
#, c-format
msgid "malformed options sheet: '%s'"
-msgstr "bảng tùy chá»n dị hình: “%sâ€"
+msgstr "bảng tùy chá»n sai quy cách: '%s'"
msgid "empty commit set passed"
-msgstr "lần chuyển giao trống rỗng đặt là hợp quy cách"
+msgstr "được chỉ định một lần chuyển giao trống rỗng"
msgid "revert is already in progress"
msgstr "có thao tác hoàn nguyên đang được thực hiện"
@@ -19300,7 +20456,7 @@ msgid "try \"git revert (--continue | %s--abort | --quit)\""
msgstr "hãy thử \"git revert (--continue | %s--abort | --quit)\""
msgid "cherry-pick is already in progress"
-msgstr "có thao tác “cherry-pick†đang được thực hiện"
+msgstr "có thao tác cherry-pick đang được thực hiện"
#, c-format
msgid "try \"git cherry-pick (--continue | %s--abort | --quit)\""
@@ -19308,62 +20464,57 @@ msgstr "hãy thử \"git cherry-pick (--continue | %s--abort | --quit)\""
#, c-format
msgid "could not create sequencer directory '%s'"
-msgstr "không thể tạo thÆ° mục xếp dãy “%sâ€"
-
-msgid "could not lock HEAD"
-msgstr "không thể khóa HEAD"
+msgstr "không thể tạo thư mục sequencer '%s'"
msgid "no cherry-pick or revert in progress"
-msgstr "không cherry-pick hay hoàn nguyên trong tiến trình"
+msgstr "không có cherry-pick hay hoàn nguyên đang được thực hiện"
msgid "cannot resolve HEAD"
msgstr "không thể phân giải HEAD"
msgid "cannot abort from a branch yet to be born"
-msgstr "không thể hủy bỠtừ một nhánh mà nó còn chưa được tạo ra"
+msgstr "không thể hủy bỠtừ một nhánh chưa được tạo ra"
#, c-format
msgid "cannot read '%s': %s"
-msgstr "không thể Ä‘á»c “%sâ€: %s"
+msgstr "không thể Ä‘á»c '%s': %s"
msgid "unexpected end of file"
msgstr "gặp kết thúc tập tin đột xuất"
#, c-format
msgid "stored pre-cherry-pick HEAD file '%s' is corrupt"
-msgstr "tập tin HEAD “pre-cherry-pick†đã lÆ°u “%s†bị há»ng"
+msgstr "tập tin HEAD trÆ°á»›c cherry-pick '%s' bị há»ng"
msgid "You seem to have moved HEAD. Not rewinding, check your HEAD!"
-msgstr ""
-"Bạn có lẽ đã có HEAD đã bị di chuyển đi, Không thể tua, kiểm tra HEAD của "
-"bạn!"
+msgstr "Bạn có lẽ đã di chuyển HEAD, Không thể quay lại, hãy kiểm tra HEAD!"
msgid "no revert in progress"
-msgstr "không có tiến trình hoàn nguyên nào"
+msgstr "không có hoàn nguyên nào đang được thực hiện"
msgid "no cherry-pick in progress"
msgstr "không có cherry-pick đang được thực hiện"
msgid "failed to skip the commit"
-msgstr "gặp lỗi khi bỠqua đối tượng chuyển giao"
+msgstr "gặp lỗi khi bỠqua lần chuyển giao"
msgid "there is nothing to skip"
-msgstr "ở đây không có gì để mà bỠqua cả"
+msgstr "ở đây không có gì để bỠqua"
#, c-format
msgid ""
"have you committed already?\n"
"try \"git %s --continue\""
msgstr ""
-"bạn đã sẵn sàng chuyển giao chưa?\n"
-"thá»­ \"git %s --continue\""
+"hình như bạn đã bắt đầu chuyển giao rồi?\n"
+"thử chạy \"git %s --continue\""
msgid "cannot read HEAD"
msgstr "không thể Ä‘á»c HEAD"
#, c-format
msgid "unable to copy '%s' to '%s'"
-msgstr "không thể chép “%s†sang “%sâ€"
+msgstr "không thể sao chép '%s' sang '%s'"
#, c-format
msgid ""
@@ -19375,21 +20526,21 @@ msgid ""
"\n"
" git rebase --continue\n"
msgstr ""
-"Bạn có thể tu bổ lần chuyển giao ngay bây giỠbằng:\n"
+"Bạn có thể tu bổ lần chuyển giao bằng:\n"
"\n"
" git commit --amend %s\n"
"\n"
-"Một khi đã hài lòng với những thay đổi của mình, thì chạy:\n"
+"Sau khi hài lòng với những thay đổi của mình, hãy chạy:\n"
"\n"
" git rebase --continue\n"
#, c-format
msgid "Could not apply %s... %.*s"
-msgstr "Không thể áp dụng %s… %.*s"
+msgstr "Không thể áp dụng %s... %.*s"
#, c-format
msgid "Could not merge %.*s"
-msgstr "Không hòa trộn %.*s"
+msgstr "Không thể hòa trộn %.*s"
#, c-format
msgid "Executing: %s\n"
@@ -19404,33 +20555,37 @@ msgid ""
"\n"
msgstr ""
"thực thi gặp lỗi: %s\n"
-"%sBạn có thể sửa các trục trặc, và sau đó chạy lệnh\n"
+"%sBạn có thể sửa lại, và sau đó chạy lệnh\n"
"\n"
" git rebase --continue\n"
"\n"
-msgid "and made changes to the index and/or the working tree\n"
-msgstr "và tạo các thay đổi bảng mục lục và/hay cây làm việc\n"
+msgid "and made changes to the index and/or the working tree.\n"
+msgstr "và thay đổi chỉ mục hay cây làm việc\n"
#, c-format
msgid ""
"execution succeeded: %s\n"
-"but left changes to the index and/or the working tree\n"
+"but left changes to the index and/or the working tree.\n"
"Commit or stash your changes, and then run\n"
"\n"
" git rebase --continue\n"
"\n"
msgstr ""
"thực thi thành công: %s\n"
-"nhưng còn các thay đổi trong mục lục và/hoặc cây làm việc\n"
-"Chuyển giao hay tạm cất các thay đổi này đi, rồi chạy\n"
+"nhưng còn các thay đổi trong chỉ mục hay cây làm việc.\n"
+"Hãy chuyển giao hay tạm cất các thay đổi này, rồi chạy\n"
"\n"
" git rebase --continue\n"
"\n"
#, c-format
msgid "illegal label name: '%.*s'"
-msgstr "tên nhãn dị hình: “%.*sâ€"
+msgstr "tên nhãn không hợp lệ: '%.*s'"
+
+#, c-format
+msgid "could not resolve '%s'"
+msgstr "không thể phân giải '%s'"
msgid "writing fake root commit"
msgstr "ghi lần chuyển giao gốc giả"
@@ -19438,45 +20593,63 @@ msgstr "ghi lần chuyển giao gốc giả"
msgid "writing squash-onto"
msgstr "Ä‘ang ghi squash-onto"
-#, c-format
-msgid "could not resolve '%s'"
-msgstr "không thể phân giải “%sâ€"
-
msgid "cannot merge without a current revision"
-msgstr "không thể hòa trộn mà không có một điểm xét duyệt hiện tại"
+msgstr "không thể hòa trộn mà không có điểm hiệu chỉnh hiện tại"
#, c-format
msgid "unable to parse '%.*s'"
-msgstr "không thể phân tích “%.*sâ€"
+msgstr "không thể Ä‘á»c '%.*s'"
#, c-format
msgid "nothing to merge: '%.*s'"
-msgstr "chẳng có gì để hòa trá»™n: “%.*sâ€"
+msgstr "chẳng có gì để hòa trộn: '%.*s'"
msgid "octopus merge cannot be executed on top of a [new root]"
-msgstr "hòa trộn octopus không thể được thực thi trên đỉnh của một [new root]"
+msgstr ""
+"hòa trộn kiểu bạch tuộc không thể được thực thi trên đỉnh của [new root]"
#, c-format
msgid "could not get commit message of '%s'"
-msgstr "không thể lấy chú thích của lần chuyển giao của “%sâ€"
+msgstr "không thể lấy chú thích của lần chuyển giao của '%s'"
#, c-format
msgid "could not even attempt to merge '%.*s'"
-msgstr "không thể ngay cả khi thá»­ hòa trá»™n “%.*sâ€"
+msgstr "hoàn toàn không thể hòa trộn '%.*s'"
msgid "merge: Unable to write new index file"
-msgstr "merge: Không thể ghi tập tin lưu bảng mục lục mới"
+msgstr "merge: Không thể ghi tập tin chỉ mục mới"
+
+#, c-format
+msgid ""
+"another 'rebase' process appears to be running; '%s.lock' already exists"
+msgstr "Một lần cải tổ khác đang diễn ra; %s.lock đã tồn tại"
+
+#, c-format
+msgid ""
+"Updated the following refs with %s:\n"
+"%s"
+msgstr ""
+"Äã cập nhật các tham chiếu sau thành %s:\n"
+"%s"
+
+#, c-format
+msgid ""
+"Failed to update the following refs with %s:\n"
+"%s"
+msgstr ""
+"Không thể cập nhật các tham chiếu sau thành %s:\n"
+"%s"
msgid "Cannot autostash"
msgstr "Không thể autostash"
#, c-format
msgid "Unexpected stash response: '%s'"
-msgstr "Gặp đáp ứng stash không cần: “%sâ€"
+msgstr "Gặp phản hồi stash bất thÆ°á»ng '%s'"
#, c-format
msgid "Could not create directory for '%s'"
-msgstr "Không thể tạo thÆ° mục cho “%sâ€"
+msgstr "Không thể tạo thư mục cho '%s'"
#, c-format
msgid "Created autostash: %s\n"
@@ -19491,7 +20664,7 @@ msgstr "Äã áp dụng autostash.\n"
#, c-format
msgid "cannot store %s"
-msgstr "không thá»­ lÆ°u “%sâ€"
+msgstr "không thể lưu '%s'"
#, c-format
msgid ""
@@ -19500,16 +20673,19 @@ msgid ""
"You can run \"git stash pop\" or \"git stash drop\" at any time.\n"
msgstr ""
"%s\n"
-"Các thay đổi của bạn an toàn trong stash (tạm cất đi).\n"
+"Các thay đổi của bạn an toàn trong tạm cất.\n"
"Bạn có thể chạy lệnh \"git stash pop\" hay \"git stash drop\" bất kỳ lúc "
"nào.\n"
msgid "Applying autostash resulted in conflicts."
-msgstr "Ãp dụng autostash có hiệu quả trong các xung Ä‘á»™t."
+msgstr "Ãp dụng autostash đã gây nên xung Ä‘á»™t."
msgid "Autostash exists; creating a new stash entry."
msgstr "Autostash đã sẵn có; nên tạo một mục stash mới."
+msgid "autostash reference is a symref"
+msgstr "tham chiếu autostash là symref"
+
msgid "could not detach HEAD"
msgstr "không thể tách rá»i HEAD"
@@ -19535,19 +20711,19 @@ msgstr ""
"Không thể thực thi lệnh todo\n"
"\n"
" %.*s\n"
-"Nó đã được lên lịch lại: Äể sá»­a lệnh trÆ°á»›c khi tiếp tục, vui lòng\n"
+"Lệnh đã được lên lịch lại. Äể sá»­a lệnh trÆ°á»›c khi tiếp tục, vui lòng\n"
"sửa danh sách todo trước:\n"
"\n"
" git rebase --edit-todo\n"
" git rebase --continue\n"
#, c-format
-msgid "Rebasing (%d/%d)%s"
-msgstr "Äang cải tổ (%d/%d)%s"
+msgid "Stopped at %s... %.*s\n"
+msgstr "Dừng lại ở %s... %.*s\n"
#, c-format
-msgid "Stopped at %s... %.*s\n"
-msgstr "Dừng lại ở %s… %.*s\n"
+msgid "Rebasing (%d/%d)%s"
+msgstr "Äang cải tổ (%d/%d)%s"
#, c-format
msgid "unknown command %d"
@@ -19557,7 +20733,7 @@ msgid "could not read orig-head"
msgstr "không thể Ä‘á»c orig-head"
msgid "could not read 'onto'"
-msgstr "không thể Ä‘á»c “ontoâ€."
+msgstr "không thể Ä‘á»c 'onto'."
#, c-format
msgid "could not update HEAD to %s"
@@ -19571,15 +20747,15 @@ msgid "cannot rebase: You have unstaged changes."
msgstr "không thể cải tổ: Bạn có các thay đổi chưa được đưa lên bệ phóng."
msgid "cannot amend non-existing commit"
-msgstr "không thể tu bỠmột lần chuyển giao không tồn tại"
+msgstr "không thể tu sửa lần chuyển giao không tồn tại"
#, c-format
msgid "invalid file: '%s'"
-msgstr "tập tin không hợp lệ: “%sâ€"
+msgstr "tập tin không hợp lệ: '%s'"
#, c-format
msgid "invalid contents: '%s'"
-msgstr "ná»™i dung không hợp lệ: “%sâ€"
+msgstr "nội dung không hợp lệ: '%s'"
msgid ""
"\n"
@@ -19588,11 +20764,11 @@ msgid ""
msgstr ""
"\n"
"Bạn có các thay đổi chưa chuyển giao trong thư mục làm việc. Vui lòng\n"
-"chuyển giao chúng trước và sau đó chạy lệnh “git rebase --continue†lần nữa."
+"chuyển giao chúng trước rồi sau đó chạy lệnh 'git rebase --continue'."
#, c-format
msgid "could not write file: '%s'"
-msgstr "không thể ghi tập tin: “%sâ€"
+msgstr "không thể ghi tập tin: '%s'"
msgid "could not remove CHERRY_PICK_HEAD"
msgstr "không thể xóa bỠCHERRY_PICK_HEAD"
@@ -19602,14 +20778,14 @@ msgstr "không thể chuyển giao các thay đổi đã đưa lên bệ phóng.
#, c-format
msgid "%s: can't cherry-pick a %s"
-msgstr "%s: không thể cherry-pick một %s"
+msgstr "%s: không thể cherry-pick %s"
#, c-format
msgid "%s: bad revision"
-msgstr "%s: điểm xét duyệt sai"
+msgstr "%s: điểm hiệu chỉnh không hợp lệ"
msgid "can't revert as initial commit"
-msgstr "không thể hoàn nguyên một lần chuyển giao khởi tạo"
+msgstr "không thể hoàn nguyên lần chuyển giao khởi tạo"
#, c-format
msgid "skipped previously applied commit %s"
@@ -19629,14 +20805,18 @@ msgid "nothing to do"
msgstr "không có gì để làm"
msgid "could not skip unnecessary pick commands"
-msgstr "không thể bỠqua các lệnh cậy (pick) không cần thiết"
+msgstr "không thể bỠqua các lệnh pick không cần thiết"
msgid "the script was already rearranged."
-msgstr "văn lệnh đã sẵn được sắp đặt rồi."
+msgstr "script đã được sắp đặt rồi."
+
+#, c-format
+msgid "update-refs file at '%s' is invalid"
+msgstr "tập tin update-refs '%s' không hợp lệ"
#, c-format
msgid "'%s' is outside repository at '%s'"
-msgstr "“%s†ngoài má»™t kho chứa tại “%sâ€"
+msgstr "'%s' nằm ngoài kho chứa tại '%s'"
#, c-format
msgid ""
@@ -19644,8 +20824,8 @@ msgid ""
"Use 'git <command> -- <path>...' to specify paths that do not exist locally."
msgstr ""
"%s: không có Ä‘Æ°á»ng dẫn nào nhÆ° thế ở trong cây làm việc.\n"
-"Dùng “git <lệnh> -- <Ä‘Æ°á»ng/dẫn>…†để chỉ định Ä‘Æ°á»ng dẫn mà nó không tồn tại "
-"một cách nội bộ."
+"Dùng 'git <lệnh> -- <Ä‘Æ°á»ng/dẫn>...' để chỉ định Ä‘Æ°á»ng dẫn không tồn tại ná»™i "
+"bá»™."
#, c-format
msgid ""
@@ -19653,14 +20833,14 @@ msgid ""
"Use '--' to separate paths from revisions, like this:\n"
"'git <command> [<revision>...] -- [<file>...]'"
msgstr ""
-"tham số chÆ°a rõ ràng “%sâ€: chÆ°a biết Ä‘iểm xem xét hay Ä‘Æ°á»ng dẫn không trong "
-"cây làm việc.\n"
-"Dùng “--†để ngăn cách các Ä‘Æ°á»ng dẫn khá»i Ä‘iểm xem xét, nhÆ° thế này:\n"
-"“git <lệnh> [<Ä‘iểm xem xét>…] -- [<tập tin>…]â€"
+"tham số chÆ°a rõ ràng '%s': chÆ°a biết Ä‘iểm xét duyệt hay Ä‘Æ°á»ng dẫn không "
+"trong cây làm việc.\n"
+"Dùng '--' để ngăn cách các Ä‘Æ°á»ng dẫn khá»i Ä‘iểm xét duyệt, nhÆ° thế này:\n"
+"'git <lệnh> [<điểm xét duyệt>...] -- [<tập tin>...]'"
#, c-format
msgid "option '%s' must come before non-option arguments"
-msgstr "tùy chá»n “%s†phải trÆ°á»›c các đối số đầu tiên không có tùy chá»n"
+msgstr "tùy chá»n '%s' phải trÆ°á»›c các đối số đầu tiên không có tùy chá»n"
#, c-format
msgid ""
@@ -19668,16 +20848,20 @@ msgid ""
"Use '--' to separate paths from revisions, like this:\n"
"'git <command> [<revision>...] -- [<file>...]'"
msgstr ""
-"tham số chÆ°a rõ ràng “%sâ€: cả Ä‘iểm xem xét và tên tập tin.\n"
-"Dùng “--†để ngăn cách các Ä‘Æ°á»ng dẫn khá»i Ä‘iểm xem xét, nhÆ° thế này:\n"
-"“git <lệnh> [<Ä‘iểm xem xét>…] -- [<tập tin>…]â€"
+"tham số chưa rõ ràng '%s': cả điểm xem xét và tên tập tin.\n"
+"Dùng '--' để ngăn cách các Ä‘Æ°á»ng dẫn khá»i Ä‘iểm xem xét, nhÆ° thế này:\n"
+"'git <lệnh> [<điểm xem xét>...] -- [<tập tin>...]'"
msgid "unable to set up work tree using invalid config"
-msgstr "không thể cài đặt thư mục làm việc sử dụng cấu hình không hợp lệ"
+msgstr "không thể thiết lập thư mục làm việc với cấu hình không hợp lệ"
+
+#, c-format
+msgid "'%s' already specified as '%s'"
+msgstr "'%s' đã được chỉ định là '%s' rồi"
#, c-format
msgid "Expected git repo version <= %d, found %d"
-msgstr "Cần phiên bản kho git <= %d, nhưng lại nhận được %d"
+msgstr "Cần phiên bản kho git <= %d, nhưng lại là %d"
msgid "unknown repository extension found:"
msgid_plural "unknown repository extensions found:"
@@ -19685,15 +20869,16 @@ msgstr[0] "tìm thấy phần mở rộng kho chưa biết:"
msgid "repo version is 0, but v1-only extension found:"
msgid_plural "repo version is 0, but v1-only extensions found:"
-msgstr[0] "phiên bản kho là 0, nhưng lại tìm thấy phần mở rộng chỉ v1:"
+msgstr[0] ""
+"phiên bản kho là 0, nhưng lại tìm thấy phần mở rộng chỉ dành cho v1:"
#, c-format
msgid "error opening '%s'"
-msgstr "gặp lá»—i khi mở “%sâ€"
+msgstr "gặp lỗi khi mở '%s'"
#, c-format
msgid "too large to be a .git file: '%s'"
-msgstr "tập tin .git là quá lá»›n: “%sâ€"
+msgstr "tập tin .git quá lớn: '%s'"
#, c-format
msgid "error reading %s"
@@ -19701,11 +20886,11 @@ msgstr "gặp lá»—i khi Ä‘á»c %s"
#, c-format
msgid "invalid gitfile format: %s"
-msgstr "định dạng tập tin git không hợp lệ: %s"
+msgstr "định dạng gitfile không hợp lệ: %s"
#, c-format
msgid "no path in gitfile: %s"
-msgstr "không có Ä‘Æ°á»ng dẫn trong tập tin git: %s"
+msgstr "không có Ä‘Æ°á»ng dẫn trong gitfile: %s"
#, c-format
msgid "not a git repository: %s"
@@ -19713,56 +20898,61 @@ msgstr "không phải là kho git: %s"
#, c-format
msgid "'$%s' too big"
-msgstr "“$%s†quá lớn"
+msgstr "'$%s' quá lớn"
#, c-format
msgid "not a git repository: '%s'"
-msgstr "không phải là kho git: “%sâ€"
+msgstr "không phải là kho git: '%s'"
#, c-format
msgid "cannot chdir to '%s'"
-msgstr "không thể chdir (chuyển đổi thÆ° mục) sang “%sâ€"
+msgstr "không thể chdir (chuyển thư mục) sang '%s'"
msgid "cannot come back to cwd"
-msgstr "không thể quay lại cwd"
+msgstr "không thể quay lại thư mục làm việc hiện hành"
#, c-format
msgid "failed to stat '%*s%s%s'"
-msgstr "gặp lá»—i khi lấy thống kê vỠ“%*s%s%sâ€"
+msgstr "gặp lỗi khi stat'%*s%s%s'"
msgid "Unable to read current working directory"
msgstr "Không thể Ä‘á»c thÆ° mục làm việc hiện hành"
#, c-format
msgid "cannot change to '%s'"
-msgstr "không thể chuyển sang “%sâ€"
+msgstr "không thể chuyển sang '%s'"
#, c-format
msgid "not a git repository (or any of the parent directories): %s"
-msgstr "không phải là kho git (hoặc bất kỳ thư mục cha mẹ nào): %s"
+msgstr "không phải là kho git (các thư mục cha cũng không phải): %s"
#, c-format
msgid ""
"not a git repository (or any parent up to mount point %s)\n"
"Stopping at filesystem boundary (GIT_DISCOVERY_ACROSS_FILESYSTEM not set)."
msgstr ""
-"không phải là kho git (hay bất kỳ cha mẹ nào đến tận điểm gắn kết %s)\n"
+"không phải là kho git (các thư mục cha dưới điểm gắn kết %s cũng không "
+"phải)\n"
"Dừng tại biên của hệ thống tập tin (GIT_DISCOVERY_ACROSS_FILESYSTEM chưa "
-"đặt)."
+"được đặt)."
#, c-format
msgid ""
-"unsafe repository ('%s' is owned by someone else)\n"
-"To add an exception for this directory, call:\n"
+"detected dubious ownership in repository at '%s'\n"
+"%sTo add an exception for this directory, call:\n"
"\n"
"\tgit config --global --add safe.directory %s"
msgstr ""
-"kho lÆ°u trữ không an toàn ('%s' thuá»™c sở hữu của ngÆ°á»i khác)\n"
-"Äể thêm ngoại lệ cho thÆ° mục này, hãy gá»i:\n"
+"kho lÆ°u trữ '%s' thuá»™c sở hữu của ngÆ°á»i khác\n"
+"%sÄể thêm ngoại lệ cho thÆ° mục này, hãy gá»i:\n"
"\n"
"\tgit config --global --add safe.directory %s"
#, c-format
+msgid "cannot use bare repository '%s' (safe.bareRepository is '%s')"
+msgstr "không thể dùng kho chứa bare '%s' (safe.bareRepository là '%s')"
+
+#, c-format
msgid ""
"problem with core.sharedRepository filemode value (0%.3o).\n"
"The owner of files must always have read and write permissions."
@@ -19771,17 +20961,107 @@ msgstr ""
"ngÆ°á»i sở hữu tập tin phải luôn có quyá»n Ä‘á»c và ghi."
msgid "fork failed"
-msgstr "gặp lỗi khi rẽ nhánh tiến trình"
+msgstr "gặp lỗi khi fork"
msgid "setsid failed"
msgstr "setsid gặp lỗi"
#, c-format
+msgid "cannot stat template '%s'"
+msgstr "không thể lấy thông tin vỠmẫu '%s'"
+
+#, c-format
+msgid "cannot opendir '%s'"
+msgstr "không thể mở thư mục '%s'"
+
+#, c-format
+msgid "cannot readlink '%s'"
+msgstr "không thể Ä‘á»c ná»™i dung liên kết '%s'"
+
+#, c-format
+msgid "cannot symlink '%s' '%s'"
+msgstr "không thể tạo liên kết má»m '%s' '%s'"
+
+#, c-format
+msgid "cannot copy '%s' to '%s'"
+msgstr "không thể sao chép '%s' sang '%s'"
+
+#, c-format
+msgid "ignoring template %s"
+msgstr "đang bỠqua mẫu '%s'"
+
+#, c-format
+msgid "templates not found in %s"
+msgstr "các mẫu không được tìm thấy trong %s"
+
+#, c-format
+msgid "not copying templates from '%s': %s"
+msgstr "không sao chép các mẫu từ '%s': %s"
+
+#, c-format
+msgid "invalid initial branch name: '%s'"
+msgstr "tên nhánh khởi tạo không hợp lệ: '%s'"
+
+#, c-format
+msgid "re-init: ignored --initial-branch=%s"
+msgstr "re-init: --initial-branch=%s bị bỠqua"
+
+#, c-format
+msgid "unable to handle file type %d"
+msgstr "không thể xử lý (handle) tập tin kiểu %d"
+
+#, c-format
+msgid "unable to move %s to %s"
+msgstr "không di chuyển được %s vào %s"
+
+msgid "attempt to reinitialize repository with different hash"
+msgstr "cố để khởi tạo lại một kho với kiểu băm dữ liệu khác"
+
+msgid ""
+"attempt to reinitialize repository with different reference storage format"
+msgstr "cố khởi tạo lại một kho với kiểu lưu tham chiếu dữ liệu khác"
+
+#, c-format
+msgid "%s already exists"
+msgstr "%s đã có từ trước rồi"
+
+#, c-format
+msgid "Reinitialized existing shared Git repository in %s%s\n"
+msgstr "Äã khởi tạo lại kho Git chia sẻ sẵn có trong %s%s\n"
+
+#, c-format
+msgid "Reinitialized existing Git repository in %s%s\n"
+msgstr "Äã khởi tạo lại kho Git sẵn có trong %s%s\n"
+
+#, c-format
+msgid "Initialized empty shared Git repository in %s%s\n"
+msgstr "Äã khởi tạo lại kho Git chia sẻ trống rá»—ng sẵn có trong %s%s\n"
+
+#, c-format
+msgid "Initialized empty Git repository in %s%s\n"
+msgstr "Äã khởi tạo lại kho Git trống rá»—ng sẵn có trong %s%s\n"
+
+#, c-format
msgid "index entry is a directory, but not sparse (%08x)"
-msgstr "mục tin mục lục là một thư mục, nhưng không \"sparse\" (%08x)"
+msgstr "mục tin chỉ mục là một thư mục, nhưng không \"sparse\" (%08x)"
msgid "cannot use split index with a sparse index"
-msgstr "không thể sử dụng bảng mục lục chia tách với một \"sparse index\""
+msgstr "không thể sử dụng chỉ mục chia tách với một \"sparse index\""
+
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not start with '('"
+msgstr "định dạng %s sai: phần tử '%s' không bắt đầu bằng '('"
+
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: element '%s' does not end in ')'"
+msgstr "định dạng %s sai: phần tử '%s' không bắt kết thúc bằng ')'"
+
+#. TRANSLATORS: %s is a command like "ls-tree".
+#, c-format
+msgid "bad %s format: %%%.*s"
+msgstr "định dạng %s sai: %%%.*s"
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#, c-format
@@ -19826,21 +21106,15 @@ msgid_plural "%u bytes/s"
msgstr[0] "%u byte/giây"
#, c-format
-msgid "could not edit '%s'"
-msgstr "không thể sá»­a “%sâ€"
-
-#, c-format
msgid "ignoring suspicious submodule name: %s"
-msgstr "Ä‘ang lá» Ä‘i tên mô-Ä‘un-con mập má»: %s"
+msgstr "Ä‘ang bá» qua tên mô-Ä‘un-con mập má»: %s"
msgid "negative values not allowed for submodule.fetchJobs"
msgstr "không cho phép giá trị âm ở submodule.fetchJobs"
#, c-format
msgid "ignoring '%s' which may be interpreted as a command-line option: %s"
-msgstr ""
-"Ä‘ang bá» qua “%s†cái mà có thể được phiên dịch nhÆ° là má»™t tùy chá»n dòng "
-"lệnh: %s"
+msgstr "Ä‘ang bá» qua '%s' nhÆ°ng có thể được hiểu là tùy chá»n trên dòng lệnh: %s"
#, c-format
msgid "Could not update .gitmodules entry %s"
@@ -19864,11 +21138,11 @@ msgstr "gặp lỗi khi tổ chức .gitmodules đã cập nhật"
#, c-format
msgid "in unpopulated submodule '%s'"
-msgstr "trong mô-Ä‘un-con không có gì “%sâ€"
+msgstr "trong mô-đun-con không có gì '%s'"
#, c-format
msgid "Pathspec '%s' is in submodule '%.*s'"
-msgstr "Äặc tả Ä‘Æ°á»ng dẫn “%s†thì ở trong mô-Ä‘un-con “%.*sâ€"
+msgstr "Äặc tả Ä‘Æ°á»ng dẫn '%s' ở trong mô-Ä‘un-con '%.*s'"
#, c-format
msgid "bad --ignore-submodules argument: %s"
@@ -19879,33 +21153,33 @@ msgid ""
"Submodule in commit %s at path: '%s' collides with a submodule named the "
"same. Skipping it."
msgstr ""
-"Mô-Ä‘un-con trong lần chuyển giao %s tại Ä‘Æ°á»ng dẫn: “%s†va chạm vá»›i mô-Ä‘un-"
-"con cùng tên. Nên bỠqua nó."
+"Mô-Ä‘un-con trong lần chuyển giao %s tại Ä‘Æ°á»ng dẫn: '%s' va chạm vá»›i mô-Ä‘un-"
+"con cùng tên. Nên sẽ bỠqua."
#, c-format
msgid "submodule entry '%s' (%s) is a %s, not a commit"
msgstr ""
-"mục tin mô-đun-con “%s†(%s) là một %s, không phải là một lần chuyển giao"
+"mục tin mô-đun-con '%s' (%s) là một %s, không phải là một lần chuyển giao"
#, c-format
msgid ""
"Could not run 'git rev-list <commits> --not --remotes -n 1' command in "
"submodule %s"
msgstr ""
-"Không thể chạy lệnh “git rev-list <các lần chuyển giao> --not --remotes -n "
-"1†trong mô-Ä‘un-con “%sâ€"
+"Không thể chạy lệnh 'git rev-list <các lần chuyển giao> --not --remotes -n "
+"1' trong mô-đun-con '%s'"
#, c-format
msgid "process for submodule '%s' failed"
-msgstr "xử lý cho mô-đun-con “%s†gặp lỗi"
+msgstr "xử lý cho mô-đun-con '%s' gặp lỗi"
#, c-format
msgid "Pushing submodule '%s'\n"
-msgstr "Äẩy lên mô-Ä‘un-con “%sâ€\n"
+msgstr "Äẩy lên mô-Ä‘un-con '%s'\n"
#, c-format
msgid "Unable to push submodule '%s'\n"
-msgstr "Không thể đẩy lên mô-Ä‘un-con “%sâ€\n"
+msgstr "Không thể đẩy lên mô-đun-con '%s'\n"
#, c-format
msgid "Fetching submodule %s%s\n"
@@ -19913,11 +21187,11 @@ msgstr "Äang lấy vá» mô-Ä‘un-con %s%s\n"
#, c-format
msgid "Could not access submodule '%s'\n"
-msgstr "Không thể truy cập mô-Ä‘un-con “%sâ€\n"
+msgstr "Không thể truy cập mô-đun-con '%s'\n"
#, c-format
msgid "Could not access submodule '%s' at commit %s\n"
-msgstr "Không thể truy cập mô-đun-con “%s†ở lần chuyển giao %s\n"
+msgstr "Không thể truy cập mô-đun-con '%s' ở lần chuyển giao %s\n"
#, c-format
msgid "Fetching submodule %s%s at commit %s\n"
@@ -19929,65 +21203,65 @@ msgid ""
"%s"
msgstr ""
"Có lỗi khi lấy vỠmô-đun-con:\n"
-" “%sâ€"
+" '%s'"
#, c-format
msgid "'%s' not recognized as a git repository"
-msgstr "không nhận ra “%s†là một kho git"
+msgstr "không nhận ra '%s' là một kho git"
#, c-format
msgid "Could not run 'git status --porcelain=2' in submodule %s"
-msgstr "Không thể chạy “git status --porcelain=2†trong mô-Ä‘un-con “%sâ€"
+msgstr "Không thể chạy 'git status --porcelain=2' trong mô-đun-con '%s'"
#, c-format
msgid "'git status --porcelain=2' failed in submodule %s"
-msgstr "“git status --porcelain=2†gặp lá»—i trong mô-Ä‘un-con “%sâ€"
+msgstr "'git status --porcelain=2' gặp lỗi trong mô-đun-con '%s'"
#, c-format
msgid "could not start 'git status' in submodule '%s'"
-msgstr "không thể lấy thống kê “git status†trong mô-Ä‘un-con “%sâ€"
+msgstr "không thể khởi chạy 'git status' trong mô-đun-con '%s'"
#, c-format
msgid "could not run 'git status' in submodule '%s'"
-msgstr "không thể chạy “git status†trong mô-Ä‘un-con “%sâ€"
+msgstr "không thể chạy 'git status' trong mô-đun-con '%s'"
#, c-format
msgid "Could not unset core.worktree setting in submodule '%s'"
-msgstr "Không thể đặt core.worktree trong mô-Ä‘un-con “%sâ€"
+msgstr "Không thể đặt core.worktree trong mô-đun-con '%s'"
#, c-format
msgid "could not recurse into submodule '%s'"
-msgstr "không thể đệ quy vào trong mô-Ä‘un-con “%sâ€"
+msgstr "không thể đệ quy vào trong mô-đun-con '%s'"
msgid "could not reset submodule index"
-msgstr "không thể đặt lại mục lục của mô-đun-con"
+msgstr "không thể đặt lại chỉ mục của mô-đun-con"
#, c-format
msgid "submodule '%s' has dirty index"
-msgstr "mô-đun-con “%s†có mục lục còn bẩn"
+msgstr "mô-đun-con '%s' có chỉ mục không sạch"
#, c-format
msgid "Submodule '%s' could not be updated."
-msgstr "Mô-đun-con “%s†không thể được cập nhật."
+msgstr "Mô-đun-con '%s' không thể được cập nhật."
#, c-format
msgid "submodule git dir '%s' is inside git dir '%.*s'"
-msgstr "thÆ° mục git mô Ä‘un con “%s†là bên trong git DIR “%.*sâ€"
+msgstr "thư mục git mô đun con '%s' là bên trong git DIR '%.*s'"
#, c-format
msgid ""
"relocate_gitdir for submodule '%s' with more than one worktree not supported"
msgstr ""
-"relocate_gitdir cho mô-Ä‘un-con “%s†vá»›i nhiá»u hÆ¡n má»™t cây làm việc là chÆ°a "
+"relocate_gitdir cho mô-Ä‘un-con '%s' vá»›i nhiá»u hÆ¡n má»™t cây làm việc là chÆ°a "
"được hỗ trợ"
#, c-format
msgid "could not lookup name for submodule '%s'"
-msgstr "không thể tìm kiếm tên cho mô-Ä‘un-con “%sâ€"
+msgstr "không thể tìm kiếm tên cho mô-đun-con '%s'"
#, c-format
msgid "refusing to move '%s' into an existing git dir"
-msgstr "từ chối di chuyển “%s†vào trong một thư mục git sẵn có"
+msgstr "từ chối di chuyển '%s' vào trong một thư mục git sẵn có"
#, c-format
msgid ""
@@ -19995,12 +21269,12 @@ msgid ""
"'%s' to\n"
"'%s'\n"
msgstr ""
-"Di cư thư mục git của “%s%s†từ\n"
-"“%s†sang\n"
-"“%sâ€\n"
+"Di cư thư mục git của '%s%s' từ\n"
+"'%s' sang\n"
+"'%s'\n"
msgid "could not start ls-files in .."
-msgstr "không thể lấy thông tin thống kê vỠls-files trong .."
+msgstr "không thể khởi chạy ls-files trong .."
#, c-format
msgid "ls-tree returned unexpected return code %d"
@@ -20008,13 +21282,26 @@ msgstr "ls-tree trả vỠmã không như mong đợi %d"
#, c-format
msgid "failed to lstat '%s'"
-msgstr "gặp lá»—i khi lstat “%sâ€"
+msgstr "gặp lỗi khi lstat '%s'"
-msgid "unhandled options"
-msgstr "các tùy chá»n được không xá»­ lý"
+msgid "no remote configured to get bundle URIs from"
+msgstr "không có máy chủ để lấy URI bundle"
-msgid "error preparing revisions"
-msgstr "gặp lỗi khi chuẩn bị các điểm xét duyệt"
+#, c-format
+msgid "remote '%s' has no configured URL"
+msgstr "máy chủ '%s' không có cấu hình URL"
+
+msgid "could not get the bundle-uri list"
+msgstr "không thể lấy vỠdanh sách bundle-uri"
+
+msgid "test-tool cache-tree <options> (control|prime|update)"
+msgstr "test-tool cache-tree <các tuỳ chá»n> (control|prime|update)"
+
+msgid "clear the cache tree before each iteration"
+msgstr "dá»n cây nhá»› tạm trÆ°á»›c má»—i chu kỳ"
+
+msgid "number of entries in the cache tree to invalidate (default 0)"
+msgstr "số mục cần huỷ trong câu nhớ tạm (mặc định 0)"
#, c-format
msgid "commit %s is not marked reachable"
@@ -20027,7 +21314,7 @@ msgid "test-tool serve-v2 [<options>]"
msgstr "test-tool serve-v2 [<các tùy chá»n>]"
msgid "exit immediately after advertising capabilities"
-msgstr "thoát ngay sau khi khởi tạo quảng cáo capabilities"
+msgstr "thoát ngay sau khi quảng bá capabilities"
msgid "test-helper simple-ipc is-active [<name>] [<options>]"
msgstr "test-helper simple-ipc is-active [<tên>] [<các tùy chá»n>]"
@@ -20062,7 +21349,7 @@ msgid "named-pipe name"
msgstr "tên named-pipe"
msgid "number of threads in server thread pool"
-msgstr "số lượng tiến trình trong kho tiến trình máy phục vụ"
+msgstr "số lượng tiến trình trong kho tiến trình máy chủ"
msgid "seconds to wait for daemon to start or stop"
msgstr "số giây mà dịch vụ chạy ná»n chá» khi khởi Ä‘á»™ng hoặc dừng"
@@ -20083,67 +21370,44 @@ msgid "token"
msgstr "thẻ bài"
msgid "command token to send to the server"
-msgstr "thẻ bài lệnh để gửi lên cho máy phục vụ"
+msgstr "thẻ bài lệnh để gửi lên cho máy chủ"
#, c-format
msgid "running trailer command '%s' failed"
-msgstr "chạy lệnh kéo theo “%s†gặp lỗi"
+msgstr "chạy lệnh kéo theo '%s' gặp lỗi"
#, c-format
msgid "unknown value '%s' for key '%s'"
-msgstr "không hiểu giá trị “%s†cho khóa “%sâ€"
+msgstr "không hiểu giá trị '%s' cho khóa '%s'"
#, c-format
msgid "empty trailer token in trailer '%.*s'"
-msgstr "thẻ thừa trống rá»—ng trong phần thừa “%.*sâ€"
-
-#, c-format
-msgid "could not read input file '%s'"
-msgstr "không Ä‘á»c được tập tin đầu vào “%sâ€"
-
-#, c-format
-msgid "could not stat %s"
-msgstr "không thể lấy thông tin thống kê vỠ%s"
-
-#, c-format
-msgid "file %s is not a regular file"
-msgstr "\"%s\" không phải là tập tin bình thÆ°á»ng"
-
-#, c-format
-msgid "file %s is not writable by user"
-msgstr "tập tin %s ngÆ°á»i dùng không thể ghi được"
-
-msgid "could not open temporary file"
-msgstr "không thể tạo tập tin tạm thá»i"
-
-#, c-format
-msgid "could not rename temporary file to %s"
-msgstr "không thể đổi tên tập tin tạm thá»i thành %s"
+msgstr "thẻ thừa trống rỗng trong phần thừa '%.*s'"
msgid "full write to remote helper failed"
-msgstr "ghi đầy đủ lên bộ hỗ trợ máy chủ gặp lỗi"
+msgstr "ghi đầy đủ lên helper máy chủ gặp lỗi"
#, c-format
msgid "unable to find remote helper for '%s'"
-msgstr "không thể tìm thấy bá»™ há»— trợ máy chủ cho “%sâ€"
+msgstr "không thể tìm thấy helper máy chủ cho '%s'"
msgid "can't dup helper output fd"
-msgstr "không thể nhân đôi fd dầu ra bộ hỗ trợ"
+msgstr "không thể nhân đôi fd dầu ra helper"
#, c-format
msgid ""
"unknown mandatory capability %s; this remote helper probably needs newer "
"version of Git"
msgstr ""
-"không hiểu capability bắt buộc %s; bộ hỗ trợ máy chủ này gần như chắc chắn "
-"là cần phiên bản Git mới hơn"
+"không hiểu capability bắt buộc %s; helper máy chủ này gần như chắc chắn là "
+"cần phiên bản Git mới hơn"
msgid "this remote helper should implement refspec capability"
-msgstr "bộ hỗ trợ máy chủ này cần phải thực thi capability đặc tả tham chiếu"
+msgstr "remote helper này cần hỗ trợ capability đặc tả tham chiếu"
#, c-format
msgid "%s unexpectedly said: '%s'"
-msgstr "%s said bất ngá»: “%sâ€"
+msgstr "%s bất ngá» trả lá»i: '%s'"
#, c-format
msgid "%s also locked %s"
@@ -20169,9 +21433,6 @@ msgstr "giao thức này không há»— trợ cài đặt Ä‘Æ°á»ng dẫn dịch vá
msgid "invalid remote service path"
msgstr "Ä‘Æ°á»ng dẫn dịch vụ máy chủ không hợp lệ"
-msgid "operation not supported by protocol"
-msgstr "thao tác không được gia thức hỗ trợ"
-
#, c-format
msgid "can't connect to subservice %s"
msgstr "không thể kết nối đến dịch vụ phụ %s"
@@ -20180,15 +21441,15 @@ msgid "--negotiate-only requires protocol v2"
msgstr "--negotiate-only cần giao thức v2"
msgid "'option' without a matching 'ok/error' directive"
-msgstr "“option†không có chỉ thị “ok/error†tương ứng"
+msgstr "'option' không có chỉ thị 'ok/error' tương ứng"
#, c-format
msgid "expected ok/error, helper said '%s'"
-msgstr "cần ok/error, nhÆ°ng bá»™ há»— trợ lại nói “%sâ€"
+msgstr "cần ok/error, nhưng helper lại nói '%s'"
#, c-format
msgid "helper reported unexpected status of %s"
-msgstr "bộ hỗ trợ báo cáo rằng không cần tình trạng của %s"
+msgstr "helper báo cáo tình trạng bất thÆ°á»ng của %s"
#, c-format
msgid "helper %s does not support dry-run"
@@ -20212,14 +21473,14 @@ msgstr "helper %s không hỗ trợ --%s"
#, c-format
msgid "helper %s does not support 'push-option'"
-msgstr "helper %s không há»— trợ “push-optionâ€"
+msgstr "helper %s không hỗ trợ 'push-option'"
msgid "remote-helper doesn't support push; refspec needed"
msgstr "remote-helper không hỗ trợ push; cần đặc tả tham chiếu"
#, c-format
-msgid "helper %s does not support 'force'"
-msgstr "helper %s không há»— trợ “forceâ€"
+msgid "helper %s does not support '--force'"
+msgstr "helper %s không hỗ trợ '--force'"
msgid "couldn't run fast-export"
msgstr "không thể chạy fast-export"
@@ -20238,7 +21499,7 @@ msgstr ""
#, c-format
msgid "unsupported object format '%s'"
-msgstr "không há»— trợ định dạng đối tượng “%sâ€"
+msgstr "không hỗ trợ định dạng đối tượng '%s'"
#, c-format
msgid "malformed response in ref list: %s"
@@ -20277,18 +21538,18 @@ msgstr "không thể khởi chạy tuyến trình cho việc chép dữ liệu"
#, c-format
msgid "Would set upstream of '%s' to '%s' of '%s'\n"
-msgstr "Không thể đặt thượng nguồn của “%s†thành “%s†của “%sâ€\n"
+msgstr "Không thể đặt thượng nguồn của '%s' thành '%s' của '%s'\n"
#, c-format
msgid "could not read bundle '%s'"
-msgstr "không thể Ä‘á»c bó “%sâ€"
+msgstr "không thể Ä‘á»c bó '%s'"
#, c-format
msgid "transport: invalid depth option '%s'"
-msgstr "vận chuyển: tùy chá»n Ä‘á»™ sâu “%s†không hợp lệ"
+msgstr "vận chuyển: tùy chá»n Ä‘á»™ sâu '%s' không hợp lệ"
msgid "see protocol.version in 'git help config' for more details"
-msgstr "xem protocol.version trong “git help config†để có thêm thông tin"
+msgstr "xem protocol.version trong 'git help config' để có thêm thông tin"
msgid "server options require protocol version 2 or later"
msgstr "các tùy chá»n máy chủ yêu cầu giao thức phiên bản 2 hoặc má»›i hÆ¡n"
@@ -20297,18 +21558,14 @@ msgid "server does not support wait-for-done"
msgstr "máy chủ không hỗ trợ wait-for-done"
msgid "could not parse transport.color.* config"
-msgstr "không thể phân tích cú pháp cấu hình transport.color.*"
+msgstr "không hiểu cú pháp cấu hình transport.color.*"
msgid "support for protocol v2 not implemented yet"
-msgstr "việc hỗ trợ giao thức v2 chưa được thực hiện"
-
-#, c-format
-msgid "unknown value for config '%s': %s"
-msgstr "không hiểu giá trị cho cho cấu hình “%sâ€: %s"
+msgstr "chưa hỗ trợ giao thức v2"
#, c-format
msgid "transport '%s' not allowed"
-msgstr "không cho phép phÆ°Æ¡ng thức vận chuyển “%sâ€"
+msgstr "không cho phép phương thức vận chuyển '%s'"
msgid "git-over-rsync is no longer supported"
msgstr "git-over-rsync không còn được hỗ trợ nữa"
@@ -20319,7 +21576,7 @@ msgid ""
"not be found on any remote:\n"
msgstr ""
"Các Ä‘Æ°á»ng dẫn mô-Ä‘un-con sau đây có chứa các thay đổi cái mà\n"
-"có thể được tìm thấy trên má»i máy phục vụ:\n"
+"có thể được tìm thấy trên má»i máy chủ:\n"
#, c-format
msgid ""
@@ -20344,20 +21601,29 @@ msgstr ""
"\n"
"\tgit push\n"
"\n"
-"để đẩy chúng lên máy phục vụ.\n"
+"để đẩy chúng lên máy chủ.\n"
"\n"
msgid "Aborting."
-msgstr "Bãi bá»."
+msgstr "huá»· bá»."
msgid "failed to push all needed submodules"
msgstr "gặp lỗi khi đẩy dữ liệu của tất cả các mô-đun-con cần thiết"
+msgid "bundle-uri operation not supported by protocol"
+msgstr "thao tác bundle-uri không được giao thức hỗ trợ"
+
+msgid "could not retrieve server-advertised bundle-uri list"
+msgstr "không thể lấy vỠdanh sách bundle-uri do phía máy chủ quảng bá"
+
+msgid "operation not supported by protocol"
+msgstr "thao tác không được giao thức hỗ trợ"
+
msgid "too-short tree object"
msgstr "đối tượng cây quá ngắn"
msgid "malformed mode in tree entry"
-msgstr "chế độ dị hình trong đỠmục cây"
+msgstr "chế độ sai quy cách trong đỠmục cây"
msgid "empty filename in tree entry"
msgstr "tên tập tin trống rỗng trong mục tin cây"
@@ -20452,7 +21718,7 @@ msgid ""
"The following untracked working tree files would be removed by checkout:\n"
"%%s"
msgstr ""
-"Các tập tin cây làm việc chưa được theo dõi sau đây sẽ bị gỡ bỠbởi lệnh "
+"Các tập tin trong cây làm việc chưa được theo dõi sau sẽ bị xoá bỠbởi lệnh "
"checkout:\n"
"%%s"
@@ -20461,17 +21727,17 @@ msgid ""
"The following untracked working tree files would be removed by merge:\n"
"%%sPlease move or remove them before you merge."
msgstr ""
-"Các tập tin cây làm việc chưa được theo dõi sau đây sẽ bị gỡ bỠbởi lệnh hòa "
-"trá»™n:\n"
-"%%sVui lòng di chuyển hay gỡ bỠchúng trước khi bạn hòa trộn."
+"Các tập tin trong cây làm việc chưa được theo dõi sau sẽ bị xoá bỠbởi lệnh "
+"hòa trộn:\n"
+"%%sVui lòng di chuyển hay xoá bỠchúng trước khi bạn hòa trộn."
#, c-format
msgid ""
"The following untracked working tree files would be removed by merge:\n"
"%%s"
msgstr ""
-"Các tập tin cây làm việc chưa được theo dõi sau đây sẽ bị gỡ bỠbởi lệnh hòa "
-"trá»™n:\n"
+"Các tập tin trong cây làm việc chưa được theo dõi sau sẽ bị xoá bỠbởi lệnh "
+"hòa trộn:\n"
"%%s"
#, c-format
@@ -20479,15 +21745,15 @@ msgid ""
"The following untracked working tree files would be removed by %s:\n"
"%%sPlease move or remove them before you %s."
msgstr ""
-"Các tập tin cây làm việc chưa được theo dõi sau đây sẽ bị gỡ bỠbởi %s:\n"
-"%%sVui lòng di chuyển hay gỡ bỠchúng trước khi bạn %s."
+"Các tập tin trong cây làm việc chưa được theo dõi sau sẽ bị xoá bỠbởi %s:\n"
+"%%sVui lòng di chuyển hay xoá bỠchúng trước khi bạn %s."
#, c-format
msgid ""
"The following untracked working tree files would be removed by %s:\n"
"%%s"
msgstr ""
-"Các tập tin cây làm việc chưa được theo dõi sau đây sẽ bị gỡ bỠbởi %s:\n"
+"Các tập tin trong cây làm việc chưa được theo dõi sau sẽ bị xoá bỠbởi %s:\n"
"%%s"
#, c-format
@@ -20496,9 +21762,9 @@ msgid ""
"checkout:\n"
"%%sPlease move or remove them before you switch branches."
msgstr ""
-"Các tập tin cây làm việc chưa được theo dõi sau đây sẽ bị ghi đè bởi lệnh "
+"Các tập tin trong cây làm việc chưa được theo dõi sau sẽ bị ghi đè bởi lệnh "
"checkout:\n"
-"%%sVui lòng di chuyển hay gỡ bỠchúng trước khi bạn chuyển nhánh."
+"%%sVui lòng di chuyển hay xoá bỠchúng trước khi bạn chuyển nhánh."
#, c-format
msgid ""
@@ -20506,7 +21772,7 @@ msgid ""
"checkout:\n"
"%%s"
msgstr ""
-"Các tập tin cây làm việc chưa được theo dõi sau đây sẽ bị ghi đè bởi lệnh "
+"Các tập tin trong cây làm việc chưa được theo dõi sau sẽ bị ghi đè bởi lệnh "
"checkout:\n"
"%%s"
@@ -20515,16 +21781,16 @@ msgid ""
"The following untracked working tree files would be overwritten by merge:\n"
"%%sPlease move or remove them before you merge."
msgstr ""
-"Các tập tin cây làm việc chưa được theo dõi sau đây sẽ bị ghi đè bởi lệnh "
+"Các tập tin trong cây làm việc chưa được theo dõi sau sẽ bị ghi đè bởi lệnh "
"hòa trộn:\n"
-"%%sVui lòng di chuyển hay gỡ bỠchúng trước khi bạn hòa trộn."
+"%%sVui lòng di chuyển hay xoá bỠchúng trước khi bạn hòa trộn."
#, c-format
msgid ""
"The following untracked working tree files would be overwritten by merge:\n"
"%%s"
msgstr ""
-"Các tập tin cây làm việc chưa được theo dõi sau đây sẽ bị ghi đè bởi lệnh "
+"Các tập tin trong cây làm việc chưa được theo dõi sau sẽ bị ghi đè bởi lệnh "
"hòa trộn:\n"
"%%s"
@@ -20533,22 +21799,22 @@ msgid ""
"The following untracked working tree files would be overwritten by %s:\n"
"%%sPlease move or remove them before you %s."
msgstr ""
-"Các tập tin cây làm việc chưa được theo dõi sau đây sẽ bị ghi đè bởi lệnh "
+"Các tập tin trong cây làm việc chưa được theo dõi sau sẽ bị ghi đè bởi lệnh "
"%s:\n"
-"%%sVui lòng di chuyển hay gỡ bỠchúng trước khi bạn %s."
+"%%sVui lòng di chuyển hay xoá chúng trước khi bạn %s."
#, c-format
msgid ""
"The following untracked working tree files would be overwritten by %s:\n"
"%%s"
msgstr ""
-"Các tập tin cây làm việc chưa được theo dõi sau đây sẽ bị ghi đè bởi lệnh "
+"Các tập tin trong cây làm việc chưa được theo dõi sau sẽ bị ghi đè bởi lệnh "
"%s:\n"
"%%s"
#, c-format
msgid "Entry '%s' overlaps with '%s'. Cannot bind."
-msgstr "Mục “%s†đè lên “%sâ€. Không thể buá»™c."
+msgstr "Mục '%s' đè lên '%s'. Không thể bind."
#, c-format
msgid ""
@@ -20564,7 +21830,7 @@ msgid ""
"patterns:\n"
"%s"
msgstr ""
-"Các Ä‘Æ°á»ng dẫn sau đây không được cập nhật và vẫn được để lại bất chấp các "
+"Các Ä‘Æ°á»ng dẫn sau đây chÆ°a được cập nhật và vẫn được để lại mặc dù khá»›p các "
"mẫu sparse:\n"
"%s"
@@ -20583,21 +21849,21 @@ msgid ""
"patterns:\n"
"%s"
msgstr ""
-"Các Ä‘Æ°á»ng dẫn sau đây đã sẵn hiện diện và nhÆ° vậy không được cập nhật bất "
-"cấp các mẫu sparse:\n"
+"Các Ä‘Æ°á»ng dẫn sau đây đã tồn tại và nhÆ° vậy không được cập nhật mặc dù khá»›p "
+"các mẫu sparse:\n"
"%s"
#, c-format
msgid "Aborting\n"
-msgstr "Bãi bá»\n"
+msgstr "Huá»· bá»\n"
#, c-format
msgid ""
"After fixing the above paths, you may want to run `git sparse-checkout "
"reapply`.\n"
msgstr ""
-"Sau khi sá»­a các Ä‘Æ°á»ng dẫn phía trên, bạn có thể chạy “git sparse-checkout "
-"reapply“.\n"
+"Sau khi sá»­a các Ä‘Æ°á»ng dẫn phía trên, bạn có thể chạy 'git sparse-checkout "
+"reapply'.\n"
msgid "Updating files"
msgstr "Äang cập nhật các tập tin"
@@ -20607,12 +21873,12 @@ msgid ""
"on a case-insensitive filesystem) and only one from the same\n"
"colliding group is in the working tree:\n"
msgstr ""
-"các Ä‘Æ°á»ng dẫn sau đây có xung Ä‘á»™t(vd: các Ä‘Æ°á»ng dẫn phân biệt\n"
-"HOA/thÆ°á»ng trên má»™t hệ thống tập tin không phân biệt HOA/thÆ°á»ng)\n"
-"và chỉ một từ cùng một nhóm xung đột là trong cây làm việc hiện tại:\n"
+"các Ä‘Æ°á»ng dẫn sau đây có xung Ä‘á»™t (vd: các Ä‘Æ°á»ng dẫn phân biệt HOA/thÆ°á»ng\n"
+"trên hệ thống tập tin không phân biệt HOA/thÆ°á»ng) và chỉ má»™t Ä‘Æ°á»ng dẫn\n"
+"trong nhóm xung đột nằm trong cây làm việc hiện tại:\n"
msgid "Updating index flags"
-msgstr "Äang cập nhật các cá» mục lục"
+msgstr "Äang cập nhật các cá» chỉ mục"
#, c-format
msgid "worktree and untracked commit have duplicate entries: %s"
@@ -20623,17 +21889,17 @@ msgid "expected flush after fetch arguments"
msgstr "cần đẩy dữ liệu lên đĩa sau các tham số của lệnh fetch"
msgid "invalid URL scheme name or missing '://' suffix"
-msgstr "tên lược đồ URL không hợp lệ, hoặc thiếu hậu tố “://â€"
+msgstr "tên lược đồ URL không hợp lệ, hoặc thiếu hậu tố '://'"
#, c-format
msgid "invalid %XX escape sequence"
msgstr "thoát chuỗi %XX không hợp lệ"
msgid "missing host and scheme is not 'file:'"
-msgstr "thiếu máy chủ và lược đồ thì không phải là giao thức “file:â€"
+msgstr "thiếu máy chủ và lược đồ không phải là 'file:'"
msgid "a 'file:' URL may not have a port number"
-msgstr "một URL kiểu “file:†không được chứa cổng"
+msgstr "URL kiểu 'file:' không được chứa cổng"
msgid "invalid characters in host name"
msgstr "có các ký tự không hợp lệ trong tên máy"
@@ -20642,27 +21908,43 @@ msgid "invalid port number"
msgstr "tên cổng không hợp lệ"
msgid "invalid '..' path segment"
-msgstr "Ä‘oạn Ä‘Æ°á»ng dẫn “..†không hợp lệ"
+msgstr "Ä‘oạn Ä‘Æ°á»ng dẫn '..' không hợp lệ"
+
+#, c-format
+msgid "error: unable to format message: %s\n"
+msgstr "lỗi: không thể định dạng thông điệp: %s\n"
+
+msgid "usage: "
+msgstr "cách dùng: %s"
+
+msgid "fatal: "
+msgstr "lá»—i nghiêm trá»ng: "
+
+msgid "error: "
+msgstr "lá»—i: "
+
+msgid "warning: "
+msgstr "cảnh báo: "
msgid "Fetching objects"
msgstr "Äang lấy vá» các đối tượng"
#, c-format
msgid "'%s' at main working tree is not the repository directory"
-msgstr "“%s†tại cây làm việc chình không phải là thư mục kho"
+msgstr "'%s' tại cây làm việc chính không phải là thư mục kho"
#, c-format
msgid "'%s' file does not contain absolute path to the working tree location"
msgstr ""
-"tập tin “%s†không chứa Ä‘Æ°á»ng dẫn tuyệt đối đến vị trí cây làm việc hiện"
+"tập tin '%s' không chứa Ä‘Æ°á»ng dẫn tuyệt đối đến vị trí cây làm việc hiện"
#, c-format
msgid "'%s' is not a .git file, error code %d"
-msgstr "“%s†không phải là tập tin .git, mã lỗi %d"
+msgstr "'%s' không phải là tập tin .git, mã lỗi %d"
#, c-format
msgid "'%s' does not point back to '%s'"
-msgstr "“%s†không chỉ ngược đến “%sâ€"
+msgstr "'%s' không chỉ ngược đến '%s'"
msgid "not a directory"
msgstr "không phải thư mục"
@@ -20671,7 +21953,7 @@ msgid ".git is not a file"
msgstr ".git không phải là một tập tin"
msgid ".git file broken"
-msgstr "tệp .git bị há»ng"
+msgstr "tập tin .git bị há»ng"
msgid ".git file incorrect"
msgstr "tập tin .git không chính xác"
@@ -20680,13 +21962,13 @@ msgid "not a valid path"
msgstr "không phải là má»™t Ä‘Æ°á»ng dẫn hợp lệ"
msgid "unable to locate repository; .git is not a file"
-msgstr "không thể phân bổ kho chứa; .git không phải là một tập tin"
+msgstr "không thể định vị kho chứa; .git không phải là một tập tin"
msgid "unable to locate repository; .git file does not reference a repository"
-msgstr "không thể phân bổ kho chứa; tập tin .git tham chiếu đến một kho"
+msgstr "không thể định vị kho chứa; tập tin .git không chỉ đến một kho"
msgid "unable to locate repository; .git file broken"
-msgstr "không thể phân bổ kho chứa; tập tin .git bị há»ng"
+msgstr "không thể định vị kho chứa; tập tin .git bị há»ng"
msgid "gitdir unreadable"
msgstr "gitdir không thể Ä‘á»c được"
@@ -20716,7 +21998,7 @@ msgstr "tập tin gitdir chỉ đến vị trí không tồn tại"
#, c-format
msgid "unable to set %s in '%s'"
-msgstr "không thể đặt %s trong “%sâ€"
+msgstr "không thể đặt %s trong '%s'"
#, c-format
msgid "unable to unset %s in '%s'"
@@ -20727,48 +22009,49 @@ msgstr "gặp lỗi khi đặt cài đặt extensions.worktreeConfig"
#, c-format
msgid "could not setenv '%s'"
-msgstr "không thể setenv “%sâ€"
+msgstr "không thể setenv '%s'"
#, c-format
msgid "unable to create '%s'"
-msgstr "không thể tạo “%sâ€"
+msgstr "không thể tạo '%s'"
#, c-format
msgid "could not open '%s' for reading and writing"
-msgstr "không thể mở “%s†để Ä‘á»c và ghi"
+msgstr "không thể mở '%s' để Ä‘á»c và ghi"
#, c-format
msgid "unable to access '%s'"
-msgstr "không thể truy cập “%sâ€"
+msgstr "không thể truy cập '%s'"
msgid "unable to get current working directory"
msgstr "không thể lấy thư mục làm việc hiện hành"
+msgid "unable to get random bytes"
+msgstr "không thể lấy byte ngẫu nhiên"
+
msgid "Unmerged paths:"
msgstr "Những Ä‘Æ°á»ng dẫn chÆ°a được hòa trá»™n:"
msgid " (use \"git restore --staged <file>...\" to unstage)"
-msgstr " (dùng \"git restore --staged <tập-tin>…\" để bá» ra khá»i bệ phóng)"
+msgstr " (dùng \"git restore --staged <tập-tin>...\" để bá» ra khá»i bệ phóng)"
#, c-format
msgid " (use \"git restore --source=%s --staged <file>...\" to unstage)"
msgstr ""
-" (dùng \"git restore --source=%s --staged <tập-tin>…\" để bá» ra khá»i bệ "
+" (dùng \"git restore --source=%s --staged <tập-tin>...\" để bá» ra khá»i bệ "
"phóng)"
msgid " (use \"git rm --cached <file>...\" to unstage)"
-msgstr " (dùng \"git rm --cached <tập-tin>…\" để bá» ra khá»i bệ phóng)"
+msgstr " (dùng \"git rm --cached <tập-tin>...\" để bá» ra khá»i bệ phóng)"
msgid " (use \"git add <file>...\" to mark resolution)"
-msgstr " (dùng \"git add <tập-tin>…\" để đánh dấu là cần giải quyết)"
+msgstr " (dùng \"git add <tập-tin>...\" để đánh dấu là muốn thêm)"
msgid " (use \"git add/rm <file>...\" as appropriate to mark resolution)"
-msgstr ""
-" (dùng \"git add/rm <tập-tin>…\" như là một cách thích hợp để đánh dấu là "
-"cần được giải quyết)"
+msgstr " (dùng \"git add/rm <tập-tin>...\" để đánh dấu là muốn thêm/xoá)"
msgid " (use \"git rm <file>...\" to mark resolution)"
-msgstr " (dùng \"git rm <tập-tin>…\" để đánh dấu là cần giải quyết)"
+msgstr " (dùng \"git rm <tập-tin>...\" để đánh dấu là muốn xoá)"
msgid "Changes to be committed:"
msgstr "Những thay đổi sẽ được chuyển giao:"
@@ -20777,45 +22060,46 @@ msgid "Changes not staged for commit:"
msgstr "Các thay đổi chưa được đặt lên bệ phóng để chuyển giao:"
msgid " (use \"git add <file>...\" to update what will be committed)"
-msgstr " (dùng \"git add <tập-tin>…\" để cập nhật những gì sẽ chuyển giao)"
+msgstr ""
+" (dùng \"git add <tập-tin>...\" để cập nhật những gì sẽ được chuyển giao)"
msgid " (use \"git add/rm <file>...\" to update what will be committed)"
msgstr ""
-" (dùng \"git add/rm <tập-tin>…\" để cập nhật những gì sẽ được chuyển giao)"
+" (dùng \"git add/rm <tập-tin>...\" để cập nhật những gì sẽ được chuyển giao)"
msgid ""
" (use \"git restore <file>...\" to discard changes in working directory)"
msgstr ""
-" (dùng \"git restore <tập-tin>…\" để loại bỠcác thay đổi trong thư mục làm "
-"việc)"
+" (dùng \"git restore <tập-tin>...\" để loại bỠcác thay đổi trong thư mục "
+"làm việc)"
msgid " (commit or discard the untracked or modified content in submodules)"
msgstr ""
" (chuyển giao hoặc là loại bỠcác nội dung chưa được theo dõi hay đã sửa "
-"chữa trong mô-đun-con)"
+"trong mô-đun-con)"
#, c-format
msgid " (use \"git %s <file>...\" to include in what will be committed)"
msgstr ""
-" (dùng \"git %s <tập-tin>…\" để thêm vào những gì cần được chuyển giao)"
+" (dùng \"git %s <tập-tin>...\" để thêm vào những gì cần được chuyển giao)"
msgid "both deleted:"
-msgstr "bị xóa bởi cả hai:"
+msgstr "bị cả hai xóa đi:"
msgid "added by us:"
-msgstr "được thêm vào bởi chúng ta:"
+msgstr "được ta thêm vào:"
msgid "deleted by them:"
-msgstr "bị xóa Ä‘i bởi há»:"
+msgstr "bị hỠxóa đi:"
msgid "added by them:"
-msgstr "được thêm vào bởi há»:"
+msgstr "được hỠthêm vào:"
msgid "deleted by us:"
-msgstr "bị xóa bởi chúng ta:"
+msgstr "bị ta xóa đi:"
msgid "both added:"
-msgstr "được thêm vào bởi cả hai:"
+msgstr "được cả hai thêm vào:"
msgid "both modified:"
msgstr "bị sửa bởi cả hai:"
@@ -20836,10 +22120,10 @@ msgid "renamed:"
msgstr "đã đổi tên:"
msgid "typechange:"
-msgstr "đổi-kiểu:"
+msgstr "đổi kiểu:"
msgid "unknown:"
-msgstr "không hiểu:"
+msgstr "không rõ:"
msgid "unmerged:"
msgstr "chưa hòa trộn:"
@@ -20856,20 +22140,20 @@ msgstr "nội dung chưa được theo dõi, "
#, c-format
msgid "Your stash currently has %d entry"
msgid_plural "Your stash currently has %d entries"
-msgstr[0] "Bạn hiện nay ở trong phần cất đi đang có %d mục"
+msgstr[0] "Hiện trong phần cất đi đang có %d mục"
msgid "Submodules changed but not updated:"
msgstr "Những mô-đun-con đã bị thay đổi nhưng chưa được cập nhật:"
msgid "Submodule changes to be committed:"
-msgstr "Những mô-đun-con thay đổi đã được chuyển giao:"
+msgstr "Những thay đổi mô-đun-con sẽ được chuyển giao:"
msgid ""
"Do not modify or remove the line above.\n"
"Everything below it will be ignored."
msgstr ""
"Không sá»­a hay xóa bá» Ä‘Æ°á»ng ở trên.\n"
-"Má»i thứ phía dÆ°á»›i sẽ được xóa bá»."
+"Má»i thứ phía dÆ°á»›i sẽ được bá» qua."
#, c-format
msgid ""
@@ -20878,8 +22162,8 @@ msgid ""
"You can use '--no-ahead-behind' to avoid this.\n"
msgstr ""
"\n"
-"Nó cần %.2f giây để tính toán giá trị của trước/sau của nhánh.\n"
-"Bạn có thể dùng “--no-ahead-behind†tránh phải Ä‘iá»u này.\n"
+"Cần tới %.2f giây để tính toán giá trị đứng trước/sau của nhánh.\n"
+"Bạn có thể dùng '--no-ahead-behind' để bỠqua.\n"
msgid "You have unmerged paths."
msgstr "Bạn có những Ä‘Æ°á»ng dẫn chÆ°a được hòa trá»™n."
@@ -20888,7 +22172,7 @@ msgid " (fix conflicts and run \"git commit\")"
msgstr " (sửa các xung đột rồi chạy \"git commit\")"
msgid " (use \"git merge --abort\" to abort the merge)"
-msgstr " (dùng \"git merge --abort\" để bãi bỠviệc hòa trộn)"
+msgstr " (dùng \"git merge --abort\" để huỷ bỠviệc hòa trộn)"
msgid "All conflicts fixed but you are still merging."
msgstr "Tất cả các xung đột đã được giải quyết nhưng bạn vẫn đang hòa trộn."
@@ -20897,112 +22181,107 @@ msgid " (use \"git commit\" to conclude merge)"
msgstr " (dùng \"git commit\" để hoàn tất việc hòa trộn)"
msgid "You are in the middle of an am session."
-msgstr "Bạn Ä‘ang ở giữa của má»™t phiên “amâ€."
+msgstr "Bạn đang trong một phiên 'am' (áp dụng bản vá từ hòm thư)."
msgid "The current patch is empty."
-msgstr "Miếng vá hiện tại bị trống rỗng."
+msgstr "bản vá hiện tại bị trống."
msgid " (fix conflicts and then run \"git am --continue\")"
msgstr " (sửa các xung đột và sau đó chạy lệnh \"git am --continue\")"
msgid " (use \"git am --skip\" to skip this patch)"
-msgstr " (dùng \"git am --skip\" để bỠqua miếng vá này)"
+msgstr " (dùng \"git am --skip\" để bỠqua bản vá này)"
msgid ""
" (use \"git am --allow-empty\" to record this patch as an empty commit)"
msgstr ""
-" (dùng \"git am --allow-empty\" ghi miếng vá này như một lần chuyển giao "
+" (dùng \"git am --allow-empty\" để ghi bản vá này thành một lần chuyển giao "
"rá»—ng)"
msgid " (use \"git am --abort\" to restore the original branch)"
-msgstr " (dùng \"git am --abort\" để phục hồi lại nhánh nguyên thủy)"
+msgstr " (dùng \"git am --abort\" để phục hồi lại nhánh gốc)"
msgid "git-rebase-todo is missing."
msgstr "thiếu git-rebase-todo."
msgid "No commands done."
-msgstr "Không thực hiện lệnh nào."
+msgstr "Chưa thực hiện lệnh nào."
#, c-format
msgid "Last command done (%<PRIuMAX> command done):"
msgid_plural "Last commands done (%<PRIuMAX> commands done):"
-msgstr[0] "Lệnh thực hiện cuối (%<PRIuMAX> lệnh được thực thi):"
+msgstr[0] "Lệnh thực hiện cuối (đã thực thi %<PRIuMAX> lệnh):"
#, c-format
msgid " (see more in file %s)"
msgstr " (xem thêm trong %s)"
msgid "No commands remaining."
-msgstr "Không có lệnh nào còn lại."
+msgstr "Không còn lệnh nào."
#, c-format
msgid "Next command to do (%<PRIuMAX> remaining command):"
msgid_plural "Next commands to do (%<PRIuMAX> remaining commands):"
-msgstr[0] "Lệnh cần làm kế tiếp (%<PRIuMAX> lệnh còn lại):"
+msgstr[0] "Lệnh cần làm kế tiếp (còn %<PRIuMAX> lệnh):"
msgid " (use \"git rebase --edit-todo\" to view and edit)"
msgstr " (dùng lệnh \"git rebase --edit-todo\" để xem và sửa)"
#, c-format
msgid "You are currently rebasing branch '%s' on '%s'."
-msgstr "Bạn hiện nay Ä‘ang thá»±c hiện việc “rebase†nhánh “%s†trên “%sâ€."
+msgstr "Bạn hiện đang thực hiện rebase (cải tổ) nhánh '%s' lên '%s'."
msgid "You are currently rebasing."
-msgstr "Bạn hiện nay đang thực hiện việc “rebase†(cải tổ)."
+msgstr "Bạn hiện đang thực hiện rebase (cải tổ)."
msgid " (fix conflicts and then run \"git rebase --continue\")"
-msgstr ""
-" (sửa các xung đột và sau đó chạy lệnh “cải tổ†\"git rebase --continue\")"
+msgstr " (sửa các xung đột và sau đó chạy lệnh \"git rebase --continue\")"
msgid " (use \"git rebase --skip\" to skip this patch)"
-msgstr " (dùng lệnh “cải tổ†\"git rebase --skip\" để bỠqua lần vá này)"
+msgstr " (dùng lệnh \"git rebase --skip\" để bỠqua bản vá này)"
msgid " (use \"git rebase --abort\" to check out the original branch)"
-msgstr ""
-" (dùng lệnh “cải tổ†\"git rebase --abort\" để check-out nhánh nguyên thủy)"
+msgstr " (dùng lệnh \"git rebase --abort\" để check-out nhánh gốc)"
msgid " (all conflicts fixed: run \"git rebase --continue\")"
msgstr ""
-" (khi tất cả các xung đột đã sửa xong: chạy lệnh “cải tổ†\"git rebase --"
-"continue\")"
+" (khi tất cả các xung đột đã sửa xong: chạy lệnh \"git rebase --continue\")"
#, c-format
msgid ""
"You are currently splitting a commit while rebasing branch '%s' on '%s'."
msgstr ""
-"Bạn hiện nay đang thực hiện việc chia tách một lần chuyển giao trong khi "
-"Ä‘ang “rebase†nhánh “%s†trên “%sâ€."
+"Bạn hiện đang chia nhỠmột lần chuyển giao trong khi đang rebase nhánh '%s' "
+"lên '%s'."
msgid "You are currently splitting a commit during a rebase."
msgstr ""
-"Bạn hiện tại đang cắt đôi một lần chuyển giao trong khi đang thực hiện việc "
-"rebase."
+"Bạn hiện đang chia nhỠmột lần chuyển giao trong khi đang thực hiện rebase."
msgid " (Once your working directory is clean, run \"git rebase --continue\")"
msgstr ""
-" (Má»™t khi thÆ° mục làm việc của bạn đã gá»n gàng, chạy lệnh “cải tổ†\"git "
-"rebase --continue\")"
+" (Sau khi thư mục làm việc đã ổn, chạy lệnh \"git rebase --continue\")"
#, c-format
msgid "You are currently editing a commit while rebasing branch '%s' on '%s'."
msgstr ""
-"Bạn hiện nay đang thực hiện việc sửa chữa một lần chuyển giao trong khi đang "
-"rebase nhánh “%s†trên “%sâ€."
+"Bạn hiện đang thực hiện sửa chữa một lần chuyển giao trong khi đang rebase "
+"nhánh '%s' lên '%s'."
msgid "You are currently editing a commit during a rebase."
-msgstr "Bạn hiện đang sửa một lần chuyển giao trong khi bạn thực hiện rebase."
+msgstr "Bạn hiện đang sửa một lần chuyển giao trong khi đang thực hiện rebase."
msgid " (use \"git commit --amend\" to amend the current commit)"
-msgstr " (dùng \"git commit --amend\" để “tu bổ†lần chuyển giao hiện tại)"
+msgstr " (dùng \"git commit --amend\" để tu bổ lần chuyển giao hiện tại)"
msgid ""
" (use \"git rebase --continue\" once you are satisfied with your changes)"
msgstr ""
-" (chạy lệnh “cải tổ†\"git rebase --continue\" một khi bạn cảm thấy hài "
-"lòng vỠnhững thay đổi của mình)"
+" (chạy lệnh \"git rebase --continue\" khi bạn cảm thấy hài lòng vỠnhững "
+"thay đổi của mình)"
msgid "Cherry-pick currently in progress."
-msgstr "Cherry-pick hiện tại đang được thực hiện."
+msgstr "Cherry-pick hiện đang được thực hiện."
#, c-format
msgid "You are currently cherry-picking commit %s."
@@ -21021,17 +22300,17 @@ msgstr ""
"continue\")"
msgid " (use \"git cherry-pick --skip\" to skip this patch)"
-msgstr " (dùng \"git cherry-pick --skip\" để bỠqua miếng vá này)"
+msgstr " (dùng \"git cherry-pick --skip\" để bỠqua bản vá này)"
msgid " (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"
msgstr " (dùng \"git cherry-pick --abort\" để hủy bỠthao tác cherry-pick)"
msgid "Revert currently in progress."
-msgstr "Hoàn nguyên hiện tại đang thực hiện."
+msgstr "Hoàn nguyên hiện đang được thực hiện."
#, c-format
msgid "You are currently reverting commit %s."
-msgstr "Bạn hiện nay Ä‘ang thá»±c hiện thao tác hoàn nguyên lần chuyển giao “%sâ€."
+msgstr "Bạn hiện nay đang thực hiện thao tác hoàn nguyên lần chuyển giao '%s'."
msgid " (fix conflicts and run \"git revert --continue\")"
msgstr " (sửa các xung đột và sau đó chạy lệnh \"git revert --continue\")"
@@ -21053,7 +22332,7 @@ msgstr " (dùng \"git revert --abort\" để hủy bỠthao tác hoàn nguyên
msgid "You are currently bisecting, started from branch '%s'."
msgstr ""
"Bạn hiện nay đang thực hiện thao tác di chuyển nửa bước (bisect), bắt đầu từ "
-"nhánh “%sâ€."
+"nhánh '%s'."
msgid "You are currently bisecting."
msgstr "Bạn hiện tại đang thực hiện việc bisect (di chuyển nửa bước)."
@@ -21062,19 +22341,18 @@ msgid " (use \"git bisect reset\" to get back to the original branch)"
msgstr " (dùng \"git bisect reset\" để quay trở lại nhánh nguyên thủy)"
msgid "You are in a sparse checkout."
-msgstr "Bạn đang trong lần lấy ra sparse."
+msgstr "Bạn đang ở trong lần checkout thưa."
#, c-format
msgid "You are in a sparse checkout with %d%% of tracked files present."
msgstr ""
-"Bạn đang ở trong lần lấy ra sparser %d%% của các tập tin được theo dõi hiện "
-"tại."
+"Bạn đang ở trong lần checkout thưa với %d%% tập tin hiện được theo dõi."
msgid "On branch "
msgstr "Trên nhánh "
msgid "interactive rebase in progress; onto "
-msgstr "rebase ở chế độ tương tác đang được thực hiện; lên trên "
+msgstr "rebase có tương tác đang được thực hiện; lên trên "
msgid "rebase in progress; onto "
msgstr "rebase đang được thực hiện: lên trên "
@@ -21098,33 +22376,37 @@ msgid "Untracked files"
msgstr "Những tập tin chưa được theo dõi"
msgid "Ignored files"
-msgstr "Những tập tin bị lỠđi"
+msgstr "Những tập tin bị bỠqua"
#, c-format
msgid ""
-"It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
-"may speed it up, but you have to be careful not to forget to add\n"
-"new files yourself (see 'git help status')."
+"It took %.2f seconds to enumerate untracked files,\n"
+"but the results were cached, and subsequent runs may be faster."
msgstr ""
-"Cần %.2f giây để liệt kê tất cả các tập tin chưa được theo dõi. “status -"
-"unoâ€\n"
-"có lẽ làm nó nhanh hơn, nhưng bạn phải cẩn thận đừng quên mình phải\n"
-"tá»± thêm các tập tin má»›i (xem “git help statusâ€.."
+"Cần %.2f để duyệt các tập tin không được theo dõi,\n"
+"nhưng đã ghi nhớ kết quả, và các lần chạy sau sẽ nhanh hơn."
+
+#, c-format
+msgid "It took %.2f seconds to enumerate untracked files."
+msgstr "Cần %.2f để duyệt các tập tin không được theo dõi."
+
+msgid "See 'git help status' for information on how to improve this."
+msgstr "Xem 'git help status' để biết cách cải thiện việc này."
#, c-format
msgid "Untracked files not listed%s"
-msgstr "Những tập tin chưa được theo dõi không được liệt kê ra %s"
+msgstr "Không liệt kê những tập tin chưa được theo dõi%s"
msgid " (use -u option to show untracked files)"
-msgstr " (dùng tùy chá»n -u để hiển thị các tập tin chÆ°a được theo dõi)"
+msgstr " (dùng tùy chá»n -u để hiển thị những tập tin chÆ°a được theo dõi)"
msgid "No changes"
-msgstr "Không có thay đổi nào"
+msgstr "Không có thay đổi"
#, c-format
msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
msgstr ""
-"không có thay đổi nào được thêm vào để chuyển giao (dùng \"git add\" và/hoặc "
+"không có thay đổi nào được thêm vào để chuyển giao (dùng \"git add\" hoặc "
"\"git commit -a\")\n"
#, c-format
@@ -21136,14 +22418,14 @@ msgid ""
"nothing added to commit but untracked files present (use \"git add\" to "
"track)\n"
msgstr ""
-"không có gì được thêm vào lần chuyển giao nhưng có những tập tin chưa được "
-"theo dõi hiện diện (dùng \"git add\" để đưa vào theo dõi)\n"
+"không có gì được thêm vào để chuyển giao nhưng hiện có những tập tin chưa "
+"được theo dõi (dùng \"git add\" để đưa vào theo dõi)\n"
#, c-format
msgid "nothing added to commit but untracked files present\n"
msgstr ""
-"không có gì được thêm vào lần chuyển giao nhưng có những tập tin chưa được "
-"theo dõi hiện diện\n"
+"không có gì được thêm vào lần chuyển giao nhưng có những tập tin hiện chưa "
+"được theo dõi\n"
#, c-format
msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
@@ -21158,26 +22440,27 @@ msgstr "không có gì để chuyển giao\n"
#, c-format
msgid "nothing to commit (use -u to show untracked files)\n"
msgstr ""
-"không có gì để chuyển giao (dùng -u xem các tập tin chưa được theo dõi)\n"
+"không có gì để chuyển giao (dùng -u để xem những tập tin chưa được theo "
+"dõi)\n"
#, c-format
msgid "nothing to commit, working tree clean\n"
msgstr "không có gì để chuyển giao, thư mục làm việc sạch sẽ\n"
msgid "No commits yet on "
-msgstr "Vẫn không thực hiện lệnh chuyển giao nào "
+msgstr "Chưa thực hiện lệnh chuyển giao nào trên"
msgid "HEAD (no branch)"
msgstr "HEAD (không nhánh)"
msgid "different"
-msgstr "khác"
+msgstr "khác nhau"
msgid "behind "
-msgstr "đằng sau "
+msgstr "đứng sau "
msgid "ahead "
-msgstr "phía trước "
+msgstr "đứng trước "
#. TRANSLATORS: the action is e.g. "pull with rebase"
#, c-format
@@ -21185,26 +22468,29 @@ msgid "cannot %s: You have unstaged changes."
msgstr "không thể %s: Bạn có các thay đổi chưa được đưa lên bệ phóng."
msgid "additionally, your index contains uncommitted changes."
-msgstr ""
-"thêm vào đó, bảng mục lục của bạn có chứa các thay đổi chưa được chuyển giao."
+msgstr "ngoài ra, chỉ mục của bạn có chứa các thay đổi chưa được chuyển giao."
#, c-format
msgid "cannot %s: Your index contains uncommitted changes."
msgstr ""
-"không thể %s: Mục lục của bạn có chứa các thay đổi chưa được chuyển giao."
+"không thể %s: chỉ mục của bạn có chứa các thay đổi chưa được chuyển giao."
+
+#, c-format
+msgid "unknown style '%s' given for '%s'"
+msgstr "không hiểu style '%s' cho '%s'"
msgid ""
"Error: Your local changes to the following files would be overwritten by "
"merge"
msgstr ""
-"Lỗi: Các thay đổi nội bộ của bạn với các tập tin sau đây sẽ bị ghi đè bởi "
-"lệnh hòa trộn"
+"Lỗi: Các thay đổi nội bộ của bạn với các tập tin sau đây sẽ bị ghi đè khi "
+"hòa trộn"
msgid "Automated merge did not work."
-msgstr "Hòa trộn một cách tự động không làm việc."
+msgstr "Hòa trộn tự động không thành công."
msgid "Should not be doing an octopus."
-msgstr "Không thể thực hiện một octopus."
+msgstr "Không thể thực hiện hoà trộn kiểu bạch tuộc."
#, sh-format
msgid "Unable to find common commit with $pretty_name"
@@ -21223,7 +22509,7 @@ msgid "Trying simple merge with $pretty_name"
msgstr "Äang thá»­ hòa trá»™n Ä‘Æ¡n giản vá»›i $pretty_name"
msgid "Simple merge did not work, trying automatic merge."
-msgstr "Hòa trộn đơn giản không làm việc, thử hòa trộn tự động."
+msgstr "Hòa trộn đơn giản không thành công, thử hòa trộn tự động."
#, sh-format
msgid "usage: $dashless $USAGE"
@@ -21231,14 +22517,12 @@ msgstr "cách dùng: $dashless $USAGE"
#, sh-format
msgid "Cannot chdir to $cdup, the toplevel of the working tree"
-msgstr ""
-"Không thể chuyển thư mục (chdir) sang $cdup, thư mục ở mức cao nhất của cây "
-"làm việc"
+msgstr "Không thể chuyển thư mục sang $cdup, ở mức cao nhất của cây làm việc"
#, sh-format
msgid "fatal: $program_name cannot be used without a working tree."
msgstr ""
-"lá»—i nghiêm trá»ng: $program_name không thể được dùng ngoaoif thÆ° mục làm việc."
+"lá»—i nghiêm trá»ng: $program_name không thể được dùng ngoài thÆ° mục làm việc."
msgid "Cannot rewrite branches: You have unstaged changes."
msgstr ""
@@ -21251,12 +22535,11 @@ msgstr "Không thể $action: Bạn có các thay đổi chÆ°a được Ä‘Æ°a lÃ
#, sh-format
msgid "Cannot $action: Your index contains uncommitted changes."
msgstr ""
-"Không thể $action: Mục lục của bạn có chứa các thay đổi chưa được chuyển "
+"Không thể $action: chỉ mục của bạn có chứa các thay đổi chưa được chuyển "
"giao."
msgid "Additionally, your index contains uncommitted changes."
-msgstr ""
-"Thêm vào đó, bảng mục lục của bạn có chứa các thay đổi chưa được chuyển giao."
+msgstr "Ngoài ra, chỉ mục của bạn có chứa các thay đổi chưa được chuyển giao."
msgid "You need to run this command from the toplevel of the working tree."
msgstr "Bạn cần chạy lệnh này từ thư mục ở mức cao nhất của cây làm việc."
@@ -21264,360 +22547,73 @@ msgstr "Bạn cần chạy lệnh này từ thư mục ở mức cao nhất củ
msgid "Unable to determine absolute path of git directory"
msgstr "Không thể dò tìm Ä‘Æ°á»ng dẫn tuyệt đối của thÆ° mục git"
-#. TRANSLATORS: you can adjust this to align "git add -i" status menu
-#, perl-format
-msgid "%12s %12s %s"
-msgstr "%12s %12s %s"
-
-#, perl-format
-msgid "touched %d path\n"
-msgid_plural "touched %d paths\n"
-msgstr[0] "%d Ä‘Æ°á»ng dẫn đã touch (chạm)\n"
-
-msgid ""
-"If the patch applies cleanly, the edited hunk will immediately be\n"
-"marked for staging."
-msgstr ""
-"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sửa sẽ ngay lập tức\n"
-"được đánh dấu để chuyển lên bệ phóng."
-
-msgid ""
-"If the patch applies cleanly, the edited hunk will immediately be\n"
-"marked for stashing."
-msgstr ""
-"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sửa sẽ ngay lập tức\n"
-"được đánh dấu để tạm cất."
-
-msgid ""
-"If the patch applies cleanly, the edited hunk will immediately be\n"
-"marked for unstaging."
-msgstr ""
-"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sửa sẽ ngay lập tức\n"
-"được đánh dấu để bỠchuyển lên bệ phóng."
-
-msgid ""
-"If the patch applies cleanly, the edited hunk will immediately be\n"
-"marked for applying."
-msgstr ""
-"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sửa sẽ ngay lập tức\n"
-"được đánh dấu để áp dụng."
-
-msgid ""
-"If the patch applies cleanly, the edited hunk will immediately be\n"
-"marked for discarding."
-msgstr ""
-"Nếu miếng vá được áp dụng sạch sẽ, khúc đã sửa sẽ ngay lập tức\n"
-"được đánh dấu để loại bá»."
-
-#, perl-format
-msgid "failed to open hunk edit file for writing: %s"
-msgstr "gặp lỗi khi tập tin sửa khúc để ghi: %s"
-
-#, perl-format
-msgid ""
-"---\n"
-"To remove '%s' lines, make them ' ' lines (context).\n"
-"To remove '%s' lines, delete them.\n"
-"Lines starting with %s will be removed.\n"
-msgstr ""
-"---\n"
-"Äể gỡ bá» các dòng “%sâ€, làm chúng thành những dòng “ “ (ná»™i dung).\n"
-"Äể xóa bá» dòng “%sâ€, xóa chúng Ä‘i.\n"
-"Những dòng bắt đầu bằng %s sẽ bị loại bá».\n"
-
-#, perl-format
-msgid "failed to open hunk edit file for reading: %s"
-msgstr "gặp lá»—i khi mở tập tin khúc để Ä‘á»c: %s"
-
-msgid ""
-"y - stage this hunk\n"
-"n - do not stage this hunk\n"
-"q - quit; do not stage this hunk or any of the remaining ones\n"
-"a - stage this hunk and all later hunks in the file\n"
-"d - do not stage this hunk or any of the later hunks in the file"
-msgstr ""
-"y - đưa lên bệ phóng khúc này\n"
-"n - đừng đưa lên bệ phóng khúc này\n"
-"q - thoát; đừng đưa lên bệ phóng khúc này cũng như bất kỳ cái nào còn lại\n"
-"a - đưa lên bệ phóng khúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng đưa lên bệ phóng khúc này cũng như bất kỳ cái nào còn lại trong tập "
-"tin"
-
-msgid ""
-"y - stash this hunk\n"
-"n - do not stash this hunk\n"
-"q - quit; do not stash this hunk or any of the remaining ones\n"
-"a - stash this hunk and all later hunks in the file\n"
-"d - do not stash this hunk or any of the later hunks in the file"
-msgstr ""
-"y - tạm cất khúc này\n"
-"n - đừng tạm cất khúc này\n"
-"q - thoát; đừng tạm cất khúc này cũng như bất kỳ cái nào còn lại\n"
-"a - tạm cất khúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng tạm cất khúc này cũng như bất kỳ cái nào còn lại trong tập tin"
-
-msgid ""
-"y - unstage this hunk\n"
-"n - do not unstage this hunk\n"
-"q - quit; do not unstage this hunk or any of the remaining ones\n"
-"a - unstage this hunk and all later hunks in the file\n"
-"d - do not unstage this hunk or any of the later hunks in the file"
-msgstr ""
-"y - Ä‘Æ°a ra khá»i bệ phóng khúc này\n"
-"n - đừng Ä‘Æ°a ra khá»i bệ phóng khúc này\n"
-"q - thoát; đừng Ä‘Æ°a ra khá»i bệ phóng khúc này cÅ©ng nhÆ° bất kỳ cái nào còn "
-"lại\n"
-"a - Ä‘Æ°a ra khá»i bệ phóng khúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng Ä‘Æ°a ra khá»i bệ phóng khúc này cÅ©ng nhÆ° bất kỳ cái nào còn lại trong "
-"tập tin"
-
-msgid ""
-"y - apply this hunk to index\n"
-"n - do not apply this hunk to index\n"
-"q - quit; do not apply this hunk or any of the remaining ones\n"
-"a - apply this hunk and all later hunks in the file\n"
-"d - do not apply this hunk or any of the later hunks in the file"
-msgstr ""
-"y - áp dụng khúc này vào mục lục\n"
-"n - đừng áp dụng khúc này vào mục lục\n"
-"q - thoát; đừng áp dụng khúc này cũng như bất kỳ cái nào còn lại\n"
-"a - áp dụng khúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng áp dụng khúc này cũng như bất kỳ cái nào sau này trong tập tin"
-
-msgid ""
-"y - discard this hunk from worktree\n"
-"n - do not discard this hunk from worktree\n"
-"q - quit; do not discard this hunk or any of the remaining ones\n"
-"a - discard this hunk and all later hunks in the file\n"
-"d - do not discard this hunk or any of the later hunks in the file"
-msgstr ""
-"y - loại bá» khúc này khá»i cây làm việc\n"
-"n - đừng loại bá» khúc khá»i cây làm việc\n"
-"q - thoát; đừng loại bỠkhúc này cũng như bất kỳ cái nào còn lại\n"
-"a - loại bỠkhúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng loại bỠkhúc này cũng như bất kỳ cái nào sau này trong tập tin"
-
-msgid ""
-"y - discard this hunk from index and worktree\n"
-"n - do not discard this hunk from index and worktree\n"
-"q - quit; do not discard this hunk or any of the remaining ones\n"
-"a - discard this hunk and all later hunks in the file\n"
-"d - do not discard this hunk or any of the later hunks in the file"
-msgstr ""
-"y - loại bá» khúc này khá»i mục lục và cây làm việc\n"
-"n - đừng loại bá» khúc khá»i mục lục và cây làm việc\n"
-"q - thoát; đừng loại bỠkhúc này cũng như bất kỳ cái nào còn lại\n"
-"a - loại bỠkhúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng loại bỠkhúc này cũng như bất kỳ cái nào sau này trong tập tin"
-
-msgid ""
-"y - apply this hunk to index and worktree\n"
-"n - do not apply this hunk to index and worktree\n"
-"q - quit; do not apply this hunk or any of the remaining ones\n"
-"a - apply this hunk and all later hunks in the file\n"
-"d - do not apply this hunk or any of the later hunks in the file"
-msgstr ""
-"y - áp dụng khúc này vào mục lục và cây làm việc\n"
-"n - đừng áp dụng khúc vào mục lục và cây làm việc\n"
-"q - thoát; đừng áp dụng khúc này cũng như bất kỳ cái nào còn lại\n"
-"a - áp dụng khúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng áp dụng khúc này cũng như bất kỳ cái nào sau này trong tập tin"
-
-msgid ""
-"y - apply this hunk to worktree\n"
-"n - do not apply this hunk to worktree\n"
-"q - quit; do not apply this hunk or any of the remaining ones\n"
-"a - apply this hunk and all later hunks in the file\n"
-"d - do not apply this hunk or any of the later hunks in the file"
-msgstr ""
-"y - áp dụng khúc này vào cây làm việc\n"
-"n - đừng áp dụng khúc vào cây làm việc\n"
-"q - thoát; đừng áp dụng khúc này cũng như bất kỳ cái nào còn lại\n"
-"a - áp dụng khúc này và tất cả các khúc sau này trong tập tin\n"
-"d - đừng áp dụng khúc này cũng như bất kỳ cái nào sau này trong tập tin"
-
-msgid ""
-"g - select a hunk to go to\n"
-"/ - search for a hunk matching the given regex\n"
-"j - leave this hunk undecided, see next undecided hunk\n"
-"J - leave this hunk undecided, see next hunk\n"
-"k - leave this hunk undecided, see previous undecided hunk\n"
-"K - leave this hunk undecided, see previous hunk\n"
-"s - split the current hunk into smaller hunks\n"
-"e - manually edit the current hunk\n"
-"? - print help\n"
-msgstr ""
-"g - chá»n má»™t khúc muốn tá»›i\n"
-"/ - tìm một khúc khớp với biểu thức chính quy đưa ra\n"
-"j - để lại khúc này là chưa quyết định, xem khúc chưa quyết định kế\n"
-"J - để lại khúc này là chưa quyết định, xem khúc kế\n"
-"k - để lại khúc này là chưa quyết định, xem khúc chưa quyết định kế trước\n"
-"K - để lại khúc này là chưa quyết định, xem khúc kế trước\n"
-"s - chia khúc hiện tại thành các khúc nhỠhơn\n"
-"e - sửa bằng tay khúc hiện hành\n"
-"? - in trợ giúp\n"
-
-msgid "The selected hunks do not apply to the index!\n"
-msgstr "Các khúc đã chá»n không được áp dụng vào bảng mục lục!\n"
-
-#, perl-format
-msgid "ignoring unmerged: %s\n"
-msgstr "bỠqua những thứ chưa hòa trộn: %s\n"
-
-#, perl-format
-msgid "Apply mode change to worktree [y,n,q,a,d%s,?]? "
-msgstr "Ãp dụng thay đổi chế Ä‘á»™ cho cây làm việc [y,n,q,a,d%s,?]? "
-
-#, perl-format
-msgid "Apply deletion to worktree [y,n,q,a,d%s,?]? "
-msgstr "Ãp dụng việc xóa cho cây làm việc [y,n,q,a,d%s,?]? "
-
-#, perl-format
-msgid "Apply addition to worktree [y,n,q,a,d%s,?]? "
-msgstr "Ãp dụng việc thêm cho cây làm việc [y,n,q,a,d%s,?]? "
-
-#, perl-format
-msgid "Apply this hunk to worktree [y,n,q,a,d%s,?]? "
-msgstr "Ãp dụng khúc này vào cây làm việc [y,n,q,a,d%s,?]? "
-
-msgid "No other hunks to goto\n"
-msgstr "Không còn khúc nào để mà nhảy đến\n"
-
-#, perl-format
-msgid "Invalid number: '%s'\n"
-msgstr "Số không hợp lệ: “%sâ€\n"
-
-#, perl-format
-msgid "Sorry, only %d hunk available.\n"
-msgid_plural "Sorry, only %d hunks available.\n"
-msgstr[0] "Rất tiếc, chỉ có sẵn %d khúc.\n"
-
-msgid "No other hunks to search\n"
-msgstr "Không còn khúc nào để mà tìm kiếm\n"
-
-#, perl-format
-msgid "Malformed search regexp %s: %s\n"
-msgstr "Äịnh dạng tìm kiếm của biểu thức chính quy không đúng %s: %s\n"
-
-msgid "No hunk matches the given pattern\n"
-msgstr "Không thấy khúc nào khớp mẫu đã cho\n"
-
-msgid "No previous hunk\n"
-msgstr "Không có khúc kế trước\n"
-
-msgid "No next hunk\n"
-msgstr "Không có khúc kế tiếp\n"
-
-msgid "Sorry, cannot split this hunk\n"
-msgstr "Rất tiếc, không thể chia nhỠkhúc này\n"
-
-#, perl-format
-msgid "Split into %d hunk.\n"
-msgid_plural "Split into %d hunks.\n"
-msgstr[0] "Chi nhỠthành %d khúc.\n"
-
-msgid "Sorry, cannot edit this hunk\n"
-msgstr "Rất tiếc, không thể sửa khúc này\n"
-
-#. TRANSLATORS: please do not translate the command names
-#. 'status', 'update', 'revert', etc.
-msgid ""
-"status - show paths with changes\n"
-"update - add working tree state to the staged set of changes\n"
-"revert - revert staged set of changes back to the HEAD version\n"
-"patch - pick hunks and update selectively\n"
-"diff - view diff between HEAD and index\n"
-"add untracked - add contents of untracked files to the staged set of "
-"changes\n"
-msgstr ""
-"status - hiển thị các Ä‘Æ°á»ng dẫn vá»›i các thay đổi\n"
-"update - đặt trạng thái cây làm việc thành tập hợp các thay đổi đã "
-"đặt lên bệ phóng\n"
-"revert - hoàn nguyên tập hợp các thay đổi đã đặt lên bệ phóng trở lại "
-"phiên bản HEAD\n"
-"patch - cậy các khúc và cập nhật có lá»±a chá»n\n"
-"diff\t - xem khác biệt giữa HEAD và mục lục\n"
-"add untracked - thêm nội dung các các tập tin chưa theo dõi và tập hợp các "
-"thay đổi đã đặt lên bệ phóng\n"
-
-msgid "missing --"
-msgstr "thiếu --"
-
-#, perl-format
-msgid "unknown --patch mode: %s"
-msgstr "không hiểu chế độ --patch: %s"
-
-#, perl-format
-msgid "invalid argument %s, expecting --"
-msgstr "đối số không hợp lệ %s, cần --"
-
msgid "local zone differs from GMT by a non-minute interval\n"
-msgstr "múi giá» ná»™i bá»™ khác biệt vá»›i GMT bởi khoảng thá»i gian không-phút\n"
+msgstr "múi giá» ná»™i bá»™ lệch vá»›i GMT má»™t khoảng thá»i gian không-tròn-phút\n"
msgid "local time offset greater than or equal to 24 hours\n"
-msgstr "khoảng bù thá»i gian ná»™i bá»™ lá»›n hÆ¡n hoặc bằng 24 giá»\n"
+msgstr "Ä‘á»™ lệch thá»i gian ná»™i bá»™ lá»›n hÆ¡n hoặc bằng 24 giá»\n"
#, perl-format
msgid "fatal: command '%s' died with exit code %d"
-msgstr "lá»—i nghiêm trá»ng: lệnh “%s†chết vá»›i mã thoát %d"
+msgstr "lá»—i nghiêm trá»ng: lệnh '%s' đã thoát vá»›i mã %d"
msgid "the editor exited uncleanly, aborting everything"
-msgstr "trình soạn thảo thoát không sạch sẽ, bãi bá» má»i thứ"
+msgstr "trình soạn thảo thoát không thành công, huỷ bỠcác thay đổi"
#, perl-format
msgid ""
"'%s' contains an intermediate version of the email you were composing.\n"
-msgstr "“%s†có chưa một phiên bản trung gian của thư bạn đã soạn.\n"
+msgstr "'%s' có chứa một phiên bản trung gian của email bạn đã soạn.\n"
#, perl-format
msgid "'%s.final' contains the composed email.\n"
-msgstr "“%s.final†chứa thư điện tử đã soạn thảo.\n"
+msgstr "'%s.final' chứa emal đã soạn thảo.\n"
msgid "--dump-aliases incompatible with other options\n"
-msgstr "--dump-aliases xung khắc vá»›i các tùy chá»n khác\n"
+msgstr "--dump-aliases không tÆ°Æ¡ng thích vá»›i các tùy chá»n khác\n"
msgid ""
"fatal: found configuration options for 'sendmail'\n"
"git-send-email is configured with the sendemail.* options - note the 'e'.\n"
"Set sendemail.forbidSendmailVariables to false to disable this check.\n"
msgstr ""
-"lá»—i nghiêm trá»ng: tìm thấy các tùy chá»n cấu hình cho “sendmailâ€\n"
-"git-send-email được cấu hình vá»›i các tùy chá»n sendemail.* - chú ý “eâ€.\n"
+"lá»—i nghiêm trá»ng: tìm thấy các tùy chá»n cấu hình có tên 'sendmail'\n"
+"git-send-email được cấu hình vá»›i các tùy chá»n sendemail.* - chú ý chữ 'e'.\n"
"Äặt sendemail.forbidSendmailVariables thành false để tắt kiểm tra này.\n"
msgid "Cannot run git format-patch from outside a repository\n"
-msgstr "Không thể chạy git format-patch ở ngoài một kho chứa\n"
+msgstr "Không thể chạy git format-patch ở ngoài kho chứa\n"
msgid ""
"`batch-size` and `relogin` must be specified together (via command-line or "
"configuration option)\n"
msgstr ""
-"“batch-size†và “relogin†phải được chỉ định cùng với nhau (thông qua dòng "
-"lệnh hoặc tùy chá»n cấu hình)\n"
+"'batch-size' và 'relogin' phải được chỉ định cùng nhau (thông qua dòng lệnh "
+"hoặc tùy chá»n cấu hình)\n"
#, perl-format
msgid "Unknown --suppress-cc field: '%s'\n"
-msgstr "Không hiểu trÆ°á»ng --suppress-cc: “%sâ€\n"
+msgstr "Không hiểu trÆ°á»ng --suppress-cc: '%s'\n"
#, perl-format
msgid "Unknown --confirm setting: '%s'\n"
-msgstr "Không hiểu cài đặt --confirm: “%sâ€\n"
+msgstr "Không hiểu cài đặt --confirm: '%s'\n"
#, perl-format
msgid "warning: sendmail alias with quotes is not supported: %s\n"
-msgstr "cảnh báo: bí danh sendmail với dấu trích dẫn không được hỗ trợ: %s\n"
+msgstr "cảnh báo: không hỗ trợ bí danh sendmail với dấu trích dẫn: %s\n"
#, perl-format
msgid "warning: `:include:` not supported: %s\n"
-msgstr "cảnh báo: “:include:“ không được hỗ trợ: %s\n"
+msgstr "cảnh báo: không hỗ trợ ':include:': %s\n"
#, perl-format
msgid "warning: `/file` or `|pipe` redirection not supported: %s\n"
-msgstr "cảnh báo: chuyển hướng “/file“ hay “|pipe“ không được hỗ trợ: %s\n"
+msgstr "cảnh báo: không hỗ trợ chuyển hướng '/file' hay '|pipe': %s\n"
#, perl-format
msgid "warning: sendmail line is not recognized: %s\n"
-msgstr "cảnh báo: dòng sendmail không nhận ra được: %s\n"
+msgstr "cảnh báo: không hiểu dòng cấu hình sendmail: %s\n"
#, perl-format
msgid ""
@@ -21627,15 +22623,15 @@ msgid ""
" * Saying \"./%s\" if you mean a file; or\n"
" * Giving --format-patch option if you mean a range.\n"
msgstr ""
-"Tập tin “%s†đã có sẵn nhưng nó có lẽ cũng là chuẩn bị của\n"
-"các miếng vá tạo lần chuyển giao. Vui lòng làm rõ ý bằng…\n"
+"Tập tin '%s' có tồn tại nhưng cũng có thể hiểu là cần tạo bản vá cho\n"
+"một khoảng các lần chuyển giao. Vui lòng làm rõ ý của bạn bằng...\n"
"\n"
-" * Nói \"./%s\" nếu ý bạn là một tập tin; hoặc\n"
-" * ÄÆ°a ra tùy chá»n --format-patch nếu ý bạn là chuẩn bị.\n"
+" * Ghi \"./%s\" nếu ý bạn là tập tin; hoặc\n"
+" * ÄÆ°a ra tùy chá»n --format-patch nếu ý bạn là tạo bản vá.\n"
#, perl-format
msgid "Failed to opendir %s: %s"
-msgstr "Gặp lá»—i khi mở thÆ° mục “%sâ€: %s"
+msgstr "Gặp lỗi khi opendir %s: %s"
msgid ""
"\n"
@@ -21643,7 +22639,7 @@ msgid ""
"\n"
msgstr ""
"\n"
-"Chưa chỉ định các tập tin miếng vá!\n"
+"Chưa chỉ định các tập tin bản vá!\n"
"\n"
#, perl-format
@@ -21652,7 +22648,7 @@ msgstr "Không có dòng chủ đỠtrong %s?"
#, perl-format
msgid "Failed to open for writing %s: %s"
-msgstr "Gặp lỗi khi mở “%s†để ghi: %s"
+msgstr "Gặp lỗi khi mở %s để ghi: %s"
msgid ""
"Lines beginning in \"GIT:\" will be removed.\n"
@@ -21662,21 +22658,21 @@ msgid ""
"Clear the body content if you don't wish to send a summary.\n"
msgstr ""
"Các dòng bắt đầu bằng \"GIT:\" sẽ bị xóa bá».\n"
-"Cân nhắc bao gồm một thống kê diff toàn thể hay bảng nội dung\n"
-"cho miếng vá mà bạn đang viết.\n"
+"Hãy cân nhắc bao gồm một bản diffstat hay chỉ mục\n"
+"cho bản vá bạn đang viết.\n"
"\n"
"Xóa nội dung phần thân nếu bạn không muốn gửi tóm tắt.\n"
#, perl-format
-msgid "Failed to open %s: %s"
-msgstr "Gặp lá»—i khi mở “%sâ€: %s"
-
-#, perl-format
msgid "Failed to open %s.final: %s"
msgstr "Gặp lỗi khi mở %s.final: %s"
+#, perl-format
+msgid "Failed to open %s: %s"
+msgstr "Gặp lỗi khi mở %s: %s"
+
msgid "Summary email is empty, skipping it\n"
-msgstr "Thư tổng thể là trống rỗng, nên bỠqua nó\n"
+msgstr "Thư tóm tắt trống, nên sẽ bỠqua\n"
#. TRANSLATORS: please keep [y/N] as is.
#, perl-format
@@ -21687,11 +22683,10 @@ msgid ""
"The following files are 8bit, but do not declare a Content-Transfer-"
"Encoding.\n"
msgstr ""
-"Các trÆ°á»ng sau đây là 8bit, nhÆ°ng không khai báo má»™t Content-Transfer-"
-"Encoding.\n"
+"Các trÆ°á»ng sau đây là 8bit, nhÆ°ng không khai báo Content-Transfer-Encoding.\n"
msgid "Which 8bit encoding should I declare [UTF-8]? "
-msgstr "Bảng mã 8bit nào tôi nên khai báo [UTF-8]? "
+msgstr "Nên khai báo bảng mã 8bit nào [UTF-8]? "
#, perl-format
msgid ""
@@ -21700,24 +22695,24 @@ msgid ""
"has the template subject '*** SUBJECT HERE ***'. Pass --force if you really "
"want to send.\n"
msgstr ""
-"Từ chối gửi bởi vì miếng vá\n"
+"Từ chối gửi vì bản vá\n"
"\t%s\n"
-"có chủ đỠở dạng mẫu “*** SUBJECT HERE ***â€. Dùng --force nếu bạn thá»±c sá»± "
+"có chủ đỠở dạng mẫu '*** SUBJECT HERE ***'. Dùng --force nếu bạn thực sự "
"muốn gửi.\n"
msgid "To whom should the emails be sent (if anyone)?"
-msgstr "Tá»›i ngÆ°á»i mà thÆ° được gá»­i (nếu có)?"
+msgstr "Gửi email đến ai (nếu có)?"
#, perl-format
msgid "fatal: alias '%s' expands to itself\n"
-msgstr "nghiêm trá»ng: bí danh “%s†được khai triển thành chính nó\n"
+msgstr "lá»—i nghiêm trá»ng: khai triển bí danh '%s' lại thành chính nó\n"
msgid "Message-ID to be used as In-Reply-To for the first email (if any)? "
-msgstr "Message-ID được dùng như là In-Reply-To cho thư đầu tiên (nếu có)? "
+msgstr "Dùng Message-ID như In-Reply-To cho email đầu tiên (nếu có)? "
#, perl-format
msgid "error: unable to extract a valid address from: %s\n"
-msgstr "lỗi: không thể rút trích một địa chỉ hợp lệ từ: %s\n"
+msgstr "lỗi: không thể trích xuất địa chỉ hợp lệ từ: %s\n"
#. TRANSLATORS: Make sure to include [q] [d] [e] in your
#. translation. The program will only accept English input
@@ -21727,7 +22722,7 @@ msgstr "Làm gì với địa chỉ này? (thoát[q]|xóa[d]|sửa[e]): "
#, perl-format
msgid "CA path \"%s\" does not exist"
-msgstr "ÄÆ°á»ng dẫn CA “%s†không tồn tại"
+msgstr "CA path '%s' không tồn tại"
msgid ""
" The Cc list above has been expanded by additional\n"
@@ -21741,28 +22736,28 @@ msgid ""
" run 'git config --global sendemail.confirm auto'.\n"
"\n"
msgstr ""
-" Danh sách Cc ở trên được diễn giải bằng các địa chỉ phụ\n"
-" thêm tìm thấy trong lá»i ghi chú lần chuyển giao của miếng vá.\n"
-" Theo mặc định send-email sẽ nhắc trước khi gửi bất cứ khi\n"
-" nào Ä‘iá»u này xảy ra. Cách hành xá»­ này được Ä‘iá»u khiển bởi cài\n"
+" Danh sách Cc ở trên đã được thêm các địa chỉ có trong\n"
+" nội dung lần chuyển giao của bản vá. Theo mặc định\n"
+" send-email sẽ nhắc bạn trÆ°á»›c khi gá»­i má»—i khi Ä‘iá»u này \n"
+" xảy ra. Bạn có thể Ä‘iá»u chỉnh hành vi này qua cài\n"
" đặt cấu hình sendemail.confirm.\n"
"\n"
-" Äể biết thêm chi tiết, hãy chạy lệnh “git send-email --helpâ€.\n"
-" Äể giữ lại cách hành xá»­ hiện nay, làm hết lá»i nhắn này,\n"
-" chạy “git config --global sendemail.confirm autoâ€.\n"
+" Äể biết thêm chi tiết, hãy chạy lệnh 'git send-email --help'.\n"
+" Äể tiếp tục sá»­ dụng hành vi này, nhÆ°ng bá» hiển thị lá»i nhắc,\n"
+" chạy 'git config --global sendemail.confirm auto'.\n"
"\n"
#. TRANSLATORS: Make sure to include [y] [n] [e] [q] [a] in your
#. translation. The program will only accept English input
#. at this point.
msgid "Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): "
-msgstr "Gửi thư này chứ? ([y]có|[n]không|[e]sửa|[q]thoát|[a]tất): "
+msgstr "Gửi email này chứ? ([y]có|[n]không|[e]sửa|[q]thoát|[a]tất): "
msgid "Send this email reply required"
-msgstr "Gá»­i thÆ° này trả lá»i yêu cầu"
+msgstr "Hãy trả lá»i yêu cầu gá»­i email"
msgid "The required SMTP server is not properly defined."
-msgstr "Máy phục vụ SMTP chưa được định nghĩa một cách thích hợp."
+msgstr "Máy chủ SMTP chưa được định nghĩa đúng cách."
#, perl-format
msgid "Server does not support STARTTLS! %s"
@@ -21774,8 +22769,7 @@ msgstr "STARTTLS gặp lỗi! %s"
msgid "Unable to initialize SMTP properly. Check config and use --smtp-debug."
msgstr ""
-"Không thể khởi tạo SMTP một cách đúng đắn. Kiểm tra cấu hình và dùng --smtp-"
-"debug."
+"Không thể khởi tạo SMTP đúng cách. Kiểm tra cấu hình và dùng --smtp-debug."
#, perl-format
msgid "Failed to send %s\n"
@@ -21790,51 +22784,55 @@ msgid "Sent %s\n"
msgstr "Gá»­i %s\n"
msgid "Dry-OK. Log says:\n"
-msgstr "Dry-OK. Nhật ký nói rằng:\n"
+msgstr "Thử gửi OK. Nhật ký ghi lại:\n"
msgid "OK. Log says:\n"
-msgstr "OK. Nhật ký nói rằng:\n"
+msgstr "OK. Nhật ký ghi lại:\n"
msgid "Result: "
msgstr "Kết quả: "
msgid "Result: OK\n"
-msgstr "Kết quả: Tốt\n"
+msgstr "Kết quả: OK\n"
#, perl-format
msgid "can't open file %s"
-msgstr "không thể mở tập tin “%sâ€"
+msgstr "không thể mở tập tin '%s'"
#, perl-format
msgid "(mbox) Adding cc: %s from line '%s'\n"
-msgstr "(mbox) Thêm cc: %s từ dòng “%sâ€\n"
+msgstr "(mbox) Thêm cc: %s từ dòng '%s'\n"
#, perl-format
msgid "(mbox) Adding to: %s from line '%s'\n"
-msgstr "(mbox) Äang thêm to: %s từ dòng “%sâ€\n"
+msgstr "(mbox) Thêm to: %s từ dòng '%s'\n"
#, perl-format
msgid "(non-mbox) Adding cc: %s from line '%s'\n"
-msgstr "(non-mbox) Thêm cc: %s từ dòng “%sâ€\n"
+msgstr "(non-mbox) Thêm cc: %s từ dòng '%s'\n"
#, perl-format
msgid "(body) Adding cc: %s from line '%s'\n"
-msgstr "(body) Thêm cc: %s từ dòng “%sâ€\n"
+msgstr "(body) Thêm cc: %s từ dòng '%s'\n"
#, perl-format
msgid "(%s) Could not execute '%s'"
-msgstr "(%s) Không thể thá»±c thi “%sâ€"
+msgstr "(%s) Không thể thực thi '%s'"
#, perl-format
-msgid "(%s) Adding %s: %s from: '%s'\n"
-msgstr "(%s) Äang thêm %s: %s từ: “%sâ€\n"
+msgid "(%s) Malformed output from '%s'"
+msgstr "(%s) Dòng đầu ra sai quy cách từ '%s'"
#, perl-format
msgid "(%s) failed to close pipe to '%s'"
-msgstr "(%s) gặp lá»—i khi đóng Ä‘Æ°á»ng ống đến “%sâ€"
+msgstr "(%s) gặp lỗi khi đóng pipe đến '%s'"
+
+#, perl-format
+msgid "(%s) Adding %s: %s from: '%s'\n"
+msgstr "(%s) Thêm %s: %s từ: '%s'\n"
msgid "cannot send message as 7bit"
-msgstr "không thể lấy gửi thư dạng 7 bít"
+msgstr "không thể gửi thư dạng 7bit"
msgid "invalid transfer encoding"
msgstr "bảng mã truyá»n không hợp lệ"
@@ -21845,9 +22843,9 @@ msgid ""
"%s\n"
"warning: no patches were sent\n"
msgstr ""
-"nghiêm trá»ng: %s: bị từ chối bởi móc %s\n"
+"nghiêm trá»ng: %s: bị từ chối bởi hook %s\n"
"%s\n"
-"cảnh báo: không có miếng vá nào được gửi đi\n"
+"cảnh báo: không gửi đi bản vá nào\n"
#, perl-format
msgid "unable to open %s: %s\n"
@@ -21858,307 +22856,14 @@ msgid ""
"fatal: %s:%d is longer than 998 characters\n"
"warning: no patches were sent\n"
msgstr ""
-"nghiêm trá»ng: %s: %d là dài hÆ¡n 998 ký tá»±\n"
-"cảnh báo: không có miếng vá nào được gửi đi\n"
+"nghiêm trá»ng: %s: %d dài hÆ¡n 998 ký tá»±\n"
+"cảnh báo: không có bản vá nào được gửi đi\n"
#, perl-format
msgid "Skipping %s with backup suffix '%s'.\n"
-msgstr "Bá» qua %s vá»›i hậu tố sao lÆ°u dá»± phòng “%sâ€.\n"
+msgstr "BỠqua %s với hậu tố sao lưu '%s'.\n"
#. TRANSLATORS: please keep "[y|N]" as is.
#, perl-format
msgid "Do you really want to send %s? [y|N]: "
msgstr "Bạn có thực sự muốn gửi %s? [y|N](có/KHÔNG): "
-
-#~ msgid "--preserve-merges was replaced by --rebase-merges"
-#~ msgstr "--preserve-merges đã bị thay thế bằng --rebase-merges"
-
-#, 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 sẽ bị thay thế bằng LF trong %s.\n"
-#~ "Tập tin sẽ có kiểu xuống dòng như bản gốc trong thư mục làm việc của bạn"
-
-#, 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 sẽ bị thay thế bằng CRLF trong %s.\n"
-#~ "Tập tin sẽ có kiểu xuống dòng như bản gốc trong thư mục làm việc của bạn"
-
-#, c-format
-#~ msgid "error reading section header '%s'"
-#~ msgstr "gặp lá»—i khi Ä‘á»c phần đầu của Ä‘oạn %s"
-
-#~ msgid "load_reverse_index: could not open pack"
-#~ msgstr "load_reverse_index: không thể mở gói"
-
-#, perl-format
-#~ msgid "fatal: %s: rejected by %s hook\n"
-#~ msgstr "lá»—i nghiêm trá»ng: %s: bị từ chối bởi móc %s\n"
-
-#~ msgid "git archive --list"
-#~ msgstr "git archive --list"
-
-#, c-format
-#~ msgid "unknown value for --diff-merges: %s"
-#~ msgstr "không hiểu giá trị cho --diff-merges: %s"
-
-#, c-format
-#~ msgid "invalid value '%s' for lsrefs.unborn"
-#~ msgstr "giá trị “%s†không hợp lệ cho lsrefs.unborn"
-
-#~ msgid "backend for `git stash -p`"
-#~ msgstr "ứng dụng chạy phía sau cho “git stash -pâ€"
-
-#, c-format
-#~ msgid "Invalid value for --empty: %s"
-#~ msgstr "Giá trị cho --empty không hợp lệ: %s"
-
-#, c-format
-#~ msgid "Invalid value for --patch-format: %s"
-#~ msgstr "Giá trị không hợp lệ cho --patch-format: %s"
-
-#, c-format
-#~ msgid "Invalid value for --show-current-patch: %s"
-#~ msgstr "Giá trị không hợp lệ cho --show-current-patch: %s"
-
-#~ msgid ""
-#~ "git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad "
-#~ "| --term-new]"
-#~ msgstr ""
-#~ "git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad "
-#~ "| --term-new]"
-
-#~ msgid "git bisect--helper --bisect-next"
-#~ msgstr "git bisect--helper --bisect-next"
-
-#~ msgid "git bisect--helper --bisect-visualize"
-#~ msgstr "git bisect--helper --bisect-visualize"
-
-#, c-format
-#~ msgid "invalid color '%s' in color.blame.repeatedLines"
-#~ msgstr "màu không hợp lệ “%s†trong color.blame.repeatedLines"
-
-#~ msgid "invalid value for blame.coloring"
-#~ msgstr "màu không hợp lệ cho blame.coloring"
-
-#~ msgid ""
-#~ "git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e "
-#~ "| -p | <type> | --textconv | --filters) [--path=<path>] <object>"
-#~ msgstr ""
-#~ "git cat-file (-t [--allow-unknown-type] | -s [--allow-unknown-type] | -e "
-#~ "| -p | <kiểu> | --textconv) | --filters) [--path=<Ä‘Æ°á»ng/dẫn>] <đối_tượng>"
-
-#~ msgid "show object type"
-#~ msgstr "hiển thị kiểu đối tượng"
-
-#~ msgid "exit with zero when there's no error"
-#~ msgstr "thoát với 0 khi không có lỗi"
-
-#~ msgid "show info and content of objects fed from the standard input"
-#~ msgstr ""
-#~ "hiển thị thông tin và nội dung của các đối tượng lấy từ đầu vào tiêu chuẩn"
-
-#~ msgid "show info about objects fed from the standard input"
-#~ msgstr "hiển thị các thông tin vỠđối tượng fed từ đầu vào tiêu chuẩn"
-
-#~ msgid "follow in-tree symlinks (used with --batch or --batch-check)"
-#~ msgstr ""
-#~ "theo liên kết má»m trong-cây (được dùng vá»›i --batch hay --batch-check)"
-
-#~ msgid "show all objects with --batch or --batch-check"
-#~ msgstr "hiển thị má»i đối tượng vá»›i --batch hay --batch-check"
-
-#~ msgid "do not order --batch-all-objects output"
-#~ msgstr "đừng sắp xếp đầu ra --batch-all-objects"
-
-#~ msgid "set up tracking mode (see git-pull(1))"
-#~ msgstr "cài đặt chế độ theo dõi (xem git-pull(1))"
-
-#~ msgid "Using both --reset-author and --author does not make sense"
-#~ msgstr "Sá»­ dụng cả hai tùy chá»n --reset-author và --author không hợp lý"
-
-#~ msgid "Options --squash and --fixup cannot be used together"
-#~ msgstr "Các tùy chá»n --squash và --fixup không thể sá»­ dụng cùng vá»›i nhau"
-
-#~ msgid "Only one of -c/-C/-F/--fixup can be used."
-#~ msgstr "Chỉ được dùng má»™t trong số tùy chá»n trong số -c/-C/-F/--fixup."
-
-#~ msgid "Option -m cannot be combined with -c/-C/-F."
-#~ msgstr "Tùy chá»n -m không thể được tổ hợp cùng vá»›i -c/-C/-F."
-
-#~ msgid ""
-#~ "Only one of --include/--only/--all/--interactive/--patch can be used."
-#~ msgstr ""
-#~ "Chỉ má»™t trong các tùy chá»n --include/--only/--all/--interactive/--patch "
-#~ "được sử dụng."
-
-#~ msgid "git count-objects [-v] [-H | --human-readable]"
-#~ msgstr "git count-objects [-v] [-H | --human-readable]"
-
-#, c-format
-#~ msgid "configuration fetch.output contains invalid value %s"
-#~ msgstr "phần cấu hình fetch.output có chứa giá-trị không hợp lệ %s"
-
-#~ msgid "--cached or --untracked cannot be used with --no-index"
-#~ msgstr "--cached hay --untracked không được sử dụng với --no-index"
-
-#~ msgid "--untracked cannot be used with --cached"
-#~ msgstr "--untracked không thể được sá»­ dụng vá»›i tùy chá»n --cached"
-
-#~ msgid "git hash-object --stdin-paths"
-#~ msgstr "git hash-object --stdin-paths"
-
-#~ msgid "git help [-g|--guides]"
-#~ msgstr "git help [-g|--guides]"
-
-#~ msgid "git help [-c|--config]"
-#~ msgstr "git help [-c|--config]"
-
-#~ msgid "git mktag"
-#~ msgstr "git mktag"
-
-#~ msgid "git mktree [-z] [--missing] [--batch]"
-#~ msgstr "git mktree [-z] [--missing] [--batch]"
-
-#~ msgid "read from stdin"
-#~ msgstr "Ä‘á»c từ đầu vào tiêu chuẩn"
-
-#~ msgid "git notes merge --commit [-v | -q]"
-#~ msgstr "git notes merge --commit [-v | -q]"
-
-#~ msgid "git notes merge --abort [-v | -q]"
-#~ msgstr "git notes merge --abort [-v | -q]"
-
-#~ msgid "git notes get-ref"
-#~ msgstr "git notes get-ref"
-
-#~ msgid "invalid value for --missing"
-#~ msgstr "giá trị cho --missing không hợp lệ"
-
-#~ msgid "git prune-packed [-n | --dry-run] [-q | --quiet]"
-#~ msgstr "git prune-packed [-n | --dry-run] [-q | --quiet]"
-
-#, c-format
-#~ msgid "Invalid value for %s: %s"
-#~ msgstr "Giá trị không hợp lệ %s: %s"
-
-#, c-format
-#~ msgid "Invalid value for pull.ff: %s"
-#~ msgstr "Giá trị không hợp lệ cho pull.ff: %s"
-
-#~ msgid "git rebase --continue | --abort | --skip | --edit-todo"
-#~ msgstr "git rebase --continue | --abort | --skip | --edit-todo"
-
-#, c-format
-#~ msgid "'%s' is not a valid timestamp"
-#~ msgstr "“%s†không phải là dấu thá»i gian hợp lệ"
-
-#~ msgid "git reflog [ show | expire | delete | exists ]"
-#~ msgstr "git reflog [ show | expire | delete | exists ]"
-
-#~ msgid "git remote [-v | --verbose]"
-#~ msgstr "git remote [-v | --verbose]"
-
-#~ msgid "git replace [-f] --convert-graft-file"
-#~ msgstr "git replace [-f] --convert-graft-file"
-
-#, c-format
-#~ msgid ""
-#~ "\n"
-#~ "It took %.2f seconds to enumerate unstaged changes after reset. You can\n"
-#~ "use '--quiet' to avoid this. Set the config setting reset.quiet to true\n"
-#~ "to make this the default.\n"
-#~ msgstr ""
-#~ "\n"
-#~ "Cần %.2f giây để kiểm đếm các thay đổi chưa đưa lên bệ phóng sau khi đặt "
-#~ "lại.\n"
-#~ "Bạn có thể sá»­ dụng “--quiet†để tránh việc này. Äặt reset.quiet thành "
-#~ "true trong\n"
-#~ "cài đặt config nếu bạn muốn thực hiện nó như là mặc định.\n"
-
-#~ msgid "git sparse-checkout list"
-#~ msgstr "git sparse-checkout list"
-
-#~ msgid "unable to upgrade repository format to enable worktreeConfig"
-#~ msgstr ""
-#~ "không thể nâng cấp định dạng kho lưu trữ để kích hoạt worktreeConfig"
-
-#~ msgid "git sparse-checkout init [--cone] [--[no-]sparse-index]"
-#~ msgstr "git sparse-checkout init [--cone] [--[no-]sparse-index]"
-
-#~ msgid "git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]"
-#~ msgstr "git sparse-checkout reapply [--[no-]cone] [--[no-]sparse-index]"
-
-#~ msgid "git sparse-checkout disable"
-#~ msgstr "git sparse-checkout disable"
-
-#~ msgid ""
-#~ "the stash.useBuiltin support has been removed!\n"
-#~ "See its entry in 'git help config' for details."
-#~ msgstr ""
-#~ "việc hỗ trợ stash.useBuiltin đã bị xóa!\n"
-#~ "Xem mục tin của nó trong “git help config†để biết chi tiết."
-
-#~ msgid "git stripspace [-s | --strip-comments]"
-#~ msgstr "git stripspace [-s | --strip-comments]"
-
-#~ msgid "git stripspace [-c | --comment-lines]"
-#~ msgstr "git stripspace [-c | --comment-lines]"
-
-#~ msgid "submodule--helper print-default-remote takes no arguments"
-#~ msgstr "submodule--helper print-default-remote takes không nhận tham số"
-
-#~ msgid "git submodule--helper update-clone [--prefix=<path>] [<path>...]"
-#~ msgstr ""
-#~ "git submodule--helper update-clone [--prefix=</Ä‘Æ°á»ng/dẫn>] [</Ä‘Æ°á»ng/dẫn>…]"
-
-#~ msgid "suppress output for update by rebase or merge"
-#~ msgstr "chặn kết xuất cho cập nhật bởi cải tổ hoặc hòa trộn"
-
-#~ msgid "overrides update mode in case the repository is a fresh clone"
-#~ msgstr "ghi đè chế Ä‘á»™ cập nhật trong trÆ°á»ng hợp kho lÆ°u trữ là bản sao má»›i"
-
-#~ msgid "depth for shallow fetch"
-#~ msgstr "chiá»u sâu lịch sá»­ muốn lấy vá»"
-
-#~ msgid "sha1"
-#~ msgstr "sha1"
-
-#~ msgid "SHA1 expected by superproject"
-#~ msgstr "SHA1 là cần thiết cho superproject"
-
-#~ msgid "subsha1"
-#~ msgstr "subsha1"
-
-#~ msgid "SHA1 of submodule's HEAD"
-#~ msgstr "SHA1 của HEAD của mô-đun-con"
-
-#~ msgid "git submodule--helper run-update-procedure [<options>] <path>"
-#~ msgstr ""
-#~ "git submodule--helper run-update-procedure [<các tùy chá»n>] </Ä‘Æ°á»ng/dẫn>"
-
-#~ msgid "git submodule--helper config --check-writeable"
-#~ msgstr "git submodule--helper config --check-writeable"
-
-#~ msgid "git update-server-info [--force]"
-#~ msgstr "git update-server-info [--force]"
-
-#~ msgid "Initialize and modify the sparse-checkout"
-#~ msgstr "Khởi tạo và sửa đổi sparse-checkout"
-
-#, sh-format
-#~ msgid ""
-#~ "Unable to find current ${remote_name}/${branch} revision in submodule "
-#~ "path '$sm_path'"
-#~ msgstr ""
-#~ "Không thể tìm thấy điểm xét duyệt hiện hành ${remote_name}/${branch} "
-#~ "trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “$sm_pathâ€"
-
-#, sh-format
-#~ msgid "Failed to recurse into submodule path '$displaypath'"
-#~ msgstr "Gặp lá»—i khi đệ quy vào trong Ä‘Æ°á»ng dẫn mô-Ä‘un-con “$displaypathâ€"
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 39efaf1012..4838c19b0b 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -103,6 +103,7 @@
# preferred pack | 首选包(多包索引中引入的首选包概念)
# promisor | 承诺者
# prune | 清除
+# pseudorefs | 伪引用
# pull | 拉,拉å–
# push | 推,推é€
# reachable | å¯è¾¾
@@ -153,8 +154,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2024-02-16 14:27+0800\n"
-"PO-Revision-Date: 2024-02-18 11:47+0800\n"
+"POT-Creation-Date: 2024-04-28 19:59+0800\n"
+"PO-Revision-Date: 2024-04-28 20:31+0800\n"
"Last-Translator: Teng Long <dyroneteng@gmail.com>\n"
"Language-Team: GitHub <https://github.com/dyrone/git/>\n"
"Language: zh_CN\n"
@@ -726,12 +727,12 @@ msgid ""
"---\n"
"To remove '%c' lines, make them ' ' lines (context).\n"
"To remove '%c' lines, delete them.\n"
-"Lines starting with %c will be removed.\n"
+"Lines starting with %s will be removed.\n"
msgstr ""
"---\n"
"è¦åˆ é™¤ '%c' 开始的行,使其æˆä¸º ' ' 开始的行(上下文)。\n"
"è¦åˆ é™¤ '%c' 开始的行,删除它们。\n"
-"以 %c 开始的行将被删除。\n"
+"以 %s 开始的行将被删除。\n"
#: add-patch.c
msgid ""
@@ -783,6 +784,7 @@ msgid ""
"/ - search for a hunk matching the given regex\n"
"s - split the current hunk into smaller hunks\n"
"e - manually edit the current hunk\n"
+"p - print the current hunk\n"
"? - print help\n"
msgstr ""
"j - ç»´æŒè¯¥å—未决状æ€ï¼ŒæŸ¥çœ‹ä¸‹ä¸€ä¸ªæœªå†³å—\n"
@@ -793,6 +795,7 @@ msgstr ""
"/ - 查找和给定正则表达å¼åŒ¹é…çš„å—\n"
"s - 拆分当å‰å—为更å°çš„å—\n"
"e - 手动编辑当å‰å—\n"
+"p - 显示当å‰å—\n"
"? - 显示帮助\n"
#: add-patch.c
@@ -872,8 +875,8 @@ msgstr ""
#: advice.c
#, c-format
-msgid "%shint: %.*s%s\n"
-msgstr "%sæ示:%.*s%s\n"
+msgid "%shint:%s%.*s%s\n"
+msgstr "%sæ示:%s%.*s%s\n"
#: advice.c
msgid "Cherry-picking is not possible because you have unmerged files."
@@ -1471,11 +1474,6 @@ msgstr[1] "应用 %%s 个补ä¸ï¼Œå…¶ä¸­ %d 个被拒ç»..."
#: apply.c
#, c-format
-msgid "truncating .rej filename to %.*s.rej"
-msgstr "截短 .rej 文件å为 %.*s.rej"
-
-#: apply.c
-#, c-format
msgid "cannot open %s"
msgstr "ä¸èƒ½æ‰“å¼€ %s"
@@ -2013,6 +2011,11 @@ msgstr "需è¦ä¸€ä¸ª %s 版本"
msgid "could not create file '%s'"
msgstr "ä¸èƒ½åˆ›å»ºæ–‡ä»¶ '%s'"
+#: bisect.c builtin/notes.c
+#, c-format
+msgid "unable to start 'show' for object '%s'"
+msgstr "ä¸èƒ½ä¸ºå¯¹è±¡ '%s' 开始 'show'"
+
#: bisect.c builtin/merge.c
#, c-format
msgid "could not read file '%s'"
@@ -2062,8 +2065,8 @@ msgid "--reverse and --first-parent together require specified latest commit"
msgstr "--reverse å’Œ --first-parent 共用,需è¦æŒ‡å®šæœ€æ–°çš„æ交"
#: blame.c builtin/commit.c builtin/log.c builtin/merge.c
-#: builtin/pack-objects.c builtin/shortlog.c midx.c pack-bitmap.c remote.c
-#: sequencer.c submodule.c
+#: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c
+#: remote.c sequencer.c submodule.c
msgid "revision walk setup failed"
msgstr "版本é历åˆå§‹åŒ–失败"
@@ -2180,6 +2183,10 @@ msgstr ""
msgid "'%s' is not a valid branch name"
msgstr "'%s' ä¸æ˜¯ä¸€ä¸ªæœ‰æ•ˆçš„分支å称"
+#: branch.c builtin/branch.c
+msgid "See `man git check-ref-format`"
+msgstr "查阅 `man git check-ref-format`"
+
#: branch.c
#, c-format
msgid "a branch named '%s' already exists"
@@ -2410,14 +2417,8 @@ msgid "adding embedded git repository: %s"
msgstr "æ­£åœ¨æ·»åŠ åµŒå…¥å¼ git 仓库:%s"
#: builtin/add.c
-msgid ""
-"Use -f if you really want to add them.\n"
-"Turn this message off by running\n"
-"\"git config advice.addIgnoredFile false\""
-msgstr ""
-"如果您确实è¦æ·»åŠ å®ƒä»¬ï¼Œä½¿ç”¨ -f å‚数。\n"
-"è¿è¡Œä¸‹é¢çš„命令æ¥å…³é—­æœ¬æ¶ˆæ¯\n"
-"\"git config advice.addIgnoredFile false\""
+msgid "Use -f if you really want to add them."
+msgstr "如果您确实想添加它们,请使用 -f 选项。"
#: builtin/add.c
msgid "adding files failed"
@@ -2440,14 +2441,8 @@ msgid "Nothing specified, nothing added.\n"
msgstr "没有指定文件,也没有文件被添加。\n"
#: builtin/add.c
-msgid ""
-"Maybe you wanted to say 'git add .'?\n"
-"Turn this message off by running\n"
-"\"git config advice.addEmptyPathspec false\""
-msgstr ""
-"也许您想è¦æ‰§è¡Œ 'git add .'?\n"
-"è¿è¡Œä¸‹é¢çš„命令æ¥å…³é—­æœ¬æ¶ˆæ¯\n"
-"\"git config advice.addEmptyPathspec false\""
+msgid "Maybe you wanted to say 'git add .'?"
+msgstr "也许您想è¦æ‰§è¡Œ 'git add .'?"
#: builtin/add.c builtin/check-ignore.c builtin/checkout.c builtin/clean.c
#: builtin/commit.c builtin/diff-tree.c builtin/grep.c builtin/mv.c
@@ -2467,8 +2462,8 @@ msgid "bad action '%s' for '%s'"
msgstr "'%2$s' 的错误动作 '%1$s'"
#: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c
-#: builtin/pull.c config.c diff-merges.c gpg-interface.c ls-refs.c
-#: parallel-checkout.c sequencer.c setup.c
+#: builtin/pull.c builtin/revert.c config.c diff-merges.c gpg-interface.c
+#: ls-refs.c parallel-checkout.c sequencer.c setup.c
#, c-format
msgid "invalid value for '%s': '%s'"
msgstr "'%s' 的值无效:'%s'"
@@ -2552,18 +2547,19 @@ msgstr "无法拆分补ä¸ã€‚"
#: builtin/am.c
#, c-format
-msgid "When you have resolved this problem, run \"%s --continue\"."
-msgstr "当您解决这一问题,执行 \"%s --continue\"。"
+msgid "When you have resolved this problem, run \"%s --continue\".\n"
+msgstr "当您解决这一问题之åŽï¼Œæ‰§è¡Œ \"%s --continue\"。\n"
#: builtin/am.c
#, c-format
-msgid "If you prefer to skip this patch, run \"%s --skip\" instead."
-msgstr "如果您想è¦è·³è¿‡è¿™ä¸€è¡¥ä¸ï¼Œåˆ™æ‰§è¡Œ \"%s --skip\"。"
+msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n"
+msgstr "如果您想è¦è·³è¿‡è¿™ä¸€è¡¥ä¸ï¼Œåˆ™æ‰§è¡Œ \"%s --skip\"。\n"
#: builtin/am.c
#, c-format
-msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"."
-msgstr "è‹¥è¦æŠŠç©ºè¡¥ä¸è®°å½•ä¸ºç©ºæ交,执行 \"%s --allow-empty\"。"
+msgid ""
+"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"
+msgstr "è‹¥è¦æŠŠç©ºè¡¥ä¸è®°å½•ä¸ºç©ºæ交,执行 \"%s --allow-empty\"。\n"
#: builtin/am.c
#, c-format
@@ -3623,11 +3619,11 @@ msgstr "分支已拷è´ï¼Œä½†æ›´æ–°é…置文件失败"
msgid ""
"Please edit the description for the branch\n"
" %s\n"
-"Lines starting with '%c' will be stripped.\n"
+"Lines starting with '%s' will be stripped.\n"
msgstr ""
"请编辑分支的æè¿°\n"
" %s\n"
-"以 '%c' 开头的行将被过滤。\n"
+"以 '%s' 开头的行将被过滤。\n"
#: builtin/branch.c
msgid "Generic options"
@@ -3883,10 +3879,12 @@ msgstr "ä¸æ˜¯åœ¨ git 仓库中执行 - 没有å¯æ˜¾ç¤ºçš„é’©å­\n"
#: builtin/bugreport.c
msgid ""
-"git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"git bugreport [(-o | --output-directory) <path>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
" [--diagnose[=<mode>]]"
msgstr ""
-"git bugreport [-o|--output-directory <文件>] [(-s|--suffix) <æ ¼å¼>]\n"
+"git bugreport [-o | --output-directory <文件>]\n"
+" [(-s | --suffix) <æ ¼å¼> | --no-suffix]\n"
" [--diagnose[=<模å¼>]"
#: builtin/bugreport.c
@@ -4488,6 +4486,12 @@ msgstr "'%s'ã€'%s' 或 '%s' ä¸èƒ½åœ¨æ£€å‡ºä¸€ä¸ªæ ‘时使用"
msgid "path '%s' is unmerged"
msgstr "路径 '%s' 未åˆå¹¶"
+#: builtin/checkout.c builtin/grep.c builtin/merge-tree.c builtin/reset.c
+#: merge-ort.c reset.c sequencer.c tree-walk.c
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr "无法读å–树(%s)"
+
#: builtin/checkout.c
msgid "you need to resolve your current index first"
msgstr "您需è¦å…ˆè§£å†³å½“å‰ç´¢å¼•çš„冲çª"
@@ -4755,6 +4759,11 @@ msgid "missing branch or commit argument"
msgstr "缺少分支或æ交å‚æ•°"
#: builtin/checkout.c
+#, c-format
+msgid "unknown conflict style '%s'"
+msgstr "未知的冲çªé£Žæ ¼ '%s'"
+
+#: builtin/checkout.c
msgid "perform a 3-way merge with the new branch"
msgstr "和新的分支执行三方åˆå¹¶"
@@ -5074,18 +5083,8 @@ msgid "remove only ignored files"
msgstr "åªåˆ é™¤å¿½ç•¥çš„文件"
#: builtin/clean.c
-msgid ""
-"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to "
-"clean"
-msgstr ""
-"clean.requireForce 设置为 true 且未æä¾› -iã€-n 或 -f 选项,拒ç»æ‰§è¡Œæ¸…ç†åŠ¨ä½œ"
-
-#: builtin/clean.c
-msgid ""
-"clean.requireForce defaults to true and neither -i, -n, nor -f given; "
-"refusing to clean"
-msgstr ""
-"clean.requireForce 默认为 true 且未æä¾› -iã€-n 或 -f 选项,拒ç»æ‰§è¡Œæ¸…ç†åŠ¨ä½œ"
+msgid "clean.requireForce is true and -f not given: refusing to clean"
+msgstr "clean.requireForce 设置为 true 且未æä¾› -f 选项:拒ç»æ‰§è¡Œæ¸…ç†åŠ¨ä½œ"
#: builtin/clone.c
msgid "git clone [<options>] [--] <repo> [<dir>]"
@@ -5104,8 +5103,8 @@ msgid "create a bare repository"
msgstr "创建一个纯仓库"
#: builtin/clone.c
-msgid "create a mirror repository (implies bare)"
-msgstr "创建一个镜åƒä»“库(也是纯仓库)"
+msgid "create a mirror repository (implies --bare)"
+msgstr "创建一个镜åƒä»“库(éšå« --bare)"
#: builtin/clone.c
msgid "to clone from a local repository"
@@ -5507,6 +5506,11 @@ msgid "padding space between columns"
msgstr "两列之间的填充空间"
#: builtin/column.c
+#, c-format
+msgid "%s must be non-negative"
+msgstr "%s 必须为éžè´Ÿæ•´æ•°"
+
+#: builtin/column.c
msgid "--command must be the first argument"
msgstr "--command 必须是第一个å‚æ•°"
@@ -5839,7 +5843,7 @@ msgid ""
"in the current commit message"
msgstr "无法选择一个未被当å‰æ交说明使用的注释字符"
-#: builtin/commit.c builtin/merge-tree.c
+#: builtin/commit.c
#, c-format
msgid "could not lookup commit '%s'"
msgstr "ä¸èƒ½æŸ¥è¯¢æ交 '%s'"
@@ -5884,35 +5888,35 @@ msgstr "ä¸èƒ½å†™æ交模版"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored.\n"
-msgstr "请为您的å˜æ›´è¾“å…¥æ交说明。以 '%c' 开始的行将被忽略。\n"
+"with '%s' will be ignored.\n"
+msgstr "请为您的å˜æ›´è¾“å…¥æ交说明。以 '%s' 开始的行将被忽略。\n"
#: builtin/commit.c
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored, and an empty message aborts the commit.\n"
+"with '%s' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
-"请为您的å˜æ›´è¾“å…¥æ交说明。以 '%c' 开始的行将被忽略,而一个空的æ交\n"
+"请为您的å˜æ›´è¾“å…¥æ交说明。以 '%s' 开始的行将被忽略,而一个空的æ交\n"
"说明将会终止æ交。\n"
#: builtin/commit.c
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
msgstr ""
-"请为您的å˜æ›´è¾“å…¥æ交说明。以 '%c' 开始的行将被ä¿ç•™ï¼Œå¦‚果您愿æ„\n"
+"请为您的å˜æ›´è¾“å…¥æ交说明。以 '%s' 开始的行将被ä¿ç•™ï¼Œå¦‚果您愿æ„\n"
"也å¯ä»¥åˆ é™¤å®ƒä»¬ã€‚\n"
#: builtin/commit.c
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
-"请为您的å˜æ›´è¾“å…¥æ交说明。以 '%c' 开始的行将被ä¿ç•™ï¼Œå¦‚果您愿æ„\n"
+"请为您的å˜æ›´è¾“å…¥æ交说明。以 '%s' 开始的行将被ä¿ç•™ï¼Œå¦‚果您愿æ„\n"
"也å¯ä»¥åˆ é™¤å®ƒä»¬ã€‚一个空的æ交说明将会终止æ交。\n"
#: builtin/commit.c
@@ -6141,7 +6145,7 @@ msgstr "日期"
msgid "override date for commit"
msgstr "æ交时覆盖日期"
-#: builtin/commit.c builtin/merge-tree.c parse-options.h ref-filter.h
+#: builtin/commit.c parse-options.h ref-filter.h
msgid "commit"
msgstr "æ交"
@@ -6466,6 +6470,10 @@ msgid "with --get, use default value when missing entry"
msgstr "使用 --get å‚数,当缺少设置时使用默认值"
#: builtin/config.c
+msgid "human-readable comment string (# will be prepended as needed)"
+msgstr "人类å¯è¯»çš„注释字符串(# 将根æ®éœ€è¦æ·»åŠ åˆ°å‰é¢ï¼‰"
+
+#: builtin/config.c
#, c-format
msgid "wrong number of arguments, should be %d"
msgstr "错误的å‚数个数,应该为 %d 个"
@@ -6578,6 +6586,10 @@ msgid "--default is only applicable to --get"
msgstr "--default 仅适用于 --get"
#: builtin/config.c
+msgid "--comment is only applicable to add/set/replace operations"
+msgstr "--comment 仅适用于 add/set/replace æ“作"
+
+#: builtin/config.c
msgid "--fixed-value only applies with 'value-pattern'"
msgstr "--fixed-value 仅适用于有 '值模å¼'"
@@ -6843,7 +6855,7 @@ msgstr "--merge-base 仅适用于两个æ交"
#: builtin/diff.c
#, c-format
msgid "'%s': not a regular file or symlink"
-msgstr "'%s':ä¸æ˜¯ä¸€ä¸ªæ­£è§„文件或符å·é“¾æŽ¥"
+msgstr "'%s':ä¸æ˜¯ä¸€ä¸ªæ™®é€šæ–‡ä»¶æˆ–符å·é“¾æŽ¥"
#: builtin/diff.c
msgid "no merge given, only parents."
@@ -7623,6 +7635,10 @@ msgid "read reference patterns from stdin"
msgstr "从标准输入读å–引用的模å¼"
#: builtin/for-each-ref.c
+msgid "also include HEAD ref and pseudorefs"
+msgstr "还包括 HEAD 引用和伪引用"
+
+#: builtin/for-each-ref.c
msgid "unknown arguments supplied with --stdin"
msgstr "为 --stdin æ供了未知的命令å‚æ•°"
@@ -8397,11 +8413,6 @@ msgstr "没有线程支æŒï¼Œå¿½ç•¥ %s"
#: builtin/grep.c
#, c-format
-msgid "unable to read tree (%s)"
-msgstr "无法读å–树(%s)"
-
-#: builtin/grep.c
-#, c-format
msgid "unable to read tree %s"
msgstr "无法读å–æ ‘ %s"
@@ -9164,13 +9175,46 @@ msgstr "--separate-git-dir ä¸èƒ½ç”¨äºŽçº¯ä»“库"
#: builtin/interpret-trailers.c
msgid ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n"
+" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
" [--parse] [<file>...]"
msgstr ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
" [(--trailer (<é”®|键别å>)[(=|:)<值>])...]\n"
" [--parse] [<文件>...]"
+#: builtin/interpret-trailers.c wrapper.c
+#, c-format
+msgid "could not stat %s"
+msgstr "ä¸èƒ½å¯¹ %s 调用 stat"
+
+#: builtin/interpret-trailers.c
+#, c-format
+msgid "file %s is not a regular file"
+msgstr "文件 %s ä¸æ˜¯ä¸€ä¸ªæ™®é€šæ–‡ä»¶"
+
+#: builtin/interpret-trailers.c
+#, c-format
+msgid "file %s is not writable by user"
+msgstr "文件 %s 用户ä¸å¯å†™"
+
+#: builtin/interpret-trailers.c
+msgid "could not open temporary file"
+msgstr "ä¸èƒ½æ‰“开临时文件"
+
+#: builtin/interpret-trailers.c
+#, c-format
+msgid "could not read input file '%s'"
+msgstr "ä¸èƒ½è¯»å–输入文件 '%s'"
+
+#: builtin/interpret-trailers.c builtin/mktag.c imap-send.c
+msgid "could not read from stdin"
+msgstr "ä¸èƒ½è‡ªæ ‡å‡†è¾“入读å–"
+
+#: builtin/interpret-trailers.c
+#, c-format
+msgid "could not rename temporary file to %s"
+msgstr "ä¸èƒ½é‡å‘½å临时文件为 %s"
+
#: builtin/interpret-trailers.c
msgid "edit files in place"
msgstr "在原ä½ç¼–辑文件"
@@ -9669,21 +9713,6 @@ msgid "could not get object info about '%s'"
msgstr "无法获得关于 '%s' 的对象信æ¯"
#: builtin/ls-files.c
-#, c-format
-msgid "bad ls-files format: element '%s' does not start with '('"
-msgstr "åçš„ ls-files æ ¼å¼ï¼šå…ƒç´  '%s' 没有以 '(' 开头"
-
-#: builtin/ls-files.c
-#, c-format
-msgid "bad ls-files format: element '%s' does not end in ')'"
-msgstr "åçš„ ls-files æ ¼å¼ï¼šå…ƒç´  '%s' 没有以 ')' 结尾"
-
-#: builtin/ls-files.c
-#, c-format
-msgid "bad ls-files format: %%%.*s"
-msgstr "åçš„ ls-files æ ¼å¼: %%%.*s"
-
-#: builtin/ls-files.c
msgid "git ls-files [<options>] [<file>...]"
msgstr "git ls-files [<选项>] [<文件>...]"
@@ -9775,7 +9804,7 @@ msgstr "显示相对于顶级目录的文件å"
msgid "if any <file> is not in the index, treat this as an error"
msgstr "如果任何 <文件> 都ä¸åœ¨ç´¢å¼•åŒºï¼Œè§†ä¸ºé”™è¯¯"
-#: builtin/ls-files.c
+#: builtin/ls-files.c builtin/merge-tree.c
msgid "tree-ish"
msgstr "树对象"
@@ -9854,21 +9883,6 @@ msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
msgstr "git ls-tree [<选项>] <树对象> [<路径>...]"
#: builtin/ls-tree.c
-#, c-format
-msgid "bad ls-tree format: element '%s' does not start with '('"
-msgstr "åçš„ ls-tree æ ¼å¼ï¼šå…ƒç´  '%s' 没有以 '(' 开头"
-
-#: builtin/ls-tree.c
-#, c-format
-msgid "bad ls-tree format: element '%s' does not end in ')'"
-msgstr "åçš„ ls-tree æ ¼å¼ï¼šå…ƒç´  '%s' 没有以 ')' 结尾"
-
-#: builtin/ls-tree.c
-#, c-format
-msgid "bad ls-tree format: %%%.*s"
-msgstr "åçš„ ls-tree æ ¼å¼: %%%.*s"
-
-#: builtin/ls-tree.c
msgid "only show trees"
msgstr "åªæ˜¾ç¤ºæ ‘"
@@ -10018,7 +10032,9 @@ msgstr ""
msgid ""
"option diff-algorithm accepts \"myers\", \"minimal\", \"patience\" and "
"\"histogram\""
-msgstr "选项 diff-algorithm 接å—å‚æ•° \"myers\"ã€\"minimal\"ã€\"patience\" å’Œ \"histogram\""
+msgstr ""
+"选项 diff-algorithm 接å—å‚æ•° \"myers\"ã€\"minimal\"ã€\"patience\" å’Œ "
+"\"histogram\""
#: builtin/merge-file.c
msgid "send results to standard output"
@@ -10108,6 +10124,11 @@ msgstr "无法解æžå¼•ç”¨ '%s'"
msgid "Merging %s with %s\n"
msgstr "åˆå¹¶ %s å’Œ %s\n"
+#: builtin/merge-tree.c
+#, c-format
+msgid "could not parse as tree '%s'"
+msgstr "无法解æžä¸ºæ ‘对象 '%s'"
+
#: builtin/merge-tree.c builtin/merge.c
msgid "not something we can merge"
msgstr "ä¸æ˜¯å¯ä»¥åˆå¹¶çš„东西"
@@ -10370,9 +10391,9 @@ msgstr "空的æ交说明会终止æ交。\n"
#: builtin/merge.c
#, c-format
msgid ""
-"Lines starting with '%c' will be ignored, and an empty message aborts\n"
+"Lines starting with '%s' will be ignored, and an empty message aborts\n"
"the commit.\n"
-msgstr "以 '%c' 开始的行将被忽略,而空的æ交说明将终止æ交。\n"
+msgstr "以 '%s' 开始的行将被忽略,而空的æ交说明将终止æ交。\n"
#: builtin/merge.c
msgid "Empty commit message."
@@ -10565,10 +10586,6 @@ msgstr "ä¸èƒ½è¯»å–被标记的对象 '%s'"
msgid "object '%s' tagged as '%s', but is a '%s' type"
msgstr "对象 '%s' 被标记为 '%s',然而是一个 '%s' 类型"
-#: builtin/mktag.c imap-send.c trailer.c
-msgid "could not read from stdin"
-msgstr "ä¸èƒ½è‡ªæ ‡å‡†è¾“入读å–"
-
#: builtin/mktag.c
msgid "tag on stdin did not pass our strict fsck check"
msgstr "标准输入上的标签未通过我们严格的 fsck 检查"
@@ -10901,11 +10918,6 @@ msgid "Write/edit the notes for the following object:"
msgstr "为下é¢çš„对象写/编辑说明:"
#: builtin/notes.c
-#, c-format
-msgid "unable to start 'show' for object '%s'"
-msgstr "ä¸èƒ½ä¸ºå¯¹è±¡ '%s' 开始 'show'"
-
-#: builtin/notes.c
msgid "could not read 'show' output"
msgstr "ä¸èƒ½è¯»å– 'show' 的输出"
@@ -11677,10 +11689,11 @@ msgstr "æ‹’ç»åœ¨æœªæŒ‡å®š --i-still-use-this 选项时è¿è¡Œ"
#: builtin/pack-refs.c
msgid ""
-"git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude "
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
"<pattern>]"
msgstr ""
-"git pack-refs [--all] [--no-prune] [--include <模å¼>] [--exclude <模å¼>]"
+"git pack-refs [--all] [--no-prune] [--auto] [--include <模å¼>] [--exclude <模"
+"å¼>]"
#: builtin/pack-refs.c
msgid "pack everything"
@@ -11691,6 +11704,10 @@ msgid "prune loose refs (default)"
msgstr "清除æ¾æ•£çš„引用(默认)"
#: builtin/pack-refs.c
+msgid "auto-pack refs as needed"
+msgstr "按需对引用自动打包"
+
+#: builtin/pack-refs.c
msgid "references to include"
msgstr "需包å«çš„引用"
@@ -12451,19 +12468,6 @@ msgid "could not remove '%s'"
msgstr "无法删除 '%s'"
#: builtin/rebase.c
-msgid ""
-"Resolve all conflicts manually, mark them as resolved with\n"
-"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
-"You can instead skip this commit: run \"git rebase --skip\".\n"
-"To abort and get back to the state before \"git rebase\", run \"git rebase --"
-"abort\"."
-msgstr ""
-"手工解决所有冲çªï¼Œæ‰§è¡Œ \"git add/rm <冲çªçš„文件>\" 标记\n"
-"冲çªå·²è§£å†³ï¼Œç„¶åŽæ‰§è¡Œ \"git rebase --continue\"。您也å¯ä»¥æ‰§è¡Œ\n"
-"\"git rebase --skip\" 命令跳过这个æ交。如果想è¦ç»ˆæ­¢æ‰§è¡Œå¹¶å›žåˆ°\n"
-"\"git rebase\" 执行之å‰çš„状æ€ï¼Œæ‰§è¡Œ \"git rebase --abort\"。"
-
-#: builtin/rebase.c
#, c-format
msgid ""
"\n"
@@ -12496,11 +12500,15 @@ msgid "apply options and merge options cannot be used together"
msgstr "应用选项和åˆå¹¶é€‰é¡¹ä¸èƒ½åŒæ—¶ä½¿ç”¨"
#: builtin/rebase.c
+msgid "--empty=ask is deprecated; use '--empty=stop' instead."
+msgstr "--empty=ask 已弃用;请使用 '--empty=stop'。"
+
+#: builtin/rebase.c
#, c-format
msgid ""
"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
-"\"ask\"."
-msgstr "无法识别的空类型 '%s';有效值有 \"drop\"ã€\"keep\" å’Œ \"ask\"。"
+"\"stop\"."
+msgstr "无法识别的空类型 '%s';有效值有 \"drop\"ã€\"keep\" å’Œ \"stop\"。"
#: builtin/rebase.c
msgid ""
@@ -12642,7 +12650,7 @@ msgstr "让用户编辑è¦å˜åŸºçš„æ交列表"
msgid "(REMOVED) was: try to recreate merges instead of ignoring them"
msgstr "(已删除)曾是:å°è¯•é‡å»ºåˆå¹¶æ交而éžå¿½ç•¥å®ƒä»¬"
-#: builtin/rebase.c
+#: builtin/rebase.c builtin/revert.c
msgid "how to handle commits that become empty"
msgstr "如何处ç†æˆä¸ºç©ºæ交的æ交"
@@ -12723,8 +12731,8 @@ msgstr ""
"å–而代之请使用 'merges'"
#: builtin/rebase.c
-msgid "No rebase in progress?"
-msgstr "没有正在进行的å˜åŸºï¼Ÿ"
+msgid "no rebase in progress"
+msgstr "没有正在进行的å˜åŸº"
#: builtin/rebase.c
msgid "The --edit-todo action can only be used during interactive rebase."
@@ -12941,6 +12949,10 @@ msgid "git reflog [show] [<log-options>] [<ref>]"
msgstr "git reflog [show] [<log 选项>] [<引用>]"
#: builtin/reflog.c
+msgid "git reflog list"
+msgstr "git reflog list"
+
+#: builtin/reflog.c
msgid ""
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
" [--rewrite] [--updateref] [--stale-fix]\n"
@@ -12969,6 +12981,11 @@ msgstr "git reflog exists <引用>"
msgid "invalid timestamp '%s' given to '--%s'"
msgstr "给 '--%2$s' 的时间戳 '%1$s' 无效"
+#: builtin/reflog.c sequencer.c
+#, c-format
+msgid "%s does not accept arguments: '%s'"
+msgstr "%s ä¸æŽ¥å—å‚数:'%s'"
+
#: builtin/reflog.c
msgid "do not actually prune any entries"
msgstr "ä¸è¦å®žé™…清除任何æ¡ç›®"
@@ -13128,8 +13145,8 @@ msgstr ""
#: builtin/remote.c
#, c-format
-msgid "unknown mirror argument: %s"
-msgstr "未知的镜åƒå‚数:%s"
+msgid "unknown --mirror argument: %s"
+msgstr "未知的 --mirror å‚数:%s"
#: builtin/remote.c
msgid "fetch the remote branches"
@@ -13580,6 +13597,10 @@ msgid "could not start pack-objects to repack promisor objects"
msgstr "无法开始 pack-objects æ¥é‡æ–°æ‰“包 promisor 对象"
#: builtin/repack.c
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "无法将承诺者对象æ供给 pack-objects"
+
+#: builtin/repack.c
msgid "repack: Expecting full hex object ID lines only from pack-objects."
msgstr "repack:期望æ¥è‡ª pack-objects 的完整å六进制对象 ID。"
@@ -14030,7 +14051,9 @@ msgstr "ä¸èƒ½éšå¼åœ°ç¡®å®š --onto 正确的基线"
msgid ""
"(EXPERIMENTAL!) git replay ([--contained] --onto <newbase> | --advance "
"<branch>) <revision-range>..."
-msgstr "(试验中ï¼ï¼‰git replay ([--contained] --onto <新基线> | --advance <分支>) <版本范围>..."
+msgstr ""
+"(试验中ï¼ï¼‰git replay ([--contained] --onto <新基线> | --advance <分支>) <版"
+"本范围>..."
#: builtin/replay.c
msgid "make replay advance given branch"
@@ -14053,7 +14076,8 @@ msgstr "选项 --onto 或 --advance 必须指定其一"
msgid ""
"some rev walking options will be overridden as '%s' bit in 'struct rev_info' "
"will be forced"
-msgstr "一些版本é历选项将被覆盖,如 'struct rev_info' 中的 '%s' ä½å°†è¢«å¼ºåˆ¶è®¾å®š"
+msgstr ""
+"一些版本é历选项将被覆盖,如 'struct rev_info' 中的 '%s' ä½å°†è¢«å¼ºåˆ¶è®¾å®š"
#: builtin/replay.c
msgid "error preparing revisions"
@@ -14322,6 +14346,15 @@ msgid "--prefix requires an argument"
msgstr "--prefix 需è¦ä¸€ä¸ªå‚æ•°"
#: builtin/rev-parse.c
+msgid "no object format specified"
+msgstr "未指定对象格å¼"
+
+#: builtin/rev-parse.c
+#, c-format
+msgid "unsupported object format: %s"
+msgstr "ä¸æ”¯æŒçš„对象格å¼ï¼š'%s'"
+
+#: builtin/rev-parse.c
#, c-format
msgid "unknown mode for --abbrev-ref: %s"
msgstr "未知的 --abbrev-ref 模å¼ï¼š%s"
@@ -14425,8 +14458,8 @@ msgid "allow commits with empty messages"
msgstr "å…许æ交说明为空"
#: builtin/revert.c
-msgid "keep redundant, empty commits"
-msgstr "ä¿æŒå¤šä½™çš„ã€ç©ºçš„æ交"
+msgid "deprecated: use --empty=keep instead"
+msgstr "已弃用:å–而代之使用 --empty=keep"
#: builtin/revert.c
msgid "use the 'reference' format to refer to commits"
@@ -14877,7 +14910,7 @@ msgstr "åˆå§‹åŒ–稀ç–检出为锥形模å¼"
msgid "toggle the use of a sparse index"
msgstr "切æ¢ç¨€ç–索引的使用"
-#: builtin/sparse-checkout.c commit-graph.c midx.c sequencer.c
+#: builtin/sparse-checkout.c commit-graph.c midx-write.c sequencer.c
#, c-format
msgid "unable to create leading directories of %s"
msgstr "ä¸èƒ½ä¸º %s 创建先导目录"
@@ -16041,12 +16074,12 @@ msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be ignored.\n"
+"Lines starting with '%s' will be ignored.\n"
msgstr ""
"\n"
"输入一个标签说明:\n"
" %s\n"
-"以 '%c' 开头的行将被忽略。\n"
+"以 '%s' 开头的行将被忽略。\n"
#: builtin/tag.c
#, c-format
@@ -16054,13 +16087,13 @@ msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be kept; you may remove them yourself if you "
+"Lines starting with '%s' will be kept; you may remove them yourself if you "
"want to.\n"
msgstr ""
"\n"
"输入一个标签说明:\n"
" %s\n"
-"以 '%c' 开头的行将被ä¿ç•™ï¼Œå¦‚果您愿æ„也å¯ä»¥åˆ é™¤å®ƒä»¬ã€‚\n"
+"以 '%s' 开头的行将被ä¿ç•™ï¼Œå¦‚果您愿æ„也å¯ä»¥åˆ é™¤å®ƒä»¬ã€‚\n"
#: builtin/tag.c
msgid "unable to sign the tag"
@@ -16169,6 +16202,10 @@ msgid "print only tags of the object"
msgstr "åªæ‰“å°æŒ‡å‘该对象的标签"
#: builtin/tag.c
+msgid "could not start 'git column'"
+msgstr "无法å¯åŠ¨ 'git column'"
+
+#: builtin/tag.c
#, c-format
msgid "the '%s' option is only allowed in list mode"
msgstr "'%s' 选项åªå…许用在列表显示模å¼"
@@ -16473,12 +16510,12 @@ msgid "fsmonitor disabled"
msgstr "fsmonitor 被ç¦ç”¨"
#: builtin/update-ref.c
-msgid "git update-ref [<options>] -d <refname> [<old-val>]"
-msgstr "git update-ref [<选项>] -d <引用å> [<旧值>]"
+msgid "git update-ref [<options>] -d <refname> [<old-oid>]"
+msgstr "git update-ref [<选项>] -d <引用å> [<旧对象>]"
#: builtin/update-ref.c
-msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]"
-msgstr "git update-ref [<选项>] <引用å> <新值> [<旧值>]"
+msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]"
+msgstr "git update-ref [<选项>] <引用å> <新对象> [<旧对象>]"
#: builtin/update-ref.c
msgid "git update-ref [<options>] --stdin [-z]"
@@ -18101,7 +18138,8 @@ msgstr "无法é‡å‘½å临时æ交图文件"
#: commit-graph.c
#, c-format
msgid "cannot merge graphs with %<PRIuMAX>, %<PRIuMAX> commits"
-msgstr "无法åˆå¹¶æ交图,总共已累加æ交数:%<PRIuMAX>,当å‰å¾…累加æ交数:%<PRIuMAX>"
+msgstr ""
+"无法åˆå¹¶æ交图,总共已累加æ交数:%<PRIuMAX>,当å‰å¾…累加æ交数:%<PRIuMAX>"
#: commit-graph.c
#, c-format
@@ -18189,6 +18227,11 @@ msgstr "æ交图具有零和éžé›¶çš„世代(例如:æ交 '%s' å’Œ '%s')"
msgid "Verifying commits in commit graph"
msgstr "正在校验æ交图中的æ交"
+#: commit-reach.c sequencer.c
+#, c-format
+msgid "could not parse commit %s"
+msgstr "ä¸èƒ½è§£æžæ交 %s"
+
#: commit.c
#, c-format
msgid "%s %s is not a commit!"
@@ -18716,8 +18759,14 @@ msgid "bad zlib compression level %d"
msgstr "错误的 zlib 压缩级别 %d"
#: config.c
-msgid "core.commentChar should only be one ASCII character"
-msgstr "core.commentChar 应该是一个 ASCII ç¼–ç çš„字符"
+#, c-format
+msgid "%s cannot contain newline"
+msgstr "%s ä¸èƒ½åŒ…å«æ¢è¡Œç¬¦"
+
+#: config.c
+#, c-format
+msgid "%s must have at least one character"
+msgstr "%s 必须至少有一个字符"
#: config.c
#, c-format
@@ -18807,6 +18856,11 @@ msgstr "无法写入新的é…置文件 %s"
#: config.c
#, c-format
+msgid "no multi-line comment allowed: '%s'"
+msgstr "ä¸å…许多行注释:'%s'"
+
+#: config.c
+#, c-format
msgid "could not lock config file %s"
msgstr "ä¸èƒ½é”定é…置文件 %s"
@@ -20983,6 +21037,16 @@ msgstr ""
msgid "Unable to create '%s.lock': %s"
msgstr "ä¸èƒ½åˆ›å»º '%s.lock':%s"
+#: loose.c
+#, c-format
+msgid "could not write loose object index %s"
+msgstr "ä¸èƒ½å†™å…¥æ¾æ•£å¯¹è±¡ç´¢å¼• %s"
+
+#: loose.c
+#, c-format
+msgid "failed to write loose object index %s\n"
+msgstr "无法写入æ¾æ•£å¯¹è±¡ç´¢å¼• %s\n"
+
#: ls-refs.c
#, c-format
msgid "unexpected line: '%s'"
@@ -20996,6 +21060,11 @@ msgstr "在 ls-refs å‚æ•°åŽåº”该有一个 flush 包"
msgid "quoted CRLF detected"
msgstr "检测到被引用的 CRLF"
+#: mem-pool.c strbuf.c wrapper.c
+#, c-format
+msgid "unable to format message: %s"
+msgstr "无法格å¼åŒ–消æ¯ï¼š%s"
+
#: merge-ort.c merge-recursive.c
#, c-format
msgid "Failed to merge submodule %s (not checked out)"
@@ -21013,6 +21082,11 @@ msgstr "无法åˆå¹¶å­æ¨¡ç»„ %s(æ交ä¸å­˜åœ¨ï¼‰"
#: merge-ort.c merge-recursive.c
#, c-format
+msgid "Failed to merge submodule %s (repository corrupt)"
+msgstr "无法åˆå¹¶å­æ¨¡ç»„ %s(仓库æŸå)"
+
+#: merge-ort.c merge-recursive.c
+#, c-format
msgid "Failed to merge submodule %s (commits don't follow merge-base)"
msgstr "无法åˆå¹¶å­æ¨¡ç»„ %s (æ交未跟éšåˆå¹¶åŸºçº¿ï¼‰"
@@ -21541,6 +21615,104 @@ msgstr "ä¸èƒ½è§£æžå¯¹è±¡ '%s'"
msgid "failed to read the cache"
msgstr "无法读å–缓存"
+#: midx-write.c
+#, c-format
+msgid "failed to add packfile '%s'"
+msgstr "无法添加包文件 '%s'"
+
+#: midx-write.c
+#, c-format
+msgid "failed to open pack-index '%s'"
+msgstr "无法打开包索引 '%s'"
+
+#: midx-write.c
+#, c-format
+msgid "failed to locate object %d in packfile"
+msgstr "无法在包文件中定ä½å¯¹è±¡ %d"
+
+#: midx-write.c
+msgid "cannot store reverse index file"
+msgstr "无法存储åå‘索引文件"
+
+#: midx-write.c
+#, c-format
+msgid "could not parse line: %s"
+msgstr "ä¸èƒ½è§£æžè¡Œï¼š%s"
+
+#: midx-write.c
+#, c-format
+msgid "malformed line: %s"
+msgstr "æ ¼å¼é”™è¯¯çš„行:%s"
+
+#: midx-write.c
+msgid "ignoring existing multi-pack-index; checksum mismatch"
+msgstr "忽略已存在的多包索引,校验ç ä¸åŒ¹é…"
+
+#: midx-write.c
+msgid "could not load pack"
+msgstr "ä¸èƒ½è½½å…¥åŒ…"
+
+#: midx-write.c
+#, c-format
+msgid "could not open index for %s"
+msgstr "ä¸èƒ½æ‰“å¼€ %s 的索引"
+
+#: midx-write.c
+msgid "Adding packfiles to multi-pack-index"
+msgstr "添加包文件到多包索引"
+
+#: midx-write.c
+#, c-format
+msgid "unknown preferred pack: '%s'"
+msgstr "未知的首选包:'%s'"
+
+#: midx-write.c
+#, c-format
+msgid "cannot select preferred pack %s with no objects"
+msgstr "ä¸èƒ½é€‰æ‹©æ²¡æœ‰å¯¹è±¡çš„首选包 %s"
+
+#: midx-write.c
+#, c-format
+msgid "did not see pack-file %s to drop"
+msgstr "没有看到è¦ä¸¢å¼ƒçš„包文件 %s"
+
+#: midx-write.c
+#, c-format
+msgid "preferred pack '%s' is expired"
+msgstr "首选包 '%s' 已过期"
+
+#: midx-write.c
+msgid "no pack files to index."
+msgstr "没有è¦ç´¢å¼•çš„包文件。"
+
+#: midx-write.c
+msgid "refusing to write multi-pack .bitmap without any objects"
+msgstr "æ‹’ç»å†™å…¥æ²¡æœ‰ä»»ä½•å¯¹è±¡çš„多包ä½å›¾"
+
+#: midx-write.c
+msgid "could not write multi-pack bitmap"
+msgstr "无法写入多包ä½å›¾"
+
+#: midx-write.c
+msgid "could not write multi-pack-index"
+msgstr "无法写入多包索引"
+
+#: midx-write.c
+msgid "Counting referenced objects"
+msgstr "正在对引用对象计数"
+
+#: midx-write.c
+msgid "Finding and deleting unreferenced packfiles"
+msgstr "正在查找和删除未引用的包文件"
+
+#: midx-write.c
+msgid "could not start pack-objects"
+msgstr "ä¸èƒ½å¼€å§‹ pack-objects"
+
+#: midx-write.c
+msgid "could not finish pack-objects"
+msgstr "ä¸èƒ½ç»“æŸ pack-objects"
+
#: midx.c
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "多包索引的对象 ID 扇出表大å°é”™è¯¯"
@@ -21628,88 +21800,6 @@ msgstr "多包索引大å移区越界"
#: midx.c
#, c-format
-msgid "failed to add packfile '%s'"
-msgstr "无法添加包文件 '%s'"
-
-#: midx.c
-#, c-format
-msgid "failed to open pack-index '%s'"
-msgstr "无法打开包索引 '%s'"
-
-#: midx.c
-#, c-format
-msgid "failed to locate object %d in packfile"
-msgstr "无法在包文件中定ä½å¯¹è±¡ %d"
-
-#: midx.c
-msgid "cannot store reverse index file"
-msgstr "无法存储åå‘索引文件"
-
-#: midx.c
-#, c-format
-msgid "could not parse line: %s"
-msgstr "ä¸èƒ½è§£æžè¡Œï¼š%s"
-
-#: midx.c
-#, c-format
-msgid "malformed line: %s"
-msgstr "æ ¼å¼é”™è¯¯çš„行:%s"
-
-#: midx.c
-msgid "ignoring existing multi-pack-index; checksum mismatch"
-msgstr "忽略已存在的多包索引,校验ç ä¸åŒ¹é…"
-
-#: midx.c
-msgid "could not load pack"
-msgstr "ä¸èƒ½è½½å…¥åŒ…"
-
-#: midx.c
-#, c-format
-msgid "could not open index for %s"
-msgstr "ä¸èƒ½æ‰“å¼€ %s 的索引"
-
-#: midx.c
-msgid "Adding packfiles to multi-pack-index"
-msgstr "添加包文件到多包索引"
-
-#: midx.c
-#, c-format
-msgid "unknown preferred pack: '%s'"
-msgstr "未知的首选包:'%s'"
-
-#: midx.c
-#, c-format
-msgid "cannot select preferred pack %s with no objects"
-msgstr "ä¸èƒ½é€‰æ‹©æ²¡æœ‰å¯¹è±¡çš„首选包 %s"
-
-#: midx.c
-#, c-format
-msgid "did not see pack-file %s to drop"
-msgstr "没有看到è¦ä¸¢å¼ƒçš„包文件 %s"
-
-#: midx.c
-#, c-format
-msgid "preferred pack '%s' is expired"
-msgstr "首选包 '%s' 已过期"
-
-#: midx.c
-msgid "no pack files to index."
-msgstr "没有è¦ç´¢å¼•çš„包文件。"
-
-#: midx.c
-msgid "refusing to write multi-pack .bitmap without any objects"
-msgstr "æ‹’ç»å†™å…¥æ²¡æœ‰ä»»ä½•å¯¹è±¡çš„多包ä½å›¾ .bitmap"
-
-#: midx.c
-msgid "could not write multi-pack bitmap"
-msgstr "无法写入多包ä½å›¾"
-
-#: midx.c
-msgid "could not write multi-pack-index"
-msgstr "无法写入多包索引"
-
-#: midx.c
-#, c-format
msgid "failed to clear multi-pack-index at %s"
msgstr "无法清ç†ä½äºŽ %s 的多包索引"
@@ -21761,22 +21851,6 @@ msgstr "无法为包文件 %s 加载包索引"
msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>"
msgstr "oid[%d] = %s 错误的对象å移:%<PRIx64> != %<PRIx64>"
-#: midx.c
-msgid "Counting referenced objects"
-msgstr "正在对引用对象计数"
-
-#: midx.c
-msgid "Finding and deleting unreferenced packfiles"
-msgstr "正在查找和删除未引用的包文件"
-
-#: midx.c
-msgid "could not start pack-objects"
-msgstr "ä¸èƒ½å¼€å§‹ pack-objects"
-
-#: midx.c
-msgid "could not finish pack-objects"
-msgstr "ä¸èƒ½ç»“æŸ pack-objects"
-
#: name-hash.c
#, c-format
msgid "unable to create lazy_dir thread: %s"
@@ -21831,6 +21905,30 @@ msgstr "æ‹’ç»å‘ %s(在 refs/notes/ 之外)写入注解"
msgid "Bad %s value: '%s'"
msgstr "åçš„ %s 值:'%s'"
+#: object-file-convert.c
+msgid "failed to decode tree entry"
+msgstr "无法解ç æ ‘对象"
+
+#: object-file-convert.c
+#, c-format
+msgid "failed to map tree entry for %s"
+msgstr "无法为 %s 映射树对象"
+
+#: object-file-convert.c
+#, c-format
+msgid "bad %s in commit"
+msgstr "æ交中有错误的 %s"
+
+#: object-file-convert.c
+#, c-format
+msgid "unable to map %s %s in commit object"
+msgstr "无法将 %s %s 映射到æ交对象中"
+
+#: object-file-convert.c
+#, c-format
+msgid "Failed to convert object from %s to %s"
+msgstr "无法将对象从 %s 转æ¢ä¸º %s"
+
#: object-file.c
#, c-format
msgid "object directory %s does not exist; check .git/objects/info/alternates"
@@ -21959,6 +22057,11 @@ msgstr "打包对象 %s(ä¿å­˜åœ¨ %s)已æŸå"
#: object-file.c
#, c-format
+msgid "missing mapping of %s to %s"
+msgstr "缺少 %s 到 %s 的映射"
+
+#: object-file.c
+#, c-format
msgid "unable to write file %s"
msgstr "无法写文件 %s"
@@ -22026,6 +22129,11 @@ msgstr "ä¸èƒ½è¯»å–对象 %s"
#: object-file.c
#, c-format
+msgid "cannot map object %s to %s"
+msgstr "无法将对象 %s 映射到 %s"
+
+#: object-file.c
+#, c-format
msgid "object fails fsck: %s"
msgstr "对象 fsck 失败:%s"
@@ -22387,6 +22495,10 @@ msgid "unable to load pack: '%s', disabling pack-reuse"
msgstr "无法打开包:'%s',ç¦ç”¨åŒ…é‡ç”¨"
#: pack-bitmap.c
+msgid "unable to compute preferred pack, disabling pack-reuse"
+msgstr "无法计算首选包,ç¦ç”¨åŒ…é‡ç”¨"
+
+#: pack-bitmap.c
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "对象 %s 为在类型ä½å›¾ä¸­æ‰¾åˆ°"
@@ -23656,6 +23768,84 @@ msgstr "无法删除引用 %s:%s"
msgid "could not delete references: %s"
msgstr "无法删除引用:%s"
+#: refs/reftable-backend.c
+#, c-format
+msgid "refname is dangerous: %s"
+msgstr "å±é™©çš„引用å称:%s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "trying to write ref '%s' with nonexistent object %s"
+msgstr "试图用ä¸å­˜åœ¨çš„对象 %2$s 写入引用 '%1$s'"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "trying to write non-commit object %s to branch '%s'"
+msgstr "å°è¯•å°†éžæ交对象 %s 写入分支 '%s'"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid ""
+"multiple updates for 'HEAD' (including one via its referent '%s') are not "
+"allowed"
+msgstr "ä¸å…许对 'HEAD' 进行多次更新(包括通过其引用 '%s' 进行的更新)"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': unable to resolve reference '%s'"
+msgstr "无法é”定引用 '%s':无法解æžå¼•ç”¨ '%s'"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': error reading reference"
+msgstr "无法é”定引用 '%s':读å–引用时出错"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid ""
+"multiple updates for '%s' (including one via symref '%s') are not allowed"
+msgstr "ä¸å…许对 '%s' 进行多次更新(包括通过符å·å¼•ç”¨ '%s' 更新)"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': reference already exists"
+msgstr "无法é”定引用 '%s':引用已存在"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': reference is missing but expected %s"
+msgstr "无法é”定 '%s' 引用:引用丢失,但预期为 %s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': is at %s but expected %s"
+msgstr "无法é”定 '%s' 引用:ä½äºŽ %s,但预期为 %s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "reftable: transaction prepare: %s"
+msgstr "reftable: 事务准备:%s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "reftable: transaction failure: %s"
+msgstr "reftable: 事务失败:%s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "unable to compact stack: %s"
+msgstr "无法压缩栈:%s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "refname %s not found"
+msgstr "引用å称 %s 未找到"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "refname %s is a symbolic ref, copying it is not supported"
+msgstr "引用å %s 是一个符å·å¼•ç”¨ï¼Œä¸æ”¯æŒå¤åˆ¶"
+
#: refspec.c
#, c-format
msgid "invalid refspec '%s'"
@@ -23668,6 +23858,11 @@ msgstr "在 push-option å–值中无效的引å·ï¼š'%s'"
#: remote-curl.c
#, c-format
+msgid "unknown value for object-format: %s"
+msgstr "对象格å¼çš„未知å–值:%s"
+
+#: remote-curl.c
+#, c-format
msgid "%sinfo/refs not valid: is this a git repository?"
msgstr "%sinfo/refs 无效:这是 git 仓库么?"
@@ -24203,8 +24398,21 @@ msgstr "resolve-undo 记录 `%s`,现缺失"
#: revision.c
#, c-format
-msgid "could not get commit for ancestry-path argument %s"
-msgstr "无法获得 ancestry-path å‚æ•° %s çš„æ交"
+msgid "%s exists but is a symbolic ref"
+msgstr "%s 存在但是一个符å·å¼•ç”¨"
+
+#: revision.c
+msgid ""
+"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD or REBASE_HEAD"
+msgstr ""
+"--merge 选项需è¦æŒ‡å®š MERGE_HEADã€CHERRY_PICK_HEADã€REVERT_HEAD 或 "
+"REBASE_HEAD 中的一个伪引用"
+
+#: revision.c
+#, c-format
+msgid "could not get commit for --ancestry-path argument %s"
+msgstr "无法获得 --ancestry-path å‚æ•° %s çš„æ交"
#: revision.c
msgid "--unpacked=<packfile> no longer supported"
@@ -24565,6 +24773,19 @@ msgstr "未知动作:%d"
#: sequencer.c
msgid ""
+"Resolve all conflicts manually, mark them as resolved with\n"
+"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
+"You can instead skip this commit: run \"git rebase --skip\".\n"
+"To abort and get back to the state before \"git rebase\", run \"git rebase --"
+"abort\"."
+msgstr ""
+"手工解决所有冲çªï¼Œæ‰§è¡Œ \"git add/rm <冲çªçš„文件>\" 标记\n"
+"冲çªå·²è§£å†³ï¼Œç„¶åŽæ‰§è¡Œ \"git rebase --continue\"。您也å¯ä»¥æ‰§è¡Œ\n"
+"\"git rebase --skip\" 命令跳过这个æ交。如果想è¦ç»ˆæ­¢æ‰§è¡Œå¹¶å›žåˆ°\n"
+"\"git rebase\" 执行之å‰çš„状æ€ï¼Œæ‰§è¡Œ \"git rebase --abort\"。"
+
+#: sequencer.c
+msgid ""
"after resolving the conflicts, mark the corrected paths\n"
"with 'git add <paths>' or 'git rm <paths>'"
msgstr ""
@@ -24813,11 +25034,6 @@ msgstr "ä¸èƒ½æ›´æ–° %s"
#: sequencer.c
#, c-format
-msgid "could not parse commit %s"
-msgstr "ä¸èƒ½è§£æžæ交 %s"
-
-#: sequencer.c
-#, c-format
msgid "could not parse parent commit %s"
msgstr "ä¸èƒ½è§£æžçˆ¶æ交 %s"
@@ -24948,11 +25164,6 @@ msgstr "无效命令 '%.*s'"
#: sequencer.c
#, c-format
-msgid "%s does not accept arguments: '%s'"
-msgstr "%s ä¸æŽ¥å—å‚数:'%s'"
-
-#: sequencer.c
-#, c-format
msgid "missing arguments for %s"
msgstr "缺少 %s çš„å‚æ•°"
@@ -25502,6 +25713,11 @@ msgstr "无法使用无效é…ç½®æ¥åˆ›å»ºå·¥ä½œåŒº"
#: setup.c
#, c-format
+msgid "'%s' already specified as '%s'"
+msgstr "'%s' 已指定为 '%s'"
+
+#: setup.c
+#, c-format
msgid "Expected git repo version <= %d, found %d"
msgstr "期望 git 仓库版本 <= %d,å´å¾—到 %d"
@@ -25732,6 +25948,24 @@ msgstr "索引æ¡ç›®æ˜¯ä¸€ä¸ªç›®å½•ï¼Œä½†ä¸æ˜¯ç¨€ç–çš„ (%08x)"
msgid "cannot use split index with a sparse index"
msgstr "拆分索引无法与稀ç–索引一起使用"
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#: strbuf.c
+#, c-format
+msgid "bad %s format: element '%s' does not start with '('"
+msgstr "åçš„ %s æ ¼å¼ï¼šå…ƒç´  '%s' 没有以 '(' 开头"
+
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#: strbuf.c
+#, c-format
+msgid "bad %s format: element '%s' does not end in ')'"
+msgstr "åçš„ %s æ ¼å¼ï¼šå…ƒç´  '%s' 没有以 ')' 结尾"
+
+#. TRANSLATORS: %s is a command like "ls-tree".
+#: strbuf.c
+#, c-format
+msgid "bad %s format: %%%.*s"
+msgstr "åçš„ %s æ ¼å¼: %%%.*s"
+
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#: strbuf.c
#, c-format
@@ -26123,35 +26357,6 @@ msgstr "é”® '%2$s' 的未知å–值 '%1$s'"
msgid "empty trailer token in trailer '%.*s'"
msgstr "尾注 '%.*s' 的键为空"
-#: trailer.c
-#, c-format
-msgid "could not read input file '%s'"
-msgstr "ä¸èƒ½è¯»å–输入文件 '%s'"
-
-#: trailer.c wrapper.c
-#, c-format
-msgid "could not stat %s"
-msgstr "ä¸èƒ½å¯¹ %s 调用 stat"
-
-#: trailer.c
-#, c-format
-msgid "file %s is not a regular file"
-msgstr "文件 %s ä¸æ˜¯ä¸€ä¸ªæ­£è§„文件"
-
-#: trailer.c
-#, c-format
-msgid "file %s is not writable by user"
-msgstr "文件 %s 用户ä¸å¯å†™"
-
-#: trailer.c
-msgid "could not open temporary file"
-msgstr "ä¸èƒ½æ‰“开临时文件"
-
-#: trailer.c
-#, c-format
-msgid "could not rename temporary file to %s"
-msgstr "ä¸èƒ½é‡å‘½å临时文件为 %s"
-
#: transport-helper.c
msgid "full write to remote helper failed"
msgstr "完整写入远程助手失败"
@@ -26271,8 +26476,8 @@ msgstr "remote-heper ä¸æ”¯æŒæŽ¨é€ï¼Œéœ€è¦å¼•ç”¨è§„æ ¼"
#: transport-helper.c
#, c-format
-msgid "helper %s does not support 'force'"
-msgstr "助手 %s ä¸æ”¯æŒ 'force'"
+msgid "helper %s does not support '--force'"
+msgstr "助手 %s ä¸æ”¯æŒ '--force'"
#: transport-helper.c
msgid "couldn't run fast-export"
@@ -26747,6 +26952,11 @@ msgid "invalid '..' path segment"
msgstr "无效的 '..' 路径片段"
#: usage.c
+#, c-format
+msgid "error: unable to format message: %s\n"
+msgstr "错误:无法格å¼åŒ–消æ¯ï¼š%s\n"
+
+#: usage.c
msgid "usage: "
msgstr "用法:"
diff --git a/po/zh_TW.po b/po/zh_TW.po
index 312dd128a4..f554381a7a 100644
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
@@ -22,12 +22,13 @@
# Yi-Jyun Pan <pan93412@gmail.com>, 2021, 2022, 2023, 2024.
# Kaiyang Wu <self@origincode.me>, 2022.
# lumynou5 <lumynou5.tw@gmail.com>, 2023, 2024.
+# Kisaragi Hiu <mail@kisaragi-hiu.com>, 2024.
msgid ""
msgstr ""
"Project-Id-Version: Git\n"
"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2024-02-18 20:48+0800\n"
-"PO-Revision-Date: 2024-02-18 20:50+0800\n"
+"POT-Creation-Date: 2024-04-28 18:52+0800\n"
+"PO-Revision-Date: 2024-04-28 18:44+0800\n"
"Last-Translator: Yi-Jyun Pan <pan93412@gmail.com>\n"
"Language-Team: Chinese (Traditional) <http://weblate.slat.org/projects/git-"
"po/git-cli/zh_Hant/>\n"
@@ -601,12 +602,12 @@ msgid ""
"---\n"
"To remove '%c' lines, make them ' ' lines (context).\n"
"To remove '%c' lines, delete them.\n"
-"Lines starting with %c will be removed.\n"
+"Lines starting with %s will be removed.\n"
msgstr ""
"---\n"
-"è¦åˆªé™¤ “%c†開頭的列,請將列首(上下文)改æˆç©ºç™½ã€‚\n"
-"è¦åˆªé™¤ “%c†開頭的列,請直接刪除。\n"
-"開頭是 %c 的列將會被移除。\n"
+"è¦åˆªé™¤ã€Œ%cã€é–‹é ­çš„列,請將列首(上下文)改æˆç©ºç™½ã€‚\n"
+"è¦åˆªé™¤ã€Œ%cã€é–‹é ­çš„列,請直接刪除。\n"
+"開頭是 %s 的列將會被移除。\n"
#: add-patch.c
msgid ""
@@ -659,16 +660,18 @@ msgid ""
"/ - search for a hunk matching the given regex\n"
"s - split the current hunk into smaller hunks\n"
"e - manually edit the current hunk\n"
+"p - print the current hunk\n"
"? - print help\n"
msgstr ""
-"j - 維æŒæ­¤å€å¡Šæœªæ±ºç‹€æ…‹ï¼Œæª¢è¦–下一個未決定å€å¡Š\n"
-"J - 維æŒæ­¤å€å¡Šæœªæ±ºç‹€æ…‹ï¼Œæª¢è¦–下一個å€å¡Š\n"
-"k - 維æŒæ­¤å€å¡Šæœªæ±ºç‹€æ…‹ï¼Œæª¢è¦–上一個未決定å€å¡Š\n"
-"K - 維æŒæ­¤å€å¡Šæœªæ±ºç‹€æ…‹ï¼Œæª¢è¦–上一個å€å¡Š\n"
+"j - 維æŒæ­¤å€å¡Šæœªæ±ºå®šç‹€æ…‹ï¼Œæª¢è¦–下一個未決定å€å¡Š\n"
+"J - 維æŒæ­¤å€å¡Šæœªæ±ºå®šç‹€æ…‹ï¼Œæª¢è¦–下一個å€å¡Š\n"
+"k - 維æŒæ­¤å€å¡Šæœªæ±ºå®šç‹€æ…‹ï¼Œæª¢è¦–上一個未決定å€å¡Š\n"
+"K - 維æŒæ­¤å€å¡Šæœªæ±ºå®šç‹€æ…‹ï¼Œæª¢è¦–上一個å€å¡Š\n"
"g - é¸æ“‡è¦è·³è½‰è‡³çš„å€å¡Š\n"
"/ - 尋找符åˆæ供之常è¦è¡¨ç¤ºå¼çš„å€å¡Š\n"
"s - 分割目å‰å€å¡Šç‚ºæ›´å°çš„å€å¡Š\n"
"e - 手動編輯目å‰å€å¡Š\n"
+"p - 輸出目å‰å€å¡Š\n"
"? - 顯示說明\n"
#: add-patch.c
@@ -747,8 +750,8 @@ msgstr ""
#: advice.c
#, c-format
-msgid "%shint: %.*s%s\n"
-msgstr "%sæ示:%.*s%s\n"
+msgid "%shint:%s%.*s%s\n"
+msgstr "%sæ示:%s%.*s%s\n"
#: advice.c
msgid "Cherry-picking is not possible because you have unmerged files."
@@ -1345,11 +1348,6 @@ msgstr[0] "套用 %%s 個修補檔,其中 %d 個被拒絕……"
#: apply.c
#, c-format
-msgid "truncating .rej filename to %.*s.rej"
-msgstr "正在將 .rej 檔案å稱截短為 %.*s.rej"
-
-#: apply.c
-#, c-format
msgid "cannot open %s"
msgstr "無法開啟 %s"
@@ -1884,6 +1882,11 @@ msgstr "需è¦ä¸€å€‹ %s 修訂版"
msgid "could not create file '%s'"
msgstr "無法建立 “%s†檔案"
+#: bisect.c builtin/notes.c
+#, c-format
+msgid "unable to start 'show' for object '%s'"
+msgstr "ä¸èƒ½ç‚ºç‰©ä»¶ '%s' 開始 'show'"
+
#: bisect.c builtin/merge.c
#, c-format
msgid "could not read file '%s'"
@@ -1931,8 +1934,8 @@ msgid "--reverse and --first-parent together require specified latest commit"
msgstr "--reverse å’Œ --first-parent 共用,需è¦æŒ‡å®šæœ€æ–°çš„æ交"
#: blame.c builtin/commit.c builtin/log.c builtin/merge.c
-#: builtin/pack-objects.c builtin/shortlog.c midx.c pack-bitmap.c remote.c
-#: sequencer.c submodule.c
+#: builtin/pack-objects.c builtin/shortlog.c midx-write.c pack-bitmap.c
+#: remote.c sequencer.c submodule.c
msgid "revision walk setup failed"
msgstr "修訂版é歷設定失敗"
@@ -2007,10 +2010,12 @@ 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
@@ -2049,6 +2054,10 @@ msgstr ""
msgid "'%s' is not a valid branch name"
msgstr "“%s†ä¸æ˜¯æœ‰æ•ˆçš„分支å稱"
+#: branch.c builtin/branch.c
+msgid "See `man git check-ref-format`"
+msgstr "è«‹åƒé–±ã€Œman git check-ref-formatã€"
+
#: branch.c
#, c-format
msgid "a branch named '%s' already exists"
@@ -2283,14 +2292,8 @@ msgid "adding embedded git repository: %s"
msgstr "æ­£åœ¨åŠ å…¥åµŒå…¥å¼ git 版本庫:%s"
#: builtin/add.c
-msgid ""
-"Use -f if you really want to add them.\n"
-"Turn this message off by running\n"
-"\"git config advice.addIgnoredFile false\""
-msgstr ""
-"若您真的想加入,請傳入 -f。\n"
-"如è¦é—œé–‰æ­¤è¨Šæ¯ï¼Œè«‹åŸ·è¡Œ\n"
-"“git config advice.addIgnoredFile falseâ€"
+msgid "Use -f if you really want to add them."
+msgstr "如果您確定想è¦åŠ å…¥ä»–們,請使用「-fã€ã€‚"
#: builtin/add.c
msgid "adding files failed"
@@ -2313,14 +2316,8 @@ msgid "Nothing specified, nothing added.\n"
msgstr "沒有指定,亦未加入檔案。\n"
#: builtin/add.c
-msgid ""
-"Maybe you wanted to say 'git add .'?\n"
-"Turn this message off by running\n"
-"\"git config advice.addEmptyPathspec false\""
-msgstr ""
-"å¯èƒ½æ‚¨æƒ³åš “git add .â€ï¼Ÿ\n"
-"如è¦é—œé–‰æ­¤è¨Šæ¯ï¼Œè«‹åŸ·è¡Œ\n"
-"“git config advice.addEmptyPathspec falseâ€"
+msgid "Maybe you wanted to say 'git add .'?"
+msgstr "也許您想è¦åŸ·è¡Œçš„是「git add .ã€ï¼Ÿ"
#: builtin/add.c builtin/check-ignore.c builtin/checkout.c builtin/clean.c
#: builtin/commit.c builtin/diff-tree.c builtin/grep.c builtin/mv.c
@@ -2340,8 +2337,8 @@ msgid "bad action '%s' for '%s'"
msgstr "“%sâ€ å‹•ä½œå° â€œ%s†無效"
#: builtin/am.c builtin/blame.c builtin/fetch.c builtin/pack-objects.c
-#: builtin/pull.c config.c diff-merges.c gpg-interface.c ls-refs.c
-#: parallel-checkout.c sequencer.c setup.c
+#: builtin/pull.c builtin/revert.c config.c diff-merges.c gpg-interface.c
+#: ls-refs.c parallel-checkout.c sequencer.c setup.c
#, c-format
msgid "invalid value for '%s': '%s'"
msgstr "“%s†的值無效:“%sâ€"
@@ -2425,18 +2422,19 @@ msgstr "無法切割修補檔。"
#: builtin/am.c
#, c-format
-msgid "When you have resolved this problem, run \"%s --continue\"."
-msgstr "解決此å•é¡Œå¾Œï¼Œè«‹åŸ·è¡Œ “%s --continueâ€ã€‚"
+msgid "When you have resolved this problem, run \"%s --continue\".\n"
+msgstr "解決此å•é¡Œå¾Œï¼Œè«‹åŸ·è¡Œã€Œ%s --continueã€ã€‚\n"
#: builtin/am.c
#, c-format
-msgid "If you prefer to skip this patch, run \"%s --skip\" instead."
-msgstr "è‹¥è¦ç•¥éŽæ­¤ä¿®è£œï¼Œè«‹æ”¹åŸ·è¡Œ “%s --skipâ€ã€‚"
+msgid "If you prefer to skip this patch, run \"%s --skip\" instead.\n"
+msgstr "è‹¥è¦ç•¥éŽæ­¤ä¿®è£œï¼Œè«‹æ”¹åŸ·è¡Œã€Œ%s --skipã€ã€‚\n"
#: builtin/am.c
#, c-format
-msgid "To record the empty patch as an empty commit, run \"%s --allow-empty\"."
-msgstr "è‹¥è¦å°‡ç©ºç™½ä¿®è£œæª”錄入為空白æ交,請執行 “%s --allow-emptyâ€ã€‚"
+msgid ""
+"To record the empty patch as an empty commit, run \"%s --allow-empty\".\n"
+msgstr "è‹¥è¦å°‡ç©ºç™½ä¿®è£œæª”錄入為空白æ交,請執行「%s --allow-emptyã€ã€‚\n"
#: builtin/am.c
#, c-format
@@ -3503,11 +3501,11 @@ msgstr "分支已拷è²ï¼Œä½†ç„¡æ³•æ›´æ–°çµ„態檔案"
msgid ""
"Please edit the description for the branch\n"
" %s\n"
-"Lines starting with '%c' will be stripped.\n"
+"Lines starting with '%s' will be stripped.\n"
msgstr ""
"請編輯下述分支的æè¿°\n"
" %s\n"
-"開頭是 “%c†的列將被刪除。\n"
+"開頭是「%sã€çš„列將被刪除。\n"
#: builtin/branch.c
msgid "Generic options"
@@ -3763,10 +3761,12 @@ msgstr "ä¸æ˜¯åœ¨ git 版本庫執行 — 沒有å¯é¡¯ç¤ºçš„掛鉤\n"
#: builtin/bugreport.c
msgid ""
-"git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"git bugreport [(-o | --output-directory) <path>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
" [--diagnose[=<mode>]]"
msgstr ""
-"git bugreport [(-o | --output-directory) <path>] [(-s | --suffix) <format>]\n"
+"git bugreport [(-o | --output-directory) <path>]\n"
+" [(-s | --suffix) <format> | --no-suffix]\n"
" [--diagnose[=<mode>]]"
#: builtin/bugreport.c
@@ -4366,6 +4366,12 @@ msgstr "“%sâ€ã€â€œ%s†或 “%s†無法在簽出樹狀物件時使用"
msgid "path '%s' is unmerged"
msgstr "路徑 “%s†未åˆä½µ"
+#: builtin/checkout.c builtin/grep.c builtin/merge-tree.c builtin/reset.c
+#: merge-ort.c reset.c sequencer.c tree-walk.c
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr "無法讀å–樹(%s)"
+
#: builtin/checkout.c
msgid "you need to resolve your current index first"
msgstr "您需è¦å…ˆè§£æ±ºç›®å‰ç´¢å¼•å€çš„è¡çª"
@@ -4625,6 +4631,11 @@ msgid "missing branch or commit argument"
msgstr "缺少分支或æ交引數"
#: builtin/checkout.c
+#, c-format
+msgid "unknown conflict style '%s'"
+msgstr "未知的è¡çªè¼¸å‡ºé¢¨æ ¼ã€Œ%sã€"
+
+#: builtin/checkout.c
msgid "perform a 3-way merge with the new branch"
msgstr "和新分支進行三方åˆä½µ"
@@ -4945,18 +4956,8 @@ msgid "remove only ignored files"
msgstr "åªç§»é™¤å¿½ç•¥çš„檔案"
#: builtin/clean.c
-msgid ""
-"clean.requireForce set to true and neither -i, -n, nor -f given; refusing to "
-"clean"
-msgstr ""
-"clean.requireForce 設定為 true 且未æä¾› -iã€-n 或 -f é¸é …,拒絕執行清ç†å‹•ä½œ"
-
-#: builtin/clean.c
-msgid ""
-"clean.requireForce defaults to true and neither -i, -n, nor -f given; "
-"refusing to clean"
-msgstr ""
-"clean.requireForce é è¨­ç‚º true 且未æä¾› -iã€-n 或 -f é¸é …,拒絕執行清ç†å‹•ä½œ"
+msgid "clean.requireForce is true and -f not given: refusing to clean"
+msgstr "clean.requireForce 是 true 且未給定 -f é¸é …:拒絕清ç†"
#: builtin/clone.c
msgid "git clone [<options>] [--] <repo> [<dir>]"
@@ -4975,8 +4976,8 @@ msgid "create a bare repository"
msgstr "建立裸版本庫"
#: builtin/clone.c
-msgid "create a mirror repository (implies bare)"
-msgstr "建立é¡åƒç‰ˆæœ¬åº«ï¼ˆäº¦å³è£¸ç‰ˆæœ¬åº«ï¼‰"
+msgid "create a mirror repository (implies --bare)"
+msgstr "建立é¡åƒç‰ˆæœ¬åº«ï¼ˆéš±å« --bare)"
#: builtin/clone.c
msgid "to clone from a local repository"
@@ -5378,6 +5379,11 @@ msgid "padding space between columns"
msgstr "兩直行之間的填充空間"
#: builtin/column.c
+#, c-format
+msgid "%s must be non-negative"
+msgstr "%s ä¸å¾—為負數"
+
+#: builtin/column.c
msgid "--command must be the first argument"
msgstr "--command 必須是第一個åƒæ•¸"
@@ -5710,7 +5716,7 @@ msgid ""
"in the current commit message"
msgstr "無法é¸æ“‡ä¸€å€‹æœªè¢«ç›®å‰æ交說明使用的備註字元"
-#: builtin/commit.c builtin/merge-tree.c
+#: builtin/commit.c
#, c-format
msgid "could not lookup commit '%s'"
msgstr "無法查詢æ交 “%sâ€"
@@ -5745,7 +5751,7 @@ msgstr "ä¸èƒ½è®€å– MERGE_MSG"
#: builtin/commit.c bundle.c rerere.c sequencer.c
#, c-format
msgid "could not open '%s'"
-msgstr "ä¸èƒ½é–‹å•Ÿ '%s'"
+msgstr "無法開啟「%sã€"
#: builtin/commit.c
msgid "could not write commit template"
@@ -5755,38 +5761,38 @@ msgstr "ä¸èƒ½å¯«æ交範本"
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored.\n"
+"with '%s' will be ignored.\n"
msgstr ""
"請輸入æ述您變更的æ交訊æ¯ã€‚\n"
-"開頭是「%cã€çš„行皆會忽略。\n"
+"開頭是「%sã€çš„列皆會忽略。\n"
#: builtin/commit.c
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be ignored, and an empty message aborts the commit.\n"
+"with '%s' will be ignored, and an empty message aborts the commit.\n"
msgstr ""
-"請輸入æ述您變更的æ交訊æ¯ã€‚開頭是「%cã€\n"
-"的行皆會忽略。æ交訊æ¯ç©ºç™½å‰‡å–消本次æ交作業。\n"
+"請輸入æ述您變更的æ交訊æ¯ã€‚開頭是「%sã€çš„列\n"
+"皆會忽略。æ交訊æ¯ç©ºç™½å‰‡å–消本次æ交作業。\n"
#: builtin/commit.c
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
msgstr ""
-"請輸入æ述您變更的æ交訊æ¯ã€‚會ä¿ç•™é–‹é ­æ˜¯ã€Œ%cã€\n"
-"的行,但也å¯ä»¥è‡ªå·±ç§»é™¤æŽ‰é€™äº›è¡Œã€‚\n"
+"請輸入æ述您變更的æ交訊æ¯ã€‚會ä¿ç•™é–‹é ­æ˜¯ã€Œ%sã€\n"
+"的列,但也å¯ä»¥è‡ªå·±ç§»é™¤æŽ‰é€™äº›åˆ—。\n"
#: builtin/commit.c
#, c-format
msgid ""
"Please enter the commit message for your changes. Lines starting\n"
-"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"with '%s' will be kept; you may remove them yourself if you want to.\n"
"An empty message aborts the commit.\n"
msgstr ""
"請輸入æ述您變更的æ交訊æ¯ã€‚會ä¿ç•™é–‹é ­æ˜¯\n"
-"「%cã€çš„行,但也å¯ä»¥è‡ªå·±ç§»é™¤æŽ‰é€™äº›è¡Œã€‚\n"
+"「%sã€çš„列,但也å¯ä»¥è‡ªå·±ç§»é™¤æŽ‰é€™äº›åˆ—。\n"
"æ交訊æ¯ç©ºç™½å‰‡å–消本次æ交作業。\n"
#: builtin/commit.c
@@ -6018,7 +6024,7 @@ msgstr "日期"
msgid "override date for commit"
msgstr "æ交時覆蓋日期"
-#: builtin/commit.c builtin/merge-tree.c parse-options.h ref-filter.h
+#: builtin/commit.c parse-options.h ref-filter.h
msgid "commit"
msgstr "æ交"
@@ -6345,6 +6351,10 @@ msgid "with --get, use default value when missing entry"
msgstr "使用 --get 但未指定åƒæ•¸æ™‚所使用的é è¨­å€¼"
#: builtin/config.c
+msgid "human-readable comment string (# will be prepended as needed)"
+msgstr "人類å¯è®€çš„備註字串(將按需æ’å…¥ # 至å‰æ–¹ï¼‰"
+
+#: builtin/config.c
#, c-format
msgid "wrong number of arguments, should be %d"
msgstr "錯誤的åƒæ•¸å€‹æ•¸ï¼Œæ‡‰è©²ç‚º %d 個"
@@ -6457,6 +6467,10 @@ msgid "--default is only applicable to --get"
msgstr "--default 僅é©ç”¨æ–¼ --get"
#: builtin/config.c
+msgid "--comment is only applicable to add/set/replace operations"
+msgstr "--comment åªèƒ½ç”¨æ–¼åŠ å…¥ã€è¨­å®šå’Œå–代動作"
+
+#: builtin/config.c
msgid "--fixed-value only applies with 'value-pattern'"
msgstr "--fixed-value 僅套用至 'value-pattern'"
@@ -7025,7 +7039,7 @@ msgstr "來自 %.*s\n"
#: builtin/fetch.c
#, c-format
msgid "object %s not found"
-msgstr "物件 %s 未發ç¾"
+msgstr "找ä¸åˆ°ç‰©ä»¶ %s"
#: builtin/fetch.c
msgid "[up to date]"
@@ -7505,6 +7519,10 @@ msgid "read reference patterns from stdin"
msgstr "從 stdin 讀å–引用模å¼"
#: builtin/for-each-ref.c
+msgid "also include HEAD ref and pseudorefs"
+msgstr "åŒ…å« HEAD 引用和å½å¼•ç”¨"
+
+#: builtin/for-each-ref.c
msgid "unknown arguments supplied with --stdin"
msgstr "為 --stdin æ供的引數未知"
@@ -8266,6 +8284,7 @@ msgstr "grep:無法建立執行緒:%s"
msgid "invalid number of threads specified (%d) for %s"
msgstr "為 %2$s 設定的執行緒數 (%1$d) 無效"
+#. #-#-#-#-# grep.c.po #-#-#-#-#
#. TRANSLATORS: %s is the configuration
#. variable for tweaking threads, currently
#. grep.threads
@@ -8277,11 +8296,6 @@ msgstr "沒有執行緒支æ´ï¼Œå¿½ç•¥ %s"
#: builtin/grep.c
#, c-format
-msgid "unable to read tree (%s)"
-msgstr "無法讀å–樹(%s)"
-
-#: builtin/grep.c
-#, c-format
msgid "unable to read tree %s"
msgstr "ç„¡æ³•è®€å– %s 樹狀物件"
@@ -9039,13 +9053,46 @@ msgstr "--separate-git-dir 與純版本庫ä¸ç›¸å®¹"
#: builtin/interpret-trailers.c
msgid ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n"
+" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
" [--parse] [<file>...]"
msgstr ""
"git interpret-trailers [--in-place] [--trim-empty]\n"
-" [(--trailer (<key>|<keyAlias>)[(=|:)<value>])...]\n"
+" [(--trailer (<key>|<key-alias>)[(=|:)<value>])...]\n"
" [--parse] [<file>...]"
+#: builtin/interpret-trailers.c wrapper.c
+#, c-format
+msgid "could not stat %s"
+msgstr "ä¸èƒ½å° %s å‘¼å« stat"
+
+#: builtin/interpret-trailers.c
+#, c-format
+msgid "file %s is not a regular file"
+msgstr "檔案 %s ä¸æ˜¯ä¸€å€‹æ­£è¦æª”案"
+
+#: builtin/interpret-trailers.c
+#, c-format
+msgid "file %s is not writable by user"
+msgstr "檔案 %s 使用者ä¸å¯å¯«"
+
+#: builtin/interpret-trailers.c
+msgid "could not open temporary file"
+msgstr "ä¸èƒ½é–‹å•Ÿæš«å­˜æª”"
+
+#: builtin/interpret-trailers.c
+#, c-format
+msgid "could not read input file '%s'"
+msgstr "ä¸èƒ½è®€å–輸入檔案 '%s'"
+
+#: builtin/interpret-trailers.c builtin/mktag.c imap-send.c
+msgid "could not read from stdin"
+msgstr "ä¸èƒ½è‡ªæ¨™æº–輸入讀å–"
+
+#: builtin/interpret-trailers.c
+#, c-format
+msgid "could not rename temporary file to %s"
+msgstr "ä¸èƒ½é‡æ–°å‘½å暫存檔為 %s"
+
#: builtin/interpret-trailers.c
msgid "edit files in place"
msgstr "在原ä½ç·¨è¼¯æª”案"
@@ -9148,7 +9195,7 @@ msgstr "追蹤 <開始>,<çµæŸ> 範åœä¸­æ©«åˆ—或 <檔案> 中> :<函數å稱
#: builtin/log.c builtin/replay.c builtin/shortlog.c bundle.c
#, c-format
msgid "unrecognized argument: %s"
-msgstr "無法識別的åƒæ•¸ï¼š%s"
+msgstr "無法識別的引數:%s"
#: builtin/log.c
msgid "-L<range>:<file> cannot be used with pathspec"
@@ -9544,21 +9591,6 @@ msgid "could not get object info about '%s'"
msgstr "無法å–得「%sã€ç›¸é—œçš„物件資訊"
#: builtin/ls-files.c
-#, c-format
-msgid "bad ls-files format: element '%s' does not start with '('"
-msgstr "ls-files æ ¼å¼éŒ¯èª¤ï¼šâ€œ%s†元素ä¸ä»¥ “(†開頭"
-
-#: builtin/ls-files.c
-#, c-format
-msgid "bad ls-files format: element '%s' does not end in ')'"
-msgstr "ls-files æ ¼å¼éŒ¯èª¤ï¼šâ€œ%s†元素ä¸ä»¥ “)†çµå°¾"
-
-#: builtin/ls-files.c
-#, c-format
-msgid "bad ls-files format: %%%.*s"
-msgstr "ls-files æ ¼å¼éŒ¯èª¤ï¼š%%%.*s"
-
-#: builtin/ls-files.c
msgid "git ls-files [<options>] [<file>...]"
msgstr "git ls-files [<é¸é …>] [<檔案>...]"
@@ -9650,7 +9682,7 @@ msgstr "顯示相å°æ–¼é ‚級目錄的檔案å"
msgid "if any <file> is not in the index, treat this as an error"
msgstr "如果任何 <檔案> 都ä¸åœ¨ç´¢å¼•å€ï¼Œè¦–為錯誤"
-#: builtin/ls-files.c
+#: builtin/ls-files.c builtin/merge-tree.c
msgid "tree-ish"
msgstr "樹或æ交"
@@ -9728,21 +9760,6 @@ msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
msgstr "git ls-tree [<é¸é …>] <樹或æ交> [<路徑>...]"
#: builtin/ls-tree.c
-#, c-format
-msgid "bad ls-tree format: element '%s' does not start with '('"
-msgstr "無效的 ls-tree æ ¼å¼ï¼šã€Œ%sã€å…ƒç´ çš„é–‹é ­ä¸æ˜¯ã€Œ(ã€"
-
-#: builtin/ls-tree.c
-#, c-format
-msgid "bad ls-tree format: element '%s' does not end in ')'"
-msgstr "無效的 ls-tree æ ¼å¼ï¼šã€Œ%sã€å…ƒç´ çš„çµå°¾ä¸æ˜¯ã€Œ)ã€"
-
-#: builtin/ls-tree.c
-#, c-format
-msgid "bad ls-tree format: %%%.*s"
-msgstr "無效的 ls-tree æ ¼å¼ï¼š%%%.*s"
-
-#: builtin/ls-tree.c
msgid "only show trees"
msgstr "åªé¡¯ç¤ºæ¨¹"
@@ -9982,6 +9999,11 @@ msgstr "無法解æžå¼•ç”¨ '%s'"
msgid "Merging %s with %s\n"
msgstr "åˆä½µ %s å’Œ %s\n"
+#: builtin/merge-tree.c
+#, c-format
+msgid "could not parse as tree '%s'"
+msgstr "無法解æžç‚ºæ¨¹ç‹€ç‰©ä»¶ã€Œ%sã€"
+
#: builtin/merge-tree.c builtin/merge.c
msgid "not something we can merge"
msgstr "ä¸èƒ½åˆä½µ"
@@ -10245,9 +10267,9 @@ msgstr "空的æ交說明會終止æ交。\n"
#: builtin/merge.c
#, c-format
msgid ""
-"Lines starting with '%c' will be ignored, and an empty message aborts\n"
+"Lines starting with '%s' will be ignored, and an empty message aborts\n"
"the commit.\n"
-msgstr "以 '%c' 開始的行將被忽略,而空的æ交說明將終止æ交。\n"
+msgstr "以「%sã€é–‹å§‹çš„列將被忽略,æ交說明留空則會終止æ交。\n"
#: builtin/merge.c
msgid "Empty commit message."
@@ -10440,10 +10462,6 @@ msgstr "無法讀å–有標籤的物件「%sã€"
msgid "object '%s' tagged as '%s', but is a '%s' type"
msgstr "「%sã€å·²æ¨™ç‚ºã€Œ%sã€ï¼Œä½†å»æ˜¯ã€Œ%sã€é¡žåž‹"
-#: builtin/mktag.c imap-send.c trailer.c
-msgid "could not read from stdin"
-msgstr "ä¸èƒ½è‡ªæ¨™æº–輸入讀å–"
-
#: builtin/mktag.c
msgid "tag on stdin did not pass our strict fsck check"
msgstr "stdin 上的標籤未通éŽæˆ‘們的嚴格 fsck 檢查"
@@ -10656,7 +10674,7 @@ msgstr "列出å¯ä»¥å¾žæ‰€æœ‰å¼•ç”¨å­˜å–çš„æ交"
#: builtin/name-rev.c
msgid "deprecated: use --annotate-stdin instead"
-msgstr "已廢棄:請改用 --annotate-stdin"
+msgstr "已棄用:請改用 --annotate-stdin"
#: builtin/name-rev.c
msgid "annotate text from stdin"
@@ -10776,11 +10794,6 @@ msgid "Write/edit the notes for the following object:"
msgstr "為下é¢çš„物件寫/編輯說明:"
#: builtin/notes.c
-#, c-format
-msgid "unable to start 'show' for object '%s'"
-msgstr "ä¸èƒ½ç‚ºç‰©ä»¶ '%s' 開始 'show'"
-
-#: builtin/notes.c
msgid "could not read 'show' output"
msgstr "ä¸èƒ½è®€å– 'show' 的輸出"
@@ -10923,8 +10936,8 @@ msgid ""
"The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n"
"Please use 'git notes add -f -m/-F/-c/-C' instead.\n"
msgstr ""
-"å­æŒ‡ä»¤ 'edit' çš„é¸é … -m/-F/-c/-C 已棄用。\n"
-"è«‹æ›ç”¨ 'git notes add -f -m/-F/-c/-C'。\n"
+"å­æŒ‡ä»¤ã€Œeditã€çš„é¸é … -m/-F/-c/-C 已棄用。\n"
+"è«‹æ›ç”¨ã€Œgit notes add -f -m/-F/-c/-Cã€ã€‚\n"
#: builtin/notes.c
msgid "failed to delete ref NOTES_MERGE_PARTIAL"
@@ -11210,8 +11223,8 @@ msgid ""
"value of uploadpack.blobpackfileuri must be of the form '<object-hash> <pack-"
"hash> <uri>' (got '%s')"
msgstr ""
-"uploadpack.blobpackfileuri 的值格å¼å¿…須為 '<object-hash> <pack-hash> "
-"<uri>' (收到 '%s')"
+"uploadpack.blobpackfileuri 的值格å¼å¿…須為 '<object-hash> <pack-hash> <uri>' "
+"(收到 '%s')"
#: builtin/pack-objects.c
#, c-format
@@ -11553,10 +11566,10 @@ msgstr "傳入 --i-still-use-this å‰æ‹’絕執行"
#: builtin/pack-refs.c
msgid ""
-"git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude "
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
"<pattern>]"
msgstr ""
-"git pack-refs [--all] [--no-prune] [--include <pattern>] [--exclude "
+"git pack-refs [--all] [--no-prune] [--auto] [--include <pattern>] [--exclude "
"<pattern>]"
#: builtin/pack-refs.c
@@ -11568,6 +11581,10 @@ msgid "prune loose refs (default)"
msgstr "剪除鬆散引用(é è¨­å€¼ï¼‰"
#: builtin/pack-refs.c
+msgid "auto-pack refs as needed"
+msgstr "按需自動å°è£å¼•ç”¨"
+
+#: builtin/pack-refs.c
msgid "references to include"
msgstr "è¦åŒ…å«çš„引用"
@@ -12331,19 +12348,6 @@ msgid "could not remove '%s'"
msgstr "無法刪除 '%s'"
#: builtin/rebase.c
-msgid ""
-"Resolve all conflicts manually, mark them as resolved with\n"
-"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
-"You can instead skip this commit: run \"git rebase --skip\".\n"
-"To abort and get back to the state before \"git rebase\", run \"git rebase --"
-"abort\"."
-msgstr ""
-"手動解決所有è¡çªï¼ŒåŸ·è¡Œ \"git add/rm <è¡çªçš„檔案>\" 標記\n"
-"è¡çªå·²è§£æ±ºï¼Œç„¶å¾ŒåŸ·è¡Œ \"git rebase --continue\"。您也å¯ä»¥åŸ·è¡Œ\n"
-"\"git rebase --skip\" 指令略éŽé€™å€‹æ交。如果想è¦çµ‚止執行並回到\n"
-"\"git rebase\" 執行之å‰çš„狀態,執行 \"git rebase --abort\"。"
-
-#: builtin/rebase.c
#, c-format
msgid ""
"\n"
@@ -12376,11 +12380,15 @@ msgid "apply options and merge options cannot be used together"
msgstr "套用é¸é …與åˆä½µé¸é …ä¸å¾—åŒæ™‚使用"
#: builtin/rebase.c
+msgid "--empty=ask is deprecated; use '--empty=stop' instead."
+msgstr "--empty=ask 已棄用。請改用「--empty=stopã€ã€‚"
+
+#: builtin/rebase.c
#, c-format
msgid ""
"unrecognized empty type '%s'; valid values are \"drop\", \"keep\", and "
-"\"ask\"."
-msgstr "無法識別的 '%s' 空類型;有效的數值有 \"drop\"ã€\"keep\" è·Ÿ \"ask\"。"
+"\"stop\"."
+msgstr "無法識別空類型「%sã€ï¼›æœ‰æ•ˆçš„數值有「dropã€ã€ã€Œkeepã€è·Ÿã€Œstopã€ã€‚"
#: builtin/rebase.c
msgid ""
@@ -12522,7 +12530,7 @@ msgstr "讓使用者編輯è¦é‡å®šåŸºåº•çš„æ交列表"
msgid "(REMOVED) was: try to recreate merges instead of ignoring them"
msgstr "(已移除)曾為:嘗試é‡æ–°å»ºç«‹ï¼Œè€Œéžå¿½ç•¥åˆä½µ"
-#: builtin/rebase.c
+#: builtin/rebase.c builtin/revert.c
msgid "how to handle commits that become empty"
msgstr "處ç†ç©ºç™½æ交的方å¼"
@@ -12603,8 +12611,8 @@ msgstr ""
"請改用 “mergesâ€"
#: builtin/rebase.c
-msgid "No rebase in progress?"
-msgstr "沒有正在進行的é‡å®šåŸºåº•ï¼Ÿ"
+msgid "no rebase in progress"
+msgstr "沒有進行中的é‡å®šåŸºåº•æµç¨‹"
#: builtin/rebase.c
msgid "The --edit-todo action can only be used during interactive rebase."
@@ -12821,6 +12829,10 @@ msgid "git reflog [show] [<log-options>] [<ref>]"
msgstr "git reflog [show] [<log-options>] [<ref>]"
#: builtin/reflog.c
+msgid "git reflog list"
+msgstr "git reflog list"
+
+#: builtin/reflog.c
msgid ""
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>]\n"
" [--rewrite] [--updateref] [--stale-fix]\n"
@@ -12849,6 +12861,11 @@ msgstr "git reflog exists <引用>"
msgid "invalid timestamp '%s' given to '--%s'"
msgstr "傳入「--%sã€çš„時間戳「%sã€ç„¡æ•ˆ"
+#: builtin/reflog.c sequencer.c
+#, c-format
+msgid "%s does not accept arguments: '%s'"
+msgstr "%s ä¸æŽ¥å—åƒæ•¸ï¼š'%s'"
+
#: builtin/reflog.c
msgid "do not actually prune any entries"
msgstr "ä¸å¯¦éš›å‰ªé™¤ä»»ä½•é …ç›®"
@@ -13003,13 +13020,13 @@ msgid ""
"--mirror is dangerous and deprecated; please\n"
"\t use --mirror=fetch or --mirror=push instead"
msgstr ""
-"--mirror é¸é …å±éšªä¸”éŽæ™‚,請使用 --mirror=fetch\n"
+"--mirror é¸é …å±éšªä¸”已棄用,請使用 --mirror=fetch\n"
"\t 或 --mirror=push"
#: builtin/remote.c
#, c-format
-msgid "unknown mirror argument: %s"
-msgstr "未知的é¡åƒåƒæ•¸ï¼š%s"
+msgid "unknown --mirror argument: %s"
+msgstr "未知的 --mirror 引數:%s"
#: builtin/remote.c
msgid "fetch the remote branches"
@@ -13459,6 +13476,10 @@ msgid "could not start pack-objects to repack promisor objects"
msgstr "無法開始 pack-objects 來é‡æ–°æ‰“包 promisor 物件"
#: builtin/repack.c
+msgid "failed to feed promisor objects to pack-objects"
+msgstr "無法將承諾者物件喂給 pack-objects"
+
+#: builtin/repack.c
msgid "repack: Expecting full hex object ID lines only from pack-objects."
msgstr "repack:期望來自 pack-objects 的完整å六進ä½ç‰©ä»¶ ID。"
@@ -13960,7 +13981,7 @@ msgstr "在索引中註冊乾淨的解決方案"
#: builtin/rerere.c
msgid "'git rerere forget' without paths is deprecated"
-msgstr "沒有路徑的 'git rerere forget' 已經éŽæ™‚"
+msgstr "沒有路徑的「git rerere forgetã€å·²ç¶“棄用"
#: builtin/rerere.c
#, c-format
@@ -14070,7 +14091,7 @@ msgstr "無法將 '%s' 解æžç‚ºä¸€å€‹æœ‰æ•ˆçš„樹狀物件。"
#: builtin/reset.c
msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
-msgstr "--mixed 帶路徑已棄用,而是用 'git reset -- <路徑>'。"
+msgstr "--mixed 帶路徑已棄用,請改用「git reset -- <路徑>ã€ã€‚"
# 譯者:漢字之間無空格,故刪除%så‰å¾Œç©ºæ ¼
#: builtin/reset.c
@@ -14206,6 +14227,15 @@ msgid "--prefix requires an argument"
msgstr "--prefix éœ€è¦ 1 個引數"
#: builtin/rev-parse.c
+msgid "no object format specified"
+msgstr "未指定物件格å¼"
+
+#: builtin/rev-parse.c
+#, c-format
+msgid "unsupported object format: %s"
+msgstr "ä¸æ”¯æ´çš„物件格å¼ï¼š%s"
+
+#: builtin/rev-parse.c
#, c-format
msgid "unknown mode for --abbrev-ref: %s"
msgstr "--abbrev-ref 的模å¼æœªçŸ¥ï¼š%s"
@@ -14310,8 +14340,8 @@ msgid "allow commits with empty messages"
msgstr "å…許æ交說明為空"
#: builtin/revert.c
-msgid "keep redundant, empty commits"
-msgstr "ä¿æŒå¤šé¤˜çš„ã€ç©ºçš„æ交"
+msgid "deprecated: use --empty=keep instead"
+msgstr "已棄用:請改用 --empty=keep"
#: builtin/revert.c
msgid "use the 'reference' format to refer to commits"
@@ -14756,7 +14786,7 @@ msgstr "以 cone 模å¼åˆå§‹åŒ–稀ç–簽出"
msgid "toggle the use of a sparse index"
msgstr "切æ›æ˜¯å¦ä½¿ç”¨ç¨€ç–索引"
-#: builtin/sparse-checkout.c commit-graph.c midx.c sequencer.c
+#: builtin/sparse-checkout.c commit-graph.c midx-write.c sequencer.c
#, c-format
msgid "unable to create leading directories of %s"
msgstr "ä¸èƒ½ç‚º %s 建立先導目錄"
@@ -15922,12 +15952,12 @@ msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be ignored.\n"
+"Lines starting with '%s' will be ignored.\n"
msgstr ""
"\n"
-"輸入一個標籤說明:\n"
+"為標籤輸入說明訊æ¯ï¼š\n"
" %s\n"
-"以 '%c' 開頭的行將被忽略。\n"
+"以「%sã€é–‹é ­çš„列將被忽略。\n"
#: builtin/tag.c
#, c-format
@@ -15935,13 +15965,13 @@ msgid ""
"\n"
"Write a message for tag:\n"
" %s\n"
-"Lines starting with '%c' will be kept; you may remove them yourself if you "
+"Lines starting with '%s' will be kept; you may remove them yourself if you "
"want to.\n"
msgstr ""
"\n"
-"輸入一個標籤說明:\n"
+"為標籤輸入說明訊æ¯ï¼š\n"
" %s\n"
-"以 '%c' 開頭的行將被ä¿ç•™ï¼Œå¦‚果您願æ„也å¯ä»¥åˆªé™¤å®ƒå€‘。\n"
+"以「%sã€é–‹é ­çš„列將被ä¿ç•™ï¼›éœ€è¦çš„話您å¯ä»¥è‡ªå·±åˆªé™¤ã€‚\n"
#: builtin/tag.c
msgid "unable to sign the tag"
@@ -16050,6 +16080,10 @@ msgid "print only tags of the object"
msgstr "åªåˆ—å°æŒ‡å‘該物件的標籤"
#: builtin/tag.c
+msgid "could not start 'git column'"
+msgstr "無法啟動 “git columnâ€"
+
+#: builtin/tag.c
#, c-format
msgid "the '%s' option is only allowed in list mode"
msgstr "「%sã€é¸é …åªèƒ½åœ¨åˆ—表顯示模å¼ä½¿ç”¨"
@@ -16352,12 +16386,12 @@ msgid "fsmonitor disabled"
msgstr "fsmonitor 被åœç”¨"
#: builtin/update-ref.c
-msgid "git update-ref [<options>] -d <refname> [<old-val>]"
-msgstr "git update-ref [<é¸é …>] -d <引用å> [<舊值>]"
+msgid "git update-ref [<options>] -d <refname> [<old-oid>]"
+msgstr "git update-ref [<options>] -d <refname> [<old-oid>]"
#: builtin/update-ref.c
-msgid "git update-ref [<options>] <refname> <new-val> [<old-val>]"
-msgstr "git update-ref [<é¸é …>] <引用å> <新值> [<舊值>]"
+msgid "git update-ref [<options>] <refname> <new-oid> [<old-oid>]"
+msgstr "git update-ref [<options>] <refname> <new-oid> [<old-oid>]"
#: builtin/update-ref.c
msgid "git update-ref [<options>] --stdin [-z]"
@@ -16667,7 +16701,7 @@ msgstr "「%sã€ã€ã€Œ%sã€å’Œã€Œ%sã€é¸é …ä¸å¾—åŒæ™‚使用"
#: builtin/worktree.c
#, c-format
msgid "option '%s' and commit-ish cannot be used together"
-msgstr "“%s†é¸é …å’Œæ交號ä¸å¾—åŒæ™‚使用"
+msgstr "「%sã€é¸é …å’Œæ交編號ä¸å¾—åŒæ™‚使用"
#: builtin/worktree.c
msgid "added with --lock"
@@ -16905,7 +16939,7 @@ msgstr "無法識別的套件包雜湊演算法:%s"
#: bundle.c
#, c-format
msgid "unknown capability '%s'"
-msgstr "未知功能 '%s'"
+msgstr "未知功能「%sã€"
#: bundle.c
#, c-format
@@ -16915,7 +16949,7 @@ msgstr "“%s†ä¸åƒæ˜¯ä¸€å€‹ v2 或 v3 版本的套件包檔案"
#: bundle.c
#, c-format
msgid "unrecognized header: %s%s (%d)"
-msgstr "無法識別的包頭:%s%s (%d)"
+msgstr "無法識別的標頭:%s%s (%d)"
#: bundle.c
msgid "Repository lacks these prerequisite commits:"
@@ -16963,7 +16997,7 @@ msgstr "無法複製套件包æè¿°å…ƒ"
#: bundle.c
msgid "Could not spawn pack-objects"
-msgstr "ä¸èƒ½ç”Ÿæˆ pack-objects 進程"
+msgstr "無法 spawn pack-objects 處ç†ç¨‹åº"
#: bundle.c
msgid "pack-objects died"
@@ -16972,7 +17006,7 @@ msgstr "pack-objects 終止"
#: bundle.c
#, c-format
msgid "ref '%s' is excluded by the rev-list options"
-msgstr "引用 '%s' 被 rev-list é¸é …排除"
+msgstr "引用「%sã€è¢« rev-list é¸é …排除"
#: bundle.c
#, c-format
@@ -16991,7 +17025,7 @@ msgstr "ä¸èƒ½å»ºç«‹ç©ºå¥—件包。"
#: bundle.c
#, c-format
msgid "cannot create '%s'"
-msgstr "ä¸èƒ½å»ºç«‹ '%s'"
+msgstr "無法建立「%sã€"
#: bundle.c
msgid "index-pack died"
@@ -16999,7 +17033,7 @@ msgstr "index-pack 終止"
#: chunk-format.c
msgid "terminating chunk id appears earlier than expected"
-msgstr "終止å€å¡Š id 出ç¾çš„時間早於é æœŸ"
+msgstr "終止å€å¡Š ID 比é æœŸé‚„早出ç¾"
#: chunk-format.c
#, c-format
@@ -18064,6 +18098,11 @@ msgstr "æäº¤åœ–å½¢ä¸­åŒ…å« 0 å’Œéž 0 兩個世代號(例如 “%s†和 â
msgid "Verifying commits in commit graph"
msgstr "正在驗證æ交圖中的æ交"
+#: commit-reach.c sequencer.c
+#, c-format
+msgid "could not parse commit %s"
+msgstr "ä¸èƒ½è§£æžæ交 %s"
+
#: commit.c
#, c-format
msgid "%s %s is not a commit!"
@@ -18080,14 +18119,14 @@ msgid ""
"Turn this message off by running\n"
"\"git config advice.graftFileDeprecated false\""
msgstr ""
-"å° <GIT_DIR>/info/grafts 的支æ´å·²è¢«æ£„用,並將在\n"
-"未來的Git版本中被移除。\n"
+"å° <GIT_DIR>/info/grafts 的支æ´å·²æ£„用,並將在\n"
+"未來的 Git 版本中被移除。\n"
"\n"
-"請使用 \"git replace --convert-graft-file\" 將\n"
+"請使用「git replace --convert-graft-fileã€å°‡\n"
"grafts 轉æ›ç‚ºå–代引用。\n"
"\n"
-"設定 \"git config advice.graftFileDeprecated false\"\n"
-"å¯é—œé–‰æœ¬æ¶ˆæ¯"
+"設定「git config advice.graftFileDeprecated falseã€\n"
+"å¯ä»¥å°‡æœ¬è¨Šæ¯é—œé–‰"
#: commit.c
#, c-format
@@ -18591,8 +18630,14 @@ msgid "bad zlib compression level %d"
msgstr "錯誤的 zlib 壓縮級別 %d"
#: config.c
-msgid "core.commentChar should only be one ASCII character"
-msgstr "core.commentChar 應該是一個 ASCII 字元"
+#, c-format
+msgid "%s cannot contain newline"
+msgstr "%s ä¸èƒ½åŒ…å«æ›è¡Œç¬¦è™Ÿ"
+
+#: config.c
+#, c-format
+msgid "%s must have at least one character"
+msgstr "%s 得有至少 1 個字元"
#: config.c
#, c-format
@@ -18601,7 +18646,7 @@ msgstr "忽略未知的 core.fsyncMethod 值「%sã€"
#: config.c
msgid "core.fsyncObjectFiles is deprecated; use core.fsync instead"
-msgstr "core.fsyncObjectFiles 已被å–代。請改用 core.fsync"
+msgstr "core.fsyncObjectFiles 已棄用。請改用 core.fsync"
#: config.c
#, c-format
@@ -18682,6 +18727,11 @@ msgstr "寫入新的設定檔案 %s 失敗"
#: config.c
#, c-format
+msgid "no multi-line comment allowed: '%s'"
+msgstr "ä¸å…許多列備註:「%sã€"
+
+#: config.c
+#, c-format
msgid "could not lock config file %s"
msgstr "ä¸èƒ½éŽ–定設定檔案 %s"
@@ -19419,7 +19469,6 @@ msgid "output only the last line of --stat"
msgstr "åªè¼¸å‡º --stat 的最後一行"
#: diff.c
-#| msgid "<param1,param2>..."
msgid "<param1>,<param2>..."
msgstr "<param1>,<param2>..."
@@ -20845,6 +20894,16 @@ msgstr ""
msgid "Unable to create '%s.lock': %s"
msgstr "ä¸èƒ½å»ºç«‹ '%s.lock':%s"
+#: loose.c
+#, c-format
+msgid "could not write loose object index %s"
+msgstr "無法寫入鬆散物件索引 %s"
+
+#: loose.c
+#, c-format
+msgid "failed to write loose object index %s\n"
+msgstr "寫入鬆散物件索引 %s 失敗\n"
+
#: ls-refs.c
#, c-format
msgid "unexpected line: '%s'"
@@ -20858,6 +20917,11 @@ msgstr "在 ls-refs 引數之後應該有一個 flush 包"
msgid "quoted CRLF detected"
msgstr "åµæ¸¬åˆ°ç”±å¯åˆ—å°å­—å…ƒ (quoted) 所組æˆçš„ CRLF"
+#: mem-pool.c strbuf.c wrapper.c
+#, c-format
+msgid "unable to format message: %s"
+msgstr "無法格å¼åŒ–訊æ¯ï¼š%s"
+
#: merge-ort.c merge-recursive.c
#, c-format
msgid "Failed to merge submodule %s (not checked out)"
@@ -20875,6 +20939,11 @@ msgstr "無法åˆä½µå­æ¨¡çµ„ %s(æ交ä¸å­˜åœ¨ï¼‰"
#: merge-ort.c merge-recursive.c
#, c-format
+msgid "Failed to merge submodule %s (repository corrupt)"
+msgstr "無法åˆä½µå­æ¨¡çµ„ %s (版本庫æ壞)"
+
+#: merge-ort.c merge-recursive.c
+#, c-format
msgid "Failed to merge submodule %s (commits don't follow merge-base)"
msgstr "無法åˆä½µå­æ¨¡çµ„ %s (æ交未跟隨åˆä½µåŸºç¤Žï¼‰"
@@ -21185,7 +21254,7 @@ msgstr "快轉å­æ¨¡çµ„ %s"
#: merge-recursive.c
#, c-format
msgid "Failed to merge submodule %s (merge following commits not found)"
-msgstr "無法åˆä½µå­æ¨¡çµ„ %s (沒發ç¾åˆä½µè·Ÿéš¨çš„æ交)"
+msgstr "無法åˆä½µå­æ¨¡çµ„ %s (找ä¸åˆ°åˆä½µè·Ÿéš¨çš„æ交)"
#: merge-recursive.c
#, c-format
@@ -21405,6 +21474,104 @@ msgstr "ä¸èƒ½è§£æžç‰©ä»¶ '%s'"
msgid "failed to read the cache"
msgstr "讀å–å¿«å–失敗"
+#: midx-write.c
+#, c-format
+msgid "failed to add packfile '%s'"
+msgstr "新增 packfile '%s' 失敗"
+
+#: midx-write.c
+#, c-format
+msgid "failed to open pack-index '%s'"
+msgstr "開啟包索引 '%s' 失敗"
+
+#: midx-write.c
+#, c-format
+msgid "failed to locate object %d in packfile"
+msgstr "在 packfile 中定ä½ç‰©ä»¶ %d 失敗"
+
+#: midx-write.c
+msgid "cannot store reverse index file"
+msgstr "無法儲存倒排索引檔案"
+
+#: midx-write.c
+#, c-format
+msgid "could not parse line: %s"
+msgstr "無法解æžæ©«åˆ—:%s"
+
+#: midx-write.c
+#, c-format
+msgid "malformed line: %s"
+msgstr "橫列格å¼éŒ¯èª¤ï¼š%s"
+
+#: midx-write.c
+msgid "ignoring existing multi-pack-index; checksum mismatch"
+msgstr "忽略ç¾æœ‰çš„多包索引:總和檢查碼ä¸ç¬¦"
+
+#: midx-write.c
+msgid "could not load pack"
+msgstr "無法載入包"
+
+#: midx-write.c
+#, c-format
+msgid "could not open index for %s"
+msgstr "無法開啟 %s 的索引"
+
+#: midx-write.c
+msgid "Adding packfiles to multi-pack-index"
+msgstr "正在新增 packfile 至多包索引"
+
+#: midx-write.c
+#, c-format
+msgid "unknown preferred pack: '%s'"
+msgstr "未知å好包:「%sã€"
+
+#: midx-write.c
+#, c-format
+msgid "cannot select preferred pack %s with no objects"
+msgstr "無法é¸å–å好,沒有物件的 %s 包"
+
+#: midx-write.c
+#, c-format
+msgid "did not see pack-file %s to drop"
+msgstr "沒有看到è¦æ¨æ£„çš„ packfile %s"
+
+#: midx-write.c
+#, c-format
+msgid "preferred pack '%s' is expired"
+msgstr "å好包「%sã€å·²ç¶“éŽæœŸ"
+
+#: midx-write.c
+msgid "no pack files to index."
+msgstr "沒有è¦ç´¢å¼•çš„ pack 檔案。"
+
+#: midx-write.c
+msgid "refusing to write multi-pack .bitmap without any objects"
+msgstr "拒絕寫入無任何物件的多包 .bitmap"
+
+#: midx-write.c
+msgid "could not write multi-pack bitmap"
+msgstr "無法寫入多包ä½åœ–"
+
+#: midx-write.c
+msgid "could not write multi-pack-index"
+msgstr "無法寫入多包索引"
+
+#: midx-write.c
+msgid "Counting referenced objects"
+msgstr "正在計算引用物件"
+
+#: midx-write.c
+msgid "Finding and deleting unreferenced packfiles"
+msgstr "正在尋找並刪除沒有引用的 packfile"
+
+#: midx-write.c
+msgid "could not start pack-objects"
+msgstr "ä¸èƒ½é–‹å§‹ pack-objects"
+
+#: midx-write.c
+msgid "could not finish pack-objects"
+msgstr "ä¸èƒ½çµæŸ pack-objects"
+
#: midx.c
msgid "multi-pack-index OID fanout is of the wrong size"
msgstr "多包索引的物件 ID fanout 大å°éŒ¯èª¤"
@@ -21492,88 +21659,6 @@ msgstr "多包索引的最大å移超出邊界"
#: midx.c
#, c-format
-msgid "failed to add packfile '%s'"
-msgstr "新增 packfile '%s' 失敗"
-
-#: midx.c
-#, c-format
-msgid "failed to open pack-index '%s'"
-msgstr "開啟包索引 '%s' 失敗"
-
-#: midx.c
-#, c-format
-msgid "failed to locate object %d in packfile"
-msgstr "在 packfile 中定ä½ç‰©ä»¶ %d 失敗"
-
-#: midx.c
-msgid "cannot store reverse index file"
-msgstr "無法儲存倒排索引檔案"
-
-#: midx.c
-#, c-format
-msgid "could not parse line: %s"
-msgstr "無法解æžæ©«åˆ—:%s"
-
-#: midx.c
-#, c-format
-msgid "malformed line: %s"
-msgstr "橫列格å¼éŒ¯èª¤ï¼š%s"
-
-#: midx.c
-msgid "ignoring existing multi-pack-index; checksum mismatch"
-msgstr "忽略ç¾æœ‰çš„多包索引:總和檢查碼ä¸ç¬¦"
-
-#: midx.c
-msgid "could not load pack"
-msgstr "無法載入包"
-
-#: midx.c
-#, c-format
-msgid "could not open index for %s"
-msgstr "無法開啟 %s 的索引"
-
-#: midx.c
-msgid "Adding packfiles to multi-pack-index"
-msgstr "正在新增 packfile 至多包索引"
-
-#: midx.c
-#, c-format
-msgid "unknown preferred pack: '%s'"
-msgstr "未知å好包:「%sã€"
-
-#: midx.c
-#, c-format
-msgid "cannot select preferred pack %s with no objects"
-msgstr "無法é¸å–å好,沒有物件的 %s 包"
-
-#: midx.c
-#, c-format
-msgid "did not see pack-file %s to drop"
-msgstr "沒有看到è¦æ¨æ£„çš„ packfile %s"
-
-#: midx.c
-#, c-format
-msgid "preferred pack '%s' is expired"
-msgstr "å好包「%sã€å·²ç¶“éŽæœŸ"
-
-#: midx.c
-msgid "no pack files to index."
-msgstr "沒有è¦ç´¢å¼•çš„ pack 檔案。"
-
-#: midx.c
-msgid "refusing to write multi-pack .bitmap without any objects"
-msgstr "拒絕寫入無任何物件的多包 .bitmap"
-
-#: midx.c
-msgid "could not write multi-pack bitmap"
-msgstr "無法寫入多包ä½åœ–"
-
-#: midx.c
-msgid "could not write multi-pack-index"
-msgstr "無法寫入多包索引"
-
-#: midx.c
-#, c-format
msgid "failed to clear multi-pack-index at %s"
msgstr "清ç†ä½æ–¼ %s 的多包索引失敗"
@@ -21625,22 +21710,6 @@ msgstr "為 packfile %s 載入包索引失敗"
msgid "incorrect object offset for oid[%d] = %s: %<PRIx64> != %<PRIx64>"
msgstr "oid[%d] = %s 錯誤的物件ä½ç§»ï¼š%<PRIx64> != %<PRIx64>"
-#: midx.c
-msgid "Counting referenced objects"
-msgstr "正在計算引用物件"
-
-#: midx.c
-msgid "Finding and deleting unreferenced packfiles"
-msgstr "正在尋找並刪除沒有引用的 packfile"
-
-#: midx.c
-msgid "could not start pack-objects"
-msgstr "ä¸èƒ½é–‹å§‹ pack-objects"
-
-#: midx.c
-msgid "could not finish pack-objects"
-msgstr "ä¸èƒ½çµæŸ pack-objects"
-
#: name-hash.c
#, c-format
msgid "unable to create lazy_dir thread: %s"
@@ -21695,6 +21764,30 @@ msgstr "æ‹’çµ•å‘ %s(在 refs/notes/ 之外)寫入註解"
msgid "Bad %s value: '%s'"
msgstr "壞的 %s 值:'%s'"
+#: object-file-convert.c
+msgid "failed to decode tree entry"
+msgstr "無法解碼樹狀物件項目"
+
+#: object-file-convert.c
+#, c-format
+msgid "failed to map tree entry for %s"
+msgstr "無法為 %s 映射樹狀物件項目"
+
+#: object-file-convert.c
+#, c-format
+msgid "bad %s in commit"
+msgstr "æ交中有無效的 %s"
+
+#: object-file-convert.c
+#, c-format
+msgid "unable to map %s %s in commit object"
+msgstr "無法在æ交物件中映射 %s %s"
+
+#: object-file-convert.c
+#, c-format
+msgid "Failed to convert object from %s to %s"
+msgstr "無法將物件從 %s 轉æ›ç‚º %s"
+
#: object-file.c
#, c-format
msgid "object directory %s does not exist; check .git/objects/info/alternates"
@@ -21823,6 +21916,11 @@ msgstr "打包物件 %s(儲存在 %s)已æ壞"
#: object-file.c
#, c-format
+msgid "missing mapping of %s to %s"
+msgstr "缺少 %s 到 %s 的映射"
+
+#: object-file.c
+#, c-format
msgid "unable to write file %s"
msgstr "無法寫檔案 %s"
@@ -21890,6 +21988,11 @@ msgstr "ä¸èƒ½è®€å–物件 %s"
#: object-file.c
#, c-format
+msgid "cannot map object %s to %s"
+msgstr "無法將物件 %s 映射到 %s"
+
+#: object-file.c
+#, c-format
msgid "object fails fsck: %s"
msgstr "物件 fsck 失敗:%s"
@@ -22252,6 +22355,10 @@ msgid "unable to load pack: '%s', disabling pack-reuse"
msgstr "無法載入「%sã€å°è£ï¼Œåœç”¨ pack-reuse"
#: pack-bitmap.c
+msgid "unable to compute preferred pack, disabling pack-reuse"
+msgstr "無法計算å好å°è£ï¼Œåœç”¨ pack-reuse"
+
+#: pack-bitmap.c
#, c-format
msgid "object '%s' not found in type bitmaps"
msgstr "在類型ä½åœ–中,找ä¸åˆ°ã€Œ%sã€ç‰©ä»¶"
@@ -22624,7 +22731,7 @@ msgstr "路徑è¦æ ¼åŒ…å«ç„¡æ•ˆçš„神奇å‰ç¶´"
#: pathspec.c
#, c-format
msgid "Invalid pathspec magic '%.*s' in '%s'"
-msgstr "在路徑è¦æ ¼ '%3$s' 中無效的神奇å‰ç¶´ '%2$.*1$s'"
+msgstr "有無效的神奇å‰ç¶´ã€Œ%.*sã€å‡ºç¾åœ¨è·¯å¾‘è¦æ ¼ã€Œ%sã€ä¸­"
#: pathspec.c
#, c-format
@@ -23521,6 +23628,84 @@ msgstr "無法刪除引用 %s:%s"
msgid "could not delete references: %s"
msgstr "無法刪除引用:%s"
+#: refs/reftable-backend.c
+#, c-format
+msgid "refname is dangerous: %s"
+msgstr "此引用å稱是å±éšªçš„:%s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "trying to write ref '%s' with nonexistent object %s"
+msgstr "嘗試以ä¸å­˜åœ¨çš„物件 %s 寫入引用「%sã€"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "trying to write non-commit object %s to branch '%s'"
+msgstr "嘗試將éžæ交物件 %s 寫入分支「%sã€"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid ""
+"multiple updates for 'HEAD' (including one via its referent '%s') are not "
+"allowed"
+msgstr "ä¸å…許å°ã€ŒHEADã€é€²è¡Œå¤šæ¬¡æ›´æ–°ï¼ˆåŒ…å«é€éŽå…¶ã€Œ%sã€å¼•ç”¨é€²è¡Œçš„更新)"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': unable to resolve reference '%s'"
+msgstr "無法鎖定引用「%sã€ï¼šç„¡æ³•è§£æžå¼•ç”¨ã€Œ%sã€"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': error reading reference"
+msgstr "無法鎖定引用「%sã€ï¼šç„¡æ³•è®€å–引用"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid ""
+"multiple updates for '%s' (including one via symref '%s') are not allowed"
+msgstr "ä¸å…許å°ã€Œ%sã€é€²è¡Œå¤šæ¬¡æ›´æ–°ï¼ˆåŒ…å«é€éŽã€Œ%sã€ç¬¦è™Ÿå¼•ç”¨é€²è¡Œçš„更新)"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': reference already exists"
+msgstr "無法鎖定引用「%sã€ï¼šå¼•ç”¨å·²ç¶“存在"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': reference is missing but expected %s"
+msgstr "無法鎖定引用「%sã€ï¼šç¼ºå°‘引用但é æœŸçš„是 %s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "cannot lock ref '%s': is at %s but expected %s"
+msgstr "無法鎖定引用「%sã€ï¼šä½æ–¼ %s 但é æœŸçš„是 %s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "reftable: transaction prepare: %s"
+msgstr "引用表:準備事務:%s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "reftable: transaction failure: %s"
+msgstr "引用表:事務失敗:%s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "unable to compact stack: %s"
+msgstr "無法壓縮堆疊:%s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "refname %s not found"
+msgstr "找ä¸åˆ°å¼•ç”¨å稱 %s"
+
+#: refs/reftable-backend.c
+#, c-format
+msgid "refname %s is a symbolic ref, copying it is not supported"
+msgstr "引用å稱 %s 是符號引用,ä¸æ”¯æ´è¤‡è£½"
+
#: refspec.c
#, c-format
msgid "invalid refspec '%s'"
@@ -23533,6 +23718,11 @@ msgstr "在 push-option å–值中無效的引號:'%s'"
#: remote-curl.c
#, c-format
+msgid "unknown value for object-format: %s"
+msgstr "未知的 object-format 值:%s"
+
+#: remote-curl.c
+#, c-format
msgid "%sinfo/refs not valid: is this a git repository?"
msgstr "%sinfo/refs 無效:這是一個 git 版本庫嗎?"
@@ -24067,8 +24257,21 @@ msgstr "resolve-undo ä¸å­˜åœ¨çš„「%sã€è¨˜éŒ„"
#: revision.c
#, c-format
-msgid "could not get commit for ancestry-path argument %s"
-msgstr "無法å–å¾— ancestry-path 引數 %s çš„æ交"
+msgid "%s exists but is a symbolic ref"
+msgstr "%s 存在但屬於符號連çµ"
+
+#: revision.c
+msgid ""
+"--merge requires one of the pseudorefs MERGE_HEAD, CHERRY_PICK_HEAD, "
+"REVERT_HEAD or REBASE_HEAD"
+msgstr ""
+"--merge 需è¦å…¶ä¸­ä¸€ç¨®å½å¼•ç”¨ MERGE_HEADã€CHERRY_PICK_HEADã€REVERT_HEAD 或 "
+"REBASE_HEAD"
+
+#: revision.c
+#, c-format
+msgid "could not get commit for --ancestry-path argument %s"
+msgstr "無法å–å¾— --ancestry-path 引數 %s çš„æ交"
#: revision.c
msgid "--unpacked=<packfile> no longer supported"
@@ -24429,6 +24632,19 @@ msgstr "未知動作:%d"
#: sequencer.c
msgid ""
+"Resolve all conflicts manually, mark them as resolved with\n"
+"\"git add/rm <conflicted_files>\", then run \"git rebase --continue\".\n"
+"You can instead skip this commit: run \"git rebase --skip\".\n"
+"To abort and get back to the state before \"git rebase\", run \"git rebase --"
+"abort\"."
+msgstr ""
+"手動解決所有è¡çªï¼ŒåŸ·è¡Œ \"git add/rm <è¡çªçš„檔案>\" 標記\n"
+"è¡çªå·²è§£æ±ºï¼Œç„¶å¾ŒåŸ·è¡Œ \"git rebase --continue\"。您也å¯ä»¥åŸ·è¡Œ\n"
+"\"git rebase --skip\" 指令略éŽé€™å€‹æ交。如果想è¦çµ‚止執行並回到\n"
+"\"git rebase\" 執行之å‰çš„狀態,執行 \"git rebase --abort\"。"
+
+#: sequencer.c
+msgid ""
"after resolving the conflicts, mark the corrected paths\n"
"with 'git add <paths>' or 'git rm <paths>'"
msgstr ""
@@ -24681,11 +24897,6 @@ msgstr "ä¸èƒ½æ›´æ–° %s"
#: sequencer.c
#, c-format
-msgid "could not parse commit %s"
-msgstr "ä¸èƒ½è§£æžæ交 %s"
-
-#: sequencer.c
-#, c-format
msgid "could not parse parent commit %s"
msgstr "ä¸èƒ½è§£æžçˆ¶æ交 %s"
@@ -24816,11 +25027,6 @@ msgstr "無效的命令 “%.*sâ€"
#: sequencer.c
#, c-format
-msgid "%s does not accept arguments: '%s'"
-msgstr "%s ä¸æŽ¥å—åƒæ•¸ï¼š'%s'"
-
-#: sequencer.c
-#, c-format
msgid "missing arguments for %s"
msgstr "缺少 %s çš„åƒæ•¸"
@@ -25371,6 +25577,11 @@ msgstr "無法使用無效設定來建立工作å€"
#: setup.c
#, c-format
+msgid "'%s' already specified as '%s'"
+msgstr "「%sã€å·²ç¶“指定為「%sã€"
+
+#: setup.c
+#, c-format
msgid "Expected git repo version <= %d, found %d"
msgstr "期望 git 版本庫版本 <= %d,å»å¾—到 %d"
@@ -25599,6 +25810,24 @@ msgstr "索引項目是資料夾,但ä¸æ˜¯ç¨€ç–資料夾(%08x)"
msgid "cannot use split index with a sparse index"
msgstr "無法在稀ç–索引使用索引分割"
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#: strbuf.c
+#, c-format
+msgid "bad %s format: element '%s' does not start with '('"
+msgstr "無效的 %s æ ¼å¼ï¼šã€Œ%sã€å…ƒç´ çš„é–‹é ­ä¸æ˜¯ã€Œ(ã€"
+
+#. TRANSLATORS: The first %s is a command like "ls-tree".
+#: strbuf.c
+#, c-format
+msgid "bad %s format: element '%s' does not end in ')'"
+msgstr "無效的 %s æ ¼å¼ï¼šã€Œ%sã€å…ƒç´ çš„çµå°¾ä¸æ˜¯ã€Œ)ã€"
+
+#. TRANSLATORS: %s is a command like "ls-tree".
+#: strbuf.c
+#, c-format
+msgid "bad %s format: %%%.*s"
+msgstr "無效的 %s æ ¼å¼ï¼š%%%.*s"
+
#. TRANSLATORS: IEC 80000-13:2008 gibibyte
#: strbuf.c
#, c-format
@@ -25988,35 +26217,6 @@ msgstr "éµ '%2$s' 的未知å–值 '%1$s'"
msgid "empty trailer token in trailer '%.*s'"
msgstr "ç°½å '%.*s' çš„éµç‚ºç©º"
-#: trailer.c
-#, c-format
-msgid "could not read input file '%s'"
-msgstr "ä¸èƒ½è®€å–輸入檔案 '%s'"
-
-#: trailer.c wrapper.c
-#, c-format
-msgid "could not stat %s"
-msgstr "ä¸èƒ½å° %s å‘¼å« stat"
-
-#: trailer.c
-#, c-format
-msgid "file %s is not a regular file"
-msgstr "檔案 %s ä¸æ˜¯ä¸€å€‹æ­£è¦æª”案"
-
-#: trailer.c
-#, c-format
-msgid "file %s is not writable by user"
-msgstr "檔案 %s 使用者ä¸å¯å¯«"
-
-#: trailer.c
-msgid "could not open temporary file"
-msgstr "ä¸èƒ½é–‹å•Ÿæš«å­˜æª”"
-
-#: trailer.c
-#, c-format
-msgid "could not rename temporary file to %s"
-msgstr "ä¸èƒ½é‡æ–°å‘½å暫存檔為 %s"
-
#: transport-helper.c
msgid "full write to remote helper failed"
msgstr "完整寫入é ç«¯å”助工具失敗"
@@ -26136,8 +26336,8 @@ msgstr "remote-heper ä¸æ”¯æ´ push,需è¦å¼•ç”¨è¦æ ¼"
#: transport-helper.c
#, c-format
-msgid "helper %s does not support 'force'"
-msgstr "å”助工具 %s ä¸æ”¯æ´ 'force'"
+msgid "helper %s does not support '--force'"
+msgstr "å”助工具 %s ä¸æ”¯æ´ã€Œ--forceã€"
#: transport-helper.c
msgid "couldn't run fast-export"
@@ -26612,6 +26812,11 @@ msgid "invalid '..' path segment"
msgstr "無效的 '..' 路徑å€å¡Š"
#: usage.c
+#, c-format
+msgid "error: unable to format message: %s\n"
+msgstr "錯誤:無法格å¼åŒ–訊æ¯ï¼š%s\n"
+
+#: usage.c
msgid "usage: "
msgstr "用法: "
@@ -27793,6 +27998,53 @@ msgstr "ç•¥éŽ %s å«å‚™ä»½å¾Œç¶´ '%s'。\n"
msgid "Do you really want to send %s? [y|N]: "
msgstr "您真的è¦å‚³é€ %s?[y|N]: "
+#, c-format
+#~ msgid "truncating .rej filename to %.*s.rej"
+#~ msgstr "正在將 .rej 檔案å稱截短為 %.*s.rej"
+
+#~ msgid ""
+#~ "Use -f if you really want to add them.\n"
+#~ "Turn this message off by running\n"
+#~ "\"git config advice.addIgnoredFile false\""
+#~ msgstr ""
+#~ "若您真的想加入,請傳入 -f。\n"
+#~ "如è¦é—œé–‰æ­¤è¨Šæ¯ï¼Œè«‹åŸ·è¡Œ\n"
+#~ "“git config advice.addIgnoredFile falseâ€"
+
+#~ msgid ""
+#~ "Maybe you wanted to say 'git add .'?\n"
+#~ "Turn this message off by running\n"
+#~ "\"git config advice.addEmptyPathspec false\""
+#~ msgstr ""
+#~ "å¯èƒ½æ‚¨æƒ³åš “git add .â€ï¼Ÿ\n"
+#~ "如è¦é—œé–‰æ­¤è¨Šæ¯ï¼Œè«‹åŸ·è¡Œ\n"
+#~ "“git config advice.addEmptyPathspec falseâ€"
+
+#~ msgid ""
+#~ "clean.requireForce defaults to true and neither -i, -n, nor -f given; "
+#~ "refusing to clean"
+#~ msgstr ""
+#~ "clean.requireForce é è¨­ç‚º true 且未æä¾› -iã€-n 或 -f é¸é …,拒絕執行清ç†å‹•"
+#~ "作"
+
+#, c-format
+#~ msgid "bad ls-files format: element '%s' does not start with '('"
+#~ msgstr "ls-files æ ¼å¼éŒ¯èª¤ï¼šâ€œ%s†元素ä¸ä»¥ “(†開頭"
+
+#, c-format
+#~ msgid "bad ls-files format: element '%s' does not end in ')'"
+#~ msgstr "ls-files æ ¼å¼éŒ¯èª¤ï¼šâ€œ%s†元素ä¸ä»¥ “)†çµå°¾"
+
+#, c-format
+#~ msgid "bad ls-files format: %%%.*s"
+#~ msgstr "ls-files æ ¼å¼éŒ¯èª¤ï¼š%%%.*s"
+
+#~ msgid "keep redundant, empty commits"
+#~ msgstr "ä¿æŒå¤šé¤˜çš„ã€ç©ºçš„æ交"
+
+#~ msgid "core.commentChar should only be one ASCII character"
+#~ msgstr "core.commentChar 應該是一個 ASCII 字元"
+
#~ msgid "-x and -X cannot be used together"
#~ msgstr "-x å’Œ -X ä¸èƒ½åŒæ™‚使用"
@@ -27838,9 +28090,5 @@ msgstr "您真的è¦å‚³é€ %s?[y|N]: "
#~ msgid "%s is incompatible with %s"
#~ msgstr "%s 與 %s ä¸ç›¸å®¹"
-#, c-format
-#~ msgid "could not remove reference %s"
-#~ msgstr "無法刪除引用 %s"
-
#~ msgid "unhandled options"
#~ msgstr "未處ç†é¸é …"
diff --git a/promisor-remote.c b/promisor-remote.c
index ac3aa1e365..b414922c44 100644
--- a/promisor-remote.c
+++ b/promisor-remote.c
@@ -8,6 +8,7 @@
#include "transport.h"
#include "strvec.h"
#include "packfile.h"
+#include "environment.h"
struct promisor_remote_config {
struct promisor_remote *promisors;
@@ -23,6 +24,15 @@ static int fetch_objects(struct repository *repo,
int i;
FILE *child_in;
+ if (git_env_bool(NO_LAZY_FETCH_ENVIRONMENT, 0)) {
+ static int warning_shown;
+ if (!warning_shown) {
+ warning_shown = 1;
+ warning(_("lazy fetching disabled; some objects may not be available"));
+ }
+ return -1;
+ }
+
child.git_cmd = 1;
child.in = -1;
if (repo != the_repository)
diff --git a/pseudo-merge.c b/pseudo-merge.c
new file mode 100644
index 0000000000..f85629b02e
--- /dev/null
+++ b/pseudo-merge.c
@@ -0,0 +1,740 @@
+#include "git-compat-util.h"
+#include "pseudo-merge.h"
+#include "date.h"
+#include "oid-array.h"
+#include "strbuf.h"
+#include "config.h"
+#include "string-list.h"
+#include "refs.h"
+#include "pack-bitmap.h"
+#include "commit.h"
+#include "alloc.h"
+#include "progress.h"
+#include "hex.h"
+
+#define DEFAULT_PSEUDO_MERGE_DECAY 1.0f
+#define DEFAULT_PSEUDO_MERGE_MAX_MERGES 64
+#define DEFAULT_PSEUDO_MERGE_SAMPLE_RATE 100
+#define DEFAULT_PSEUDO_MERGE_THRESHOLD approxidate("1.week.ago")
+#define DEFAULT_PSEUDO_MERGE_STABLE_THRESHOLD approxidate("1.month.ago")
+#define DEFAULT_PSEUDO_MERGE_STABLE_SIZE 512
+
+static float gitexp(float base, int exp)
+{
+ float result = 1;
+ while (1) {
+ if (exp % 2)
+ result *= base;
+ exp >>= 1;
+ if (!exp)
+ break;
+ base *= base;
+ }
+ return result;
+}
+
+static uint32_t pseudo_merge_group_size(const struct pseudo_merge_group *group,
+ const struct pseudo_merge_matches *matches,
+ uint32_t i)
+{
+ float C = 0.0f;
+ uint32_t n;
+
+ /*
+ * The size of pseudo-merge groups decays according to a power series,
+ * which looks like:
+ *
+ * f(n) = C * n^-k
+ *
+ * , where 'n' is the n-th pseudo-merge group, 'f(n)' is its size, 'k'
+ * is the decay rate, and 'C' is a scaling value.
+ *
+ * The value of C depends on the number of groups, decay rate, and total
+ * number of commits. It is computed such that if there are M and N
+ * total groups and commits, respectively, that:
+ *
+ * N = f(0) + f(1) + ... f(M-1)
+ *
+ * Rearranging to isolate C, we get:
+ *
+ * N = \sum_{n=1}^M C / n^k
+ *
+ * N / C = \sum_{n=1}^M n^-k
+ *
+ * C = N / \sum_{n=1}^M n^-k
+ *
+ * For example, if we have a decay rate of 'k' being equal to 1.5, 'N'
+ * total commits equal to 10,000, and 'M' being equal to 6 groups, then
+ * the (rounded) group sizes are:
+ *
+ * { 5469, 1934, 1053, 684, 489, 372 }
+ *
+ * increasing the number of total groups, say to 10, scales the group
+ * sizes appropriately:
+ *
+ * { 5012, 1772, 964, 626, 448, 341, 271, 221, 186, 158 }
+ */
+ for (n = 0; n < group->max_merges; n++)
+ C += 1.0f / gitexp(n + 1, group->decay);
+ C = matches->unstable_nr / C;
+
+ return (int)((C / gitexp(i + 1, group->decay)) + 0.5);
+}
+
+static void init_pseudo_merge_group(struct pseudo_merge_group *group)
+{
+ memset(group, 0, sizeof(struct pseudo_merge_group));
+
+ strmap_init_with_options(&group->matches, NULL, 0);
+
+ group->decay = DEFAULT_PSEUDO_MERGE_DECAY;
+ group->max_merges = DEFAULT_PSEUDO_MERGE_MAX_MERGES;
+ group->sample_rate = DEFAULT_PSEUDO_MERGE_SAMPLE_RATE;
+ group->threshold = DEFAULT_PSEUDO_MERGE_THRESHOLD;
+ group->stable_threshold = DEFAULT_PSEUDO_MERGE_STABLE_THRESHOLD;
+ group->stable_size = DEFAULT_PSEUDO_MERGE_STABLE_SIZE;
+}
+
+static int pseudo_merge_config(const char *var, const char *value,
+ const struct config_context *ctx,
+ void *cb_data)
+{
+ struct string_list *list = cb_data;
+ struct string_list_item *item;
+ struct pseudo_merge_group *group;
+ struct strbuf buf = STRBUF_INIT;
+ const char *sub, *key;
+ size_t sub_len;
+
+ if (parse_config_key(var, "bitmappseudomerge", &sub, &sub_len, &key))
+ return 0;
+
+ if (!sub_len)
+ return 0;
+
+ strbuf_add(&buf, sub, sub_len);
+
+ item = string_list_lookup(list, buf.buf);
+ if (!item) {
+ item = string_list_insert(list, buf.buf);
+
+ item->util = xmalloc(sizeof(struct pseudo_merge_group));
+ init_pseudo_merge_group(item->util);
+ }
+
+ group = item->util;
+
+ if (!strcmp(key, "pattern")) {
+ struct strbuf re = STRBUF_INIT;
+
+ free(group->pattern);
+ if (*value != '^')
+ strbuf_addch(&re, '^');
+ strbuf_addstr(&re, value);
+
+ group->pattern = xcalloc(1, sizeof(regex_t));
+ if (regcomp(group->pattern, re.buf, REG_EXTENDED))
+ die(_("failed to load pseudo-merge regex for %s: '%s'"),
+ sub, re.buf);
+
+ strbuf_release(&re);
+ } else if (!strcmp(key, "decay")) {
+ group->decay = git_config_int(var, value, ctx->kvi);
+ if (group->decay < 0) {
+ warning(_("%s must be non-negative, using default"), var);
+ group->decay = DEFAULT_PSEUDO_MERGE_DECAY;
+ }
+ } else if (!strcmp(key, "samplerate")) {
+ group->sample_rate = git_config_int(var, value, ctx->kvi);
+ if (!(0 <= group->sample_rate && group->sample_rate <= 100)) {
+ warning(_("%s must be between 0 and 100, using default"), var);
+ group->sample_rate = DEFAULT_PSEUDO_MERGE_SAMPLE_RATE;
+ }
+ } else if (!strcmp(key, "threshold")) {
+ if (git_config_expiry_date(&group->threshold, var, value)) {
+ strbuf_release(&buf);
+ return -1;
+ }
+ } else if (!strcmp(key, "maxmerges")) {
+ group->max_merges = git_config_int(var, value, ctx->kvi);
+ if (group->max_merges < 0) {
+ warning(_("%s must be non-negative, using default"), var);
+ group->max_merges = DEFAULT_PSEUDO_MERGE_MAX_MERGES;
+ }
+ } else if (!strcmp(key, "stablethreshold")) {
+ if (git_config_expiry_date(&group->stable_threshold, var, value)) {
+ strbuf_release(&buf);
+ return -1;
+ }
+ } else if (!strcmp(key, "stablesize")) {
+ group->stable_size = git_config_int(var, value, ctx->kvi);
+ if (group->stable_size <= 0) {
+ warning(_("%s must be positive, using default"), var);
+ group->stable_size = DEFAULT_PSEUDO_MERGE_STABLE_SIZE;
+ }
+ }
+
+ strbuf_release(&buf);
+
+ return 0;
+}
+
+void load_pseudo_merges_from_config(struct string_list *list)
+{
+ struct string_list_item *item;
+
+ git_config(pseudo_merge_config, list);
+
+ for_each_string_list_item(item, list) {
+ struct pseudo_merge_group *group = item->util;
+ if (!group->pattern)
+ die(_("pseudo-merge group '%s' missing required pattern"),
+ item->string);
+ if (group->threshold < group->stable_threshold)
+ die(_("pseudo-merge group '%s' has unstable threshold "
+ "before stable one"), item->string);
+ }
+}
+
+static int find_pseudo_merge_group_for_ref(const char *refname,
+ const struct object_id *oid,
+ int flags UNUSED,
+ void *_data)
+{
+ struct string_list *list = _data;
+ struct object_id peeled;
+ struct commit *c;
+ uint32_t i;
+ int has_bitmap;
+
+ if (!peel_iterated_oid(oid, &peeled))
+ oid = &peeled;
+
+ c = lookup_commit(the_repository, oid);
+ if (!c)
+ return 0;
+
+ has_bitmap = bitmap_writer_has_bitmapped_object_id(oid);
+
+ for (i = 0; i < list->nr; i++) {
+ struct pseudo_merge_group *group;
+ struct pseudo_merge_matches *matches;
+ struct strbuf group_name = STRBUF_INIT;
+ regmatch_t captures[16];
+ size_t j;
+
+ group = list->items[i].util;
+ if (regexec(group->pattern, refname, ARRAY_SIZE(captures),
+ captures, 0))
+ continue;
+
+ if (captures[ARRAY_SIZE(captures) - 1].rm_so != -1)
+ warning(_("pseudo-merge regex from config has too many capture "
+ "groups (max=%"PRIuMAX")"),
+ (uintmax_t)ARRAY_SIZE(captures) - 2);
+
+ for (j = !!group->pattern->re_nsub; j < ARRAY_SIZE(captures); j++) {
+ regmatch_t *match = &captures[j];
+ if (match->rm_so == -1)
+ continue;
+
+ if (group_name.len)
+ strbuf_addch(&group_name, '-');
+
+ strbuf_add(&group_name, refname + match->rm_so,
+ match->rm_eo - match->rm_so);
+ }
+
+ matches = strmap_get(&group->matches, group_name.buf);
+ if (!matches) {
+ matches = xcalloc(1, sizeof(*matches));
+ strmap_put(&group->matches, strbuf_detach(&group_name, NULL),
+ matches);
+ }
+
+ if (c->date <= group->stable_threshold) {
+ ALLOC_GROW(matches->stable, matches->stable_nr + 1,
+ matches->stable_alloc);
+ matches->stable[matches->stable_nr++] = c;
+ } else if (c->date <= group->threshold && !has_bitmap) {
+ ALLOC_GROW(matches->unstable, matches->unstable_nr + 1,
+ matches->unstable_alloc);
+ matches->unstable[matches->unstable_nr++] = c;
+ }
+
+ strbuf_release(&group_name);
+ }
+
+ return 0;
+}
+
+static struct commit *push_pseudo_merge(struct pseudo_merge_group *group)
+{
+ struct commit *merge;
+
+ ALLOC_GROW(group->merges, group->merges_nr + 1, group->merges_alloc);
+
+ merge = alloc_commit_node(the_repository);
+ merge->object.parsed = 1;
+ merge->object.flags |= BITMAP_PSEUDO_MERGE;
+
+ group->merges[group->merges_nr++] = merge;
+
+ return merge;
+}
+
+static struct pseudo_merge_commit_idx *pseudo_merge_idx(kh_oid_map_t *pseudo_merge_commits,
+ const struct object_id *oid)
+
+{
+ struct pseudo_merge_commit_idx *pmc;
+ khiter_t hash_pos;
+
+ hash_pos = kh_get_oid_map(pseudo_merge_commits, *oid);
+ if (hash_pos == kh_end(pseudo_merge_commits)) {
+ int hash_ret;
+ hash_pos = kh_put_oid_map(pseudo_merge_commits, *oid, &hash_ret);
+
+ CALLOC_ARRAY(pmc, 1);
+
+ kh_value(pseudo_merge_commits, hash_pos) = pmc;
+ } else {
+ pmc = kh_value(pseudo_merge_commits, hash_pos);
+ }
+
+ return pmc;
+}
+
+#define MIN_PSEUDO_MERGE_SIZE 8
+
+static void select_pseudo_merges_1(struct pseudo_merge_group *group,
+ struct pseudo_merge_matches *matches,
+ kh_oid_map_t *pseudo_merge_commits,
+ uint32_t *pseudo_merges_nr)
+{
+ uint32_t i, j;
+ uint32_t stable_merges_nr;
+
+ if (!matches->stable_nr && !matches->unstable_nr)
+ return; /* all tips in this group already have bitmaps */
+
+ stable_merges_nr = matches->stable_nr / group->stable_size;
+ if (matches->stable_nr % group->stable_size)
+ stable_merges_nr++;
+
+ /* make stable_merges_nr pseudo merges for stable commits */
+ for (i = 0, j = 0; i < stable_merges_nr; i++) {
+ struct commit *merge;
+ struct commit_list **p;
+
+ merge = push_pseudo_merge(group);
+ p = &merge->parents;
+
+ do {
+ struct commit *c;
+ struct pseudo_merge_commit_idx *pmc;
+
+ if (j >= matches->stable_nr)
+ break;
+
+ c = matches->stable[j++];
+ pmc = pseudo_merge_idx(pseudo_merge_commits,
+ &c->object.oid);
+
+ ALLOC_GROW(pmc->pseudo_merge, pmc->nr + 1, pmc->alloc);
+
+ pmc->pseudo_merge[pmc->nr++] = *pseudo_merges_nr;
+ p = commit_list_append(c, p);
+ } while (j % group->stable_size);
+
+ bitmap_writer_push_bitmapped_commit(merge, 1);
+ (*pseudo_merges_nr)++;
+ }
+
+ /* make up to group->max_merges pseudo merges for unstable commits */
+ for (i = 0, j = 0; i < group->max_merges; i++) {
+ struct commit *merge;
+ struct commit_list **p;
+ uint32_t size, end;
+
+ merge = push_pseudo_merge(group);
+ p = &merge->parents;
+
+ size = pseudo_merge_group_size(group, matches, i);
+ end = size < MIN_PSEUDO_MERGE_SIZE ? matches->unstable_nr : j + size;
+
+ for (; j < end && j < matches->unstable_nr; j++) {
+ struct commit *c = matches->unstable[j];
+ struct pseudo_merge_commit_idx *pmc;
+
+ if (j % (100 / group->sample_rate))
+ continue;
+
+ pmc = pseudo_merge_idx(pseudo_merge_commits,
+ &c->object.oid);
+
+ ALLOC_GROW(pmc->pseudo_merge, pmc->nr + 1, pmc->alloc);
+
+ pmc->pseudo_merge[pmc->nr++] = *pseudo_merges_nr;
+ p = commit_list_append(c, p);
+ }
+
+ bitmap_writer_push_bitmapped_commit(merge, 1);
+ (*pseudo_merges_nr)++;
+ if (end >= matches->unstable_nr)
+ break;
+ }
+}
+
+static int commit_date_cmp(const void *va, const void *vb)
+{
+ timestamp_t a = (*(const struct commit **)va)->date;
+ timestamp_t b = (*(const struct commit **)vb)->date;
+
+ if (a < b)
+ return -1;
+ else if (a > b)
+ return 1;
+ return 0;
+}
+
+static void sort_pseudo_merge_matches(struct pseudo_merge_matches *matches)
+{
+ QSORT(matches->stable, matches->stable_nr, commit_date_cmp);
+ QSORT(matches->unstable, matches->unstable_nr, commit_date_cmp);
+}
+
+void select_pseudo_merges(struct string_list *list,
+ struct commit **commits, size_t commits_nr,
+ kh_oid_map_t *pseudo_merge_commits,
+ uint32_t *pseudo_merges_nr,
+ unsigned show_progress)
+{
+ struct progress *progress = NULL;
+ uint32_t i;
+
+ if (!list->nr)
+ return;
+
+ if (show_progress)
+ progress = start_progress("Selecting pseudo-merge commits", list->nr);
+
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ find_pseudo_merge_group_for_ref, list);
+
+ for (i = 0; i < list->nr; i++) {
+ struct pseudo_merge_group *group;
+ struct hashmap_iter iter;
+ struct strmap_entry *e;
+
+ group = list->items[i].util;
+ strmap_for_each_entry(&group->matches, &iter, e) {
+ struct pseudo_merge_matches *matches = e->value;
+
+ sort_pseudo_merge_matches(matches);
+
+ select_pseudo_merges_1(group, matches,
+ pseudo_merge_commits,
+ pseudo_merges_nr);
+ }
+
+ display_progress(progress, i + 1);
+ }
+
+ stop_progress(&progress);
+}
+
+void free_pseudo_merge_map(struct pseudo_merge_map *pm)
+{
+ uint32_t i;
+ for (i = 0; i < pm->nr; i++) {
+ ewah_pool_free(pm->v[i].commits);
+ ewah_pool_free(pm->v[i].bitmap);
+ }
+ free(pm->v);
+}
+
+struct pseudo_merge_commit_ext {
+ uint32_t nr;
+ const unsigned char *ptr;
+};
+
+static int pseudo_merge_ext_at(const struct pseudo_merge_map *pm,
+ struct pseudo_merge_commit_ext *ext, size_t at)
+{
+ if (at >= pm->map_size)
+ return error(_("extended pseudo-merge read out-of-bounds "
+ "(%"PRIuMAX" >= %"PRIuMAX")"),
+ (uintmax_t)at, (uintmax_t)pm->map_size);
+
+ ext->nr = get_be32(pm->map + at);
+ ext->ptr = pm->map + at + sizeof(uint32_t);
+
+ return 0;
+}
+
+struct ewah_bitmap *pseudo_merge_bitmap(const struct pseudo_merge_map *pm,
+ struct pseudo_merge *merge)
+{
+ if (!merge->loaded_commits)
+ BUG("cannot use unloaded pseudo-merge bitmap");
+
+ if (!merge->loaded_bitmap) {
+ size_t at = merge->bitmap_at;
+
+ merge->bitmap = read_bitmap(pm->map, pm->map_size, &at);
+ merge->loaded_bitmap = 1;
+ }
+
+ return merge->bitmap;
+}
+
+struct pseudo_merge *use_pseudo_merge(const struct pseudo_merge_map *pm,
+ struct pseudo_merge *merge)
+{
+ if (!merge->loaded_commits) {
+ size_t pos = merge->at;
+
+ merge->commits = read_bitmap(pm->map, pm->map_size, &pos);
+ merge->bitmap_at = pos;
+ merge->loaded_commits = 1;
+ }
+ return merge;
+}
+
+static struct pseudo_merge *pseudo_merge_at(const struct pseudo_merge_map *pm,
+ struct object_id *oid,
+ size_t want)
+{
+ size_t lo = 0;
+ size_t hi = pm->nr;
+
+ while (lo < hi) {
+ size_t mi = lo + (hi - lo) / 2;
+ size_t got = pm->v[mi].at;
+
+ if (got == want)
+ return use_pseudo_merge(pm, &pm->v[mi]);
+ else if (got < want)
+ hi = mi;
+ else
+ lo = mi + 1;
+ }
+
+ warning(_("could not find pseudo-merge for commit %s at offset %"PRIuMAX),
+ oid_to_hex(oid), (uintmax_t)want);
+
+ return NULL;
+}
+
+struct pseudo_merge_commit {
+ uint32_t commit_pos;
+ uint64_t pseudo_merge_ofs;
+};
+
+#define PSEUDO_MERGE_COMMIT_RAWSZ (sizeof(uint32_t)+sizeof(uint64_t))
+
+static void read_pseudo_merge_commit_at(struct pseudo_merge_commit *merge,
+ const unsigned char *at)
+{
+ merge->commit_pos = get_be32(at);
+ merge->pseudo_merge_ofs = get_be64(at + sizeof(uint32_t));
+}
+
+static int nth_pseudo_merge_ext(const struct pseudo_merge_map *pm,
+ struct pseudo_merge_commit_ext *ext,
+ struct pseudo_merge_commit *merge,
+ uint32_t n)
+{
+ size_t ofs;
+
+ if (n >= ext->nr)
+ return error(_("extended pseudo-merge lookup out-of-bounds "
+ "(%"PRIu32" >= %"PRIu32")"), n, ext->nr);
+
+ ofs = get_be64(ext->ptr + st_mult(n, sizeof(uint64_t)));
+ if (ofs >= pm->map_size)
+ return error(_("out-of-bounds read: (%"PRIuMAX" >= %"PRIuMAX")"),
+ (uintmax_t)ofs, (uintmax_t)pm->map_size);
+
+ read_pseudo_merge_commit_at(merge, pm->map + ofs);
+
+ return 0;
+}
+
+static unsigned apply_pseudo_merge(const struct pseudo_merge_map *pm,
+ struct pseudo_merge *merge,
+ struct bitmap *result,
+ struct bitmap *roots)
+{
+ if (merge->satisfied)
+ return 0;
+
+ if (!ewah_bitmap_is_subset(merge->commits, roots ? roots : result))
+ return 0;
+
+ bitmap_or_ewah(result, pseudo_merge_bitmap(pm, merge));
+ if (roots)
+ bitmap_or_ewah(roots, pseudo_merge_bitmap(pm, merge));
+ merge->satisfied = 1;
+
+ return 1;
+}
+
+static int pseudo_merge_commit_cmp(const void *va, const void *vb)
+{
+ struct pseudo_merge_commit merge;
+ uint32_t key = *(uint32_t*)va;
+
+ read_pseudo_merge_commit_at(&merge, vb);
+
+ if (key < merge.commit_pos)
+ return -1;
+ if (key > merge.commit_pos)
+ return 1;
+ return 0;
+}
+
+static struct pseudo_merge_commit *find_pseudo_merge(const struct pseudo_merge_map *pm,
+ uint32_t pos)
+{
+ if (!pm->commits_nr)
+ return NULL;
+
+ return bsearch(&pos, pm->commits, pm->commits_nr,
+ PSEUDO_MERGE_COMMIT_RAWSZ, pseudo_merge_commit_cmp);
+}
+
+int apply_pseudo_merges_for_commit(const struct pseudo_merge_map *pm,
+ struct bitmap *result,
+ struct commit *commit, uint32_t commit_pos)
+{
+ struct pseudo_merge *merge;
+ struct pseudo_merge_commit *merge_commit;
+ int ret = 0;
+
+ merge_commit = find_pseudo_merge(pm, commit_pos);
+ if (!merge_commit)
+ return 0;
+
+ if (merge_commit->pseudo_merge_ofs & ((uint64_t)1<<63)) {
+ struct pseudo_merge_commit_ext ext = { 0 };
+ off_t ofs = merge_commit->pseudo_merge_ofs & ~((uint64_t)1<<63);
+ uint32_t i;
+
+ if (pseudo_merge_ext_at(pm, &ext, ofs) < -1) {
+ warning(_("could not read extended pseudo-merge table "
+ "for commit %s"),
+ oid_to_hex(&commit->object.oid));
+ return ret;
+ }
+
+ for (i = 0; i < ext.nr; i++) {
+ if (nth_pseudo_merge_ext(pm, &ext, merge_commit, i) < 0)
+ return ret;
+
+ merge = pseudo_merge_at(pm, &commit->object.oid,
+ merge_commit->pseudo_merge_ofs);
+
+ if (!merge)
+ return ret;
+
+ if (apply_pseudo_merge(pm, merge, result, NULL))
+ ret++;
+ }
+ } else {
+ merge = pseudo_merge_at(pm, &commit->object.oid,
+ merge_commit->pseudo_merge_ofs);
+
+ if (!merge)
+ return ret;
+
+ if (apply_pseudo_merge(pm, merge, result, NULL))
+ ret++;
+ }
+
+ if (ret)
+ cascade_pseudo_merges(pm, result, NULL);
+
+ return ret;
+}
+
+int cascade_pseudo_merges(const struct pseudo_merge_map *pm,
+ struct bitmap *result,
+ struct bitmap *roots)
+{
+ unsigned any_satisfied;
+ int ret = 0;
+
+ do {
+ struct pseudo_merge *merge;
+ uint32_t i;
+
+ any_satisfied = 0;
+
+ for (i = 0; i < pm->nr; i++) {
+ merge = use_pseudo_merge(pm, &pm->v[i]);
+ if (apply_pseudo_merge(pm, merge, result, roots)) {
+ any_satisfied |= 1;
+ ret++;
+ }
+ }
+ } while (any_satisfied);
+
+ return ret;
+}
+
+struct pseudo_merge *pseudo_merge_for_parents(const struct pseudo_merge_map *pm,
+ struct bitmap *parents)
+{
+ struct pseudo_merge *match = NULL;
+ size_t i;
+
+ if (!pm->nr)
+ return NULL;
+
+ /*
+ * NOTE: this loop is quadratic in the worst-case (where no
+ * matching pseudo-merge bitmaps are found), but in practice
+ * this is OK for a few reasons:
+ *
+ * - Rejecting pseudo-merge bitmaps that do not match the
+ * given commit is done quickly (i.e. `bitmap_equals_ewah()`
+ * returns early when we know the two bitmaps aren't equal.
+ *
+ * - Already matched pseudo-merge bitmaps (which we track with
+ * the `->satisfied` bit here) are skipped as potential
+ * candidates.
+ *
+ * - The number of pseudo-merges should be small (in the
+ * hundreds for most repositories).
+ *
+ * If in the future this semi-quadratic behavior does become a
+ * problem, another approach would be to keep track of which
+ * pseudo-merges are still "viable" after enumerating the
+ * pseudo-merge commit's parents:
+ *
+ * - A pseudo-merge bitmap becomes non-viable when the bit(s)
+ * corresponding to one or more parent(s) of the given
+ * commit are not set in a candidate pseudo-merge's commits
+ * bitmap.
+ *
+ * - After processing all bits, enumerate the remaining set of
+ * viable pseudo-merge bitmaps, and check that their
+ * popcount() matches the number of parents in the given
+ * commit.
+ */
+ for (i = 0; i < pm->nr; i++) {
+ struct pseudo_merge *candidate = use_pseudo_merge(pm, &pm->v[i]);
+ if (!candidate || candidate->satisfied)
+ continue;
+ if (!bitmap_equals_ewah(parents, candidate->commits))
+ continue;
+
+ match = candidate;
+ match->satisfied = 1;
+ break;
+ }
+
+ return match;
+}
diff --git a/pseudo-merge.h b/pseudo-merge.h
new file mode 100644
index 0000000000..f700b02f3b
--- /dev/null
+++ b/pseudo-merge.h
@@ -0,0 +1,218 @@
+#ifndef PSEUDO_MERGE_H
+#define PSEUDO_MERGE_H
+
+#include "git-compat-util.h"
+#include "strmap.h"
+#include "khashl.h"
+#include "ewah/ewok.h"
+
+struct commit;
+struct string_list;
+struct bitmap_index;
+
+/*
+ * A pseudo-merge group tracks the set of non-bitmapped reference tips
+ * that match the given pattern.
+ *
+ * Within those matches, they are further segmented by separating
+ * consecutive capture groups with '-' dash character capture groups
+ * with '-' dash characters.
+ *
+ * Those groups are then ordered by committer date and partitioned
+ * into individual pseudo-merge(s) according to the decay, max_merges,
+ * sample_rate, and threshold parameters.
+ */
+struct pseudo_merge_group {
+ regex_t *pattern;
+
+ /* capture group(s) -> struct pseudo_merge_matches */
+ struct strmap matches;
+
+ /*
+ * The individual pseudo-merge(s) that are generated from the
+ * above array of matches, partitioned according to the below
+ * parameters.
+ */
+ struct commit **merges;
+ size_t merges_nr;
+ size_t merges_alloc;
+
+ /*
+ * Pseudo-merge grouping parameters. See git-config(1) for
+ * more information.
+ */
+ float decay;
+ int max_merges;
+ int sample_rate;
+ int stable_size;
+ timestamp_t threshold;
+ timestamp_t stable_threshold;
+};
+
+struct pseudo_merge_matches {
+ struct commit **stable;
+ struct commit **unstable;
+ size_t stable_nr, stable_alloc;
+ size_t unstable_nr, unstable_alloc;
+};
+
+/*
+ * Read the repository's configuration:
+ *
+ * - bitmapPseudoMerge.<name>.pattern
+ * - bitmapPseudoMerge.<name>.decay
+ * - bitmapPseudoMerge.<name>.sampleRate
+ * - bitmapPseudoMerge.<name>.threshold
+ * - bitmapPseudoMerge.<name>.maxMerges
+ * - bitmapPseudoMerge.<name>.stableThreshold
+ * - bitmapPseudoMerge.<name>.stableSize
+ *
+ * and populates the given `list` with pseudo-merge groups. String
+ * entry keys are the pseudo-merge group names, and the values are
+ * pointers to the pseudo_merge_group structure itself.
+ */
+void load_pseudo_merges_from_config(struct string_list *list);
+
+/*
+ * A pseudo-merge commit index (pseudo_merge_commit_idx) maps a
+ * particular (non-pseudo-merge) commit to the list of pseudo-merge(s)
+ * it appears in.
+ */
+struct pseudo_merge_commit_idx {
+ uint32_t *pseudo_merge;
+ size_t nr, alloc;
+};
+
+/*
+ * Selects pseudo-merges from a list of commits, populating the given
+ * string_list of pseudo-merge groups.
+ *
+ * Populates the pseudo_merge_commits map with a commit_idx
+ * corresponding to each commit in the list. Counts the total number
+ * of pseudo-merges generated.
+ *
+ * Optionally shows a progress meter.
+ */
+void select_pseudo_merges(struct string_list *list,
+ struct commit **commits, size_t commits_nr,
+ kh_oid_map_t *pseudo_merge_commits,
+ uint32_t *pseudo_merges_nr,
+ unsigned show_progress);
+
+/*
+ * Represents a serialized view of a file containing pseudo-merge(s)
+ * (see Documentation/technical/bitmap-format.txt for a specification
+ * of the format).
+ */
+struct pseudo_merge_map {
+ /*
+ * An array of pseudo-merge(s), lazily loaded from the .bitmap
+ * file.
+ */
+ struct pseudo_merge *v;
+ size_t nr;
+ size_t commits_nr;
+
+ /*
+ * Pointers into a memory-mapped view of the .bitmap file:
+ *
+ * - map: the beginning of the .bitmap file
+ * - commits: the beginning of the pseudo-merge commit index
+ * - map_size: the size of the .bitmap file
+ */
+ const unsigned char *map;
+ const unsigned char *commits;
+
+ size_t map_size;
+};
+
+/*
+ * An individual pseudo-merge, storing a pair of lazily-loaded
+ * bitmaps:
+ *
+ * - commits: the set of commit(s) that are part of the pseudo-merge
+ * - bitmap: the set of object(s) reachable from the above set of
+ * commits.
+ *
+ * The `at` and `bitmap_at` fields are used to store the locations of
+ * each of the above bitmaps in the .bitmap file.
+ */
+struct pseudo_merge {
+ struct ewah_bitmap *commits;
+ struct ewah_bitmap *bitmap;
+
+ off_t at;
+ off_t bitmap_at;
+
+ /*
+ * `satisfied` indicates whether the given pseudo-merge has been
+ * used.
+ *
+ * `loaded_commits` and `loaded_bitmap` indicate whether the
+ * respective bitmaps have been loaded and read from the
+ * .bitmap file.
+ */
+ unsigned satisfied : 1,
+ loaded_commits : 1,
+ loaded_bitmap : 1;
+};
+
+/*
+ * Frees the given pseudo-merge map, releasing any memory held by (a)
+ * parsed EWAH bitmaps, or (b) the array of pseudo-merges itself. Does
+ * not free the memory-mapped view of the .bitmap file.
+ */
+void free_pseudo_merge_map(struct pseudo_merge_map *pm);
+
+/*
+ * Loads the bitmap corresponding to the given pseudo-merge from the
+ * map, if it has not already been loaded.
+ */
+struct ewah_bitmap *pseudo_merge_bitmap(const struct pseudo_merge_map *pm,
+ struct pseudo_merge *merge);
+
+/*
+ * Loads the pseudo-merge and its commits bitmap from the given
+ * pseudo-merge map, if it has not already been loaded.
+ */
+struct pseudo_merge *use_pseudo_merge(const struct pseudo_merge_map *pm,
+ struct pseudo_merge *merge);
+
+/*
+ * Applies pseudo-merge(s) containing the given commit to the bitmap
+ * "result".
+ *
+ * If any pseudo-merge(s) were satisfied, returns the number
+ * satisfied, otherwise returns 0. If any were satisfied, the
+ * remaining unsatisfied pseudo-merges are cascaded (see below).
+ */
+int apply_pseudo_merges_for_commit(const struct pseudo_merge_map *pm,
+ struct bitmap *result,
+ struct commit *commit, uint32_t commit_pos);
+
+/*
+ * Applies pseudo-merge(s) which are satisfied according to the
+ * current bitmap in result (or roots, see below). If any
+ * pseudo-merges were satisfied, repeat the process over unsatisfied
+ * pseudo-merge commits until no more pseudo-merges are satisfied.
+ *
+ * Result is the bitmap to which the pseudo-merge(s) are applied.
+ * Roots (if given) is a bitmap of the traversal tip(s) for either
+ * side of a reachability traversal.
+ *
+ * Roots may given instead of a populated results bitmap at the
+ * beginning of a traversal on either side where the reachability
+ * closure over tips is not yet known.
+ */
+int cascade_pseudo_merges(const struct pseudo_merge_map *pm,
+ struct bitmap *result,
+ struct bitmap *roots);
+
+/*
+ * Returns a pseudo-merge which contains the exact set of commits
+ * listed in the "parents" bitamp, or NULL if none could be found.
+ */
+struct pseudo_merge *pseudo_merge_for_parents(const struct pseudo_merge_map *pm,
+ struct bitmap *parents);
+
+#endif
diff --git a/range-diff.h b/range-diff.h
index 04ffe217be..2f69f6a434 100644
--- a/range-diff.h
+++ b/range-diff.h
@@ -6,6 +6,12 @@
#define RANGE_DIFF_CREATION_FACTOR_DEFAULT 60
+/*
+ * A much higher value than the default, when we KNOW we are comparing
+ * the same series (e.g., used when format-patch calls range-diff).
+ */
+#define CREATION_FACTOR_FOR_THE_SAME_SERIES 999
+
struct range_diff_options {
int creation_factor;
unsigned dual_color:1;
diff --git a/reachable.c b/reachable.c
index 3b85add243..1224b30008 100644
--- a/reachable.c
+++ b/reachable.c
@@ -363,10 +363,11 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
add_index_objects_to_pending(revs, 0);
/* Add all external refs */
- for_each_ref(add_one_ref, revs);
+ refs_for_each_ref(get_main_ref_store(the_repository), add_one_ref,
+ revs);
/* detached HEAD is not included in the list above */
- head_ref(add_one_ref, revs);
+ refs_head_ref(get_main_ref_store(the_repository), add_one_ref, revs);
other_head_refs(add_one_ref, revs);
/* rebase autostash and orig-head */
diff --git a/read-cache.c b/read-cache.c
index e1723ad796..a6db25a16d 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1116,19 +1116,32 @@ static int has_dir_name(struct index_state *istate,
istate->cache[istate->cache_nr - 1]->name,
&len_eq_last);
if (cmp_last > 0) {
- if (len_eq_last == 0) {
+ if (name[len_eq_last] != '/') {
/*
* The entry sorts AFTER the last one in the
- * index and their paths have no common prefix,
- * so there cannot be a F/D conflict.
+ * index.
+ *
+ * If there were a conflict with "file", then our
+ * name would start with "file/" and the last index
+ * entry would start with "file" but not "file/".
+ *
+ * The next character after common prefix is
+ * not '/', so there can be no conflict.
*/
return retval;
} else {
/*
* The entry sorts AFTER the last one in the
- * index, but has a common prefix. Fall through
- * to the loop below to disect the entry's path
- * and see where the difference is.
+ * index, and the next character after common
+ * prefix is '/'.
+ *
+ * Either the last index entry is a file in
+ * conflict with this entry, or it has a name
+ * which sorts between this entry and the
+ * potential conflicting file.
+ *
+ * In both cases, we fall through to the loop
+ * below and let the regular search code handle it.
*/
}
} else if (cmp_last == 0) {
@@ -1152,53 +1165,6 @@ static int has_dir_name(struct index_state *istate,
}
len = slash - name;
- if (cmp_last > 0) {
- /*
- * (len + 1) is a directory boundary (including
- * the trailing slash). And since the loop is
- * decrementing "slash", the first iteration is
- * the longest directory prefix; subsequent
- * iterations consider parent directories.
- */
-
- if (len + 1 <= len_eq_last) {
- /*
- * The directory prefix (including the trailing
- * slash) also appears as a prefix in the last
- * entry, so the remainder cannot collide (because
- * strcmp said the whole path was greater).
- *
- * EQ: last: xxx/A
- * this: xxx/B
- *
- * LT: last: xxx/file_A
- * this: xxx/file_B
- */
- return retval;
- }
-
- if (len > len_eq_last) {
- /*
- * This part of the directory prefix (excluding
- * the trailing slash) is longer than the known
- * equal portions, so this sub-directory cannot
- * collide with a file.
- *
- * GT: last: xxxA
- * this: xxxB/file
- */
- return retval;
- }
-
- /*
- * This is a possible collision. Fall through and
- * let the regular search code handle it.
- *
- * last: xxx
- * this: xxx/file
- */
- }
-
pos = index_name_stage_pos(istate, name, len, stage, EXPAND_SPARSE);
if (pos >= 0) {
/*
diff --git a/rebase-interactive.c b/rebase-interactive.c
index c343e16fcd..56fd7206a9 100644
--- a/rebase-interactive.c
+++ b/rebase-interactive.c
@@ -101,9 +101,10 @@ void append_todo_help(int command_count,
strbuf_add_commented_lines(buf, msg, strlen(msg), comment_line_str);
}
-int edit_todo_list(struct repository *r, struct todo_list *todo_list,
- struct todo_list *new_todo, const char *shortrevisions,
- const char *shortonto, unsigned flags)
+int edit_todo_list(struct repository *r, struct replay_opts *opts,
+ struct todo_list *todo_list, struct todo_list *new_todo,
+ const char *shortrevisions, const char *shortonto,
+ unsigned flags)
{
const char *todo_file = rebase_path_todo(),
*todo_backup = rebase_path_todo_backup();
@@ -114,7 +115,9 @@ int edit_todo_list(struct repository *r, struct todo_list *todo_list,
* it. If there is an error, we do not return, because the user
* might want to fix it in the first place. */
if (!initial)
- incorrect = todo_list_parse_insn_buffer(r, todo_list->buf.buf, todo_list) |
+ incorrect = todo_list_parse_insn_buffer(r, opts,
+ todo_list->buf.buf,
+ todo_list) |
file_exists(rebase_path_dropped());
if (todo_list_write_to_file(r, todo_list, todo_file, shortrevisions, shortonto,
@@ -134,13 +137,13 @@ int edit_todo_list(struct repository *r, struct todo_list *todo_list,
if (initial && new_todo->buf.len == 0)
return -3;
- if (todo_list_parse_insn_buffer(r, new_todo->buf.buf, new_todo)) {
+ if (todo_list_parse_insn_buffer(r, opts, new_todo->buf.buf, new_todo)) {
fprintf(stderr, _(edit_todo_list_advice));
return -4;
}
if (incorrect) {
- if (todo_list_check_against_backup(r, new_todo)) {
+ if (todo_list_check_against_backup(r, opts, new_todo)) {
write_file(rebase_path_dropped(), "%s", "");
return -4;
}
@@ -228,13 +231,15 @@ leave_check:
return res;
}
-int todo_list_check_against_backup(struct repository *r, struct todo_list *todo_list)
+int todo_list_check_against_backup(struct repository *r,
+ struct replay_opts *opts,
+ struct todo_list *todo_list)
{
struct todo_list backup = TODO_LIST_INIT;
int res = 0;
if (strbuf_read_file(&backup.buf, rebase_path_todo_backup(), 0) > 0) {
- todo_list_parse_insn_buffer(r, backup.buf.buf, &backup);
+ todo_list_parse_insn_buffer(r, opts, backup.buf.buf, &backup);
res = todo_list_check(&backup, todo_list);
}
diff --git a/rebase-interactive.h b/rebase-interactive.h
index 7239c60f79..8e5b181b33 100644
--- a/rebase-interactive.h
+++ b/rebase-interactive.h
@@ -3,17 +3,20 @@
struct strbuf;
struct repository;
+struct replay_opts;
struct todo_list;
void append_todo_help(int command_count,
const char *shortrevisions, const char *shortonto,
struct strbuf *buf);
-int edit_todo_list(struct repository *r, struct todo_list *todo_list,
- struct todo_list *new_todo, const char *shortrevisions,
- const char *shortonto, unsigned flags);
+int edit_todo_list(struct repository *r, struct replay_opts *opts,
+ struct todo_list *todo_list, struct todo_list *new_todo,
+ const char *shortrevisions, const char *shortonto,
+ unsigned flags);
int todo_list_check(struct todo_list *old_todo, struct todo_list *new_todo);
int todo_list_check_against_backup(struct repository *r,
+ struct replay_opts *opts,
struct todo_list *todo_list);
#endif
diff --git a/ref-filter.c b/ref-filter.c
index 59ad6f54dd..b4a77a7137 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -895,7 +895,9 @@ static int head_atom_parser(struct ref_format *format UNUSED,
{
if (arg)
return err_no_arg(err, "HEAD");
- atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL);
+ atom->u.head = refs_resolve_refdup(get_main_ref_store(the_repository),
+ "HEAD", RESOLVE_REF_READING, NULL,
+ NULL);
return 0;
}
@@ -2135,7 +2137,9 @@ static const char *rstrip_ref_components(const char *refname, int len)
static const char *show_ref(struct refname_atom *atom, const char *refname)
{
if (atom->option == R_SHORT)
- return shorten_unambiguous_ref(refname, warn_ambiguous_refs);
+ return refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+ refname,
+ warn_ambiguous_refs);
else if (atom->option == R_LSTRIP)
return lstrip_ref_components(refname, atom->lstrip);
else if (atom->option == R_RSTRIP)
@@ -2338,8 +2342,10 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
CALLOC_ARRAY(ref->value, used_atom_cnt);
if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
- ref->symref = resolve_refdup(ref->refname, RESOLVE_REF_READING,
- NULL, NULL);
+ ref->symref = refs_resolve_refdup(get_main_ref_store(the_repository),
+ ref->refname,
+ RESOLVE_REF_READING,
+ NULL, NULL);
if (!ref->symref)
ref->symref = xstrdup("");
}
@@ -2628,7 +2634,7 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
each_ref_fn cb,
void *cb_data)
{
- if (filter->kind == FILTER_REFS_KIND_MASK) {
+ if (filter->kind & FILTER_REFS_ROOT_REFS) {
/* In this case, we want to print all refs including root refs. */
return refs_for_each_include_root_refs(get_main_ref_store(the_repository),
cb, cb_data);
@@ -2640,7 +2646,8 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
* prefixes like "refs/heads/" etc. are stripped off,
* so we have to look at everything:
*/
- return for_each_fullref_in("", cb, cb_data);
+ return refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ "", NULL, cb, cb_data);
}
if (filter->ignore_case) {
@@ -2649,7 +2656,8 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
* so just return everything and let the caller
* sort it out.
*/
- return for_each_fullref_in("", cb, cb_data);
+ return refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ "", NULL, cb, cb_data);
}
if (!filter->name_patterns[0]) {
@@ -2756,8 +2764,10 @@ static int ref_kind_from_refname(const char *refname)
return ref_kind[i].kind;
}
- if (is_pseudoref(get_main_ref_store(the_repository), refname))
+ if (is_pseudo_ref(refname))
return FILTER_REFS_PSEUDOREFS;
+ if (is_root_ref(get_main_ref_store(the_repository), refname))
+ return FILTER_REFS_ROOT_REFS;
return FILTER_REFS_OTHERS;
}
@@ -2794,11 +2804,11 @@ static struct ref_array_item *apply_ref_filter(const char *refname, const struct
/*
* Generally HEAD refs are printed with special description denoting a rebase,
* detached state and so forth. This is useful when only printing the HEAD ref
- * But when it is being printed along with other pseudorefs, it makes sense to
- * keep the formatting consistent. So we mask the type to act like a pseudoref.
+ * But when it is being printed along with other root refs, it makes sense to
+ * keep the formatting consistent. So we mask the type to act like a root ref.
*/
- if (filter->kind == FILTER_REFS_KIND_MASK && kind == FILTER_REFS_DETACHED_HEAD)
- kind = FILTER_REFS_PSEUDOREFS;
+ if (filter->kind & FILTER_REFS_ROOT_REFS && kind == FILTER_REFS_DETACHED_HEAD)
+ kind = FILTER_REFS_ROOT_REFS;
else if (!(kind & filter->kind))
return NULL;
@@ -3060,11 +3070,17 @@ static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref
* of filter_ref_kind().
*/
if (filter->kind == FILTER_REFS_BRANCHES)
- ret = for_each_fullref_in("refs/heads/", fn, cb_data);
+ ret = refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ "refs/heads/", NULL,
+ fn, cb_data);
else if (filter->kind == FILTER_REFS_REMOTES)
- ret = for_each_fullref_in("refs/remotes/", fn, cb_data);
+ ret = refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ "refs/remotes/", NULL,
+ fn, cb_data);
else if (filter->kind == FILTER_REFS_TAGS)
- ret = for_each_fullref_in("refs/tags/", fn, cb_data);
+ ret = refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ "refs/tags/", NULL, fn,
+ cb_data);
else if (filter->kind & FILTER_REFS_REGULAR)
ret = for_each_fullref_in_pattern(filter, fn, cb_data);
@@ -3072,9 +3088,10 @@ static int do_filter_refs(struct ref_filter *filter, unsigned int type, each_ref
* When printing all ref types, HEAD is already included,
* so we don't want to print HEAD again.
*/
- if (!ret && (filter->kind != FILTER_REFS_KIND_MASK) &&
+ if (!ret && !(filter->kind & FILTER_REFS_ROOT_REFS) &&
(filter->kind & FILTER_REFS_DETACHED_HEAD))
- head_ref(fn, cb_data);
+ refs_head_ref(get_main_ref_store(the_repository), fn,
+ cb_data);
}
clear_contains_cache(&filter->internal.contains_cache);
diff --git a/ref-filter.h b/ref-filter.h
index 0ca28d2bba..27ae1aa0d1 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -23,9 +23,9 @@
FILTER_REFS_REMOTES | FILTER_REFS_OTHERS)
#define FILTER_REFS_DETACHED_HEAD 0x0020
#define FILTER_REFS_PSEUDOREFS 0x0040
-#define FILTER_REFS_ROOT_REFS (FILTER_REFS_DETACHED_HEAD | FILTER_REFS_PSEUDOREFS)
+#define FILTER_REFS_ROOT_REFS 0x0080
#define FILTER_REFS_KIND_MASK (FILTER_REFS_REGULAR | FILTER_REFS_DETACHED_HEAD | \
- FILTER_REFS_PSEUDOREFS)
+ FILTER_REFS_PSEUDOREFS | FILTER_REFS_ROOT_REFS)
struct atom_value;
struct ref_sorting;
diff --git a/reflog-walk.c b/reflog-walk.c
index 66484f4f32..f11b97e889 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -67,24 +67,32 @@ static struct complete_reflogs *read_complete_reflog(const char *ref)
struct complete_reflogs *reflogs =
xcalloc(1, sizeof(struct complete_reflogs));
reflogs->ref = xstrdup(ref);
- for_each_reflog_ent(ref, read_one_reflog, reflogs);
+ refs_for_each_reflog_ent(get_main_ref_store(the_repository), ref,
+ read_one_reflog, reflogs);
if (reflogs->nr == 0) {
const char *name;
void *name_to_free;
- name = name_to_free = resolve_refdup(ref, RESOLVE_REF_READING,
- NULL, NULL);
+ name = name_to_free = refs_resolve_refdup(get_main_ref_store(the_repository),
+ ref,
+ RESOLVE_REF_READING,
+ NULL, NULL);
if (name) {
- for_each_reflog_ent(name, read_one_reflog, reflogs);
+ refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+ name, read_one_reflog,
+ reflogs);
free(name_to_free);
}
}
if (reflogs->nr == 0) {
char *refname = xstrfmt("refs/%s", ref);
- for_each_reflog_ent(refname, read_one_reflog, reflogs);
+ refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+ refname, read_one_reflog, reflogs);
if (reflogs->nr == 0) {
free(refname);
refname = xstrfmt("refs/heads/%s", ref);
- for_each_reflog_ent(refname, read_one_reflog, reflogs);
+ refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+ refname, read_one_reflog,
+ reflogs);
}
free(refname);
}
@@ -174,7 +182,8 @@ int add_reflog_for_walk(struct reflog_walk_info *info,
else {
if (*branch == '\0') {
free(branch);
- branch = resolve_refdup("HEAD", 0, NULL, NULL);
+ branch = refs_resolve_refdup(get_main_ref_store(the_repository),
+ "HEAD", 0, NULL, NULL);
if (!branch)
die("no current branch");
@@ -236,7 +245,9 @@ void get_reflog_selector(struct strbuf *sb,
if (shorten) {
if (!commit_reflog->reflogs->short_ref)
commit_reflog->reflogs->short_ref
- = shorten_unambiguous_ref(commit_reflog->reflogs->ref, 0);
+ = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+ commit_reflog->reflogs->ref,
+ 0);
printed_ref = commit_reflog->reflogs->short_ref;
} else {
printed_ref = commit_reflog->reflogs->ref;
diff --git a/reflog.c b/reflog.c
index 647f3ca398..8861c2d606 100644
--- a/reflog.c
+++ b/reflog.c
@@ -343,7 +343,8 @@ void reflog_expiry_prepare(const char *refname,
case UE_ALWAYS:
return;
case UE_HEAD:
- for_each_ref(push_tip_to_list, &cb->tips);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ push_tip_to_list, &cb->tips);
for (elem = cb->tips; elem; elem = elem->next)
commit_list_insert(elem->item, &cb->mark_list);
break;
@@ -416,19 +417,22 @@ int reflog_delete(const char *rev, enum expire_reflog_flags flags, int verbose)
recno = strtoul(spec + 2, &ep, 10);
if (*ep == '}') {
cmd.recno = -recno;
- for_each_reflog_ent(ref, count_reflog_ent, &cmd);
+ refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+ ref, count_reflog_ent, &cmd);
} else {
cmd.expire_total = approxidate(spec + 2);
- for_each_reflog_ent(ref, count_reflog_ent, &cmd);
+ refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+ ref, count_reflog_ent, &cmd);
cmd.expire_total = 0;
}
cb.cmd = cmd;
- status |= reflog_expire(ref, flags,
- reflog_expiry_prepare,
- should_prune_fn,
- reflog_expiry_cleanup,
- &cb);
+ status |= refs_reflog_expire(get_main_ref_store(the_repository), ref,
+ flags,
+ reflog_expiry_prepare,
+ should_prune_fn,
+ reflog_expiry_cleanup,
+ &cb);
cleanup:
free(ref);
diff --git a/refs.c b/refs.c
index 55d2e0b2cb..484e69707c 100644
--- a/refs.c
+++ b/refs.c
@@ -384,14 +384,6 @@ char *refs_resolve_refdup(struct ref_store *refs,
return xstrdup_or_null(result);
}
-char *resolve_refdup(const char *refname, int resolve_flags,
- struct object_id *oid, int *flags)
-{
- return refs_resolve_refdup(get_main_ref_store(the_repository),
- refname, resolve_flags,
- oid, flags);
-}
-
/* The argument to for_each_filter_refs */
struct for_each_ref_filter {
const char *pattern;
@@ -400,19 +392,18 @@ struct for_each_ref_filter {
void *cb_data;
};
-int read_ref_full(const char *refname, int resolve_flags, struct object_id *oid, int *flags)
+int refs_read_ref_full(struct ref_store *refs, const char *refname,
+ int resolve_flags, struct object_id *oid, int *flags)
{
- struct ref_store *refs = get_main_ref_store(the_repository);
-
if (refs_resolve_ref_unsafe(refs, refname, resolve_flags,
oid, flags))
return 0;
return -1;
}
-int read_ref(const char *refname, struct object_id *oid)
+int refs_read_ref(struct ref_store *refs, const char *refname, struct object_id *oid)
{
- return read_ref_full(refname, RESOLVE_REF_READING, oid, NULL);
+ return refs_read_ref_full(refs, refname, RESOLVE_REF_READING, oid, NULL);
}
int refs_ref_exists(struct ref_store *refs, const char *refname)
@@ -421,11 +412,6 @@ int refs_ref_exists(struct ref_store *refs, const char *refname)
NULL, NULL);
}
-int ref_exists(const char *refname)
-{
- return refs_ref_exists(get_main_ref_store(the_repository), refname);
-}
-
static int for_each_filter_refs(const char *refname,
const struct object_id *oid,
int flags, void *data)
@@ -477,7 +463,8 @@ static int warn_if_dangling_symref(const char *refname,
if (!(flags & REF_ISSYMREF))
return 0;
- resolves_to = resolve_ref_unsafe(refname, 0, NULL, NULL);
+ resolves_to = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ refname, 0, NULL, NULL);
if (!resolves_to
|| (d->refname
? strcmp(resolves_to, d->refname)
@@ -498,7 +485,8 @@ void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
data.refname = refname;
data.refnames = NULL;
data.msg_fmt = msg_fmt;
- for_each_rawref(warn_if_dangling_symref, &data);
+ refs_for_each_rawref(get_main_ref_store(the_repository),
+ warn_if_dangling_symref, &data);
}
void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_list *refnames)
@@ -509,7 +497,8 @@ void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct string_li
data.refname = NULL;
data.refnames = refnames;
data.msg_fmt = msg_fmt;
- for_each_rawref(warn_if_dangling_symref, &data);
+ refs_for_each_rawref(get_main_ref_store(the_repository),
+ warn_if_dangling_symref, &data);
}
int refs_for_each_tag_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
@@ -517,32 +506,17 @@ int refs_for_each_tag_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
return refs_for_each_ref_in(refs, "refs/tags/", fn, cb_data);
}
-int for_each_tag_ref(each_ref_fn fn, void *cb_data)
-{
- return refs_for_each_tag_ref(get_main_ref_store(the_repository), fn, cb_data);
-}
-
int refs_for_each_branch_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
{
return refs_for_each_ref_in(refs, "refs/heads/", fn, cb_data);
}
-int for_each_branch_ref(each_ref_fn fn, void *cb_data)
-{
- return refs_for_each_branch_ref(get_main_ref_store(the_repository), fn, cb_data);
-}
-
int refs_for_each_remote_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
{
return refs_for_each_ref_in(refs, "refs/remotes/", fn, cb_data);
}
-int for_each_remote_ref(each_ref_fn fn, void *cb_data)
-{
- return refs_for_each_remote_ref(get_main_ref_store(the_repository), fn, cb_data);
-}
-
-int head_ref_namespaced(each_ref_fn fn, void *cb_data)
+int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, void *cb_data)
{
struct strbuf buf = STRBUF_INIT;
int ret = 0;
@@ -550,7 +524,7 @@ int head_ref_namespaced(each_ref_fn fn, void *cb_data)
int flag;
strbuf_addf(&buf, "%sHEAD", get_git_namespace());
- if (!read_ref_full(buf.buf, RESOLVE_REF_READING, &oid, &flag))
+ if (!refs_read_ref_full(refs, buf.buf, RESOLVE_REF_READING, &oid, &flag))
ret = fn(buf.buf, &oid, flag, cb_data);
strbuf_release(&buf);
@@ -583,8 +557,8 @@ void normalize_glob_ref(struct string_list_item *item, const char *prefix,
strbuf_release(&normalized_pattern);
}
-int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
- const char *prefix, void *cb_data)
+int refs_for_each_glob_ref_in(struct ref_store *refs, each_ref_fn fn,
+ const char *pattern, const char *prefix, void *cb_data)
{
struct strbuf real_pattern = STRBUF_INIT;
struct for_each_ref_filter filter;
@@ -607,15 +581,16 @@ int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
filter.prefix = prefix;
filter.fn = fn;
filter.cb_data = cb_data;
- ret = for_each_ref(for_each_filter_refs, &filter);
+ ret = refs_for_each_ref(refs, for_each_filter_refs, &filter);
strbuf_release(&real_pattern);
return ret;
}
-int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
+int refs_for_each_glob_ref(struct ref_store *refs, each_ref_fn fn,
+ const char *pattern, void *cb_data)
{
- return for_each_glob_ref_in(fn, pattern, NULL, cb_data);
+ return refs_for_each_glob_ref_in(refs, fn, pattern, NULL, cb_data);
}
const char *prettify_refname(const char *name)
@@ -844,7 +819,22 @@ int is_per_worktree_ref(const char *refname)
starts_with(refname, "refs/rewritten/");
}
-static int is_pseudoref_syntax(const char *refname)
+int is_pseudo_ref(const char *refname)
+{
+ static const char * const pseudo_refs[] = {
+ "FETCH_HEAD",
+ "MERGE_HEAD",
+ };
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(pseudo_refs); i++)
+ if (!strcmp(refname, pseudo_refs[i]))
+ return 1;
+
+ return 0;
+}
+
+static int is_root_ref_syntax(const char *refname)
{
const char *c;
@@ -860,49 +850,52 @@ static int is_pseudoref_syntax(const char *refname)
return 1;
}
-int is_pseudoref(struct ref_store *refs, const char *refname)
+int is_root_ref(struct ref_store *refs, const char *refname)
{
- static const char *const irregular_pseudorefs[] = {
+ static const char *const irregular_root_refs[] = {
+ "HEAD",
"AUTO_MERGE",
"BISECT_EXPECTED_REV",
"NOTES_MERGE_PARTIAL",
"NOTES_MERGE_REF",
"MERGE_AUTOSTASH",
};
- struct object_id oid;
+ struct strbuf referent = STRBUF_INIT;
+ struct object_id oid = { 0 };
+ int failure_errno, ret = 0;
+ unsigned int flags;
size_t i;
- if (!is_pseudoref_syntax(refname))
+ if (!is_root_ref_syntax(refname) ||
+ is_pseudo_ref(refname))
return 0;
+ /*
+ * Note that we cannot use `refs_ref_exists()` here because that also
+ * checks whether its target ref exists in case refname is a symbolic
+ * ref.
+ */
if (ends_with(refname, "_HEAD")) {
- refs_resolve_ref_unsafe(refs, refname,
- RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
- &oid, NULL);
- return !is_null_oid(&oid);
+ ret = !refs_read_raw_ref(refs, refname, &oid, &referent,
+ &flags, &failure_errno);
+ goto done;
}
- for (i = 0; i < ARRAY_SIZE(irregular_pseudorefs); i++)
- if (!strcmp(refname, irregular_pseudorefs[i])) {
- refs_resolve_ref_unsafe(refs, refname,
- RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
- &oid, NULL);
- return !is_null_oid(&oid);
+ for (i = 0; i < ARRAY_SIZE(irregular_root_refs); i++) {
+ if (!strcmp(refname, irregular_root_refs[i])) {
+ ret = !refs_read_raw_ref(refs, refname, &oid, &referent,
+ &flags, &failure_errno);
+ goto done;
}
+ }
- return 0;
-}
-
-int is_headref(struct ref_store *refs, const char *refname)
-{
- if (!strcmp(refname, "HEAD"))
- return refs_ref_exists(refs, refname);
-
- return 0;
+done:
+ strbuf_release(&referent);
+ return ret;
}
static int is_current_worktree_ref(const char *ref) {
- return is_pseudoref_syntax(ref) || is_per_worktree_ref(ref);
+ return is_root_ref_syntax(ref) || is_per_worktree_ref(ref);
}
enum ref_worktree_type parse_worktree_ref(const char *maybe_worktree_ref,
@@ -991,13 +984,6 @@ int refs_delete_ref(struct ref_store *refs, const char *msg,
return 0;
}
-int delete_ref(const char *msg, const char *refname,
- const struct object_id *old_oid, unsigned int flags)
-{
- return refs_delete_ref(get_main_ref_store(the_repository), msg, refname,
- old_oid, flags);
-}
-
static void copy_reflog_msg(struct strbuf *sb, const char *msg)
{
char c;
@@ -1190,11 +1176,6 @@ struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
return tr;
}
-struct ref_transaction *ref_transaction_begin(struct strbuf *err)
-{
- return ref_store_transaction_begin(get_main_ref_store(the_repository), err);
-}
-
void ref_transaction_free(struct ref_transaction *transaction)
{
size_t i;
@@ -1217,6 +1198,8 @@ void ref_transaction_free(struct ref_transaction *transaction)
for (i = 0; i < transaction->nr; i++) {
free(transaction->updates[i]->msg);
+ free((char *)transaction->updates[i]->new_target);
+ free((char *)transaction->updates[i]->old_target);
free(transaction->updates[i]);
}
free(transaction->updates);
@@ -1228,6 +1211,7 @@ struct ref_update *ref_transaction_add_update(
const char *refname, unsigned int flags,
const struct object_id *new_oid,
const struct object_id *old_oid,
+ const char *new_target, const char *old_target,
const char *msg)
{
struct ref_update *update;
@@ -1235,16 +1219,24 @@ struct ref_update *ref_transaction_add_update(
if (transaction->state != REF_TRANSACTION_OPEN)
BUG("update called for transaction that is not open");
+ if (old_oid && old_target)
+ BUG("only one of old_oid and old_target should be non NULL");
+ if (new_oid && new_target)
+ BUG("only one of new_oid and new_target should be non NULL");
+
FLEX_ALLOC_STR(update, refname, refname);
ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
transaction->updates[transaction->nr++] = update;
update->flags = flags;
- if (flags & REF_HAVE_NEW)
+ update->new_target = xstrdup_or_null(new_target);
+ update->old_target = xstrdup_or_null(old_target);
+ if ((flags & REF_HAVE_NEW) && new_oid)
oidcpy(&update->new_oid, new_oid);
- if (flags & REF_HAVE_OLD)
+ if ((flags & REF_HAVE_OLD) && old_oid)
oidcpy(&update->old_oid, old_oid);
+
update->msg = normalize_reflog_message(msg);
return update;
}
@@ -1253,6 +1245,8 @@ int ref_transaction_update(struct ref_transaction *transaction,
const char *refname,
const struct object_id *new_oid,
const struct object_id *old_oid,
+ const char *new_target,
+ const char *old_target,
unsigned int flags, const char *msg,
struct strbuf *err)
{
@@ -1267,6 +1261,13 @@ int ref_transaction_update(struct ref_transaction *transaction,
return -1;
}
+ if (!(flags & REF_SKIP_REFNAME_VERIFICATION) &&
+ is_pseudo_ref(refname)) {
+ strbuf_addf(err, _("refusing to update pseudoref '%s'"),
+ refname);
+ return -1;
+ }
+
if (flags & ~REF_TRANSACTION_UPDATE_ALLOWED_FLAGS)
BUG("illegal flags 0x%x passed to ref_transaction_update()", flags);
@@ -1278,9 +1279,11 @@ int ref_transaction_update(struct ref_transaction *transaction,
flags &= REF_TRANSACTION_UPDATE_ALLOWED_FLAGS;
flags |= (new_oid ? REF_HAVE_NEW : 0) | (old_oid ? REF_HAVE_OLD : 0);
+ flags |= (new_target ? REF_HAVE_NEW : 0) | (old_target ? REF_HAVE_OLD : 0);
ref_transaction_add_update(transaction, refname, flags,
- new_oid, old_oid, msg);
+ new_oid, old_oid, new_target,
+ old_target, msg);
return 0;
}
@@ -1295,7 +1298,8 @@ int ref_transaction_create(struct ref_transaction *transaction,
return 1;
}
return ref_transaction_update(transaction, refname, new_oid,
- null_oid(), flags, msg, err);
+ null_oid(), NULL, NULL, flags,
+ msg, err);
}
int ref_transaction_delete(struct ref_transaction *transaction,
@@ -1308,7 +1312,8 @@ int ref_transaction_delete(struct ref_transaction *transaction,
BUG("delete called with old_oid set to zeros");
return ref_transaction_update(transaction, refname,
null_oid(), old_oid,
- flags, msg, err);
+ NULL, NULL, flags,
+ msg, err);
}
int ref_transaction_verify(struct ref_transaction *transaction,
@@ -1321,6 +1326,7 @@ int ref_transaction_verify(struct ref_transaction *transaction,
BUG("verify called with old_oid set to NULL");
return ref_transaction_update(transaction, refname,
NULL, old_oid,
+ NULL, NULL,
flags, NULL, err);
}
@@ -1335,8 +1341,8 @@ int refs_update_ref(struct ref_store *refs, const char *msg,
t = ref_store_transaction_begin(refs, &err);
if (!t ||
- ref_transaction_update(t, refname, new_oid, old_oid, flags, msg,
- &err) ||
+ ref_transaction_update(t, refname, new_oid, old_oid, NULL, NULL,
+ flags, msg, &err) ||
ref_transaction_commit(t, &err)) {
ret = 1;
ref_transaction_free(t);
@@ -1363,15 +1369,6 @@ int refs_update_ref(struct ref_store *refs, const char *msg,
return 0;
}
-int update_ref(const char *msg, const char *refname,
- const struct object_id *new_oid,
- const struct object_id *old_oid,
- unsigned int flags, enum action_on_err onerr)
-{
- return refs_update_ref(get_main_ref_store(the_repository), msg, refname, new_oid,
- old_oid, flags, onerr);
-}
-
/*
* Check that the string refname matches a rule of the form
* "{prefix}%.*s{suffix}". So "foo/bar/baz" would match the rule
@@ -1473,12 +1470,6 @@ char *refs_shorten_unambiguous_ref(struct ref_store *refs,
return xstrdup(refname);
}
-char *shorten_unambiguous_ref(const char *refname, int strict)
-{
- return refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
- refname, strict);
-}
-
int parse_hide_refs_config(const char *var, const char *value, const char *section,
struct strvec *hide_refs)
{
@@ -1597,11 +1588,6 @@ int refs_head_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
return 0;
}
-int head_ref(each_ref_fn fn, void *cb_data)
-{
- return refs_head_ref(get_main_ref_store(the_repository), fn, cb_data);
-}
-
struct ref_iterator *refs_ref_iterator_begin(
struct ref_store *refs,
const char *prefix,
@@ -1696,28 +1682,12 @@ int refs_for_each_ref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
return do_for_each_ref(refs, "", NULL, fn, 0, 0, cb_data);
}
-int for_each_ref(each_ref_fn fn, void *cb_data)
-{
- return refs_for_each_ref(get_main_ref_store(the_repository), fn, cb_data);
-}
-
int refs_for_each_ref_in(struct ref_store *refs, const char *prefix,
each_ref_fn fn, void *cb_data)
{
return do_for_each_ref(refs, prefix, NULL, fn, strlen(prefix), 0, cb_data);
}
-int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
-{
- return refs_for_each_ref_in(get_main_ref_store(the_repository), prefix, fn, cb_data);
-}
-
-int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data)
-{
- return do_for_each_ref(get_main_ref_store(the_repository),
- prefix, NULL, fn, 0, 0, cb_data);
-}
-
int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
const char **exclude_patterns,
each_ref_fn fn, void *cb_data)
@@ -1733,14 +1703,14 @@ int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_dat
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
}
-int for_each_namespaced_ref(const char **exclude_patterns,
- each_ref_fn fn, void *cb_data)
+int refs_for_each_namespaced_ref(struct ref_store *refs,
+ const char **exclude_patterns,
+ each_ref_fn fn, void *cb_data)
{
struct strbuf buf = STRBUF_INIT;
int ret;
strbuf_addf(&buf, "%srefs/", get_git_namespace());
- ret = do_for_each_ref(get_main_ref_store(the_repository),
- buf.buf, exclude_patterns, fn, 0, 0, cb_data);
+ ret = do_for_each_ref(refs, buf.buf, exclude_patterns, fn, 0, 0, cb_data);
strbuf_release(&buf);
return ret;
}
@@ -1751,11 +1721,6 @@ int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data)
DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
}
-int for_each_rawref(each_ref_fn fn, void *cb_data)
-{
- return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);
-}
-
int refs_for_each_include_root_refs(struct ref_store *refs, each_ref_fn fn,
void *cb_data)
{
@@ -1876,43 +1841,12 @@ done:
return result;
}
-static int is_special_ref(const char *refname)
-{
- /*
- * Special references are refs that have different semantics compared
- * to "normal" refs. These refs can thus not be stored in the ref
- * backend, but must always be accessed via the filesystem. The
- * following refs are special:
- *
- * - FETCH_HEAD may contain multiple object IDs, and each one of them
- * carries additional metadata like where it came from.
- *
- * - MERGE_HEAD may contain multiple object IDs when merging multiple
- * heads.
- *
- * Reading, writing or deleting references must consistently go either
- * through the filesystem (special refs) or through the reference
- * backend (normal ones).
- */
- static const char * const special_refs[] = {
- "FETCH_HEAD",
- "MERGE_HEAD",
- };
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(special_refs); i++)
- if (!strcmp(refname, special_refs[i]))
- return 1;
-
- return 0;
-}
-
int refs_read_raw_ref(struct ref_store *ref_store, const char *refname,
struct object_id *oid, struct strbuf *referent,
unsigned int *type, int *failure_errno)
{
assert(failure_errno);
- if (is_special_ref(refname))
+ if (is_pseudo_ref(refname))
return refs_read_special_head(ref_store, refname, oid, referent,
type, failure_errno);
@@ -2021,13 +1955,6 @@ int refs_init_db(struct ref_store *refs, int flags, struct strbuf *err)
return refs->be->init_db(refs, flags, err);
}
-const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
- struct object_id *oid, int *flags)
-{
- return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname,
- resolve_flags, oid, flags);
-}
-
int resolve_gitlink_ref(const char *submodule, const char *refname,
struct object_id *oid)
{
@@ -2266,26 +2193,27 @@ int peel_iterated_oid(const struct object_id *base, struct object_id *peeled)
return peel_object(base, peeled) ? -1 : 0;
}
-int refs_create_symref(struct ref_store *refs,
- const char *ref_target,
- const char *refs_heads_master,
- const char *logmsg)
+int refs_update_symref(struct ref_store *refs, const char *ref,
+ const char *target, const char *logmsg)
{
- char *msg;
- int retval;
+ struct ref_transaction *transaction;
+ struct strbuf err = STRBUF_INIT;
+ int ret = 0;
- msg = normalize_reflog_message(logmsg);
- retval = refs->be->create_symref(refs, ref_target, refs_heads_master,
- msg);
- free(msg);
- return retval;
-}
+ transaction = ref_store_transaction_begin(refs, &err);
+ if (!transaction ||
+ ref_transaction_update(transaction, ref, NULL, NULL,
+ target, NULL, REF_NO_DEREF,
+ logmsg, &err) ||
+ ref_transaction_commit(transaction, &err)) {
+ ret = error("%s", err.buf);
+ }
-int create_symref(const char *ref_target, const char *refs_heads_master,
- const char *logmsg)
-{
- return refs_create_symref(get_main_ref_store(the_repository), ref_target,
- refs_heads_master, logmsg);
+ strbuf_release(&err);
+ if (transaction)
+ ref_transaction_free(transaction);
+
+ return ret;
}
int ref_update_reject_duplicates(struct string_list *refnames,
@@ -2338,10 +2266,22 @@ static int run_transaction_hook(struct ref_transaction *transaction,
struct ref_update *update = transaction->updates[i];
strbuf_reset(&buf);
- strbuf_addf(&buf, "%s %s %s\n",
- oid_to_hex(&update->old_oid),
- oid_to_hex(&update->new_oid),
- update->refname);
+
+ if (!(update->flags & REF_HAVE_OLD))
+ strbuf_addf(&buf, "%s ", oid_to_hex(null_oid()));
+ else if (update->old_target)
+ strbuf_addf(&buf, "ref:%s ", update->old_target);
+ else
+ strbuf_addf(&buf, "%s ", oid_to_hex(&update->old_oid));
+
+ if (!(update->flags & REF_HAVE_NEW))
+ strbuf_addf(&buf, "%s ", oid_to_hex(null_oid()));
+ else if (update->new_target)
+ strbuf_addf(&buf, "ref:%s ", update->new_target);
+ else
+ strbuf_addf(&buf, "%s ", oid_to_hex(&update->new_oid));
+
+ strbuf_addf(&buf, "%s\n", update->refname);
if (write_in_full(proc.in, buf.buf, buf.len) < 0) {
if (errno != EPIPE) {
@@ -2581,11 +2521,6 @@ int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_dat
do_for_each_reflog_helper, &hp);
}
-int for_each_reflog(each_reflog_fn fn, void *cb_data)
-{
- return refs_for_each_reflog(get_main_ref_store(the_repository), fn, cb_data);
-}
-
int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
const char *refname,
each_reflog_ent_fn fn,
@@ -2595,58 +2530,28 @@ int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
fn, cb_data);
}
-int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
- void *cb_data)
-{
- return refs_for_each_reflog_ent_reverse(get_main_ref_store(the_repository),
- refname, fn, cb_data);
-}
-
int refs_for_each_reflog_ent(struct ref_store *refs, const char *refname,
each_reflog_ent_fn fn, void *cb_data)
{
return refs->be->for_each_reflog_ent(refs, refname, fn, cb_data);
}
-int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
- void *cb_data)
-{
- return refs_for_each_reflog_ent(get_main_ref_store(the_repository), refname,
- fn, cb_data);
-}
-
int refs_reflog_exists(struct ref_store *refs, const char *refname)
{
return refs->be->reflog_exists(refs, refname);
}
-int reflog_exists(const char *refname)
-{
- return refs_reflog_exists(get_main_ref_store(the_repository), refname);
-}
-
int refs_create_reflog(struct ref_store *refs, const char *refname,
struct strbuf *err)
{
return refs->be->create_reflog(refs, refname, err);
}
-int safe_create_reflog(const char *refname, struct strbuf *err)
-{
- return refs_create_reflog(get_main_ref_store(the_repository), refname,
- err);
-}
-
int refs_delete_reflog(struct ref_store *refs, const char *refname)
{
return refs->be->delete_reflog(refs, refname);
}
-int delete_reflog(const char *refname)
-{
- return refs_delete_reflog(get_main_ref_store(the_repository), refname);
-}
-
int refs_reflog_expire(struct ref_store *refs,
const char *refname,
unsigned int flags,
@@ -2660,19 +2565,6 @@ int refs_reflog_expire(struct ref_store *refs,
cleanup_fn, policy_cb_data);
}
-int reflog_expire(const char *refname,
- unsigned int flags,
- reflog_expiry_prepare_fn prepare_fn,
- reflog_expiry_should_prune_fn should_prune_fn,
- reflog_expiry_cleanup_fn cleanup_fn,
- void *policy_cb_data)
-{
- return refs_reflog_expire(get_main_ref_store(the_repository),
- refname, flags,
- prepare_fn, should_prune_fn,
- cleanup_fn, policy_cb_data);
-}
-
int initial_ref_transaction_commit(struct ref_transaction *transaction,
struct strbuf *err)
{
@@ -2751,12 +2643,6 @@ out:
return ret;
}
-int delete_refs(const char *msg, struct string_list *refnames,
- unsigned int flags)
-{
- return refs_delete_refs(get_main_ref_store(the_repository), msg, refnames, flags);
-}
-
int refs_rename_ref(struct ref_store *refs, const char *oldref,
const char *newref, const char *logmsg)
{
@@ -2769,11 +2655,6 @@ int refs_rename_ref(struct ref_store *refs, const char *oldref,
return retval;
}
-int rename_ref(const char *oldref, const char *newref, const char *logmsg)
-{
- return refs_rename_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
-}
-
int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
const char *newref, const char *logmsg)
{
@@ -2786,7 +2667,37 @@ int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
return retval;
}
-int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg)
+const char *ref_update_original_update_refname(struct ref_update *update)
{
- return refs_copy_existing_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
+ while (update->parent_update)
+ update = update->parent_update;
+
+ return update->refname;
+}
+
+int ref_update_has_null_new_value(struct ref_update *update)
+{
+ return !update->new_target && is_null_oid(&update->new_oid);
+}
+
+int ref_update_check_old_target(const char *referent, struct ref_update *update,
+ struct strbuf *err)
+{
+ if (!update->old_target)
+ BUG("called without old_target set");
+
+ if (!strcmp(referent, update->old_target))
+ return 0;
+
+ if (!strcmp(referent, ""))
+ strbuf_addf(err, "verifying symref target: '%s': "
+ "reference is missing but expected %s",
+ ref_update_original_update_refname(update),
+ update->old_target);
+ else
+ strbuf_addf(err, "verifying symref target: '%s': "
+ "is at %s but expected %s",
+ ref_update_original_update_refname(update),
+ referent, update->old_target);
+ return -1;
}
diff --git a/refs.h b/refs.h
index d278775e08..6372b341a3 100644
--- a/refs.h
+++ b/refs.h
@@ -72,18 +72,14 @@ const char *refs_resolve_ref_unsafe(struct ref_store *refs,
struct object_id *oid,
int *flags);
-const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
- struct object_id *oid, int *flags);
-
char *refs_resolve_refdup(struct ref_store *refs,
const char *refname, int resolve_flags,
struct object_id *oid, int *flags);
-char *resolve_refdup(const char *refname, int resolve_flags,
- struct object_id *oid, int *flags);
-int read_ref_full(const char *refname, int resolve_flags,
- struct object_id *oid, int *flags);
-int read_ref(const char *refname, struct object_id *oid);
+int refs_read_ref_full(struct ref_store *refs, const char *refname,
+ int resolve_flags, struct object_id *oid, int *flags);
+
+int refs_read_ref(struct ref_store *refs, const char *refname, struct object_id *oid);
int refs_read_symbolic_ref(struct ref_store *ref_store, const char *refname,
struct strbuf *referent);
@@ -114,8 +110,6 @@ int refs_verify_refname_available(struct ref_store *refs,
int refs_ref_exists(struct ref_store *refs, const char *refname);
-int ref_exists(const char *refname);
-
int should_autocreate_reflog(const char *refname);
int is_branch(const char *refname);
@@ -330,18 +324,6 @@ int refs_for_each_branch_ref(struct ref_store *refs,
int refs_for_each_remote_ref(struct ref_store *refs,
each_ref_fn fn, void *cb_data);
-/* just iterates the head ref. */
-int head_ref(each_ref_fn fn, void *cb_data);
-
-/* iterates all refs. */
-int for_each_ref(each_ref_fn fn, void *cb_data);
-
-/**
- * iterates all refs which have a defined prefix and strips that prefix from
- * the passed variable refname.
- */
-int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data);
-
/*
* references matching any pattern in "exclude_patterns" are omitted from the
* result set on a best-effort basis.
@@ -349,7 +331,6 @@ int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data);
int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
const char **exclude_patterns,
each_ref_fn fn, void *cb_data);
-int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data);
/**
* iterate all refs in "patterns" by partitioning patterns into disjoint sets
@@ -369,28 +350,27 @@ int refs_for_each_fullref_in_prefixes(struct ref_store *refs,
/**
* iterate refs from the respective area.
*/
-int for_each_tag_ref(each_ref_fn fn, void *cb_data);
-int for_each_branch_ref(each_ref_fn fn, void *cb_data);
-int for_each_remote_ref(each_ref_fn fn, void *cb_data);
int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data);
/* iterates all refs that match the specified glob pattern. */
-int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data);
+int refs_for_each_glob_ref(struct ref_store *refs, each_ref_fn fn,
+ const char *pattern, void *cb_data);
+
+int refs_for_each_glob_ref_in(struct ref_store *refs, each_ref_fn fn,
+ const char *pattern, const char *prefix, void *cb_data);
-int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
- const char *prefix, void *cb_data);
+int refs_head_ref_namespaced(struct ref_store *refs, each_ref_fn fn, void *cb_data);
-int head_ref_namespaced(each_ref_fn fn, void *cb_data);
/*
* references matching any pattern in "exclude_patterns" are omitted from the
* result set on a best-effort basis.
*/
-int for_each_namespaced_ref(const char **exclude_patterns,
- each_ref_fn fn, void *cb_data);
+int refs_for_each_namespaced_ref(struct ref_store *refs,
+ const char **exclude_patterns,
+ each_ref_fn fn, void *cb_data);
/* can be used to learn about broken ref and symref */
int refs_for_each_rawref(struct ref_store *refs, each_ref_fn fn, void *cb_data);
-int for_each_rawref(each_ref_fn fn, void *cb_data);
/*
* Iterates over all refs including root refs, i.e. pseudorefs and HEAD.
@@ -446,7 +426,6 @@ int refs_pack_refs(struct ref_store *refs, struct pack_refs_opts *opts);
*/
int refs_create_reflog(struct ref_store *refs, const char *refname,
struct strbuf *err);
-int safe_create_reflog(const char *refname, struct strbuf *err);
/**
* Reads log for the value of ref during at_time (in which case "cnt" should be
@@ -470,7 +449,6 @@ int read_ref_at(struct ref_store *refs,
/** Check if a particular reflog exists */
int refs_reflog_exists(struct ref_store *refs, const char *refname);
-int reflog_exists(const char *refname);
/*
* Delete the specified reference. If old_oid is non-NULL, then
@@ -484,8 +462,6 @@ int refs_delete_ref(struct ref_store *refs, const char *msg,
const char *refname,
const struct object_id *old_oid,
unsigned int flags);
-int delete_ref(const char *msg, const char *refname,
- const struct object_id *old_oid, unsigned int flags);
/*
* Delete the specified references. If there are any problems, emit
@@ -495,12 +471,9 @@ int delete_ref(const char *msg, const char *refname,
*/
int refs_delete_refs(struct ref_store *refs, const char *msg,
struct string_list *refnames, unsigned int flags);
-int delete_refs(const char *msg, struct string_list *refnames,
- unsigned int flags);
/** Delete a reflog */
int refs_delete_reflog(struct ref_store *refs, const char *refname);
-int delete_reflog(const char *refname);
/*
* Callback to process a reflog entry found by the iteration functions (see
@@ -546,17 +519,7 @@ int refs_for_each_reflog_ent_reverse(struct ref_store *refs,
void *cb_data);
/*
- * Iterate over reflog entries in the log for `refname` in the main ref store.
- */
-
-/* oldest entry first */
-int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn, void *cb_data);
-
-/* youngest entry first */
-int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn, void *cb_data);
-
-/*
- * The signature for the callback function for the {refs_,}for_each_reflog()
+ * The signature for the callback function for the refs_for_each_reflog()
* functions below. The memory pointed to by the refname argument is only
* guaranteed to be valid for the duration of a single callback invocation.
*/
@@ -567,7 +530,6 @@ typedef int each_reflog_fn(const char *refname, void *cb_data);
* and returns the value. Reflog file order is unspecified.
*/
int refs_for_each_reflog(struct ref_store *refs, each_reflog_fn fn, void *cb_data);
-int for_each_reflog(each_reflog_fn fn, void *cb_data);
#define REFNAME_ALLOW_ONELEVEL 1
#define REFNAME_REFSPEC_PATTERN 2
@@ -592,23 +554,17 @@ const char *prettify_refname(const char *refname);
char *refs_shorten_unambiguous_ref(struct ref_store *refs,
const char *refname, int strict);
-char *shorten_unambiguous_ref(const char *refname, int strict);
/** rename ref, return 0 on success **/
int refs_rename_ref(struct ref_store *refs, const char *oldref,
const char *newref, const char *logmsg);
-int rename_ref(const char *oldref, const char *newref,
- const char *logmsg);
/** copy ref, return 0 on success **/
int refs_copy_existing_ref(struct ref_store *refs, const char *oldref,
const char *newref, const char *logmsg);
-int copy_existing_ref(const char *oldref, const char *newref,
- const char *logmsg);
-int refs_create_symref(struct ref_store *refs, const char *refname,
+int refs_update_symref(struct ref_store *refs, const char *refname,
const char *target, const char *logmsg);
-int create_symref(const char *refname, const char *target, const char *logmsg);
enum action_on_err {
UPDATE_REFS_MSG_ON_ERR,
@@ -622,7 +578,6 @@ enum action_on_err {
*/
struct ref_transaction *ref_store_transaction_begin(struct ref_store *refs,
struct strbuf *err);
-struct ref_transaction *ref_transaction_begin(struct strbuf *err);
/*
* Reference transaction updates
@@ -648,6 +603,16 @@ struct ref_transaction *ref_transaction_begin(struct strbuf *err);
* before the update. A copy of this value is made in the
* transaction.
*
+ * new_target -- the target reference that the reference will be
+ * updated to point to. If the reference is a regular reference,
+ * it will be converted to a symbolic reference. Cannot be set
+ * together with `new_oid`. A copy of this value is made in the
+ * transaction.
+ *
+ * old_target -- the reference that the reference must be pointing to.
+ * Canont be set together with `old_oid`. A copy of this value is
+ * made in the transaction.
+ *
* flags -- flags affecting the update, passed to
* update_ref_lock(). Possible flags: REF_NO_DEREF,
* REF_FORCE_CREATE_REFLOG. See those constants for more
@@ -713,7 +678,11 @@ struct ref_transaction *ref_transaction_begin(struct strbuf *err);
* beforehand. The old value is checked after the lock is taken to
* prevent races. If the old value doesn't agree with old_oid, the
* whole transaction fails. If old_oid is NULL, then the previous
- * value is not checked.
+ * value is not checked. If `old_target` is not NULL, treat the reference
+ * as a symbolic ref and validate that its target before the update is
+ * `old_target`. If the `new_target` is not NULL, then the reference
+ * will be updated to a symbolic ref which targets `new_target`.
+ * Together, these allow us to update between regular refs and symrefs.
*
* See the above comment "Reference transaction updates" for more
* information.
@@ -722,6 +691,8 @@ int ref_transaction_update(struct ref_transaction *transaction,
const char *refname,
const struct object_id *new_oid,
const struct object_id *old_oid,
+ const char *new_target,
+ const char *old_target,
unsigned int flags, const char *msg,
struct strbuf *err);
@@ -853,9 +824,6 @@ void ref_transaction_free(struct ref_transaction *transaction);
int refs_update_ref(struct ref_store *refs, const char *msg, const char *refname,
const struct object_id *new_oid, const struct object_id *old_oid,
unsigned int flags, enum action_on_err onerr);
-int update_ref(const char *msg, const char *refname,
- const struct object_id *new_oid, const struct object_id *old_oid,
- unsigned int flags, enum action_on_err onerr);
int parse_hide_refs_config(const char *var, const char *value, const char *,
struct strvec *);
@@ -913,7 +881,7 @@ enum expire_reflog_flags {
/*
* The following interface is used for reflog expiration. The caller
- * calls reflog_expire(), supplying it with three callback functions,
+ * calls refs_reflog_expire(), supplying it with three callback functions,
* of the following types. The callback functions define the
* expiration policy that is desired.
*
@@ -950,12 +918,6 @@ int refs_reflog_expire(struct ref_store *refs,
reflog_expiry_should_prune_fn should_prune_fn,
reflog_expiry_cleanup_fn cleanup_fn,
void *policy_cb_data);
-int reflog_expire(const char *refname,
- unsigned int flags,
- reflog_expiry_prepare_fn prepare_fn,
- reflog_expiry_should_prune_fn should_prune_fn,
- reflog_expiry_cleanup_fn cleanup_fn,
- void *policy_cb_data);
struct ref_store *get_main_ref_store(struct repository *r);
@@ -1051,7 +1013,258 @@ extern struct ref_namespace_info ref_namespace[NAMESPACE__COUNT];
*/
void update_ref_namespace(enum ref_namespace namespace, char *ref);
-int is_pseudoref(struct ref_store *refs, const char *refname);
-int is_headref(struct ref_store *refs, const char *refname);
+/*
+ * Check whether the reference is an existing root reference. A root reference
+ * that is a dangling symbolic ref is considered to exist.
+ *
+ * A root ref is a reference that lives in the root of the reference hierarchy.
+ * These references must conform to special syntax:
+ *
+ * - Their name must be all-uppercase or underscores ("_").
+ *
+ * - Their name must end with "_HEAD". As a special rule, "HEAD" is a root
+ * ref, as well.
+ *
+ * - Their name may not contain a slash.
+ *
+ * There is a special set of irregular root refs that exist due to historic
+ * reasons, only. This list shall not be expanded in the future:
+ *
+ * - AUTO_MERGE
+ *
+ * - BISECT_EXPECTED_REV
+ *
+ * - NOTES_MERGE_PARTIAL
+ *
+ * - NOTES_MERGE_REF
+ *
+ * - MERGE_AUTOSTASH
+ */
+int is_root_ref(struct ref_store *refs, const char *refname);
+
+/*
+ * Pseudorefs are refs that have different semantics compared to
+ * "normal" refs. These refs can thus not be stored in the ref backend,
+ * but must always be accessed via the filesystem. The following refs
+ * are pseudorefs:
+ *
+ * - FETCH_HEAD may contain multiple object IDs, and each one of them
+ * carries additional metadata like where it came from.
+ *
+ * - MERGE_HEAD may contain multiple object IDs when merging multiple
+ * heads.
+ *
+ * Reading, writing or deleting references must consistently go either
+ * through the filesystem (pseudorefs) or through the reference
+ * backend (normal ones).
+ */
+int is_pseudo_ref(const char *refname);
+
+/*
+ * The following functions have been removed in Git v2.45 in favor of functions
+ * that receive a `ref_store` as parameter. The intent of this section is
+ * merely to help patch authors of in-flight series to have a reference what
+ * they should be migrating to. The section will be removed in Git v2.46.
+ */
+#if 0
+static char *resolve_refdup(const char *refname, int resolve_flags,
+ struct object_id *oid, int *flags)
+{
+ return refs_resolve_refdup(get_main_ref_store(the_repository),
+ refname, resolve_flags,
+ oid, flags);
+}
+
+static int read_ref_full(const char *refname, int resolve_flags,
+ struct object_id *oid, int *flags)
+{
+ return refs_read_ref_full(get_main_ref_store(the_repository), refname,
+ resolve_flags, oid, flags);
+}
+
+static int read_ref(const char *refname, struct object_id *oid)
+{
+ return refs_read_ref(get_main_ref_store(the_repository), refname, oid);
+}
+
+static int ref_exists(const char *refname)
+{
+ return refs_ref_exists(get_main_ref_store(the_repository), refname);
+}
+
+static int for_each_tag_ref(each_ref_fn fn, void *cb_data)
+{
+ return refs_for_each_tag_ref(get_main_ref_store(the_repository), fn, cb_data);
+}
+
+static int for_each_branch_ref(each_ref_fn fn, void *cb_data)
+{
+ return refs_for_each_branch_ref(get_main_ref_store(the_repository), fn, cb_data);
+}
+
+static int for_each_remote_ref(each_ref_fn fn, void *cb_data)
+{
+ return refs_for_each_remote_ref(get_main_ref_store(the_repository), fn, cb_data);
+}
+
+static int head_ref_namespaced(each_ref_fn fn, void *cb_data)
+{
+ return refs_head_ref_namespaced(get_main_ref_store(the_repository),
+ fn, cb_data);
+}
+
+static int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
+ const char *prefix, void *cb_data)
+{
+ return refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
+ fn, pattern, prefix, cb_data);
+}
+
+static int for_each_glob_ref(each_ref_fn fn, const char *pattern, void *cb_data)
+{
+ return refs_for_each_glob_ref(get_main_ref_store(the_repository),
+ fn, pattern, cb_data);
+}
+
+static int delete_ref(const char *msg, const char *refname,
+ const struct object_id *old_oid, unsigned int flags)
+{
+ return refs_delete_ref(get_main_ref_store(the_repository), msg, refname,
+ old_oid, flags);
+}
+
+static struct ref_transaction *ref_transaction_begin(struct strbuf *err)
+{
+ return ref_store_transaction_begin(get_main_ref_store(the_repository), err);
+}
+
+static int update_ref(const char *msg, const char *refname,
+ const struct object_id *new_oid,
+ const struct object_id *old_oid,
+ unsigned int flags, enum action_on_err onerr)
+{
+ return refs_update_ref(get_main_ref_store(the_repository), msg, refname, new_oid,
+ old_oid, flags, onerr);
+}
+
+static char *shorten_unambiguous_ref(const char *refname, int strict)
+{
+ return refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+ refname, strict);
+}
+
+static int head_ref(each_ref_fn fn, void *cb_data)
+{
+ return refs_head_ref(get_main_ref_store(the_repository), fn, cb_data);
+}
+
+static int for_each_ref(each_ref_fn fn, void *cb_data)
+{
+ return refs_for_each_ref(get_main_ref_store(the_repository), fn, cb_data);
+}
+
+static int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
+{
+ return refs_for_each_ref_in(get_main_ref_store(the_repository), prefix, fn, cb_data);
+}
+
+static int for_each_fullref_in(const char *prefix,
+ const char **exclude_patterns,
+ each_ref_fn fn, void *cb_data)
+{
+ return refs_for_each_fullref_in(get_main_ref_store(the_repository),
+ prefix, exclude_patterns, fn, cb_data);
+}
+
+static int for_each_namespaced_ref(const char **exclude_patterns,
+ each_ref_fn fn, void *cb_data)
+{
+ return refs_for_each_namespaced_ref(get_main_ref_store(the_repository),
+ exclude_patterns, fn, cb_data);
+}
+
+static int for_each_rawref(each_ref_fn fn, void *cb_data)
+{
+ return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);
+}
+
+static const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
+ struct object_id *oid, int *flags)
+{
+ return refs_resolve_ref_unsafe(get_main_ref_store(the_repository), refname,
+ resolve_flags, oid, flags);
+}
+
+static int create_symref(const char *ref_target, const char *refs_heads_master,
+ const char *logmsg)
+{
+ return refs_create_symref(get_main_ref_store(the_repository), ref_target,
+ refs_heads_master, logmsg);
+}
+
+static int for_each_reflog(each_reflog_fn fn, void *cb_data)
+{
+ return refs_for_each_reflog(get_main_ref_store(the_repository), fn, cb_data);
+}
+
+static int for_each_reflog_ent_reverse(const char *refname, each_reflog_ent_fn fn,
+ void *cb_data)
+{
+ return refs_for_each_reflog_ent_reverse(get_main_ref_store(the_repository),
+ refname, fn, cb_data);
+}
+
+static int for_each_reflog_ent(const char *refname, each_reflog_ent_fn fn,
+ void *cb_data)
+{
+ return refs_for_each_reflog_ent(get_main_ref_store(the_repository), refname,
+ fn, cb_data);
+}
+
+static int reflog_exists(const char *refname)
+{
+ return refs_reflog_exists(get_main_ref_store(the_repository), refname);
+}
+
+static int safe_create_reflog(const char *refname, struct strbuf *err)
+{
+ return refs_create_reflog(get_main_ref_store(the_repository), refname,
+ err);
+}
+
+static int delete_reflog(const char *refname)
+{
+ return refs_delete_reflog(get_main_ref_store(the_repository), refname);
+}
+
+static int reflog_expire(const char *refname,
+ unsigned int flags,
+ reflog_expiry_prepare_fn prepare_fn,
+ reflog_expiry_should_prune_fn should_prune_fn,
+ reflog_expiry_cleanup_fn cleanup_fn,
+ void *policy_cb_data)
+{
+ return refs_reflog_expire(get_main_ref_store(the_repository),
+ refname, flags,
+ prepare_fn, should_prune_fn,
+ cleanup_fn, policy_cb_data);
+}
+
+static int delete_refs(const char *msg, struct string_list *refnames,
+ unsigned int flags)
+{
+ return refs_delete_refs(get_main_ref_store(the_repository), msg, refnames, flags);
+}
+
+static int rename_ref(const char *oldref, const char *newref, const char *logmsg)
+{
+ return refs_rename_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
+}
+
+static int copy_existing_ref(const char *oldref, const char *newref, const char *logmsg)
+{
+ return refs_copy_existing_ref(get_main_ref_store(the_repository), oldref, newref, logmsg);
+}
+#endif
#endif /* REFS_H */
diff --git a/refs/debug.c b/refs/debug.c
index c7531b17f0..8be316bb67 100644
--- a/refs/debug.c
+++ b/refs/debug.c
@@ -131,18 +131,6 @@ static int debug_pack_refs(struct ref_store *ref_store, struct pack_refs_opts *o
return res;
}
-static int debug_create_symref(struct ref_store *ref_store,
- const char *ref_name, const char *target,
- const char *logmsg)
-{
- struct debug_ref_store *drefs = (struct debug_ref_store *)ref_store;
- int res = drefs->refs->be->create_symref(drefs->refs, ref_name, target,
- logmsg);
- trace_printf_key(&trace_refs, "create_symref: %s -> %s \"%s\": %d\n", ref_name,
- target, logmsg, res);
- return res;
-}
-
static int debug_rename_ref(struct ref_store *ref_store, const char *oldref,
const char *newref, const char *logmsg)
{
@@ -441,7 +429,6 @@ struct ref_storage_be refs_be_debug = {
.initial_transaction_commit = debug_initial_transaction_commit,
.pack_refs = debug_pack_refs,
- .create_symref = debug_create_symref,
.rename_ref = debug_rename_ref,
.copy_ref = debug_copy_ref,
diff --git a/refs/files-backend.c b/refs/files-backend.c
index a098d14ea0..b3aac47348 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -351,8 +351,7 @@ static void add_pseudoref_and_head_entries(struct ref_store *ref_store,
strbuf_addstr(&refname, de->d_name);
dtype = get_dtype(de, &path, 1);
- if (dtype == DT_REG && (is_pseudoref(ref_store, de->d_name) ||
- is_headref(ref_store, de->d_name)))
+ if (dtype == DT_REG && is_root_ref(ref_store, de->d_name))
loose_fill_ref_dir_regular_file(refs, refname.buf, dir);
strbuf_setlen(&refname, dirnamelen);
@@ -794,8 +793,10 @@ retry:
*/
if (refs_verify_refname_available(
refs->packed_ref_store, refname,
- extras, NULL, err))
+ extras, NULL, err)) {
+ ret = TRANSACTION_NAME_CONFLICT;
goto error_return;
+ }
}
ret = 0;
@@ -1198,7 +1199,7 @@ static void prune_ref(struct files_ref_store *refs, struct ref_to_prune *r)
ref_transaction_add_update(
transaction, r->name,
REF_NO_DEREF | REF_HAVE_NEW | REF_HAVE_OLD | REF_IS_PRUNING,
- null_oid(), &r->oid, NULL);
+ null_oid(), &r->oid, NULL, NULL, NULL);
if (ref_transaction_commit(transaction, &err))
goto cleanup;
@@ -1292,7 +1293,7 @@ static int files_pack_refs(struct ref_store *ref_store,
* packed-refs transaction:
*/
if (ref_transaction_update(transaction, iter->refname,
- iter->oid, NULL,
+ iter->oid, NULL, NULL, NULL,
REF_NO_DEREF, NULL, &err))
die("failure preparing to create packed reference %s: %s",
iter->refname, err.buf);
@@ -1903,66 +1904,23 @@ static int create_ref_symlink(struct ref_lock *lock, const char *target)
return ret;
}
-static void update_symref_reflog(struct files_ref_store *refs,
- struct ref_lock *lock, const char *refname,
- const char *target, const char *logmsg)
+static int create_symref_lock(struct files_ref_store *refs,
+ struct ref_lock *lock, const char *refname,
+ const char *target, struct strbuf *err)
{
- struct strbuf err = STRBUF_INIT;
- struct object_id new_oid;
-
- if (logmsg &&
- refs_resolve_ref_unsafe(&refs->base, target,
- RESOLVE_REF_READING, &new_oid, NULL) &&
- files_log_ref_write(refs, refname, &lock->old_oid,
- &new_oid, logmsg, 0, &err)) {
- error("%s", err.buf);
- strbuf_release(&err);
- }
-}
-
-static int create_symref_locked(struct files_ref_store *refs,
- struct ref_lock *lock, const char *refname,
- const char *target, const char *logmsg)
-{
- if (prefer_symlink_refs && !create_ref_symlink(lock, target)) {
- update_symref_reflog(refs, lock, refname, target, logmsg);
- return 0;
+ if (!fdopen_lock_file(&lock->lk, "w")) {
+ strbuf_addf(err, "unable to fdopen %s: %s",
+ get_lock_file_path(&lock->lk), strerror(errno));
+ return -1;
}
- if (!fdopen_lock_file(&lock->lk, "w"))
- return error("unable to fdopen %s: %s",
+ if (fprintf(get_lock_file_fp(&lock->lk), "ref: %s\n", target) < 0) {
+ strbuf_addf(err, "unable to write to %s: %s",
get_lock_file_path(&lock->lk), strerror(errno));
-
- update_symref_reflog(refs, lock, refname, target, logmsg);
-
- /* no error check; commit_ref will check ferror */
- fprintf(get_lock_file_fp(&lock->lk), "ref: %s\n", target);
- if (commit_ref(lock) < 0)
- return error("unable to write symref for %s: %s", refname,
- strerror(errno));
- return 0;
-}
-
-static int files_create_symref(struct ref_store *ref_store,
- const char *refname, const char *target,
- const char *logmsg)
-{
- struct files_ref_store *refs =
- files_downcast(ref_store, REF_STORE_WRITE, "create_symref");
- struct strbuf err = STRBUF_INIT;
- struct ref_lock *lock;
- int ret;
-
- lock = lock_ref_oid_basic(refs, refname, &err);
- if (!lock) {
- error("%s", err.buf);
- strbuf_release(&err);
return -1;
}
- ret = create_symref_locked(refs, lock, refname, target, logmsg);
- unlock_ref(lock);
- return ret;
+ return 0;
}
static int files_reflog_exists(struct ref_store *ref_store,
@@ -2309,7 +2267,7 @@ static int split_head_update(struct ref_update *update,
transaction, "HEAD",
update->flags | REF_LOG_ONLY | REF_NO_DEREF,
&update->new_oid, &update->old_oid,
- update->msg);
+ NULL, NULL, update->msg);
/*
* Add "HEAD". This insertion is O(N) in the transaction
@@ -2371,8 +2329,9 @@ static int split_symref_update(struct ref_update *update,
new_update = ref_transaction_add_update(
transaction, referent, new_flags,
- &update->new_oid, &update->old_oid,
- update->msg);
+ update->new_target ? NULL : &update->new_oid,
+ update->old_target ? NULL : &update->old_oid,
+ update->new_target, update->old_target, update->msg);
new_update->parent_update = update;
@@ -2401,17 +2360,6 @@ static int split_symref_update(struct ref_update *update,
}
/*
- * Return the refname under which update was originally requested.
- */
-static const char *original_update_refname(struct ref_update *update)
-{
- while (update->parent_update)
- update = update->parent_update;
-
- return update->refname;
-}
-
-/*
* Check whether the REF_HAVE_OLD and old_oid values stored in update
* are consistent with oid, which is the reference's current value. If
* everything is OK, return 0; otherwise, write an error message to
@@ -2427,16 +2375,16 @@ static int check_old_oid(struct ref_update *update, struct object_id *oid,
if (is_null_oid(&update->old_oid))
strbuf_addf(err, "cannot lock ref '%s': "
"reference already exists",
- original_update_refname(update));
+ ref_update_original_update_refname(update));
else if (is_null_oid(oid))
strbuf_addf(err, "cannot lock ref '%s': "
"reference is missing but expected %s",
- original_update_refname(update),
+ ref_update_original_update_refname(update),
oid_to_hex(&update->old_oid));
else
strbuf_addf(err, "cannot lock ref '%s': "
"is at %s but expected %s",
- original_update_refname(update),
+ ref_update_original_update_refname(update),
oid_to_hex(oid),
oid_to_hex(&update->old_oid));
@@ -2471,7 +2419,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
files_assert_main_repository(refs, "lock_ref_for_update");
- if ((update->flags & REF_HAVE_NEW) && is_null_oid(&update->new_oid))
+ if ((update->flags & REF_HAVE_NEW) && ref_update_has_null_new_value(update))
update->flags |= REF_DELETING;
if (head_ref) {
@@ -2490,7 +2438,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
reason = strbuf_detach(err, NULL);
strbuf_addf(err, "cannot lock ref '%s': %s",
- original_update_refname(update), reason);
+ ref_update_original_update_refname(update), reason);
free(reason);
goto out;
}
@@ -2510,11 +2458,18 @@ static int lock_ref_for_update(struct files_ref_store *refs,
if (update->flags & REF_HAVE_OLD) {
strbuf_addf(err, "cannot lock ref '%s': "
"error reading reference",
- original_update_refname(update));
+ ref_update_original_update_refname(update));
ret = TRANSACTION_GENERIC_ERROR;
goto out;
}
- } else if (check_old_oid(update, &lock->old_oid, err)) {
+ }
+
+ if (update->old_target) {
+ if (ref_update_check_old_target(referent.buf, update, err)) {
+ ret = TRANSACTION_GENERIC_ERROR;
+ goto out;
+ }
+ } else if (check_old_oid(update, &lock->old_oid, err)) {
ret = TRANSACTION_GENERIC_ERROR;
goto out;
}
@@ -2535,7 +2490,17 @@ static int lock_ref_for_update(struct files_ref_store *refs,
} else {
struct ref_update *parent_update;
- if (check_old_oid(update, &lock->old_oid, err)) {
+ /*
+ * Even if the ref is a regular ref, if `old_target` is set, we
+ * check the referent value. Ideally `old_target` should only
+ * be set for symrefs, but we're strict about its usage.
+ */
+ if (update->old_target) {
+ if (ref_update_check_old_target(referent.buf, update, err)) {
+ ret = TRANSACTION_GENERIC_ERROR;
+ goto out;
+ }
+ } else if (check_old_oid(update, &lock->old_oid, err)) {
ret = TRANSACTION_GENERIC_ERROR;
goto out;
}
@@ -2553,9 +2518,28 @@ static int lock_ref_for_update(struct files_ref_store *refs,
}
}
- if ((update->flags & REF_HAVE_NEW) &&
- !(update->flags & REF_DELETING) &&
- !(update->flags & REF_LOG_ONLY)) {
+ if (update->new_target && !(update->flags & REF_LOG_ONLY)) {
+ if (create_symref_lock(refs, lock, update->refname,
+ update->new_target, err)) {
+ ret = TRANSACTION_GENERIC_ERROR;
+ goto out;
+ }
+
+ if (close_ref_gently(lock)) {
+ strbuf_addf(err, "couldn't close '%s.lock'",
+ update->refname);
+ ret = TRANSACTION_GENERIC_ERROR;
+ goto out;
+ }
+
+ /*
+ * Once we have created the symref lock, the commit
+ * phase of the transaction only needs to commit the lock.
+ */
+ update->flags |= REF_NEEDS_COMMIT;
+ } else if ((update->flags & REF_HAVE_NEW) &&
+ !(update->flags & REF_DELETING) &&
+ !(update->flags & REF_LOG_ONLY)) {
if (!(update->type & REF_ISSYMREF) &&
oideq(&lock->old_oid, &update->new_oid)) {
/*
@@ -2763,7 +2747,7 @@ static int files_transaction_prepare(struct ref_store *ref_store,
packed_transaction, update->refname,
REF_HAVE_NEW | REF_NO_DEREF,
&update->new_oid, NULL,
- NULL);
+ NULL, NULL, NULL);
}
}
@@ -2818,6 +2802,43 @@ cleanup:
return ret;
}
+static int parse_and_write_reflog(struct files_ref_store *refs,
+ struct ref_update *update,
+ struct ref_lock *lock,
+ struct strbuf *err)
+{
+ if (update->new_target) {
+ /*
+ * We want to get the resolved OID for the target, to ensure
+ * that the correct value is added to the reflog.
+ */
+ if (!refs_resolve_ref_unsafe(&refs->base, update->new_target,
+ RESOLVE_REF_READING,
+ &update->new_oid, NULL)) {
+ /*
+ * TODO: currently we skip creating reflogs for dangling
+ * symref updates. It would be nice to capture this as
+ * zero oid updates however.
+ */
+ return 0;
+ }
+ }
+
+ if (files_log_ref_write(refs, lock->ref_name, &lock->old_oid,
+ &update->new_oid, update->msg, update->flags, err)) {
+ char *old_msg = strbuf_detach(err, NULL);
+
+ strbuf_addf(err, "cannot update the ref '%s': %s",
+ lock->ref_name, old_msg);
+ free(old_msg);
+ unlock_ref(lock);
+ update->backend_data = NULL;
+ return -1;
+ }
+
+ return 0;
+}
+
static int files_transaction_finish(struct ref_store *ref_store,
struct ref_transaction *transaction,
struct strbuf *err)
@@ -2848,23 +2869,20 @@ static int files_transaction_finish(struct ref_store *ref_store,
if (update->flags & REF_NEEDS_COMMIT ||
update->flags & REF_LOG_ONLY) {
- if (files_log_ref_write(refs,
- lock->ref_name,
- &lock->old_oid,
- &update->new_oid,
- update->msg, update->flags,
- err)) {
- char *old_msg = strbuf_detach(err, NULL);
-
- strbuf_addf(err, "cannot update the ref '%s': %s",
- lock->ref_name, old_msg);
- free(old_msg);
- unlock_ref(lock);
- update->backend_data = NULL;
+ if (parse_and_write_reflog(refs, update, lock, err)) {
ret = TRANSACTION_GENERIC_ERROR;
goto cleanup;
}
}
+
+ /*
+ * We try creating a symlink, if that succeeds we continue to the
+ * next update. If not, we try and create a regular symref.
+ */
+ if (update->new_target && prefer_symlink_refs)
+ if (!create_ref_symlink(lock, update->new_target))
+ continue;
+
if (update->flags & REF_NEEDS_COMMIT) {
clear_loose_ref_cache(refs);
if (commit_ref(lock)) {
@@ -3048,7 +3066,7 @@ static int files_initial_transaction_commit(struct ref_store *ref_store,
ref_transaction_add_update(packed_transaction, update->refname,
update->flags & ~REF_HAVE_OLD,
&update->new_oid, &update->old_oid,
- NULL);
+ NULL, NULL, NULL);
}
if (packed_refs_lock(refs->packed_ref_store, 0, err)) {
@@ -3291,7 +3309,6 @@ struct ref_storage_be refs_be_files = {
.initial_transaction_commit = files_initial_transaction_commit,
.pack_refs = files_pack_refs,
- .create_symref = files_create_symref,
.rename_ref = files_rename_ref,
.copy_ref = files_copy_ref,
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index 4e826c05ff..a937e7dbfc 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -1714,7 +1714,6 @@ struct ref_storage_be refs_be_packed = {
.initial_transaction_commit = packed_initial_transaction_commit,
.pack_refs = packed_pack_refs,
- .create_symref = NULL,
.rename_ref = NULL,
.copy_ref = NULL,
diff --git a/refs/refs-internal.h b/refs/refs-internal.h
index 56641aa57a..53a6c5d842 100644
--- a/refs/refs-internal.h
+++ b/refs/refs-internal.h
@@ -125,6 +125,19 @@ struct ref_update {
struct object_id old_oid;
/*
+ * If set, point the reference to this value. This can also be
+ * used to convert regular references to become symbolic refs.
+ * Cannot be set together with `new_oid`.
+ */
+ const char *new_target;
+
+ /*
+ * If set, check that the reference previously pointed to this
+ * value. Cannot be set together with `old_oid`.
+ */
+ const char *old_target;
+
+ /*
* One or more of REF_NO_DEREF, REF_FORCE_CREATE_REFLOG,
* REF_HAVE_NEW, REF_HAVE_OLD, or backend-specific flags.
*/
@@ -173,6 +186,7 @@ struct ref_update *ref_transaction_add_update(
const char *refname, unsigned int flags,
const struct object_id *new_oid,
const struct object_id *old_oid,
+ const char *new_target, const char *old_target,
const char *msg);
/*
@@ -552,10 +566,6 @@ typedef int ref_transaction_commit_fn(struct ref_store *refs,
typedef int pack_refs_fn(struct ref_store *ref_store,
struct pack_refs_opts *opts);
-typedef int create_symref_fn(struct ref_store *ref_store,
- const char *ref_target,
- const char *refs_heads_master,
- const char *logmsg);
typedef int rename_ref_fn(struct ref_store *ref_store,
const char *oldref, const char *newref,
const char *logmsg);
@@ -676,7 +686,6 @@ struct ref_storage_be {
ref_transaction_commit_fn *initial_transaction_commit;
pack_refs_fn *pack_refs;
- create_symref_fn *create_symref;
rename_ref_fn *rename_ref;
copy_ref_fn *copy_ref;
@@ -735,4 +744,25 @@ void base_ref_store_init(struct ref_store *refs, struct repository *repo,
*/
struct ref_store *maybe_debug_wrap_ref_store(const char *gitdir, struct ref_store *store);
+/*
+ * Return the refname under which update was originally requested.
+ */
+const char *ref_update_original_update_refname(struct ref_update *update);
+
+/*
+ * Helper function to check if the new value is null, this
+ * takes into consideration that the update could be a regular
+ * ref or a symbolic ref.
+ */
+int ref_update_has_null_new_value(struct ref_update *update);
+
+/*
+ * Check whether the old_target values stored in update are consistent
+ * with the referent, which is the symbolic reference's current value.
+ * If everything is OK, return 0; otherwise, write an error message to
+ * err and return -1.
+ */
+int ref_update_check_old_target(const char *referent, struct ref_update *update,
+ struct strbuf *err);
+
#endif /* REFS_REFS_INTERNAL_H */
diff --git a/refs/reftable-backend.c b/refs/reftable-backend.c
index 1cda48c504..1226e40be0 100644
--- a/refs/reftable-backend.c
+++ b/refs/reftable-backend.c
@@ -1,6 +1,7 @@
#include "../git-compat-util.h"
#include "../abspath.h"
#include "../chdir-notify.h"
+#include "../config.h"
#include "../environment.h"
#include "../gettext.h"
#include "../hash.h"
@@ -15,7 +16,6 @@
#include "../reftable/reftable-record.h"
#include "../reftable/reftable-error.h"
#include "../reftable/reftable-iterator.h"
-#include "../reftable/reftable-merged.h"
#include "../setup.h"
#include "../strmap.h"
#include "parse.h"
@@ -129,7 +129,7 @@ static struct reftable_stack *stack_for(struct reftable_ref_store *store,
store->base.repo->commondir, wtname_buf.buf);
store->err = reftable_new_stack(&stack, wt_dir.buf,
- store->write_options);
+ &store->write_options);
assert(store->err != REFTABLE_API_ERROR);
strmap_put(&store->worktree_stacks, wtname_buf.buf, stack);
}
@@ -172,32 +172,30 @@ static int should_write_log(struct ref_store *refs, const char *refname)
}
}
-static void fill_reftable_log_record(struct reftable_log_record *log)
+static void fill_reftable_log_record(struct reftable_log_record *log, const struct ident_split *split)
{
- const char *info = git_committer_info(0);
- struct ident_split split = {0};
+ const char *tz_begin;
int sign = 1;
- if (split_ident_line(&split, info, strlen(info)))
- BUG("failed splitting committer info");
-
reftable_log_record_release(log);
log->value_type = REFTABLE_LOG_UPDATE;
log->value.update.name =
- xstrndup(split.name_begin, split.name_end - split.name_begin);
+ xstrndup(split->name_begin, split->name_end - split->name_begin);
log->value.update.email =
- xstrndup(split.mail_begin, split.mail_end - split.mail_begin);
- log->value.update.time = atol(split.date_begin);
- if (*split.tz_begin == '-') {
+ xstrndup(split->mail_begin, split->mail_end - split->mail_begin);
+ log->value.update.time = atol(split->date_begin);
+
+ tz_begin = split->tz_begin;
+ if (*tz_begin == '-') {
sign = -1;
- split.tz_begin++;
+ tz_begin++;
}
- if (*split.tz_begin == '+') {
+ if (*tz_begin == '+') {
sign = 1;
- split.tz_begin++;
+ tz_begin++;
}
- log->value.update.tz_offset = sign * atoi(split.tz_begin);
+ log->value.update.tz_offset = sign * atoi(tz_begin);
}
static int read_ref_without_reload(struct reftable_stack *stack,
@@ -230,6 +228,34 @@ done:
return ret;
}
+static int reftable_be_config(const char *var, const char *value,
+ const struct config_context *ctx,
+ void *_opts)
+{
+ struct reftable_write_options *opts = _opts;
+
+ if (!strcmp(var, "reftable.blocksize")) {
+ unsigned long block_size = git_config_ulong(var, value, ctx->kvi);
+ if (block_size > 16777215)
+ die("reftable block size cannot exceed 16MB");
+ opts->block_size = block_size;
+ } else if (!strcmp(var, "reftable.restartinterval")) {
+ unsigned long restart_interval = git_config_ulong(var, value, ctx->kvi);
+ if (restart_interval > UINT16_MAX)
+ die("reftable block size cannot exceed %u", (unsigned)UINT16_MAX);
+ opts->restart_interval = restart_interval;
+ } else if (!strcmp(var, "reftable.indexobjects")) {
+ opts->skip_index_objects = !git_config_bool(var, value);
+ } else if (!strcmp(var, "reftable.geometricfactor")) {
+ unsigned long factor = git_config_ulong(var, value, ctx->kvi);
+ if (factor > UINT8_MAX)
+ die("reftable geometric factor cannot exceed %u", (unsigned)UINT8_MAX);
+ opts->auto_compaction_factor = factor;
+ }
+
+ return 0;
+}
+
static struct ref_store *reftable_be_init(struct repository *repo,
const char *gitdir,
unsigned int store_flags)
@@ -245,12 +271,24 @@ static struct ref_store *reftable_be_init(struct repository *repo,
base_ref_store_init(&refs->base, repo, gitdir, &refs_be_reftable);
strmap_init(&refs->worktree_stacks);
refs->store_flags = store_flags;
- refs->write_options.block_size = 4096;
+
refs->write_options.hash_id = repo->hash_algo->format_id;
refs->write_options.default_permissions = calc_shared_perm(0666 & ~mask);
refs->write_options.disable_auto_compact =
!git_env_bool("GIT_TEST_REFTABLE_AUTOCOMPACTION", 1);
+ git_config(reftable_be_config, &refs->write_options);
+
+ /*
+ * It is somewhat unfortunate that we have to mirror the default block
+ * size of the reftable library here. But given that the write options
+ * wouldn't be updated by the library here, and given that we require
+ * the proper block size to trim reflog message so that they fit, we
+ * must set up a proper value here.
+ */
+ if (!refs->write_options.block_size)
+ refs->write_options.block_size = 4096;
+
/*
* Set up the main reftable stack that is hosted in GIT_COMMON_DIR.
* This stack contains both the shared and the main worktree refs.
@@ -265,7 +303,7 @@ static struct ref_store *reftable_be_init(struct repository *repo,
}
strbuf_addstr(&path, "/reftable");
refs->err = reftable_new_stack(&refs->main_stack, path.buf,
- refs->write_options);
+ &refs->write_options);
if (refs->err)
goto done;
@@ -282,7 +320,7 @@ static struct ref_store *reftable_be_init(struct repository *repo,
strbuf_addf(&path, "%s/reftable", gitdir);
refs->err = reftable_new_stack(&refs->worktree_stack, path.buf,
- refs->write_options);
+ &refs->write_options);
if (refs->err)
goto done;
}
@@ -356,8 +394,7 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
*/
if (!starts_with(iter->ref.refname, "refs/") &&
!(iter->flags & DO_FOR_EACH_INCLUDE_ROOT_REFS &&
- (is_pseudoref(&iter->refs->base, iter->ref.refname) ||
- is_headref(&iter->refs->base, iter->ref.refname)))) {
+ is_root_ref(&iter->refs->base, iter->ref.refname))) {
continue;
}
@@ -464,7 +501,6 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
const char *prefix,
int flags)
{
- struct reftable_merged_table *merged_table;
struct reftable_ref_iterator *iter;
int ret;
@@ -484,9 +520,8 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
if (ret)
goto done;
- merged_table = reftable_stack_merged_table(stack);
-
- ret = reftable_merged_table_seek_ref(merged_table, &iter->iter, prefix);
+ reftable_stack_init_ref_iterator(stack, &iter->iter);
+ ret = reftable_iterator_seek_ref(&iter->iter, prefix);
if (ret)
goto done;
@@ -581,16 +616,6 @@ static int reftable_be_read_symbolic_ref(struct ref_store *ref_store,
return ret;
}
-/*
- * Return the refname under which update was originally requested.
- */
-static const char *original_update_refname(struct ref_update *update)
-{
- while (update->parent_update)
- update = update->parent_update;
- return update->refname;
-}
-
struct reftable_transaction_update {
struct ref_update *update;
struct object_id current_oid;
@@ -829,7 +854,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
new_update = ref_transaction_add_update(
transaction, "HEAD",
u->flags | REF_LOG_ONLY | REF_NO_DEREF,
- &u->new_oid, &u->old_oid, u->msg);
+ &u->new_oid, &u->old_oid, NULL, NULL, u->msg);
string_list_insert(&affected_refnames, new_update->refname);
}
@@ -856,7 +881,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
* There is no need to write the reference deletion
* when the reference in question doesn't exist.
*/
- if (u->flags & REF_HAVE_NEW && !is_null_oid(&u->new_oid)) {
+ if ((u->flags & REF_HAVE_NEW) && !ref_update_has_null_new_value(u)) {
ret = queue_transaction_update(refs, tx_data, u,
&current_oid, err);
if (ret)
@@ -869,7 +894,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
/* The reference does not exist, but we expected it to. */
strbuf_addf(err, _("cannot lock ref '%s': "
"unable to resolve reference '%s'"),
- original_update_refname(u), u->refname);
+ ref_update_original_update_refname(u), u->refname);
ret = -1;
goto done;
}
@@ -907,8 +932,10 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
* intertwined with the locking in files-backend.c.
*/
new_update = ref_transaction_add_update(
- transaction, referent.buf, new_flags,
- &u->new_oid, &u->old_oid, u->msg);
+ transaction, referent.buf, new_flags,
+ &u->new_oid, &u->old_oid, u->new_target,
+ u->old_target, u->msg);
+
new_update->parent_update = u;
/*
@@ -938,20 +965,25 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
* individual refs. But the error messages match what the files
* backend returns, which keeps our tests happy.
*/
- if (u->flags & REF_HAVE_OLD && !oideq(&current_oid, &u->old_oid)) {
+ if (u->old_target) {
+ if (ref_update_check_old_target(referent.buf, u, err)) {
+ ret = -1;
+ goto done;
+ }
+ } else if ((u->flags & REF_HAVE_OLD) && !oideq(&current_oid, &u->old_oid)) {
if (is_null_oid(&u->old_oid))
strbuf_addf(err, _("cannot lock ref '%s': "
- "reference already exists"),
- original_update_refname(u));
+ "reference already exists"),
+ ref_update_original_update_refname(u));
else if (is_null_oid(&current_oid))
strbuf_addf(err, _("cannot lock ref '%s': "
- "reference is missing but expected %s"),
- original_update_refname(u),
+ "reference is missing but expected %s"),
+ ref_update_original_update_refname(u),
oid_to_hex(&u->old_oid));
else
strbuf_addf(err, _("cannot lock ref '%s': "
- "is at %s but expected %s"),
- original_update_refname(u),
+ "is at %s but expected %s"),
+ ref_update_original_update_refname(u),
oid_to_hex(&current_oid),
oid_to_hex(&u->old_oid));
ret = -1;
@@ -1017,13 +1049,17 @@ static int transaction_update_cmp(const void *a, const void *b)
static int write_transaction_table(struct reftable_writer *writer, void *cb_data)
{
struct write_transaction_table_arg *arg = cb_data;
- struct reftable_merged_table *mt =
- reftable_stack_merged_table(arg->stack);
uint64_t ts = reftable_stack_next_update_index(arg->stack);
struct reftable_log_record *logs = NULL;
+ struct ident_split committer_ident = {0};
size_t logs_nr = 0, logs_alloc = 0, i;
+ const char *committer_info;
int ret = 0;
+ committer_info = git_committer_info(0);
+ if (split_ident_line(&committer_ident, committer_info, strlen(committer_info)))
+ BUG("failed splitting committer info");
+
QSORT(arg->updates, arg->updates_nr, transaction_update_cmp);
reftable_writer_set_limits(writer, ts, ts);
@@ -1043,10 +1079,14 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
* - `core.logAllRefUpdates` tells us to create the reflog for
* the given ref.
*/
- if (u->flags & REF_HAVE_NEW && !(u->type & REF_ISSYMREF) && is_null_oid(&u->new_oid)) {
+ if ((u->flags & REF_HAVE_NEW) &&
+ !(u->type & REF_ISSYMREF) &&
+ ref_update_has_null_new_value(u)) {
struct reftable_log_record log = {0};
struct reftable_iterator it = {0};
+ reftable_stack_init_log_iterator(arg->stack, &it);
+
/*
* When deleting refs we also delete all reflog entries
* with them. While it is not strictly required to
@@ -1056,7 +1096,7 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
* Unfortunately, we have no better way than to delete
* all reflog entries one by one.
*/
- ret = reftable_merged_table_seek_log(mt, &it, u->refname);
+ ret = reftable_iterator_seek_log(&it, u->refname);
while (ret == 0) {
struct reftable_log_record *tombstone;
@@ -1084,24 +1124,52 @@ static int write_transaction_table(struct reftable_writer *writer, void *cb_data
(u->flags & REF_FORCE_CREATE_REFLOG ||
should_write_log(&arg->refs->base, u->refname))) {
struct reftable_log_record *log;
+ int create_reflog = 1;
+
+ if (u->new_target) {
+ if (!refs_resolve_ref_unsafe(&arg->refs->base, u->new_target,
+ RESOLVE_REF_READING, &u->new_oid, NULL)) {
+ /*
+ * TODO: currently we skip creating reflogs for dangling
+ * symref updates. It would be nice to capture this as
+ * zero oid updates however.
+ */
+ create_reflog = 0;
+ }
+ }
- ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
- log = &logs[logs_nr++];
- memset(log, 0, sizeof(*log));
-
- fill_reftable_log_record(log);
- log->update_index = ts;
- log->refname = xstrdup(u->refname);
- memcpy(log->value.update.new_hash, u->new_oid.hash, GIT_MAX_RAWSZ);
- memcpy(log->value.update.old_hash, tx_update->current_oid.hash, GIT_MAX_RAWSZ);
- log->value.update.message =
- xstrndup(u->msg, arg->refs->write_options.block_size / 2);
+ if (create_reflog) {
+ ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
+ log = &logs[logs_nr++];
+ memset(log, 0, sizeof(*log));
+
+ fill_reftable_log_record(log, &committer_ident);
+ log->update_index = ts;
+ log->refname = xstrdup(u->refname);
+ memcpy(log->value.update.new_hash,
+ u->new_oid.hash, GIT_MAX_RAWSZ);
+ memcpy(log->value.update.old_hash,
+ tx_update->current_oid.hash, GIT_MAX_RAWSZ);
+ log->value.update.message =
+ xstrndup(u->msg, arg->refs->write_options.block_size / 2);
+ }
}
if (u->flags & REF_LOG_ONLY)
continue;
- if (u->flags & REF_HAVE_NEW && is_null_oid(&u->new_oid)) {
+ if (u->new_target) {
+ struct reftable_ref_record ref = {
+ .refname = (char *)u->refname,
+ .value_type = REFTABLE_REF_SYMREF,
+ .value.symref = (char *)u->new_target,
+ .update_index = ts,
+ };
+
+ ret = reftable_writer_add_ref(writer, &ref);
+ if (ret < 0)
+ goto done;
+ } else if ((u->flags & REF_HAVE_NEW) && ref_update_has_null_new_value(u)) {
struct reftable_ref_record ref = {
.refname = (char *)u->refname,
.update_index = ts,
@@ -1227,96 +1295,12 @@ out:
struct write_create_symref_arg {
struct reftable_ref_store *refs;
struct reftable_stack *stack;
+ struct strbuf *err;
const char *refname;
const char *target;
const char *logmsg;
};
-static int write_create_symref_table(struct reftable_writer *writer, void *cb_data)
-{
- struct write_create_symref_arg *create = cb_data;
- uint64_t ts = reftable_stack_next_update_index(create->stack);
- struct reftable_ref_record ref = {
- .refname = (char *)create->refname,
- .value_type = REFTABLE_REF_SYMREF,
- .value.symref = (char *)create->target,
- .update_index = ts,
- };
- struct reftable_log_record log = {0};
- struct object_id new_oid;
- struct object_id old_oid;
- int ret;
-
- reftable_writer_set_limits(writer, ts, ts);
-
- ret = reftable_writer_add_ref(writer, &ref);
- if (ret)
- return ret;
-
- /*
- * Note that it is important to try and resolve the reference before we
- * write the log entry. This is because `should_write_log()` will munge
- * `core.logAllRefUpdates`, which is undesirable when we create a new
- * repository because it would be written into the config. As HEAD will
- * not resolve for new repositories this ordering will ensure that this
- * never happens.
- */
- if (!create->logmsg ||
- !refs_resolve_ref_unsafe(&create->refs->base, create->target,
- RESOLVE_REF_READING, &new_oid, NULL) ||
- !should_write_log(&create->refs->base, create->refname))
- return 0;
-
- fill_reftable_log_record(&log);
- log.refname = xstrdup(create->refname);
- log.update_index = ts;
- log.value.update.message = xstrndup(create->logmsg,
- create->refs->write_options.block_size / 2);
- memcpy(log.value.update.new_hash, new_oid.hash, GIT_MAX_RAWSZ);
- if (refs_resolve_ref_unsafe(&create->refs->base, create->refname,
- RESOLVE_REF_READING, &old_oid, NULL))
- memcpy(log.value.update.old_hash, old_oid.hash, GIT_MAX_RAWSZ);
-
- ret = reftable_writer_add_log(writer, &log);
- reftable_log_record_release(&log);
- return ret;
-}
-
-static int reftable_be_create_symref(struct ref_store *ref_store,
- const char *refname,
- const char *target,
- const char *logmsg)
-{
- struct reftable_ref_store *refs =
- reftable_be_downcast(ref_store, REF_STORE_WRITE, "create_symref");
- struct reftable_stack *stack = stack_for(refs, refname, &refname);
- struct write_create_symref_arg arg = {
- .refs = refs,
- .stack = stack,
- .refname = refname,
- .target = target,
- .logmsg = logmsg,
- };
- int ret;
-
- ret = refs->err;
- if (ret < 0)
- goto done;
-
- ret = reftable_stack_reload(stack);
- if (ret)
- goto done;
-
- ret = reftable_stack_add(stack, &write_create_symref_table, &arg);
-
-done:
- assert(ret != REFTABLE_API_ERROR);
- if (ret)
- error("unable to write symref for %s: %s", refname,
- reftable_error_str(ret));
- return ret;
-}
-
struct write_copy_arg {
struct reftable_ref_store *refs;
struct reftable_stack *stack;
@@ -1330,15 +1314,20 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
{
struct write_copy_arg *arg = cb_data;
uint64_t deletion_ts, creation_ts;
- struct reftable_merged_table *mt = reftable_stack_merged_table(arg->stack);
struct reftable_ref_record old_ref = {0}, refs[2] = {0};
struct reftable_log_record old_log = {0}, *logs = NULL;
struct reftable_iterator it = {0};
struct string_list skip = STRING_LIST_INIT_NODUP;
+ struct ident_split committer_ident = {0};
struct strbuf errbuf = STRBUF_INIT;
size_t logs_nr = 0, logs_alloc = 0, i;
+ const char *committer_info;
int ret;
+ committer_info = git_committer_info(0);
+ if (split_ident_line(&committer_ident, committer_info, strlen(committer_info)))
+ BUG("failed splitting committer info");
+
if (reftable_stack_read_ref(arg->stack, arg->oldname, &old_ref)) {
ret = error(_("refname %s not found"), arg->oldname);
goto done;
@@ -1361,7 +1350,8 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
/*
* Verify that the new refname is available.
*/
- string_list_insert(&skip, arg->oldname);
+ if (arg->delete_old)
+ string_list_insert(&skip, arg->oldname);
ret = refs_verify_refname_available(&arg->refs->base, arg->newname,
NULL, &skip, &errbuf);
if (ret < 0) {
@@ -1412,7 +1402,7 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
memset(&logs[logs_nr], 0, sizeof(logs[logs_nr]));
- fill_reftable_log_record(&logs[logs_nr]);
+ fill_reftable_log_record(&logs[logs_nr], &committer_ident);
logs[logs_nr].refname = (char *)arg->newname;
logs[logs_nr].update_index = deletion_ts;
logs[logs_nr].value.update.message =
@@ -1444,7 +1434,7 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
*/
ALLOC_GROW(logs, logs_nr + 1, logs_alloc);
memset(&logs[logs_nr], 0, sizeof(logs[logs_nr]));
- fill_reftable_log_record(&logs[logs_nr]);
+ fill_reftable_log_record(&logs[logs_nr], &committer_ident);
logs[logs_nr].refname = (char *)arg->newname;
logs[logs_nr].update_index = creation_ts;
logs[logs_nr].value.update.message =
@@ -1457,7 +1447,8 @@ static int write_copy_table(struct reftable_writer *writer, void *cb_data)
* copy over all log entries from the old reflog. Last but not least,
* when renaming we also have to delete all the old reflog entries.
*/
- ret = reftable_merged_table_seek_log(mt, &it, arg->oldname);
+ reftable_stack_init_log_iterator(arg->stack, &it);
+ ret = reftable_iterator_seek_log(&it, arg->oldname);
if (ret < 0)
goto done;
@@ -1663,7 +1654,6 @@ static struct ref_iterator_vtable reftable_reflog_iterator_vtable = {
static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftable_ref_store *refs,
struct reftable_stack *stack)
{
- struct reftable_merged_table *merged_table;
struct reftable_reflog_iterator *iter;
int ret;
@@ -1680,9 +1670,8 @@ static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftabl
if (ret < 0)
goto done;
- merged_table = reftable_stack_merged_table(stack);
-
- ret = reftable_merged_table_seek_log(merged_table, &iter->iter, "");
+ reftable_stack_init_log_iterator(stack, &iter->iter);
+ ret = reftable_iterator_seek_log(&iter->iter, "");
if (ret < 0)
goto done;
@@ -1740,7 +1729,6 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
struct reftable_ref_store *refs =
reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent_reverse");
struct reftable_stack *stack = stack_for(refs, refname, &refname);
- struct reftable_merged_table *mt = NULL;
struct reftable_log_record log = {0};
struct reftable_iterator it = {0};
int ret;
@@ -1748,8 +1736,8 @@ static int reftable_be_for_each_reflog_ent_reverse(struct ref_store *ref_store,
if (refs->err < 0)
return refs->err;
- mt = reftable_stack_merged_table(stack);
- ret = reftable_merged_table_seek_log(mt, &it, refname);
+ reftable_stack_init_log_iterator(stack, &it);
+ ret = reftable_iterator_seek_log(&it, refname);
while (!ret) {
ret = reftable_iterator_next_log(&it, &log);
if (ret < 0)
@@ -1777,7 +1765,6 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
struct reftable_ref_store *refs =
reftable_be_downcast(ref_store, REF_STORE_READ, "for_each_reflog_ent");
struct reftable_stack *stack = stack_for(refs, refname, &refname);
- struct reftable_merged_table *mt = NULL;
struct reftable_log_record *logs = NULL;
struct reftable_iterator it = {0};
size_t logs_alloc = 0, logs_nr = 0, i;
@@ -1786,8 +1773,8 @@ static int reftable_be_for_each_reflog_ent(struct ref_store *ref_store,
if (refs->err < 0)
return refs->err;
- mt = reftable_stack_merged_table(stack);
- ret = reftable_merged_table_seek_log(mt, &it, refname);
+ reftable_stack_init_log_iterator(stack, &it);
+ ret = reftable_iterator_seek_log(&it, refname);
while (!ret) {
struct reftable_log_record log = {0};
@@ -1824,7 +1811,6 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store,
struct reftable_ref_store *refs =
reftable_be_downcast(ref_store, REF_STORE_READ, "reflog_exists");
struct reftable_stack *stack = stack_for(refs, refname, &refname);
- struct reftable_merged_table *mt = reftable_stack_merged_table(stack);
struct reftable_log_record log = {0};
struct reftable_iterator it = {0};
int ret;
@@ -1837,7 +1823,8 @@ static int reftable_be_reflog_exists(struct ref_store *ref_store,
if (ret < 0)
goto done;
- ret = reftable_merged_table_seek_log(mt, &it, refname);
+ reftable_stack_init_log_iterator(stack, &it);
+ ret = reftable_iterator_seek_log(&it, refname);
if (ret < 0)
goto done;
@@ -1935,8 +1922,6 @@ struct write_reflog_delete_arg {
static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_data)
{
struct write_reflog_delete_arg *arg = cb_data;
- struct reftable_merged_table *mt =
- reftable_stack_merged_table(arg->stack);
struct reftable_log_record log = {0}, tombstone = {0};
struct reftable_iterator it = {0};
uint64_t ts = reftable_stack_next_update_index(arg->stack);
@@ -1944,12 +1929,14 @@ static int write_reflog_delete_table(struct reftable_writer *writer, void *cb_da
reftable_writer_set_limits(writer, ts, ts);
+ reftable_stack_init_log_iterator(arg->stack, &it);
+
/*
* In order to delete a table we need to delete all reflog entries one
* by one. This is inefficient, but the reftable format does not have a
* better marker right now.
*/
- ret = reftable_merged_table_seek_log(mt, &it, arg->refname);
+ ret = reftable_iterator_seek_log(&it, arg->refname);
while (ret == 0) {
ret = reftable_iterator_next_log(&it, &log);
if (ret < 0)
@@ -2085,7 +2072,6 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
struct reftable_ref_store *refs =
reftable_be_downcast(ref_store, REF_STORE_WRITE, "reflog_expire");
struct reftable_stack *stack = stack_for(refs, refname, &refname);
- struct reftable_merged_table *mt = reftable_stack_merged_table(stack);
struct reftable_log_record *logs = NULL;
struct reftable_log_record *rewritten = NULL;
struct reftable_ref_record ref_record = {0};
@@ -2104,7 +2090,9 @@ static int reftable_be_reflog_expire(struct ref_store *ref_store,
if (ret < 0)
goto done;
- ret = reftable_merged_table_seek_log(mt, &it, refname);
+ reftable_stack_init_log_iterator(stack, &it);
+
+ ret = reftable_iterator_seek_log(&it, refname);
if (ret < 0)
goto done;
@@ -2224,7 +2212,6 @@ struct ref_storage_be refs_be_reftable = {
.initial_transaction_commit = reftable_be_initial_transaction_commit,
.pack_refs = reftable_be_pack_refs,
- .create_symref = reftable_be_create_symref,
.rename_ref = reftable_be_rename_ref,
.copy_ref = reftable_be_copy_ref,
diff --git a/reftable/block.c b/reftable/block.c
index 3e87460cba..00030eee06 100644
--- a/reftable/block.c
+++ b/reftable/block.c
@@ -76,6 +76,10 @@ void block_writer_init(struct block_writer *bw, uint8_t typ, uint8_t *buf,
bw->entries = 0;
bw->restart_len = 0;
bw->last_key.len = 0;
+ if (!bw->zstream) {
+ REFTABLE_CALLOC_ARRAY(bw->zstream, 1);
+ deflateInit(bw->zstream, 9);
+ }
}
uint8_t block_writer_type(struct block_writer *bw)
@@ -139,39 +143,52 @@ int block_writer_finish(struct block_writer *w)
w->next += 2;
put_be24(w->buf + 1 + w->header_off, w->next);
+ /*
+ * Log records are stored zlib-compressed. Note that the compression
+ * also spans over the restart points we have just written.
+ */
if (block_writer_type(w) == BLOCK_TYPE_LOG) {
int block_header_skip = 4 + w->header_off;
- uLongf src_len = w->next - block_header_skip;
- uLongf dest_cap = src_len * 1.001 + 12;
- uint8_t *compressed;
-
- REFTABLE_ALLOC_ARRAY(compressed, dest_cap);
-
- while (1) {
- uLongf out_dest_len = dest_cap;
- int zresult = compress2(compressed, &out_dest_len,
- w->buf + block_header_skip,
- src_len, 9);
- if (zresult == Z_BUF_ERROR && dest_cap < LONG_MAX) {
- dest_cap *= 2;
- compressed =
- reftable_realloc(compressed, dest_cap);
- if (compressed)
- continue;
- }
-
- if (Z_OK != zresult) {
- reftable_free(compressed);
- return REFTABLE_ZLIB_ERROR;
- }
-
- memcpy(w->buf + block_header_skip, compressed,
- out_dest_len);
- w->next = out_dest_len + block_header_skip;
- reftable_free(compressed);
- break;
- }
+ uLongf src_len = w->next - block_header_skip, compressed_len;
+ int ret;
+
+ ret = deflateReset(w->zstream);
+ if (ret != Z_OK)
+ return REFTABLE_ZLIB_ERROR;
+
+ /*
+ * Precompute the upper bound of how many bytes the compressed
+ * data may end up with. Combined with `Z_FINISH`, `deflate()`
+ * is guaranteed to return `Z_STREAM_END`.
+ */
+ compressed_len = deflateBound(w->zstream, src_len);
+ REFTABLE_ALLOC_GROW(w->compressed, compressed_len, w->compressed_cap);
+
+ w->zstream->next_out = w->compressed;
+ w->zstream->avail_out = compressed_len;
+ w->zstream->next_in = w->buf + block_header_skip;
+ w->zstream->avail_in = src_len;
+
+ /*
+ * We want to perform all decompression in a single step, which
+ * is why we can pass Z_FINISH here. As we have precomputed the
+ * deflated buffer's size via `deflateBound()` this function is
+ * guaranteed to succeed according to the zlib documentation.
+ */
+ ret = deflate(w->zstream, Z_FINISH);
+ if (ret != Z_STREAM_END)
+ return REFTABLE_ZLIB_ERROR;
+
+ /*
+ * Overwrite the uncompressed data we have already written and
+ * adjust the `next` pointer to point right after the
+ * compressed data.
+ */
+ memcpy(w->buf + block_header_skip, w->compressed,
+ w->zstream->total_out);
+ w->next = w->zstream->total_out + block_header_skip;
}
+
return w->next;
}
@@ -309,9 +326,9 @@ int block_reader_first_key(const struct block_reader *br, struct strbuf *key)
return 0;
}
-static uint32_t block_reader_restart_offset(const struct block_reader *br, int i)
+static uint32_t block_reader_restart_offset(const struct block_reader *br, size_t idx)
{
- return get_be24(br->restart_bytes + 3 * i);
+ return get_be24(br->restart_bytes + 3 * idx);
}
void block_iter_seek_start(struct block_iter *it, const struct block_reader *br)
@@ -514,7 +531,10 @@ done:
void block_writer_release(struct block_writer *bw)
{
+ deflateEnd(bw->zstream);
+ FREE_AND_NULL(bw->zstream);
FREE_AND_NULL(bw->restarts);
+ FREE_AND_NULL(bw->compressed);
strbuf_release(&bw->last_key);
/* the block is not owned. */
}
diff --git a/reftable/block.h b/reftable/block.h
index ea4384a7e2..1c8f25ee6e 100644
--- a/reftable/block.h
+++ b/reftable/block.h
@@ -18,6 +18,10 @@ https://developers.google.com/open-source/licenses/bsd
* allocation overhead.
*/
struct block_writer {
+ z_stream *zstream;
+ unsigned char *compressed;
+ size_t compressed_cap;
+
uint8_t *buf;
uint32_t block_size;
@@ -25,7 +29,7 @@ struct block_writer {
uint32_t header_off;
/* How often to restart keys. */
- int restart_interval;
+ uint16_t restart_interval;
int hash_size;
/* Offset of next uint8_t to write. */
diff --git a/reftable/constants.h b/reftable/constants.h
index 5eee72c4c1..f6beb843eb 100644
--- a/reftable/constants.h
+++ b/reftable/constants.h
@@ -17,5 +17,6 @@ https://developers.google.com/open-source/licenses/bsd
#define MAX_RESTARTS ((1 << 16) - 1)
#define DEFAULT_BLOCK_SIZE 4096
+#define DEFAULT_GEOMETRIC_FACTOR 2
#endif
diff --git a/reftable/dump.c b/reftable/dump.c
index 26e0393c7d..41abbb8ecf 100644
--- a/reftable/dump.c
+++ b/reftable/dump.c
@@ -27,9 +27,9 @@ https://developers.google.com/open-source/licenses/bsd
static int compact_stack(const char *stackdir)
{
struct reftable_stack *stack = NULL;
- struct reftable_write_options cfg = { 0 };
+ struct reftable_write_options opts = { 0 };
- int err = reftable_new_stack(&stack, stackdir, cfg);
+ int err = reftable_new_stack(&stack, stackdir, &opts);
if (err < 0)
goto done;
@@ -48,6 +48,7 @@ static void print_help(void)
printf("usage: dump [-cst] arg\n\n"
"options: \n"
" -c compact\n"
+ " -b dump blocks\n"
" -t dump table\n"
" -s dump stack\n"
" -6 sha256 hash format\n"
@@ -58,6 +59,7 @@ static void print_help(void)
int reftable_dump_main(int argc, char *const *argv)
{
int err = 0;
+ int opt_dump_blocks = 0;
int opt_dump_table = 0;
int opt_dump_stack = 0;
int opt_compact = 0;
@@ -67,6 +69,8 @@ int reftable_dump_main(int argc, char *const *argv)
for (; argc > 1; argv++, argc--)
if (*argv[1] != '-')
break;
+ else if (!strcmp("-b", argv[1]))
+ opt_dump_blocks = 1;
else if (!strcmp("-t", argv[1]))
opt_dump_table = 1;
else if (!strcmp("-6", argv[1]))
@@ -88,7 +92,9 @@ int reftable_dump_main(int argc, char *const *argv)
arg = argv[1];
- if (opt_dump_table) {
+ if (opt_dump_blocks) {
+ err = reftable_reader_print_blocks(arg);
+ } else if (opt_dump_table) {
err = reftable_reader_print_file(arg);
} else if (opt_dump_stack) {
err = reftable_stack_print_directory(arg, opt_hash_id);
diff --git a/reftable/error.c b/reftable/error.c
index cfb7a0fda4..a25f28a43e 100644
--- a/reftable/error.c
+++ b/reftable/error.c
@@ -27,8 +27,6 @@ const char *reftable_error_str(int err)
return "misuse of the reftable API";
case REFTABLE_ZLIB_ERROR:
return "zlib failure";
- case REFTABLE_NAME_CONFLICT:
- return "file/directory conflict";
case REFTABLE_EMPTY_TABLE_ERROR:
return "wrote empty table";
case REFTABLE_REFNAME_ERROR:
diff --git a/reftable/generic.c b/reftable/generic.c
index b9f1c7c18a..28ae26145e 100644
--- a/reftable/generic.c
+++ b/reftable/generic.c
@@ -12,32 +12,66 @@ https://developers.google.com/open-source/licenses/bsd
#include "reftable-iterator.h"
#include "reftable-generic.h"
-int reftable_table_seek_ref(struct reftable_table *tab,
- struct reftable_iterator *it, const char *name)
+void table_init_iter(struct reftable_table *tab,
+ struct reftable_iterator *it,
+ uint8_t typ)
{
- struct reftable_record rec = { .type = BLOCK_TYPE_REF,
- .u.ref = {
- .refname = (char *)name,
- } };
- return tab->ops->seek_record(tab->table_arg, it, &rec);
+
+ tab->ops->init_iter(tab->table_arg, it, typ);
+}
+
+void reftable_table_init_ref_iter(struct reftable_table *tab,
+ struct reftable_iterator *it)
+{
+ table_init_iter(tab, it, BLOCK_TYPE_REF);
+}
+
+void reftable_table_init_log_iter(struct reftable_table *tab,
+ struct reftable_iterator *it)
+{
+ table_init_iter(tab, it, BLOCK_TYPE_LOG);
+}
+
+int reftable_iterator_seek_ref(struct reftable_iterator *it,
+ const char *name)
+{
+ struct reftable_record want = {
+ .type = BLOCK_TYPE_REF,
+ .u.ref = {
+ .refname = (char *)name,
+ },
+ };
+ return it->ops->seek(it->iter_arg, &want);
+}
+
+int reftable_iterator_seek_log_at(struct reftable_iterator *it,
+ const char *name, uint64_t update_index)
+{
+ struct reftable_record want = {
+ .type = BLOCK_TYPE_LOG,
+ .u.log = {
+ .refname = (char *)name,
+ .update_index = update_index,
+ },
+ };
+ return it->ops->seek(it->iter_arg, &want);
}
-int reftable_table_seek_log(struct reftable_table *tab,
- struct reftable_iterator *it, const char *name)
+int reftable_iterator_seek_log(struct reftable_iterator *it,
+ const char *name)
{
- struct reftable_record rec = { .type = BLOCK_TYPE_LOG,
- .u.log = {
- .refname = (char *)name,
- .update_index = ~((uint64_t)0),
- } };
- return tab->ops->seek_record(tab->table_arg, it, &rec);
+ return reftable_iterator_seek_log_at(it, name, ~((uint64_t) 0));
}
int reftable_table_read_ref(struct reftable_table *tab, const char *name,
struct reftable_ref_record *ref)
{
struct reftable_iterator it = { NULL };
- int err = reftable_table_seek_ref(tab, &it, name);
+ int err;
+
+ reftable_table_init_ref_iter(tab, &it);
+
+ err = reftable_iterator_seek_ref(&it, name);
if (err)
goto done;
@@ -62,10 +96,13 @@ int reftable_table_print(struct reftable_table *tab) {
struct reftable_ref_record ref = { NULL };
struct reftable_log_record log = { NULL };
uint32_t hash_id = reftable_table_hash_id(tab);
- int err = reftable_table_seek_ref(tab, &it, "");
- if (err < 0) {
+ int err;
+
+ reftable_table_init_ref_iter(tab, &it);
+
+ err = reftable_iterator_seek_ref(&it, "");
+ if (err < 0)
return err;
- }
while (1) {
err = reftable_iterator_next_ref(&it, &ref);
@@ -80,10 +117,12 @@ int reftable_table_print(struct reftable_table *tab) {
reftable_iterator_destroy(&it);
reftable_ref_record_release(&ref);
- err = reftable_table_seek_log(tab, &it, "");
- if (err < 0) {
+ reftable_table_init_log_iter(tab, &it);
+
+ err = reftable_iterator_seek_log(&it, "");
+ if (err < 0)
return err;
- }
+
while (1) {
err = reftable_iterator_next_log(&it, &log);
if (err > 0) {
@@ -152,11 +191,21 @@ int reftable_iterator_next_log(struct reftable_iterator *it,
return err;
}
+int iterator_seek(struct reftable_iterator *it, struct reftable_record *want)
+{
+ return it->ops->seek(it->iter_arg, want);
+}
+
int iterator_next(struct reftable_iterator *it, struct reftable_record *rec)
{
return it->ops->next(it->iter_arg, rec);
}
+static int empty_iterator_seek(void *arg, struct reftable_record *want)
+{
+ return 0;
+}
+
static int empty_iterator_next(void *arg, struct reftable_record *rec)
{
return 1;
@@ -167,6 +216,7 @@ static void empty_iterator_close(void *arg)
}
static struct reftable_iterator_vtable empty_vtable = {
+ .seek = &empty_iterator_seek,
.next = &empty_iterator_next,
.close = &empty_iterator_close,
};
diff --git a/reftable/generic.h b/reftable/generic.h
index 98886a0640..8341fa570e 100644
--- a/reftable/generic.h
+++ b/reftable/generic.h
@@ -14,19 +14,24 @@ https://developers.google.com/open-source/licenses/bsd
/* generic interface to reftables */
struct reftable_table_vtable {
- int (*seek_record)(void *tab, struct reftable_iterator *it,
- struct reftable_record *);
+ void (*init_iter)(void *tab, struct reftable_iterator *it, uint8_t typ);
uint32_t (*hash_id)(void *tab);
uint64_t (*min_update_index)(void *tab);
uint64_t (*max_update_index)(void *tab);
};
+void table_init_iter(struct reftable_table *tab,
+ struct reftable_iterator *it,
+ uint8_t typ);
+
struct reftable_iterator_vtable {
+ int (*seek)(void *iter_arg, struct reftable_record *want);
int (*next)(void *iter_arg, struct reftable_record *rec);
void (*close)(void *iter_arg);
};
void iterator_set_empty(struct reftable_iterator *it);
+int iterator_seek(struct reftable_iterator *it, struct reftable_record *want);
int iterator_next(struct reftable_iterator *it, struct reftable_record *rec);
#endif
diff --git a/reftable/iter.c b/reftable/iter.c
index aa9ac199b1..fddea31e51 100644
--- a/reftable/iter.c
+++ b/reftable/iter.c
@@ -23,6 +23,13 @@ static void filtering_ref_iterator_close(void *iter_arg)
reftable_iterator_destroy(&fri->it);
}
+static int filtering_ref_iterator_seek(void *iter_arg,
+ struct reftable_record *want)
+{
+ struct filtering_ref_iterator *fri = iter_arg;
+ return iterator_seek(&fri->it, want);
+}
+
static int filtering_ref_iterator_next(void *iter_arg,
struct reftable_record *rec)
{
@@ -38,11 +45,11 @@ static int filtering_ref_iterator_next(void *iter_arg,
if (fri->double_check) {
struct reftable_iterator it = { NULL };
- err = reftable_table_seek_ref(&fri->tab, &it,
- ref->refname);
- if (err == 0) {
+ reftable_table_init_ref_iter(&fri->tab, &it);
+
+ err = reftable_iterator_seek_ref(&it, ref->refname);
+ if (err == 0)
err = reftable_iterator_next_ref(&it, ref);
- }
reftable_iterator_destroy(&it);
@@ -73,6 +80,7 @@ static int filtering_ref_iterator_next(void *iter_arg,
}
static struct reftable_iterator_vtable filtering_ref_iterator_vtable = {
+ .seek = &filtering_ref_iterator_seek,
.next = &filtering_ref_iterator_next,
.close = &filtering_ref_iterator_close,
};
@@ -119,6 +127,12 @@ static int indexed_table_ref_iter_next_block(struct indexed_table_ref_iter *it)
return 0;
}
+static int indexed_table_ref_iter_seek(void *p, struct reftable_record *want)
+{
+ BUG("seeking indexed table is not supported");
+ return -1;
+}
+
static int indexed_table_ref_iter_next(void *p, struct reftable_record *rec)
{
struct indexed_table_ref_iter *it = p;
@@ -175,6 +189,7 @@ int new_indexed_table_ref_iter(struct indexed_table_ref_iter **dest,
}
static struct reftable_iterator_vtable indexed_table_ref_iter_vtable = {
+ .seek = &indexed_table_ref_iter_seek,
.next = &indexed_table_ref_iter_next,
.close = &indexed_table_ref_iter_close,
};
diff --git a/reftable/merged.c b/reftable/merged.c
index f85a24c678..0da9dba265 100644
--- a/reftable/merged.c
+++ b/reftable/merged.c
@@ -25,34 +25,25 @@ struct merged_subiter {
struct merged_iter {
struct merged_subiter *subiters;
struct merged_iter_pqueue pq;
- uint32_t hash_id;
size_t stack_len;
- uint8_t typ;
int suppress_deletions;
ssize_t advance_index;
};
-static int merged_iter_init(struct merged_iter *mi)
+static void merged_iter_init(struct merged_iter *mi,
+ struct reftable_merged_table *mt,
+ uint8_t typ)
{
- for (size_t i = 0; i < mi->stack_len; i++) {
- struct pq_entry e = {
- .index = i,
- .rec = &mi->subiters[i].rec,
- };
- int err;
-
- reftable_record_init(&mi->subiters[i].rec, mi->typ);
- err = iterator_next(&mi->subiters[i].iter,
- &mi->subiters[i].rec);
- if (err < 0)
- return err;
- if (err > 0)
- continue;
+ memset(mi, 0, sizeof(*mi));
+ mi->advance_index = -1;
+ mi->suppress_deletions = mt->suppress_deletions;
- merged_iter_pqueue_add(&mi->pq, &e);
+ REFTABLE_CALLOC_ARRAY(mi->subiters, mt->stack_len);
+ for (size_t i = 0; i < mt->stack_len; i++) {
+ reftable_record_init(&mi->subiters[i].rec, typ);
+ table_init_iter(&mt->stack[i], &mi->subiters[i].iter, typ);
}
-
- return 0;
+ mi->stack_len = mt->stack_len;
}
static void merged_iter_close(void *p)
@@ -83,6 +74,27 @@ static int merged_iter_advance_subiter(struct merged_iter *mi, size_t idx)
return 0;
}
+static int merged_iter_seek(struct merged_iter *mi, struct reftable_record *want)
+{
+ int err;
+
+ mi->advance_index = -1;
+
+ for (size_t i = 0; i < mi->stack_len; i++) {
+ err = iterator_seek(&mi->subiters[i].iter, want);
+ if (err < 0)
+ return err;
+ if (err > 0)
+ continue;
+
+ err = merged_iter_advance_subiter(mi, i);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
static int merged_iter_next_entry(struct merged_iter *mi,
struct reftable_record *rec)
{
@@ -148,6 +160,11 @@ static int merged_iter_next_entry(struct merged_iter *mi,
return 0;
}
+static int merged_iter_seek_void(void *it, struct reftable_record *want)
+{
+ return merged_iter_seek(it, want);
+}
+
static int merged_iter_next_void(void *p, struct reftable_record *rec)
{
struct merged_iter *mi = p;
@@ -162,6 +179,7 @@ static int merged_iter_next_void(void *p, struct reftable_record *rec)
}
static struct reftable_iterator_vtable merged_iter_vtable = {
+ .seek = merged_iter_seek_void,
.next = &merged_iter_next_void,
.close = &merged_iter_close,
};
@@ -235,81 +253,13 @@ reftable_merged_table_min_update_index(struct reftable_merged_table *mt)
return mt->min;
}
-static int reftable_table_seek_record(struct reftable_table *tab,
- struct reftable_iterator *it,
- struct reftable_record *rec)
-{
- return tab->ops->seek_record(tab->table_arg, it, rec);
-}
-
-static int merged_table_seek_record(struct reftable_merged_table *mt,
- struct reftable_iterator *it,
- struct reftable_record *rec)
-{
- struct merged_iter merged = {
- .typ = reftable_record_type(rec),
- .hash_id = mt->hash_id,
- .suppress_deletions = mt->suppress_deletions,
- .advance_index = -1,
- };
- struct merged_iter *p;
- int err;
-
- REFTABLE_CALLOC_ARRAY(merged.subiters, mt->stack_len);
- for (size_t i = 0; i < mt->stack_len; i++) {
- err = reftable_table_seek_record(&mt->stack[i],
- &merged.subiters[merged.stack_len].iter, rec);
- if (err < 0)
- goto out;
- if (!err)
- merged.stack_len++;
- }
-
- err = merged_iter_init(&merged);
- if (err < 0)
- goto out;
-
- p = reftable_malloc(sizeof(struct merged_iter));
- *p = merged;
- iterator_from_merged_iter(it, p);
-
-out:
- if (err < 0)
- merged_iter_close(&merged);
- return err;
-}
-
-int reftable_merged_table_seek_ref(struct reftable_merged_table *mt,
- struct reftable_iterator *it,
- const char *name)
-{
- struct reftable_record rec = {
- .type = BLOCK_TYPE_REF,
- .u.ref = {
- .refname = (char *)name,
- },
- };
- return merged_table_seek_record(mt, it, &rec);
-}
-
-int reftable_merged_table_seek_log_at(struct reftable_merged_table *mt,
- struct reftable_iterator *it,
- const char *name, uint64_t update_index)
-{
- struct reftable_record rec = { .type = BLOCK_TYPE_LOG,
- .u.log = {
- .refname = (char *)name,
- .update_index = update_index,
- } };
- return merged_table_seek_record(mt, it, &rec);
-}
-
-int reftable_merged_table_seek_log(struct reftable_merged_table *mt,
- struct reftable_iterator *it,
- const char *name)
+void merged_table_init_iter(struct reftable_merged_table *mt,
+ struct reftable_iterator *it,
+ uint8_t typ)
{
- uint64_t max = ~((uint64_t)0);
- return reftable_merged_table_seek_log_at(mt, it, name, max);
+ struct merged_iter *mi = reftable_malloc(sizeof(*mi));
+ merged_iter_init(mi, mt, typ);
+ iterator_from_merged_iter(it, mi);
}
uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *mt)
@@ -317,11 +267,11 @@ uint32_t reftable_merged_table_hash_id(struct reftable_merged_table *mt)
return mt->hash_id;
}
-static int reftable_merged_table_seek_void(void *tab,
- struct reftable_iterator *it,
- struct reftable_record *rec)
+static void reftable_merged_table_init_iter_void(void *tab,
+ struct reftable_iterator *it,
+ uint8_t typ)
{
- return merged_table_seek_record(tab, it, rec);
+ merged_table_init_iter(tab, it, typ);
}
static uint32_t reftable_merged_table_hash_id_void(void *tab)
@@ -340,7 +290,7 @@ static uint64_t reftable_merged_table_max_update_index_void(void *tab)
}
static struct reftable_table_vtable merged_table_vtable = {
- .seek_record = reftable_merged_table_seek_void,
+ .init_iter = reftable_merged_table_init_iter_void,
.hash_id = reftable_merged_table_hash_id_void,
.min_update_index = reftable_merged_table_min_update_index_void,
.max_update_index = reftable_merged_table_max_update_index_void,
diff --git a/reftable/merged.h b/reftable/merged.h
index a2571dbc99..a10469f58e 100644
--- a/reftable/merged.h
+++ b/reftable/merged.h
@@ -26,4 +26,10 @@ struct reftable_merged_table {
void merged_table_release(struct reftable_merged_table *mt);
+struct reftable_iterator;
+
+void merged_table_init_iter(struct reftable_merged_table *mt,
+ struct reftable_iterator *it,
+ uint8_t typ);
+
#endif
diff --git a/reftable/merged_test.c b/reftable/merged_test.c
index 530fc82d1c..33a17efcde 100644
--- a/reftable/merged_test.c
+++ b/reftable/merged_test.c
@@ -12,6 +12,7 @@ https://developers.google.com/open-source/licenses/bsd
#include "basics.h"
#include "blocksource.h"
+#include "constants.h"
#include "reader.h"
#include "record.h"
#include "test_framework.h"
@@ -145,7 +146,10 @@ static void test_merged_between(void)
int i;
struct reftable_ref_record ref = { NULL };
struct reftable_iterator it = { NULL };
- int err = reftable_merged_table_seek_ref(mt, &it, "a");
+ int err;
+
+ merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+ err = reftable_iterator_seek_ref(&it, "a");
EXPECT_ERR(err);
err = reftable_iterator_next_ref(&it, &ref);
@@ -217,14 +221,15 @@ static void test_merged(void)
struct reftable_reader **readers = NULL;
struct reftable_merged_table *mt =
merged_table_from_records(refs, &bs, &readers, sizes, bufs, 3);
-
struct reftable_iterator it = { NULL };
- int err = reftable_merged_table_seek_ref(mt, &it, "a");
+ int err;
struct reftable_ref_record *out = NULL;
size_t len = 0;
size_t cap = 0;
int i = 0;
+ merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+ err = reftable_iterator_seek_ref(&it, "a");
EXPECT_ERR(err);
EXPECT(reftable_merged_table_hash_id(mt) == GIT_SHA1_FORMAT_ID);
EXPECT(reftable_merged_table_min_update_index(mt) == 1);
@@ -348,14 +353,15 @@ static void test_merged_logs(void)
struct reftable_reader **readers = NULL;
struct reftable_merged_table *mt = merged_table_from_log_records(
logs, &bs, &readers, sizes, bufs, 3);
-
struct reftable_iterator it = { NULL };
- int err = reftable_merged_table_seek_log(mt, &it, "a");
+ int err;
struct reftable_log_record *out = NULL;
size_t len = 0;
size_t cap = 0;
int i = 0;
+ merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
+ err = reftable_iterator_seek_log(&it, "a");
EXPECT_ERR(err);
EXPECT(reftable_merged_table_hash_id(mt) == GIT_SHA1_FORMAT_ID);
EXPECT(reftable_merged_table_min_update_index(mt) == 1);
@@ -377,7 +383,8 @@ static void test_merged_logs(void)
GIT_SHA1_RAWSZ));
}
- err = reftable_merged_table_seek_log_at(mt, &it, "a", 2);
+ merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
+ err = reftable_iterator_seek_log_at(&it, "a", 2);
EXPECT_ERR(err);
reftable_log_record_release(&out[0]);
err = reftable_iterator_next_log(&it, &out[0]);
diff --git a/reftable/reader.c b/reftable/reader.c
index 481dff10d4..29c99e2269 100644
--- a/reftable/reader.c
+++ b/reftable/reader.c
@@ -224,8 +224,14 @@ struct table_iter {
struct block_iter bi;
int is_finished;
};
-#define TABLE_ITER_INIT { \
- .bi = BLOCK_ITER_INIT \
+
+static int table_iter_init(struct table_iter *ti, struct reftable_reader *r)
+{
+ struct block_iter bi = BLOCK_ITER_INIT;
+ memset(ti, 0, sizeof(*ti));
+ ti->r = r;
+ ti->bi = bi;
+ return 0;
}
static int table_iter_next_in_block(struct table_iter *ti,
@@ -363,50 +369,23 @@ static int table_iter_next(struct table_iter *ti, struct reftable_record *rec)
}
}
-static int table_iter_next_void(void *ti, struct reftable_record *rec)
-{
- return table_iter_next(ti, rec);
-}
-
-static void table_iter_close_void(void *ti)
-{
- table_iter_close(ti);
-}
-
-static struct reftable_iterator_vtable table_iter_vtable = {
- .next = &table_iter_next_void,
- .close = &table_iter_close_void,
-};
-
-static void iterator_from_table_iter(struct reftable_iterator *it,
- struct table_iter *ti)
-{
- assert(!it->ops);
- it->iter_arg = ti;
- it->ops = &table_iter_vtable;
-}
-
-static int reader_table_iter_at(struct reftable_reader *r,
- struct table_iter *ti, uint64_t off,
- uint8_t typ)
+static int table_iter_seek_to(struct table_iter *ti, uint64_t off, uint8_t typ)
{
int err;
- err = reader_init_block_reader(r, &ti->br, off, typ);
+ err = reader_init_block_reader(ti->r, &ti->br, off, typ);
if (err != 0)
return err;
- ti->r = r;
ti->typ = block_reader_type(&ti->br);
ti->block_off = off;
block_iter_seek_start(&ti->bi, &ti->br);
return 0;
}
-static int reader_start(struct reftable_reader *r, struct table_iter *ti,
- uint8_t typ, int index)
+static int table_iter_seek_start(struct table_iter *ti, uint8_t typ, int index)
{
- struct reftable_reader_offsets *offs = reader_offsets_for(r, typ);
+ struct reftable_reader_offsets *offs = reader_offsets_for(ti->r, typ);
uint64_t off = offs->offset;
if (index) {
off = offs->index_offset;
@@ -416,16 +395,16 @@ static int reader_start(struct reftable_reader *r, struct table_iter *ti,
typ = BLOCK_TYPE_INDEX;
}
- return reader_table_iter_at(r, ti, off, typ);
+ return table_iter_seek_to(ti, off, typ);
}
-static int reader_seek_linear(struct table_iter *ti,
- struct reftable_record *want)
+static int table_iter_seek_linear(struct table_iter *ti,
+ struct reftable_record *want)
{
struct strbuf want_key = STRBUF_INIT;
struct strbuf got_key = STRBUF_INIT;
struct reftable_record rec;
- int err = -1;
+ int err;
reftable_record_init(&rec, reftable_record_type(want));
reftable_record_key(want, &want_key);
@@ -499,9 +478,8 @@ done:
return err;
}
-static int reader_seek_indexed(struct reftable_reader *r,
- struct reftable_iterator *it,
- struct reftable_record *rec)
+static int table_iter_seek_indexed(struct table_iter *ti,
+ struct reftable_record *rec)
{
struct reftable_record want_index = {
.type = BLOCK_TYPE_INDEX, .u.idx = { .last_key = STRBUF_INIT }
@@ -510,15 +488,9 @@ static int reader_seek_indexed(struct reftable_reader *r,
.type = BLOCK_TYPE_INDEX,
.u.idx = { .last_key = STRBUF_INIT },
};
- struct table_iter index_iter = TABLE_ITER_INIT;
- struct table_iter empty = TABLE_ITER_INIT;
- struct table_iter next = TABLE_ITER_INIT;
- int err = 0;
+ int err;
reftable_record_key(rec, &want_index.u.idx.last_key);
- err = reader_start(r, &index_iter, reftable_record_type(rec), 1);
- if (err < 0)
- goto done;
/*
* The index may consist of multiple levels, where each level may have
@@ -526,7 +498,7 @@ static int reader_seek_indexed(struct reftable_reader *r,
* highest layer that identifies the relevant index block as well as
* the record inside that block that corresponds to our wanted key.
*/
- err = reader_seek_linear(&index_iter, &want_index);
+ err = table_iter_seek_linear(ti, &want_index);
if (err < 0)
goto done;
@@ -552,123 +524,113 @@ static int reader_seek_indexed(struct reftable_reader *r,
* all levels of the index only to find out that the key does
* not exist.
*/
- err = table_iter_next(&index_iter, &index_result);
+ err = table_iter_next(ti, &index_result);
if (err != 0)
goto done;
- err = reader_table_iter_at(r, &next, index_result.u.idx.offset,
- 0);
+ err = table_iter_seek_to(ti, index_result.u.idx.offset, 0);
if (err != 0)
goto done;
- err = block_iter_seek_key(&next.bi, &next.br, &want_index.u.idx.last_key);
+ err = block_iter_seek_key(&ti->bi, &ti->br, &want_index.u.idx.last_key);
if (err < 0)
goto done;
- if (next.typ == reftable_record_type(rec)) {
+ if (ti->typ == reftable_record_type(rec)) {
err = 0;
break;
}
- if (next.typ != BLOCK_TYPE_INDEX) {
+ if (ti->typ != BLOCK_TYPE_INDEX) {
err = REFTABLE_FORMAT_ERROR;
- break;
+ goto done;
}
-
- table_iter_close(&index_iter);
- index_iter = next;
- next = empty;
- }
-
- if (err == 0) {
- struct table_iter *malloced = reftable_calloc(1, sizeof(*malloced));
- *malloced = next;
- next = empty;
- iterator_from_table_iter(it, malloced);
}
done:
- table_iter_close(&next);
- table_iter_close(&index_iter);
reftable_record_release(&want_index);
reftable_record_release(&index_result);
return err;
}
-static int reader_seek_internal(struct reftable_reader *r,
- struct reftable_iterator *it,
- struct reftable_record *rec)
+static int table_iter_seek(struct table_iter *ti,
+ struct reftable_record *want)
{
- struct reftable_reader_offsets *offs =
- reader_offsets_for(r, reftable_record_type(rec));
- uint64_t idx = offs->index_offset;
- struct table_iter ti = TABLE_ITER_INIT, *p;
+ uint8_t typ = reftable_record_type(want);
+ struct reftable_reader_offsets *offs = reader_offsets_for(ti->r, typ);
int err;
- if (idx > 0)
- return reader_seek_indexed(r, it, rec);
-
- err = reader_start(r, &ti, reftable_record_type(rec), 0);
+ err = table_iter_seek_start(ti, reftable_record_type(want),
+ !!offs->index_offset);
if (err < 0)
goto out;
- err = reader_seek_linear(&ti, rec);
- if (err < 0)
+ if (offs->index_offset)
+ err = table_iter_seek_indexed(ti, want);
+ else
+ err = table_iter_seek_linear(ti, want);
+ if (err)
goto out;
- REFTABLE_ALLOC_ARRAY(p, 1);
- *p = ti;
- iterator_from_table_iter(it, p);
-
out:
- if (err)
- table_iter_close(&ti);
return err;
}
-static int reader_seek(struct reftable_reader *r, struct reftable_iterator *it,
- struct reftable_record *rec)
+static int table_iter_seek_void(void *ti, struct reftable_record *want)
{
- uint8_t typ = reftable_record_type(rec);
+ return table_iter_seek(ti, want);
+}
- struct reftable_reader_offsets *offs = reader_offsets_for(r, typ);
- if (!offs->is_present) {
- iterator_set_empty(it);
- return 0;
- }
+static int table_iter_next_void(void *ti, struct reftable_record *rec)
+{
+ return table_iter_next(ti, rec);
+}
- return reader_seek_internal(r, it, rec);
+static void table_iter_close_void(void *ti)
+{
+ table_iter_close(ti);
}
-int reftable_reader_seek_ref(struct reftable_reader *r,
- struct reftable_iterator *it, const char *name)
+static struct reftable_iterator_vtable table_iter_vtable = {
+ .seek = &table_iter_seek_void,
+ .next = &table_iter_next_void,
+ .close = &table_iter_close_void,
+};
+
+static void iterator_from_table_iter(struct reftable_iterator *it,
+ struct table_iter *ti)
{
- struct reftable_record rec = {
- .type = BLOCK_TYPE_REF,
- .u.ref = {
- .refname = (char *)name,
- },
- };
- return reader_seek(r, it, &rec);
+ assert(!it->ops);
+ it->iter_arg = ti;
+ it->ops = &table_iter_vtable;
}
-int reftable_reader_seek_log_at(struct reftable_reader *r,
- struct reftable_iterator *it, const char *name,
- uint64_t update_index)
+static void reader_init_iter(struct reftable_reader *r,
+ struct reftable_iterator *it,
+ uint8_t typ)
{
- struct reftable_record rec = { .type = BLOCK_TYPE_LOG,
- .u.log = {
- .refname = (char *)name,
- .update_index = update_index,
- } };
- return reader_seek(r, it, &rec);
+ struct reftable_reader_offsets *offs = reader_offsets_for(r, typ);
+
+ if (offs->is_present) {
+ struct table_iter *ti;
+ REFTABLE_ALLOC_ARRAY(ti, 1);
+ table_iter_init(ti, r);
+ iterator_from_table_iter(it, ti);
+ } else {
+ iterator_set_empty(it);
+ }
}
-int reftable_reader_seek_log(struct reftable_reader *r,
- struct reftable_iterator *it, const char *name)
+void reftable_reader_init_ref_iterator(struct reftable_reader *r,
+ struct reftable_iterator *it)
{
- uint64_t max = ~((uint64_t)0);
- return reftable_reader_seek_log_at(r, it, name, max);
+ reader_init_iter(r, it, BLOCK_TYPE_REF);
+}
+
+void reftable_reader_init_log_iterator(struct reftable_reader *r,
+ struct reftable_iterator *it)
+{
+ reader_init_iter(r, it, BLOCK_TYPE_LOG);
}
void reader_close(struct reftable_reader *r)
@@ -719,7 +681,8 @@ static int reftable_reader_refs_for_indexed(struct reftable_reader *r,
struct indexed_table_ref_iter *itr = NULL;
/* Look through the reverse index. */
- err = reader_seek(r, &oit, &want);
+ reader_init_iter(r, &oit, BLOCK_TYPE_OBJ);
+ err = iterator_seek(&oit, &want);
if (err != 0)
goto done;
@@ -754,15 +717,15 @@ static int reftable_reader_refs_for_unindexed(struct reftable_reader *r,
struct reftable_iterator *it,
uint8_t *oid)
{
- struct table_iter ti_empty = TABLE_ITER_INIT;
- struct table_iter *ti = reftable_calloc(1, sizeof(*ti));
+ struct table_iter *ti;
struct filtering_ref_iterator *filter = NULL;
struct filtering_ref_iterator empty = FILTERING_REF_ITERATOR_INIT;
int oid_len = hash_size(r->hash_id);
int err;
- *ti = ti_empty;
- err = reader_start(r, ti, BLOCK_TYPE_REF, 0);
+ REFTABLE_ALLOC_ARRAY(ti, 1);
+ table_iter_init(ti, r);
+ err = table_iter_seek_start(ti, BLOCK_TYPE_REF, 0);
if (err < 0) {
reftable_free(ti);
return err;
@@ -800,10 +763,11 @@ uint64_t reftable_reader_min_update_index(struct reftable_reader *r)
/* generic table interface. */
-static int reftable_reader_seek_void(void *tab, struct reftable_iterator *it,
- struct reftable_record *rec)
+static void reftable_reader_init_iter_void(void *tab,
+ struct reftable_iterator *it,
+ uint8_t typ)
{
- return reader_seek(tab, it, rec);
+ reader_init_iter(tab, it, typ);
}
static uint32_t reftable_reader_hash_id_void(void *tab)
@@ -822,7 +786,7 @@ static uint64_t reftable_reader_max_update_index_void(void *tab)
}
static struct reftable_table_vtable reader_vtable = {
- .seek_record = reftable_reader_seek_void,
+ .init_iter = reftable_reader_init_iter_void,
.hash_id = reftable_reader_hash_id_void,
.min_update_index = reftable_reader_min_update_index_void,
.max_update_index = reftable_reader_max_update_index_void,
@@ -856,3 +820,68 @@ done:
reftable_reader_free(r);
return err;
}
+
+int reftable_reader_print_blocks(const char *tablename)
+{
+ struct {
+ const char *name;
+ int type;
+ } sections[] = {
+ {
+ .name = "ref",
+ .type = BLOCK_TYPE_REF,
+ },
+ {
+ .name = "obj",
+ .type = BLOCK_TYPE_OBJ,
+ },
+ {
+ .name = "log",
+ .type = BLOCK_TYPE_LOG,
+ },
+ };
+ struct reftable_block_source src = { 0 };
+ struct reftable_reader *r = NULL;
+ struct table_iter ti = { 0 };
+ size_t i;
+ int err;
+
+ err = reftable_block_source_from_file(&src, tablename);
+ if (err < 0)
+ goto done;
+
+ err = reftable_new_reader(&r, &src, tablename);
+ if (err < 0)
+ goto done;
+
+ table_iter_init(&ti, r);
+
+ printf("header:\n");
+ printf(" block_size: %d\n", r->block_size);
+
+ for (i = 0; i < ARRAY_SIZE(sections); i++) {
+ err = table_iter_seek_start(&ti, sections[i].type, 0);
+ if (err < 0)
+ goto done;
+ if (err > 0)
+ continue;
+
+ printf("%s:\n", sections[i].name);
+
+ while (1) {
+ printf(" - length: %u\n", ti.br.block_len);
+ printf(" restarts: %u\n", ti.br.restart_count);
+
+ err = table_iter_next_block(&ti);
+ if (err < 0)
+ goto done;
+ if (err > 0)
+ break;
+ }
+ }
+
+done:
+ reftable_reader_free(r);
+ table_iter_close(&ti);
+ return err;
+}
diff --git a/reftable/readwrite_test.c b/reftable/readwrite_test.c
index a6dbd214c5..d99543bbd6 100644
--- a/reftable/readwrite_test.c
+++ b/reftable/readwrite_test.c
@@ -239,7 +239,9 @@ static void test_log_write_read(void)
err = init_reader(&rd, &source, "file.log");
EXPECT_ERR(err);
- err = reftable_reader_seek_ref(&rd, &it, names[N - 1]);
+ reftable_reader_init_ref_iterator(&rd, &it);
+
+ err = reftable_iterator_seek_ref(&it, names[N - 1]);
EXPECT_ERR(err);
err = reftable_iterator_next_ref(&it, &ref);
@@ -252,7 +254,9 @@ static void test_log_write_read(void)
reftable_iterator_destroy(&it);
reftable_ref_record_release(&ref);
- err = reftable_reader_seek_log(&rd, &it, "");
+ reftable_reader_init_log_iterator(&rd, &it);
+
+ err = reftable_iterator_seek_log(&it, "");
EXPECT_ERR(err);
i = 0;
@@ -330,7 +334,8 @@ static void test_log_zlib_corruption(void)
err = init_reader(&rd, &source, "file.log");
EXPECT_ERR(err);
- err = reftable_reader_seek_log(&rd, &it, "refname");
+ reftable_reader_init_log_iterator(&rd, &it);
+ err = reftable_iterator_seek_log(&it, "refname");
EXPECT(err == REFTABLE_ZLIB_ERROR);
reftable_iterator_destroy(&it);
@@ -358,7 +363,8 @@ static void test_table_read_write_sequential(void)
err = init_reader(&rd, &source, "file.ref");
EXPECT_ERR(err);
- err = reftable_reader_seek_ref(&rd, &it, "");
+ reftable_reader_init_ref_iterator(&rd, &it);
+ err = reftable_iterator_seek_ref(&it, "");
EXPECT_ERR(err);
while (1) {
@@ -412,7 +418,8 @@ static void test_table_read_api(void)
err = init_reader(&rd, &source, "file.ref");
EXPECT_ERR(err);
- err = reftable_reader_seek_ref(&rd, &it, names[0]);
+ reftable_reader_init_ref_iterator(&rd, &it);
+ err = reftable_iterator_seek_ref(&it, names[0]);
EXPECT_ERR(err);
err = reftable_iterator_next_log(&it, &log);
@@ -457,7 +464,8 @@ static void test_table_read_write_seek(int index, int hash_id)
}
for (i = 1; i < N; i++) {
- int err = reftable_reader_seek_ref(&rd, &it, names[i]);
+ reftable_reader_init_ref_iterator(&rd, &it);
+ err = reftable_iterator_seek_ref(&it, names[i]);
EXPECT_ERR(err);
err = reftable_iterator_next_ref(&it, &ref);
EXPECT_ERR(err);
@@ -472,7 +480,8 @@ static void test_table_read_write_seek(int index, int hash_id)
strbuf_addstr(&pastLast, names[N - 1]);
strbuf_addstr(&pastLast, "/");
- err = reftable_reader_seek_ref(&rd, &it, pastLast.buf);
+ reftable_reader_init_ref_iterator(&rd, &it);
+ err = reftable_iterator_seek_ref(&it, pastLast.buf);
if (err == 0) {
struct reftable_ref_record ref = { NULL };
int err = reftable_iterator_next_ref(&it, &ref);
@@ -576,7 +585,8 @@ static void test_table_refs_for(int indexed)
rd.obj_offsets.is_present = 0;
}
- err = reftable_reader_seek_ref(&rd, &it, "");
+ reftable_reader_init_ref_iterator(&rd, &it);
+ err = reftable_iterator_seek_ref(&it, "");
EXPECT_ERR(err);
reftable_iterator_destroy(&it);
@@ -639,7 +649,8 @@ static void test_write_empty_table(void)
err = reftable_new_reader(&rd, &source, "filename");
EXPECT_ERR(err);
- err = reftable_reader_seek_ref(rd, &it, "");
+ reftable_reader_init_ref_iterator(rd, &it);
+ err = reftable_iterator_seek_ref(&it, "");
EXPECT_ERR(err);
err = reftable_iterator_next_ref(&it, &rec);
@@ -846,7 +857,8 @@ static void test_write_multiple_indices(void)
* Seeking the log uses the log index now. In case there is any
* confusion regarding indices we would notice here.
*/
- err = reftable_reader_seek_log(reader, &it, "");
+ reftable_reader_init_log_iterator(reader, &it);
+ err = reftable_iterator_seek_log(&it, "");
EXPECT_ERR(err);
reftable_iterator_destroy(&it);
@@ -901,7 +913,8 @@ static void test_write_multi_level_index(void)
/*
* Seeking the last ref should work as expected.
*/
- err = reftable_reader_seek_ref(reader, &it, "refs/heads/199");
+ reftable_reader_init_ref_iterator(reader, &it);
+ err = reftable_iterator_seek_ref(&it, "refs/heads/199");
EXPECT_ERR(err);
reftable_iterator_destroy(&it);
diff --git a/reftable/refname.c b/reftable/refname.c
deleted file mode 100644
index bbfde15754..0000000000
--- a/reftable/refname.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- Copyright 2020 Google LLC
-
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file or at
- https://developers.google.com/open-source/licenses/bsd
-*/
-
-#include "system.h"
-#include "reftable-error.h"
-#include "basics.h"
-#include "refname.h"
-#include "reftable-iterator.h"
-
-struct refname_needle_lesseq_args {
- char **haystack;
- const char *needle;
-};
-
-static int refname_needle_lesseq(size_t k, void *_args)
-{
- struct refname_needle_lesseq_args *args = _args;
- return strcmp(args->needle, args->haystack[k]) <= 0;
-}
-
-static int modification_has_ref(struct modification *mod, const char *name)
-{
- struct reftable_ref_record ref = { NULL };
- int err = 0;
-
- if (mod->add_len > 0) {
- struct refname_needle_lesseq_args args = {
- .haystack = mod->add,
- .needle = name,
- };
- size_t idx = binsearch(mod->add_len, refname_needle_lesseq, &args);
- if (idx < mod->add_len && !strcmp(mod->add[idx], name))
- return 0;
- }
-
- if (mod->del_len > 0) {
- struct refname_needle_lesseq_args args = {
- .haystack = mod->del,
- .needle = name,
- };
- size_t idx = binsearch(mod->del_len, refname_needle_lesseq, &args);
- if (idx < mod->del_len && !strcmp(mod->del[idx], name))
- return 1;
- }
-
- err = reftable_table_read_ref(&mod->tab, name, &ref);
- reftable_ref_record_release(&ref);
- return err;
-}
-
-static void modification_release(struct modification *mod)
-{
- /* don't delete the strings themselves; they're owned by ref records.
- */
- FREE_AND_NULL(mod->add);
- FREE_AND_NULL(mod->del);
- mod->add_len = 0;
- mod->del_len = 0;
-}
-
-static int modification_has_ref_with_prefix(struct modification *mod,
- const char *prefix)
-{
- struct reftable_iterator it = { NULL };
- struct reftable_ref_record ref = { NULL };
- int err = 0;
-
- if (mod->add_len > 0) {
- struct refname_needle_lesseq_args args = {
- .haystack = mod->add,
- .needle = prefix,
- };
- size_t idx = binsearch(mod->add_len, refname_needle_lesseq, &args);
- if (idx < mod->add_len &&
- !strncmp(prefix, mod->add[idx], strlen(prefix)))
- goto done;
- }
- err = reftable_table_seek_ref(&mod->tab, &it, prefix);
- if (err)
- goto done;
-
- while (1) {
- err = reftable_iterator_next_ref(&it, &ref);
- if (err)
- goto done;
-
- if (mod->del_len > 0) {
- struct refname_needle_lesseq_args args = {
- .haystack = mod->del,
- .needle = ref.refname,
- };
- size_t idx = binsearch(mod->del_len, refname_needle_lesseq, &args);
- if (idx < mod->del_len &&
- !strcmp(ref.refname, mod->del[idx]))
- continue;
- }
-
- if (strncmp(ref.refname, prefix, strlen(prefix))) {
- err = 1;
- goto done;
- }
- err = 0;
- goto done;
- }
-
-done:
- reftable_ref_record_release(&ref);
- reftable_iterator_destroy(&it);
- return err;
-}
-
-static int validate_refname(const char *name)
-{
- while (1) {
- char *next = strchr(name, '/');
- if (!*name) {
- return REFTABLE_REFNAME_ERROR;
- }
- if (!next) {
- return 0;
- }
- if (next - name == 0 || (next - name == 1 && *name == '.') ||
- (next - name == 2 && name[0] == '.' && name[1] == '.'))
- return REFTABLE_REFNAME_ERROR;
- name = next + 1;
- }
- return 0;
-}
-
-int validate_ref_record_addition(struct reftable_table tab,
- struct reftable_ref_record *recs, size_t sz)
-{
- struct modification mod = {
- .tab = tab,
- .add = reftable_calloc(sz, sizeof(*mod.add)),
- .del = reftable_calloc(sz, sizeof(*mod.del)),
- };
- int i = 0;
- int err = 0;
- for (; i < sz; i++) {
- if (reftable_ref_record_is_deletion(&recs[i])) {
- mod.del[mod.del_len++] = recs[i].refname;
- } else {
- mod.add[mod.add_len++] = recs[i].refname;
- }
- }
-
- err = modification_validate(&mod);
- modification_release(&mod);
- return err;
-}
-
-static void strbuf_trim_component(struct strbuf *sl)
-{
- while (sl->len > 0) {
- int is_slash = (sl->buf[sl->len - 1] == '/');
- strbuf_setlen(sl, sl->len - 1);
- if (is_slash)
- break;
- }
-}
-
-int modification_validate(struct modification *mod)
-{
- struct strbuf slashed = STRBUF_INIT;
- int err = 0;
- int i = 0;
- for (; i < mod->add_len; i++) {
- err = validate_refname(mod->add[i]);
- if (err)
- goto done;
- strbuf_reset(&slashed);
- strbuf_addstr(&slashed, mod->add[i]);
- strbuf_addstr(&slashed, "/");
-
- err = modification_has_ref_with_prefix(mod, slashed.buf);
- if (err == 0) {
- err = REFTABLE_NAME_CONFLICT;
- goto done;
- }
- if (err < 0)
- goto done;
-
- strbuf_reset(&slashed);
- strbuf_addstr(&slashed, mod->add[i]);
- while (slashed.len) {
- strbuf_trim_component(&slashed);
- err = modification_has_ref(mod, slashed.buf);
- if (err == 0) {
- err = REFTABLE_NAME_CONFLICT;
- goto done;
- }
- if (err < 0)
- goto done;
- }
- }
- err = 0;
-done:
- strbuf_release(&slashed);
- return err;
-}
diff --git a/reftable/refname.h b/reftable/refname.h
deleted file mode 100644
index a24b40fcb4..0000000000
--- a/reftable/refname.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- Copyright 2020 Google LLC
-
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file or at
- https://developers.google.com/open-source/licenses/bsd
-*/
-#ifndef REFNAME_H
-#define REFNAME_H
-
-#include "reftable-record.h"
-#include "reftable-generic.h"
-
-struct modification {
- struct reftable_table tab;
-
- char **add;
- size_t add_len;
-
- char **del;
- size_t del_len;
-};
-
-int validate_ref_record_addition(struct reftable_table tab,
- struct reftable_ref_record *recs, size_t sz);
-
-int modification_validate(struct modification *mod);
-
-#endif
diff --git a/reftable/refname_test.c b/reftable/refname_test.c
deleted file mode 100644
index b9cc62554e..0000000000
--- a/reftable/refname_test.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-Copyright 2020 Google LLC
-
-Use of this source code is governed by a BSD-style
-license that can be found in the LICENSE file or at
-https://developers.google.com/open-source/licenses/bsd
-*/
-
-#include "basics.h"
-#include "block.h"
-#include "blocksource.h"
-#include "reader.h"
-#include "record.h"
-#include "refname.h"
-#include "reftable-error.h"
-#include "reftable-writer.h"
-#include "system.h"
-
-#include "test_framework.h"
-#include "reftable-tests.h"
-
-struct testcase {
- char *add;
- char *del;
- int error_code;
-};
-
-static void test_conflict(void)
-{
- struct reftable_write_options opts = { 0 };
- struct strbuf buf = STRBUF_INIT;
- struct reftable_writer *w =
- reftable_new_writer(&strbuf_add_void, &noop_flush, &buf, &opts);
- struct reftable_ref_record rec = {
- .refname = "a/b",
- .value_type = REFTABLE_REF_SYMREF,
- .value.symref = "destination", /* make sure it's not a symref.
- */
- .update_index = 1,
- };
- int err;
- int i;
- struct reftable_block_source source = { NULL };
- struct reftable_reader *rd = NULL;
- struct reftable_table tab = { NULL };
- struct testcase cases[] = {
- { "a/b/c", NULL, REFTABLE_NAME_CONFLICT },
- { "b", NULL, 0 },
- { "a", NULL, REFTABLE_NAME_CONFLICT },
- { "a", "a/b", 0 },
-
- { "p/", NULL, REFTABLE_REFNAME_ERROR },
- { "p//q", NULL, REFTABLE_REFNAME_ERROR },
- { "p/./q", NULL, REFTABLE_REFNAME_ERROR },
- { "p/../q", NULL, REFTABLE_REFNAME_ERROR },
-
- { "a/b/c", "a/b", 0 },
- { NULL, "a//b", 0 },
- };
- reftable_writer_set_limits(w, 1, 1);
-
- err = reftable_writer_add_ref(w, &rec);
- EXPECT_ERR(err);
-
- err = reftable_writer_close(w);
- EXPECT_ERR(err);
- reftable_writer_free(w);
-
- block_source_from_strbuf(&source, &buf);
- err = reftable_new_reader(&rd, &source, "filename");
- EXPECT_ERR(err);
-
- reftable_table_from_reader(&tab, rd);
-
- for (i = 0; i < ARRAY_SIZE(cases); i++) {
- struct modification mod = {
- .tab = tab,
- };
-
- if (cases[i].add) {
- mod.add = &cases[i].add;
- mod.add_len = 1;
- }
- if (cases[i].del) {
- mod.del = &cases[i].del;
- mod.del_len = 1;
- }
-
- err = modification_validate(&mod);
- EXPECT(err == cases[i].error_code);
- }
-
- reftable_reader_free(rd);
- strbuf_release(&buf);
-}
-
-int refname_test_main(int argc, const char *argv[])
-{
- RUN_TEST(test_conflict);
- return 0;
-}
diff --git a/reftable/reftable-error.h b/reftable/reftable-error.h
index e9b07c9f36..6368cd9ed9 100644
--- a/reftable/reftable-error.h
+++ b/reftable/reftable-error.h
@@ -48,9 +48,6 @@ enum reftable_error {
/* Wrote a table without blocks. */
REFTABLE_EMPTY_TABLE_ERROR = -8,
- /* Dir/file conflict. */
- REFTABLE_NAME_CONFLICT = -9,
-
/* Invalid ref name. */
REFTABLE_REFNAME_ERROR = -10,
diff --git a/reftable/reftable-generic.h b/reftable/reftable-generic.h
index d239751a77..65670ea093 100644
--- a/reftable/reftable-generic.h
+++ b/reftable/reftable-generic.h
@@ -21,11 +21,11 @@ struct reftable_table {
void *table_arg;
};
-int reftable_table_seek_log(struct reftable_table *tab,
- struct reftable_iterator *it, const char *name);
+void reftable_table_init_ref_iter(struct reftable_table *tab,
+ struct reftable_iterator *it);
-int reftable_table_seek_ref(struct reftable_table *tab,
- struct reftable_iterator *it, const char *name);
+void reftable_table_init_log_iter(struct reftable_table *tab,
+ struct reftable_iterator *it);
/* returns the hash ID from a generic reftable_table */
uint32_t reftable_table_hash_id(struct reftable_table *tab);
diff --git a/reftable/reftable-iterator.h b/reftable/reftable-iterator.h
index d3eee7af35..e3bf688d53 100644
--- a/reftable/reftable-iterator.h
+++ b/reftable/reftable-iterator.h
@@ -21,12 +21,33 @@ struct reftable_iterator {
void *iter_arg;
};
+/*
+ * Position the iterator at the ref record with given name such that the next
+ * call to `next_ref()` would yield the record.
+ */
+int reftable_iterator_seek_ref(struct reftable_iterator *it,
+ const char *name);
+
/* reads the next reftable_ref_record. Returns < 0 for error, 0 for OK and > 0:
* end of iteration.
*/
int reftable_iterator_next_ref(struct reftable_iterator *it,
struct reftable_ref_record *ref);
+/*
+ * Position the iterator at the log record with given name and update index
+ * such that the next call to `next_log()` would yield the record.
+ */
+int reftable_iterator_seek_log_at(struct reftable_iterator *it,
+ const char *name, uint64_t update_index);
+
+/*
+ * Position the iterator at the newest log record with given name such that the
+ * next call to `next_log()` would yield the record.
+ */
+int reftable_iterator_seek_log(struct reftable_iterator *it,
+ const char *name);
+
/* reads the next reftable_log_record. Returns < 0 for error, 0 for OK and > 0:
* end of iteration.
*/
diff --git a/reftable/reftable-merged.h b/reftable/reftable-merged.h
index c91a2d83a2..14d5fc9f05 100644
--- a/reftable/reftable-merged.h
+++ b/reftable/reftable-merged.h
@@ -36,21 +36,6 @@ int reftable_new_merged_table(struct reftable_merged_table **dest,
struct reftable_table *stack, size_t n,
uint32_t hash_id);
-/* returns an iterator positioned just before 'name' */
-int reftable_merged_table_seek_ref(struct reftable_merged_table *mt,
- struct reftable_iterator *it,
- const char *name);
-
-/* returns an iterator for log entry, at given update_index */
-int reftable_merged_table_seek_log_at(struct reftable_merged_table *mt,
- struct reftable_iterator *it,
- const char *name, uint64_t update_index);
-
-/* like reftable_merged_table_seek_log_at but look for the newest entry. */
-int reftable_merged_table_seek_log(struct reftable_merged_table *mt,
- struct reftable_iterator *it,
- const char *name);
-
/* returns the max update_index covered by this merged table. */
uint64_t
reftable_merged_table_max_update_index(struct reftable_merged_table *mt);
diff --git a/reftable/reftable-reader.h b/reftable/reftable-reader.h
index 4a4bc2fdf8..a32f31d648 100644
--- a/reftable/reftable-reader.h
+++ b/reftable/reftable-reader.h
@@ -36,48 +36,17 @@ struct reftable_table;
int reftable_new_reader(struct reftable_reader **pp,
struct reftable_block_source *src, const char *name);
-/* reftable_reader_seek_ref returns an iterator where 'name' would be inserted
- in the table. To seek to the start of the table, use name = "".
-
- example:
-
- struct reftable_reader *r = NULL;
- int err = reftable_new_reader(&r, &src, "filename");
- if (err < 0) { ... }
- struct reftable_iterator it = {0};
- err = reftable_reader_seek_ref(r, &it, "refs/heads/master");
- if (err < 0) { ... }
- struct reftable_ref_record ref = {0};
- while (1) {
- err = reftable_iterator_next_ref(&it, &ref);
- if (err > 0) {
- break;
- }
- if (err < 0) {
- ..error handling..
- }
- ..found..
- }
- reftable_iterator_destroy(&it);
- reftable_ref_record_release(&ref);
-*/
-int reftable_reader_seek_ref(struct reftable_reader *r,
- struct reftable_iterator *it, const char *name);
+/* Initialize a reftable iterator for reading refs. */
+void reftable_reader_init_ref_iterator(struct reftable_reader *r,
+ struct reftable_iterator *it);
+
+/* Initialize a reftable iterator for reading logs. */
+void reftable_reader_init_log_iterator(struct reftable_reader *r,
+ struct reftable_iterator *it);
/* returns the hash ID used in this table. */
uint32_t reftable_reader_hash_id(struct reftable_reader *r);
-/* seek to logs for the given name, older than update_index. To seek to the
- start of the table, use name = "".
-*/
-int reftable_reader_seek_log_at(struct reftable_reader *r,
- struct reftable_iterator *it, const char *name,
- uint64_t update_index);
-
-/* seek to newest log entry for given name. */
-int reftable_reader_seek_log(struct reftable_reader *r,
- struct reftable_iterator *it, const char *name);
-
/* closes and deallocates a reader. */
void reftable_reader_free(struct reftable_reader *);
@@ -97,5 +66,7 @@ void reftable_table_from_reader(struct reftable_table *tab,
/* print table onto stdout for debugging. */
int reftable_reader_print_file(const char *tablename);
+/* print blocks onto stdout for debugging. */
+int reftable_reader_print_blocks(const char *tablename);
#endif
diff --git a/reftable/reftable-stack.h b/reftable/reftable-stack.h
index 1b602dda58..09e97c9991 100644
--- a/reftable/reftable-stack.h
+++ b/reftable/reftable-stack.h
@@ -29,7 +29,7 @@ struct reftable_stack;
* stored in 'dir'. Typically, this should be .git/reftables.
*/
int reftable_new_stack(struct reftable_stack **dest, const char *dir,
- struct reftable_write_options config);
+ const struct reftable_write_options *opts);
/* returns the update_index at which a next table should be written. */
uint64_t reftable_stack_next_update_index(struct reftable_stack *st);
@@ -66,6 +66,24 @@ int reftable_stack_add(struct reftable_stack *st,
void *write_arg),
void *write_arg);
+struct reftable_iterator;
+
+/*
+ * Initialize an iterator for the merged tables contained in the stack that can
+ * be used to iterate through refs. The iterator is valid until the next reload
+ * or write.
+ */
+void reftable_stack_init_ref_iterator(struct reftable_stack *st,
+ struct reftable_iterator *it);
+
+/*
+ * Initialize an iterator for the merged tables contained in the stack that can
+ * be used to iterate through logs. The iterator is valid until the next reload
+ * or write.
+ */
+void reftable_stack_init_log_iterator(struct reftable_stack *st,
+ struct reftable_iterator *it);
+
/* returns the merged_table for seeking. This table is valid until the
* next write or reload, and should not be closed or deleted.
*/
diff --git a/reftable/reftable-tests.h b/reftable/reftable-tests.h
index 0019cbcfa4..114cc3d053 100644
--- a/reftable/reftable-tests.h
+++ b/reftable/reftable-tests.h
@@ -14,7 +14,6 @@ int block_test_main(int argc, const char **argv);
int merged_test_main(int argc, const char **argv);
int pq_test_main(int argc, const char **argv);
int record_test_main(int argc, const char **argv);
-int refname_test_main(int argc, const char **argv);
int readwrite_test_main(int argc, const char **argv);
int stack_test_main(int argc, const char **argv);
int tree_test_main(int argc, const char **argv);
diff --git a/reftable/reftable-writer.h b/reftable/reftable-writer.h
index 155bf0bbe2..189b1f4144 100644
--- a/reftable/reftable-writer.h
+++ b/reftable/reftable-writer.h
@@ -28,7 +28,7 @@ struct reftable_write_options {
unsigned skip_index_objects : 1;
/* how often to write complete keys in each block. */
- int restart_interval;
+ uint16_t restart_interval;
/* 4-byte identifier ("sha1", "s256") of the hash.
* Defaults to SHA1 if unset
@@ -38,10 +38,6 @@ struct reftable_write_options {
/* Default mode for creating files. If unset, use 0666 (+umask) */
unsigned int default_permissions;
- /* boolean: do not check ref names for validity or dir/file conflicts.
- */
- unsigned skip_name_check : 1;
-
/* boolean: copy log messages exactly. If unset, check that the message
* is a single line, and add '\n' if missing.
*/
@@ -49,6 +45,12 @@ struct reftable_write_options {
/* boolean: Prevent auto-compaction of tables. */
unsigned disable_auto_compact : 1;
+
+ /*
+ * Geometric sequence factor used by auto-compaction to decide which
+ * tables to compact. Defaults to 2 if unset.
+ */
+ uint8_t auto_compaction_factor;
};
/* reftable_block_stats holds statistics for a single block type */
@@ -92,7 +94,7 @@ struct reftable_stats {
struct reftable_writer *
reftable_new_writer(ssize_t (*writer_func)(void *, const void *, size_t),
int (*flush_func)(void *),
- void *writer_arg, struct reftable_write_options *opts);
+ void *writer_arg, const struct reftable_write_options *opts);
/* Set the range of update indices for the records we will add. When writing a
table into a stack, the min should be at least
diff --git a/reftable/stack.c b/reftable/stack.c
index 80266bcbab..98ac9cf9f9 100644
--- a/reftable/stack.c
+++ b/reftable/stack.c
@@ -10,10 +10,11 @@ https://developers.google.com/open-source/licenses/bsd
#include "../write-or-die.h"
#include "system.h"
+#include "constants.h"
#include "merged.h"
#include "reader.h"
-#include "refname.h"
#include "reftable-error.h"
+#include "reftable-generic.h"
#include "reftable-record.h"
#include "reftable-merged.h"
#include "writer.h"
@@ -27,8 +28,6 @@ static int stack_write_compact(struct reftable_stack *st,
struct reftable_writer *wr,
size_t first, size_t last,
struct reftable_log_expiry_config *config);
-static int stack_check_addition(struct reftable_stack *st,
- const char *new_tab_name);
static void reftable_addition_close(struct reftable_addition *add);
static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
int reuse_open);
@@ -56,15 +55,17 @@ static int reftable_fd_flush(void *arg)
}
int reftable_new_stack(struct reftable_stack **dest, const char *dir,
- struct reftable_write_options config)
+ const struct reftable_write_options *_opts)
{
struct reftable_stack *p = reftable_calloc(1, sizeof(*p));
struct strbuf list_file_name = STRBUF_INIT;
+ struct reftable_write_options opts = {0};
int err = 0;
- if (config.hash_id == 0) {
- config.hash_id = GIT_SHA1_FORMAT_ID;
- }
+ if (_opts)
+ opts = *_opts;
+ if (opts.hash_id == 0)
+ opts.hash_id = GIT_SHA1_FORMAT_ID;
*dest = NULL;
@@ -75,7 +76,7 @@ int reftable_new_stack(struct reftable_stack **dest, const char *dir,
p->list_file = strbuf_detach(&list_file_name, NULL);
p->list_fd = -1;
p->reftable_dir = xstrdup(dir);
- p->config = config;
+ p->opts = opts;
err = reftable_stack_reload_maybe_reuse(p, 1);
if (err < 0) {
@@ -132,6 +133,20 @@ int read_lines(const char *filename, char ***namesp)
return err;
}
+void reftable_stack_init_ref_iterator(struct reftable_stack *st,
+ struct reftable_iterator *it)
+{
+ merged_table_init_iter(reftable_stack_merged_table(st),
+ it, BLOCK_TYPE_REF);
+}
+
+void reftable_stack_init_log_iterator(struct reftable_stack *st,
+ struct reftable_iterator *it)
+{
+ merged_table_init_iter(reftable_stack_merged_table(st),
+ it, BLOCK_TYPE_LOG);
+}
+
struct reftable_merged_table *
reftable_stack_merged_table(struct reftable_stack *st)
{
@@ -257,7 +272,7 @@ static int reftable_stack_reload_once(struct reftable_stack *st, char **names,
/* success! */
err = reftable_new_merged_table(&new_merged, new_tables,
- new_readers_len, st->config.hash_id);
+ new_readers_len, st->opts.hash_id);
if (err < 0)
goto done;
@@ -580,8 +595,8 @@ static int reftable_stack_init_addition(struct reftable_addition *add,
}
goto done;
}
- if (st->config.default_permissions) {
- if (chmod(add->lock_file->filename.buf, st->config.default_permissions) < 0) {
+ if (st->opts.default_permissions) {
+ if (chmod(add->lock_file->filename.buf, st->opts.default_permissions) < 0) {
err = REFTABLE_IO_ERROR;
goto done;
}
@@ -680,7 +695,7 @@ int reftable_addition_commit(struct reftable_addition *add)
if (err)
goto done;
- if (!add->stack->config.disable_auto_compact) {
+ if (!add->stack->opts.disable_auto_compact) {
/*
* Auto-compact the stack to keep the number of tables in
* control. It is possible that a concurrent writer is already
@@ -758,9 +773,9 @@ int reftable_addition_add(struct reftable_addition *add,
err = REFTABLE_IO_ERROR;
goto done;
}
- if (add->stack->config.default_permissions) {
+ if (add->stack->opts.default_permissions) {
if (chmod(get_tempfile_path(tab_file),
- add->stack->config.default_permissions)) {
+ add->stack->opts.default_permissions)) {
err = REFTABLE_IO_ERROR;
goto done;
}
@@ -768,7 +783,7 @@ int reftable_addition_add(struct reftable_addition *add,
tab_fd = get_tempfile_fd(tab_file);
wr = reftable_new_writer(reftable_fd_write, reftable_fd_flush, &tab_fd,
- &add->stack->config);
+ &add->stack->opts);
err = write_table(wr, arg);
if (err < 0)
goto done;
@@ -787,10 +802,6 @@ int reftable_addition_add(struct reftable_addition *add,
goto done;
}
- err = stack_check_addition(add->stack, get_tempfile_path(tab_file));
- if (err < 0)
- goto done;
-
if (wr->min_update_index < add->next_update_index) {
err = REFTABLE_API_ERROR;
goto done;
@@ -855,14 +866,14 @@ static int stack_compact_locked(struct reftable_stack *st,
}
tab_fd = get_tempfile_fd(tab_file);
- if (st->config.default_permissions &&
- chmod(get_tempfile_path(tab_file), st->config.default_permissions) < 0) {
+ if (st->opts.default_permissions &&
+ chmod(get_tempfile_path(tab_file), st->opts.default_permissions) < 0) {
err = REFTABLE_IO_ERROR;
goto done;
}
wr = reftable_new_writer(reftable_fd_write, reftable_fd_flush,
- &tab_fd, &st->config);
+ &tab_fd, &st->opts);
err = stack_write_compact(st, wr, first, last, config);
if (err < 0)
goto done;
@@ -910,13 +921,14 @@ static int stack_write_compact(struct reftable_stack *st,
st->readers[last]->max_update_index);
err = reftable_new_merged_table(&mt, subtabs, subtabs_len,
- st->config.hash_id);
+ st->opts.hash_id);
if (err < 0) {
reftable_free(subtabs);
goto done;
}
- err = reftable_merged_table_seek_ref(mt, &it, "");
+ merged_table_init_iter(mt, &it, BLOCK_TYPE_REF);
+ err = reftable_iterator_seek_ref(&it, "");
if (err < 0)
goto done;
@@ -940,7 +952,8 @@ static int stack_write_compact(struct reftable_stack *st,
}
reftable_iterator_destroy(&it);
- err = reftable_merged_table_seek_log(mt, &it, "");
+ merged_table_init_iter(mt, &it, BLOCK_TYPE_LOG);
+ err = reftable_iterator_seek_log(&it, "");
if (err < 0)
goto done;
@@ -1100,9 +1113,9 @@ static int stack_compact_range(struct reftable_stack *st,
goto done;
}
- if (st->config.default_permissions) {
+ if (st->opts.default_permissions) {
if (chmod(get_lock_file_path(&tables_list_lock),
- st->config.default_permissions) < 0) {
+ st->opts.default_permissions) < 0) {
err = REFTABLE_IO_ERROR;
goto done;
}
@@ -1216,12 +1229,16 @@ static int segment_size(struct segment *s)
return s->end - s->start;
}
-struct segment suggest_compaction_segment(uint64_t *sizes, size_t n)
+struct segment suggest_compaction_segment(uint64_t *sizes, size_t n,
+ uint8_t factor)
{
struct segment seg = { 0 };
uint64_t bytes;
size_t i;
+ if (!factor)
+ factor = DEFAULT_GEOMETRIC_FACTOR;
+
/*
* If there are no tables or only a single one then we don't have to
* compact anything. The sequence is geometric by definition already.
@@ -1253,7 +1270,7 @@ struct segment suggest_compaction_segment(uint64_t *sizes, size_t n)
* 64, 32, 16, 8, 4, 3, 1
*/
for (i = n - 1; i > 0; i--) {
- if (sizes[i - 1] < sizes[i] * 2) {
+ if (sizes[i - 1] < sizes[i] * factor) {
seg.end = i + 1;
bytes = sizes[i];
break;
@@ -1279,7 +1296,7 @@ struct segment suggest_compaction_segment(uint64_t *sizes, size_t n)
uint64_t curr = bytes;
bytes += sizes[i - 1];
- if (sizes[i - 1] < curr * 2) {
+ if (sizes[i - 1] < curr * factor) {
seg.start = i - 1;
seg.bytes = bytes;
}
@@ -1292,7 +1309,7 @@ static uint64_t *stack_table_sizes_for_compaction(struct reftable_stack *st)
{
uint64_t *sizes =
reftable_calloc(st->merged->stack_len, sizeof(*sizes));
- int version = (st->config.hash_id == GIT_SHA1_FORMAT_ID) ? 1 : 2;
+ int version = (st->opts.hash_id == GIT_SHA1_FORMAT_ID) ? 1 : 2;
int overhead = header_size(version) - 1;
int i = 0;
for (i = 0; i < st->merged->stack_len; i++) {
@@ -1305,7 +1322,8 @@ int reftable_stack_auto_compact(struct reftable_stack *st)
{
uint64_t *sizes = stack_table_sizes_for_compaction(st);
struct segment seg =
- suggest_compaction_segment(sizes, st->merged->stack_len);
+ suggest_compaction_segment(sizes, st->merged->stack_len,
+ st->opts.auto_compaction_factor);
reftable_free(sizes);
if (segment_size(&seg) > 0)
return stack_compact_range_stats(st, seg.start, seg.end - 1,
@@ -1331,9 +1349,11 @@ int reftable_stack_read_ref(struct reftable_stack *st, const char *refname,
int reftable_stack_read_log(struct reftable_stack *st, const char *refname,
struct reftable_log_record *log)
{
- struct reftable_iterator it = { NULL };
- struct reftable_merged_table *mt = reftable_stack_merged_table(st);
- int err = reftable_merged_table_seek_log(mt, &it, refname);
+ struct reftable_iterator it = {0};
+ int err;
+
+ reftable_stack_init_log_iterator(st, &it);
+ err = reftable_iterator_seek_log(&it, refname);
if (err)
goto done;
@@ -1355,65 +1375,6 @@ done:
return err;
}
-static int stack_check_addition(struct reftable_stack *st,
- const char *new_tab_name)
-{
- int err = 0;
- struct reftable_block_source src = { NULL };
- struct reftable_reader *rd = NULL;
- struct reftable_table tab = { NULL };
- struct reftable_ref_record *refs = NULL;
- struct reftable_iterator it = { NULL };
- int cap = 0;
- int len = 0;
- int i = 0;
-
- if (st->config.skip_name_check)
- return 0;
-
- err = reftable_block_source_from_file(&src, new_tab_name);
- if (err < 0)
- goto done;
-
- err = reftable_new_reader(&rd, &src, new_tab_name);
- if (err < 0)
- goto done;
-
- err = reftable_reader_seek_ref(rd, &it, "");
- if (err > 0) {
- err = 0;
- goto done;
- }
- if (err < 0)
- goto done;
-
- while (1) {
- struct reftable_ref_record ref = { NULL };
- err = reftable_iterator_next_ref(&it, &ref);
- if (err > 0)
- break;
- if (err < 0)
- goto done;
-
- REFTABLE_ALLOC_GROW(refs, len + 1, cap);
- refs[len++] = ref;
- }
-
- reftable_table_from_merged_table(&tab, reftable_stack_merged_table(st));
-
- err = validate_ref_record_addition(tab, refs, len);
-
-done:
- for (i = 0; i < len; i++) {
- reftable_ref_record_release(&refs[i]);
- }
-
- free(refs);
- reftable_iterator_destroy(&it);
- reftable_reader_free(rd);
- return err;
-}
-
static int is_table_name(const char *s)
{
const char *dot = strrchr(s, '.');
@@ -1500,11 +1461,11 @@ done:
int reftable_stack_print_directory(const char *stackdir, uint32_t hash_id)
{
struct reftable_stack *stack = NULL;
- struct reftable_write_options cfg = { .hash_id = hash_id };
+ struct reftable_write_options opts = { .hash_id = hash_id };
struct reftable_merged_table *merged = NULL;
struct reftable_table table = { NULL };
- int err = reftable_new_stack(&stack, stackdir, cfg);
+ int err = reftable_new_stack(&stack, stackdir, &opts);
if (err < 0)
goto done;
diff --git a/reftable/stack.h b/reftable/stack.h
index d43efa4760..5b45cff4f7 100644
--- a/reftable/stack.h
+++ b/reftable/stack.h
@@ -20,7 +20,7 @@ struct reftable_stack {
char *reftable_dir;
- struct reftable_write_options config;
+ struct reftable_write_options opts;
struct reftable_reader **readers;
size_t readers_len;
@@ -35,6 +35,7 @@ struct segment {
uint64_t bytes;
};
-struct segment suggest_compaction_segment(uint64_t *sizes, size_t n);
+struct segment suggest_compaction_segment(uint64_t *sizes, size_t n,
+ uint8_t factor);
#endif
diff --git a/reftable/stack_test.c b/reftable/stack_test.c
index 1df3ffce52..0f7b1453e6 100644
--- a/reftable/stack_test.c
+++ b/reftable/stack_test.c
@@ -150,7 +150,7 @@ static void test_reftable_stack_add_one(void)
char *dir = get_tmp_dir(__LINE__);
struct strbuf scratch = STRBUF_INIT;
int mask = umask(002);
- struct reftable_write_options cfg = {
+ struct reftable_write_options opts = {
.default_permissions = 0660,
};
struct reftable_stack *st = NULL;
@@ -163,7 +163,7 @@ static void test_reftable_stack_add_one(void)
};
struct reftable_ref_record dest = { NULL };
struct stat stat_result = { 0 };
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
err = reftable_stack_add(st, &write_test_ref, &ref);
@@ -186,7 +186,7 @@ static void test_reftable_stack_add_one(void)
strbuf_addstr(&scratch, "/tables.list");
err = stat(scratch.buf, &stat_result);
EXPECT(!err);
- EXPECT((stat_result.st_mode & 0777) == cfg.default_permissions);
+ EXPECT((stat_result.st_mode & 0777) == opts.default_permissions);
strbuf_reset(&scratch);
strbuf_addstr(&scratch, dir);
@@ -195,7 +195,7 @@ static void test_reftable_stack_add_one(void)
strbuf_addstr(&scratch, st->readers[0]->name);
err = stat(scratch.buf, &stat_result);
EXPECT(!err);
- EXPECT((stat_result.st_mode & 0777) == cfg.default_permissions);
+ EXPECT((stat_result.st_mode & 0777) == opts.default_permissions);
#else
(void) stat_result;
#endif
@@ -209,7 +209,7 @@ static void test_reftable_stack_add_one(void)
static void test_reftable_stack_uptodate(void)
{
- struct reftable_write_options cfg = { 0 };
+ struct reftable_write_options opts = { 0 };
struct reftable_stack *st1 = NULL;
struct reftable_stack *st2 = NULL;
char *dir = get_tmp_dir(__LINE__);
@@ -232,10 +232,10 @@ static void test_reftable_stack_uptodate(void)
/* simulate multi-process access to the same stack
by creating two stacks for the same directory.
*/
- err = reftable_new_stack(&st1, dir, cfg);
+ err = reftable_new_stack(&st1, dir, &opts);
EXPECT_ERR(err);
- err = reftable_new_stack(&st2, dir, cfg);
+ err = reftable_new_stack(&st2, dir, &opts);
EXPECT_ERR(err);
err = reftable_stack_add(st1, &write_test_ref, &ref1);
@@ -257,8 +257,7 @@ static void test_reftable_stack_uptodate(void)
static void test_reftable_stack_transaction_api(void)
{
char *dir = get_tmp_dir(__LINE__);
-
- struct reftable_write_options cfg = { 0 };
+ struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
int err;
struct reftable_addition *add = NULL;
@@ -271,8 +270,7 @@ static void test_reftable_stack_transaction_api(void)
};
struct reftable_ref_record dest = { NULL };
-
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
reftable_addition_destroy(add);
@@ -301,12 +299,12 @@ static void test_reftable_stack_transaction_api(void)
static void test_reftable_stack_transaction_api_performs_auto_compaction(void)
{
char *dir = get_tmp_dir(__LINE__);
- struct reftable_write_options cfg = {0};
+ struct reftable_write_options opts = {0};
struct reftable_addition *add = NULL;
struct reftable_stack *st = NULL;
int i, n = 20, err;
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
for (i = 0; i <= n; i++) {
@@ -325,7 +323,7 @@ static void test_reftable_stack_transaction_api_performs_auto_compaction(void)
* we can ensure that we indeed honor this setting and have
* better control over when exactly auto compaction runs.
*/
- st->config.disable_auto_compact = i != n;
+ st->opts.disable_auto_compact = i != n;
err = reftable_stack_new_addition(&add, st);
EXPECT_ERR(err);
@@ -361,13 +359,13 @@ static void test_reftable_stack_auto_compaction_fails_gracefully(void)
.value_type = REFTABLE_REF_VAL1,
.value.val1 = {0x01},
};
- struct reftable_write_options cfg = {0};
+ struct reftable_write_options opts = {0};
struct reftable_stack *st;
struct strbuf table_path = STRBUF_INIT;
char *dir = get_tmp_dir(__LINE__);
int err;
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
err = reftable_stack_add(st, write_test_ref, &ref);
@@ -396,44 +394,6 @@ static void test_reftable_stack_auto_compaction_fails_gracefully(void)
clear_dir(dir);
}
-static void test_reftable_stack_validate_refname(void)
-{
- struct reftable_write_options cfg = { 0 };
- struct reftable_stack *st = NULL;
- int err;
- char *dir = get_tmp_dir(__LINE__);
-
- int i;
- struct reftable_ref_record ref = {
- .refname = "a/b",
- .update_index = 1,
- .value_type = REFTABLE_REF_SYMREF,
- .value.symref = "master",
- };
- char *additions[] = { "a", "a/b/c" };
-
- err = reftable_new_stack(&st, dir, cfg);
- EXPECT_ERR(err);
-
- err = reftable_stack_add(st, &write_test_ref, &ref);
- EXPECT_ERR(err);
-
- for (i = 0; i < ARRAY_SIZE(additions); i++) {
- struct reftable_ref_record ref = {
- .refname = additions[i],
- .update_index = 1,
- .value_type = REFTABLE_REF_SYMREF,
- .value.symref = "master",
- };
-
- err = reftable_stack_add(st, &write_test_ref, &ref);
- EXPECT(err == REFTABLE_NAME_CONFLICT);
- }
-
- reftable_stack_destroy(st);
- clear_dir(dir);
-}
-
static int write_error(struct reftable_writer *wr, void *arg)
{
return *((int *)arg);
@@ -442,8 +402,7 @@ static int write_error(struct reftable_writer *wr, void *arg)
static void test_reftable_stack_update_index_check(void)
{
char *dir = get_tmp_dir(__LINE__);
-
- struct reftable_write_options cfg = { 0 };
+ struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
int err;
struct reftable_ref_record ref1 = {
@@ -459,7 +418,7 @@ static void test_reftable_stack_update_index_check(void)
.value.symref = "master",
};
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
err = reftable_stack_add(st, &write_test_ref, &ref1);
@@ -474,12 +433,11 @@ static void test_reftable_stack_update_index_check(void)
static void test_reftable_stack_lock_failure(void)
{
char *dir = get_tmp_dir(__LINE__);
-
- struct reftable_write_options cfg = { 0 };
+ struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
int err, i;
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
for (i = -1; i != REFTABLE_EMPTY_TABLE_ERROR; i--) {
err = reftable_stack_add(st, &write_error, &i);
@@ -494,7 +452,7 @@ static void test_reftable_stack_add(void)
{
int i = 0;
int err = 0;
- struct reftable_write_options cfg = {
+ struct reftable_write_options opts = {
.exact_log_message = 1,
.default_permissions = 0660,
.disable_auto_compact = 1,
@@ -507,7 +465,7 @@ static void test_reftable_stack_add(void)
struct stat stat_result;
int N = ARRAY_SIZE(refs);
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
for (i = 0; i < N; i++) {
@@ -566,7 +524,7 @@ static void test_reftable_stack_add(void)
strbuf_addstr(&path, "/tables.list");
err = stat(path.buf, &stat_result);
EXPECT(!err);
- EXPECT((stat_result.st_mode & 0777) == cfg.default_permissions);
+ EXPECT((stat_result.st_mode & 0777) == opts.default_permissions);
strbuf_reset(&path);
strbuf_addstr(&path, dir);
@@ -575,7 +533,7 @@ static void test_reftable_stack_add(void)
strbuf_addstr(&path, st->readers[0]->name);
err = stat(path.buf, &stat_result);
EXPECT(!err);
- EXPECT((stat_result.st_mode & 0777) == cfg.default_permissions);
+ EXPECT((stat_result.st_mode & 0777) == opts.default_permissions);
#else
(void) stat_result;
#endif
@@ -593,7 +551,7 @@ static void test_reftable_stack_add(void)
static void test_reftable_stack_log_normalize(void)
{
int err = 0;
- struct reftable_write_options cfg = {
+ struct reftable_write_options opts = {
0,
};
struct reftable_stack *st = NULL;
@@ -617,7 +575,7 @@ static void test_reftable_stack_log_normalize(void)
.update_index = 1,
};
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
input.value.update.message = "one\ntwo";
@@ -650,8 +608,7 @@ static void test_reftable_stack_tombstone(void)
{
int i = 0;
char *dir = get_tmp_dir(__LINE__);
-
- struct reftable_write_options cfg = { 0 };
+ struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
int err;
struct reftable_ref_record refs[2] = { { NULL } };
@@ -660,8 +617,7 @@ static void test_reftable_stack_tombstone(void)
struct reftable_ref_record dest = { NULL };
struct reftable_log_record log_dest = { NULL };
-
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
/* even entries add the refs, odd entries delete them. */
@@ -729,8 +685,7 @@ static void test_reftable_stack_tombstone(void)
static void test_reftable_stack_hash_id(void)
{
char *dir = get_tmp_dir(__LINE__);
-
- struct reftable_write_options cfg = { 0 };
+ struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
int err;
@@ -740,24 +695,24 @@ static void test_reftable_stack_hash_id(void)
.value.symref = "target",
.update_index = 1,
};
- struct reftable_write_options cfg32 = { .hash_id = GIT_SHA256_FORMAT_ID };
+ struct reftable_write_options opts32 = { .hash_id = GIT_SHA256_FORMAT_ID };
struct reftable_stack *st32 = NULL;
- struct reftable_write_options cfg_default = { 0 };
+ struct reftable_write_options opts_default = { 0 };
struct reftable_stack *st_default = NULL;
struct reftable_ref_record dest = { NULL };
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
err = reftable_stack_add(st, &write_test_ref, &ref);
EXPECT_ERR(err);
/* can't read it with the wrong hash ID. */
- err = reftable_new_stack(&st32, dir, cfg32);
+ err = reftable_new_stack(&st32, dir, &opts32);
EXPECT(err == REFTABLE_FORMAT_ERROR);
- /* check that we can read it back with default config too. */
- err = reftable_new_stack(&st_default, dir, cfg_default);
+ /* check that we can read it back with default opts too. */
+ err = reftable_new_stack(&st_default, dir, &opts_default);
EXPECT_ERR(err);
err = reftable_stack_read_ref(st_default, "master", &dest);
@@ -774,7 +729,7 @@ static void test_suggest_compaction_segment(void)
{
uint64_t sizes[] = { 512, 64, 17, 16, 9, 9, 9, 16, 2, 16 };
struct segment min =
- suggest_compaction_segment(sizes, ARRAY_SIZE(sizes));
+ suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2);
EXPECT(min.start == 1);
EXPECT(min.end == 10);
}
@@ -783,15 +738,14 @@ static void test_suggest_compaction_segment_nothing(void)
{
uint64_t sizes[] = { 64, 32, 16, 8, 4, 2 };
struct segment result =
- suggest_compaction_segment(sizes, ARRAY_SIZE(sizes));
+ suggest_compaction_segment(sizes, ARRAY_SIZE(sizes), 2);
EXPECT(result.start == result.end);
}
static void test_reflog_expire(void)
{
char *dir = get_tmp_dir(__LINE__);
-
- struct reftable_write_options cfg = { 0 };
+ struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
struct reftable_log_record logs[20] = { { NULL } };
int N = ARRAY_SIZE(logs) - 1;
@@ -802,8 +756,7 @@ static void test_reflog_expire(void)
};
struct reftable_log_record log = { NULL };
-
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
for (i = 1; i <= N; i++) {
@@ -866,21 +819,19 @@ static int write_nothing(struct reftable_writer *wr, void *arg)
static void test_empty_add(void)
{
- struct reftable_write_options cfg = { 0 };
+ struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
int err;
char *dir = get_tmp_dir(__LINE__);
-
struct reftable_stack *st2 = NULL;
-
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
err = reftable_stack_add(st, &write_nothing, NULL);
EXPECT_ERR(err);
- err = reftable_new_stack(&st2, dir, cfg);
+ err = reftable_new_stack(&st2, dir, &opts);
EXPECT_ERR(err);
clear_dir(dir);
reftable_stack_destroy(st);
@@ -899,16 +850,15 @@ static int fastlog2(uint64_t sz)
static void test_reftable_stack_auto_compaction(void)
{
- struct reftable_write_options cfg = {
+ struct reftable_write_options opts = {
.disable_auto_compact = 1,
};
struct reftable_stack *st = NULL;
char *dir = get_tmp_dir(__LINE__);
-
int err, i;
int N = 100;
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
for (i = 0; i < N; i++) {
@@ -938,13 +888,13 @@ static void test_reftable_stack_auto_compaction(void)
static void test_reftable_stack_add_performs_auto_compaction(void)
{
- struct reftable_write_options cfg = { 0 };
+ struct reftable_write_options opts = { 0 };
struct reftable_stack *st = NULL;
struct strbuf refname = STRBUF_INIT;
char *dir = get_tmp_dir(__LINE__);
int err, i, n = 20;
- err = reftable_new_stack(&st, dir, cfg);
+ err = reftable_new_stack(&st, dir, &opts);
EXPECT_ERR(err);
for (i = 0; i <= n; i++) {
@@ -959,7 +909,7 @@ static void test_reftable_stack_add_performs_auto_compaction(void)
* we can ensure that we indeed honor this setting and have
* better control over when exactly auto compaction runs.
*/
- st->config.disable_auto_compact = i != n;
+ st->opts.disable_auto_compact = i != n;
strbuf_reset(&refname);
strbuf_addf(&refname, "branch-%04d", i);
@@ -986,14 +936,13 @@ static void test_reftable_stack_add_performs_auto_compaction(void)
static void test_reftable_stack_compaction_concurrent(void)
{
- struct reftable_write_options cfg = { 0 };
+ struct reftable_write_options opts = { 0 };
struct reftable_stack *st1 = NULL, *st2 = NULL;
char *dir = get_tmp_dir(__LINE__);
-
int err, i;
int N = 3;
- err = reftable_new_stack(&st1, dir, cfg);
+ err = reftable_new_stack(&st1, dir, &opts);
EXPECT_ERR(err);
for (i = 0; i < N; i++) {
@@ -1010,7 +959,7 @@ static void test_reftable_stack_compaction_concurrent(void)
EXPECT_ERR(err);
}
- err = reftable_new_stack(&st2, dir, cfg);
+ err = reftable_new_stack(&st2, dir, &opts);
EXPECT_ERR(err);
err = reftable_stack_compact_all(st1, NULL);
@@ -1036,14 +985,13 @@ static void unclean_stack_close(struct reftable_stack *st)
static void test_reftable_stack_compaction_concurrent_clean(void)
{
- struct reftable_write_options cfg = { 0 };
+ struct reftable_write_options opts = { 0 };
struct reftable_stack *st1 = NULL, *st2 = NULL, *st3 = NULL;
char *dir = get_tmp_dir(__LINE__);
-
int err, i;
int N = 3;
- err = reftable_new_stack(&st1, dir, cfg);
+ err = reftable_new_stack(&st1, dir, &opts);
EXPECT_ERR(err);
for (i = 0; i < N; i++) {
@@ -1060,7 +1008,7 @@ static void test_reftable_stack_compaction_concurrent_clean(void)
EXPECT_ERR(err);
}
- err = reftable_new_stack(&st2, dir, cfg);
+ err = reftable_new_stack(&st2, dir, &opts);
EXPECT_ERR(err);
err = reftable_stack_compact_all(st1, NULL);
@@ -1069,7 +1017,7 @@ static void test_reftable_stack_compaction_concurrent_clean(void)
unclean_stack_close(st1);
unclean_stack_close(st2);
- err = reftable_new_stack(&st3, dir, cfg);
+ err = reftable_new_stack(&st3, dir, &opts);
EXPECT_ERR(err);
err = reftable_stack_clean(st3);
@@ -1105,7 +1053,6 @@ int stack_test_main(int argc, const char *argv[])
RUN_TEST(test_reftable_stack_auto_compaction_fails_gracefully);
RUN_TEST(test_reftable_stack_update_index_check);
RUN_TEST(test_reftable_stack_uptodate);
- RUN_TEST(test_reftable_stack_validate_refname);
RUN_TEST(test_suggest_compaction_segment);
RUN_TEST(test_suggest_compaction_segment_nothing);
return 0;
diff --git a/reftable/writer.c b/reftable/writer.c
index 1d9ff0fbfa..45b3e9ce1f 100644
--- a/reftable/writer.c
+++ b/reftable/writer.c
@@ -109,7 +109,7 @@ static void writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ)
block_start = header_size(writer_version(w));
}
- strbuf_release(&w->last_key);
+ strbuf_reset(&w->last_key);
block_writer_init(&w->block_writer_data, typ, w->block,
w->opts.block_size, block_start,
hash_size(w->opts.hash_id));
@@ -117,25 +117,26 @@ static void writer_reinit_block_writer(struct reftable_writer *w, uint8_t typ)
w->block_writer->restart_interval = w->opts.restart_interval;
}
-static struct strbuf reftable_empty_strbuf = STRBUF_INIT;
-
struct reftable_writer *
reftable_new_writer(ssize_t (*writer_func)(void *, const void *, size_t),
int (*flush_func)(void *),
- void *writer_arg, struct reftable_write_options *opts)
+ void *writer_arg, const struct reftable_write_options *_opts)
{
struct reftable_writer *wp = reftable_calloc(1, sizeof(*wp));
+ struct reftable_write_options opts = {0};
+
+ if (_opts)
+ opts = *_opts;
+ options_set_defaults(&opts);
+ if (opts.block_size >= (1 << 24))
+ BUG("configured block size exceeds 16MB");
+
strbuf_init(&wp->block_writer_data.last_key, 0);
- options_set_defaults(opts);
- if (opts->block_size >= (1 << 24)) {
- /* TODO - error return? */
- abort();
- }
- wp->last_key = reftable_empty_strbuf;
- REFTABLE_CALLOC_ARRAY(wp->block, opts->block_size);
+ strbuf_init(&wp->last_key, 0);
+ REFTABLE_CALLOC_ARRAY(wp->block, opts.block_size);
wp->write = writer_func;
wp->write_arg = writer_arg;
- wp->opts = *opts;
+ wp->opts = opts;
wp->flush = flush_func;
writer_reinit_block_writer(wp, BLOCK_TYPE_REF);
@@ -149,11 +150,21 @@ void reftable_writer_set_limits(struct reftable_writer *w, uint64_t min,
w->max_update_index = max;
}
+static void writer_release(struct reftable_writer *w)
+{
+ if (w) {
+ reftable_free(w->block);
+ w->block = NULL;
+ block_writer_release(&w->block_writer_data);
+ w->block_writer = NULL;
+ writer_clear_index(w);
+ strbuf_release(&w->last_key);
+ }
+}
+
void reftable_writer_free(struct reftable_writer *w)
{
- if (!w)
- return;
- reftable_free(w->block);
+ writer_release(w);
reftable_free(w);
}
@@ -209,7 +220,8 @@ static int writer_add_record(struct reftable_writer *w,
struct reftable_record *rec)
{
struct strbuf key = STRBUF_INIT;
- int err = -1;
+ int err;
+
reftable_record_key(rec, &key);
if (strbuf_cmp(&w->last_key, &key) >= 0) {
err = REFTABLE_API_ERROR;
@@ -218,27 +230,42 @@ static int writer_add_record(struct reftable_writer *w,
strbuf_reset(&w->last_key);
strbuf_addbuf(&w->last_key, &key);
- if (!w->block_writer) {
+ if (!w->block_writer)
writer_reinit_block_writer(w, reftable_record_type(rec));
- }
- assert(block_writer_type(w->block_writer) == reftable_record_type(rec));
+ if (block_writer_type(w->block_writer) != reftable_record_type(rec))
+ BUG("record of type %d added to writer of type %d",
+ reftable_record_type(rec), block_writer_type(w->block_writer));
- if (block_writer_add(w->block_writer, rec) == 0) {
+ /*
+ * Try to add the record to the writer. If this succeeds then we're
+ * done. Otherwise the block writer may have hit the block size limit
+ * and needs to be flushed.
+ */
+ if (!block_writer_add(w->block_writer, rec)) {
err = 0;
goto done;
}
+ /*
+ * The current block is full, so we need to flush and reinitialize the
+ * writer to start writing the next block.
+ */
err = writer_flush_block(w);
- if (err < 0) {
+ if (err < 0)
goto done;
- }
-
writer_reinit_block_writer(w, reftable_record_type(rec));
+
+ /*
+ * Try to add the record to the writer again. If this still fails then
+ * the record does not fit into the block size.
+ *
+ * TODO: it would be great to have `block_writer_add()` return proper
+ * error codes so that we don't have to second-guess the failure
+ * mode here.
+ */
err = block_writer_add(w->block_writer, rec);
- if (err == -1) {
- /* we are writing into memory, so an error can only mean it
- * doesn't fit. */
+ if (err) {
err = REFTABLE_ENTRY_TOO_BIG_ERROR;
goto done;
}
@@ -452,7 +479,7 @@ static int writer_finish_section(struct reftable_writer *w)
bstats->max_index_level = max_level;
/* Reinit lastKey, as the next section can start with any key. */
- w->last_key.len = 0;
+ strbuf_reset(&w->last_key);
return 0;
}
@@ -627,74 +654,87 @@ int reftable_writer_close(struct reftable_writer *w)
}
done:
- /* free up memory. */
- block_writer_release(&w->block_writer_data);
- writer_clear_index(w);
- strbuf_release(&w->last_key);
+ writer_release(w);
return err;
}
static void writer_clear_index(struct reftable_writer *w)
{
- for (size_t i = 0; i < w->index_len; i++)
+ for (size_t i = 0; w->index && i < w->index_len; i++)
strbuf_release(&w->index[i].last_key);
FREE_AND_NULL(w->index);
w->index_len = 0;
w->index_cap = 0;
}
-static const int debug = 0;
-
static int writer_flush_nonempty_block(struct reftable_writer *w)
{
+ struct reftable_index_record index_record = {
+ .last_key = STRBUF_INIT,
+ };
uint8_t typ = block_writer_type(w->block_writer);
- struct reftable_block_stats *bstats =
- writer_reftable_block_stats(w, typ);
- uint64_t block_typ_off = (bstats->blocks == 0) ? w->next : 0;
- int raw_bytes = block_writer_finish(w->block_writer);
- int padding = 0;
- int err = 0;
- struct reftable_index_record ir = { .last_key = STRBUF_INIT };
+ struct reftable_block_stats *bstats;
+ int raw_bytes, padding = 0, err;
+ uint64_t block_typ_off;
+
+ /*
+ * Finish the current block. This will cause the block writer to emit
+ * restart points and potentially compress records in case we are
+ * writing a log block.
+ *
+ * Note that this is still happening in memory.
+ */
+ raw_bytes = block_writer_finish(w->block_writer);
if (raw_bytes < 0)
return raw_bytes;
- if (!w->opts.unpadded && typ != BLOCK_TYPE_LOG) {
+ /*
+ * By default, all records except for log records are padded to the
+ * block size.
+ */
+ if (!w->opts.unpadded && typ != BLOCK_TYPE_LOG)
padding = w->opts.block_size - raw_bytes;
- }
- if (block_typ_off > 0) {
+ bstats = writer_reftable_block_stats(w, typ);
+ block_typ_off = (bstats->blocks == 0) ? w->next : 0;
+ if (block_typ_off > 0)
bstats->offset = block_typ_off;
- }
-
bstats->entries += w->block_writer->entries;
bstats->restarts += w->block_writer->restart_len;
bstats->blocks++;
w->stats.blocks++;
- if (debug) {
- fprintf(stderr, "block %c off %" PRIu64 " sz %d (%d)\n", typ,
- w->next, raw_bytes,
- get_be24(w->block + w->block_writer->header_off + 1));
- }
-
- if (w->next == 0) {
+ /*
+ * If this is the first block we're writing to the table then we need
+ * to also write the reftable header.
+ */
+ if (!w->next)
writer_write_header(w, w->block);
- }
err = padded_write(w, w->block, raw_bytes, padding);
if (err < 0)
return err;
+ /*
+ * Add an index record for every block that we're writing. If we end up
+ * having more than a threshold of index records we will end up writing
+ * an index section in `writer_finish_section()`. Each index record
+ * contains the last record key of the block it is indexing as well as
+ * the offset of that block.
+ *
+ * Note that this also applies when flushing index blocks, in which
+ * case we will end up with a multi-level index.
+ */
REFTABLE_ALLOC_GROW(w->index, w->index_len + 1, w->index_cap);
-
- ir.offset = w->next;
- strbuf_reset(&ir.last_key);
- strbuf_addbuf(&ir.last_key, &w->block_writer->last_key);
- w->index[w->index_len] = ir;
-
+ index_record.offset = w->next;
+ strbuf_reset(&index_record.last_key);
+ strbuf_addbuf(&index_record.last_key, &w->block_writer->last_key);
+ w->index[w->index_len] = index_record;
w->index_len++;
+
w->next += padding + raw_bytes;
w->block_writer = NULL;
+
return 0;
}
diff --git a/remote-curl.c b/remote-curl.c
index 0b6d7815fd..6008d7e87c 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -266,12 +266,23 @@ static struct ref *parse_git_refs(struct discovery *heads, int for_push)
return list;
}
+/*
+ * Try to detect the hash algorithm used by the remote repository when using
+ * the dumb HTTP transport. As dumb transports cannot tell us the object hash
+ * directly have to derive it from the advertised ref lengths.
+ */
static const struct git_hash_algo *detect_hash_algo(struct discovery *heads)
{
const char *p = memchr(heads->buf, '\t', heads->len);
int algo;
+
+ /*
+ * In case the remote has no refs we have no way to reliably determine
+ * the object hash used by that repository. In that case we simply fall
+ * back to SHA1, which may or may not be correct.
+ */
if (!p)
- return the_hash_algo;
+ return &hash_algos[GIT_HASH_SHA1];
algo = hash_algo_by_length((p - heads->buf) / 2);
if (algo == GIT_HASH_UNKNOWN)
@@ -295,6 +306,12 @@ static struct ref *parse_info_refs(struct discovery *heads)
"is this a git repository?",
transport_anonymize_url(url.buf));
+ /*
+ * Set the repository's hash algo to whatever we have just detected.
+ * This ensures that we can correctly parse the remote references.
+ */
+ repo_set_hash_algo(the_repository, hash_algo_by_ptr(options.hash_algo));
+
data = heads->buf;
start = NULL;
mid = data;
@@ -889,7 +906,7 @@ static curl_off_t xcurl_off_t(size_t len)
static int post_rpc(struct rpc_state *rpc, int stateless_connect, int flush_received)
{
struct active_request_slot *slot;
- struct curl_slist *headers = http_copy_default_headers();
+ struct curl_slist *headers = NULL;
int use_gzip = rpc->gzip_request;
char *gzip_body = NULL;
size_t gzip_size = 0;
@@ -922,20 +939,24 @@ static int post_rpc(struct rpc_state *rpc, int stateless_connect, int flush_rece
do {
err = probe_rpc(rpc, &results);
if (err == HTTP_REAUTH)
- credential_fill(&http_auth);
+ credential_fill(&http_auth, 0);
} while (err == HTTP_REAUTH);
if (err != HTTP_OK)
return -1;
- if (results.auth_avail & CURLAUTH_GSSNEGOTIATE)
+ if (results.auth_avail & CURLAUTH_GSSNEGOTIATE || http_auth.authtype)
needs_100_continue = 1;
}
+retry:
+ headers = http_copy_default_headers();
headers = curl_slist_append(headers, rpc->hdr_content_type);
headers = curl_slist_append(headers, rpc->hdr_accept);
headers = curl_slist_append(headers, needs_100_continue ?
"Expect: 100-continue" : "Expect:");
+ headers = http_append_auth_header(&http_auth, headers);
+
/* Add Accept-Language header */
if (rpc->hdr_accept_language)
headers = curl_slist_append(headers, rpc->hdr_accept_language);
@@ -944,7 +965,6 @@ static int post_rpc(struct rpc_state *rpc, int stateless_connect, int flush_rece
if (rpc->protocol_header)
headers = curl_slist_append(headers, rpc->protocol_header);
-retry:
slot = get_active_slot();
curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
@@ -1041,7 +1061,8 @@ retry:
rpc->any_written = 0;
err = run_slot(slot, NULL);
if (err == HTTP_REAUTH && !large_request) {
- credential_fill(&http_auth);
+ credential_fill(&http_auth, 0);
+ curl_slist_free_all(headers);
goto retry;
}
if (err != HTTP_OK)
diff --git a/remote.c b/remote.c
index 2b650b813b..ec8c158e60 100644
--- a/remote.c
+++ b/remote.c
@@ -1198,8 +1198,10 @@ static char *guess_ref(const char *name, struct ref *peer)
{
struct strbuf buf = STRBUF_INIT;
- const char *r = resolve_ref_unsafe(peer->name, RESOLVE_REF_READING,
- NULL, NULL);
+ const char *r = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ peer->name,
+ RESOLVE_REF_READING,
+ NULL, NULL);
if (!r)
return NULL;
@@ -1316,9 +1318,10 @@ static int match_explicit(struct ref *src, struct ref *dst,
if (!dst_value) {
int flag;
- dst_value = resolve_ref_unsafe(matched_src->name,
- RESOLVE_REF_READING,
- NULL, &flag);
+ dst_value = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ matched_src->name,
+ RESOLVE_REF_READING,
+ NULL, &flag);
if (!dst_value ||
((flag & REF_ISSYMREF) &&
!starts_with(dst_value, "refs/heads/")))
@@ -1882,7 +1885,7 @@ const char *branch_get_upstream(struct branch *branch, struct strbuf *err)
* or because it is not a real branch, and get_branch
* auto-vivified it?
*/
- if (!ref_exists(branch->refname))
+ if (!refs_ref_exists(get_main_ref_store(the_repository), branch->refname))
return error_buf(err, _("no such branch: '%s'"),
branch->name);
return error_buf(err,
@@ -2168,13 +2171,13 @@ static int stat_branch_pair(const char *branch_name, const char *base,
struct strvec argv = STRVEC_INIT;
/* Cannot stat if what we used to build on no longer exists */
- if (read_ref(base, &oid))
+ if (refs_read_ref(get_main_ref_store(the_repository), base, &oid))
return -1;
theirs = lookup_commit_reference(the_repository, &oid);
if (!theirs)
return -1;
- if (read_ref(branch_name, &oid))
+ if (refs_read_ref(get_main_ref_store(the_repository), branch_name, &oid))
return -1;
ours = lookup_commit_reference(the_repository, &oid);
if (!ours)
@@ -2278,7 +2281,8 @@ int format_tracking_info(struct branch *branch, struct strbuf *sb,
upstream_is_gone = 1;
}
- base = shorten_unambiguous_ref(full_base, 0);
+ base = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+ full_base, 0);
if (upstream_is_gone) {
strbuf_addf(sb,
_("Your branch is based on '%s', but the upstream is gone.\n"),
@@ -2358,7 +2362,8 @@ struct ref *get_local_heads(void)
{
struct ref *local_refs = NULL, **local_tail = &local_refs;
- for_each_ref(one_local_ref, &local_tail);
+ refs_for_each_ref(get_main_ref_store(the_repository), one_local_ref,
+ &local_tail);
return local_refs;
}
@@ -2468,7 +2473,8 @@ struct ref *get_stale_heads(struct refspec *rs, struct ref *fetch_map)
for (ref = fetch_map; ref; ref = ref->next)
string_list_append(&ref_names, ref->name);
string_list_sort(&ref_names);
- for_each_ref(get_stale_heads_cb, &info);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ get_stale_heads_cb, &info);
string_list_clear(&ref_names, 0);
return stale_refs;
}
@@ -2553,7 +2559,7 @@ static int remote_tracking(struct remote *remote, const char *refname,
dst = apply_refspecs(&remote->fetch, refname);
if (!dst)
return -1; /* no tracking ref for refname at remote */
- if (read_ref(dst, oid))
+ if (refs_read_ref(get_main_ref_store(the_repository), dst, oid))
return -1; /* we know what the tracking ref is but we cannot read it */
*dst_refname = dst;
@@ -2659,12 +2665,16 @@ static int is_reachable_in_reflog(const char *local, const struct ref *remote)
* Get the timestamp from the latest entry
* of the remote-tracking ref's reflog.
*/
- for_each_reflog_ent_reverse(remote->tracking_ref, peek_reflog, &date);
+ refs_for_each_reflog_ent_reverse(get_main_ref_store(the_repository),
+ remote->tracking_ref, peek_reflog,
+ &date);
cb.remote_commit = commit;
cb.local_commits = &arr;
cb.remote_reflog_timestamp = date;
- ret = for_each_reflog_ent_reverse(local, check_and_collect_until, &cb);
+ ret = refs_for_each_reflog_ent_reverse(get_main_ref_store(the_repository),
+ local, check_and_collect_until,
+ &cb);
/* We found an entry in the reflog. */
if (ret > 0)
diff --git a/repo-settings.c b/repo-settings.c
index a0b590bc6c..2b4e68731b 100644
--- a/repo-settings.c
+++ b/repo-settings.c
@@ -23,6 +23,7 @@ void prepare_repo_settings(struct repository *r)
int value;
const char *strval;
int manyfiles;
+ int read_changed_paths;
if (!r->gitdir)
BUG("Cannot add settings for uninitialized repository");
@@ -54,7 +55,10 @@ void prepare_repo_settings(struct repository *r)
/* Commit graph config or default, does not cascade (simple) */
repo_cfg_bool(r, "core.commitgraph", &r->settings.core_commit_graph, 1);
repo_cfg_int(r, "commitgraph.generationversion", &r->settings.commit_graph_generation_version, 2);
- repo_cfg_bool(r, "commitgraph.readchangedpaths", &r->settings.commit_graph_read_changed_paths, 1);
+ repo_cfg_bool(r, "commitgraph.readchangedpaths", &read_changed_paths, 1);
+ repo_cfg_int(r, "commitgraph.changedpathsversion",
+ &r->settings.commit_graph_changed_paths_version,
+ read_changed_paths ? -1 : 0);
repo_cfg_bool(r, "gc.writecommitgraph", &r->settings.gc_write_commit_graph, 1);
repo_cfg_bool(r, "fetch.writecommitgraph", &r->settings.fetch_write_commit_graph, 0);
diff --git a/repository.c b/repository.c
index e15b416944..c96f2e915c 100644
--- a/repository.c
+++ b/repository.c
@@ -1,10 +1,6 @@
-/*
- * not really _using_ the compat macros, just make sure the_index
- * declaration matches the definition in this file.
- */
-#define USE_THE_INDEX_VARIABLE
#include "git-compat-util.h"
#include "abspath.h"
+#include "environment.h"
#include "repository.h"
#include "object-store-ll.h"
#include "config.h"
@@ -22,21 +18,54 @@
/* The main repository */
static struct repository the_repo;
-struct repository *the_repository;
-struct index_state the_index;
+struct repository *the_repository = &the_repo;
-void initialize_the_repository(void)
+static void set_default_hash_algo(struct repository *repo)
{
- the_repository = &the_repo;
+ const char *hash_name;
+ int algo;
- the_repo.index = &the_index;
- the_repo.objects = raw_object_store_new();
- the_repo.remote_state = remote_state_new();
- the_repo.parsed_objects = parsed_object_pool_new();
+ hash_name = getenv(GIT_DEFAULT_HASH_ENVIRONMENT);
+ if (!hash_name)
+ return;
+ algo = hash_algo_by_name(hash_name);
- index_state_init(&the_index, the_repository);
+ /*
+ * NEEDSWORK: after all, falling back to SHA-1 by assigning
+ * GIT_HASH_SHA1 to algo here, instead of returning, may give
+ * us better behaviour.
+ */
+ if (algo == GIT_HASH_UNKNOWN)
+ return;
- repo_set_hash_algo(&the_repo, GIT_HASH_SHA1);
+ repo_set_hash_algo(repo, algo);
+}
+
+void initialize_repository(struct repository *repo)
+{
+ repo->objects = raw_object_store_new();
+ repo->remote_state = remote_state_new();
+ repo->parsed_objects = parsed_object_pool_new();
+ ALLOC_ARRAY(repo->index, 1);
+ index_state_init(repo->index, repo);
+
+ /*
+ * When a command runs inside a repository, it learns what
+ * hash algorithm is in use from the repository, but some
+ * commands are designed to work outside a repository, yet
+ * they want to access the_hash_algo, if only for the length
+ * of the hashed value to see if their input looks like a
+ * plausible hash value.
+ *
+ * We are in the process of identifying the codepaths and
+ * giving them an appropriate default individually; any
+ * unconverted codepath that tries to access the_hash_algo
+ * will thus fail. The end-users however have an escape hatch
+ * to set GIT_DEFAULT_HASH environment variable to "sha1" get
+ * back the old behaviour of defaulting to SHA-1.
+ */
+ if (repo == the_repository)
+ set_default_hash_algo(repo);
}
static void expand_base_dir(char **out, const char *in,
@@ -188,9 +217,7 @@ int repo_init(struct repository *repo,
struct repository_format format = REPOSITORY_FORMAT_INIT;
memset(repo, 0, sizeof(*repo));
- repo->objects = raw_object_store_new();
- repo->parsed_objects = parsed_object_pool_new();
- repo->remote_state = remote_state_new();
+ initialize_repository(repo);
if (repo_init_gitdir(repo, gitdir))
goto error;
@@ -295,6 +322,8 @@ void repo_clear(struct repository *repo)
parsed_object_pool_clear(repo->parsed_objects);
FREE_AND_NULL(repo->parsed_objects);
+ FREE_AND_NULL(repo->settings.fsmonitor);
+
if (repo->config) {
git_configset_clear(repo->config);
FREE_AND_NULL(repo->config);
@@ -307,8 +336,7 @@ void repo_clear(struct repository *repo)
if (repo->index) {
discard_index(repo->index);
- if (repo->index != &the_index)
- FREE_AND_NULL(repo->index);
+ FREE_AND_NULL(repo->index);
}
if (repo->promisor_remote_config) {
diff --git a/repository.h b/repository.h
index 268436779c..efa079970d 100644
--- a/repository.h
+++ b/repository.h
@@ -33,7 +33,7 @@ struct repo_settings {
int core_commit_graph;
int commit_graph_generation_version;
- int commit_graph_read_changed_paths;
+ int commit_graph_changed_paths_version;
int gc_write_commit_graph;
int fetch_write_commit_graph;
int command_requires_full_index;
@@ -187,9 +187,6 @@ struct repository {
};
extern struct repository *the_repository;
-#ifdef USE_THE_INDEX_VARIABLE
-extern struct index_state the_index;
-#endif
/*
* Define a custom repository layout. Any field can be NULL, which
@@ -210,7 +207,7 @@ void repo_set_worktree(struct repository *repo, const char *path);
void repo_set_hash_algo(struct repository *repo, int algo);
void repo_set_compat_hash_algo(struct repository *repo, int compat_algo);
void repo_set_ref_storage_format(struct repository *repo, unsigned int format);
-void initialize_the_repository(void);
+void initialize_repository(struct repository *repo);
RESULT_MUST_BE_USED
int repo_init(struct repository *r, const char *gitdir, const char *worktree);
diff --git a/rerere.c b/rerere.c
index c7e1f8fd25..2ad46ab2a1 100644
--- a/rerere.c
+++ b/rerere.c
@@ -393,12 +393,8 @@ static int handle_conflict(struct strbuf *out, struct rerere_io *io,
strbuf_addbuf(out, &two);
rerere_strbuf_putconflict(out, '>', marker_size);
if (ctx) {
- the_hash_algo->update_fn(ctx, one.buf ?
- one.buf : "",
- one.len + 1);
- the_hash_algo->update_fn(ctx, two.buf ?
- two.buf : "",
- two.len + 1);
+ the_hash_algo->update_fn(ctx, one.buf, one.len + 1);
+ the_hash_algo->update_fn(ctx, two.buf, two.len + 1);
}
break;
} else if (hunk == RR_SIDE_1)
@@ -457,7 +453,7 @@ static int handle_path(unsigned char *hash, struct rerere_io *io, int marker_siz
/*
* Scan the path for conflicts, do the "handle_path()" thing above, and
- * return the number of conflict hunks found.
+ * return true iff conflict hunks were found.
*/
static int handle_file(struct index_state *istate,
const char *path, unsigned char *hash, const char *output)
@@ -502,9 +498,11 @@ static int handle_file(struct index_state *istate,
}
/*
- * Look at a cache entry at "i" and see if it is not conflicting,
- * conflicting and we are willing to handle, or conflicting and
- * we are unable to handle, and return the determination in *type.
+ * Look at a cache entry at "i" and see if it is not conflicting
+ * (RESOLVED), conflicting and we are willing to handle (THREE_STAGED),
+ * or conflicting and we are unable to handle (PUNTED), and return the
+ * determination in *type.
+ *
* Return the cache index to be looked at next, by skipping the
* stages we have already looked at in this invocation of this
* function.
@@ -512,6 +510,7 @@ static int handle_file(struct index_state *istate,
static int check_one_conflict(struct index_state *istate, int i, int *type)
{
const struct cache_entry *e = istate->cache[i];
+ unsigned int seen_stages = 0;
if (!ce_stage(e)) {
*type = RESOLVED;
@@ -519,24 +518,17 @@ static int check_one_conflict(struct index_state *istate, int i, int *type)
}
*type = PUNTED;
- while (i < istate->cache_nr && ce_stage(istate->cache[i]) == 1)
- i++;
-
- /* Only handle regular files with both stages #2 and #3 */
- if (i + 1 < istate->cache_nr) {
- const struct cache_entry *e2 = istate->cache[i];
- const struct cache_entry *e3 = istate->cache[i + 1];
- if (ce_stage(e2) == 2 &&
- ce_stage(e3) == 3 &&
- ce_same_name(e, e3) &&
- S_ISREG(e2->ce_mode) &&
- S_ISREG(e3->ce_mode))
- *type = THREE_STAGED;
+ for (; i < istate->cache_nr; i++) {
+ const struct cache_entry *n = istate->cache[i];
+ if (!ce_same_name(n, e))
+ break;
+ if (S_ISREG(n->ce_mode))
+ seen_stages |= 1u << (ce_stage(n) - 1);
}
- /* Skip the entries with the same name */
- while (i < istate->cache_nr && ce_same_name(e, istate->cache[i]))
- i++;
+ if ((seen_stages & 6) == 6)
+ *type = THREE_STAGED; /* has both stages #2 and #3 */
+
return i;
}
@@ -624,7 +616,7 @@ static int try_merge(struct index_state *istate,
if (read_mmfile(&base, rerere_path(id, "preimage")) ||
read_mmfile(&other, rerere_path(id, "postimage"))) {
- ret = LL_MERGE_CONFLICT;
+ ret = LL_MERGE_ERROR;
} else {
/*
* A three-way merge. Note that this honors user-customizable
diff --git a/reset.c b/reset.c
index d619cb7115..937f11c0f4 100644
--- a/reset.c
+++ b/reset.c
@@ -47,11 +47,13 @@ static int update_refs(const struct reset_head_opts *opts,
strbuf_addstr(&msg, "updating ORIG_HEAD");
reflog_orig_head = msg.buf;
}
- update_ref(reflog_orig_head, "ORIG_HEAD",
- orig_head ? orig_head : head,
- old_orig, 0, UPDATE_REFS_MSG_ON_ERR);
+ refs_update_ref(get_main_ref_store(the_repository),
+ reflog_orig_head, "ORIG_HEAD",
+ orig_head ? orig_head : head,
+ old_orig, 0, UPDATE_REFS_MSG_ON_ERR);
} else if (old_orig)
- delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
+ refs_delete_ref(get_main_ref_store(the_repository),
+ NULL, "ORIG_HEAD", old_orig, 0);
}
if (!reflog_head) {
@@ -60,16 +62,19 @@ static int update_refs(const struct reset_head_opts *opts,
reflog_head = msg.buf;
}
if (!switch_to_branch)
- ret = update_ref(reflog_head, "HEAD", oid, head,
- detach_head ? REF_NO_DEREF : 0,
- UPDATE_REFS_MSG_ON_ERR);
+ ret = refs_update_ref(get_main_ref_store(the_repository),
+ reflog_head, "HEAD", oid, head,
+ detach_head ? REF_NO_DEREF : 0,
+ UPDATE_REFS_MSG_ON_ERR);
else {
- ret = update_ref(reflog_branch ? reflog_branch : reflog_head,
- switch_to_branch, oid, NULL, 0,
- UPDATE_REFS_MSG_ON_ERR);
+ ret = refs_update_ref(get_main_ref_store(the_repository),
+ reflog_branch ? reflog_branch : reflog_head,
+ switch_to_branch, oid, NULL, 0,
+ UPDATE_REFS_MSG_ON_ERR);
if (!ret)
- ret = create_symref("HEAD", switch_to_branch,
- reflog_head);
+ ret = refs_update_symref(get_main_ref_store(the_repository),
+ "HEAD", switch_to_branch,
+ reflog_head);
}
if (!ret && run_hook)
run_hooks_l("post-checkout",
diff --git a/revision.c b/revision.c
index 7e45f765d9..ec59208860 100644
--- a/revision.c
+++ b/revision.c
@@ -844,17 +844,28 @@ static int rev_compare_tree(struct rev_info *revs,
return tree_difference;
}
-static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
+static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit,
+ int nth_parent)
{
struct tree *t1 = repo_get_commit_tree(the_repository, commit);
+ int bloom_ret = -1;
if (!t1)
return 0;
+ if (!nth_parent && revs->bloom_keys_nr) {
+ bloom_ret = check_maybe_different_in_bloom_filter(revs, commit);
+ if (!bloom_ret)
+ return 1;
+ }
+
tree_difference = REV_TREE_SAME;
revs->pruning.flags.has_changes = 0;
diff_tree_oid(NULL, &t1->object.oid, "", &revs->pruning);
+ if (bloom_ret == 1 && tree_difference == REV_TREE_SAME)
+ count_bloom_filter_false_positive++;
+
return tree_difference == REV_TREE_SAME;
}
@@ -892,7 +903,7 @@ static int compact_treesame(struct rev_info *revs, struct commit *commit, unsign
if (nth_parent != 0)
die("compact_treesame %u", nth_parent);
old_same = !!(commit->object.flags & TREESAME);
- if (rev_same_tree_as_empty(revs, commit))
+ if (rev_same_tree_as_empty(revs, commit, nth_parent))
commit->object.flags |= TREESAME;
else
commit->object.flags &= ~TREESAME;
@@ -988,7 +999,14 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
return;
if (!commit->parents) {
- if (rev_same_tree_as_empty(revs, commit))
+ /*
+ * Pretend as if we are comparing ourselves to the
+ * (non-existent) first parent of this commit object. Even
+ * though no such parent exists, its changed-path Bloom filter
+ * (if one exists) is relative to the empty tree, using Bloom
+ * filters is allowed here.
+ */
+ if (rev_same_tree_as_empty(revs, commit, 0))
commit->object.flags |= TREESAME;
return;
}
@@ -1069,7 +1087,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
case REV_TREE_NEW:
if (revs->remove_empty_trees &&
- rev_same_tree_as_empty(revs, p)) {
+ rev_same_tree_as_empty(revs, p, nth_parent)) {
/* We are adding all the specified
* paths from this parent, so the
* history beyond this parent is not
@@ -1738,7 +1756,8 @@ void add_reflogs_to_pending(struct rev_info *revs, unsigned flags)
cb.all_revs = revs;
cb.all_flags = flags;
cb.wt = NULL;
- for_each_reflog(handle_one_reflog, &cb);
+ refs_for_each_reflog(get_main_ref_store(the_repository),
+ handle_one_reflog, &cb);
if (!revs->single_worktree)
add_other_reflogs_to_pending(&cb);
@@ -1979,9 +1998,9 @@ static const char *lookup_other_head(struct object_id *oid)
};
for (i = 0; i < ARRAY_SIZE(other_head); i++)
- if (!read_ref_full(other_head[i],
- RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
- oid, NULL)) {
+ if (!refs_read_ref_full(get_main_ref_store(the_repository), other_head[i],
+ RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+ oid, NULL)) {
if (is_null_oid(oid))
die(_("%s exists but is a symbolic ref"), other_head[i]);
return other_head[i];
@@ -2789,7 +2808,8 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
} else if ((argcount = parse_long_opt("glob", argv, &optarg))) {
struct all_refs_cb cb;
init_all_refs_cb(&cb, revs, *flags);
- for_each_glob_ref(handle_one_ref, optarg, &cb);
+ refs_for_each_glob_ref(get_main_ref_store(the_repository),
+ handle_one_ref, optarg, &cb);
clear_ref_exclusions(&revs->ref_excludes);
return argcount;
} else if ((argcount = parse_long_opt("exclude", argv, &optarg))) {
@@ -2804,7 +2824,9 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
return error(_("options '%s' and '%s' cannot be used together"),
"--exclude-hidden", "--branches");
init_all_refs_cb(&cb, revs, *flags);
- for_each_glob_ref_in(handle_one_ref, optarg, "refs/heads/", &cb);
+ refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
+ handle_one_ref, optarg,
+ "refs/heads/", &cb);
clear_ref_exclusions(&revs->ref_excludes);
} else if (skip_prefix(arg, "--tags=", &optarg)) {
struct all_refs_cb cb;
@@ -2812,7 +2834,9 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
return error(_("options '%s' and '%s' cannot be used together"),
"--exclude-hidden", "--tags");
init_all_refs_cb(&cb, revs, *flags);
- for_each_glob_ref_in(handle_one_ref, optarg, "refs/tags/", &cb);
+ refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
+ handle_one_ref, optarg,
+ "refs/tags/", &cb);
clear_ref_exclusions(&revs->ref_excludes);
} else if (skip_prefix(arg, "--remotes=", &optarg)) {
struct all_refs_cb cb;
@@ -2820,7 +2844,9 @@ static int handle_revision_pseudo_opt(struct rev_info *revs,
return error(_("options '%s' and '%s' cannot be used together"),
"--exclude-hidden", "--remotes");
init_all_refs_cb(&cb, revs, *flags);
- for_each_glob_ref_in(handle_one_ref, optarg, "refs/remotes/", &cb);
+ refs_for_each_glob_ref_in(get_main_ref_store(the_repository),
+ handle_one_ref, optarg,
+ "refs/remotes/", &cb);
clear_ref_exclusions(&revs->ref_excludes);
} else if (!strcmp(arg, "--reflog")) {
add_reflogs_to_pending(revs, *flags);
@@ -2911,7 +2937,8 @@ static void NORETURN diagnose_missing_default(const char *def)
int flags;
const char *refname;
- refname = resolve_ref_unsafe(def, 0, NULL, &flags);
+ refname = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ def, 0, NULL, &flags);
if (!refname || !(flags & REF_ISSYMREF) || (flags & REF_ISBROKEN))
die(_("your current branch appears to be broken"));
diff --git a/scalar.c b/scalar.c
index fb2940c2a0..7234049a1b 100644
--- a/scalar.c
+++ b/scalar.c
@@ -645,7 +645,6 @@ static int cmd_reconfigure(int argc, const char **argv)
};
struct string_list scalar_repos = STRING_LIST_INIT_DUP;
int i, res = 0;
- struct repository r = { NULL };
struct strbuf commondir = STRBUF_INIT, gitdir = STRBUF_INIT;
argc = parse_options(argc, argv, NULL, options,
@@ -665,6 +664,7 @@ static int cmd_reconfigure(int argc, const char **argv)
for (i = 0; i < scalar_repos.nr; i++) {
int succeeded = 0;
+ struct repository *old_repo, r = { NULL };
const char *dir = scalar_repos.items[i].string;
strbuf_reset(&commondir);
@@ -712,13 +712,17 @@ static int cmd_reconfigure(int argc, const char **argv)
git_config_clear();
+ if (repo_init(&r, gitdir.buf, commondir.buf))
+ goto loop_end;
+
+ old_repo = the_repository;
the_repository = &r;
- r.commondir = commondir.buf;
- r.gitdir = gitdir.buf;
if (set_recommended_config(1) >= 0)
succeeded = 1;
+ the_repository = old_repo;
+
loop_end:
if (!succeeded) {
res = -1;
diff --git a/sequencer.c b/sequencer.c
index 2c19846385..0518a4a725 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -207,6 +207,46 @@ static GIT_PATH_FUNC(rebase_path_no_reschedule_failed_exec, "rebase-merge/no-res
static GIT_PATH_FUNC(rebase_path_drop_redundant_commits, "rebase-merge/drop_redundant_commits")
static GIT_PATH_FUNC(rebase_path_keep_redundant_commits, "rebase-merge/keep_redundant_commits")
+/*
+ * A 'struct replay_ctx' represents the private state of the sequencer.
+ */
+struct replay_ctx {
+ /*
+ * The commit message that will be used except at the end of a
+ * chain of fixup and squash commands.
+ */
+ struct strbuf message;
+ /*
+ * The list of completed fixup and squash commands in the
+ * current chain.
+ */
+ struct strbuf current_fixups;
+ /*
+ * Stores the reflog message that will be used when creating a
+ * commit. Points to a static buffer and should not be free()'d.
+ */
+ const char *reflog_message;
+ /*
+ * The number of completed fixup and squash commands in the
+ * current chain.
+ */
+ int current_fixup_count;
+ /*
+ * Whether message contains a commit message.
+ */
+ unsigned have_message :1;
+};
+
+struct replay_ctx* replay_ctx_new(void)
+{
+ struct replay_ctx *ctx = xcalloc(1, sizeof(*ctx));
+
+ strbuf_init(&ctx->current_fixups, 0);
+ strbuf_init(&ctx->message, 0);
+
+ return ctx;
+}
+
/**
* A 'struct update_refs_record' represents a value in the update-refs
* list. We use a string_list to map refs to these (before, after) pairs.
@@ -226,7 +266,7 @@ static struct update_ref_record *init_update_ref_record(const char *ref)
oidcpy(&rec->after, null_oid());
/* This may fail, but that's fine, we will keep the null OID. */
- read_ref(ref, &rec->before);
+ refs_read_ref(get_main_ref_store(the_repository), ref, &rec->before);
return rec;
}
@@ -319,35 +359,32 @@ static const char *get_todo_path(const struct replay_opts *opts)
static int has_conforming_footer(struct strbuf *sb, struct strbuf *sob,
size_t ignore_footer)
{
- struct process_trailer_options opts = PROCESS_TRAILER_OPTIONS_INIT;
- struct trailer_info info;
- size_t i;
+ struct trailer_iterator iter;
+ size_t i = 0;
int found_sob = 0, found_sob_last = 0;
char saved_char;
- opts.no_divider = 1;
-
if (ignore_footer) {
saved_char = sb->buf[sb->len - ignore_footer];
sb->buf[sb->len - ignore_footer] = '\0';
}
- trailer_info_get(&opts, sb->buf, &info);
+ trailer_iterator_init(&iter, sb->buf);
if (ignore_footer)
sb->buf[sb->len - ignore_footer] = saved_char;
- if (info.trailer_block_start == info.trailer_block_end)
- return 0;
+ while (trailer_iterator_advance(&iter)) {
+ i++;
+ if (sob && !strncmp(iter.raw, sob->buf, sob->len))
+ found_sob = i;
+ }
+ trailer_iterator_release(&iter);
- for (i = 0; i < info.trailer_nr; i++)
- if (sob && !strncmp(info.trailers[i], sob->buf, sob->len)) {
- found_sob = 1;
- if (i == info.trailer_nr - 1)
- found_sob_last = 1;
- }
+ if (!i)
+ return 0;
- trailer_info_release(&info);
+ found_sob_last = (int)i == found_sob;
if (found_sob_last)
return 3;
@@ -366,17 +403,26 @@ static const char *gpg_sign_opt_quoted(struct replay_opts *opts)
return buf.buf;
}
+static void replay_ctx_release(struct replay_ctx *ctx)
+{
+ strbuf_release(&ctx->current_fixups);
+ strbuf_release(&ctx->message);
+}
+
void replay_opts_release(struct replay_opts *opts)
{
+ struct replay_ctx *ctx = opts->ctx;
+
free(opts->gpg_sign);
free(opts->reflog_action);
free(opts->default_strategy);
free(opts->strategy);
strvec_clear (&opts->xopts);
- strbuf_release(&opts->current_fixups);
if (opts->revs)
release_revisions(opts->revs);
free(opts->revs);
+ replay_ctx_release(ctx);
+ free(opts->ctx);
}
int sequencer_remove_state(struct replay_opts *opts)
@@ -391,7 +437,7 @@ int sequencer_remove_state(struct replay_opts *opts)
char *eol = strchr(p, '\n');
if (eol)
*eol = '\0';
- if (delete_ref("(rebase) cleanup", p, NULL, 0) < 0) {
+ if (refs_delete_ref(get_main_ref_store(the_repository), "(rebase) cleanup", p, NULL, 0) < 0) {
warning(_("could not delete '%s'"), p);
ret = -1;
}
@@ -612,11 +658,12 @@ static int fast_forward_to(struct repository *r,
strbuf_addf(&sb, "%s: fast-forward", action_name(opts));
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction ||
ref_transaction_update(transaction, "HEAD",
to, unborn && !is_rebase_i(opts) ?
- null_oid() : from,
+ null_oid() : from, NULL, NULL,
0, sb.buf, &err) ||
ref_transaction_commit(transaction, &err)) {
ref_transaction_free(transaction);
@@ -792,11 +839,12 @@ static int is_index_unchanged(struct repository *r)
struct index_state *istate = r->index;
const char *head_name;
- if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, &head_oid, NULL)) {
+ if (!refs_resolve_ref_unsafe(get_main_ref_store(the_repository), "HEAD", RESOLVE_REF_READING, &head_oid, NULL)) {
/* Check to see if this is an unborn branch */
- head_name = resolve_ref_unsafe("HEAD",
- RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
- &head_oid, NULL);
+ head_name = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ "HEAD",
+ RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+ &head_oid, NULL);
if (!head_name ||
!starts_with(head_name, "refs/heads/") ||
!is_null_oid(&head_oid))
@@ -1084,6 +1132,7 @@ static int run_git_commit(const char *defmsg,
struct replay_opts *opts,
unsigned int flags)
{
+ struct replay_ctx *ctx = opts->ctx;
struct child_process cmd = CHILD_PROCESS_INIT;
if ((flags & CLEANUP_MSG) && (flags & VERBATIM_MSG))
@@ -1101,7 +1150,7 @@ static int run_git_commit(const char *defmsg,
gpg_opt, gpg_opt);
}
- strvec_pushf(&cmd.env, GIT_REFLOG_ACTION "=%s", opts->reflog_message);
+ strvec_pushf(&cmd.env, GIT_REFLOG_ACTION "=%s", ctx->reflog_message);
if (opts->committer_date_is_author_date)
strvec_pushf(&cmd.env, "GIT_COMMITTER_DATE=%s",
@@ -1244,11 +1293,12 @@ int update_head_with_reflog(const struct commit *old_head,
strbuf_addch(&sb, '\n');
}
- transaction = ref_transaction_begin(err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ err);
if (!transaction ||
ref_transaction_update(transaction, "HEAD", new_head,
old_head ? &old_head->object.oid : null_oid(),
- 0, sb.buf, err) ||
+ NULL, NULL, 0, sb.buf, err) ||
ref_transaction_commit(transaction, err)) {
ret = -1;
}
@@ -1487,6 +1537,7 @@ static int try_to_commit(struct repository *r,
struct replay_opts *opts, unsigned int flags,
struct object_id *oid)
{
+ struct replay_ctx *ctx = opts->ctx;
struct object_id tree;
struct commit *current_head = NULL;
struct commit_list *parents = NULL;
@@ -1648,7 +1699,7 @@ static int try_to_commit(struct repository *r,
goto out;
}
- if (update_head_with_reflog(current_head, oid, opts->reflog_message,
+ if (update_head_with_reflog(current_head, oid, ctx->reflog_message,
msg, &err)) {
res = error("%s", err.buf);
goto out;
@@ -1669,8 +1720,8 @@ out:
static int write_rebase_head(struct object_id *oid)
{
- if (update_ref("rebase", "REBASE_HEAD", oid,
- NULL, REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
+ if (refs_update_ref(get_main_ref_store(the_repository), "rebase", "REBASE_HEAD", oid,
+ NULL, REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
return error(_("could not update %s"), "REBASE_HEAD");
return 0;
@@ -1878,10 +1929,10 @@ static void add_commented_lines(struct strbuf *buf, const void *str, size_t len)
}
/* Does the current fixup chain contain a squash command? */
-static int seen_squash(struct replay_opts *opts)
+static int seen_squash(struct replay_ctx *ctx)
{
- return starts_with(opts->current_fixups.buf, "squash") ||
- strstr(opts->current_fixups.buf, "\nsquash");
+ return starts_with(ctx->current_fixups.buf, "squash") ||
+ strstr(ctx->current_fixups.buf, "\nsquash");
}
static void update_comment_bufs(struct strbuf *buf1, struct strbuf *buf2, int n)
@@ -1957,6 +2008,7 @@ static int append_squash_message(struct strbuf *buf, const char *body,
enum todo_command command, struct replay_opts *opts,
unsigned flag)
{
+ struct replay_ctx *ctx = opts->ctx;
const char *fixup_msg;
size_t commented_len = 0, fixup_off;
/*
@@ -1965,13 +2017,13 @@ static int append_squash_message(struct strbuf *buf, const char *body,
* squashing commit messages.
*/
if (starts_with(body, "amend!") ||
- ((command == TODO_SQUASH || seen_squash(opts)) &&
+ ((command == TODO_SQUASH || seen_squash(ctx)) &&
(starts_with(body, "squash!") || starts_with(body, "fixup!"))))
commented_len = commit_subject_length(body);
strbuf_addf(buf, "\n%s ", comment_line_str);
strbuf_addf(buf, _(nth_commit_msg_fmt),
- ++opts->current_fixup_count + 1);
+ ++ctx->current_fixup_count + 1);
strbuf_addstr(buf, "\n\n");
strbuf_add_commented_lines(buf, body, commented_len, comment_line_str);
/* buf->buf may be reallocated so store an offset into the buffer */
@@ -1979,7 +2031,7 @@ static int append_squash_message(struct strbuf *buf, const char *body,
strbuf_addstr(buf, body + commented_len);
/* fixup -C after squash behaves like squash */
- if (is_fixup_flag(command, flag) && !seen_squash(opts)) {
+ if (is_fixup_flag(command, flag) && !seen_squash(ctx)) {
/*
* We're replacing the commit message so we need to
* append the Signed-off-by: trailer if the user
@@ -2013,12 +2065,13 @@ static int update_squash_messages(struct repository *r,
struct replay_opts *opts,
unsigned flag)
{
+ struct replay_ctx *ctx = opts->ctx;
struct strbuf buf = STRBUF_INIT;
int res = 0;
const char *message, *body;
const char *encoding = get_commit_output_encoding();
- if (opts->current_fixup_count > 0) {
+ if (ctx->current_fixup_count > 0) {
struct strbuf header = STRBUF_INIT;
char *eol;
@@ -2031,10 +2084,10 @@ static int update_squash_messages(struct repository *r,
strbuf_addf(&header, "%s ", comment_line_str);
strbuf_addf(&header, _(combined_commit_msg_fmt),
- opts->current_fixup_count + 2);
+ ctx->current_fixup_count + 2);
strbuf_splice(&buf, 0, eol - buf.buf, header.buf, header.len);
strbuf_release(&header);
- if (is_fixup_flag(command, flag) && !seen_squash(opts))
+ if (is_fixup_flag(command, flag) && !seen_squash(ctx))
update_squash_message_for_fixup(&buf);
} else {
struct object_id head;
@@ -2081,7 +2134,7 @@ static int update_squash_messages(struct repository *r,
} else if (command == TODO_FIXUP) {
strbuf_addf(&buf, "\n%s ", comment_line_str);
strbuf_addf(&buf, _(skip_nth_commit_msg_fmt),
- ++opts->current_fixup_count + 1);
+ ++ctx->current_fixup_count + 1);
strbuf_addstr(&buf, "\n\n");
strbuf_add_commented_lines(&buf, body, strlen(body),
comment_line_str);
@@ -2095,12 +2148,12 @@ static int update_squash_messages(struct repository *r,
strbuf_release(&buf);
if (!res) {
- strbuf_addf(&opts->current_fixups, "%s%s %s",
- opts->current_fixups.len ? "\n" : "",
+ strbuf_addf(&ctx->current_fixups, "%s%s %s",
+ ctx->current_fixups.len ? "\n" : "",
command_to_string(command),
oid_to_hex(&commit->object.oid));
- res = write_message(opts->current_fixups.buf,
- opts->current_fixups.len,
+ res = write_message(ctx->current_fixups.buf,
+ ctx->current_fixups.len,
rebase_path_current_fixups(), 0);
}
@@ -2178,6 +2231,7 @@ static int do_pick_commit(struct repository *r,
struct replay_opts *opts,
int final_fixup, int *check_todo)
{
+ struct replay_ctx *ctx = opts->ctx;
unsigned int flags = should_edit(opts) ? EDIT_MSG : 0;
const char *msg_file = should_edit(opts) ? NULL : git_path_merge_msg(r);
struct object_id head;
@@ -2185,7 +2239,6 @@ static int do_pick_commit(struct repository *r,
const char *base_label, *next_label;
char *author = NULL;
struct commit_message msg = { NULL, NULL, NULL, NULL };
- struct strbuf msgbuf = STRBUF_INIT;
int res, unborn = 0, reword = 0, allow, drop_commit;
enum todo_command command = item->command;
struct commit *commit = item->commit;
@@ -2284,7 +2337,7 @@ static int do_pick_commit(struct repository *r,
next = parent;
next_label = msg.parent_label;
if (opts->commit_use_reference) {
- strbuf_addstr(&msgbuf,
+ strbuf_addstr(&ctx->message,
"# *** SAY WHY WE ARE REVERTING ON THE TITLE LINE ***");
} else if (skip_prefix(msg.subject, "Revert \"", &orig_subject) &&
/*
@@ -2293,21 +2346,21 @@ static int do_pick_commit(struct repository *r,
* thus requiring excessive complexity to deal with.
*/
!starts_with(orig_subject, "Revert \"")) {
- strbuf_addstr(&msgbuf, "Reapply \"");
- strbuf_addstr(&msgbuf, orig_subject);
+ strbuf_addstr(&ctx->message, "Reapply \"");
+ strbuf_addstr(&ctx->message, orig_subject);
} else {
- strbuf_addstr(&msgbuf, "Revert \"");
- strbuf_addstr(&msgbuf, msg.subject);
- strbuf_addstr(&msgbuf, "\"");
+ strbuf_addstr(&ctx->message, "Revert \"");
+ strbuf_addstr(&ctx->message, msg.subject);
+ strbuf_addstr(&ctx->message, "\"");
}
- strbuf_addstr(&msgbuf, "\n\nThis reverts commit ");
- refer_to_commit(opts, &msgbuf, commit);
+ strbuf_addstr(&ctx->message, "\n\nThis reverts commit ");
+ refer_to_commit(opts, &ctx->message, commit);
if (commit->parents && commit->parents->next) {
- strbuf_addstr(&msgbuf, ", reversing\nchanges made to ");
- refer_to_commit(opts, &msgbuf, parent);
+ strbuf_addstr(&ctx->message, ", reversing\nchanges made to ");
+ refer_to_commit(opts, &ctx->message, parent);
}
- strbuf_addstr(&msgbuf, ".\n");
+ strbuf_addstr(&ctx->message, ".\n");
} else {
const char *p;
@@ -2316,21 +2369,22 @@ static int do_pick_commit(struct repository *r,
next = commit;
next_label = msg.label;
- /* Append the commit log message to msgbuf. */
+ /* Append the commit log message to ctx->message. */
if (find_commit_subject(msg.message, &p))
- strbuf_addstr(&msgbuf, p);
+ strbuf_addstr(&ctx->message, p);
if (opts->record_origin) {
- strbuf_complete_line(&msgbuf);
- if (!has_conforming_footer(&msgbuf, NULL, 0))
- strbuf_addch(&msgbuf, '\n');
- strbuf_addstr(&msgbuf, cherry_picked_prefix);
- strbuf_addstr(&msgbuf, oid_to_hex(&commit->object.oid));
- strbuf_addstr(&msgbuf, ")\n");
+ strbuf_complete_line(&ctx->message);
+ if (!has_conforming_footer(&ctx->message, NULL, 0))
+ strbuf_addch(&ctx->message, '\n');
+ strbuf_addstr(&ctx->message, cherry_picked_prefix);
+ strbuf_addstr(&ctx->message, oid_to_hex(&commit->object.oid));
+ strbuf_addstr(&ctx->message, ")\n");
}
if (!is_fixup(command))
author = get_author(msg.message);
}
+ ctx->have_message = 1;
if (command == TODO_REWORD)
reword = 1;
@@ -2361,7 +2415,7 @@ static int do_pick_commit(struct repository *r,
}
if (opts->signoff && !is_fixup(command))
- append_signoff(&msgbuf, 0, 0);
+ append_signoff(&ctx->message, 0, 0);
if (is_rebase_i(opts) && write_author_script(msg.message) < 0)
res = -1;
@@ -2370,17 +2424,17 @@ static int do_pick_commit(struct repository *r,
!strcmp(opts->strategy, "ort") ||
command == TODO_REVERT) {
res = do_recursive_merge(r, base, next, base_label, next_label,
- &head, &msgbuf, opts);
+ &head, &ctx->message, opts);
if (res < 0)
goto leave;
- res |= write_message(msgbuf.buf, msgbuf.len,
+ res |= write_message(ctx->message.buf, ctx->message.len,
git_path_merge_msg(r), 0);
} else {
struct commit_list *common = NULL;
struct commit_list *remotes = NULL;
- res = write_message(msgbuf.buf, msgbuf.len,
+ res = write_message(ctx->message.buf, ctx->message.len,
git_path_merge_msg(r), 0);
commit_list_insert(base, &common);
@@ -2401,12 +2455,12 @@ static int do_pick_commit(struct repository *r,
if ((command == TODO_PICK || command == TODO_REWORD ||
command == TODO_EDIT) && !opts->no_commit &&
(res == 0 || res == 1) &&
- update_ref(NULL, "CHERRY_PICK_HEAD", &commit->object.oid, NULL,
- REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
+ refs_update_ref(get_main_ref_store(the_repository), NULL, "CHERRY_PICK_HEAD", &commit->object.oid, NULL,
+ REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
res = -1;
if (command == TODO_REVERT && ((opts->no_commit && res == 0) || res == 1) &&
- update_ref(NULL, "REVERT_HEAD", &commit->object.oid, NULL,
- REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
+ refs_update_ref(get_main_ref_store(the_repository), NULL, "REVERT_HEAD", &commit->object.oid, NULL,
+ REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR))
res = -1;
if (res) {
@@ -2458,14 +2512,13 @@ fast_forward_edit:
unlink(rebase_path_fixup_msg());
unlink(rebase_path_squash_msg());
unlink(rebase_path_current_fixups());
- strbuf_reset(&opts->current_fixups);
- opts->current_fixup_count = 0;
+ strbuf_reset(&ctx->current_fixups);
+ ctx->current_fixup_count = 0;
}
leave:
free_message(commit, &msg);
free(author);
- strbuf_release(&msgbuf);
update_abort_safety_file();
return res;
@@ -2573,8 +2626,37 @@ static int check_label_or_ref_arg(enum todo_command command, const char *arg)
return 0;
}
-static int parse_insn_line(struct repository *r, struct todo_item *item,
- const char *buf, const char *bol, char *eol)
+static int error_merge_commit(enum todo_command command)
+{
+ switch(command) {
+ case TODO_PICK:
+ return error(_("'%s' does not accept merge commits, "
+ "please use '%s'"),
+ todo_command_info[command].str, "merge -C");
+
+ case TODO_REWORD:
+ return error(_("'%s' does not accept merge commits, "
+ "please use '%s'"),
+ todo_command_info[command].str, "merge -c");
+
+ case TODO_EDIT:
+ return error(_("'%s' does not accept merge commits, "
+ "please use '%s' followed by '%s'"),
+ todo_command_info[command].str,
+ "merge -C", "break");
+
+ case TODO_FIXUP:
+ case TODO_SQUASH:
+ return error(_("cannot squash merge commit into another commit"));
+
+ default:
+ BUG("unexpected todo_command");
+ }
+}
+
+static int parse_insn_line(struct repository *r, struct replay_opts *opts,
+ struct todo_item *item, const char *buf,
+ const char *bol, char *eol)
{
struct object_id commit_oid;
char *end_of_object_name;
@@ -2678,7 +2760,12 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
return status;
item->commit = lookup_commit_reference(r, &commit_oid);
- return item->commit ? 0 : -1;
+ if (!item->commit)
+ return -1;
+ if (is_rebase_i(opts) && item->command != TODO_MERGE &&
+ item->commit->parents && item->commit->parents->next)
+ return error_merge_commit(item->command);
+ return 0;
}
int sequencer_get_last_command(struct repository *r UNUSED, enum replay_action *action)
@@ -2708,8 +2795,8 @@ int sequencer_get_last_command(struct repository *r UNUSED, enum replay_action *
return ret;
}
-int todo_list_parse_insn_buffer(struct repository *r, char *buf,
- struct todo_list *todo_list)
+int todo_list_parse_insn_buffer(struct repository *r, struct replay_opts *opts,
+ char *buf, struct todo_list *todo_list)
{
struct todo_item *item;
char *p = buf, *next_p;
@@ -2727,7 +2814,7 @@ int todo_list_parse_insn_buffer(struct repository *r, char *buf,
item = append_new_todo(todo_list);
item->offset_in_buf = p - todo_list->buf.buf;
- if (parse_insn_line(r, item, buf, p, eol)) {
+ if (parse_insn_line(r, opts, item, buf, p, eol)) {
res = error(_("invalid line %d: %.*s"),
i, (int)(eol - p), p);
item->command = TODO_COMMENT + 1;
@@ -2846,12 +2933,14 @@ void sequencer_post_commit_cleanup(struct repository *r, int verbose)
NULL, REF_NO_DEREF);
if (!need_cleanup)
- return;
+ goto out;
if (!have_finished_the_last_pick())
- return;
+ goto out;
sequencer_remove_state(&opts);
+out:
+ replay_opts_release(&opts);
}
static void todo_list_write_total_nr(struct todo_list *todo_list)
@@ -2875,7 +2964,7 @@ static int read_populate_todo(struct repository *r,
if (strbuf_read_file_or_whine(&todo_list->buf, todo_file) < 0)
return -1;
- res = todo_list_parse_insn_buffer(r, todo_list->buf.buf, todo_list);
+ res = todo_list_parse_insn_buffer(r, opts, todo_list->buf.buf, todo_list);
if (res) {
if (is_rebase_i(opts))
return error(_("please fix this using "
@@ -2905,7 +2994,7 @@ static int read_populate_todo(struct repository *r,
struct todo_list done = TODO_LIST_INIT;
if (strbuf_read_file(&done.buf, rebase_path_done(), 0) > 0 &&
- !todo_list_parse_insn_buffer(r, done.buf.buf, &done))
+ !todo_list_parse_insn_buffer(r, opts, done.buf.buf, &done))
todo_list->done_nr = count_commands(&done);
else
todo_list->done_nr = 0;
@@ -3022,6 +3111,8 @@ static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf)
static int read_populate_opts(struct replay_opts *opts)
{
+ struct replay_ctx *ctx = opts->ctx;
+
if (is_rebase_i(opts)) {
struct strbuf buf = STRBUF_INIT;
int ret = 0;
@@ -3081,13 +3172,13 @@ static int read_populate_opts(struct replay_opts *opts)
read_strategy_opts(opts, &buf);
strbuf_reset(&buf);
- if (read_oneliner(&opts->current_fixups,
+ if (read_oneliner(&ctx->current_fixups,
rebase_path_current_fixups(),
READ_ONELINER_SKIP_IF_EMPTY)) {
- const char *p = opts->current_fixups.buf;
- opts->current_fixup_count = 1;
+ const char *p = ctx->current_fixups.buf;
+ ctx->current_fixup_count = 1;
while ((p = strchr(p, '\n'))) {
- opts->current_fixup_count++;
+ ctx->current_fixup_count++;
p++;
}
}
@@ -3307,7 +3398,7 @@ static int rollback_single_pick(struct repository *r)
if (!refs_ref_exists(get_main_ref_store(r), "CHERRY_PICK_HEAD") &&
!refs_ref_exists(get_main_ref_store(r), "REVERT_HEAD"))
return error(_("no cherry-pick or revert in progress"));
- if (read_ref_full("HEAD", 0, &head_oid, NULL))
+ if (refs_read_ref_full(get_main_ref_store(the_repository), "HEAD", 0, &head_oid, NULL))
return error(_("cannot resolve HEAD"));
if (is_null_oid(&head_oid))
return error(_("cannot abort from a branch yet to be born"));
@@ -3318,7 +3409,7 @@ static int skip_single_pick(void)
{
struct object_id head;
- if (read_ref_full("HEAD", 0, &head, NULL))
+ if (refs_read_ref_full(get_main_ref_store(the_repository), "HEAD", 0, &head, NULL))
return error(_("cannot resolve HEAD"));
return reset_merge(&head);
}
@@ -3608,13 +3699,24 @@ static int error_with_patch(struct repository *r,
struct replay_opts *opts,
int exit_code, int to_amend)
{
- if (commit) {
- if (make_patch(r, commit, opts))
+ struct replay_ctx *ctx = opts->ctx;
+
+ /*
+ * Write the commit message to be used by "git rebase
+ * --continue". If a "fixup" or "squash" command has conflicts
+ * then we will have already written rebase_path_message() in
+ * error_failed_squash(). If an "edit" command was
+ * fast-forwarded then we don't have a message in ctx->message
+ * and rely on make_patch() to write rebase_path_message()
+ * instead.
+ */
+ if (ctx->have_message && !file_exists(rebase_path_message()) &&
+ write_message(ctx->message.buf, ctx->message.len,
+ rebase_path_message(), 0))
+ return error(_("could not write commit message file"));
+
+ if (commit && make_patch(r, commit, opts))
return -1;
- } else if (copy_file(rebase_path_message(),
- git_path_merge_msg(r), 0666))
- return error(_("unable to copy '%s' to '%s'"),
- git_path_merge_msg(r), rebase_path_message());
if (to_amend) {
if (intend_to_amend())
@@ -3764,8 +3866,9 @@ static int do_label(struct repository *r, const char *name, int len)
} else if (repo_get_oid(r, "HEAD", &head_oid)) {
error(_("could not read HEAD"));
ret = -1;
- } else if (ref_transaction_update(transaction, ref_name.buf, &head_oid,
- NULL, 0, msg.buf, &err) < 0 ||
+ } else if (ref_transaction_update(transaction, ref_name.buf,
+ &head_oid, NULL, NULL, NULL,
+ 0, msg.buf, &err) < 0 ||
ref_transaction_commit(transaction, &err)) {
error("%s", err.buf);
ret = -1;
@@ -3823,7 +3926,7 @@ static struct commit *lookup_label(struct repository *r, const char *label,
strbuf_reset(buf);
strbuf_addf(buf, "refs/rewritten/%.*s", len, label);
- if (!read_ref(buf->buf, &oid)) {
+ if (!refs_read_ref(get_main_ref_store(the_repository), buf->buf, &oid)) {
commit = lookup_commit_object(r, &oid);
} else {
/* fall back to non-rewritten ref or commit */
@@ -3919,9 +4022,10 @@ static int do_reset(struct repository *r,
ret = error(_("could not write index"));
if (!ret)
- ret = update_ref(reflog_message(opts, "reset", "'%.*s'",
- len, name), "HEAD", &oid,
- NULL, 0, UPDATE_REFS_MSG_ON_ERR);
+ ret = refs_update_ref(get_main_ref_store(the_repository), reflog_message(opts, "reset", "'%.*s'",
+ len, name),
+ "HEAD", &oid,
+ NULL, 0, UPDATE_REFS_MSG_ON_ERR);
cleanup:
free((void *)desc.buffer);
if (ret < 0)
@@ -3936,6 +4040,7 @@ static int do_merge(struct repository *r,
const char *arg, int arg_len,
int flags, int *check_todo, struct replay_opts *opts)
{
+ struct replay_ctx *ctx = opts->ctx;
int run_commit_flags = 0;
struct strbuf ref_name = STRBUF_INIT;
struct commit *head_commit, *merge_commit, *i;
@@ -4064,40 +4169,31 @@ static int do_merge(struct repository *r,
write_author_script(message);
find_commit_subject(message, &body);
len = strlen(body);
- ret = write_message(body, len, git_path_merge_msg(r), 0);
+ strbuf_add(&ctx->message, body, len);
repo_unuse_commit_buffer(r, commit, message);
- if (ret) {
- error_errno(_("could not write '%s'"),
- git_path_merge_msg(r));
- goto leave_merge;
- }
} else {
struct strbuf buf = STRBUF_INIT;
- int len;
strbuf_addf(&buf, "author %s", git_author_info(0));
write_author_script(buf.buf);
- strbuf_reset(&buf);
+ strbuf_release(&buf);
if (oneline_offset < arg_len) {
- p = arg + oneline_offset;
- len = arg_len - oneline_offset;
+ strbuf_add(&ctx->message, arg + oneline_offset,
+ arg_len - oneline_offset);
} else {
- strbuf_addf(&buf, "Merge %s '%.*s'",
+ strbuf_addf(&ctx->message, "Merge %s '%.*s'",
to_merge->next ? "branches" : "branch",
merge_arg_len, arg);
- p = buf.buf;
- len = buf.len;
- }
-
- ret = write_message(p, len, git_path_merge_msg(r), 0);
- strbuf_release(&buf);
- if (ret) {
- error_errno(_("could not write '%s'"),
- git_path_merge_msg(r));
- goto leave_merge;
}
}
+ ctx->have_message = 1;
+ if (write_message(ctx->message.buf, ctx->message.len,
+ git_path_merge_msg(r), 0)) {
+ ret = error_errno(_("could not write '%s'"),
+ git_path_merge_msg(r));
+ goto leave_merge;
+ }
if (strategy || to_merge->next) {
/* Octopus merge */
@@ -4411,7 +4507,7 @@ static int do_update_ref(struct repository *r, const char *refname)
for_each_string_list_item(item, &list) {
if (!strcmp(item->string, refname)) {
struct update_ref_record *rec = item->util;
- if (read_ref("HEAD", &rec->after))
+ if (refs_read_ref(get_main_ref_store(the_repository), "HEAD", &rec->after))
return -1;
break;
}
@@ -4758,11 +4854,12 @@ static int pick_one_commit(struct repository *r,
struct replay_opts *opts,
int *check_todo, int* reschedule)
{
+ struct replay_ctx *ctx = opts->ctx;
int res;
struct todo_item *item = todo_list->items + todo_list->current;
const char *arg = todo_item_get_arg(todo_list, item);
if (is_rebase_i(opts))
- opts->reflog_message = reflog_message(
+ ctx->reflog_message = reflog_message(
opts, command_to_string(item->command), NULL);
res = do_pick_commit(r, item, opts, is_final_fixup(todo_list),
@@ -4819,9 +4916,10 @@ static int pick_commits(struct repository *r,
struct todo_list *todo_list,
struct replay_opts *opts)
{
+ struct replay_ctx *ctx = opts->ctx;
int res = 0, reschedule = 0;
- opts->reflog_message = sequencer_reflog_action(opts);
+ ctx->reflog_message = sequencer_reflog_action(opts);
if (opts->allow_ff)
assert(!(opts->signoff || opts->no_commit ||
opts->record_origin || should_edit(opts) ||
@@ -4871,6 +4969,8 @@ static int pick_commits(struct repository *r,
return stopped_at_head(r);
}
}
+ strbuf_reset(&ctx->message);
+ ctx->have_message = 0;
if (item->command <= TODO_SQUASH) {
res = pick_one_commit(r, todo_list, opts, &check_todo,
&reschedule);
@@ -4967,15 +5067,15 @@ cleanup_head_ref:
}
msg = reflog_message(opts, "finish", "%s onto %s",
head_ref.buf, buf.buf);
- if (update_ref(msg, head_ref.buf, &head, &orig,
- REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) {
+ if (refs_update_ref(get_main_ref_store(the_repository), msg, head_ref.buf, &head, &orig,
+ REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) {
res = error(_("could not update %s"),
head_ref.buf);
goto cleanup_head_ref;
}
msg = reflog_message(opts, "finish", "returning to %s",
head_ref.buf);
- if (create_symref("HEAD", head_ref.buf, msg)) {
+ if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", head_ref.buf, msg)) {
res = error(_("could not update HEAD to %s"),
head_ref.buf);
goto cleanup_head_ref;
@@ -5076,6 +5176,7 @@ static int commit_staged_changes(struct repository *r,
struct replay_opts *opts,
struct todo_list *todo_list)
{
+ struct replay_ctx *ctx = opts->ctx;
unsigned int flags = ALLOW_EMPTY | EDIT_MSG;
unsigned int final_fixup = 0, is_clean;
@@ -5112,7 +5213,7 @@ static int commit_staged_changes(struct repository *r,
* the commit message and if there was a squash, let the user
* edit it.
*/
- if (!is_clean || !opts->current_fixup_count)
+ if (!is_clean || !ctx->current_fixup_count)
; /* this is not the final fixup */
else if (!oideq(&head, &to_amend) ||
!file_exists(rebase_path_stopped_sha())) {
@@ -5121,20 +5222,20 @@ static int commit_staged_changes(struct repository *r,
unlink(rebase_path_fixup_msg());
unlink(rebase_path_squash_msg());
unlink(rebase_path_current_fixups());
- strbuf_reset(&opts->current_fixups);
- opts->current_fixup_count = 0;
+ strbuf_reset(&ctx->current_fixups);
+ ctx->current_fixup_count = 0;
}
} else {
/* we are in a fixup/squash chain */
- const char *p = opts->current_fixups.buf;
- int len = opts->current_fixups.len;
+ const char *p = ctx->current_fixups.buf;
+ int len = ctx->current_fixups.len;
- opts->current_fixup_count--;
+ ctx->current_fixup_count--;
if (!len)
BUG("Incorrect current_fixups:\n%s", p);
while (len && p[len - 1] != '\n')
len--;
- strbuf_setlen(&opts->current_fixups, len);
+ strbuf_setlen(&ctx->current_fixups, len);
if (write_message(p, len, rebase_path_current_fixups(),
0) < 0)
return error(_("could not write file: '%s'"),
@@ -5151,7 +5252,7 @@ static int commit_staged_changes(struct repository *r,
* actually need to re-commit with a cleaned up commit
* message.
*/
- if (opts->current_fixup_count > 0 &&
+ if (ctx->current_fixup_count > 0 &&
!is_fixup(peek_command(todo_list, 0))) {
final_fixup = 1;
/*
@@ -5224,20 +5325,21 @@ static int commit_staged_changes(struct repository *r,
unlink(rebase_path_fixup_msg());
unlink(rebase_path_squash_msg());
}
- if (opts->current_fixup_count > 0) {
+ if (ctx->current_fixup_count > 0) {
/*
* Whether final fixup or not, we just cleaned up the commit
* message...
*/
unlink(rebase_path_current_fixups());
- strbuf_reset(&opts->current_fixups);
- opts->current_fixup_count = 0;
+ strbuf_reset(&ctx->current_fixups);
+ ctx->current_fixup_count = 0;
}
return 0;
}
int sequencer_continue(struct repository *r, struct replay_opts *opts)
{
+ struct replay_ctx *ctx = opts->ctx;
struct todo_list todo_list = TODO_LIST_INIT;
int res;
@@ -5251,13 +5353,14 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)
goto release_todo_list;
if (file_exists(rebase_path_dropped())) {
- if ((res = todo_list_check_against_backup(r, &todo_list)))
+ if ((res = todo_list_check_against_backup(r, opts,
+ &todo_list)))
goto release_todo_list;
unlink(rebase_path_dropped());
}
- opts->reflog_message = reflog_message(opts, "continue", NULL);
+ ctx->reflog_message = reflog_message(opts, "continue", NULL);
if (commit_staged_changes(r, opts, &todo_list)) {
res = -1;
goto release_todo_list;
@@ -5309,7 +5412,7 @@ static int single_pick(struct repository *r,
TODO_PICK : TODO_REVERT;
item.commit = cmit;
- opts->reflog_message = sequencer_reflog_action(opts);
+ opts->ctx->reflog_message = sequencer_reflog_action(opts);
return do_pick_commit(r, &item, opts, 0, &check_todo);
}
@@ -6143,10 +6246,11 @@ static int add_decorations_to_list(const struct commit *commit,
struct todo_add_branch_context *ctx)
{
const struct name_decoration *decoration = get_name_decoration(&commit->object);
- const char *head_ref = resolve_ref_unsafe("HEAD",
- RESOLVE_REF_READING,
- NULL,
- NULL);
+ const char *head_ref = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ "HEAD",
+ RESOLVE_REF_READING,
+ NULL,
+ NULL);
while (decoration) {
struct todo_item *item;
@@ -6294,7 +6398,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
return error(_("nothing to do"));
}
- res = edit_todo_list(r, todo_list, &new_todo, shortrevisions,
+ res = edit_todo_list(r, opts, todo_list, &new_todo, shortrevisions,
shortonto, flags);
if (res == -1)
return -1;
@@ -6322,7 +6426,7 @@ int complete_action(struct repository *r, struct replay_opts *opts, unsigned fla
strbuf_release(&buf2);
/* Nothing is done yet, and we're reparsing, so let's reset the count */
new_todo.total_nr = 0;
- if (todo_list_parse_insn_buffer(r, new_todo.buf.buf, &new_todo) < 0)
+ if (todo_list_parse_insn_buffer(r, opts, new_todo.buf.buf, &new_todo) < 0)
BUG("invalid todo list after expanding IDs:\n%s",
new_todo.buf.buf);
diff --git a/sequencer.h b/sequencer.h
index 437eabd38a..304ba4b4d3 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -31,6 +31,9 @@ enum commit_msg_cleanup_mode {
COMMIT_MSG_CLEANUP_ALL
};
+struct replay_ctx;
+struct replay_ctx* replay_ctx_new(void);
+
struct replay_opts {
enum replay_action action;
@@ -68,10 +71,6 @@ struct replay_opts {
/* Reflog */
char *reflog_action;
- /* Used by fixup/squash */
- struct strbuf current_fixups;
- int current_fixup_count;
-
/* placeholder commit for -i --root */
struct object_id squash_onto;
int have_squash_onto;
@@ -80,13 +79,13 @@ struct replay_opts {
struct rev_info *revs;
/* Private use */
- const char *reflog_message;
+ struct replay_ctx *ctx;
};
#define REPLAY_OPTS_INIT { \
.edit = -1, \
.action = -1, \
- .current_fixups = STRBUF_INIT, \
.xopts = STRVEC_INIT, \
+ .ctx = replay_ctx_new(), \
}
/*
@@ -137,8 +136,8 @@ struct todo_list {
.buf = STRBUF_INIT, \
}
-int todo_list_parse_insn_buffer(struct repository *r, char *buf,
- struct todo_list *todo_list);
+int todo_list_parse_insn_buffer(struct repository *r, struct replay_opts *opts,
+ char *buf, struct todo_list *todo_list);
int todo_list_write_to_file(struct repository *r, struct todo_list *todo_list,
const char *file, const char *shortrevisions,
const char *shortonto, int num, unsigned flags);
diff --git a/server-info.c b/server-info.c
index e2fe0f9143..6feaa457c5 100644
--- a/server-info.c
+++ b/server-info.c
@@ -175,7 +175,8 @@ static int add_info_ref(const char *path, const struct object_id *oid,
static int generate_info_refs(struct update_info_ctx *uic)
{
- return for_each_ref(add_info_ref, uic);
+ return refs_for_each_ref(get_main_ref_store(the_repository),
+ add_info_ref, uic);
}
static int update_info_refs(int force)
diff --git a/setup.c b/setup.c
index f4b32f76e3..83fc620b23 100644
--- a/setup.c
+++ b/setup.c
@@ -4,6 +4,7 @@
#include "environment.h"
#include "exec-cmd.h"
#include "gettext.h"
+#include "hex.h"
#include "object-name.h"
#include "refs.h"
#include "repository.h"
@@ -16,6 +17,7 @@
#include "quote.h"
#include "trace2.h"
#include "worktree.h"
+#include "exec-cmd.h"
static int inside_git_dir = -1;
static int inside_work_tree = -1;
@@ -341,6 +343,58 @@ int get_common_dir_noenv(struct strbuf *sb, const char *gitdir)
return ret;
}
+static int validate_headref(const char *path)
+{
+ struct stat st;
+ char buffer[256];
+ const char *refname;
+ struct object_id oid;
+ int fd;
+ ssize_t len;
+
+ if (lstat(path, &st) < 0)
+ return -1;
+
+ /* Make sure it is a "refs/.." symlink */
+ if (S_ISLNK(st.st_mode)) {
+ len = readlink(path, buffer, sizeof(buffer)-1);
+ if (len >= 5 && !memcmp("refs/", buffer, 5))
+ return 0;
+ return -1;
+ }
+
+ /*
+ * Anything else, just open it and try to see if it is a symbolic ref.
+ */
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+ len = read_in_full(fd, buffer, sizeof(buffer)-1);
+ close(fd);
+
+ if (len < 0)
+ return -1;
+ buffer[len] = '\0';
+
+ /*
+ * Is it a symbolic ref?
+ */
+ if (skip_prefix(buffer, "ref:", &refname)) {
+ while (isspace(*refname))
+ refname++;
+ if (starts_with(refname, "refs/"))
+ return 0;
+ }
+
+ /*
+ * Is this a detached HEAD?
+ */
+ if (get_oid_hex_any(buffer, &oid) != GIT_HASH_UNKNOWN)
+ return 0;
+
+ return -1;
+}
+
/*
* Test if it looks like we're at a git directory.
* We want to see:
@@ -1220,6 +1274,27 @@ static int ensure_valid_ownership(const char *gitfile,
return data.is_safe;
}
+void die_upon_dubious_ownership(const char *gitfile, const char *worktree,
+ const char *gitdir)
+{
+ struct strbuf report = STRBUF_INIT, quoted = STRBUF_INIT;
+ const char *path;
+
+ if (ensure_valid_ownership(gitfile, worktree, gitdir, &report))
+ return;
+
+ strbuf_complete(&report, '\n');
+ path = gitfile ? gitfile : gitdir;
+ sq_quote_buf_pretty(&quoted, path);
+
+ die(_("detected dubious ownership in repository at '%s'\n"
+ "%s"
+ "To add an exception for this directory, call:\n"
+ "\n"
+ "\tgit config --global --add safe.directory %s"),
+ path, report.buf, quoted.buf);
+}
+
static int allowed_bare_repo_cb(const char *key, const char *value,
const struct config_context *ctx UNUSED,
void *d)
@@ -1781,14 +1856,63 @@ int daemonize(void)
#endif
}
+struct template_dir_cb_data {
+ char *path;
+ int initialized;
+};
+
+static int template_dir_cb(const char *key, const char *value,
+ const struct config_context *ctx, void *d)
+{
+ struct template_dir_cb_data *data = d;
+
+ if (strcmp(key, "init.templatedir"))
+ return 0;
+
+ if (!value) {
+ data->path = NULL;
+ } else {
+ char *path = NULL;
+
+ FREE_AND_NULL(data->path);
+ if (!git_config_pathname((const char **)&path, key, value))
+ data->path = path ? path : xstrdup(value);
+ }
+
+ return 0;
+}
+
+const char *get_template_dir(const char *option_template)
+{
+ const char *template_dir = option_template;
+
+ if (!template_dir)
+ template_dir = getenv(TEMPLATE_DIR_ENVIRONMENT);
+ if (!template_dir) {
+ static struct template_dir_cb_data data;
+
+ if (!data.initialized) {
+ git_protected_config(template_dir_cb, &data);
+ data.initialized = 1;
+ }
+ template_dir = data.path;
+ }
+ if (!template_dir) {
+ static char *dir;
+
+ if (!dir)
+ dir = system_path(DEFAULT_GIT_TEMPLATE_DIR);
+ template_dir = dir;
+ }
+ return template_dir;
+}
+
#ifdef NO_TRUSTABLE_FILEMODE
#define TEST_FILEMODE 0
#else
#define TEST_FILEMODE 1
#endif
-#define GIT_DEFAULT_HASH_ENVIRONMENT "GIT_DEFAULT_HASH"
-
static void copy_templates_1(struct strbuf *path, struct strbuf *template_path,
DIR *dir)
{
@@ -1856,8 +1980,9 @@ static void copy_templates_1(struct strbuf *path, struct strbuf *template_path,
}
}
-static void copy_templates(const char *template_dir, const char *init_template_dir)
+static void copy_templates(const char *option_template)
{
+ const char *template_dir = get_template_dir(option_template);
struct strbuf path = STRBUF_INIT;
struct strbuf template_path = STRBUF_INIT;
size_t template_len;
@@ -1866,16 +1991,8 @@ static void copy_templates(const char *template_dir, const char *init_template_d
DIR *dir;
char *to_free = NULL;
- if (!template_dir)
- template_dir = getenv(TEMPLATE_DIR_ENVIRONMENT);
- if (!template_dir)
- template_dir = init_template_dir;
- if (!template_dir)
- template_dir = to_free = system_path(DEFAULT_GIT_TEMPLATE_DIR);
- if (!template_dir[0]) {
- free(to_free);
+ if (!template_dir || !*template_dir)
return;
- }
strbuf_addstr(&template_path, template_dir);
strbuf_complete(&template_path, '/');
@@ -2001,7 +2118,7 @@ void create_reference_database(unsigned int ref_storage_format,
die(_("invalid initial branch name: '%s'"),
initial_branch);
- if (create_symref("HEAD", ref, NULL) < 0)
+ if (refs_update_symref(get_main_ref_store(the_repository), "HEAD", ref, NULL) < 0)
exit(1);
free(ref);
}
@@ -2023,7 +2140,6 @@ static int create_default_files(const char *template_path,
char *path;
int reinit;
int filemode;
- const char *init_template_dir = NULL;
const char *work_tree = get_git_work_tree();
/*
@@ -2035,9 +2151,7 @@ static int create_default_files(const char *template_path,
* values (since we've just potentially changed what's available on
* disk).
*/
- git_config_get_pathname("init.templatedir", &init_template_dir);
- copy_templates(template_path, init_template_dir);
- free((char *)init_template_dir);
+ copy_templates(template_path);
git_config_clear();
reset_shared_repository();
git_config(git_default_config, NULL);
diff --git a/setup.h b/setup.h
index d88bb37aaf..b3fd3bf45a 100644
--- a/setup.h
+++ b/setup.h
@@ -41,6 +41,18 @@ const char *read_gitfile_gently(const char *path, int *return_error_code);
const char *resolve_gitdir_gently(const char *suspect, int *return_error_code);
#define resolve_gitdir(path) resolve_gitdir_gently((path), NULL)
+/*
+ * Check if a repository is safe and die if it is not, by verifying the
+ * ownership of the worktree (if any), the git directory, and the gitfile (if
+ * any).
+ *
+ * Exemptions for known-safe repositories can be added via `safe.directory`
+ * config settings; for non-bare repositories, their worktree needs to be
+ * added, for bare ones their git directory.
+ */
+void die_upon_dubious_ownership(const char *gitfile, const char *worktree,
+ const char *gitdir);
+
void setup_work_tree(void);
/*
@@ -172,6 +184,8 @@ int verify_repository_format(const struct repository_format *format,
*/
void check_repository_format(struct repository_format *fmt);
+const char *get_template_dir(const char *option_template);
+
#define INIT_DB_QUIET (1 << 0)
#define INIT_DB_EXIST_OK (1 << 1)
#define INIT_DB_SKIP_REFDB (1 << 2)
diff --git a/shallow.c b/shallow.c
index 7ff50dd0da..a0b181ba8a 100644
--- a/shallow.c
+++ b/shallow.c
@@ -678,8 +678,10 @@ void assign_shallow_commits_to_refs(struct shallow_info *info,
* connect to old refs. If not (e.g. force ref updates) it'll
* have to go down to the current shallow commits.
*/
- head_ref(mark_uninteresting, NULL);
- for_each_ref(mark_uninteresting, NULL);
+ refs_head_ref(get_main_ref_store(the_repository), mark_uninteresting,
+ NULL);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ mark_uninteresting, NULL);
/* Mark potential bottoms so we won't go out of bound */
for (i = 0; i < nr_shallow; i++) {
@@ -782,8 +784,8 @@ static void post_assign_shallow(struct shallow_info *info,
info->nr_theirs = dst;
memset(&ca, 0, sizeof(ca));
- head_ref(add_ref, &ca);
- for_each_ref(add_ref, &ca);
+ refs_head_ref(get_main_ref_store(the_repository), add_ref, &ca);
+ refs_for_each_ref(get_main_ref_store(the_repository), add_ref, &ca);
/* Remove unreachable shallow commits from "ours" */
for (i = dst = 0; i < info->nr_ours; i++) {
@@ -822,8 +824,10 @@ int delayed_reachability_test(struct shallow_info *si, int c)
struct commit_array ca;
memset(&ca, 0, sizeof(ca));
- head_ref(add_ref, &ca);
- for_each_ref(add_ref, &ca);
+ refs_head_ref(get_main_ref_store(the_repository),
+ add_ref, &ca);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ add_ref, &ca);
si->commits = ca.commits;
si->nr_commits = ca.nr;
}
diff --git a/strbuf.c b/strbuf.c
index 1492a08225..d5b4b3903a 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -277,7 +277,7 @@ void strbuf_vinsertf(struct strbuf *sb, size_t pos, const char *fmt, va_list ap)
len = vsnprintf(sb->buf + sb->len, 0, fmt, cp);
va_end(cp);
if (len < 0)
- BUG("your vsnprintf is broken (returned %d)", len);
+ die(_("unable to format message: %s"), fmt);
if (!len)
return; /* nothing to do */
if (unsigned_add_overflows(sb->len, len))
@@ -404,7 +404,7 @@ void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap)
len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, cp);
va_end(cp);
if (len < 0)
- BUG("your vsnprintf is broken (returned %d)", len);
+ die(_("unable to format message: %s"), fmt);
if (len > strbuf_avail(sb)) {
strbuf_grow(sb, len);
len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
@@ -592,6 +592,7 @@ int strbuf_getcwd(struct strbuf *sb)
strbuf_grow(sb, guessed_len);
if (getcwd(sb->buf, sb->alloc)) {
strbuf_setlen(sb, strlen(sb->buf));
+ precompose_strbuf_if_needed(sb);
return 0;
}
diff --git a/submodule.c b/submodule.c
index ce2d032521..f6313cd99f 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1015,6 +1015,9 @@ static int submodule_has_commits(struct repository *r,
.super_oid = super_oid
};
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
oid_array_for_each_unique(commits, check_has_commit, &has_commit);
if (has_commit.result) {
@@ -1137,6 +1140,9 @@ static int push_submodule(const char *path,
const struct string_list *push_options,
int dry_run)
{
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
struct child_process cp = CHILD_PROCESS_INIT;
strvec_push(&cp.args, "push");
@@ -1186,6 +1192,9 @@ static void submodule_push_check(const char *path, const char *head,
struct child_process cp = CHILD_PROCESS_INIT;
int i;
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
strvec_push(&cp.args, "submodule--helper");
strvec_push(&cp.args, "push-check");
strvec_push(&cp.args, head);
@@ -1233,7 +1242,8 @@ int push_unpushed_submodules(struct repository *r,
char *head;
struct object_id head_oid;
- head = resolve_refdup("HEAD", 0, &head_oid, NULL);
+ head = refs_resolve_refdup(get_main_ref_store(the_repository),
+ "HEAD", 0, &head_oid, NULL);
if (!head)
die(_("Failed to resolve HEAD as a valid ref."));
@@ -1271,7 +1281,8 @@ static int append_oid_to_array(const char *ref UNUSED,
void check_for_new_submodule_commits(struct object_id *oid)
{
if (!initialized_fetch_ref_tips) {
- for_each_ref(append_oid_to_array, &ref_tips_before_fetch);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ append_oid_to_array, &ref_tips_before_fetch);
initialized_fetch_ref_tips = 1;
}
@@ -1517,6 +1528,9 @@ static struct fetch_task *fetch_task_create(struct submodule_parallel_fetch *spf
struct fetch_task *task = xmalloc(sizeof(*task));
memset(task, 0, sizeof(*task));
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
task->sub = submodule_from_path(spf->r, treeish_name, path);
if (!task->sub) {
@@ -1878,6 +1892,9 @@ unsigned is_submodule_modified(const char *path, int ignore_untracked)
const char *git_dir;
int ignore_cp_exit_code = 0;
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
strbuf_addf(&buf, "%s/.git", path);
git_dir = read_gitfile(buf.buf);
if (!git_dir)
@@ -1954,6 +1971,9 @@ int submodule_uses_gitfile(const char *path)
struct strbuf buf = STRBUF_INIT;
const char *git_dir;
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
strbuf_addf(&buf, "%s/.git", path);
git_dir = read_gitfile(buf.buf);
if (!git_dir) {
@@ -1993,6 +2013,9 @@ int bad_to_remove_submodule(const char *path, unsigned flags)
struct strbuf buf = STRBUF_INIT;
int ret = 0;
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
if (!file_exists(path) || is_empty_dir(path))
return 0;
@@ -2043,6 +2066,9 @@ void submodule_unset_core_worktree(const struct submodule *sub)
{
struct strbuf config_path = STRBUF_INIT;
+ if (validate_submodule_path(sub->path) < 0)
+ exit(128);
+
submodule_name_to_gitdir(&config_path, the_repository, sub->name);
strbuf_addstr(&config_path, "/config");
@@ -2057,6 +2083,9 @@ static int submodule_has_dirty_index(const struct submodule *sub)
{
struct child_process cp = CHILD_PROCESS_INIT;
+ if (validate_submodule_path(sub->path) < 0)
+ exit(128);
+
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
@@ -2074,6 +2103,10 @@ static int submodule_has_dirty_index(const struct submodule *sub)
static void submodule_reset_index(const char *path, const char *super_prefix)
{
struct child_process cp = CHILD_PROCESS_INIT;
+
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
prepare_submodule_repo_env(&cp.env);
cp.git_cmd = 1;
@@ -2137,10 +2170,27 @@ int submodule_move_head(const char *path, const char *super_prefix,
if (!submodule_uses_gitfile(path))
absorb_git_dir_into_superproject(path,
super_prefix);
+ else {
+ char *dotgit = xstrfmt("%s/.git", path);
+ char *git_dir = xstrdup(read_gitfile(dotgit));
+
+ free(dotgit);
+ if (validate_submodule_git_dir(git_dir,
+ sub->name) < 0)
+ die(_("refusing to create/use '%s' in "
+ "another submodule's git dir"),
+ git_dir);
+ free(git_dir);
+ }
} else {
struct strbuf gitdir = STRBUF_INIT;
submodule_name_to_gitdir(&gitdir, the_repository,
sub->name);
+ if (validate_submodule_git_dir(gitdir.buf,
+ sub->name) < 0)
+ die(_("refusing to create/use '%s' in another "
+ "submodule's git dir"),
+ gitdir.buf);
connect_work_tree_and_git_dir(path, gitdir.buf, 0);
strbuf_release(&gitdir);
@@ -2261,6 +2311,34 @@ int validate_submodule_git_dir(char *git_dir, const char *submodule_name)
return 0;
}
+int validate_submodule_path(const char *path)
+{
+ char *p = xstrdup(path);
+ struct stat st;
+ int i, ret = 0;
+ char sep;
+
+ for (i = 0; !ret && p[i]; i++) {
+ if (!is_dir_sep(p[i]))
+ continue;
+
+ sep = p[i];
+ p[i] = '\0';
+ /* allow missing components, but no symlinks */
+ ret = lstat(p, &st) || !S_ISLNK(st.st_mode) ? 0 : -1;
+ p[i] = sep;
+ if (ret)
+ error(_("expected '%.*s' in submodule path '%s' not to "
+ "be a symbolic link"), i, p, p);
+ }
+ if (!lstat(p, &st) && S_ISLNK(st.st_mode))
+ ret = error(_("expected submodule path '%s' not to be a "
+ "symbolic link"), p);
+ free(p);
+ return ret;
+}
+
+
/*
* Embeds a single submodules git directory into the superprojects git dir,
* non recursively.
@@ -2272,6 +2350,9 @@ static void relocate_single_git_dir_into_superproject(const char *path,
struct strbuf new_gitdir = STRBUF_INIT;
const struct submodule *sub;
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
if (submodule_uses_worktrees(path))
die(_("relocate_gitdir for submodule '%s' with "
"more than one worktree not supported"), path);
@@ -2313,6 +2394,9 @@ static void absorb_git_dir_into_superproject_recurse(const char *path,
struct child_process cp = CHILD_PROCESS_INIT;
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
cp.dir = path;
cp.git_cmd = 1;
cp.no_stdin = 1;
@@ -2337,6 +2421,10 @@ void absorb_git_dir_into_superproject(const char *path,
int err_code;
const char *sub_git_dir;
struct strbuf gitdir = STRBUF_INIT;
+
+ if (validate_submodule_path(path) < 0)
+ exit(128);
+
strbuf_addf(&gitdir, "%s/.git", path);
sub_git_dir = resolve_gitdir_gently(gitdir.buf, &err_code);
@@ -2479,6 +2567,9 @@ int submodule_to_gitdir(struct strbuf *buf, const char *submodule)
const char *git_dir;
int ret = 0;
+ if (validate_submodule_path(submodule) < 0)
+ exit(128);
+
strbuf_reset(buf);
strbuf_addstr(buf, submodule);
strbuf_complete(buf, '/');
diff --git a/submodule.h b/submodule.h
index c55a25ca37..b50d29eba4 100644
--- a/submodule.h
+++ b/submodule.h
@@ -148,6 +148,11 @@ void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r,
*/
int validate_submodule_git_dir(char *git_dir, const char *submodule_name);
+/*
+ * Make sure that the given submodule path does not follow symlinks.
+ */
+int validate_submodule_path(const char *path);
+
#define SUBMODULE_MOVE_HEAD_DRY_RUN (1<<0)
#define SUBMODULE_MOVE_HEAD_FORCE (1<<1)
int submodule_move_head(const char *path, const char *super_prefix,
diff --git a/t/Makefile b/t/Makefile
index 2d95046f26..b2eb9f770b 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -48,7 +48,8 @@ CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.tes
CHAINLINT = '$(PERL_PATH_SQ)' chainlint.pl
UNIT_TEST_SOURCES = $(wildcard unit-tests/t-*.c)
UNIT_TEST_PROGRAMS = $(patsubst unit-tests/%.c,unit-tests/bin/%$(X),$(UNIT_TEST_SOURCES))
-UNIT_TESTS = $(sort $(filter-out unit-tests/bin/t-basic%,$(UNIT_TEST_PROGRAMS)))
+UNIT_TESTS = $(sort $(UNIT_TEST_PROGRAMS))
+UNIT_TESTS_NO_DIR = $(notdir $(UNIT_TESTS))
# `test-chainlint` (which is a dependency of `test-lint`, `test` and `prove`)
# checks all tests in all scripts via a single invocation, so tell individual
@@ -67,7 +68,7 @@ failed:
test -z "$$failed" || $(MAKE) $$failed
prove: pre-clean check-chainlint $(TEST_LINT)
- @echo "*** prove ***"; $(CHAINLINTSUPPRESS) $(PROVE) --exec '$(TEST_SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
+ @echo "*** prove (shell & unit tests) ***"; $(CHAINLINTSUPPRESS) TEST_SHELL_PATH='$(TEST_SHELL_PATH_SQ)' $(PROVE) --exec ./run-test.sh $(GIT_PROVE_OPTS) $(T) $(UNIT_TESTS) :: $(GIT_TEST_OPTS)
$(MAKE) clean-except-prove-cache
$(T):
@@ -76,7 +77,7 @@ $(T):
$(UNIT_TESTS):
@echo "*** $@ ***"; $@
-.PHONY: unit-tests unit-tests-raw unit-tests-prove
+.PHONY: unit-tests unit-tests-raw unit-tests-prove unit-tests-test-tool
unit-tests: $(DEFAULT_UNIT_TEST_TARGET)
unit-tests-raw: $(UNIT_TESTS)
@@ -84,6 +85,13 @@ unit-tests-raw: $(UNIT_TESTS)
unit-tests-prove:
@echo "*** prove - unit tests ***"; $(PROVE) $(GIT_PROVE_OPTS) $(UNIT_TESTS)
+unit-tests-test-tool:
+ @echo "*** test-tool - unit tests **"
+ ( \
+ cd unit-tests/bin && \
+ ../../helper/test-tool$X run-command testsuite $(UNIT_TESTS_NO_DIR)\
+ )
+
pre-clean:
$(RM) -r '$(TEST_RESULTS_DIRECTORY_SQ)'
diff --git a/t/helper/test-bitmap.c b/t/helper/test-bitmap.c
index af43ee1cb5..6af2b42678 100644
--- a/t/helper/test-bitmap.c
+++ b/t/helper/test-bitmap.c
@@ -13,21 +13,41 @@ static int bitmap_dump_hashes(void)
return test_bitmap_hashes(the_repository);
}
+static int bitmap_dump_pseudo_merges(void)
+{
+ return test_bitmap_pseudo_merges(the_repository);
+}
+
+static int bitmap_dump_pseudo_merge_commits(uint32_t n)
+{
+ return test_bitmap_pseudo_merge_commits(the_repository, n);
+}
+
+static int bitmap_dump_pseudo_merge_objects(uint32_t n)
+{
+ return test_bitmap_pseudo_merge_objects(the_repository, n);
+}
+
int cmd__bitmap(int argc, const char **argv)
{
setup_git_directory();
- if (argc != 2)
- goto usage;
-
- if (!strcmp(argv[1], "list-commits"))
+ if (argc == 2 && !strcmp(argv[1], "list-commits"))
return bitmap_list_commits();
- if (!strcmp(argv[1], "dump-hashes"))
+ if (argc == 2 && !strcmp(argv[1], "dump-hashes"))
return bitmap_dump_hashes();
+ if (argc == 2 && !strcmp(argv[1], "dump-pseudo-merges"))
+ return bitmap_dump_pseudo_merges();
+ if (argc == 3 && !strcmp(argv[1], "dump-pseudo-merge-commits"))
+ return bitmap_dump_pseudo_merge_commits(atoi(argv[2]));
+ if (argc == 3 && !strcmp(argv[1], "dump-pseudo-merge-objects"))
+ return bitmap_dump_pseudo_merge_objects(atoi(argv[2]));
-usage:
usage("\ttest-tool bitmap list-commits\n"
- "\ttest-tool bitmap dump-hashes");
+ "\ttest-tool bitmap dump-hashes\n"
+ "\ttest-tool bitmap dump-pseudo-merges\n"
+ "\ttest-tool bitmap dump-pseudo-merge-commits <n>\n"
+ "\ttest-tool bitmap dump-pseudo-merge-objects <n>");
return -1;
}
diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c
index 1281e66876..eefc1668c7 100644
--- a/t/helper/test-bloom.c
+++ b/t/helper/test-bloom.c
@@ -49,6 +49,7 @@ static void get_bloom_filter_for_commit(const struct object_id *commit_oid)
static const char *bloom_usage = "\n"
" test-tool bloom get_murmur3 <string>\n"
+" test-tool bloom get_murmur3_seven_highbit\n"
" test-tool bloom generate_filter <string> [<string>...]\n"
" test-tool bloom get_filter_for_commit <commit-hex>\n";
@@ -63,7 +64,13 @@ int cmd__bloom(int argc, const char **argv)
uint32_t hashed;
if (argc < 3)
usage(bloom_usage);
- hashed = murmur3_seeded(0, argv[2], strlen(argv[2]));
+ hashed = murmur3_seeded_v2(0, argv[2], strlen(argv[2]));
+ printf("Murmur3 Hash with seed=0:0x%08x\n", hashed);
+ }
+
+ if (!strcmp(argv[1], "get_murmur3_seven_highbit")) {
+ uint32_t hashed;
+ hashed = murmur3_seeded_v2(0, "\x99\xaa\xbb\xcc\xdd\xee\xff", 7);
printf("Murmur3 Hash with seed=0:0x%08x\n", hashed);
}
diff --git a/t/helper/test-cache-tree.c b/t/helper/test-cache-tree.c
index e7236392c8..dc89ecfd71 100644
--- a/t/helper/test-cache-tree.c
+++ b/t/helper/test-cache-tree.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
#include "gettext.h"
#include "hex.h"
@@ -38,29 +37,29 @@ int cmd__cache_tree(int argc, const char **argv)
if (repo_read_index(the_repository) < 0)
die(_("unable to read index file"));
- oidcpy(&oid, &the_index.cache_tree->oid);
+ oidcpy(&oid, &the_repository->index->cache_tree->oid);
tree = parse_tree_indirect(&oid);
if (!tree)
die(_("not a tree object: %s"), oid_to_hex(&oid));
if (empty) {
/* clear the cache tree & allocate a new one */
- cache_tree_free(&the_index.cache_tree);
- the_index.cache_tree = cache_tree();
+ cache_tree_free(&the_repository->index->cache_tree);
+ the_repository->index->cache_tree = cache_tree();
} else if (invalidate_qty) {
/* invalidate the specified number of unique paths */
- float f_interval = (float)the_index.cache_nr / invalidate_qty;
+ float f_interval = (float)the_repository->index->cache_nr / invalidate_qty;
int interval = f_interval < 1.0 ? 1 : (int)f_interval;
- for (i = 0; i < invalidate_qty && i * interval < the_index.cache_nr; i++)
- cache_tree_invalidate_path(&the_index, the_index.cache[i * interval]->name);
+ for (i = 0; i < invalidate_qty && i * interval < the_repository->index->cache_nr; i++)
+ cache_tree_invalidate_path(the_repository->index, the_repository->index->cache[i * interval]->name);
}
if (argc != 1)
usage_with_options(test_cache_tree_usage, options);
else if (!strcmp(argv[0], "prime"))
- prime_cache_tree(the_repository, &the_index, tree);
+ prime_cache_tree(the_repository, the_repository->index, tree);
else if (!strcmp(argv[0], "update"))
- cache_tree_update(&the_index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
+ cache_tree_update(the_repository->index, WRITE_TREE_SILENT | WRITE_TREE_REPAIR);
/* use "control" subcommand to specify no-op */
else if (!!strcmp(argv[0], "control"))
die(_("Unhandled subcommand '%s'"), argv[0]);
diff --git a/t/helper/test-dump-cache-tree.c b/t/helper/test-dump-cache-tree.c
index c38f546e4f..02b0b46c3f 100644
--- a/t/helper/test-dump-cache-tree.c
+++ b/t/helper/test-dump-cache-tree.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
#include "hash.h"
#include "hex.h"
@@ -68,10 +67,10 @@ int cmd__dump_cache_tree(int ac UNUSED, const char **av UNUSED)
setup_git_directory();
if (repo_read_index(the_repository) < 0)
die("unable to read index file");
- istate = the_index;
+ istate = *the_repository->index;
istate.cache_tree = another;
cache_tree_update(&istate, WRITE_TREE_DRY_RUN);
- ret = dump_cache_tree(the_index.cache_tree, another, "");
+ ret = dump_cache_tree(the_repository->index->cache_tree, another, "");
cache_tree_free(&another);
return ret;
diff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c
index f29d18ef94..f472691a3c 100644
--- a/t/helper/test-dump-split-index.c
+++ b/t/helper/test-dump-split-index.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
#include "hex.h"
#include "read-cache-ll.h"
@@ -19,16 +18,16 @@ int cmd__dump_split_index(int ac UNUSED, const char **av)
setup_git_directory();
- do_read_index(&the_index, av[1], 1);
- printf("own %s\n", oid_to_hex(&the_index.oid));
- si = the_index.split_index;
+ do_read_index(the_repository->index, av[1], 1);
+ printf("own %s\n", oid_to_hex(&the_repository->index->oid));
+ si = the_repository->index->split_index;
if (!si) {
printf("not a split index\n");
return 0;
}
printf("base %s\n", oid_to_hex(&si->base_oid));
- for (i = 0; i < the_index.cache_nr; i++) {
- struct cache_entry *ce = the_index.cache[i];
+ for (i = 0; i < the_repository->index->cache_nr; i++) {
+ struct cache_entry *ce = the_repository->index->cache[i];
printf("%06o %s %d\t%s\n", ce->ce_mode,
oid_to_hex(&ce->oid), ce_stage(ce), ce->name);
}
diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c
index b4af9712fe..9ff67c3967 100644
--- a/t/helper/test-dump-untracked-cache.c
+++ b/t/helper/test-dump-untracked-cache.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
#include "dir.h"
#include "hex.h"
@@ -56,7 +55,7 @@ int cmd__dump_untracked_cache(int ac UNUSED, const char **av UNUSED)
setup_git_directory();
if (repo_read_index(the_repository) < 0)
die("unable to read index file");
- uc = the_index.untracked;
+ uc = the_repository->index->untracked;
if (!uc) {
printf("no untracked cache\n");
return 0;
diff --git a/t/unit-tests/t-basic.c b/t/helper/test-example-tap.c
index fda1ae59a6..d072ad559f 100644
--- a/t/unit-tests/t-basic.c
+++ b/t/helper/test-example-tap.c
@@ -1,4 +1,5 @@
-#include "test-lib.h"
+#include "test-tool.h"
+#include "t/unit-tests/test-lib.h"
/*
* The purpose of this "unit test" is to verify a few invariants of the unit
@@ -69,7 +70,7 @@ static void t_empty(void)
; /* empty */
}
-int cmd_main(int argc, const char **argv)
+int cmd__example_tap(int argc, const char **argv)
{
test_res = TEST(check_res = check_int(1, ==, 1), "passing test");
TEST(t_res(1), "passing test and assertion return 1");
diff --git a/t/helper/test-lazy-init-name-hash.c b/t/helper/test-lazy-init-name-hash.c
index 187a115d57..5f33bb7b8f 100644
--- a/t/helper/test-lazy-init-name-hash.c
+++ b/t/helper/test-lazy-init-name-hash.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
#include "environment.h"
#include "name-hash.h"
@@ -40,22 +39,22 @@ static void dump_run(void)
repo_read_index(the_repository);
if (single) {
- test_lazy_init_name_hash(&the_index, 0);
+ test_lazy_init_name_hash(the_repository->index, 0);
} else {
- int nr_threads_used = test_lazy_init_name_hash(&the_index, 1);
+ int nr_threads_used = test_lazy_init_name_hash(the_repository->index, 1);
if (!nr_threads_used)
die("non-threaded code path used");
}
- hashmap_for_each_entry(&the_index.dir_hash, &iter_dir, dir,
+ hashmap_for_each_entry(&the_repository->index->dir_hash, &iter_dir, dir,
ent /* member name */)
printf("dir %08x %7d %s\n", dir->ent.hash, dir->nr, dir->name);
- hashmap_for_each_entry(&the_index.name_hash, &iter_cache, ce,
+ hashmap_for_each_entry(&the_repository->index->name_hash, &iter_cache, ce,
ent /* member name */)
printf("name %08x %s\n", ce->ent.hash, ce->name);
- discard_index(&the_index);
+ discard_index(the_repository->index);
}
/*
@@ -74,7 +73,7 @@ static uint64_t time_runs(int try_threaded)
t0 = getnanotime();
repo_read_index(the_repository);
t1 = getnanotime();
- nr_threads_used = test_lazy_init_name_hash(&the_index, try_threaded);
+ nr_threads_used = test_lazy_init_name_hash(the_repository->index, try_threaded);
t2 = getnanotime();
sum += (t2 - t1);
@@ -86,16 +85,16 @@ static uint64_t time_runs(int try_threaded)
printf("%f %f %d multi %d\n",
((double)(t1 - t0))/1000000000,
((double)(t2 - t1))/1000000000,
- the_index.cache_nr,
+ the_repository->index->cache_nr,
nr_threads_used);
else
printf("%f %f %d single\n",
((double)(t1 - t0))/1000000000,
((double)(t2 - t1))/1000000000,
- the_index.cache_nr);
+ the_repository->index->cache_nr);
fflush(stdout);
- discard_index(&the_index);
+ discard_index(the_repository->index);
}
avg = sum / count;
@@ -120,8 +119,8 @@ static void analyze_run(void)
int nr;
repo_read_index(the_repository);
- cache_nr_limit = the_index.cache_nr;
- discard_index(&the_index);
+ cache_nr_limit = the_repository->index->cache_nr;
+ discard_index(the_repository->index);
nr = analyze;
while (1) {
@@ -135,22 +134,22 @@ static void analyze_run(void)
for (i = 0; i < count; i++) {
repo_read_index(the_repository);
- the_index.cache_nr = nr; /* cheap truncate of index */
+ the_repository->index->cache_nr = nr; /* cheap truncate of index */
t1s = getnanotime();
- test_lazy_init_name_hash(&the_index, 0);
+ test_lazy_init_name_hash(the_repository->index, 0);
t2s = getnanotime();
sum_single += (t2s - t1s);
- the_index.cache_nr = cache_nr_limit;
- discard_index(&the_index);
+ the_repository->index->cache_nr = cache_nr_limit;
+ discard_index(the_repository->index);
repo_read_index(the_repository);
- the_index.cache_nr = nr; /* cheap truncate of index */
+ the_repository->index->cache_nr = nr; /* cheap truncate of index */
t1m = getnanotime();
- nr_threads_used = test_lazy_init_name_hash(&the_index, 1);
+ nr_threads_used = test_lazy_init_name_hash(the_repository->index, 1);
t2m = getnanotime();
sum_multi += (t2m - t1m);
- the_index.cache_nr = cache_nr_limit;
- discard_index(&the_index);
+ the_repository->index->cache_nr = cache_nr_limit;
+ discard_index(the_repository->index);
if (!nr_threads_used)
printf(" [size %8d] [single %f] non-threaded code path used\n",
diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c
index 70396fa384..023ed2e1a7 100644
--- a/t/helper/test-path-utils.c
+++ b/t/helper/test-path-utils.c
@@ -7,6 +7,7 @@
#include "string-list.h"
#include "trace.h"
#include "utf8.h"
+#include "copy.h"
/*
* A "string_list_each_func_t" function that normalizes an entry from
@@ -500,6 +501,16 @@ int cmd__path_utils(int argc, const char **argv)
return !!res;
}
+ if (argc == 4 && !strcmp(argv[1], "do_files_match")) {
+ int ret = do_files_match(argv[2], argv[3]);
+
+ if (ret)
+ printf("equal\n");
+ else
+ printf("different\n");
+ return !ret;
+ }
+
fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
argv[1] ? argv[1] : "(there was none)");
return 1;
diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c
index 1acd362346..e803c43ece 100644
--- a/t/helper/test-read-cache.c
+++ b/t/helper/test-read-cache.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
#include "config.h"
#include "read-cache-ll.h"
@@ -10,7 +9,7 @@ int cmd__read_cache(int argc, const char **argv)
int i, cnt = 1;
const char *name = NULL;
- initialize_the_repository();
+ initialize_repository(the_repository);
if (argc > 1 && skip_prefix(argv[1], "--print-and-refresh=", &name)) {
argc--;
@@ -27,16 +26,16 @@ int cmd__read_cache(int argc, const char **argv)
if (name) {
int pos;
- refresh_index(&the_index, REFRESH_QUIET,
+ refresh_index(the_repository->index, REFRESH_QUIET,
NULL, NULL, NULL);
- pos = index_name_pos(&the_index, name, strlen(name));
+ pos = index_name_pos(the_repository->index, name, strlen(name));
if (pos < 0)
die("%s not in index", name);
printf("%s is%s up to date\n", name,
- ce_uptodate(the_index.cache[pos]) ? "" : " not");
+ ce_uptodate(the_repository->index->cache[pos]) ? "" : " not");
write_file(name, "%d\n", i);
}
- discard_index(&the_index);
+ discard_index(the_repository->index);
}
return 0;
}
diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c
index 8c7a83f578..899b5f41cc 100644
--- a/t/helper/test-read-graph.c
+++ b/t/helper/test-read-graph.c
@@ -5,20 +5,8 @@
#include "bloom.h"
#include "setup.h"
-int cmd__read_graph(int argc UNUSED, const char **argv UNUSED)
+static void dump_graph_info(struct commit_graph *graph)
{
- struct commit_graph *graph = NULL;
- struct object_directory *odb;
-
- setup_git_directory();
- odb = the_repository->objects->odb;
-
- prepare_repo_settings(the_repository);
-
- graph = read_commit_graph_one(the_repository, odb);
- if (!graph)
- return 1;
-
printf("header: %08x %d %d %d %d\n",
ntohl(*(uint32_t*)graph->data),
*(unsigned char*)(graph->data + 4),
@@ -57,8 +45,57 @@ int cmd__read_graph(int argc UNUSED, const char **argv UNUSED)
if (graph->topo_levels)
printf(" topo_levels");
printf("\n");
+}
+
+static void dump_graph_bloom_filters(struct commit_graph *graph)
+{
+ uint32_t i;
+
+ for (i = 0; i < graph->num_commits + graph->num_commits_in_base; i++) {
+ struct bloom_filter filter = { 0 };
+ size_t j;
+
+ if (load_bloom_filter_from_graph(graph, &filter, i) < 0) {
+ fprintf(stderr, "missing Bloom filter for graph "
+ "position %"PRIu32"\n", i);
+ continue;
+ }
+
+ for (j = 0; j < filter.len; j++)
+ printf("%02x", filter.data[j]);
+ if (filter.len)
+ printf("\n");
+ }
+}
+
+int cmd__read_graph(int argc, const char **argv)
+{
+ struct commit_graph *graph = NULL;
+ struct object_directory *odb;
+ int ret = 0;
+
+ setup_git_directory();
+ odb = the_repository->objects->odb;
+
+ prepare_repo_settings(the_repository);
+
+ graph = read_commit_graph_one(the_repository, odb);
+ if (!graph) {
+ ret = 1;
+ goto done;
+ }
+
+ if (argc <= 1)
+ dump_graph_info(graph);
+ else if (!strcmp(argv[1], "bloom-filters"))
+ dump_graph_bloom_filters(graph);
+ else {
+ fprintf(stderr, "unknown sub-command: '%s'\n", argv[1]);
+ ret = 1;
+ }
+done:
UNLEAK(graph);
- return 0;
+ return ret;
}
diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c
index 82bbf6e2e6..4651e4ced7 100644
--- a/t/helper/test-ref-store.c
+++ b/t/helper/test-ref-store.c
@@ -118,7 +118,7 @@ static int cmd_create_symref(struct ref_store *refs, const char **argv)
const char *target = notnull(*argv++, "target");
const char *logmsg = *argv++;
- return refs_create_symref(refs, refname, target, logmsg);
+ return refs_update_symref(refs, refname, target, logmsg);
}
static struct flag_definition transaction_flags[] = {
diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c
index 00237ef0d9..bae731669c 100644
--- a/t/helper/test-reftable.c
+++ b/t/helper/test-reftable.c
@@ -13,7 +13,6 @@ int cmd__reftable(int argc, const char **argv)
readwrite_test_main(argc, argv);
merged_test_main(argc, argv);
stack_test_main(argc, argv);
- refname_test_main(argc, argv);
return 0;
}
diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c
index c0ed8722c8..61eb1175fe 100644
--- a/t/helper/test-run-command.c
+++ b/t/helper/test-run-command.c
@@ -65,6 +65,7 @@ struct testsuite {
struct string_list tests, failed;
int next;
int quiet, immediate, verbose, verbose_log, trace, write_junit_xml;
+ const char *shell_path;
};
#define TESTSUITE_INIT { \
.tests = STRING_LIST_INIT_DUP, \
@@ -80,7 +81,9 @@ static int next_test(struct child_process *cp, struct strbuf *err, void *cb,
return 0;
test = suite->tests.items[suite->next++].string;
- strvec_pushl(&cp->args, "sh", test, NULL);
+ if (suite->shell_path)
+ strvec_push(&cp->args, suite->shell_path);
+ strvec_push(&cp->args, test);
if (suite->quiet)
strvec_push(&cp->args, "--quiet");
if (suite->immediate)
@@ -155,6 +158,8 @@ static int testsuite(int argc, const char **argv)
.task_finished = test_finished,
.data = &suite,
};
+ struct strbuf progpath = STRBUF_INIT;
+ size_t path_prefix_len;
argc = parse_options(argc, argv, NULL, options,
testsuite_usage, PARSE_OPT_STOP_AT_NON_OPTION);
@@ -162,26 +167,36 @@ static int testsuite(int argc, const char **argv)
if (max_jobs <= 0)
max_jobs = online_cpus();
+ /*
+ * If we run without a shell, execute the programs directly from CWD.
+ */
+ suite.shell_path = getenv("TEST_SHELL_PATH");
+ if (!suite.shell_path)
+ strbuf_addstr(&progpath, "./");
+ path_prefix_len = progpath.len;
+
dir = opendir(".");
if (!dir)
die("Could not open the current directory");
while ((d = readdir(dir))) {
const char *p = d->d_name;
- if (*p != 't' || !isdigit(p[1]) || !isdigit(p[2]) ||
- !isdigit(p[3]) || !isdigit(p[4]) || p[5] != '-' ||
- !ends_with(p, ".sh"))
+ if (!strcmp(p, ".") || !strcmp(p, ".."))
continue;
/* No pattern: match all */
if (!argc) {
- string_list_append(&suite.tests, p);
+ strbuf_setlen(&progpath, path_prefix_len);
+ strbuf_addstr(&progpath, p);
+ string_list_append(&suite.tests, progpath.buf);
continue;
}
for (i = 0; i < argc; i++)
if (!wildmatch(argv[i], p, 0)) {
- string_list_append(&suite.tests, p);
+ strbuf_setlen(&progpath, path_prefix_len);
+ strbuf_addstr(&progpath, p);
+ string_list_append(&suite.tests, progpath.buf);
break;
}
}
@@ -208,6 +223,7 @@ static int testsuite(int argc, const char **argv)
string_list_clear(&suite.tests, 0);
string_list_clear(&suite.failed, 0);
+ strbuf_release(&progpath);
return ret;
}
diff --git a/t/helper/test-scrap-cache-tree.c b/t/helper/test-scrap-cache-tree.c
index 0a816a96e2..737cbe475b 100644
--- a/t/helper/test-scrap-cache-tree.c
+++ b/t/helper/test-scrap-cache-tree.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
#include "lockfile.h"
#include "read-cache-ll.h"
@@ -15,9 +14,9 @@ int cmd__scrap_cache_tree(int ac UNUSED, const char **av UNUSED)
repo_hold_locked_index(the_repository, &index_lock, LOCK_DIE_ON_ERROR);
if (repo_read_index(the_repository) < 0)
die("unable to read index file");
- cache_tree_free(&the_index.cache_tree);
- the_index.cache_tree = NULL;
- if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
+ cache_tree_free(&the_repository->index->cache_tree);
+ the_repository->index->cache_tree = NULL;
+ if (write_locked_index(the_repository->index, &index_lock, COMMIT_LOCK))
die("unable to write index file");
return 0;
}
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index 80a946b847..f707eb5893 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -30,6 +30,7 @@ static struct test_cmd cmds[] = {
{ "dump-untracked-cache", cmd__dump_untracked_cache },
{ "env-helper", cmd__env_helper },
{ "example-decorate", cmd__example_decorate },
+ { "example-tap", cmd__example_tap },
{ "find-pack", cmd__find_pack },
{ "fsmonitor-client", cmd__fsmonitor_client },
{ "genrandom", cmd__genrandom },
@@ -87,6 +88,7 @@ static struct test_cmd cmds[] = {
{ "truncate", cmd__truncate },
{ "userdiff", cmd__userdiff },
{ "urlmatch-normalization", cmd__urlmatch_normalization },
+ { "xgethostname", cmd__xgethostname },
{ "xml-encode", cmd__xml_encode },
{ "wildmatch", cmd__wildmatch },
#ifdef GIT_WINDOWS_NATIVE
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index 2808b92419..b4805000cb 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -24,6 +24,7 @@ int cmd__dump_untracked_cache(int argc, const char **argv);
int cmd__dump_reftable(int argc, const char **argv);
int cmd__env_helper(int argc, const char **argv);
int cmd__example_decorate(int argc, const char **argv);
+int cmd__example_tap(int argc, const char **argv);
int cmd__find_pack(int argc, const char **argv);
int cmd__fsmonitor_client(int argc, const char **argv);
int cmd__genrandom(int argc, const char **argv);
@@ -80,6 +81,7 @@ int cmd__trace2(int argc, const char **argv);
int cmd__truncate(int argc, const char **argv);
int cmd__userdiff(int argc, const char **argv);
int cmd__urlmatch_normalization(int argc, const char **argv);
+int cmd__xgethostname(int argc, const char **argv);
int cmd__xml_encode(int argc, const char **argv);
int cmd__wildmatch(int argc, const char **argv);
#ifdef GIT_WINDOWS_NATIVE
diff --git a/t/helper/test-write-cache.c b/t/helper/test-write-cache.c
index f084034d38..7e3da380a9 100644
--- a/t/helper/test-write-cache.c
+++ b/t/helper/test-write-cache.c
@@ -1,4 +1,3 @@
-#define USE_THE_INDEX_VARIABLE
#include "test-tool.h"
#include "lockfile.h"
#include "read-cache-ll.h"
@@ -16,7 +15,7 @@ int cmd__write_cache(int argc, const char **argv)
for (i = 0; i < cnt; i++) {
repo_hold_locked_index(the_repository, &index_lock,
LOCK_DIE_ON_ERROR);
- if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
+ if (write_locked_index(the_repository->index, &index_lock, COMMIT_LOCK))
die("unable to write index file");
}
diff --git a/t/helper/test-xgethostname.c b/t/helper/test-xgethostname.c
new file mode 100644
index 0000000000..285746aef5
--- /dev/null
+++ b/t/helper/test-xgethostname.c
@@ -0,0 +1,12 @@
+#include "test-tool.h"
+
+int cmd__xgethostname(int argc, const char **argv)
+{
+ char hostname[HOST_NAME_MAX + 1];
+
+ if (xgethostname(hostname, sizeof(hostname)))
+ die("unable to get the host name");
+
+ puts(hostname);
+ return 0;
+}
diff --git a/t/lib-chunk.sh b/t/lib-chunk.sh
index a7cd9c3c6d..9f01df190b 100644
--- a/t/lib-chunk.sh
+++ b/t/lib-chunk.sh
@@ -13,5 +13,6 @@ corrupt_chunk_file () {
fn=$1; shift
perl "$TEST_DIRECTORY"/lib-chunk/corrupt-chunk-file.pl \
"$@" <"$fn" >"$fn.tmp" &&
- mv "$fn.tmp" "$fn"
+ # some vintages of macOS 'mv' fails to overwrite a read-only file.
+ mv -f "$fn.tmp" "$fn"
}
diff --git a/t/lib-credential.sh b/t/lib-credential.sh
index 44799c0d38..58b9c74060 100644
--- a/t/lib-credential.sh
+++ b/t/lib-credential.sh
@@ -538,6 +538,129 @@ helper_test_oauth_refresh_token() {
'
}
+helper_test_authtype() {
+ HELPER=$1
+
+ test_expect_success "helper ($HELPER) stores authtype and credential" '
+ check approve $HELPER <<-\EOF
+ capability[]=authtype
+ authtype=Bearer
+ credential=random-token
+ protocol=https
+ host=git.example.com
+ EOF
+ '
+
+ test_expect_success "helper ($HELPER) gets authtype and credential" '
+ check fill $HELPER <<-\EOF
+ capability[]=authtype
+ protocol=https
+ host=git.example.com
+ --
+ capability[]=authtype
+ authtype=Bearer
+ credential=random-token
+ protocol=https
+ host=git.example.com
+ --
+ EOF
+ '
+
+ test_expect_success "helper ($HELPER) stores authtype and credential with username" '
+ check approve $HELPER <<-\EOF
+ capability[]=authtype
+ authtype=Bearer
+ credential=other-token
+ protocol=https
+ host=git.example.com
+ username=foobar
+ EOF
+ '
+
+ test_expect_success "helper ($HELPER) gets authtype and credential with username" '
+ check fill $HELPER <<-\EOF
+ capability[]=authtype
+ protocol=https
+ host=git.example.com
+ username=foobar
+ --
+ capability[]=authtype
+ authtype=Bearer
+ credential=other-token
+ protocol=https
+ host=git.example.com
+ username=foobar
+ --
+ EOF
+ '
+
+ test_expect_success "helper ($HELPER) does not get authtype and credential with different username" '
+ check fill $HELPER <<-\EOF
+ capability[]=authtype
+ protocol=https
+ host=git.example.com
+ username=barbaz
+ --
+ protocol=https
+ host=git.example.com
+ username=barbaz
+ password=askpass-password
+ --
+ askpass: Password for '\''https://barbaz@git.example.com'\'':
+ EOF
+ '
+
+ test_expect_success "helper ($HELPER) does not store ephemeral authtype and credential" '
+ check approve $HELPER <<-\EOF &&
+ capability[]=authtype
+ authtype=Bearer
+ credential=git2-token
+ protocol=https
+ host=git2.example.com
+ ephemeral=1
+ EOF
+
+ check fill $HELPER <<-\EOF
+ capability[]=authtype
+ protocol=https
+ host=git2.example.com
+ --
+ protocol=https
+ host=git2.example.com
+ username=askpass-username
+ password=askpass-password
+ --
+ askpass: Username for '\''https://git2.example.com'\'':
+ askpass: Password for '\''https://askpass-username@git2.example.com'\'':
+ EOF
+ '
+
+ test_expect_success "helper ($HELPER) does not store ephemeral username and password" '
+ check approve $HELPER <<-\EOF &&
+ capability[]=authtype
+ protocol=https
+ host=git2.example.com
+ user=barbaz
+ password=secret
+ ephemeral=1
+ EOF
+
+ check fill $HELPER <<-\EOF
+ capability[]=authtype
+ protocol=https
+ host=git2.example.com
+ --
+ protocol=https
+ host=git2.example.com
+ username=askpass-username
+ password=askpass-password
+ --
+ askpass: Username for '\''https://git2.example.com'\'':
+ askpass: Password for '\''https://askpass-username@git2.example.com'\'':
+ EOF
+ '
+}
+
write_script askpass <<\EOF
echo >&2 askpass: $*
what=$(echo $1 | cut -d" " -f1 | tr A-Z a-z | tr -cd a-z)
diff --git a/t/lib-httpd/nph-custom-auth.sh b/t/lib-httpd/nph-custom-auth.sh
index f5345e775e..d408d2caad 100644
--- a/t/lib-httpd/nph-custom-auth.sh
+++ b/t/lib-httpd/nph-custom-auth.sh
@@ -19,21 +19,30 @@ CHALLENGE_FILE=custom-auth.challenge
#
if test -n "$HTTP_AUTHORIZATION" && \
- grep -Fqsx "${HTTP_AUTHORIZATION}" "$VALID_CREDS_FILE"
+ grep -Fqs "creds=${HTTP_AUTHORIZATION}" "$VALID_CREDS_FILE"
then
+ idno=$(grep -F "creds=${HTTP_AUTHORIZATION}" "$VALID_CREDS_FILE" | sed -e 's/^id=\([a-z0-9-][a-z0-9-]*\) .*$/\1/')
+ status=$(sed -ne "s/^id=$idno.*status=\\([0-9][0-9][0-9]\\).*\$/\\1/p" "$CHALLENGE_FILE" | head -n1)
# Note that although git-http-backend returns a status line, it
# does so using a CGI 'Status' header. Because this script is an
# No Parsed Headers (NPH) script, we must return a real HTTP
# status line.
# This is only a test script, so we don't bother to check for
# the actual status from git-http-backend and always return 200.
- echo 'HTTP/1.1 200 OK'
- exec "$GIT_EXEC_PATH"/git-http-backend
+ echo "HTTP/1.1 $status Nonspecific Reason Phrase"
+ if test "$status" -eq 200
+ then
+ exec "$GIT_EXEC_PATH"/git-http-backend
+ else
+ sed -ne "s/^id=$idno.*response=//p" "$CHALLENGE_FILE"
+ echo
+ exit
+ fi
fi
echo 'HTTP/1.1 401 Authorization Required'
if test -f "$CHALLENGE_FILE"
then
- cat "$CHALLENGE_FILE"
+ sed -ne 's/^id=default.*response=//p' "$CHALLENGE_FILE"
fi
echo
diff --git a/t/perf/p5333-pseudo-merge-bitmaps.sh b/t/perf/p5333-pseudo-merge-bitmaps.sh
new file mode 100755
index 0000000000..4bec409d10
--- /dev/null
+++ b/t/perf/p5333-pseudo-merge-bitmaps.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+test_description='pseudo-merge bitmaps'
+. ./perf-lib.sh
+
+test_perf_large_repo
+
+test_expect_success 'setup' '
+ git \
+ -c bitmapPseudoMerge.all.pattern="refs/" \
+ -c bitmapPseudoMerge.all.threshold=now \
+ -c bitmapPseudoMerge.all.stableThreshold=never \
+ -c bitmapPseudoMerge.all.maxMerges=64 \
+ -c pack.writeBitmapLookupTable=true \
+ repack -adb
+'
+
+test_perf 'git rev-list --count --all --objects (no bitmaps)' '
+ git rev-list --objects --all
+'
+
+test_perf 'git rev-list --count --all --objects (no pseudo-merges)' '
+ GIT_TEST_USE_PSEDUO_MERGES=0 \
+ git rev-list --objects --all --use-bitmap-index
+'
+
+test_perf 'git rev-list --count --all --objects (with pseudo-merges)' '
+ GIT_TEST_USE_PSEDUO_MERGES=1 \
+ git rev-list --objects --all --use-bitmap-index
+'
+
+test_done
diff --git a/t/run-test.sh b/t/run-test.sh
new file mode 100755
index 0000000000..13c353b91b
--- /dev/null
+++ b/t/run-test.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# A simple wrapper to run shell tests via TEST_SHELL_PATH,
+# or exec unit tests directly.
+
+case "$1" in
+*.sh)
+ if test -z "${TEST_SHELL_PATH}"
+ then
+ echo >&2 "ERROR: TEST_SHELL_PATH is empty or not set"
+ exit 1
+ fi
+ exec "${TEST_SHELL_PATH}" "$@"
+ ;;
+*)
+ exec "$@"
+ ;;
+esac
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 6e300be2ac..98b81e4d63 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -1201,6 +1201,34 @@ test_expect_success 'very long name in the index handled sanely' '
test $len = 4098
'
+# D/F conflict checking uses an optimization when adding to the end.
+# make sure it does not get confused by `a-` sorting _between_
+# `a` and `a/`.
+test_expect_success 'more update-index D/F conflicts' '
+ # empty the index to make sure our entry is last
+ git read-tree --empty &&
+ cacheinfo=100644,$(test_oid empty_blob) &&
+ git update-index --add --cacheinfo $cacheinfo,path5/a &&
+
+ test_must_fail git update-index --add --cacheinfo $cacheinfo,path5/a/file &&
+ test_must_fail git update-index --add --cacheinfo $cacheinfo,path5/a/b/file &&
+ test_must_fail git update-index --add --cacheinfo $cacheinfo,path5/a/b/c/file &&
+
+ # "a-" sorts between "a" and "a/"
+ git update-index --add --cacheinfo $cacheinfo,path5/a- &&
+
+ test_must_fail git update-index --add --cacheinfo $cacheinfo,path5/a/file &&
+ test_must_fail git update-index --add --cacheinfo $cacheinfo,path5/a/b/file &&
+ test_must_fail git update-index --add --cacheinfo $cacheinfo,path5/a/b/c/file &&
+
+ cat >expected <<-\EOF &&
+ path5/a
+ path5/a-
+ EOF
+ git ls-files >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'test_must_fail on a failing git command' '
test_must_fail git notacommand
'
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index 774b52c298..66ccb5889d 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -398,13 +398,19 @@ test_expect_success 'bad attr source defaults to reading .gitattributes file' '
)
'
-test_expect_success 'bare repo defaults to reading .gitattributes from HEAD' '
+test_expect_success 'bare repo no longer defaults to reading .gitattributes from HEAD' '
test_when_finished rm -rf test bare_with_gitattribute &&
git init test &&
test_commit -C test gitattributes .gitattributes "f/path test=val" &&
git clone --bare test bare_with_gitattribute &&
- echo "f/path: test: val" >expect &&
+
+ echo "f/path: test: unspecified" >expect &&
git -C bare_with_gitattribute check-attr test -- f/path >actual &&
+ test_cmp expect actual &&
+
+ echo "f/path: test: val" >expect &&
+ git -C bare_with_gitattribute -c attr.tree=HEAD \
+ check-attr test -- f/path >actual &&
test_cmp expect actual
'
@@ -428,6 +434,21 @@ test_expect_success 'precedence of --attr-source, GIT_ATTR_SOURCE, then attr.tre
)
'
+test_expect_success 'diff without repository with attr source' '
+ mkdir -p "$TRASH_DIRECTORY/outside/nongit" &&
+ (
+ cd "$TRASH_DIRECTORY/outside/nongit" &&
+ GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY/outside" &&
+ export GIT_CEILING_DIRECTORIES &&
+ touch file &&
+ cat >expect <<-EOF &&
+ fatal: cannot use --attr-source or GIT_ATTR_SOURCE without repo
+ EOF
+ test_must_fail env GIT_ATTR_SOURCE=HEAD git grep --no-index foo file 2>err &&
+ test_cmp expect err
+ )
+'
+
test_expect_success 'bare repository: with --source' '
(
cd bare.git &&
@@ -572,6 +593,16 @@ test_expect_success EXPENSIVE 'large attributes file ignored in index' '
test_cmp expect err
'
+test_expect_success EXPENSIVE 'large attributes blob ignored' '
+ test_when_finished "git update-index --remove .gitattributes" &&
+ blob=$(dd if=/dev/zero bs=1048576 count=101 2>/dev/null | git hash-object -w --stdin) &&
+ git update-index --add --cacheinfo 100644,$blob,.gitattributes &&
+ tree="$(git write-tree)" &&
+ git check-attr --cached --all --source="$tree" path >/dev/null 2>err &&
+ echo "warning: ignoring overly large gitattributes blob ${SQ}.gitattributes${SQ}" >expect &&
+ test_cmp expect err
+'
+
test_expect_success 'builtin object mode attributes work (dir and regular paths)' '
>normal &&
attr_check_object_mode normal 100644 &&
diff --git a/t/t0018-advice.sh b/t/t0018-advice.sh
index 0dcfb760a2..29306b367c 100755
--- a/t/t0018-advice.sh
+++ b/t/t0018-advice.sh
@@ -2,6 +2,9 @@
test_description='Test advise_if_enabled functionality'
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=trunk
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
@@ -29,4 +32,72 @@ test_expect_success 'advice should not be printed when config variable is set to
test_must_be_empty actual
'
+test_expect_success 'advice should not be printed when --no-advice is used' '
+ q_to_tab >expect <<-\EOF &&
+ On branch trunk
+
+ No commits yet
+
+ Untracked files:
+ QREADME
+
+ nothing added to commit but untracked files present
+ EOF
+
+ test_when_finished "rm -fr advice-test" &&
+ git init advice-test &&
+ (
+ cd advice-test &&
+ >README &&
+ git --no-advice status
+ ) >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'advice should not be printed when GIT_ADVICE is set to false' '
+ q_to_tab >expect <<-\EOF &&
+ On branch trunk
+
+ No commits yet
+
+ Untracked files:
+ QREADME
+
+ nothing added to commit but untracked files present
+ EOF
+
+ test_when_finished "rm -fr advice-test" &&
+ git init advice-test &&
+ (
+ cd advice-test &&
+ >README &&
+ GIT_ADVICE=false git status
+ ) >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'advice should be printed when GIT_ADVICE is set to true' '
+ q_to_tab >expect <<-\EOF &&
+ On branch trunk
+
+ No commits yet
+
+ Untracked files:
+ (use "git add <file>..." to include in what will be committed)
+ QREADME
+
+ nothing added to commit but untracked files present (use "git add" to track)
+ EOF
+
+ test_when_finished "rm -fr advice-test" &&
+ git init advice-test &&
+ (
+ cd advice-test &&
+ >README &&
+ GIT_ADVICE=true git status
+ ) >actual &&
+ cat actual > /tmp/actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh
index dc3496897a..11c3e8f28e 100755
--- a/t/t0033-safe-directory.sh
+++ b/t/t0033-safe-directory.sh
@@ -80,4 +80,28 @@ test_expect_success 'safe.directory in included file' '
git status
'
+test_expect_success 'local clone of unowned repo refused in unsafe directory' '
+ test_when_finished "rm -rf source" &&
+ git init source &&
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ test_commit -C source initial
+ ) &&
+ test_must_fail git clone --local source target &&
+ test_path_is_missing target
+'
+
+test_expect_success 'local clone of unowned repo accepted in safe directory' '
+ test_when_finished "rm -rf source" &&
+ git init source &&
+ (
+ sane_unset GIT_TEST_ASSUME_DIFFERENT_OWNER &&
+ test_commit -C source initial
+ ) &&
+ test_must_fail git clone --local source target &&
+ git config --global --add safe.directory "$(pwd)/source/.git" &&
+ git clone --local source target &&
+ test_path_is_dir target
+'
+
test_done
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index 8bb2a8b453..45a773642f 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -176,6 +176,23 @@ test_expect_success 'long options' '
test_cmp expect output
'
+test_expect_success 'abbreviate to something longer than SHA1 length' '
+ cat >expect <<-EOF &&
+ boolean: 0
+ integer: 0
+ magnitude: 0
+ timestamp: 0
+ string: (not set)
+ abbrev: 100
+ verbose: -1
+ quiet: 0
+ dry run: no
+ file: (not set)
+ EOF
+ test-tool parse-options --abbrev=100 >output &&
+ test_cmp expect output
+'
+
test_expect_success 'missing required value' '
cat >expect <<-\EOF &&
error: switch `s'\'' requires a value
diff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh
index 325eb1c3cd..925734c819 100755
--- a/t/t0050-filesystem.sh
+++ b/t/t0050-filesystem.sh
@@ -156,4 +156,15 @@ test_expect_success CASE_INSENSITIVE_FS 'checkout with no pathspec and a case in
)
'
+test_expect_success 'git ls-files under NFD' '
+ (
+ mkdir -p "somewhere/$aumlcdiar" &&
+ mypwd=$PWD &&
+ cd "somewhere/$aumlcdiar" &&
+ git init &&
+ git --literal-pathspecs ls-files "$mypwd/somewhere/$aumlcdiar" 2>err &&
+ >expected &&
+ test_cmp expected err
+ )
+'
test_done
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 0afa3d0d31..85686ee15d 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -610,4 +610,45 @@ test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD '%(prefix)/ works'
test_cmp expect actual
'
+test_expect_success 'do_files_match()' '
+ test_seq 0 10 >0-10.txt &&
+ test_seq -1 10 >-1-10.txt &&
+ test_seq 1 10 >1-10.txt &&
+ test_seq 1 9 >1-9.txt &&
+ test_seq 0 8 >0-8.txt &&
+
+ test-tool path-utils do_files_match 0-10.txt 0-10.txt >out &&
+
+ assert_fails() {
+ test_must_fail \
+ test-tool path-utils do_files_match "$1" "$2" >out &&
+ grep different out
+ } &&
+
+ assert_fails 0-8.txt 1-9.txt &&
+ assert_fails -1-10.txt 0-10.txt &&
+ assert_fails 1-10.txt 1-9.txt &&
+ assert_fails 1-10.txt .git &&
+ assert_fails does-not-exist 1-10.txt &&
+
+ if test_have_prereq FILEMODE
+ then
+ cp 0-10.txt 0-10.x &&
+ chmod a+x 0-10.x &&
+ assert_fails 0-10.txt 0-10.x
+ fi &&
+
+ if test_have_prereq SYMLINKS
+ then
+ ln -sf 0-10.txt symlink &&
+ ln -s 0-10.txt another-symlink &&
+ ln -s over-the-ocean yet-another-symlink &&
+ ln -s "$PWD/0-10.txt" absolute-symlink &&
+ assert_fails 0-10.txt symlink &&
+ test-tool path-utils do_files_match symlink another-symlink &&
+ assert_fails symlink yet-another-symlink &&
+ assert_fails symlink absolute-symlink
+ fi
+'
+
test_done
diff --git a/t/t0068-for-each-repo.sh b/t/t0068-for-each-repo.sh
index 4b90b74d5d..95019e01ed 100755
--- a/t/t0068-for-each-repo.sh
+++ b/t/t0068-for-each-repo.sh
@@ -59,4 +59,20 @@ test_expect_success 'error on NULL value for config keys' '
test_cmp expect actual
'
+test_expect_success '--keep-going' '
+ git config keep.going non-existing &&
+ git config --add keep.going . &&
+
+ test_must_fail git for-each-repo --config=keep.going \
+ -- branch >out 2>err &&
+ test_grep "cannot change to .*non-existing" err &&
+ test_must_be_empty out &&
+
+ test_must_fail git for-each-repo --config=keep.going --keep-going \
+ -- branch >out 2>err &&
+ test_grep "cannot change to .*non-existing" err &&
+ git branch >expect &&
+ test_cmp expect out
+'
+
test_done
diff --git a/t/t0080-unit-test-output.sh b/t/t0080-unit-test-output.sh
index 6657c114a3..7bbb065d58 100755
--- a/t/t0080-unit-test-output.sh
+++ b/t/t0080-unit-test-output.sh
@@ -9,50 +9,50 @@ test_expect_success 'TAP output from unit tests' '
cat >expect <<-EOF &&
ok 1 - passing test
ok 2 - passing test and assertion return 1
- # check "1 == 2" failed at t/unit-tests/t-basic.c:76
+ # check "1 == 2" failed at t/helper/test-example-tap.c:77
# left: 1
# right: 2
not ok 3 - failing test
ok 4 - failing test and assertion return 0
not ok 5 - passing TEST_TODO() # TODO
ok 6 - passing TEST_TODO() returns 1
- # todo check ${SQ}check(x)${SQ} succeeded at t/unit-tests/t-basic.c:25
+ # todo check ${SQ}check(x)${SQ} succeeded at t/helper/test-example-tap.c:26
not ok 7 - failing TEST_TODO()
ok 8 - failing TEST_TODO() returns 0
- # check "0" failed at t/unit-tests/t-basic.c:30
+ # check "0" failed at t/helper/test-example-tap.c:31
# skipping test - missing prerequisite
- # skipping check ${SQ}1${SQ} at t/unit-tests/t-basic.c:32
+ # skipping check ${SQ}1${SQ} at t/helper/test-example-tap.c:33
ok 9 - test_skip() # SKIP
ok 10 - skipped test returns 1
# skipping test - missing prerequisite
ok 11 - test_skip() inside TEST_TODO() # SKIP
ok 12 - test_skip() inside TEST_TODO() returns 1
- # check "0" failed at t/unit-tests/t-basic.c:48
+ # check "0" failed at t/helper/test-example-tap.c:49
not ok 13 - TEST_TODO() after failing check
ok 14 - TEST_TODO() after failing check returns 0
- # check "0" failed at t/unit-tests/t-basic.c:56
+ # check "0" failed at t/helper/test-example-tap.c:57
not ok 15 - failing check after TEST_TODO()
ok 16 - failing check after TEST_TODO() returns 0
- # check "!strcmp("\thello\\\\", "there\"\n")" failed at t/unit-tests/t-basic.c:61
+ # check "!strcmp("\thello\\\\", "there\"\n")" failed at t/helper/test-example-tap.c:62
# left: "\011hello\\\\"
# right: "there\"\012"
- # check "!strcmp("NULL", NULL)" failed at t/unit-tests/t-basic.c:62
+ # check "!strcmp("NULL", NULL)" failed at t/helper/test-example-tap.c:63
# left: "NULL"
# right: NULL
- # check "${SQ}a${SQ} == ${SQ}\n${SQ}" failed at t/unit-tests/t-basic.c:63
+ # check "${SQ}a${SQ} == ${SQ}\n${SQ}" failed at t/helper/test-example-tap.c:64
# left: ${SQ}a${SQ}
# right: ${SQ}\012${SQ}
- # check "${SQ}\\\\${SQ} == ${SQ}\\${SQ}${SQ}" failed at t/unit-tests/t-basic.c:64
+ # check "${SQ}\\\\${SQ} == ${SQ}\\${SQ}${SQ}" failed at t/helper/test-example-tap.c:65
# left: ${SQ}\\\\${SQ}
# right: ${SQ}\\${SQ}${SQ}
not ok 17 - messages from failing string and char comparison
- # BUG: test has no checks at t/unit-tests/t-basic.c:91
+ # BUG: test has no checks at t/helper/test-example-tap.c:92
not ok 18 - test with no checks
ok 19 - test with no checks returns 0
1..19
EOF
- ! "$GIT_BUILD_DIR"/t/unit-tests/bin/t-basic >actual &&
+ ! test-tool example-tap >actual &&
test_cmp expect actual
'
diff --git a/t/t0095-bloom.sh b/t/t0095-bloom.sh
index b567383eb8..c8d84ab606 100755
--- a/t/t0095-bloom.sh
+++ b/t/t0095-bloom.sh
@@ -29,6 +29,14 @@ test_expect_success 'compute unseeded murmur3 hash for test string 2' '
test_cmp expect actual
'
+test_expect_success 'compute unseeded murmur3 hash for test string 3' '
+ cat >expect <<-\EOF &&
+ Murmur3 Hash with seed=0:0xa183ccfd
+ EOF
+ test-tool bloom get_murmur3_seven_highbit >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'compute bloom key for empty string' '
cat >expect <<-\EOF &&
Hashes:0x5615800c|0x5b966560|0x61174ab4|0x66983008|0x6c19155c|0x7199fab0|0x771ae004|
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index 400f6bdbca..432f029d48 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -12,7 +12,13 @@ test_expect_success 'setup helper scripts' '
IFS==
while read key value; do
echo >&2 "$whoami: $key=$value"
- eval "$key=$value"
+ if test -z "${key%%*\[\]}"
+ then
+ key=${key%%\[\]}
+ eval "$key=\"\$$key $value\""
+ else
+ eval "$key=$value"
+ fi
done
IFS=$OIFS
EOF
@@ -35,6 +41,30 @@ test_expect_success 'setup helper scripts' '
test -z "$pass" || echo password=$pass
EOF
+ write_script git-credential-verbatim-cred <<-\EOF &&
+ authtype=$1; shift
+ credential=$1; shift
+ . ./dump
+ echo capability[]=authtype
+ echo capability[]=state
+ test -z "${capability##*authtype*}" || exit 0
+ test -z "$authtype" || echo authtype=$authtype
+ test -z "$credential" || echo credential=$credential
+ test -z "${capability##*state*}" || exit 0
+ echo state[]=verbatim-cred:foo
+ EOF
+
+ write_script git-credential-verbatim-ephemeral <<-\EOF &&
+ authtype=$1; shift
+ credential=$1; shift
+ . ./dump
+ echo capability[]=authtype
+ test -z "${capability##*authtype*}" || exit 0
+ test -z "$authtype" || echo authtype=$authtype
+ test -z "$credential" || echo credential=$credential
+ echo "ephemeral=1"
+ EOF
+
write_script git-credential-verbatim-with-expiry <<-\EOF &&
user=$1; shift
pass=$1; shift
@@ -64,6 +94,67 @@ test_expect_success 'credential_fill invokes helper' '
EOF
'
+test_expect_success 'credential_fill invokes helper with credential' '
+ check fill "verbatim-cred Bearer token" <<-\EOF
+ capability[]=authtype
+ protocol=http
+ host=example.com
+ --
+ capability[]=authtype
+ authtype=Bearer
+ credential=token
+ protocol=http
+ host=example.com
+ --
+ verbatim-cred: get
+ verbatim-cred: capability[]=authtype
+ verbatim-cred: protocol=http
+ verbatim-cred: host=example.com
+ EOF
+'
+
+test_expect_success 'credential_fill invokes helper with ephemeral credential' '
+ check fill "verbatim-ephemeral Bearer token" <<-\EOF
+ capability[]=authtype
+ protocol=http
+ host=example.com
+ --
+ capability[]=authtype
+ authtype=Bearer
+ credential=token
+ ephemeral=1
+ protocol=http
+ host=example.com
+ --
+ verbatim-ephemeral: get
+ verbatim-ephemeral: capability[]=authtype
+ verbatim-ephemeral: protocol=http
+ verbatim-ephemeral: host=example.com
+ EOF
+'
+test_expect_success 'credential_fill invokes helper with credential and state' '
+ check fill "verbatim-cred Bearer token" <<-\EOF
+ capability[]=authtype
+ capability[]=state
+ protocol=http
+ host=example.com
+ --
+ capability[]=authtype
+ capability[]=state
+ authtype=Bearer
+ credential=token
+ protocol=http
+ host=example.com
+ state[]=verbatim-cred:foo
+ --
+ verbatim-cred: get
+ verbatim-cred: capability[]=authtype
+ verbatim-cred: capability[]=state
+ verbatim-cred: protocol=http
+ verbatim-cred: host=example.com
+ EOF
+'
+
test_expect_success 'credential_fill invokes multiple helpers' '
check fill useless "verbatim foo bar" <<-\EOF
protocol=http
@@ -83,6 +174,45 @@ test_expect_success 'credential_fill invokes multiple helpers' '
EOF
'
+test_expect_success 'credential_fill response does not get capabilities when helpers are incapable' '
+ check fill useless "verbatim foo bar" <<-\EOF
+ capability[]=authtype
+ capability[]=state
+ protocol=http
+ host=example.com
+ --
+ protocol=http
+ host=example.com
+ username=foo
+ password=bar
+ --
+ useless: get
+ useless: capability[]=authtype
+ useless: capability[]=state
+ useless: protocol=http
+ useless: host=example.com
+ verbatim: get
+ verbatim: capability[]=authtype
+ verbatim: capability[]=state
+ verbatim: protocol=http
+ verbatim: host=example.com
+ EOF
+'
+
+test_expect_success 'credential_fill response does not get capabilities when caller is incapable' '
+ check fill "verbatim-cred Bearer token" <<-\EOF
+ protocol=http
+ host=example.com
+ --
+ protocol=http
+ host=example.com
+ --
+ verbatim-cred: get
+ verbatim-cred: protocol=http
+ verbatim-cred: host=example.com
+ EOF
+'
+
test_expect_success 'credential_fill stops when we get a full response' '
check fill "verbatim one two" "verbatim three four" <<-\EOF
protocol=http
@@ -99,6 +229,25 @@ test_expect_success 'credential_fill stops when we get a full response' '
EOF
'
+test_expect_success 'credential_fill thinks a credential is a full response' '
+ check fill "verbatim-cred Bearer token" "verbatim three four" <<-\EOF
+ capability[]=authtype
+ protocol=http
+ host=example.com
+ --
+ capability[]=authtype
+ authtype=Bearer
+ credential=token
+ protocol=http
+ host=example.com
+ --
+ verbatim-cred: get
+ verbatim-cred: capability[]=authtype
+ verbatim-cred: protocol=http
+ verbatim-cred: host=example.com
+ EOF
+'
+
test_expect_success 'credential_fill continues through partial response' '
check fill "verbatim one \"\"" "verbatim two three" <<-\EOF
protocol=http
@@ -175,6 +324,20 @@ test_expect_success 'credential_fill passes along metadata' '
EOF
'
+test_expect_success 'credential_fill produces no credential without capability' '
+ check fill "verbatim-cred Bearer token" <<-\EOF
+ protocol=http
+ host=example.com
+ --
+ protocol=http
+ host=example.com
+ --
+ verbatim-cred: get
+ verbatim-cred: protocol=http
+ verbatim-cred: host=example.com
+ EOF
+'
+
test_expect_success 'credential_approve calls all helpers' '
check approve useless "verbatim one two" <<-\EOF
protocol=http
diff --git a/t/t0301-credential-cache.sh b/t/t0301-credential-cache.sh
index f2c146fa2a..c10e35905e 100755
--- a/t/t0301-credential-cache.sh
+++ b/t/t0301-credential-cache.sh
@@ -39,6 +39,7 @@ test_atexit 'git credential-cache exit'
helper_test cache
helper_test_password_expiry_utc cache
helper_test_oauth_refresh_token cache
+helper_test_authtype cache
test_expect_success 'socket defaults to ~/.cache/git/credential/socket' '
test_when_finished "
diff --git a/t/t0411-clone-from-partial.sh b/t/t0411-clone-from-partial.sh
new file mode 100755
index 0000000000..c98d501869
--- /dev/null
+++ b/t/t0411-clone-from-partial.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+test_description='check that local clone does not fetch from promisor remotes'
+
+. ./test-lib.sh
+
+test_expect_success 'create evil repo' '
+ git init tmp &&
+ test_commit -C tmp a &&
+ git -C tmp config uploadpack.allowfilter 1 &&
+ git clone --filter=blob:none --no-local --no-checkout tmp evil &&
+ rm -rf tmp &&
+
+ git -C evil config remote.origin.uploadpack \"\$TRASH_DIRECTORY/fake-upload-pack\" &&
+ write_script fake-upload-pack <<-\EOF &&
+ echo >&2 "fake-upload-pack running"
+ >"$TRASH_DIRECTORY/script-executed"
+ exit 1
+ EOF
+ export TRASH_DIRECTORY &&
+
+ # empty shallow file disables local clone optimization
+ >evil/.git/shallow
+'
+
+test_expect_success 'local clone must not fetch from promisor remote and execute script' '
+ rm -f script-executed &&
+ test_must_fail git clone \
+ --upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \
+ evil clone1 2>err &&
+ test_grep "detected dubious ownership" err &&
+ test_grep ! "fake-upload-pack running" err &&
+ test_path_is_missing script-executed
+'
+
+test_expect_success 'clone from file://... must not fetch from promisor remote and execute script' '
+ rm -f script-executed &&
+ test_must_fail git clone \
+ --upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \
+ "file://$(pwd)/evil" clone2 2>err &&
+ test_grep "detected dubious ownership" err &&
+ test_grep ! "fake-upload-pack running" err &&
+ test_path_is_missing script-executed
+'
+
+test_expect_success 'fetch from file://... must not fetch from promisor remote and execute script' '
+ rm -f script-executed &&
+ test_must_fail git fetch \
+ --upload-pack="GIT_TEST_ASSUME_DIFFERENT_OWNER=true git-upload-pack" \
+ "file://$(pwd)/evil" 2>err &&
+ test_grep "detected dubious ownership" err &&
+ test_grep ! "fake-upload-pack running" err &&
+ test_path_is_missing script-executed
+'
+
+test_expect_success 'pack-objects should fetch from promisor remote and execute script' '
+ rm -f script-executed &&
+ echo "HEAD" | test_must_fail git -C evil pack-objects --revs --stdout >/dev/null 2>err &&
+ test_grep "fake-upload-pack running" err &&
+ test_path_is_file script-executed
+'
+
+test_expect_success 'clone from promisor remote does not lazy-fetch by default' '
+ rm -f script-executed &&
+ test_must_fail git clone evil no-lazy 2>err &&
+ test_grep "lazy fetching disabled" err &&
+ test_path_is_missing script-executed
+'
+
+test_expect_success 'promisor lazy-fetching can be re-enabled' '
+ rm -f script-executed &&
+ test_must_fail env GIT_NO_LAZY_FETCH=0 \
+ git clone evil lazy-ok 2>err &&
+ test_grep "fake-upload-pack running" err &&
+ test_path_is_file script-executed
+'
+
+test_done
diff --git a/t/t0450/txt-help-mismatches b/t/t0450/txt-help-mismatches
index a0777acd66..28003f18c9 100644
--- a/t/t0450/txt-help-mismatches
+++ b/t/t0450/txt-help-mismatches
@@ -10,7 +10,6 @@ checkout
checkout-index
clone
column
-config
credential
credential-cache
credential-store
diff --git a/t/t0600-reffiles-backend.sh b/t/t0600-reffiles-backend.sh
index 64214340e7..a390cffc80 100755
--- a/t/t0600-reffiles-backend.sh
+++ b/t/t0600-reffiles-backend.sh
@@ -4,16 +4,12 @@ test_description='Test reffiles backend'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+GIT_TEST_DEFAULT_REF_FORMAT=files
+export GIT_TEST_DEFAULT_REF_FORMAT
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
-if ! test_have_prereq REFFILES
-then
- skip_all='skipping reffiles specific tests'
- test_done
-fi
-
test_expect_success 'setup' '
git commit --allow-empty -m Initial &&
C=$(git rev-parse HEAD) &&
diff --git a/t/t0601-reffiles-pack-refs.sh b/t/t0601-reffiles-pack-refs.sh
index 7d4ab0b91a..60a544b8ee 100755
--- a/t/t0601-reffiles-pack-refs.sh
+++ b/t/t0601-reffiles-pack-refs.sh
@@ -9,18 +9,15 @@ test_description='git pack-refs should not change the branch semantic
This test runs git pack-refs and git show-ref and checks that the branch
semantic is still the same.
'
+
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+GIT_TEST_DEFAULT_REF_FORMAT=files
+export GIT_TEST_DEFAULT_REF_FORMAT
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
-if ! test_have_prereq REFFILES
-then
- skip_all='skipping reffiles specific tests'
- test_done
-fi
-
test_expect_success 'enable reflogs' '
git config core.logallrefupdates true
'
diff --git a/t/t0610-reftable-basics.sh b/t/t0610-reftable-basics.sh
index 178791e086..cc5bbfd732 100755
--- a/t/t0610-reftable-basics.sh
+++ b/t/t0610-reftable-basics.sh
@@ -4,17 +4,14 @@
#
test_description='reftable basics'
+
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+GIT_TEST_DEFAULT_REF_FORMAT=reftable
+export GIT_TEST_DEFAULT_REF_FORMAT
. ./test-lib.sh
-if ! test_have_prereq REFTABLE
-then
- skip_all='skipping reftable tests; set GIT_TEST_DEFAULT_REF_FORMAT=reftable'
- test_done
-fi
-
INVALID_OID=$(test_oid 001)
test_expect_success 'init: creates basic reftable structures' '
@@ -81,8 +78,8 @@ test_expect_success 'init: reinitializing reftable with files backend fails' '
'
test_expect_perms () {
- local perms="$1"
- local file="$2"
+ local perms="$1" &&
+ local file="$2" &&
local actual="$(ls -l "$file")" &&
case "$actual" in
@@ -286,7 +283,7 @@ test_expect_success 'ref transaction: creating symbolic ref fails with F/D confl
git init repo &&
test_commit -C repo A &&
cat >expect <<-EOF &&
- error: unable to write symref for refs/heads: file/directory conflict
+ error: ${SQ}refs/heads/main${SQ} exists; cannot create ${SQ}refs/heads${SQ}
EOF
test_must_fail git -C repo symbolic-ref refs/heads refs/heads/foo 2>err &&
test_cmp expect err
@@ -854,6 +851,39 @@ test_expect_success 'reflog: updates via HEAD update HEAD reflog' '
)
'
+test_expect_success 'branch: copying branch with D/F conflict' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit A &&
+ git branch branch &&
+ cat >expect <<-EOF &&
+ error: ${SQ}refs/heads/branch${SQ} exists; cannot create ${SQ}refs/heads/branch/moved${SQ}
+ fatal: branch copy failed
+ EOF
+ test_must_fail git branch -c branch branch/moved 2>err &&
+ test_cmp expect err
+ )
+'
+
+test_expect_success 'branch: moving branch with D/F conflict' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit A &&
+ git branch branch &&
+ git branch conflict &&
+ cat >expect <<-EOF &&
+ error: ${SQ}refs/heads/conflict${SQ} exists; cannot create ${SQ}refs/heads/conflict/moved${SQ}
+ fatal: branch rename failed
+ EOF
+ test_must_fail git branch -m branch conflict/moved 2>err &&
+ test_cmp expect err
+ )
+'
+
test_expect_success 'worktree: adding worktree creates separate stack' '
test_when_finished "rm -rf repo worktree" &&
git init repo &&
diff --git a/t/t0612-reftable-jgit-compatibility.sh b/t/t0612-reftable-jgit-compatibility.sh
new file mode 100755
index 0000000000..d0d7e80b49
--- /dev/null
+++ b/t/t0612-reftable-jgit-compatibility.sh
@@ -0,0 +1,132 @@
+#!/bin/sh
+
+test_description='reftables are compatible with JGit'
+
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+GIT_TEST_DEFAULT_REF_FORMAT=reftable
+export GIT_TEST_DEFAULT_REF_FORMAT
+
+# JGit does not support the 'link' DIRC extension.
+GIT_TEST_SPLIT_INDEX=0
+export GIT_TEST_SPLIT_INDEX
+
+. ./test-lib.sh
+
+if ! test_have_prereq JGIT
+then
+ skip_all='skipping reftable JGit tests; JGit is not present in PATH'
+ test_done
+fi
+
+if ! test_have_prereq SHA1
+then
+ skip_all='skipping reftable JGit tests; JGit does not support SHA256 reftables'
+ test_done
+fi
+
+test_commit_jgit () {
+ touch "$1" &&
+ jgit add "$1" &&
+ jgit commit -m "$1"
+}
+
+test_same_refs () {
+ git show-ref --head >cgit.actual &&
+ jgit show-ref >jgit-tabs.actual &&
+ tr "\t" " " <jgit-tabs.actual >jgit.actual &&
+ test_cmp cgit.actual jgit.actual
+}
+
+test_same_ref () {
+ git rev-parse "$1" >cgit.actual &&
+ jgit rev-parse "$1" >jgit.actual &&
+ test_cmp cgit.actual jgit.actual
+}
+
+test_same_reflog () {
+ git reflog "$*" >cgit.actual &&
+ jgit reflog "$*" >jgit-newline.actual &&
+ sed '/^$/d' <jgit-newline.actual >jgit.actual &&
+ test_cmp cgit.actual jgit.actual
+}
+
+test_expect_success 'CGit repository can be read by JGit' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit A &&
+ test_same_refs &&
+ test_same_ref HEAD &&
+ test_same_reflog HEAD
+ )
+'
+
+test_expect_success 'JGit repository can be read by CGit' '
+ test_when_finished "rm -rf repo" &&
+ jgit init repo &&
+ (
+ cd repo &&
+
+ touch file &&
+ jgit add file &&
+ jgit commit -m "initial commit" &&
+
+ # Note that we must convert the ref storage after we have
+ # written the default branch. Otherwise JGit will end up with
+ # no HEAD at all.
+ jgit convert-ref-storage --format=reftable &&
+
+ test_same_refs &&
+ test_same_ref HEAD &&
+ # Interestingly, JGit cannot read its own reflog here. CGit can
+ # though.
+ printf "%s HEAD@{0}: commit (initial): initial commit" "$(git rev-parse --short HEAD)" >expect &&
+ git reflog HEAD >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'mixed writes from JGit and CGit' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ test_commit A &&
+ test_commit_jgit B &&
+ test_commit C &&
+ test_commit_jgit D &&
+
+ test_same_refs &&
+ test_same_ref HEAD &&
+ test_same_reflog HEAD
+ )
+'
+
+test_expect_success 'JGit can read multi-level index' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+
+ test_commit A &&
+ awk "
+ BEGIN {
+ print \"start\";
+ for (i = 0; i < 10000; i++)
+ printf \"create refs/heads/branch-%d HEAD\n\", i;
+ print \"commit\";
+ }
+ " >input &&
+ git update-ref --stdin <input &&
+
+ test_same_refs &&
+ test_same_ref refs/heads/branch-1 &&
+ test_same_ref refs/heads/branch-5738 &&
+ test_same_ref refs/heads/branch-9999
+ )
+'
+
+test_done
diff --git a/t/t0613-reftable-write-options.sh b/t/t0613-reftable-write-options.sh
new file mode 100755
index 0000000000..e2708e11d5
--- /dev/null
+++ b/t/t0613-reftable-write-options.sh
@@ -0,0 +1,286 @@
+#!/bin/sh
+
+test_description='reftable write options'
+
+GIT_TEST_DEFAULT_REF_FORMAT=reftable
+export GIT_TEST_DEFAULT_REF_FORMAT
+# Disable auto-compaction for all tests as we explicitly control repacking of
+# refs.
+GIT_TEST_REFTABLE_AUTOCOMPACTION=false
+export GIT_TEST_REFTABLE_AUTOCOMPACTION
+# Block sizes depend on the hash function, so we force SHA1 here.
+GIT_TEST_DEFAULT_HASH=sha1
+export GIT_TEST_DEFAULT_HASH
+# Block sizes also depend on the actual refs we write, so we force "master" to
+# be the default initial branch name.
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
+. ./test-lib.sh
+
+test_expect_success 'default write options' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ git pack-refs &&
+ cat >expect <<-EOF &&
+ header:
+ block_size: 4096
+ ref:
+ - length: 129
+ restarts: 2
+ log:
+ - length: 262
+ restarts: 2
+ EOF
+ test-tool dump-reftable -b .git/reftable/*.ref >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'disabled reflog writes no log blocks' '
+ test_config_global core.logAllRefUpdates false &&
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ git pack-refs &&
+ cat >expect <<-EOF &&
+ header:
+ block_size: 4096
+ ref:
+ - length: 129
+ restarts: 2
+ EOF
+ test-tool dump-reftable -b .git/reftable/*.ref >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'many refs results in multiple blocks' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ for i in $(test_seq 200)
+ do
+ printf "update refs/heads/branch-%d HEAD\n" "$i" ||
+ return 1
+ done >input &&
+ git update-ref --stdin <input &&
+ git pack-refs &&
+
+ cat >expect <<-EOF &&
+ header:
+ block_size: 4096
+ ref:
+ - length: 4049
+ restarts: 11
+ - length: 1136
+ restarts: 3
+ log:
+ - length: 4041
+ restarts: 4
+ - length: 4015
+ restarts: 3
+ - length: 4014
+ restarts: 3
+ - length: 4012
+ restarts: 3
+ - length: 3289
+ restarts: 3
+ EOF
+ test-tool dump-reftable -b .git/reftable/*.ref >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'tiny block size leads to error' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ cat >expect <<-EOF &&
+ error: unable to compact stack: entry too large
+ EOF
+ test_must_fail git -c reftable.blockSize=50 pack-refs 2>err &&
+ test_cmp expect err
+ )
+'
+
+test_expect_success 'small block size leads to multiple ref blocks' '
+ test_config_global core.logAllRefUpdates false &&
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit A &&
+ test_commit B &&
+ git -c reftable.blockSize=100 pack-refs &&
+
+ cat >expect <<-EOF &&
+ header:
+ block_size: 100
+ ref:
+ - length: 53
+ restarts: 1
+ - length: 74
+ restarts: 1
+ - length: 38
+ restarts: 1
+ EOF
+ test-tool dump-reftable -b .git/reftable/*.ref >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'small block size fails with large reflog message' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit A &&
+ perl -e "print \"a\" x 500" >logmsg &&
+ cat >expect <<-EOF &&
+ fatal: update_ref failed for ref ${SQ}refs/heads/logme${SQ}: reftable: transaction failure: entry too large
+ EOF
+ test_must_fail git -c reftable.blockSize=100 \
+ update-ref -m "$(cat logmsg)" refs/heads/logme HEAD 2>err &&
+ test_cmp expect err
+ )
+'
+
+test_expect_success 'block size exceeding maximum supported size' '
+ test_config_global core.logAllRefUpdates false &&
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit A &&
+ test_commit B &&
+ cat >expect <<-EOF &&
+ fatal: reftable block size cannot exceed 16MB
+ EOF
+ test_must_fail git -c reftable.blockSize=16777216 pack-refs 2>err &&
+ test_cmp expect err
+ )
+'
+
+test_expect_success 'restart interval at every single record' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ for i in $(test_seq 10)
+ do
+ printf "update refs/heads/branch-%d HEAD\n" "$i" ||
+ return 1
+ done >input &&
+ git update-ref --stdin <input &&
+ git -c reftable.restartInterval=1 pack-refs &&
+
+ cat >expect <<-EOF &&
+ header:
+ block_size: 4096
+ ref:
+ - length: 566
+ restarts: 13
+ log:
+ - length: 1393
+ restarts: 12
+ EOF
+ test-tool dump-reftable -b .git/reftable/*.ref >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'restart interval exceeding maximum supported interval' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ cat >expect <<-EOF &&
+ fatal: reftable block size cannot exceed 65535
+ EOF
+ test_must_fail git -c reftable.restartInterval=65536 pack-refs 2>err &&
+ test_cmp expect err
+ )
+'
+
+test_expect_success 'object index gets written by default with ref index' '
+ test_config_global core.logAllRefUpdates false &&
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ for i in $(test_seq 5)
+ do
+ printf "update refs/heads/branch-%d HEAD\n" "$i" ||
+ return 1
+ done >input &&
+ git update-ref --stdin <input &&
+ git -c reftable.blockSize=100 pack-refs &&
+
+ cat >expect <<-EOF &&
+ header:
+ block_size: 100
+ ref:
+ - length: 53
+ restarts: 1
+ - length: 95
+ restarts: 1
+ - length: 71
+ restarts: 1
+ - length: 80
+ restarts: 1
+ obj:
+ - length: 11
+ restarts: 1
+ EOF
+ test-tool dump-reftable -b .git/reftable/*.ref >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'object index can be disabled' '
+ test_config_global core.logAllRefUpdates false &&
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ for i in $(test_seq 5)
+ do
+ printf "update refs/heads/branch-%d HEAD\n" "$i" ||
+ return 1
+ done >input &&
+ git update-ref --stdin <input &&
+ git -c reftable.blockSize=100 -c reftable.indexObjects=false pack-refs &&
+
+ cat >expect <<-EOF &&
+ header:
+ block_size: 100
+ ref:
+ - length: 53
+ restarts: 1
+ - length: 95
+ restarts: 1
+ - length: 71
+ restarts: 1
+ - length: 80
+ restarts: 1
+ EOF
+ test-tool dump-reftable -b .git/reftable/*.ref >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_done
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
index 64aea38486..4c138c6ca4 100755
--- a/t/t1007-hash-object.sh
+++ b/t/t1007-hash-object.sh
@@ -260,4 +260,10 @@ test_expect_success '--literally with extra-long type' '
echo example | git hash-object -t $t --literally --stdin
'
+test_expect_success '--stdin outside of repository' '
+ nongit git hash-object --stdin <hello >actual &&
+ echo "$(test_oid hello)" >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 9b65d9eaf5..9de2d95f06 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -11,6 +11,34 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
+for mode in legacy subcommands
+do
+
+case "$mode" in
+legacy)
+ mode_prefix="--"
+ mode_get=""
+ mode_get_all="--get-all"
+ mode_get_regexp="--get-regexp"
+ mode_set=""
+ mode_replace_all="--replace-all"
+ mode_unset="--unset"
+ mode_unset_all="--unset-all"
+ ;;
+subcommands)
+ mode_prefix=""
+ mode_get="get"
+ mode_get_all="get --all"
+ mode_get_regexp="get --regexp --all --show-names"
+ mode_set="set"
+ mode_replace_all="set --all"
+ mode_unset="unset"
+ mode_unset_all="unset --all"
+ ;;
+*)
+ BUG "unknown mode $mode";;
+esac
+
test_expect_success 'setup whitespace config' '
sed -e "s/^|//" \
-e "s/[$]$//" \
@@ -112,7 +140,7 @@ cat > expect << EOF
penguin = little blue
EOF
test_expect_success 'initial' '
- git config section.penguin "little blue" &&
+ git config ${mode_set} section.penguin "little blue" &&
test_cmp expect .git/config
'
@@ -122,7 +150,7 @@ cat > expect << EOF
Movie = BadPhysics
EOF
test_expect_success 'mixed case' '
- git config Section.Movie BadPhysics &&
+ git config ${mode_set} Section.Movie BadPhysics &&
test_cmp expect .git/config
'
@@ -134,7 +162,7 @@ cat > expect << EOF
WhatEver = Second
EOF
test_expect_success 'similar section' '
- git config Sections.WhatEver Second &&
+ git config ${mode_set} Sections.WhatEver Second &&
test_cmp expect .git/config
'
@@ -147,7 +175,7 @@ cat > expect << EOF
WhatEver = Second
EOF
test_expect_success 'uppercase section' '
- git config SECTION.UPPERCASE true &&
+ git config ${mode_set} SECTION.UPPERCASE true &&
test_cmp expect .git/config
'
@@ -174,8 +202,8 @@ EOF
test_expect_success 'append comments' '
git config --replace-all --comment="Pygoscelis papua" section.penguin gentoo &&
- git config --comment="find fish" section.disposition peckish &&
- git config --comment="#abc" section.foo bar &&
+ git config ${mode_set} --comment="find fish" section.disposition peckish &&
+ git config ${mode_set} --comment="#abc" section.foo bar &&
git config --comment="and comment" section.spsp value &&
git config --comment=" # and comment" section.htsp value &&
@@ -184,7 +212,7 @@ test_expect_success 'append comments' '
'
test_expect_success 'Prohibited LF in comment' '
- test_must_fail git config --comment="a${LF}b" section.k v
+ test_must_fail git config ${mode_set} --comment="a${LF}b" section.k v
'
test_expect_success 'non-match result' 'test_cmp expect .git/config'
@@ -235,7 +263,7 @@ foo = bar
EOF
test_expect_success 'unset with cont. lines' '
- git config --unset beta.baz
+ git config ${mode_unset} beta.baz
'
cat > expect <<\EOF
@@ -262,7 +290,7 @@ EOF
cp .git/config .git/config2
test_expect_success 'multiple unset' '
- git config --unset-all beta.haha
+ git config ${mode_unset_all} beta.haha
'
cat > expect << EOF
@@ -281,14 +309,14 @@ test_expect_success 'multiple unset is correct' '
cp .git/config2 .git/config
test_expect_success '--replace-all missing value' '
- test_must_fail git config --replace-all beta.haha &&
+ test_must_fail git config ${mode_replace_all} beta.haha &&
test_cmp .git/config2 .git/config
'
rm .git/config2
test_expect_success '--replace-all' '
- git config --replace-all beta.haha gamma
+ git config ${mode_replace_all} beta.haha gamma
'
cat > expect << EOF
@@ -315,7 +343,7 @@ noIndent= sillyValue ; 'nother silly comment
[nextSection] noNewline = ouch
EOF
test_expect_success 'really mean test' '
- git config beta.haha alpha &&
+ git config ${mode_set} beta.haha alpha &&
test_cmp expect .git/config
'
@@ -330,7 +358,7 @@ noIndent= sillyValue ; 'nother silly comment
nonewline = wow
EOF
test_expect_success 'really really mean test' '
- git config nextsection.nonewline wow &&
+ git config ${mode_set} nextsection.nonewline wow &&
test_cmp expect .git/config
'
@@ -348,7 +376,7 @@ noIndent= sillyValue ; 'nother silly comment
nonewline = wow
EOF
test_expect_success 'unset' '
- git config --unset beta.haha &&
+ git config ${mode_unset} beta.haha &&
test_cmp expect .git/config
'
@@ -384,7 +412,7 @@ test_expect_success 'multi-valued get-all returns all' '
wow
wow2 for me
EOF
- git config --get-all nextsection.nonewline >actual &&
+ git config ${mode_get_all} nextsection.nonewline >actual &&
test_cmp expect actual
'
@@ -404,11 +432,11 @@ test_expect_success 'multivar replace' '
'
test_expect_success 'ambiguous unset' '
- test_must_fail git config --unset nextsection.nonewline
+ test_must_fail git config ${mode_unset} nextsection.nonewline
'
test_expect_success 'invalid unset' '
- test_must_fail git config --unset somesection.nonewline
+ test_must_fail git config ${mode_unset} somesection.nonewline
'
cat > expect << EOF
@@ -422,7 +450,12 @@ noIndent= sillyValue ; 'nother silly comment
EOF
test_expect_success 'multivar unset' '
- git config --unset nextsection.nonewline "wow3$" &&
+ case "$mode" in
+ legacy)
+ git config --unset nextsection.nonewline "wow3$";;
+ subcommands)
+ git config unset --value="wow3$" nextsection.nonewline;;
+ esac &&
test_cmp expect .git/config
'
@@ -460,11 +493,11 @@ version.1.2.3eX.alpha=beta
EOF
test_expect_success 'working --list' '
- git config --list > output &&
+ git config ${mode_prefix}list > output &&
test_cmp expect output
'
test_expect_success '--list without repo produces empty output' '
- git --git-dir=nonexistent config --list >output &&
+ git --git-dir=nonexistent config ${mode_prefix}list >output &&
test_must_be_empty output
'
@@ -476,7 +509,7 @@ version.1.2.3eX.alpha
EOF
test_expect_success '--name-only --list' '
- git config --name-only --list >output &&
+ git config ${mode_prefix}list --name-only >output &&
test_cmp expect output
'
@@ -486,7 +519,7 @@ nextsection.nonewline wow2 for me
EOF
test_expect_success '--get-regexp' '
- git config --get-regexp in >output &&
+ git config ${mode_get_regexp} in >output &&
test_cmp expect output
'
@@ -496,7 +529,7 @@ nextsection.nonewline
EOF
test_expect_success '--name-only --get-regexp' '
- git config --name-only --get-regexp in >output &&
+ git config ${mode_get_regexp} --name-only in >output &&
test_cmp expect output
'
@@ -507,7 +540,7 @@ EOF
test_expect_success '--add' '
git config --add nextsection.nonewline "wow4 for you" &&
- git config --get-all nextsection.nonewline > output &&
+ git config ${mode_get_all} nextsection.nonewline > output &&
test_cmp expect output
'
@@ -529,21 +562,21 @@ test_expect_success 'get variable with empty value' '
echo novalue.variable > expect
test_expect_success 'get-regexp variable with no value' '
- git config --get-regexp novalue > output &&
+ git config ${mode_get_regexp} novalue > output &&
test_cmp expect output
'
echo 'novalue.variable true' > expect
test_expect_success 'get-regexp --bool variable with no value' '
- git config --bool --get-regexp novalue > output &&
+ git config ${mode_get_regexp} --bool novalue > output &&
test_cmp expect output
'
echo 'emptyvalue.variable ' > expect
test_expect_success 'get-regexp variable with empty value' '
- git config --get-regexp emptyvalue > output &&
+ git config ${mode_get_regexp} emptyvalue > output &&
test_cmp expect output
'
@@ -563,7 +596,8 @@ test_expect_success 'get bool variable with empty value' '
test_expect_success 'no arguments, but no crash' '
test_must_fail git config >output 2>&1 &&
- test_grep usage output
+ echo "error: no action specified" >expect &&
+ test_cmp expect output
'
cat > .git/config << EOF
@@ -614,17 +648,17 @@ ein.bahn=strasse
EOF
test_expect_success 'alternative GIT_CONFIG' '
- GIT_CONFIG=other-config git config --list >output &&
+ GIT_CONFIG=other-config git config ${mode_prefix}list >output &&
test_cmp expect output
'
test_expect_success 'alternative GIT_CONFIG (--file)' '
- git config --file other-config --list >output &&
+ git config ${mode_prefix}list --file other-config >output &&
test_cmp expect output
'
test_expect_success 'alternative GIT_CONFIG (--file=-)' '
- git config --file - --list <other-config >output &&
+ git config ${mode_prefix}list --file - <other-config >output &&
test_cmp expect output
'
@@ -633,10 +667,11 @@ test_expect_success 'setting a value in stdin is an error' '
'
test_expect_success 'editing stdin is an error' '
- test_must_fail git config --file - --edit
+ test_must_fail git config ${mode_prefix}edit --file -
'
test_expect_success 'refer config from subdirectory' '
+ test_when_finished "rm -r x" &&
mkdir x &&
test_cmp_config -C x strasse --file=../other-config --get ein.bahn
'
@@ -665,7 +700,7 @@ weird
EOF
test_expect_success 'rename section' '
- git config --rename-section branch.eins branch.zwei
+ git config ${mode_prefix}rename-section branch.eins branch.zwei
'
cat > expect << EOF
@@ -684,7 +719,7 @@ test_expect_success 'rename succeeded' '
'
test_expect_success 'rename non-existing section' '
- test_must_fail git config --rename-section \
+ test_must_fail git config ${mode_prefix}rename-section \
branch."world domination" branch.drei
'
@@ -693,7 +728,7 @@ test_expect_success 'rename succeeded' '
'
test_expect_success 'rename another section' '
- git config --rename-section branch."1 234 blabl/a" branch.drei
+ git config ${mode_prefix}rename-section branch."1 234 blabl/a" branch.drei
'
cat > expect << EOF
@@ -716,7 +751,7 @@ cat >> .git/config << EOF
EOF
test_expect_success 'rename a section with a var on the same line' '
- git config --rename-section branch.vier branch.zwei
+ git config ${mode_prefix}rename-section branch.vier branch.zwei
'
cat > expect << EOF
@@ -737,11 +772,11 @@ test_expect_success 'rename succeeded' '
'
test_expect_success 'renaming empty section name is rejected' '
- test_must_fail git config --rename-section branch.zwei ""
+ test_must_fail git config ${mode_prefix}rename-section branch.zwei ""
'
test_expect_success 'renaming to bogus section is rejected' '
- test_must_fail git config --rename-section branch.zwei "bogus name"
+ test_must_fail git config ${mode_prefix}rename-section branch.zwei "bogus name"
'
test_expect_success 'renaming a section with a long line' '
@@ -750,7 +785,7 @@ test_expect_success 'renaming a section with a long line' '
printf " c = d %1024s [a] e = f\\n" " " &&
printf "[a] g = h\\n"
} >y &&
- git config -f y --rename-section a xyz &&
+ git config ${mode_prefix}rename-section -f y a xyz &&
test_must_fail git config -f y b.e
'
@@ -760,7 +795,7 @@ test_expect_success 'renaming an embedded section with a long line' '
printf " c = d %1024s [a] [foo] e = f\\n" " " &&
printf "[a] g = h\\n"
} >y &&
- git config -f y --rename-section a xyz &&
+ git config ${mode_prefix}rename-section -f y a xyz &&
test_must_fail git config -f y foo.e
'
@@ -770,7 +805,7 @@ test_expect_success 'renaming a section with an overly-long line' '
printf " c = d %525000s e" " " &&
printf "[a] g = h\\n"
} >y &&
- test_must_fail git config -f y --rename-section a xyz 2>err &&
+ test_must_fail git config ${mode_prefix}rename-section -f y a xyz 2>err &&
grep "refusing to work with overly long line in .y. on line 2" err
'
@@ -779,7 +814,7 @@ cat >> .git/config << EOF
EOF
test_expect_success 'remove section' '
- git config --remove-section branch.zwei
+ git config ${mode_prefix}remove-section branch.zwei
'
cat > expect << EOF
@@ -803,16 +838,16 @@ EOF
test_expect_success 'section ending' '
rm -f .git/config &&
- git config gitcvs.enabled true &&
- git config gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite &&
- git config gitcvs.dbname %Ggitcvs2.%a.%m.sqlite &&
+ git config ${mode_set} gitcvs.enabled true &&
+ git config ${mode_set} gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite &&
+ git config ${mode_set} gitcvs.dbname %Ggitcvs2.%a.%m.sqlite &&
test_cmp expect .git/config
'
test_expect_success numbers '
- git config kilo.gram 1k &&
- git config mega.ton 1m &&
+ git config ${mode_set} kilo.gram 1k &&
+ git config ${mode_set} mega.ton 1m &&
echo 1024 >expect &&
echo 1048576 >>expect &&
git config --int --get kilo.gram >actual &&
@@ -821,20 +856,20 @@ test_expect_success numbers '
'
test_expect_success '--int is at least 64 bits' '
- git config giga.watts 121g &&
+ git config ${mode_set} giga.watts 121g &&
echo >expect &&
test_cmp_config 129922760704 --int --get giga.watts
'
test_expect_success 'invalid unit' '
- git config aninvalid.unit "1auto" &&
+ git config ${mode_set} aninvalid.unit "1auto" &&
test_cmp_config 1auto aninvalid.unit &&
test_must_fail git config --int --get aninvalid.unit 2>actual &&
test_grep "bad numeric config value .1auto. for .aninvalid.unit. in file .git/config: invalid unit" actual
'
test_expect_success 'invalid unit boolean' '
- git config commit.gpgsign "1true" &&
+ git config ${mode_set} commit.gpgsign "1true" &&
test_cmp_config 1true commit.gpgsign &&
test_must_fail git config --bool --get commit.gpgsign 2>actual &&
test_grep "bad boolean config value .1true. for .commit.gpgsign." actual
@@ -847,7 +882,7 @@ test_expect_success 'line number is reported correctly' '
'
test_expect_success 'invalid stdin config' '
- echo "[broken" | test_must_fail git config --list --file - >output 2>&1 &&
+ echo "[broken" | test_must_fail git config ${mode_prefix}list --file - >output 2>&1 &&
test_grep "bad config line 1 in standard input" output
'
@@ -864,14 +899,14 @@ EOF
test_expect_success bool '
- git config bool.true1 01 &&
- git config bool.true2 -1 &&
- git config bool.true3 YeS &&
- git config bool.true4 true &&
- git config bool.false1 000 &&
- git config bool.false2 "" &&
- git config bool.false3 nO &&
- git config bool.false4 FALSE &&
+ git config ${mode_set} bool.true1 01 &&
+ git config ${mode_set} bool.true2 -1 &&
+ git config ${mode_set} bool.true3 YeS &&
+ git config ${mode_set} bool.true4 true &&
+ git config ${mode_set} bool.false1 000 &&
+ git config ${mode_set} bool.false2 "" &&
+ git config ${mode_set} bool.false3 nO &&
+ git config ${mode_set} bool.false4 FALSE &&
rm -f result &&
for i in 1 2 3 4
do
@@ -882,7 +917,7 @@ test_expect_success bool '
test_expect_success 'invalid bool (--get)' '
- git config bool.nobool foobar &&
+ git config ${mode_set} bool.nobool foobar &&
test_must_fail git config --bool --get bool.nobool'
test_expect_success 'invalid bool (set)' '
@@ -1071,7 +1106,7 @@ test_expect_success 'get --expiry-date' '
test_expect_success 'get --type=color' '
rm .git/config &&
- git config foo.color "red" &&
+ git config ${mode_set} foo.color "red" &&
git config --get --type=color foo.color >actual.raw &&
test_decode_color <actual.raw >actual &&
echo "<RED>" >expect &&
@@ -1108,18 +1143,18 @@ cat > expect << EOF
EOF
test_expect_success 'quoting' '
rm -f .git/config &&
- git config quote.leading " test" &&
- git config quote.ending "test " &&
- git config quote.semicolon "test;test" &&
- git config quote.hash "test#test" &&
+ git config ${mode_set} quote.leading " test" &&
+ git config ${mode_set} quote.ending "test " &&
+ git config ${mode_set} quote.semicolon "test;test" &&
+ git config ${mode_set} quote.hash "test#test" &&
test_cmp expect .git/config
'
test_expect_success 'key with newline' '
- test_must_fail git config "key.with
+ test_must_fail git config ${mode_get} "key.with
newline" 123'
-test_expect_success 'value with newline' 'git config key.sub value.with\\\
+test_expect_success 'value with newline' 'git config ${mode_set} key.sub value.with\\\
newline'
cat > .git/config <<\EOF
@@ -1139,7 +1174,7 @@ section.quotecont=cont;inued
EOF
test_expect_success 'value continued on next line' '
- git config --list > result &&
+ git config ${mode_prefix}list > result &&
test_cmp expect result
'
@@ -1163,14 +1198,14 @@ Qsection.sub=section.val4
Qsection.sub=section.val5Q
EOF
test_expect_success '--null --list' '
- git config --null --list >result.raw &&
+ git config ${mode_prefix}list --null >result.raw &&
nul_to_q <result.raw >result &&
echo >>result &&
test_cmp expect result
'
test_expect_success '--null --get-regexp' '
- git config --null --get-regexp "val[0-9]" >result.raw &&
+ git config ${mode_get_regexp} --null "val[0-9]" >result.raw &&
nul_to_q <result.raw >result &&
echo >>result &&
test_cmp expect result
@@ -1178,26 +1213,27 @@ test_expect_success '--null --get-regexp' '
test_expect_success 'inner whitespace kept verbatim, spaces only' '
echo "foo bar" >expect &&
- git config section.val "foo bar" &&
- git config --get section.val >actual &&
+ git config ${mode_set} section.val "foo bar" &&
+ git config ${mode_get} section.val >actual &&
test_cmp expect actual
'
test_expect_success 'inner whitespace kept verbatim, horizontal tabs only' '
echo "fooQQbar" | q_to_tab >expect &&
- git config section.val "$(cat expect)" &&
- git config --get section.val >actual &&
+ git config ${mode_set} section.val "$(cat expect)" &&
+ git config ${mode_get} section.val >actual &&
test_cmp expect actual
'
test_expect_success 'inner whitespace kept verbatim, horizontal tabs and spaces' '
echo "foo Q bar" | q_to_tab >expect &&
- git config section.val "$(cat expect)" &&
- git config --get section.val >actual &&
+ git config ${mode_set} section.val "$(cat expect)" &&
+ git config ${mode_get} section.val >actual &&
test_cmp expect actual
'
test_expect_success SYMLINKS 'symlinked configuration' '
+ test_when_finished "rm myconfig" &&
ln -s notyet myconfig &&
git config --file=myconfig test.frotz nitfol &&
test -h myconfig &&
@@ -1218,10 +1254,11 @@ test_expect_success SYMLINKS 'symlinked configuration' '
'
test_expect_success SYMLINKS 'symlink to nonexistent configuration' '
+ test_when_finished "rm linktonada linktolinktonada" &&
ln -s doesnotexist linktonada &&
ln -s linktonada linktolinktonada &&
- test_must_fail git config --file=linktonada --list &&
- test_must_fail git config --file=linktolinktonada --list
+ test_must_fail git config ${mode_prefix}list --file=linktonada &&
+ test_must_fail git config ${mode_prefix}list --file=linktolinktonada
'
test_expect_success 'check split_cmdline return' '
@@ -1229,12 +1266,12 @@ test_expect_success 'check split_cmdline return' '
git init repo &&
(
cd repo &&
- git config alias.split-cmdline-fix "echo \"" &&
+ git config ${mode_set} alias.split-cmdline-fix "echo \"" &&
test_must_fail git split-cmdline-fix &&
echo foo >foo &&
git add foo &&
git commit -m "initial commit" &&
- git config branch.main.mergeoptions "echo \"" &&
+ git config ${mode_set} branch.main.mergeoptions "echo \"" &&
test_must_fail git merge main
)
'
@@ -1266,18 +1303,18 @@ test_expect_success 'git -c can represent empty string' '
'
test_expect_success 'key sanity-checking' '
- test_must_fail git config foo=bar &&
- test_must_fail git config foo=.bar &&
- test_must_fail git config foo.ba=r &&
- test_must_fail git config foo.1bar &&
- test_must_fail git config foo."ba
+ test_must_fail git config ${mode_get} foo=bar &&
+ test_must_fail git config ${mode_get} foo=.bar &&
+ test_must_fail git config ${mode_get} foo.ba=r &&
+ test_must_fail git config ${mode_get} foo.1bar &&
+ test_must_fail git config ${mode_get} foo."ba
z".bar &&
- test_must_fail git config . false &&
- test_must_fail git config .foo false &&
- test_must_fail git config foo. false &&
- test_must_fail git config .foo. false &&
- git config foo.bar true &&
- git config foo."ba =z".bar false
+ test_must_fail git config ${mode_set} . false &&
+ test_must_fail git config ${mode_set} .foo false &&
+ test_must_fail git config ${mode_set} foo. false &&
+ test_must_fail git config ${mode_set} .foo. false &&
+ git config ${mode_set} foo.bar true &&
+ git config ${mode_set} foo."ba =z".bar false
'
test_expect_success 'git -c works with aliases of builtins' '
@@ -1319,7 +1356,7 @@ test_expect_success 'git -c complains about empty key and value' '
'
test_expect_success 'multiple git -c appends config' '
- test_config alias.x "!git -c x.two=2 config --get-regexp ^x\.*" &&
+ test_config alias.x "!git -c x.two=2 config ${mode_get_regexp} ^x\.*" &&
cat >expect <<-\EOF &&
x.one 1
x.two 2
@@ -1478,14 +1515,14 @@ do
done
test_expect_success 'git -c is not confused by empty environment' '
- GIT_CONFIG_PARAMETERS="" git -c x.one=1 config --list
+ GIT_CONFIG_PARAMETERS="" git -c x.one=1 config ${mode_prefix}list
'
test_expect_success 'GIT_CONFIG_PARAMETERS handles old-style entries' '
v="${SQ}key.one=foo${SQ}" &&
v="$v ${SQ}key.two=bar${SQ}" &&
v="$v ${SQ}key.ambiguous=section.whatever=value${SQ}" &&
- GIT_CONFIG_PARAMETERS=$v git config --get-regexp "key.*" >actual &&
+ GIT_CONFIG_PARAMETERS=$v git config ${mode_get_regexp} "key.*" >actual &&
cat >expect <<-EOF &&
key.one foo
key.two bar
@@ -1498,7 +1535,7 @@ test_expect_success 'GIT_CONFIG_PARAMETERS handles new-style entries' '
v="${SQ}key.one${SQ}=${SQ}foo${SQ}" &&
v="$v ${SQ}key.two${SQ}=${SQ}bar${SQ}" &&
v="$v ${SQ}key.ambiguous=section.whatever${SQ}=${SQ}value${SQ}" &&
- GIT_CONFIG_PARAMETERS=$v git config --get-regexp "key.*" >actual &&
+ GIT_CONFIG_PARAMETERS=$v git config ${mode_get_regexp} "key.*" >actual &&
cat >expect <<-EOF &&
key.one foo
key.two bar
@@ -1512,7 +1549,7 @@ test_expect_success 'old and new-style entries can mix' '
v="$v ${SQ}key.newone${SQ}=${SQ}newfoo${SQ}" &&
v="$v ${SQ}key.oldtwo=oldbar${SQ}" &&
v="$v ${SQ}key.newtwo${SQ}=${SQ}newbar${SQ}" &&
- GIT_CONFIG_PARAMETERS=$v git config --get-regexp "key.*" >actual &&
+ GIT_CONFIG_PARAMETERS=$v git config ${mode_get_regexp} "key.*" >actual &&
cat >expect <<-EOF &&
key.oldone oldfoo
key.newone newfoo
@@ -1525,7 +1562,7 @@ test_expect_success 'old and new-style entries can mix' '
test_expect_success 'old and new bools with ambiguous subsection' '
v="${SQ}key.with=equals.oldbool${SQ}" &&
v="$v ${SQ}key.with=equals.newbool${SQ}=" &&
- GIT_CONFIG_PARAMETERS=$v git config --get-regexp "key.*" >actual &&
+ GIT_CONFIG_PARAMETERS=$v git config ${mode_get_regexp} "key.*" >actual &&
cat >expect <<-EOF &&
key.with equals.oldbool
key.with=equals.newbool
@@ -1539,7 +1576,7 @@ test_expect_success 'detect bogus GIT_CONFIG_PARAMETERS' '
env.two two
EOF
GIT_CONFIG_PARAMETERS="${SQ}env.one=one${SQ} ${SQ}env.two=two${SQ}" \
- git config --get-regexp "env.*" >actual &&
+ git config ${mode_get_regexp} "env.*" >actual &&
test_cmp expect actual &&
cat >expect <<-EOF &&
@@ -1547,12 +1584,12 @@ test_expect_success 'detect bogus GIT_CONFIG_PARAMETERS' '
env.two two
EOF
GIT_CONFIG_PARAMETERS="${SQ}env.one=one${SQ}\\$SQ$SQ$SQ ${SQ}env.two=two${SQ}" \
- git config --get-regexp "env.*" >actual &&
+ git config ${mode_get_regexp} "env.*" >actual &&
test_cmp expect actual &&
test_must_fail env \
GIT_CONFIG_PARAMETERS="${SQ}env.one=one${SQ}\\$SQ ${SQ}env.two=two${SQ}" \
- git config --get-regexp "env.*"
+ git config ${mode_get_regexp} "env.*"
'
test_expect_success 'git --config-env=key=envvar support' '
@@ -1600,7 +1637,7 @@ test_expect_success 'git -c and --config-env work together' '
ENVVAR=env-value git \
-c bar.cmd=cmd-value \
--config-env=bar.env=ENVVAR \
- config --get-regexp "^bar.*" >actual &&
+ config ${mode_get_regexp} "^bar.*" >actual &&
test_cmp expect actual
'
@@ -1628,7 +1665,7 @@ test_expect_success 'git config handles environment config pairs' '
GIT_CONFIG_COUNT=2 \
GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="foo" \
GIT_CONFIG_KEY_1="pair.two" GIT_CONFIG_VALUE_1="bar" \
- git config --get-regexp "pair.*" >actual &&
+ git config ${mode_get_regexp} "pair.*" >actual &&
cat >expect <<-EOF &&
pair.one foo
pair.two bar
@@ -1638,7 +1675,7 @@ test_expect_success 'git config handles environment config pairs' '
test_expect_success 'git config ignores pairs without count' '
test_must_fail env GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
- git config pair.one 2>error &&
+ git config ${mode_get} pair.one 2>error &&
test_must_be_empty error
'
@@ -1646,7 +1683,7 @@ test_expect_success 'git config ignores pairs exceeding count' '
GIT_CONFIG_COUNT=1 \
GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
GIT_CONFIG_KEY_1="pair.two" GIT_CONFIG_VALUE_1="value" \
- git config --get-regexp "pair.*" >actual 2>error &&
+ git config ${mode_get_regexp} "pair.*" >actual 2>error &&
cat >expect <<-EOF &&
pair.one value
EOF
@@ -1657,43 +1694,43 @@ test_expect_success 'git config ignores pairs exceeding count' '
test_expect_success 'git config ignores pairs with zero count' '
test_must_fail env \
GIT_CONFIG_COUNT=0 GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
- git config pair.one 2>error &&
+ git config ${mode_get} pair.one 2>error &&
test_must_be_empty error
'
test_expect_success 'git config ignores pairs with empty count' '
test_must_fail env \
GIT_CONFIG_COUNT= GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \
- git config pair.one 2>error &&
+ git config ${mode_get} pair.one 2>error &&
test_must_be_empty error
'
test_expect_success 'git config fails with invalid count' '
- test_must_fail env GIT_CONFIG_COUNT=10a git config --list 2>error &&
+ test_must_fail env GIT_CONFIG_COUNT=10a git config ${mode_prefix}list 2>error &&
test_grep "bogus count" error &&
- test_must_fail env GIT_CONFIG_COUNT=9999999999999999 git config --list 2>error &&
+ test_must_fail env GIT_CONFIG_COUNT=9999999999999999 git config ${mode_prefix}list 2>error &&
test_grep "too many entries" error
'
test_expect_success 'git config fails with missing config key' '
test_must_fail env GIT_CONFIG_COUNT=1 GIT_CONFIG_VALUE_0="value" \
- git config --list 2>error &&
+ git config ${mode_prefix}list 2>error &&
test_grep "missing config key" error
'
test_expect_success 'git config fails with missing config value' '
test_must_fail env GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0="pair.one" \
- git config --list 2>error &&
+ git config ${mode_prefix}list 2>error &&
test_grep "missing config value" error
'
test_expect_success 'git config fails with invalid config pair key' '
test_must_fail env GIT_CONFIG_COUNT=1 \
GIT_CONFIG_KEY_0= GIT_CONFIG_VALUE_0=value \
- git config --list &&
+ git config ${mode_prefix}list &&
test_must_fail env GIT_CONFIG_COUNT=1 \
GIT_CONFIG_KEY_0=missing-section GIT_CONFIG_VALUE_0=value \
- git config --list
+ git config ${mode_prefix}list
'
test_expect_success 'environment overrides config file' '
@@ -1703,7 +1740,7 @@ test_expect_success 'environment overrides config file' '
one = value
EOF
GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=pair.one GIT_CONFIG_VALUE_0=override \
- git config pair.one >actual &&
+ git config ${mode_get} pair.one >actual &&
cat >expect <<-EOF &&
override
EOF
@@ -1713,7 +1750,7 @@ test_expect_success 'environment overrides config file' '
test_expect_success 'GIT_CONFIG_PARAMETERS overrides environment config' '
GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=pair.one GIT_CONFIG_VALUE_0=value \
GIT_CONFIG_PARAMETERS="${SQ}pair.one=override${SQ}" \
- git config pair.one >actual &&
+ git config ${mode_get} pair.one >actual &&
cat >expect <<-EOF &&
override
EOF
@@ -1732,8 +1769,8 @@ test_expect_success 'command line overrides environment config' '
test_expect_success 'git config --edit works' '
git config -f tmp test.value no &&
echo test.value=yes >expect &&
- GIT_EDITOR="echo [test]value=yes >" git config -f tmp --edit &&
- git config -f tmp --list >actual &&
+ GIT_EDITOR="echo [test]value=yes >" git config ${mode_prefix}edit -f tmp &&
+ git config ${mode_prefix}list -f tmp >actual &&
test_cmp expect actual
'
@@ -1741,8 +1778,8 @@ test_expect_success 'git config --edit respects core.editor' '
git config -f tmp test.value no &&
echo test.value=yes >expect &&
test_config core.editor "echo [test]value=yes >" &&
- git config -f tmp --edit &&
- git config -f tmp --list >actual &&
+ git config ${mode_prefix}edit -f tmp &&
+ git config ${mode_prefix}list -f tmp >actual &&
test_cmp expect actual
'
@@ -1788,20 +1825,28 @@ test_expect_success 'urlmatch' '
test_expect_code 1 git config --bool --get-urlmatch doesnt.exist https://good.example.com >actual &&
test_must_be_empty actual &&
+ test_expect_code 1 git config get --url=https://good.example.com --bool doesnt.exist >actual &&
+ test_must_be_empty actual &&
echo true >expect &&
git config --bool --get-urlmatch http.SSLverify https://good.example.com >actual &&
test_cmp expect actual &&
+ git config get --bool --url=https://good.example.com http.SSLverify >actual &&
+ test_cmp expect actual &&
echo false >expect &&
git config --bool --get-urlmatch http.sslverify https://weak.example.com >actual &&
test_cmp expect actual &&
+ git config get --bool --url=https://weak.example.com http.sslverify >actual &&
+ test_cmp expect actual &&
{
echo http.cookiefile /tmp/cookie.txt &&
echo http.sslverify false
} >expect &&
git config --get-urlmatch HTTP https://weak.example.com >actual &&
+ test_cmp expect actual &&
+ git config get --url=https://weak.example.com HTTP >actual &&
test_cmp expect actual
'
@@ -1817,6 +1862,8 @@ test_expect_success 'urlmatch with --show-scope' '
local http.sslverify false
EOF
git config --get-urlmatch --show-scope HTTP https://weak.example.com >actual &&
+ test_cmp expect actual &&
+ git config get --url=https://weak.example.com --show-scope HTTP >actual &&
test_cmp expect actual
'
@@ -1849,45 +1896,67 @@ test_expect_success 'urlmatch favors more specific URLs' '
echo http.cookiefile /tmp/root.txt >expect &&
git config --get-urlmatch HTTP https://example.com >actual &&
test_cmp expect actual &&
+ git config get --url=https://example.com HTTP >actual &&
+ test_cmp expect actual &&
echo http.cookiefile /tmp/subdirectory.txt >expect &&
git config --get-urlmatch HTTP https://example.com/subdirectory >actual &&
test_cmp expect actual &&
+ git config get --url=https://example.com/subdirectory HTTP >actual &&
+ test_cmp expect actual &&
echo http.cookiefile /tmp/subdirectory.txt >expect &&
git config --get-urlmatch HTTP https://example.com/subdirectory/nested >actual &&
test_cmp expect actual &&
+ git config get --url=https://example.com/subdirectory/nested HTTP >actual &&
+ test_cmp expect actual &&
echo http.cookiefile /tmp/user.txt >expect &&
git config --get-urlmatch HTTP https://user@example.com/ >actual &&
test_cmp expect actual &&
+ git config get --url=https://user@example.com/ HTTP >actual &&
+ test_cmp expect actual &&
echo http.cookiefile /tmp/subdirectory.txt >expect &&
git config --get-urlmatch HTTP https://averylonguser@example.com/subdirectory >actual &&
test_cmp expect actual &&
+ git config get --url=https://averylonguser@example.com/subdirectory HTTP >actual &&
+ test_cmp expect actual &&
echo http.cookiefile /tmp/preceding.txt >expect &&
git config --get-urlmatch HTTP https://preceding.example.com >actual &&
test_cmp expect actual &&
+ git config get --url=https://preceding.example.com HTTP >actual &&
+ test_cmp expect actual &&
echo http.cookiefile /tmp/wildcard.txt >expect &&
git config --get-urlmatch HTTP https://wildcard.example.com >actual &&
test_cmp expect actual &&
+ git config get --url=https://wildcard.example.com HTTP >actual &&
+ test_cmp expect actual &&
echo http.cookiefile /tmp/sub.txt >expect &&
git config --get-urlmatch HTTP https://sub.example.com/wildcardwithsubdomain >actual &&
test_cmp expect actual &&
+ git config get --url=https://sub.example.com/wildcardwithsubdomain HTTP >actual &&
+ test_cmp expect actual &&
echo http.cookiefile /tmp/trailing.txt >expect &&
git config --get-urlmatch HTTP https://trailing.example.com >actual &&
test_cmp expect actual &&
+ git config get --url=https://trailing.example.com HTTP >actual &&
+ test_cmp expect actual &&
echo http.cookiefile /tmp/sub.txt >expect &&
git config --get-urlmatch HTTP https://user@sub.example.com >actual &&
test_cmp expect actual &&
+ git config get --url=https://user@sub.example.com HTTP >actual &&
+ test_cmp expect actual &&
echo http.cookiefile /tmp/multiwildcard.txt >expect &&
git config --get-urlmatch HTTP https://wildcard.example.org >actual &&
+ test_cmp expect actual &&
+ git config get --url=https://wildcard.example.org HTTP >actual &&
test_cmp expect actual
'
@@ -1954,7 +2023,7 @@ test_expect_success '--unset last key removes section (except if commented)' '
# please be careful when you update the above variable
EOF
- git config --unset section.key &&
+ git config ${mode_unset} section.key &&
test_cmp expect .git/config &&
cat >.git/config <<-\EOF &&
@@ -1967,7 +2036,7 @@ test_expect_success '--unset last key removes section (except if commented)' '
[next-section]
EOF
- git config --unset section.key &&
+ git config ${mode_unset} section.key &&
test_cmp expect .git/config &&
q_to_tab >.git/config <<-\EOF &&
@@ -1977,7 +2046,7 @@ test_expect_success '--unset last key removes section (except if commented)' '
[two]
key = true
EOF
- git config --unset two.key &&
+ git config ${mode_unset} two.key &&
! grep two .git/config &&
q_to_tab >.git/config <<-\EOF &&
@@ -1987,7 +2056,7 @@ test_expect_success '--unset last key removes section (except if commented)' '
[one]
key = true
EOF
- git config --unset-all one.key &&
+ git config ${mode_unset_all} one.key &&
test_line_count = 0 .git/config &&
q_to_tab >.git/config <<-\EOF &&
@@ -1997,7 +2066,7 @@ test_expect_success '--unset last key removes section (except if commented)' '
[two]
Qkey = true
EOF
- git config --unset two.key &&
+ git config ${mode_unset} two.key &&
grep two .git/config &&
q_to_tab >.git/config <<-\EOF &&
@@ -2009,8 +2078,8 @@ test_expect_success '--unset last key removes section (except if commented)' '
[TWO "subsection"]
[one]
EOF
- git config --unset two.subsection.key &&
- test "not [two subsection]" = "$(git config one.key)" &&
+ git config ${mode_unset} two.subsection.key &&
+ test "not [two subsection]" = "$(git config ${mode_get} one.key)" &&
test_line_count = 3 .git/config
'
@@ -2021,7 +2090,7 @@ test_expect_success '--unset-all removes section if empty & uncommented' '
key = value2
EOF
- git config --unset-all section.key &&
+ git config ${mode_unset_all} section.key &&
test_line_count = 0 .git/config
'
@@ -2044,7 +2113,7 @@ test_expect_success POSIXPERM,PERL 'preserves existing permissions' '
git config imap.pass Hunter2 &&
perl -e \
"die q(badset) if ((stat(q(.git/config)))[2] & 07777) != 0600" &&
- git config --rename-section imap pop &&
+ git config ${mode_prefix}rename-section imap pop &&
perl -e \
"die q(badrename) if ((stat(q(.git/config)))[2] & 07777) != 0600"
'
@@ -2093,7 +2162,7 @@ test_expect_success '--show-origin with --list' '
command line: user.cmdline=true
EOF
GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=user.environ GIT_CONFIG_VALUE_0=true\
- git -c user.cmdline=true config --list --show-origin >output &&
+ git -c user.cmdline=true config ${mode_prefix}list --show-origin >output &&
test_cmp expect output
'
@@ -2110,7 +2179,7 @@ test_expect_success '--show-origin with --list --null' '
includeQcommand line:Quser.cmdline
trueQ
EOF
- git -c user.cmdline=true config --null --list --show-origin >output.raw &&
+ git -c user.cmdline=true config ${mode_prefix}list --null --show-origin >output.raw &&
nul_to_q <output.raw >output &&
# The here-doc above adds a newline that the --null output would not
# include. Add it here to make the two comparable.
@@ -2124,7 +2193,7 @@ test_expect_success '--show-origin with single file' '
file:.git/config user.override=local
file:.git/config include.path=../include/relative.include
EOF
- git config --local --list --show-origin >output &&
+ git config ${mode_prefix}list --local --show-origin >output &&
test_cmp expect output
'
@@ -2133,7 +2202,7 @@ test_expect_success '--show-origin with --get-regexp' '
file:$HOME/.gitconfig user.global true
file:.git/config user.local true
EOF
- git config --show-origin --get-regexp "user\.[g|l].*" >output &&
+ git config ${mode_get_regexp} --show-origin "user\.[g|l].*" >output &&
test_cmp expect output
'
@@ -2141,7 +2210,7 @@ test_expect_success '--show-origin getting a single key' '
cat >expect <<-\EOF &&
file:.git/config local
EOF
- git config --show-origin user.override >output &&
+ git config ${mode_get} --show-origin user.override >output &&
test_cmp expect output
'
@@ -2162,7 +2231,7 @@ test_expect_success !MINGW '--show-origin escape special file name characters' '
cat >expect <<-\EOF &&
file:"file\" (dq) and spaces.conf" user.custom=true
EOF
- git config --file "$WEIRDLY_NAMED_FILE" --show-origin --list >output &&
+ git config ${mode_prefix}list --file "$WEIRDLY_NAMED_FILE" --show-origin >output &&
test_cmp expect output
'
@@ -2170,7 +2239,7 @@ test_expect_success '--show-origin stdin' '
cat >expect <<-\EOF &&
standard input: user.custom=true
EOF
- git config --file - --show-origin --list <"$CUSTOM_CONFIG_FILE" >output &&
+ git config ${mode_prefix}list --file - --show-origin <"$CUSTOM_CONFIG_FILE" >output &&
test_cmp expect output
'
@@ -2197,7 +2266,7 @@ test_expect_success '--show-origin blob' '
cat >expect <<-EOF &&
blob:$blob user.custom=true
EOF
- git config --blob=$blob --show-origin --list >output &&
+ git config ${mode_prefix}list --blob=$blob --show-origin >output &&
test_cmp expect output
)
'
@@ -2213,7 +2282,7 @@ test_expect_success '--show-origin blob ref' '
cp "$CUSTOM_CONFIG_FILE" custom.conf &&
git add custom.conf &&
git commit -m "new config file" &&
- git config --blob=main:custom.conf --show-origin --list >output &&
+ git config ${mode_prefix}list --blob=main:custom.conf --show-origin >output &&
test_cmp expect output
)
'
@@ -2239,13 +2308,14 @@ test_expect_success '--show-scope with --list' '
worktree user.worktree=true
command user.cmdline=true
EOF
+ test_when_finished "git worktree remove wt1" &&
git worktree add wt1 &&
# We need these to test for worktree scope, but outside of this
# test, this is just noise
test_config core.repositoryformatversion 1 &&
test_config extensions.worktreeConfig true &&
git config --worktree user.worktree true &&
- git -c user.cmdline=true config --list --show-scope >output &&
+ git -c user.cmdline=true config ${mode_prefix}list --show-scope >output &&
test_cmp expect output
'
@@ -2254,7 +2324,7 @@ test_expect_success !MINGW '--show-scope with --blob' '
cat >expect <<-EOF &&
command user.custom=true
EOF
- git config --blob=$blob --show-scope --list >output &&
+ git config ${mode_prefix}list --blob=$blob --show-scope >output &&
test_cmp expect output
'
@@ -2264,7 +2334,7 @@ test_expect_success '--show-scope with --local' '
local user.override=local
local include.path=../include/relative.include
EOF
- git config --local --list --show-scope >output &&
+ git config ${mode_prefix}list --local --show-scope >output &&
test_cmp expect output
'
@@ -2272,7 +2342,7 @@ test_expect_success '--show-scope getting a single value' '
cat >expect <<-\EOF &&
local true
EOF
- git config --show-scope --get user.local >output &&
+ git config ${mode_get} --show-scope user.local >output &&
test_cmp expect output
'
@@ -2288,7 +2358,7 @@ test_expect_success '--show-scope with --show-origin' '
local file:.git/../include/relative.include user.relative=include
command command line: user.cmdline=true
EOF
- git -c user.cmdline=true config --list --show-origin --show-scope >output &&
+ git -c user.cmdline=true config ${mode_prefix}list --show-origin --show-scope >output &&
test_cmp expect output
'
@@ -2329,7 +2399,7 @@ test_expect_success 'override global and system config' '
global home.config=true
local local.config=true
EOF
- git config --show-scope --list >output &&
+ git config ${mode_prefix}list --show-scope >output &&
test_cmp expect output &&
cat >expect <<-EOF &&
@@ -2338,20 +2408,20 @@ test_expect_success 'override global and system config' '
local local.config=true
EOF
GIT_CONFIG_NOSYSTEM=false GIT_CONFIG_SYSTEM=custom-system-config GIT_CONFIG_GLOBAL=custom-global-config \
- git config --show-scope --list >output &&
+ git config ${mode_prefix}list --show-scope >output &&
test_cmp expect output &&
cat >expect <<-EOF &&
local local.config=true
EOF
GIT_CONFIG_NOSYSTEM=false GIT_CONFIG_SYSTEM=/dev/null GIT_CONFIG_GLOBAL=/dev/null \
- git config --show-scope --list >output &&
+ git config ${mode_prefix}list --show-scope >output &&
test_cmp expect output
'
test_expect_success 'override global and system config with missing file' '
- test_must_fail env GIT_CONFIG_GLOBAL=does-not-exist GIT_CONFIG_SYSTEM=/dev/null git config --global --list &&
- test_must_fail env GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=does-not-exist git config --system --list &&
+ test_must_fail env GIT_CONFIG_GLOBAL=does-not-exist GIT_CONFIG_SYSTEM=/dev/null git config ${mode_prefix}list --global &&
+ test_must_fail env GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=does-not-exist git config ${mode_prefix}list --system &&
GIT_CONFIG_GLOBAL=does-not-exist GIT_CONFIG_SYSTEM=does-not-exist git version
'
@@ -2467,7 +2537,7 @@ test_expect_success '--replace-all does not invent newlines' '
[abc]
Qkey = b
EOF
- git config --replace-all abc.key b &&
+ git config ${mode_replace_all} abc.key b &&
test_cmp expect .git/config
'
@@ -2478,7 +2548,7 @@ test_expect_success 'set all config with value-pattern' '
# no match => add new entry
cp initial config &&
git config --file=config abc.key two a+ &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-\EOF &&
abc.key=one
abc.key=two
@@ -2491,7 +2561,7 @@ test_expect_success 'set all config with value-pattern' '
# multiple values, no match => add
git config --file=config abc.key three a+ &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-\EOF &&
abc.key=one
abc.key=two
@@ -2501,7 +2571,7 @@ test_expect_success 'set all config with value-pattern' '
# single match => replace
git config --file=config abc.key four h+ &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-\EOF &&
abc.key=one
abc.key=two
@@ -2516,7 +2586,7 @@ test_expect_success '--replace-all and value-pattern' '
git config --file=config --add abc.key two &&
git config --file=config --add abc.key three &&
git config --file=config --replace-all abc.key four "o+" &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-\EOF &&
abc.key=four
abc.key=three
@@ -2532,20 +2602,20 @@ test_expect_success 'refuse --fixed-value for incompatible actions' '
test_must_fail git config --file=config --fixed-value --add dev.null bogus &&
test_must_fail git config --file=config --fixed-value --get-urlmatch dev.null bogus &&
test_must_fail git config --file=config --fixed-value --get-urlmatch dev.null bogus &&
- test_must_fail git config --file=config --fixed-value --rename-section dev null &&
- test_must_fail git config --file=config --fixed-value --remove-section dev &&
- test_must_fail git config --file=config --fixed-value --list &&
+ test_must_fail git config ${mode_prefix}rename-section --file=config --fixed-value dev null &&
+ test_must_fail git config ${mode_prefix}remove-section --file=config --fixed-value dev &&
+ test_must_fail git config ${mode_prefix}list --file=config --fixed-value &&
test_must_fail git config --file=config --fixed-value --get-color dev.null &&
test_must_fail git config --file=config --fixed-value --get-colorbool dev.null &&
# These modes complain when --fixed-value has no value-pattern
- test_must_fail git config --file=config --fixed-value dev.null bogus &&
- test_must_fail git config --file=config --fixed-value --replace-all dev.null bogus &&
- test_must_fail git config --file=config --fixed-value --get dev.null &&
- test_must_fail git config --file=config --fixed-value --get-all dev.null &&
- test_must_fail git config --file=config --fixed-value --get-regexp "dev.*" &&
- test_must_fail git config --file=config --fixed-value --unset dev.null &&
- test_must_fail git config --file=config --fixed-value --unset-all dev.null
+ test_must_fail git config ${mode_set} --file=config --fixed-value dev.null bogus &&
+ test_must_fail git config ${mode_replace_all} --file=config --fixed-value dev.null bogus &&
+ test_must_fail git config ${mode_prefix}get --file=config --fixed-value dev.null &&
+ test_must_fail git config ${mode_get_all} --file=config --fixed-value dev.null &&
+ test_must_fail git config ${mode_get_regexp} --file=config --fixed-value "dev.*" &&
+ test_must_fail git config ${mode_unset} --file=config --fixed-value dev.null &&
+ test_must_fail git config ${mode_unset_all} --file=config --fixed-value dev.null
'
test_expect_success '--fixed-value uses exact string matching' '
@@ -2555,7 +2625,7 @@ test_expect_success '--fixed-value uses exact string matching' '
cp initial config &&
git config --file=config fixed.test bogus "$META" &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-EOF &&
fixed.test=$META
fixed.test=bogus
@@ -2564,7 +2634,7 @@ test_expect_success '--fixed-value uses exact string matching' '
cp initial config &&
git config --file=config --fixed-value fixed.test bogus "$META" &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-\EOF &&
fixed.test=bogus
EOF
@@ -2573,16 +2643,21 @@ test_expect_success '--fixed-value uses exact string matching' '
cp initial config &&
test_must_fail git config --file=config --unset fixed.test "$META" &&
git config --file=config --fixed-value --unset fixed.test "$META" &&
- test_must_fail git config --file=config fixed.test &&
+ test_must_fail git config ${mode_get} --file=config fixed.test &&
+
+ cp initial config &&
+ test_must_fail git config unset --file=config --value="$META" fixed.test &&
+ git config unset --file=config --fixed-value --value="$META" fixed.test &&
+ test_must_fail git config ${mode_get} --file=config fixed.test &&
cp initial config &&
test_must_fail git config --file=config --unset-all fixed.test "$META" &&
git config --file=config --fixed-value --unset-all fixed.test "$META" &&
- test_must_fail git config --file=config fixed.test &&
+ test_must_fail git config ${mode_get} --file=config fixed.test &&
cp initial config &&
- git config --file=config --replace-all fixed.test bogus "$META" &&
- git config --file=config --list >actual &&
+ git config --file=config fixed.test bogus "$META" &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-EOF &&
fixed.test=$META
fixed.test=bogus
@@ -2590,7 +2665,7 @@ test_expect_success '--fixed-value uses exact string matching' '
test_cmp expect actual &&
git config --file=config --fixed-value --replace-all fixed.test bogus "$META" &&
- git config --file=config --list >actual &&
+ git config ${mode_prefix}list --file=config >actual &&
cat >expect <<-EOF &&
fixed.test=bogus
fixed.test=bogus
@@ -2605,18 +2680,27 @@ test_expect_success '--get and --get-all with --fixed-value' '
git config --file=config --add fixed.test "$META" &&
git config --file=config --get fixed.test bogus &&
+ git config get --file=config --value=bogus fixed.test &&
test_must_fail git config --file=config --get fixed.test "$META" &&
+ test_must_fail git config get --file=config --value="$META" fixed.test &&
git config --file=config --get --fixed-value fixed.test "$META" &&
+ git config get --file=config --fixed-value --value="$META" fixed.test &&
test_must_fail git config --file=config --get --fixed-value fixed.test non-existent &&
git config --file=config --get-all fixed.test bogus &&
+ git config get --all --file=config --value=bogus fixed.test &&
test_must_fail git config --file=config --get-all fixed.test "$META" &&
+ test_must_fail git config get --all --file=config --value="$META" fixed.test &&
git config --file=config --get-all --fixed-value fixed.test "$META" &&
+ git config get --all --file=config --value="$META" --fixed-value fixed.test &&
test_must_fail git config --file=config --get-all --fixed-value fixed.test non-existent &&
git config --file=config --get-regexp fixed+ bogus &&
+ git config get --regexp --file=config --value=bogus fixed+ &&
test_must_fail git config --file=config --get-regexp fixed+ "$META" &&
+ test_must_fail git config get --regexp --file=config --value="$META" fixed+ &&
git config --file=config --get-regexp --fixed-value fixed+ "$META" &&
+ git config get --regexp --file=config --fixed-value --value="$META" fixed+ &&
test_must_fail git config --file=config --get-regexp --fixed-value fixed+ non-existent
'
@@ -2738,4 +2822,25 @@ test_expect_success 'includeIf.hasconfig:remote.*.url forbids remote url in such
grep "fatal: remote URLs cannot be configured in file directly or indirectly included by includeIf.hasconfig:remote.*.url" err
'
+test_expect_success 'negated mode causes failure' '
+ test_must_fail git config --no-get 2>err &&
+ grep "unknown option \`no-get${SQ}" err
+'
+
+test_expect_success 'specifying multiple modes causes failure' '
+ cat >expect <<-EOF &&
+ error: options ${SQ}--get-all${SQ} and ${SQ}--get${SQ} cannot be used together
+ EOF
+ test_must_fail git config --get --get-all 2>err &&
+ test_cmp expect err
+'
+
+test_expect_success 'writing to stdin is rejected' '
+ echo "fatal: writing to stdin is not supported" >expect &&
+ test_must_fail git config ${mode_set} --file - foo.bar baz 2>err &&
+ test_cmp expect err
+'
+
+done
+
test_done
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index 5cde79ef8c..ef9272fd8e 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -357,4 +357,46 @@ test_expect_success 'include cycles are detected' '
grep "exceeded maximum include depth" stderr
'
+test_expect_success 'conditional include, hostname' '
+ cat >>.git/config <<-EOF &&
+ [includeIf "hostname:$(test-tool xgethostname)a"]
+ path = bar12
+ EOF
+ cat >>.git/bar12 <<-EOF &&
+ [test]
+ twelve=12
+ EOF
+
+ test_must_fail git config test.twelve &&
+
+ cat >>.git/config <<-EOF &&
+ [includeIf "hostname:$(test-tool xgethostname)"]
+ path = bar12
+ EOF
+ echo 12 >expect &&
+ git config test.twelve >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'conditional include, hostname, wildcard' '
+ cat >>.git/config <<-EOF &&
+ [includeIf "hostname:$(test-tool xgethostname)a*"]
+ path = bar13
+ EOF
+ cat >>.git/bar13 <<-EOF &&
+ [test]
+ thirteen = 13
+ EOF
+
+ test_must_fail git config test.thirteen &&
+
+ cat >>.git/config <<-EOF &&
+ [includeIf "hostname:$(test-tool xgethostname)*"]
+ path = bar13
+ EOF
+ echo 13 >expect &&
+ git config test.thirteen >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh
index 2092488090..067fd57290 100755
--- a/t/t1416-ref-transaction-hooks.sh
+++ b/t/t1416-ref-transaction-hooks.sh
@@ -134,4 +134,27 @@ test_expect_success 'interleaving hook calls succeed' '
test_cmp expect target-repo.git/actual
'
+test_expect_success 'hook captures git-symbolic-ref updates' '
+ test_when_finished "rm actual" &&
+
+ test_hook reference-transaction <<-\EOF &&
+ echo "$*" >>actual
+ while read -r line
+ do
+ printf "%s\n" "$line"
+ done >>actual
+ EOF
+
+ git symbolic-ref refs/heads/symref refs/heads/main &&
+
+ cat >expect <<-EOF &&
+ prepared
+ $ZERO_OID ref:refs/heads/main refs/heads/symref
+ committed
+ $ZERO_OID ref:refs/heads/main refs/heads/symref
+ EOF
+
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 8a456b1142..173b4fafad 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -1060,4 +1060,41 @@ test_expect_success 'fsck reports problems in current worktree index without fil
test_cmp expect actual
'
+test_expect_success 'fsck warning on symlink target with excessive length' '
+ symlink_target=$(printf "pattern %032769d" 1 | git hash-object -w --stdin) &&
+ test_when_finished "remove_object $symlink_target" &&
+ tree=$(printf "120000 blob %s\t%s\n" $symlink_target symlink | git mktree) &&
+ test_when_finished "remove_object $tree" &&
+ cat >expected <<-EOF &&
+ warning in blob $symlink_target: symlinkTargetLength: symlink target too long
+ EOF
+ git fsck --no-dangling >actual 2>&1 &&
+ test_cmp expected actual
+'
+
+test_expect_success 'fsck warning on symlink target pointing inside git dir' '
+ gitdir=$(printf ".git" | git hash-object -w --stdin) &&
+ ntfs_gitdir=$(printf "GIT~1" | git hash-object -w --stdin) &&
+ hfs_gitdir=$(printf ".${u200c}git" | git hash-object -w --stdin) &&
+ inside_gitdir=$(printf "nested/.git/config" | git hash-object -w --stdin) &&
+ benign_target=$(printf "legit/config" | git hash-object -w --stdin) &&
+ tree=$(printf "120000 blob %s\t%s\n" \
+ $benign_target benign_target \
+ $gitdir gitdir \
+ $hfs_gitdir hfs_gitdir \
+ $inside_gitdir inside_gitdir \
+ $ntfs_gitdir ntfs_gitdir |
+ git mktree) &&
+ for o in $gitdir $ntfs_gitdir $hfs_gitdir $inside_gitdir $benign_target $tree
+ do
+ test_when_finished "remove_object $o" || return 1
+ done &&
+ printf "warning in blob %s: symlinkPointsToGitDir: symlink target points to git dir\n" \
+ $gitdir $hfs_gitdir $inside_gitdir $ntfs_gitdir |
+ sort >expected &&
+ git fsck --no-dangling >actual 2>&1 &&
+ sort actual >actual.sorted &&
+ test_cmp expected actual.sorted
+'
+
test_done
diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh
index a669e592f1..30c31918fd 100755
--- a/t/t1500-rev-parse.sh
+++ b/t/t1500-rev-parse.sh
@@ -304,4 +304,10 @@ test_expect_success 'rev-parse --bisect includes bad, excludes good' '
test_cmp expect actual
'
+test_expect_success '--short= truncates to the actual hash length' '
+ git rev-parse HEAD >expect &&
+ git rev-parse --short=100 HEAD >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1517-outside-repo.sh b/t/t1517-outside-repo.sh
new file mode 100755
index 0000000000..6f32a40c6d
--- /dev/null
+++ b/t/t1517-outside-repo.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+test_description='check random commands outside repo'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_expect_success 'set up a non-repo directory and test file' '
+ GIT_CEILING_DIRECTORIES=$(pwd) &&
+ export GIT_CEILING_DIRECTORIES &&
+ mkdir non-repo &&
+ (
+ cd non-repo &&
+ # confirm that git does not find a repo
+ test_must_fail git rev-parse --git-dir
+ ) &&
+ test_write_lines one two three four >nums &&
+ git add nums &&
+ cp nums nums.old &&
+ test_write_lines five >>nums &&
+ git diff >sample.patch
+'
+
+test_expect_success 'compute a patch-id outside repository' '
+ git patch-id <sample.patch >patch-id.expect &&
+ (
+ cd non-repo &&
+ git patch-id <../sample.patch >../patch-id.actual
+ ) &&
+ test_cmp patch-id.expect patch-id.actual
+'
+
+test_expect_success 'hash-object outside repository' '
+ git hash-object --stdin <sample.patch >hash.expect &&
+ (
+ cd non-repo &&
+ git hash-object --stdin <../sample.patch >../hash.actual
+ ) &&
+ test_cmp hash.expect hash.actual
+'
+
+test_expect_success 'apply a patch outside repository' '
+ (
+ cd non-repo &&
+ cp ../nums.old nums &&
+ git apply ../sample.patch
+ ) &&
+ test_cmp nums non-repo/nums
+'
+
+test_expect_success 'grep outside repository' '
+ git grep --cached two >expect &&
+ (
+ cd non-repo &&
+ cp ../nums.old nums &&
+ git grep --no-index two >../actual
+ ) &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t1800-hook.sh b/t/t1800-hook.sh
index 8b0234cf2d..1894ebeb0e 100755
--- a/t/t1800-hook.sh
+++ b/t/t1800-hook.sh
@@ -185,4 +185,19 @@ test_expect_success 'stdin to hooks' '
test_cmp expect actual
'
+test_expect_success 'clone protections' '
+ test_config core.hooksPath "$(pwd)/my-hooks" &&
+ mkdir -p my-hooks &&
+ write_script my-hooks/test-hook <<-\EOF &&
+ echo Hook ran $1
+ EOF
+
+ git hook run test-hook 2>err &&
+ test_grep "Hook ran" err &&
+ test_must_fail env GIT_CLONE_PROTECTION_ACTIVE=true \
+ git hook run test-hook 2>err &&
+ test_grep "active .core.hooksPath" err &&
+ test_grep ! "Hook ran" err
+'
+
test_done
diff --git a/t/t2016-checkout-patch.sh b/t/t2016-checkout-patch.sh
index c4f9bf09aa..c40b661ac1 100755
--- a/t/t2016-checkout-patch.sh
+++ b/t/t2016-checkout-patch.sh
@@ -2,6 +2,7 @@
test_description='git checkout --patch'
+TEST_PASSES_SANITIZE_LEAK=true
. ./lib-patch-mode.sh
test_expect_success 'setup' '
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index d1bead61fa..8565fd4b5a 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -2215,6 +2215,39 @@ test_expect_success 'bad labels and refs rejected when parsing todo list' '
test_path_is_missing execed
'
+test_expect_success 'non-merge commands reject merge commits' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ git checkout E &&
+ git merge I &&
+ oid=$(git rev-parse HEAD) &&
+ cat >todo <<-EOF &&
+ pick $oid
+ reword $oid
+ edit $oid
+ fixup $oid
+ squash $oid
+ EOF
+ (
+ set_replace_editor todo &&
+ test_must_fail git rebase -i HEAD 2>actual
+ ) &&
+ cat >expect <<-EOF &&
+ error: ${SQ}pick${SQ} does not accept merge commits, please use ${SQ}merge -C${SQ}
+ error: invalid line 1: pick $oid
+ error: ${SQ}reword${SQ} does not accept merge commits, please use ${SQ}merge -c${SQ}
+ error: invalid line 2: reword $oid
+ error: ${SQ}edit${SQ} does not accept merge commits, please use ${SQ}merge -C${SQ} followed by ${SQ}break${SQ}
+ error: invalid line 3: edit $oid
+ error: cannot squash merge commit into another commit
+ error: invalid line 4: fixup $oid
+ error: cannot squash merge commit into another commit
+ error: invalid line 5: squash $oid
+ You can fix this with ${SQ}git rebase --edit-todo${SQ} and then run ${SQ}git rebase --continue${SQ}.
+ Or you can abort the rebase with ${SQ}git rebase --abort${SQ}.
+ EOF
+ test_cmp expect actual
+'
+
# This must be the last test in this file
test_expect_success '$EDITOR and friends are unchanged' '
test_editor_unchanged
diff --git a/t/t3428-rebase-signoff.sh b/t/t3428-rebase-signoff.sh
index 1bebd1ce74..6f57aed9fa 100755
--- a/t/t3428-rebase-signoff.sh
+++ b/t/t3428-rebase-signoff.sh
@@ -5,12 +5,17 @@ test_description='git rebase --signoff
This test runs git rebase --signoff and make sure that it works.
'
-TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-rebase.sh
test_expect_success 'setup' '
git commit --allow-empty -m "Initial empty commit" &&
test_commit first file a &&
+ test_commit second file &&
+ git checkout -b conflict-branch first &&
+ test_commit file-2 file-2 &&
+ test_commit conflict file &&
+ test_commit third file &&
ident="$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" &&
@@ -28,6 +33,22 @@ test_expect_success 'setup' '
Signed-off-by: $ident
EOF
+ # Expected commit message after conflict resolution for rebase --signoff
+ cat >expected-signed-conflict <<-EOF &&
+ third
+
+ Signed-off-by: $ident
+
+ conflict
+
+ Signed-off-by: $ident
+
+ file-2
+
+ Signed-off-by: $ident
+
+ EOF
+
# Expected commit message after rebase without --signoff (or with --no-signoff)
cat >expected-unsigned <<-EOF &&
first
@@ -39,8 +60,12 @@ test_expect_success 'setup' '
# We configure an alias to do the rebase --signoff so that
# on the next subtest we can show that --no-signoff overrides the alias
test_expect_success 'rebase --apply --signoff adds a sign-off line' '
- git rbs --apply HEAD^ &&
- test_commit_message HEAD expected-signed
+ test_must_fail git rbs --apply second third &&
+ git checkout --theirs file &&
+ git add file &&
+ git rebase --continue &&
+ git log --format=%B -n3 >actual &&
+ test_cmp expected-signed-conflict actual
'
test_expect_success 'rebase --no-signoff does not add a sign-off line' '
@@ -51,28 +76,65 @@ test_expect_success 'rebase --no-signoff does not add a sign-off line' '
test_expect_success 'rebase --exec --signoff adds a sign-off line' '
test_when_finished "rm exec" &&
- git commit --amend -m "first" &&
- git rebase --exec "touch exec" --signoff HEAD^ &&
+ git rebase --exec "touch exec" --signoff first^ first &&
test_path_is_file exec &&
test_commit_message HEAD expected-signed
'
test_expect_success 'rebase --root --signoff adds a sign-off line' '
- git commit --amend -m "first" &&
+ git checkout first &&
git rebase --root --keep-empty --signoff &&
test_commit_message HEAD^ expected-initial-signed &&
test_commit_message HEAD expected-signed
'
-test_expect_success 'rebase -i --signoff fails' '
- git commit --amend -m "first" &&
- git rebase -i --signoff HEAD^ &&
- test_commit_message HEAD expected-signed
+test_expect_success 'rebase -m --signoff adds a sign-off line' '
+ test_must_fail git rebase -m --signoff second third &&
+ git checkout --theirs file &&
+ git add file &&
+ GIT_EDITOR="sed -n /Conflicts:/,/^\\\$/p >actual" \
+ git rebase --continue &&
+ cat >expect <<-\EOF &&
+ # Conflicts:
+ # file
+
+ EOF
+ test_cmp expect actual &&
+ git log --format=%B -n3 >actual &&
+ test_cmp expected-signed-conflict actual
'
-test_expect_success 'rebase -m --signoff fails' '
- git commit --amend -m "first" &&
- git rebase -m --signoff HEAD^ &&
- test_commit_message HEAD expected-signed
+test_expect_success 'rebase -i --signoff adds a sign-off line when editing commit' '
+ (
+ set_fake_editor &&
+ FAKE_LINES="edit 1 edit 3 edit 2" \
+ git rebase -i --signoff first third
+ ) &&
+ echo a >a &&
+ git add a &&
+ test_must_fail git rebase --continue &&
+ git checkout --ours file &&
+ echo b >a &&
+ git add a file &&
+ git rebase --continue &&
+ echo c >a &&
+ git add a &&
+ git log --format=%B -n3 >actual &&
+ cat >expect <<-EOF &&
+ conflict
+
+ Signed-off-by: $ident
+
+ third
+
+ Signed-off-by: $ident
+
+ file-2
+
+ Signed-off-by: $ident
+
+ EOF
+ test_cmp expect actual
'
+
test_done
diff --git a/t/t3434-rebase-i18n.sh b/t/t3434-rebase-i18n.sh
index e6fef696bb..a4e482d2cd 100755
--- a/t/t3434-rebase-i18n.sh
+++ b/t/t3434-rebase-i18n.sh
@@ -71,7 +71,7 @@ test_rebase_continue_update_encode () {
git config i18n.commitencoding $new &&
test_must_fail git rebase -m main &&
test -f .git/rebase-merge/message &&
- git stripspace <.git/rebase-merge/message >two.t &&
+ git stripspace -s <.git/rebase-merge/message >two.t &&
git add two.t &&
git rebase --continue &&
compare_msg $msgfile $old $new &&
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index bc55255b0a..28a95a775d 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -4,9 +4,12 @@ test_description='add -i basic tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-terminal.sh
+SP=" "
+
diff_cmp () {
for x
do
@@ -44,17 +47,30 @@ test_expect_success 'warn about add.interactive.useBuiltin' '
cat >expect <<-\EOF &&
warning: the add.interactive.useBuiltin setting has been removed!
See its entry in '\''git help config'\'' for details.
- No changes.
EOF
+ echo "No changes." >expect.out &&
for v in = =true =false
do
git -c "add.interactive.useBuiltin$v" add -p >out 2>actual &&
- test_must_be_empty out &&
+ test_cmp expect.out out &&
test_cmp expect actual || return 1
done
'
+test_expect_success 'unknown command' '
+ test_when_finished "git reset --hard; rm -f command" &&
+ echo W >command &&
+ git add -N command &&
+ git diff command >expect &&
+ cat >>expect <<-EOF &&
+ (1/1) Stage addition [y,n,q,a,d,e,p,?]? Unknown command ${SQ}W${SQ} (use ${SQ}?${SQ} for help)
+ (1/1) Stage addition [y,n,q,a,d,e,p,?]?$SP
+ EOF
+ git add -p -- command <command >actual 2>&1 &&
+ test_cmp expect actual
+'
+
test_expect_success 'setup (initial)' '
echo content >file &&
git add file &&
@@ -231,7 +247,6 @@ test_expect_success 'setup file' '
'
test_expect_success 'setup patch' '
- SP=" " &&
NULL="" &&
cat >patch <<-EOF
@@ -1,4 +1,4 @@
@@ -334,13 +349,13 @@ test_expect_success 'different prompts for mode change/deleted' '
test_expect_success 'correct message when there is nothing to do' '
git reset --hard &&
- git add -p 2>err &&
- test_grep "No changes" err &&
+ git add -p >out &&
+ test_grep "No changes" out &&
printf "\\0123" >binary &&
git add binary &&
printf "\\0abc" >binary &&
- git add -p 2>err &&
- test_grep "Only binary files changed" err
+ git add -p >out &&
+ test_grep "Only binary files changed" out
'
test_expect_success 'setup again' '
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 00db82fb24..a7f71f8126 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -393,6 +393,15 @@ test_expect_success 'stash --staged' '
test bar,bar4 = $(cat file),$(cat file2)
'
+test_expect_success 'stash --staged with binary file' '
+ printf "\0" >file &&
+ git add file &&
+ git stash --staged &&
+ git stash pop &&
+ printf "\0" >expect &&
+ test_cmp expect file
+'
+
test_expect_success 'dont assume push with non-option args' '
test_must_fail git stash -q drop 2>err &&
test_grep -e "subcommand wasn'\''t specified; '\''push'\'' can'\''t be assumed due to unexpected token '\''drop'\''" err
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index e37a1411ee..ba85b582c5 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -1368,12 +1368,38 @@ test_expect_success 'empty subject prefix does not have extra space' '
test_cmp expect actual
'
-test_expect_success '--rfc' '
+test_expect_success '--rfc and --no-rfc' '
cat >expect <<-\EOF &&
Subject: [RFC PATCH 1/1] header with . in it
EOF
git format-patch -n -1 --stdout --rfc >patch &&
grep "^Subject:" patch >actual &&
+ test_cmp expect actual &&
+ git format-patch -n -1 --stdout --rfc --no-rfc >patch &&
+ sed -e "s/RFC //" expect >expect-raw &&
+ grep "^Subject:" patch >actual &&
+ test_cmp expect-raw actual
+'
+
+test_expect_success '--rfc=WIP and --rfc=' '
+ cat >expect <<-\EOF &&
+ Subject: [WIP PATCH 1/1] header with . in it
+ EOF
+ git format-patch -n -1 --stdout --rfc=WIP >patch &&
+ grep "^Subject:" patch >actual &&
+ test_cmp expect actual &&
+ git format-patch -n -1 --stdout --rfc --rfc= >patch &&
+ sed -e "s/WIP //" expect >expect-raw &&
+ grep "^Subject:" patch >actual &&
+ test_cmp expect-raw actual
+'
+
+test_expect_success '--rfc=-(WIP) appends' '
+ cat >expect <<-\EOF &&
+ Subject: [PATCH (WIP) 1/1] header with . in it
+ EOF
+ git format-patch -n -1 --stdout --rfc="-(WIP)" >patch &&
+ grep "^Subject:" patch >actual &&
test_cmp expect actual
'
@@ -1397,6 +1423,27 @@ test_expect_success '--rfc is argument order independent' '
test_cmp expect actual
'
+test_expect_success '--subject-prefix="<non-empty>" and -k cannot be used together' '
+ echo "fatal: options '\''--subject-prefix/--rfc'\'' and '\''-k'\'' cannot be used together" >expect.err &&
+ test_must_fail git format-patch -1 --stdout --subject-prefix="MYPREFIX" -k >actual.out 2>actual.err &&
+ test_must_be_empty actual.out &&
+ test_cmp expect.err actual.err
+'
+
+test_expect_success '--subject-prefix="" and -k cannot be used together' '
+ echo "fatal: options '\''--subject-prefix/--rfc'\'' and '\''-k'\'' cannot be used together" >expect.err &&
+ test_must_fail git format-patch -1 --stdout --subject-prefix="" -k >actual.out 2>actual.err &&
+ test_must_be_empty actual.out &&
+ test_cmp expect.err actual.err
+'
+
+test_expect_success '--rfc and -k cannot be used together' '
+ echo "fatal: options '\''--subject-prefix/--rfc'\'' and '\''-k'\'' cannot be used together" >expect.err &&
+ test_must_fail git format-patch -1 --stdout --rfc -k >actual.out 2>actual.err &&
+ test_must_be_empty actual.out &&
+ test_cmp expect.err actual.err
+'
+
test_expect_success '--from=ident notices bogus ident' '
test_must_fail git format-patch -1 --stdout --from=foo >patch
'
diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh
index fdd865f7c3..26430ca66b 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -172,6 +172,14 @@ test_expect_success 'no diff with -diff' '
grep Binary out
'
+test_expect_success 'diff.external and --exit-code with output' '
+ test_expect_code 1 git -c diff.external=echo diff --exit-code
+'
+
+test_expect_success 'diff.external and --exit-code without output' '
+ git -c diff.external=true diff --exit-code
+'
+
echo NULZbetweenZwords | perl -pe 'y/Z/\000/' > file
test_expect_success 'force diff with "diff"' '
diff --git a/t/t4026-color.sh b/t/t4026-color.sh
index cc3f60d468..b05f2a9b60 100755
--- a/t/t4026-color.sh
+++ b/t/t4026-color.sh
@@ -96,8 +96,8 @@ test_expect_success '256 colors' '
color "254 bold 255" "[1;38;5;254;48;5;255m"
'
-test_expect_success '24-bit colors' '
- color "#ff00ff black" "[38;2;255;0;255;40m"
+test_expect_success 'RGB colors' '
+ color "#ff00ff #0f0" "[38;2;255;0;255;48;2;0;255;0m"
'
test_expect_success '"default" foreground' '
@@ -112,7 +112,7 @@ test_expect_success '"default" can be combined with attributes' '
color "default default no-reverse bold" "[1;27;39;49m"
'
-test_expect_success '"normal" yields no color at all"' '
+test_expect_success '"normal" yields no color at all' '
color "normal black" "[40m"
'
@@ -140,6 +140,26 @@ test_expect_success 'extra character after attribute' '
invalid_color "dimX"
'
+test_expect_success 'non-hex character in RGB color' '
+ invalid_color "#x23456" &&
+ invalid_color "#1x3456" &&
+ invalid_color "#12x456" &&
+ invalid_color "#123x56" &&
+ invalid_color "#1234x6" &&
+ invalid_color "#12345x" &&
+ invalid_color "#x23" &&
+ invalid_color "#1x3" &&
+ invalid_color "#12x"
+'
+
+test_expect_success 'wrong number of letters in RGB color' '
+ invalid_color "#1" &&
+ invalid_color "#23" &&
+ invalid_color "#789a" &&
+ invalid_color "#bcdef" &&
+ invalid_color "#1234567"
+'
+
test_expect_success 'unknown color slots are ignored (diff)' '
git config color.diff.nosuchslotwilleverbedefined white &&
git diff --color
diff --git a/t/t4046-diff-unmerged.sh b/t/t4046-diff-unmerged.sh
index fb8c51746e..afda629c98 100755
--- a/t/t4046-diff-unmerged.sh
+++ b/t/t4046-diff-unmerged.sh
@@ -98,4 +98,12 @@ test_expect_success 'diff --stat' '
test_cmp diff-stat.expect diff-stat.actual
'
+test_expect_success 'diff --quiet' '
+ test_expect_code 1 git diff --cached --quiet
+'
+
+test_expect_success 'diff --quiet --ignore-all-space' '
+ test_expect_code 1 git diff --cached --quiet --ignore-all-space
+'
+
test_done
diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh
index d370ecfe0d..144619ab87 100755
--- a/t/t4103-apply-binary.sh
+++ b/t/t4103-apply-binary.sh
@@ -9,6 +9,7 @@ test_description='git apply handling binary patches
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup' '
diff --git a/t/t4104-apply-boundary.sh b/t/t4104-apply-boundary.sh
index 71ef4132d1..dc501aac38 100755
--- a/t/t4104-apply-boundary.sh
+++ b/t/t4104-apply-boundary.sh
@@ -5,6 +5,7 @@
test_description='git apply boundary tests'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
L="c d e f g h i j k l m n o p q r s t u v w x"
diff --git a/t/t4113-apply-ending.sh b/t/t4113-apply-ending.sh
index 66fa51591e..2c65c6a169 100755
--- a/t/t4113-apply-ending.sh
+++ b/t/t4113-apply-ending.sh
@@ -6,6 +6,7 @@
test_description='git apply trying to add an ending line.
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
# setup
diff --git a/t/t4117-apply-reject.sh b/t/t4117-apply-reject.sh
index c86d05a96f..4d15ccd28e 100755
--- a/t/t4117-apply-reject.sh
+++ b/t/t4117-apply-reject.sh
@@ -7,6 +7,7 @@ test_description='git apply with rejects
'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success setup '
diff --git a/t/t4123-apply-shrink.sh b/t/t4123-apply-shrink.sh
index 3ef84619f5..3601c0c5dc 100755
--- a/t/t4123-apply-shrink.sh
+++ b/t/t4123-apply-shrink.sh
@@ -2,6 +2,7 @@
test_description='apply a patch that is larger than the preimage'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
cat >F <<\EOF
diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh
index a7fa94ce0a..605faea0c7 100755
--- a/t/t4204-patch-id.sh
+++ b/t/t4204-patch-id.sh
@@ -310,4 +310,38 @@ test_expect_success 'patch-id handles diffs with one line of before/after' '
test_config patchid.stable true &&
calc_patch_id diffu1stable <diffu1
'
+
+test_expect_failure 'patch-id computes same ID with different object hashes' '
+ test_when_finished "rm -rf repo-sha1 repo-sha256" &&
+
+ cat >diff <<-\EOF &&
+ diff --git a/bar b/bar
+ index bdaf90f..31051f6 100644
+ --- a/bar
+ +++ b/bar
+ @@ -2 +2,2 @@
+ b
+ +c
+ EOF
+
+ git init --object-format=sha1 repo-sha1 &&
+ git -C repo-sha1 patch-id <diff >patch-id-sha1 &&
+ git init --object-format=sha256 repo-sha256 &&
+ git -C repo-sha256 patch-id <diff >patch-id-sha256 &&
+ test_cmp patch-id-sha1 patch-id-sha256
+'
+
+test_expect_success 'patch-id without repository' '
+ cat >diff <<-\EOF &&
+ diff --git a/bar b/bar
+ index bdaf90f..31051f6 100644
+ --- a/bar
+ +++ b/bar
+ @@ -2 +2,2 @@
+ b
+ +c
+ EOF
+ nongit git patch-id <diff
+'
+
test_done
diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh
index 2ba0324a69..823d1cf773 100755
--- a/t/t4216-log-bloom.sh
+++ b/t/t4216-log-bloom.sh
@@ -82,7 +82,23 @@ test_bloom_filters_used () {
test_bloom_filters_not_used () {
log_args=$1
setup "$log_args" &&
- ! grep -q "statistics:{\"filter_not_present\":" "$TRASH_DIRECTORY/trace.perf" &&
+
+ if grep -q "statistics:{\"filter_not_present\":" "$TRASH_DIRECTORY/trace.perf"
+ then
+ # if the Bloom filter system is initialized, ensure that no
+ # filters were used
+ data="statistics:{"
+ # unusable filters (e.g., those computed with a
+ # different value of commitGraph.changedPathsVersion)
+ # are counted in the filter_not_present bucket, so any
+ # value is OK there.
+ data="$data\"filter_not_present\":[0-9][0-9]*,"
+ data="$data\"maybe\":0,"
+ data="$data\"definitely_not\":0,"
+ data="$data\"false_positive\":0}"
+
+ grep -q "$data" "$TRASH_DIRECTORY/trace.perf"
+ fi &&
test_cmp log_wo_bloom log_w_bloom
}
@@ -163,7 +179,7 @@ test_expect_success 'setup - add commit-graph to the chain with Bloom filters' '
test_bloom_filters_used_when_some_filters_are_missing () {
log_args=$1
- bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"maybe\":6,\"definitely_not\":9"
+ bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"maybe\":6,\"definitely_not\":10"
setup "$log_args" &&
grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" &&
test_cmp log_wo_bloom log_w_bloom
@@ -206,6 +222,10 @@ test_filter_trunc_large () {
grep "\"key\":\"filter-trunc-large\",\"value\":\"$1\"" $2
}
+test_filter_upgraded () {
+ grep "\"key\":\"filter-upgraded\",\"value\":\"$1\"" $2
+}
+
test_expect_success 'correctly report changes over limit' '
git init limits &&
(
@@ -405,8 +425,292 @@ test_expect_success 'Bloom generation backfills empty commits' '
)
'
+graph=.git/objects/info/commit-graph
+graphdir=.git/objects/info/commit-graphs
+chain=$graphdir/commit-graph-chain
+
+test_expect_success 'setup for mixed Bloom setting tests' '
+ repo=mixed-bloom-settings &&
+
+ git init $repo &&
+ for i in one two three
+ do
+ test_commit -C $repo $i file || return 1
+ done
+'
+
+test_expect_success 'ensure Bloom filters with incompatible settings are ignored' '
+ # Compute Bloom filters with "unusual" settings.
+ git -C $repo rev-parse one >in &&
+ GIT_TEST_BLOOM_SETTINGS_NUM_HASHES=3 git -C $repo commit-graph write \
+ --stdin-commits --changed-paths --split <in &&
+ layer=$(head -n 1 $repo/$chain) &&
+
+ # A commit-graph layer without Bloom filters "hides" the layers
+ # below ...
+ git -C $repo rev-parse two >in &&
+ git -C $repo commit-graph write --stdin-commits --no-changed-paths \
+ --split=no-merge <in &&
+
+ # Another commit-graph layer that has Bloom filters, but with
+ # standard settings, and is thus incompatible with the base
+ # layer written above.
+ git -C $repo rev-parse HEAD >in &&
+ git -C $repo commit-graph write --stdin-commits --changed-paths \
+ --split=no-merge <in &&
+
+ test_line_count = 3 $repo/$chain &&
+
+ # Ensure that incompatible Bloom filters are ignored.
+ git -C $repo -c core.commitGraph=false log --oneline --no-decorate -- file \
+ >expect 2>err &&
+ git -C $repo log --oneline --no-decorate -- file >actual 2>err &&
+ test_cmp expect actual &&
+ grep "disabling Bloom filters for commit-graph layer .$layer." err
+'
+
+test_expect_success 'merge graph layers with incompatible Bloom settings' '
+ # Ensure that incompatible Bloom filters are ignored when
+ # merging existing layers.
+ git -C $repo commit-graph write --reachable --changed-paths 2>err &&
+ grep "disabling Bloom filters for commit-graph layer .$layer." err &&
+
+ test_path_is_file $repo/$graph &&
+ test_dir_is_empty $repo/$graphdir &&
+
+ git -C $repo -c core.commitGraph=false log --oneline --no-decorate -- \
+ file >expect &&
+ trace_out="$(pwd)/trace.perf" &&
+ GIT_TRACE2_PERF="$trace_out" \
+ git -C $repo log --oneline --no-decorate -- file >actual 2>err &&
+
+ test_cmp expect actual &&
+ grep "statistics:{\"filter_not_present\":0," trace.perf &&
+ test_must_be_empty err
+'
+
+test_expect_success 'ensure Bloom filter with incompatible versions are ignored' '
+ rm "$repo/$graph" &&
+
+ git -C $repo log --oneline --no-decorate -- $CENT >expect &&
+
+ # Compute v1 Bloom filters for commits at the bottom.
+ git -C $repo rev-parse HEAD^ >in &&
+ git -C $repo commit-graph write --stdin-commits --changed-paths \
+ --split <in &&
+
+ # Compute v2 Bloomfilters for the rest of the commits at the top.
+ git -C $repo rev-parse HEAD >in &&
+ git -C $repo -c commitGraph.changedPathsVersion=2 commit-graph write \
+ --stdin-commits --changed-paths --split=no-merge <in &&
+
+ test_line_count = 2 $repo/$chain &&
+
+ git -C $repo log --oneline --no-decorate -- $CENT >actual 2>err &&
+ test_cmp expect actual &&
+
+ layer="$(head -n 1 $repo/$chain)" &&
+ cat >expect.err <<-EOF &&
+ warning: disabling Bloom filters for commit-graph layer $SQ$layer$SQ due to incompatible settings
+ EOF
+ test_cmp expect.err err
+'
+
+get_first_changed_path_filter () {
+ test-tool read-graph bloom-filters >filters.dat &&
+ head -n 1 filters.dat
+}
+
+# chosen to be the same under all Unicode normalization forms
+CENT=$(printf "\302\242")
+
+test_expect_success 'set up repo with high bit path, version 1 changed-path' '
+ git init highbit1 &&
+ test_commit -C highbit1 c1 "$CENT" &&
+ git -C highbit1 commit-graph write --reachable --changed-paths
+'
+
+test_expect_success 'setup check value of version 1 changed-path' '
+ (
+ cd highbit1 &&
+ echo "52a9" >expect &&
+ get_first_changed_path_filter >actual
+ )
+'
+
+# expect will not match actual if char is unsigned by default. Write the test
+# in this way, so that a user running this test script can still see if the two
+# files match. (It will appear as an ordinary success if they match, and a skip
+# if not.)
+if test_cmp highbit1/expect highbit1/actual
+then
+ test_set_prereq SIGNED_CHAR_BY_DEFAULT
+fi
+test_expect_success SIGNED_CHAR_BY_DEFAULT 'check value of version 1 changed-path' '
+ # Only the prereq matters for this test.
+ true
+'
+
+test_expect_success 'setup make another commit' '
+ # "git log" does not use Bloom filters for root commits - see how, in
+ # revision.c, rev_compare_tree() (the only code path that eventually calls
+ # get_bloom_filter()) is only called by try_to_simplify_commit() when the commit
+ # has one parent. Therefore, make another commit so that we perform the tests on
+ # a non-root commit.
+ test_commit -C highbit1 anotherc1 "another$CENT"
+'
+
+test_expect_success 'version 1 changed-path used when version 1 requested' '
+ (
+ cd highbit1 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 1 changed-path not used when version 2 requested' '
+ (
+ cd highbit1 &&
+ git config --add commitgraph.changedPathsVersion 2 &&
+ test_bloom_filters_not_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 1 changed-path used when autodetect requested' '
+ (
+ cd highbit1 &&
+ git config --add commitgraph.changedPathsVersion -1 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'when writing another commit graph, preserve existing version 1 of changed-path' '
+ test_commit -C highbit1 c1double "$CENT$CENT" &&
+ git -C highbit1 commit-graph write --reachable --changed-paths &&
+ (
+ cd highbit1 &&
+ git config --add commitgraph.changedPathsVersion -1 &&
+ echo "options: bloom(1,10,7) read_generation_data" >expect &&
+ test-tool read-graph >full &&
+ grep options full >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'set up repo with high bit path, version 2 changed-path' '
+ git init highbit2 &&
+ git -C highbit2 config --add commitgraph.changedPathsVersion 2 &&
+ test_commit -C highbit2 c2 "$CENT" &&
+ git -C highbit2 commit-graph write --reachable --changed-paths
+'
+
+test_expect_success 'check value of version 2 changed-path' '
+ (
+ cd highbit2 &&
+ echo "c01f" >expect &&
+ get_first_changed_path_filter >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'setup make another commit' '
+ # "git log" does not use Bloom filters for root commits - see how, in
+ # revision.c, rev_compare_tree() (the only code path that eventually calls
+ # get_bloom_filter()) is only called by try_to_simplify_commit() when the commit
+ # has one parent. Therefore, make another commit so that we perform the tests on
+ # a non-root commit.
+ test_commit -C highbit2 anotherc2 "another$CENT"
+'
+
+test_expect_success 'version 2 changed-path used when version 2 requested' '
+ (
+ cd highbit2 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 2 changed-path not used when version 1 requested' '
+ (
+ cd highbit2 &&
+ git config --add commitgraph.changedPathsVersion 1 &&
+ test_bloom_filters_not_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'version 2 changed-path used when autodetect requested' '
+ (
+ cd highbit2 &&
+ git config --add commitgraph.changedPathsVersion -1 &&
+ test_bloom_filters_used "-- another$CENT"
+ )
+'
+
+test_expect_success 'when writing another commit graph, preserve existing version 2 of changed-path' '
+ test_commit -C highbit2 c2double "$CENT$CENT" &&
+ git -C highbit2 commit-graph write --reachable --changed-paths &&
+ (
+ cd highbit2 &&
+ git config --add commitgraph.changedPathsVersion -1 &&
+ echo "options: bloom(2,10,7) read_generation_data" >expect &&
+ test-tool read-graph >full &&
+ grep options full >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'when writing commit graph, do not reuse changed-path of another version' '
+ git init doublewrite &&
+ test_commit -C doublewrite c "$CENT" &&
+
+ git -C doublewrite config --add commitgraph.changedPathsVersion 1 &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C doublewrite commit-graph write --reachable --changed-paths &&
+ test_filter_computed 1 trace2.txt &&
+ test_filter_upgraded 0 trace2.txt &&
+
+ git -C doublewrite commit-graph write --reachable --changed-paths &&
+ for v in -2 3
+ do
+ git -C doublewrite config --add commitgraph.changedPathsVersion $v &&
+ git -C doublewrite commit-graph write --reachable --changed-paths 2>err &&
+ cat >expect <<-EOF &&
+ warning: attempting to write a commit-graph, but ${SQ}commitgraph.changedPathsVersion${SQ} ($v) is not supported
+ EOF
+ test_cmp expect err || return 1
+ done &&
+
+ git -C doublewrite config --add commitgraph.changedPathsVersion 2 &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C doublewrite commit-graph write --reachable --changed-paths &&
+ test_filter_computed 1 trace2.txt &&
+ test_filter_upgraded 0 trace2.txt &&
+
+ (
+ cd doublewrite &&
+ echo "c01f" >expect &&
+ get_first_changed_path_filter >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'when writing commit graph, reuse changed-path of another version where possible' '
+ git init upgrade &&
+
+ test_commit -C upgrade base no-high-bits &&
+
+ git -C upgrade config --add commitgraph.changedPathsVersion 1 &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C upgrade commit-graph write --reachable --changed-paths &&
+ test_filter_computed 1 trace2.txt &&
+ test_filter_upgraded 0 trace2.txt &&
+
+ git -C upgrade config --add commitgraph.changedPathsVersion 2 &&
+ GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \
+ git -C upgrade commit-graph write --reachable --changed-paths &&
+ test_filter_computed 0 trace2.txt &&
+ test_filter_upgraded 1 trace2.txt
+'
+
corrupt_graph () {
- graph=.git/objects/info/commit-graph &&
test_when_finished "rm -rf $graph" &&
git commit-graph write --reachable --changed-paths &&
corrupt_chunk_file $graph "$@"
diff --git a/t/t4252-am-options.sh b/t/t4252-am-options.sh
index e758e634a3..5b680dc755 100755
--- a/t/t4252-am-options.sh
+++ b/t/t4252-am-options.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='git am with options and not losing them'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
tm="$TEST_DIRECTORY/t4252"
diff --git a/t/t4258-am-quoted-cr.sh b/t/t4258-am-quoted-cr.sh
index 201915b45a..3573c9147f 100755
--- a/t/t4258-am-quoted-cr.sh
+++ b/t/t4258-am-quoted-cr.sh
@@ -2,6 +2,7 @@
test_description='test am --quoted-cr=<action>'
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
DATA="$TEST_DIRECTORY/t4258"
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index eaf959d8f6..7310774af5 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -133,7 +133,8 @@ test_expect_success 'git archive vs. bare' '
'
test_expect_success 'git archive with worktree attributes, bare' '
- (cd bare && git archive --worktree-attributes HEAD) >bare-worktree.tar &&
+ (cd bare &&
+ git -c attr.tree=HEAD archive --worktree-attributes HEAD) >bare-worktree.tar &&
(mkdir bare-worktree && cd bare-worktree && "$TAR" xf -) <bare-worktree.tar
'
diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh
index 5d7d321840..cc7220b6c0 100755
--- a/t/t5326-multi-pack-bitmaps.sh
+++ b/t/t5326-multi-pack-bitmaps.sh
@@ -434,6 +434,27 @@ test_expect_success 'tagged commits are selected for bitmapping' '
)
'
+test_expect_success 'do not follow replace objects for MIDX bitmap' '
+ rm -fr repo &&
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+
+ test_commit A &&
+ test_commit B &&
+ git checkout --orphan=orphan A &&
+ test_commit orphan &&
+
+ git replace A HEAD &&
+ git repack -ad --write-midx --write-bitmap-index &&
+
+ # generating reachability bitmaps with replace refs
+ # enabled will result in broken clones
+ git clone --no-local --bare . clone.git
+ )
+'
+
corrupt_file () {
chmod a+w "$1" &&
printf "bogus" | dd of="$1" bs=1 seek="12" conv=notrunc
diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh
new file mode 100755
index 0000000000..531f1924af
--- /dev/null
+++ b/t/t5333-pseudo-merge-bitmaps.sh
@@ -0,0 +1,389 @@
+#!/bin/sh
+
+test_description='pseudo-merge bitmaps'
+
+GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0
+
+. ./test-lib.sh
+
+test_pseudo_merges () {
+ test-tool bitmap dump-pseudo-merges
+}
+
+test_pseudo_merge_commits () {
+ test-tool bitmap dump-pseudo-merge-commits "$1"
+}
+
+test_pseudo_merges_satisfied () {
+ test_trace2_data bitmap pseudo_merges_satisfied "$1"
+}
+
+test_pseudo_merges_cascades () {
+ test_trace2_data bitmap pseudo_merges_cascades "$1"
+}
+
+test_pseudo_merges_reused () {
+ test_trace2_data pack-bitmap-write building_bitmaps_pseudo_merge_reused "$1"
+}
+
+tag_everything () {
+ git rev-list --all --no-object-names >in &&
+ perl -lne '
+ print "create refs/tags/" . $. . " " . $1 if /([0-9a-f]+)/
+ ' <in | git update-ref --stdin
+}
+
+test_expect_success 'setup' '
+ test_commit_bulk 512 &&
+ tag_everything
+'
+
+test_expect_success 'bitmap traversal without pseudo-merges' '
+ git repack -adb &&
+
+ git rev-list --count --all --objects >expect &&
+
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT=$PWD/trace2.txt \
+ git rev-list --count --all --objects --use-bitmap-index >actual &&
+
+ test_pseudo_merges_satisfied 0 <trace2.txt &&
+ test_pseudo_merges_cascades 0 <trace2.txt &&
+ test_pseudo_merges >merges &&
+ test_must_be_empty merges &&
+ test_cmp expect actual
+'
+
+test_expect_success 'pseudo-merges accurately represent their objects' '
+ test_config bitmapPseudoMerge.test.pattern "refs/tags/" &&
+ test_config bitmapPseudoMerge.test.maxMerges 8 &&
+ test_config bitmapPseudoMerge.test.stableThreshold never &&
+
+ git repack -adb &&
+
+ test_pseudo_merges >merges &&
+ test_line_count = 8 merges &&
+
+ for i in $(test_seq 0 $(($(wc -l <merges)-1)))
+ do
+ test-tool bitmap dump-pseudo-merge-commits $i >commits &&
+
+ git rev-list --objects --no-object-names --stdin <commits >expect.raw &&
+ test-tool bitmap dump-pseudo-merge-objects $i >actual.raw &&
+
+ sort -u <expect.raw >expect &&
+ sort -u <actual.raw >actual &&
+
+ test_cmp expect actual || return 1
+ done
+'
+
+test_expect_success 'bitmap traversal with pseudo-merges' '
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT=$PWD/trace2.txt \
+ git rev-list --count --all --objects --use-bitmap-index >actual &&
+ git rev-list --count --all --objects >expect &&
+
+ test_pseudo_merges_satisfied 8 <trace2.txt &&
+ test_pseudo_merges_cascades 1 <trace2.txt &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stale bitmap traversal with pseudo-merges' '
+ test_commit other &&
+
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT=$PWD/trace2.txt \
+ git rev-list --count --all --objects --use-bitmap-index >actual &&
+ git rev-list --count --all --objects >expect &&
+
+ test_pseudo_merges_satisfied 8 <trace2.txt &&
+ test_pseudo_merges_cascades 1 <trace2.txt &&
+ test_cmp expect actual
+'
+
+test_expect_success 'bitmapPseudoMerge.sampleRate adjusts commit selection rate' '
+ test_config bitmapPseudoMerge.test.pattern "refs/tags/" &&
+ test_config bitmapPseudoMerge.test.maxMerges 8 &&
+ test_config bitmapPseudoMerge.test.stableThreshold never &&
+
+ commits_nr=$(git rev-list --all --count) &&
+
+ for rate in 100 50 10
+ do
+ git -c bitmapPseudoMerge.test.sampleRate=$rate repack -adb &&
+
+ test_pseudo_merges >merges &&
+ for i in $(test_seq 0 $(($(wc -l <merges)-1)))
+ do
+ test_pseudo_merge_commits $i || return 1
+ done >commits &&
+
+ test-tool bitmap list-commits >bitmaps &&
+ bitmaps_nr="$(wc -l <bitmaps)" &&
+
+ perl -MPOSIX -e "print ceil((\$ARGV[0]/100)*(\$ARGV[1]-\$ARGV[2]))" \
+ "$rate" "$commits_nr" "$bitmaps_nr" >expect &&
+
+ test $(cat expect) -eq $(wc -l <commits) || return 1
+ done
+'
+
+test_expect_success 'bitmapPseudoMerge.threshold excludes newer commits' '
+ git init pseudo-merge-threshold &&
+ (
+ cd pseudo-merge-threshold &&
+
+ new="1672549200" && # 2023-01-01
+ old="1641013200" && # 2022-01-01
+
+ test_commit_bulk --message="new" --date "$new +0000" 128 &&
+ test_commit_bulk --message="old" --date "$old +0000" 128 &&
+ test_tick &&
+
+ tag_everything &&
+
+ git \
+ -c bitmapPseudoMerge.test.pattern="refs/tags/" \
+ -c bitmapPseudoMerge.test.maxMerges=1 \
+ -c bitmapPseudoMerge.test.threshold=$(($new - 1)) \
+ -c bitmapPseudoMerge.test.stableThreshold=never \
+ repack -adb &&
+
+ test_pseudo_merges >merges &&
+ test_line_count = 1 merges &&
+
+ test_pseudo_merge_commits 0 >oids &&
+ git cat-file --batch <oids >commits &&
+
+ test $(wc -l <oids) = $(grep -c "^committer.*$old +0000$" commits)
+ )
+'
+
+test_expect_success 'bitmapPseudoMerge.stableThreshold creates stable groups' '
+ (
+ cd pseudo-merge-threshold &&
+
+ new="1672549200" && # 2023-01-01
+ mid="1654059600" && # 2022-06-01
+ old="1641013200" && # 2022-01-01
+
+ test_commit_bulk --message="mid" --date "$mid +0000" 128 &&
+ test_tick &&
+
+ git for-each-ref --format="delete %(refname)" refs/tags >in &&
+ git update-ref --stdin <in &&
+
+ tag_everything &&
+
+ git \
+ -c bitmapPseudoMerge.test.pattern="refs/tags/" \
+ -c bitmapPseudoMerge.test.maxMerges=1 \
+ -c bitmapPseudoMerge.test.threshold=$(($new - 1)) \
+ -c bitmapPseudoMerge.test.stableThreshold=$(($mid - 1)) \
+ -c bitmapPseudoMerge.test.stableSize=10 \
+ repack -adb &&
+
+ test_pseudo_merges >merges &&
+ merges_nr="$(wc -l <merges)" &&
+
+ for i in $(test_seq $(($merges_nr - 1)))
+ do
+ test_pseudo_merge_commits 0 >oids &&
+ git cat-file --batch <oids >commits &&
+
+ expect="$(grep -c "^committer.*$old +0000$" commits)" &&
+ actual="$(wc -l <oids)" &&
+
+ test $expect = $actual || return 1
+ done &&
+
+ test_pseudo_merge_commits $(($merges_nr - 1)) >oids &&
+ git cat-file --batch <oids >commits &&
+ test $(wc -l <oids) = $(grep -c "^committer.*$mid +0000$" commits)
+ )
+'
+
+test_expect_success 'out of order thresholds are rejected' '
+ test_must_fail git \
+ -c bitmapPseudoMerge.test.pattern="refs/*" \
+ -c bitmapPseudoMerge.test.threshold=1.month.ago \
+ -c bitmapPseudoMerge.test.stableThreshold=1.week.ago \
+ repack -adb 2>err &&
+
+ cat >expect <<-EOF &&
+ fatal: pseudo-merge group ${SQ}test${SQ} has unstable threshold before stable one
+ EOF
+
+ test_cmp expect err
+'
+
+test_expect_success 'pseudo-merge pattern with capture groups' '
+ git init pseudo-merge-captures &&
+ (
+ cd pseudo-merge-captures &&
+
+ test_commit_bulk 128 &&
+ tag_everything &&
+
+ for r in $(test_seq 8)
+ do
+ test_commit_bulk 16 &&
+
+ git rev-list HEAD~16.. >in &&
+
+ perl -lne "print \"create refs/remotes/$r/tags/\$. \$_\"" <in |
+ git update-ref --stdin || return 1
+ done &&
+
+ git \
+ -c bitmapPseudoMerge.tags.pattern="refs/remotes/([0-9]+)/tags/" \
+ -c bitmapPseudoMerge.tags.maxMerges=1 \
+ repack -adb &&
+
+ git for-each-ref --format="%(objectname) %(refname)" >refs &&
+
+ test_pseudo_merges >merges &&
+ for m in $(test_seq 0 $(($(wc -l <merges) - 1)))
+ do
+ test_pseudo_merge_commits $m >oids &&
+ grep -f oids refs |
+ perl -lne "print \$1 if /refs\/remotes\/([0-9]+)/" |
+ sort -u || return 1
+ done >remotes &&
+
+ test $(wc -l <remotes) -eq $(sort -u <remotes | wc -l)
+ )
+'
+
+test_expect_success 'pseudo-merge overlap setup' '
+ git init pseudo-merge-overlap &&
+ (
+ cd pseudo-merge-overlap &&
+
+ test_commit_bulk 256 &&
+ tag_everything &&
+
+ git \
+ -c bitmapPseudoMerge.all.pattern="refs/" \
+ -c bitmapPseudoMerge.all.maxMerges=1 \
+ -c bitmapPseudoMerge.all.stableThreshold=never \
+ -c bitmapPseudoMerge.tags.pattern="refs/tags/" \
+ -c bitmapPseudoMerge.tags.maxMerges=1 \
+ -c bitmapPseudoMerge.tags.stableThreshold=never \
+ repack -adb
+ )
+'
+
+test_expect_success 'pseudo-merge overlap generates overlapping groups' '
+ (
+ cd pseudo-merge-overlap &&
+
+ test_pseudo_merges >merges &&
+ test_line_count = 2 merges &&
+
+ test_pseudo_merge_commits 0 >commits-0.raw &&
+ test_pseudo_merge_commits 1 >commits-1.raw &&
+
+ sort commits-0.raw >commits-0 &&
+ sort commits-1.raw >commits-1 &&
+
+ comm -12 commits-0 commits-1 >overlap &&
+
+ test_line_count -gt 0 overlap
+ )
+'
+
+test_expect_success 'pseudo-merge overlap traversal' '
+ (
+ cd pseudo-merge-overlap &&
+
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT=$PWD/trace2.txt \
+ git rev-list --count --all --objects --use-bitmap-index >actual &&
+ git rev-list --count --all --objects >expect &&
+
+ test_pseudo_merges_satisfied 2 <trace2.txt &&
+ test_pseudo_merges_cascades 1 <trace2.txt &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'pseudo-merge overlap stale traversal' '
+ (
+ cd pseudo-merge-overlap &&
+
+ test_commit other &&
+
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT=$PWD/trace2.txt \
+ git rev-list --count --all --objects --use-bitmap-index >actual &&
+ git rev-list --count --all --objects >expect &&
+
+ test_pseudo_merges_satisfied 2 <trace2.txt &&
+ test_pseudo_merges_cascades 1 <trace2.txt &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'pseudo-merge reuse' '
+ git init pseudo-merge-reuse &&
+ (
+ cd pseudo-merge-reuse &&
+
+ stable="1641013200" && # 2022-01-01
+ unstable="1672549200" && # 2023-01-01
+
+ for date in $stable $unstable
+ do
+ test_commit_bulk --date "$date +0000" 128 &&
+ test_tick || return 1
+ done &&
+
+ tag_everything &&
+
+ git \
+ -c bitmapPseudoMerge.test.pattern="refs/tags/" \
+ -c bitmapPseudoMerge.test.maxMerges=1 \
+ -c bitmapPseudoMerge.test.threshold=now \
+ -c bitmapPseudoMerge.test.stableThreshold=$(($unstable - 1)) \
+ -c bitmapPseudoMerge.test.stableSize=512 \
+ repack -adb &&
+
+ test_pseudo_merges >merges &&
+ test_line_count = 2 merges &&
+
+ test_pseudo_merge_commits 0 >stable-oids.before &&
+ test_pseudo_merge_commits 1 >unstable-oids.before &&
+
+ : >trace2.txt &&
+ GIT_TRACE2_EVENT=$PWD/trace2.txt git \
+ -c bitmapPseudoMerge.test.pattern="refs/tags/" \
+ -c bitmapPseudoMerge.test.maxMerges=2 \
+ -c bitmapPseudoMerge.test.threshold=now \
+ -c bitmapPseudoMerge.test.stableThreshold=$(($unstable - 1)) \
+ -c bitmapPseudoMerge.test.stableSize=512 \
+ repack -adb &&
+
+ test_pseudo_merges_reused 1 <trace2.txt &&
+
+ test_pseudo_merges >merges &&
+ test_line_count = 3 merges &&
+
+ test_pseudo_merge_commits 0 >stable-oids.after &&
+ for i in 1 2
+ do
+ test_pseudo_merge_commits $i || return 1
+ done >unstable-oids.after &&
+
+ sort -u <stable-oids.before >expect &&
+ sort -u <stable-oids.after >actual &&
+ test_cmp expect actual &&
+
+ sort -u <unstable-oids.before >expect &&
+ sort -u <unstable-oids.after >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_done
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 33d34d5ae9..3b3991ab86 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -518,7 +518,7 @@ test_expect_success 'fetch with a non-applying branch.<name>.merge' '
test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [1]' '
one_head=$(cd one && git rev-parse HEAD) &&
this_head=$(git rev-parse HEAD) &&
- git update-ref -d FETCH_HEAD &&
+ rm .git/FETCH_HEAD &&
git fetch one &&
test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
test $this_head = "$(git rev-parse --verify HEAD)"
@@ -530,7 +530,7 @@ test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge
one_ref=$(cd one && git symbolic-ref HEAD) &&
git config branch.main.remote blub &&
git config branch.main.merge "$one_ref" &&
- git update-ref -d FETCH_HEAD &&
+ rm .git/FETCH_HEAD &&
git fetch one &&
test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
test $this_head = "$(git rev-parse --verify HEAD)"
@@ -540,7 +540,7 @@ test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge
# the merge spec does not match the branch the remote HEAD points to
test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge [3]' '
git config branch.main.merge "${one_ref}_not" &&
- git update-ref -d FETCH_HEAD &&
+ rm .git/FETCH_HEAD &&
git fetch one &&
test $one_head = "$(git rev-parse --verify FETCH_HEAD)" &&
test $this_head = "$(git rev-parse --verify HEAD)"
@@ -1091,6 +1091,22 @@ test_expect_success 'branchname D/F conflict resolved by --prune' '
test_cmp expect actual
'
+test_expect_success 'branchname D/F conflict rejected with targeted error message' '
+ git clone . df-conflict-error &&
+ git branch dir_conflict &&
+ (
+ cd df-conflict-error &&
+ git update-ref refs/remotes/origin/dir_conflict/file HEAD &&
+ test_must_fail git fetch 2>err &&
+ test_grep "error: some local refs could not be updated; try running" err &&
+ test_grep " ${SQ}git remote prune origin${SQ} to remove any old, conflicting branches" err &&
+ git pack-refs --all &&
+ test_must_fail git fetch 2>err-packed &&
+ test_grep "error: some local refs could not be updated; try running" err-packed &&
+ test_grep " ${SQ}git remote prune origin${SQ} to remove any old, conflicting branches" err-packed
+ )
+'
+
test_expect_success 'fetching a one-level ref works' '
test_commit extra &&
git reset --hard HEAD^ &&
@@ -1252,6 +1268,30 @@ EOF
test_cmp fatal-expect fatal-actual
'
+test_expect_success SYMLINKS 'clone does not get confused by a D/F conflict' '
+ git init df-conflict &&
+ (
+ cd df-conflict &&
+ ln -s .git a &&
+ git add a &&
+ test_tick &&
+ git commit -m symlink &&
+ test_commit a- &&
+ rm a &&
+ mkdir -p a/hooks &&
+ write_script a/hooks/post-checkout <<-EOF &&
+ echo WHOOPSIE >&2
+ echo whoopsie >"$TRASH_DIRECTORY"/whoops
+ EOF
+ git add a/hooks/post-checkout &&
+ test_tick &&
+ git commit -m post-checkout
+ ) &&
+ git clone df-conflict clone 2>err &&
+ test_grep ! WHOOPS err &&
+ test_path_is_missing whoops
+'
+
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh
index 4c3b32785d..5f16cbc58d 100755
--- a/t/t5550-http-fetch-dumb.sh
+++ b/t/t5550-http-fetch-dumb.sh
@@ -55,6 +55,21 @@ test_expect_success 'list refs from outside any repository' '
test_cmp expect actual
'
+
+test_expect_success 'list detached HEAD from outside any repository' '
+ git clone --mirror "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
+ "$HTTPD_DOCUMENT_ROOT_PATH/repo-detached.git" &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo-detached.git" \
+ update-ref --no-deref HEAD refs/heads/main &&
+ git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo-detached.git" update-server-info &&
+ cat >expect <<-EOF &&
+ $(git rev-parse main) HEAD
+ $(git rev-parse main) refs/heads/main
+ EOF
+ nongit git ls-remote "$HTTPD_URL/dumb/repo-detached.git" >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'create password-protected repository' '
mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/" &&
cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
diff --git a/t/t5563-simple-http-auth.sh b/t/t5563-simple-http-auth.sh
index ab8a721ccc..5d5caa3f58 100755
--- a/t/t5563-simple-http-auth.sh
+++ b/t/t5563-simple-http-auth.sh
@@ -21,9 +21,17 @@ test_expect_success 'setup_credential_helper' '
CREDENTIAL_HELPER="$TRASH_DIRECTORY/bin/git-credential-test-helper" &&
write_script "$CREDENTIAL_HELPER" <<-\EOF
cmd=$1
- teefile=$cmd-query.cred
+ teefile=$cmd-query-temp.cred
catfile=$cmd-reply.cred
sed -n -e "/^$/q" -e "p" >>$teefile
+ state=$(sed -ne "s/^state\[\]=helper://p" "$teefile")
+ if test -z "$state"
+ then
+ mv "$teefile" "$cmd-query.cred"
+ else
+ mv "$teefile" "$cmd-query-$state.cred"
+ catfile="$cmd-reply-$state.cred"
+ fi
if test "$cmd" = "get"
then
cat $catfile
@@ -32,13 +40,15 @@ test_expect_success 'setup_credential_helper' '
'
set_credential_reply () {
- cat >"$TRASH_DIRECTORY/$1-reply.cred"
+ local suffix="$(test -n "$2" && echo "-$2")"
+ cat >"$TRASH_DIRECTORY/$1-reply$suffix.cred"
}
expect_credential_query () {
- cat >"$TRASH_DIRECTORY/$1-expect.cred" &&
- test_cmp "$TRASH_DIRECTORY/$1-expect.cred" \
- "$TRASH_DIRECTORY/$1-query.cred"
+ local suffix="$(test -n "$2" && echo "-$2")"
+ cat >"$TRASH_DIRECTORY/$1-expect$suffix.cred" &&
+ test_cmp "$TRASH_DIRECTORY/$1-expect$suffix.cred" \
+ "$TRASH_DIRECTORY/$1-query$suffix.cred"
}
per_test_cleanup () {
@@ -63,17 +73,20 @@ test_expect_success 'access using basic auth' '
# Basic base64(alice:secret-passwd)
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
- Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
EOF
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
- WWW-Authenticate: Basic realm="example.com"
+ id=1 status=200
+ id=default response=WWW-Authenticate: Basic realm="example.com"
EOF
test_config_global credential.helper test-helper &&
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
protocol=http
host=$HTTPD_DEST
wwwauth[]=Basic realm="example.com"
@@ -87,6 +100,45 @@ test_expect_success 'access using basic auth' '
EOF
'
+test_expect_success 'access using basic auth via authtype' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ capability[]=authtype
+ authtype=Basic
+ credential=YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ # Basic base64(alice:secret-passwd)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ EOF
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ id=1 status=200
+ id=default response=WWW-Authenticate: Basic realm="example.com"
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ GIT_CURL_VERBOSE=1 git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=Basic realm="example.com"
+ EOF
+
+ expect_credential_query store <<-EOF
+ capability[]=authtype
+ authtype=Basic
+ credential=YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ protocol=http
+ host=$HTTPD_DEST
+ EOF
+'
+
test_expect_success 'access using basic auth invalid credentials' '
test_when_finished "per_test_cleanup" &&
@@ -97,17 +149,20 @@ test_expect_success 'access using basic auth invalid credentials' '
# Basic base64(alice:secret-passwd)
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
- Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
EOF
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
- WWW-Authenticate: Basic realm="example.com"
+ id=1 status=200
+ id=default response=WWW-Authenticate: Basic realm="example.com"
EOF
test_config_global credential.helper test-helper &&
test_must_fail git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
protocol=http
host=$HTTPD_DEST
wwwauth[]=Basic realm="example.com"
@@ -132,19 +187,22 @@ test_expect_success 'access using basic auth with extra challenges' '
# Basic base64(alice:secret-passwd)
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
- Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
EOF
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
- WWW-Authenticate: FooBar param1="value1" param2="value2"
- WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
- WWW-Authenticate: Basic realm="example.com"
+ id=1 status=200
+ id=default response=WWW-Authenticate: FooBar param1="value1" param2="value2"
+ id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
+ id=default response=WWW-Authenticate: Basic realm="example.com"
EOF
test_config_global credential.helper test-helper &&
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
protocol=http
host=$HTTPD_DEST
wwwauth[]=FooBar param1="value1" param2="value2"
@@ -170,19 +228,22 @@ test_expect_success 'access using basic auth mixed-case wwwauth header name' '
# Basic base64(alice:secret-passwd)
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
- Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
EOF
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
- www-authenticate: foobar param1="value1" param2="value2"
- WWW-AUTHENTICATE: BEARER authorize_uri="id.example.com" p=1 q=0
- WwW-aUtHeNtIcAtE: baSiC realm="example.com"
+ id=1 status=200
+ id=default response=www-authenticate: foobar param1="value1" param2="value2"
+ id=default response=WWW-AUTHENTICATE: BEARER authorize_uri="id.example.com" p=1 q=0
+ id=default response=WwW-aUtHeNtIcAtE: baSiC realm="example.com"
EOF
test_config_global credential.helper test-helper &&
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
protocol=http
host=$HTTPD_DEST
wwwauth[]=foobar param1="value1" param2="value2"
@@ -208,24 +269,27 @@ test_expect_success 'access using basic auth with wwwauth header continuations'
# Basic base64(alice:secret-passwd)
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
- Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
EOF
# Note that leading and trailing whitespace is important to correctly
# simulate a continuation/folded header.
cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
- WWW-Authenticate: FooBar param1="value1"
- param2="value2"
- WWW-Authenticate: Bearer authorize_uri="id.example.com"
- p=1
- q=0
- WWW-Authenticate: Basic realm="example.com"
+ id=1 status=200
+ id=default response=WWW-Authenticate: FooBar param1="value1"
+ id=default response= param2="value2"
+ id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com"
+ id=default response= p=1
+ id=default response= q=0
+ id=default response=WWW-Authenticate: Basic realm="example.com"
EOF
test_config_global credential.helper test-helper &&
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
protocol=http
host=$HTTPD_DEST
wwwauth[]=FooBar param1="value1" param2="value2"
@@ -251,26 +315,29 @@ test_expect_success 'access using basic auth with wwwauth header empty continuat
# Basic base64(alice:secret-passwd)
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
- Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
EOF
CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
# Note that leading and trailing whitespace is important to correctly
# simulate a continuation/folded header.
- printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >"$CHALLENGE" &&
- printf " \r\n" >>"$CHALLENGE" &&
- printf " param2=\"value2\"\r\n" >>"$CHALLENGE" &&
- printf "WWW-Authenticate: Bearer authorize_uri=\"id.example.com\"\r\n" >>"$CHALLENGE" &&
- printf " p=1\r\n" >>"$CHALLENGE" &&
- printf " \r\n" >>"$CHALLENGE" &&
- printf " q=0\r\n" >>"$CHALLENGE" &&
- printf "WWW-Authenticate: Basic realm=\"example.com\"\r\n" >>"$CHALLENGE" &&
+ printf "id=1 status=200\n" >"$CHALLENGE" &&
+ printf "id=default response=WWW-Authenticate: FooBar param1=\"value1\"\r\n" >>"$CHALLENGE" &&
+ printf "id=default response= \r\n" >>"$CHALLENGE" &&
+ printf "id=default response= param2=\"value2\"\r\n" >>"$CHALLENGE" &&
+ printf "id=default response=WWW-Authenticate: Bearer authorize_uri=\"id.example.com\"\r\n" >>"$CHALLENGE" &&
+ printf "id=default response= p=1\r\n" >>"$CHALLENGE" &&
+ printf "id=default response= \r\n" >>"$CHALLENGE" &&
+ printf "id=default response= q=0\r\n" >>"$CHALLENGE" &&
+ printf "id=default response=WWW-Authenticate: Basic realm=\"example.com\"\r\n" >>"$CHALLENGE" &&
test_config_global credential.helper test-helper &&
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
protocol=http
host=$HTTPD_DEST
wwwauth[]=FooBar param1="value1" param2="value2"
@@ -296,22 +363,25 @@ test_expect_success 'access using basic auth with wwwauth header mixed line-endi
# Basic base64(alice:secret-passwd)
cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
- Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
+ id=1 creds=Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA==
EOF
CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
# Note that leading and trailing whitespace is important to correctly
# simulate a continuation/folded header.
- printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >"$CHALLENGE" &&
- printf " \r\n" >>"$CHALLENGE" &&
- printf "\tparam2=\"value2\"\r\n" >>"$CHALLENGE" &&
- printf "WWW-Authenticate: Basic realm=\"example.com\"" >>"$CHALLENGE" &&
+ printf "id=1 status=200\n" >"$CHALLENGE" &&
+ printf "id=default response=WWW-Authenticate: FooBar param1=\"value1\"\r\n" >>"$CHALLENGE" &&
+ printf "id=default response= \r\n" >>"$CHALLENGE" &&
+ printf "id=default response=\tparam2=\"value2\"\r\n" >>"$CHALLENGE" &&
+ printf "id=default response=WWW-Authenticate: Basic realm=\"example.com\"" >>"$CHALLENGE" &&
test_config_global credential.helper test-helper &&
git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
protocol=http
host=$HTTPD_DEST
wwwauth[]=FooBar param1="value1" param2="value2"
@@ -326,4 +396,166 @@ test_expect_success 'access using basic auth with wwwauth header mixed line-endi
EOF
'
+test_expect_success 'access using bearer auth' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ capability[]=authtype
+ authtype=Bearer
+ credential=YS1naXQtdG9rZW4=
+ EOF
+
+ # Basic base64(a-git-token)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ id=1 creds=Bearer YS1naXQtdG9rZW4=
+ EOF
+
+ CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ id=1 status=200
+ id=default response=WWW-Authenticate: FooBar param1="value1" param2="value2"
+ id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
+ id=default response=WWW-Authenticate: Basic realm="example.com"
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=FooBar param1="value1" param2="value2"
+ wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
+ wwwauth[]=Basic realm="example.com"
+ EOF
+
+ expect_credential_query store <<-EOF
+ capability[]=authtype
+ authtype=Bearer
+ credential=YS1naXQtdG9rZW4=
+ protocol=http
+ host=$HTTPD_DEST
+ EOF
+'
+
+test_expect_success 'access using bearer auth with invalid credentials' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ capability[]=authtype
+ authtype=Bearer
+ credential=incorrect-token
+ EOF
+
+ # Basic base64(a-git-token)
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ id=1 creds=Bearer YS1naXQtdG9rZW4=
+ EOF
+
+ CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ id=1 status=200
+ id=default response=WWW-Authenticate: FooBar param1="value1" param2="value2"
+ id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
+ id=default response=WWW-Authenticate: Basic realm="example.com"
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ test_must_fail git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=FooBar param1="value1" param2="value2"
+ wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
+ wwwauth[]=Basic realm="example.com"
+ EOF
+
+ expect_credential_query erase <<-EOF
+ capability[]=authtype
+ authtype=Bearer
+ credential=incorrect-token
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=FooBar param1="value1" param2="value2"
+ wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
+ wwwauth[]=Basic realm="example.com"
+ EOF
+'
+
+test_expect_success 'access using three-legged auth' '
+ test_when_finished "per_test_cleanup" &&
+
+ set_credential_reply get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ authtype=Multistage
+ credential=YS1naXQtdG9rZW4=
+ state[]=helper:foobar
+ continue=1
+ EOF
+
+ set_credential_reply get foobar <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ authtype=Multistage
+ credential=YW5vdGhlci10b2tlbg==
+ state[]=helper:bazquux
+ EOF
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF &&
+ id=1 creds=Multistage YS1naXQtdG9rZW4=
+ id=2 creds=Multistage YW5vdGhlci10b2tlbg==
+ EOF
+
+ CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" &&
+
+ cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF &&
+ id=1 status=401 response=WWW-Authenticate: Multistage challenge="456"
+ id=1 status=401 response=WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
+ id=2 status=200
+ id=default response=WWW-Authenticate: Multistage challenge="123"
+ id=default response=WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0
+ EOF
+
+ test_config_global credential.helper test-helper &&
+ git ls-remote "$HTTPD_URL/custom_auth/repo.git" &&
+
+ expect_credential_query get <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=Multistage challenge="123"
+ wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
+ EOF
+
+ expect_credential_query get foobar <<-EOF &&
+ capability[]=authtype
+ capability[]=state
+ authtype=Multistage
+ protocol=http
+ host=$HTTPD_DEST
+ wwwauth[]=Multistage challenge="456"
+ wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0
+ state[]=helper:foobar
+ EOF
+
+ expect_credential_query store bazquux <<-EOF
+ capability[]=authtype
+ capability[]=state
+ authtype=Multistage
+ credential=YW5vdGhlci10b2tlbg==
+ protocol=http
+ host=$HTTPD_DEST
+ state[]=helper:bazquux
+ EOF
+'
+
test_done
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index ca43185681..deb1c282c7 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -650,6 +650,21 @@ test_expect_success CASE_INSENSITIVE_FS 'colliding file detection' '
test_grep "the following paths have collided" icasefs/warning
'
+test_expect_success CASE_INSENSITIVE_FS,SYMLINKS \
+ 'colliding symlink/directory keeps directory' '
+ git init icasefs-colliding-symlink &&
+ (
+ cd icasefs-colliding-symlink &&
+ a=$(printf a | git hash-object -w --stdin) &&
+ printf "100644 %s 0\tA/dir/b\n120000 %s 0\ta\n" $a $a >idx &&
+ git update-index --index-info <idx &&
+ test_tick &&
+ git commit -m initial
+ ) &&
+ git clone icasefs-colliding-symlink icasefs-colliding-symlink-clone &&
+ test_file_not_empty icasefs-colliding-symlink-clone/A/dir/b
+'
+
test_expect_success 'clone with GIT_DEFAULT_HASH' '
(
sane_unset GIT_DEFAULT_HASH &&
@@ -773,6 +788,57 @@ test_expect_success 'batch missing blob request does not inadvertently try to fe
git clone --filter=blob:limit=0 "file://$(pwd)/server" client
'
+test_expect_success 'clone with init.templatedir runs hooks' '
+ git init tmpl/hooks &&
+ write_script tmpl/hooks/post-checkout <<-EOF &&
+ echo HOOK-RUN >&2
+ echo I was here >hook.run
+ EOF
+ git -C tmpl/hooks add . &&
+ test_tick &&
+ git -C tmpl/hooks commit -m post-checkout &&
+
+ test_when_finished "git config --global --unset init.templateDir || :" &&
+ test_when_finished "git config --unset init.templateDir || :" &&
+ (
+ sane_unset GIT_TEMPLATE_DIR &&
+ NO_SET_GIT_TEMPLATE_DIR=t &&
+ export NO_SET_GIT_TEMPLATE_DIR &&
+
+ git -c core.hooksPath="$(pwd)/tmpl/hooks" \
+ clone tmpl/hooks hook-run-hookspath 2>err &&
+ test_grep ! "active .* hook found" err &&
+ test_path_is_file hook-run-hookspath/hook.run &&
+
+ git -c init.templateDir="$(pwd)/tmpl" \
+ clone tmpl/hooks hook-run-config 2>err &&
+ test_grep ! "active .* hook found" err &&
+ test_path_is_file hook-run-config/hook.run &&
+
+ git clone --template=tmpl tmpl/hooks hook-run-option 2>err &&
+ test_grep ! "active .* hook found" err &&
+ test_path_is_file hook-run-option/hook.run &&
+
+ git config --global init.templateDir "$(pwd)/tmpl" &&
+ git clone tmpl/hooks hook-run-global-config 2>err &&
+ git config --global --unset init.templateDir &&
+ test_grep ! "active .* hook found" err &&
+ test_path_is_file hook-run-global-config/hook.run &&
+
+ # clone ignores local `init.templateDir`; need to create
+ # a new repository because we deleted `.git/` in the
+ # `setup` test case above
+ git init local-clone &&
+ cd local-clone &&
+
+ git config init.templateDir "$(pwd)/../tmpl" &&
+ git clone ../tmpl/hooks hook-run-local-config 2>err &&
+ git config --unset init.templateDir &&
+ test_grep ! "active .* hook found" err &&
+ test_path_is_missing hook-run-local-config/hook.run
+ )
+'
+
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index 948f1bb5f4..163c378cfd 100755
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -52,6 +52,23 @@ test_expect_success '--include-root-refs pattern prints pseudorefs' '
test_cmp expect actual
'
+test_expect_success '--include-root-refs pattern does not print special refs' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ git rev-parse HEAD >.git/MERGE_HEAD &&
+ git for-each-ref --format="%(refname)" --include-root-refs >actual &&
+ cat >expect <<-EOF &&
+ HEAD
+ $(git symbolic-ref HEAD)
+ refs/tags/initial
+ EOF
+ test_cmp expect actual
+ )
+'
+
test_expect_success '--include-root-refs with other patterns' '
cat >expect <<-\EOF &&
HEAD
@@ -62,6 +79,23 @@ test_expect_success '--include-root-refs with other patterns' '
test_cmp expect actual
'
+test_expect_success '--include-root-refs omits dangling symrefs' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ git symbolic-ref DANGLING_HEAD refs/heads/missing &&
+ cat >expect <<-EOF &&
+ HEAD
+ $(git symbolic-ref HEAD)
+ refs/tags/initial
+ EOF
+ git for-each-ref --format="%(refname)" --include-root-refs >actual &&
+ test_cmp expect actual
+ )
+'
+
test_expect_success 'filtering with --points-at' '
cat >expect <<-\EOF &&
refs/heads/main
diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh
index 43d40175f8..ef9e3c0b89 100755
--- a/t/t6500-gc.sh
+++ b/t/t6500-gc.sh
@@ -379,7 +379,6 @@ test_expect_success 'background auto gc respects lock for all operations' '
# now fake a concurrent gc that holds the lock; we can use our
# shell pid so that it looks valid.
- hostname=$(hostname || echo unknown) &&
shell_pid=$$ &&
if test_have_prereq MINGW && test -f /proc/$shell_pid/winpid
then
@@ -388,7 +387,7 @@ test_expect_success 'background auto gc respects lock for all operations' '
# the Windows PID in this case.
shell_pid=$(cat /proc/$shell_pid/winpid)
fi &&
- printf "%d %s" "$shell_pid" "$hostname" >.git/gc.pid &&
+ printf "%d %s" "$shell_pid" "$(test-tool xgethostname)" >.git/gc.pid &&
# our gc should exit zero without doing anything
run_and_wait_for_auto_gc &&
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 696866d779..fa6336edf9 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -668,6 +668,115 @@ test_expect_success \
test_cmp expect actual
'
+# trailers
+
+test_expect_success 'create tag with -m and --trailer' '
+ get_tag_header tag-with-inline-message-and-trailers $commit commit $time >expect &&
+ cat >>expect <<-\EOF &&
+ create tag with trailers
+
+ my-trailer: here
+ alt-trailer: there
+ EOF
+ git tag -m "create tag with trailers" \
+ --trailer my-trailer=here \
+ --trailer alt-trailer=there \
+ tag-with-inline-message-and-trailers &&
+ get_tag_msg tag-with-inline-message-and-trailers >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'list tag extracting trailers' '
+ cat >expect <<-\EOF &&
+ my-trailer: here
+ alt-trailer: there
+
+ EOF
+ git tag --list --format="%(trailers)" tag-with-inline-message-and-trailers >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'create tag with -F and --trailer' '
+ echo "create tag from message file using --trailer" >messagefilewithnotrailers &&
+ get_tag_header tag-with-file-message-and-trailers $commit commit $time >expect &&
+ cat >>expect <<-\EOF &&
+ create tag from message file using --trailer
+
+ my-trailer: here
+ alt-trailer: there
+ EOF
+ git tag -F messagefilewithnotrailers \
+ --trailer my-trailer=here \
+ --trailer alt-trailer=there \
+ tag-with-file-message-and-trailers &&
+ get_tag_msg tag-with-file-message-and-trailers >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'create tag with -m and --trailer and --edit' '
+ write_script fakeeditor <<-\EOF &&
+ sed -e "1s/^/EDITED: /g" <"$1" >"$1-"
+ mv "$1-" "$1"
+ EOF
+ get_tag_header tag-with-edited-inline-message-and-trailers $commit commit $time >expect &&
+ cat >>expect <<-\EOF &&
+ EDITED: create tag with trailers
+
+ my-trailer: here
+ alt-trailer: there
+ EOF
+ GIT_EDITOR=./fakeeditor git tag --edit \
+ -m "create tag with trailers" \
+ --trailer my-trailer=here \
+ --trailer alt-trailer=there \
+ tag-with-edited-inline-message-and-trailers &&
+ get_tag_msg tag-with-edited-inline-message-and-trailers >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'create tag with -F and --trailer and --edit' '
+ echo "create tag from message file using --trailer" >messagefilewithnotrailers &&
+ get_tag_header tag-with-edited-file-message-and-trailers $commit commit $time >expect &&
+ cat >>expect <<-\EOF &&
+ EDITED: create tag from message file using --trailer
+
+ my-trailer: here
+ alt-trailer: there
+ EOF
+ GIT_EDITOR=./fakeeditor git tag --edit \
+ -F messagefilewithnotrailers \
+ --trailer my-trailer=here \
+ --trailer alt-trailer=there \
+ tag-with-edited-file-message-and-trailers &&
+ get_tag_msg tag-with-edited-file-message-and-trailers >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'create annotated tag and force editor when only --trailer is given' '
+ write_script fakeeditor <<-\EOF &&
+ echo "add a line" >"$1-"
+ cat <"$1" >>"$1-"
+ mv "$1-" "$1"
+ EOF
+ get_tag_header tag-with-trailers-and-no-message $commit commit $time >expect &&
+ cat >>expect <<-\EOF &&
+ add a line
+
+ my-trailer: here
+ alt-trailer: there
+ EOF
+ GIT_EDITOR=./fakeeditor git tag \
+ --trailer my-trailer=here \
+ --trailer alt-trailer=there \
+ tag-with-trailers-and-no-message &&
+ get_tag_msg tag-with-trailers-and-no-message >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'bad editor causes panic when only --trailer is given' '
+ test_must_fail env GIT_EDITOR=false git tag --trailer my-trailer=here tag-will-not-exist
+'
+
# listing messages for annotated non-signed tags:
test_expect_success \
@@ -810,6 +919,11 @@ test_expect_success 'git tag --format with ahead-behind' '
refs/tags/tag-lines 0 1 !
refs/tags/tag-one-line 0 1 !
refs/tags/tag-right 0 0 !
+ refs/tags/tag-with-edited-file-message-and-trailers 0 1 !
+ refs/tags/tag-with-edited-inline-message-and-trailers 0 1 !
+ refs/tags/tag-with-file-message-and-trailers 0 1 !
+ refs/tags/tag-with-inline-message-and-trailers 0 1 !
+ refs/tags/tag-with-trailers-and-no-message 0 1 !
refs/tags/tag-zero-lines 0 1 !
EOF
git tag -l --format="%(refname) %(ahead-behind:HEAD) !" >actual 2>err &&
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 5c4a89df5c..981488885f 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -1451,4 +1451,35 @@ test_expect_success 'recursive clone respects -q' '
test_must_be_empty actual
'
+test_expect_success '`submodule init` and `init.templateDir`' '
+ mkdir -p tmpl/hooks &&
+ write_script tmpl/hooks/post-checkout <<-EOF &&
+ echo HOOK-RUN >&2
+ echo I was here >hook.run
+ exit 1
+ EOF
+
+ test_config init.templateDir "$(pwd)/tmpl" &&
+ test_when_finished \
+ "git config --global --unset init.templateDir || true" &&
+ (
+ sane_unset GIT_TEMPLATE_DIR &&
+ NO_SET_GIT_TEMPLATE_DIR=t &&
+ export NO_SET_GIT_TEMPLATE_DIR &&
+
+ git config --global init.templateDir "$(pwd)/tmpl" &&
+ test_must_fail git submodule \
+ add "$submodurl" sub-global 2>err &&
+ git config --global --unset init.templateDir &&
+ test_grep HOOK-RUN err &&
+ test_path_is_file sub-global/hook.run &&
+
+ git config init.templateDir "$(pwd)/tmpl" &&
+ git submodule add "$submodurl" sub-local 2>err &&
+ git config --unset init.templateDir &&
+ test_grep ! HOOK-RUN err &&
+ test_path_is_missing sub-local/hook.run
+ )
+'
+
test_done
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 8491b8c58b..297c6c3b5c 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -1202,4 +1202,52 @@ test_expect_success 'commit with staged submodule change with ignoreSubmodules a
add_submodule_commit_and_validate
'
+test_expect_success CASE_INSENSITIVE_FS,SYMLINKS \
+ 'submodule paths must not follow symlinks' '
+
+ # This is only needed because we want to run this in a self-contained
+ # test without having to spin up an HTTP server; However, it would not
+ # be needed in a real-world scenario where the submodule is simply
+ # hosted on a public site.
+ test_config_global protocol.file.allow always &&
+
+ # Make sure that Git tries to use symlinks on Windows
+ test_config_global core.symlinks true &&
+
+ tell_tale_path="$PWD/tell.tale" &&
+ git init hook &&
+ (
+ cd hook &&
+ mkdir -p y/hooks &&
+ write_script y/hooks/post-checkout <<-EOF &&
+ echo HOOK-RUN >&2
+ echo hook-run >"$tell_tale_path"
+ EOF
+ git add y/hooks/post-checkout &&
+ test_tick &&
+ git commit -m post-checkout
+ ) &&
+
+ hook_repo_path="$(pwd)/hook" &&
+ git init captain &&
+ (
+ cd captain &&
+ git submodule add --name x/y "$hook_repo_path" A/modules/x &&
+ test_tick &&
+ git commit -m add-submodule &&
+
+ printf .git >dotgit.txt &&
+ git hash-object -w --stdin <dotgit.txt >dot-git.hash &&
+ printf "120000 %s 0\ta\n" "$(cat dot-git.hash)" >index.info &&
+ git update-index --index-info <index.info &&
+ test_tick &&
+ git commit -m add-symlink
+ ) &&
+
+ test_path_is_missing "$tell_tale_path" &&
+ git clone --recursive captain hooked 2>err &&
+ test_grep ! HOOK-RUN err &&
+ test_path_is_missing "$tell_tale_path"
+'
+
test_done
diff --git a/t/t7423-submodule-symlinks.sh b/t/t7423-submodule-symlinks.sh
new file mode 100755
index 0000000000..3d3c7af3ce
--- /dev/null
+++ b/t/t7423-submodule-symlinks.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+test_description='check that submodule operations do not follow symlinks'
+
+. ./test-lib.sh
+
+test_expect_success 'prepare' '
+ git config --global protocol.file.allow always &&
+ test_commit initial &&
+ git init upstream &&
+ test_commit -C upstream upstream submodule_file &&
+ git submodule add ./upstream a/sm &&
+ test_tick &&
+ git commit -m submodule
+'
+
+test_expect_success SYMLINKS 'git submodule update must not create submodule behind symlink' '
+ rm -rf a b &&
+ mkdir b &&
+ ln -s b a &&
+ test_path_is_missing b/sm &&
+ test_must_fail git submodule update &&
+ test_path_is_missing b/sm
+'
+
+test_expect_success SYMLINKS,CASE_INSENSITIVE_FS 'git submodule update must not create submodule behind symlink on case insensitive fs' '
+ rm -rf a b &&
+ mkdir b &&
+ ln -s b A &&
+ test_must_fail git submodule update &&
+ test_path_is_missing b/sm
+'
+
+prepare_symlink_to_repo() {
+ rm -rf a &&
+ mkdir a &&
+ git init a/target &&
+ git -C a/target fetch ../../upstream &&
+ ln -s target a/sm
+}
+
+test_expect_success SYMLINKS 'git restore --recurse-submodules must not be confused by a symlink' '
+ prepare_symlink_to_repo &&
+ test_must_fail git restore --recurse-submodules a/sm &&
+ test_path_is_missing a/sm/submodule_file &&
+ test_path_is_dir a/target/.git &&
+ test_path_is_missing a/target/submodule_file
+'
+
+test_expect_success SYMLINKS 'git restore --recurse-submodules must not migrate git dir of symlinked repo' '
+ prepare_symlink_to_repo &&
+ rm -rf .git/modules &&
+ test_must_fail git restore --recurse-submodules a/sm &&
+ test_path_is_dir a/target/.git &&
+ test_path_is_missing .git/modules/a/sm &&
+ test_path_is_missing a/target/submodule_file
+'
+
+test_expect_success SYMLINKS 'git checkout -f --recurse-submodules must not migrate git dir of symlinked repo when removing submodule' '
+ prepare_symlink_to_repo &&
+ rm -rf .git/modules &&
+ test_must_fail git checkout -f --recurse-submodules initial &&
+ test_path_is_dir a/target/.git &&
+ test_path_is_missing .git/modules/a/sm
+'
+
+test_done
diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh
index 46d4fb0354..4a9c22c9e2 100755
--- a/t/t7450-bad-git-dotfiles.sh
+++ b/t/t7450-bad-git-dotfiles.sh
@@ -320,7 +320,7 @@ test_expect_success WINDOWS 'prevent git~1 squatting on Windows' '
fi
'
-test_expect_success 'git dirs of sibling submodules must not be nested' '
+test_expect_success 'setup submodules with nested git dirs' '
git init nested &&
test_commit -C nested nested &&
(
@@ -338,9 +338,39 @@ test_expect_success 'git dirs of sibling submodules must not be nested' '
git add .gitmodules thing1 thing2 &&
test_tick &&
git commit -m nested
- ) &&
+ )
+'
+
+test_expect_success 'git dirs of sibling submodules must not be nested' '
test_must_fail git clone --recurse-submodules nested clone 2>err &&
test_grep "is inside git dir" err
'
+test_expect_success 'submodule git dir nesting detection must work with parallel cloning' '
+ test_must_fail git clone --recurse-submodules --jobs=2 nested clone_parallel 2>err &&
+ cat err &&
+ grep -E "(already exists|is inside git dir|not a git repository)" err &&
+ {
+ test_path_is_missing .git/modules/hippo/HEAD ||
+ test_path_is_missing .git/modules/hippo/hooks/HEAD
+ }
+'
+
+test_expect_success 'checkout -f --recurse-submodules must not use a nested gitdir' '
+ git clone nested nested_checkout &&
+ (
+ cd nested_checkout &&
+ git submodule init &&
+ git submodule update thing1 &&
+ mkdir -p .git/modules/hippo/hooks/refs &&
+ mkdir -p .git/modules/hippo/hooks/objects/info &&
+ echo "../../../../objects" >.git/modules/hippo/hooks/objects/info/alternates &&
+ echo "ref: refs/heads/master" >.git/modules/hippo/hooks/HEAD
+ ) &&
+ test_must_fail git -C nested_checkout checkout -f --recurse-submodules HEAD 2>err &&
+ cat err &&
+ grep "is inside git dir" err &&
+ test_path_is_missing nested_checkout/thing2/.git
+'
+
test_done
diff --git a/t/t7514-commit-patch.sh b/t/t7514-commit-patch.sh
index b4de10a5dd..03ba0c0e73 100755
--- a/t/t7514-commit-patch.sh
+++ b/t/t7514-commit-patch.sh
@@ -1,6 +1,8 @@
#!/bin/sh
test_description='hunk edit with "commit -p -m"'
+
+TEST_PASSES_SANITIZE_LEAK=true
. ./test-lib.sh
test_expect_success 'setup (initial)' '
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 0943dfa18a..8595489ceb 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -639,9 +639,9 @@ test_expect_success 'start from empty cron table' '
# start registers the repo
git config --get --global --fixed-value maintenance.repo "$(pwd)" &&
- grep "for-each-repo --config=maintenance.repo maintenance run --schedule=daily" cron.txt &&
- grep "for-each-repo --config=maintenance.repo maintenance run --schedule=hourly" cron.txt &&
- grep "for-each-repo --config=maintenance.repo maintenance run --schedule=weekly" cron.txt
+ grep "for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=daily" cron.txt &&
+ grep "for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=hourly" cron.txt &&
+ grep "for-each-repo --keep-going --config=maintenance.repo maintenance run --schedule=weekly" cron.txt
'
test_expect_success 'stop from existing schedule' '
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 5a771000c9..a5cb198a5c 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -208,6 +208,7 @@ cat >expected-show-all-headers <<\EOF
(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
+
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
@@ -821,6 +822,7 @@ cat >expected-suppress-sob <<\EOF
(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
+
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
@@ -869,6 +871,7 @@ cat >expected-suppress-sob <<\EOF
(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
+
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
@@ -904,6 +907,7 @@ cat >expected-suppress-cccmd <<\EOF
(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
+
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
@@ -940,6 +944,7 @@ test_expect_success $PREREQ 'sendemail.cccmd' '
test_expect_success $PREREQ 'setup expect' '
cat >expected-suppress-all <<\EOF
0001-Second.patch
+
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
@@ -968,6 +973,7 @@ cat >expected-suppress-body <<\EOF
(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
(cc-cmd) Adding cc: cc-cmd@example.com from: './cccmd'
+
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
@@ -1003,6 +1009,7 @@ cat >expected-suppress-body-cccmd <<\EOF
(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
+
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
@@ -1036,6 +1043,7 @@ cat >expected-suppress-sob <<\EOF
(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
+
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
@@ -1071,6 +1079,7 @@ cat >expected-suppress-bodycc <<\EOF
(mbox) Adding cc: One <one@example.com> from line 'Cc: One <one@example.com>, two@example.com'
(mbox) Adding cc: two@example.com from line 'Cc: One <one@example.com>, two@example.com'
(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
+
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
@@ -1105,6 +1114,7 @@ cat >expected-suppress-cc <<\EOF
0001-Second.patch
(mbox) Adding cc: A <author@example.com> from line 'From: A <author@example.com>'
(body) Adding cc: C O Mitter <committer@example.com> from line 'Signed-off-by: C O Mitter <committer@example.com>'
+
Dry-OK. Log says:
Server: relay.example.com
MAIL FROM:<from@example.com>
diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh
index 428339e342..a41b4fcc08 100755
--- a/t/t9210-scalar.sh
+++ b/t/t9210-scalar.sh
@@ -180,6 +180,44 @@ test_expect_success 'scalar reconfigure' '
test true = "$(git -C one/src config core.preloadIndex)"
'
+test_expect_success 'scalar reconfigure --all with includeIf.onbranch' '
+ repos="two three four" &&
+ for num in $repos
+ do
+ git init $num/src &&
+ scalar register $num/src &&
+ git -C $num/src config includeif."onbranch:foo".path something &&
+ git -C $num/src config core.preloadIndex false || return 1
+ done &&
+
+ scalar reconfigure --all &&
+
+ for num in $repos
+ do
+ test true = "$(git -C $num/src config core.preloadIndex)" || return 1
+ done
+'
+
+ test_expect_success 'scalar reconfigure --all with detached HEADs' '
+ repos="two three four" &&
+ for num in $repos
+ do
+ rm -rf $num/src &&
+ git init $num/src &&
+ scalar register $num/src &&
+ git -C $num/src config core.preloadIndex false &&
+ test_commit -C $num/src initial &&
+ git -C $num/src switch --detach HEAD || return 1
+ done &&
+
+ scalar reconfigure --all &&
+
+ for num in $repos
+ do
+ test true = "$(git -C $num/src config core.preloadIndex)" || return 1
+ done
+'
+
test_expect_success '`reconfigure -a` removes stale config entries' '
git init stale/src &&
scalar register stale &&
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 569cf23104..963f865f27 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2518,6 +2518,29 @@ test_expect_success 'complete tree filename with metacharacters' '
EOF
'
+test_expect_success 'symbolic-ref completes builtin options' '
+ test_completion "git symbolic-ref --d" <<-\EOF
+ --delete Z
+ EOF
+'
+
+test_expect_success 'symbolic-ref completes short ref names' '
+ test_completion "git symbolic-ref foo m" <<-\EOF
+ main Z
+ mybranch Z
+ mytag Z
+ EOF
+'
+
+test_expect_success 'symbolic-ref completes full ref names' '
+ test_completion "git symbolic-ref foo refs/" <<-\EOF
+ refs/heads/main Z
+ refs/heads/mybranch Z
+ refs/tags/mytag Z
+ refs/tags/A Z
+ EOF
+'
+
test_expect_success PERL 'send-email' '
test_completion "git send-email --cov" <<-\EOF &&
--cover-from-description=Z
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 862d80c974..16fd585e34 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -458,6 +458,7 @@ test_commit_bulk () {
indir=.
ref=HEAD
n=1
+ notick=
message='commit %s'
filename='%s.t'
contents='content %s'
@@ -488,6 +489,12 @@ test_commit_bulk () {
filename="${1#--*=}-%s.t"
contents="${1#--*=} %s"
;;
+ --date)
+ notick=yes
+ GIT_COMMITTER_DATE="$2"
+ GIT_AUTHOR_DATE="$2"
+ shift
+ ;;
-*)
BUG "invalid test_commit_bulk option: $1"
;;
@@ -507,7 +514,10 @@ test_commit_bulk () {
while test "$total" -gt 0
do
- test_tick &&
+ if test -z "$notick"
+ then
+ test_tick
+ fi &&
echo "commit $ref"
printf 'author %s <%s> %s\n' \
"$GIT_AUTHOR_NAME" \
diff --git a/t/unit-tests/t-trailer.c b/t/unit-tests/t-trailer.c
new file mode 100644
index 0000000000..2ecca359d9
--- /dev/null
+++ b/t/unit-tests/t-trailer.c
@@ -0,0 +1,315 @@
+#include "test-lib.h"
+#include "trailer.h"
+
+struct contents {
+ const char *raw;
+ const char *key;
+ const char *val;
+};
+
+static void t_trailer_iterator(const char *msg, size_t num_expected,
+ struct contents *contents)
+{
+ struct trailer_iterator iter;
+ size_t i = 0;
+
+ trailer_iterator_init(&iter, msg);
+ while (trailer_iterator_advance(&iter)) {
+ if (num_expected) {
+ check_str(iter.raw, contents[i].raw);
+ check_str(iter.key.buf, contents[i].key);
+ check_str(iter.val.buf, contents[i].val);
+ }
+ i++;
+ }
+ trailer_iterator_release(&iter);
+
+ check_uint(i, ==, num_expected);
+}
+
+static void run_t_trailer_iterator(void)
+{
+
+ static struct test_cases {
+ const char *name;
+ const char *msg;
+ size_t num_expected;
+ struct contents contents[10];
+ } tc[] = {
+ {
+ "empty input",
+ "",
+ 0,
+ {{0}},
+ },
+ {
+ "no newline at beginning",
+ "Fixes: x\n"
+ "Acked-by: x\n"
+ "Reviewed-by: x\n",
+ 0,
+ {{0}},
+ },
+ {
+ "newline at beginning",
+ "\n"
+ "Fixes: x\n"
+ "Acked-by: x\n"
+ "Reviewed-by: x\n",
+ 3,
+ {
+ {
+ .raw = "Fixes: x\n",
+ .key = "Fixes",
+ .val = "x",
+ },
+ {
+ .raw = "Acked-by: x\n",
+ .key = "Acked-by",
+ .val = "x",
+ },
+ {
+ .raw = "Reviewed-by: x\n",
+ .key = "Reviewed-by",
+ .val = "x",
+ },
+ {
+ 0
+ },
+ },
+ },
+ {
+ "without body text",
+ "subject: foo bar\n"
+ "\n"
+ "Fixes: x\n"
+ "Acked-by: x\n"
+ "Reviewed-by: x\n",
+ 3,
+ {
+ {
+ .raw = "Fixes: x\n",
+ .key = "Fixes",
+ .val = "x",
+ },
+ {
+ .raw = "Acked-by: x\n",
+ .key = "Acked-by",
+ .val = "x",
+ },
+ {
+ .raw = "Reviewed-by: x\n",
+ .key = "Reviewed-by",
+ .val = "x",
+ },
+ {
+ 0
+ },
+ },
+ },
+ {
+ "with body text, without divider",
+ "my subject\n"
+ "\n"
+ "my body which is long\n"
+ "and contains some special\n"
+ "chars like : = ? !\n"
+ "hello\n"
+ "\n"
+ "Fixes: x\n"
+ "Acked-by: x\n"
+ "Reviewed-by: x\n"
+ "Signed-off-by: x\n",
+ 4,
+ {
+ {
+ .raw = "Fixes: x\n",
+ .key = "Fixes",
+ .val = "x",
+ },
+ {
+ .raw = "Acked-by: x\n",
+ .key = "Acked-by",
+ .val = "x",
+ },
+ {
+ .raw = "Reviewed-by: x\n",
+ .key = "Reviewed-by",
+ .val = "x",
+ },
+ {
+ .raw = "Signed-off-by: x\n",
+ .key = "Signed-off-by",
+ .val = "x",
+ },
+ {
+ 0
+ },
+ },
+ },
+ {
+ "with body text, without divider (second trailer block)",
+ "my subject\n"
+ "\n"
+ "my body which is long\n"
+ "and contains some special\n"
+ "chars like : = ? !\n"
+ "hello\n"
+ "\n"
+ "Fixes: x\n"
+ "Acked-by: x\n"
+ "Reviewed-by: x\n"
+ "Signed-off-by: x\n"
+ "\n"
+ /*
+ * Because this is the last trailer block, it takes
+ * precedence over the first one encountered above.
+ */
+ "Helped-by: x\n"
+ "Signed-off-by: x\n",
+ 2,
+ {
+ {
+ .raw = "Helped-by: x\n",
+ .key = "Helped-by",
+ .val = "x",
+ },
+ {
+ .raw = "Signed-off-by: x\n",
+ .key = "Signed-off-by",
+ .val = "x",
+ },
+ {
+ 0
+ },
+ },
+ },
+ {
+ "with body text, with divider",
+ "my subject\n"
+ "\n"
+ "my body which is long\n"
+ "and contains some special\n"
+ "chars like : = ? !\n"
+ "hello\n"
+ "\n"
+ "---\n"
+ "\n"
+ /*
+ * This trailer still counts because the iterator
+ * always ignores the divider.
+ */
+ "Signed-off-by: x\n",
+ 1,
+ {
+ {
+ .raw = "Signed-off-by: x\n",
+ .key = "Signed-off-by",
+ .val = "x",
+ },
+ {
+ 0
+ },
+ },
+ },
+ {
+ "with non-trailer lines in trailer block",
+ "subject: foo bar\n"
+ "\n"
+ /*
+ * Even though this trailer block has a non-trailer line
+ * in it, it's still a valid trailer block because it's
+ * at least 25% trailers and is Git-generated (see
+ * git_generated_prefixes[] in trailer.c).
+ */
+ "not a trailer line\n"
+ "not a trailer line\n"
+ "not a trailer line\n"
+ "Signed-off-by: x\n",
+ /*
+ * Even though there is only really 1 real "trailer"
+ * (Signed-off-by), we still have 4 trailer objects
+ * because we still want to iterate through the entire
+ * block.
+ */
+ 4,
+ {
+ {
+ .raw = "not a trailer line\n",
+ .key = "not a trailer line",
+ .val = "",
+ },
+ {
+ .raw = "not a trailer line\n",
+ .key = "not a trailer line",
+ .val = "",
+ },
+ {
+ .raw = "not a trailer line\n",
+ .key = "not a trailer line",
+ .val = "",
+ },
+ {
+ .raw = "Signed-off-by: x\n",
+ .key = "Signed-off-by",
+ .val = "x",
+ },
+ {
+ 0
+ },
+ },
+ },
+ {
+ "with non-trailer lines (one too many) in trailer block",
+ "subject: foo bar\n"
+ "\n"
+ /*
+ * This block has only 20% trailers, so it's below the
+ * 25% threshold.
+ */
+ "not a trailer line\n"
+ "not a trailer line\n"
+ "not a trailer line\n"
+ "not a trailer line\n"
+ "Signed-off-by: x\n",
+ 0,
+ {{0}},
+ },
+ {
+ "with non-trailer lines (only 1) in trailer block, but no Git-generated trailers",
+ "subject: foo bar\n"
+ "\n"
+ /*
+ * This block has only 1 non-trailer out of 10 (IOW, 90%
+ * trailers) but is not considered a trailer block
+ * because the 25% threshold only applies to cases where
+ * there was a Git-generated trailer.
+ */
+ "Reviewed-by: x\n"
+ "Reviewed-by: x\n"
+ "Reviewed-by: x\n"
+ "Helped-by: x\n"
+ "Helped-by: x\n"
+ "Helped-by: x\n"
+ "Acked-by: x\n"
+ "Acked-by: x\n"
+ "Acked-by: x\n"
+ "not a trailer line\n",
+ 0,
+ {{0}},
+ },
+ };
+
+ for (int i = 0; i < sizeof(tc) / sizeof(tc[0]); i++) {
+ TEST(t_trailer_iterator(tc[i].msg,
+ tc[i].num_expected,
+ tc[i].contents),
+ "%s", tc[i].name);
+ }
+}
+
+int cmd_main(int argc, const char **argv)
+{
+ run_t_trailer_iterator();
+ return test_done();
+}
diff --git a/trailer.c b/trailer.c
index c72ae68709..2bcb9ba8f7 100644
--- a/trailer.c
+++ b/trailer.c
@@ -11,6 +11,27 @@
* Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
*/
+struct trailer_info {
+ /*
+ * True if there is a blank line before the location pointed to by
+ * trailer_block_start.
+ */
+ int blank_line_before_trailer;
+
+ /*
+ * Offsets to the trailer block start and end positions in the input
+ * string. If no trailer block is found, these are both set to the
+ * "true" end of the input (find_end_of_log_message()).
+ */
+ size_t trailer_block_start, trailer_block_end;
+
+ /*
+ * Array of trailers found.
+ */
+ char **trailers;
+ size_t trailer_nr;
+};
+
struct conf_info {
char *name;
char *key;
@@ -952,20 +973,72 @@ static void unfold_value(struct strbuf *val)
strbuf_release(&out);
}
+static struct trailer_info *trailer_info_new(void)
+{
+ struct trailer_info *info = xcalloc(1, sizeof(*info));
+ return info;
+}
+
+static struct trailer_info *trailer_info_get(const struct process_trailer_options *opts,
+ const char *str)
+{
+ struct trailer_info *info = trailer_info_new();
+ size_t end_of_log_message = 0, trailer_block_start = 0;
+ struct strbuf **trailer_lines, **ptr;
+ char **trailer_strings = NULL;
+ size_t nr = 0, alloc = 0;
+ char **last = NULL;
+
+ trailer_config_init();
+
+ end_of_log_message = find_end_of_log_message(str, opts->no_divider);
+ trailer_block_start = find_trailer_block_start(str, end_of_log_message);
+
+ trailer_lines = strbuf_split_buf(str + trailer_block_start,
+ end_of_log_message - trailer_block_start,
+ '\n',
+ 0);
+ for (ptr = trailer_lines; *ptr; ptr++) {
+ if (last && isspace((*ptr)->buf[0])) {
+ struct strbuf sb = STRBUF_INIT;
+ strbuf_attach(&sb, *last, strlen(*last), strlen(*last));
+ strbuf_addbuf(&sb, *ptr);
+ *last = strbuf_detach(&sb, NULL);
+ continue;
+ }
+ ALLOC_GROW(trailer_strings, nr + 1, alloc);
+ trailer_strings[nr] = strbuf_detach(*ptr, NULL);
+ last = find_separator(trailer_strings[nr], separators) >= 1
+ ? &trailer_strings[nr]
+ : NULL;
+ nr++;
+ }
+ strbuf_list_free(trailer_lines);
+
+ info->blank_line_before_trailer = ends_with_blank_line(str,
+ trailer_block_start);
+ info->trailer_block_start = trailer_block_start;
+ info->trailer_block_end = end_of_log_message;
+ info->trailers = trailer_strings;
+ info->trailer_nr = nr;
+
+ return info;
+}
+
/*
- * Parse trailers in "str", populating the trailer info and "head"
+ * Parse trailers in "str", populating the trailer info and "trailer_objects"
* linked list structure.
*/
-void parse_trailers(const struct process_trailer_options *opts,
- struct trailer_info *info,
- const char *str,
- struct list_head *head)
+struct trailer_info *parse_trailers(const struct process_trailer_options *opts,
+ const char *str,
+ struct list_head *trailer_objects)
{
+ struct trailer_info *info;
struct strbuf tok = STRBUF_INIT;
struct strbuf val = STRBUF_INIT;
size_t i;
- trailer_info_get(opts, str, info);
+ info = trailer_info_get(opts, str);
for (i = 0; i < info->trailer_nr; i++) {
int separator_pos;
@@ -978,17 +1051,19 @@ void parse_trailers(const struct process_trailer_options *opts,
separator_pos);
if (opts->unfold)
unfold_value(&val);
- add_trailer_item(head,
+ add_trailer_item(trailer_objects,
strbuf_detach(&tok, NULL),
strbuf_detach(&val, NULL));
} else if (!opts->only_trailers) {
strbuf_addstr(&val, trailer);
strbuf_strip_suffix(&val, "\n");
- add_trailer_item(head,
+ add_trailer_item(trailer_objects,
NULL,
strbuf_detach(&val, NULL));
}
}
+
+ return info;
}
void free_trailers(struct list_head *trailers)
@@ -1000,48 +1075,19 @@ void free_trailers(struct list_head *trailers)
}
}
-void trailer_info_get(const struct process_trailer_options *opts,
- const char *str,
- struct trailer_info *info)
+size_t trailer_block_start(struct trailer_info *info)
{
- size_t end_of_log_message = 0, trailer_block_start = 0;
- struct strbuf **trailer_lines, **ptr;
- char **trailer_strings = NULL;
- size_t nr = 0, alloc = 0;
- char **last = NULL;
-
- trailer_config_init();
-
- end_of_log_message = find_end_of_log_message(str, opts->no_divider);
- trailer_block_start = find_trailer_block_start(str, end_of_log_message);
+ return info->trailer_block_start;
+}
- trailer_lines = strbuf_split_buf(str + trailer_block_start,
- end_of_log_message - trailer_block_start,
- '\n',
- 0);
- for (ptr = trailer_lines; *ptr; ptr++) {
- if (last && isspace((*ptr)->buf[0])) {
- struct strbuf sb = STRBUF_INIT;
- strbuf_attach(&sb, *last, strlen(*last), strlen(*last));
- strbuf_addbuf(&sb, *ptr);
- *last = strbuf_detach(&sb, NULL);
- continue;
- }
- ALLOC_GROW(trailer_strings, nr + 1, alloc);
- trailer_strings[nr] = strbuf_detach(*ptr, NULL);
- last = find_separator(trailer_strings[nr], separators) >= 1
- ? &trailer_strings[nr]
- : NULL;
- nr++;
- }
- strbuf_list_free(trailer_lines);
+size_t trailer_block_end(struct trailer_info *info)
+{
+ return info->trailer_block_end;
+}
- info->blank_line_before_trailer = ends_with_blank_line(str,
- trailer_block_start);
- info->trailer_block_start = trailer_block_start;
- info->trailer_block_end = end_of_log_message;
- info->trailers = trailer_strings;
- info->trailer_nr = nr;
+int blank_line_before_trailer_block(struct trailer_info *info)
+{
+ return info->blank_line_before_trailer;
}
void trailer_info_release(struct trailer_info *info)
@@ -1050,6 +1096,7 @@ void trailer_info_release(struct trailer_info *info)
for (i = 0; i < info->trailer_nr; i++)
free(info->trailers[i]);
free(info->trailers);
+ free(info);
}
void format_trailers(const struct process_trailer_options *opts,
@@ -1117,21 +1164,19 @@ void format_trailers_from_commit(const struct process_trailer_options *opts,
struct strbuf *out)
{
LIST_HEAD(trailer_objects);
- struct trailer_info info;
-
- parse_trailers(opts, &info, msg, &trailer_objects);
+ struct trailer_info *info = parse_trailers(opts, msg, &trailer_objects);
/* If we want the whole block untouched, we can take the fast path. */
if (!opts->only_trailers && !opts->unfold && !opts->filter &&
!opts->separator && !opts->key_only && !opts->value_only &&
!opts->key_value_separator) {
- strbuf_add(out, msg + info.trailer_block_start,
- info.trailer_block_end - info.trailer_block_start);
+ strbuf_add(out, msg + info->trailer_block_start,
+ info->trailer_block_end - info->trailer_block_start);
} else
format_trailers(opts, &trailer_objects, out);
free_trailers(&trailer_objects);
- trailer_info_release(&info);
+ trailer_info_release(info);
}
void trailer_iterator_init(struct trailer_iterator *iter, const char *msg)
@@ -1140,23 +1185,21 @@ void trailer_iterator_init(struct trailer_iterator *iter, const char *msg)
strbuf_init(&iter->key, 0);
strbuf_init(&iter->val, 0);
opts.no_divider = 1;
- trailer_info_get(&opts, msg, &iter->internal.info);
+ iter->internal.info = trailer_info_get(&opts, msg);
iter->internal.cur = 0;
}
int trailer_iterator_advance(struct trailer_iterator *iter)
{
- while (iter->internal.cur < iter->internal.info.trailer_nr) {
- char *trailer = iter->internal.info.trailers[iter->internal.cur++];
- int separator_pos = find_separator(trailer, separators);
-
- if (separator_pos < 1)
- continue; /* not a real trailer */
+ if (iter->internal.cur < iter->internal.info->trailer_nr) {
+ char *line = iter->internal.info->trailers[iter->internal.cur++];
+ int separator_pos = find_separator(line, separators);
+ iter->raw = line;
strbuf_reset(&iter->key);
strbuf_reset(&iter->val);
parse_trailer(&iter->key, &iter->val, NULL,
- trailer, separator_pos);
+ line, separator_pos);
/* Always unfold values during iteration. */
unfold_value(&iter->val);
return 1;
@@ -1166,7 +1209,19 @@ int trailer_iterator_advance(struct trailer_iterator *iter)
void trailer_iterator_release(struct trailer_iterator *iter)
{
- trailer_info_release(&iter->internal.info);
+ trailer_info_release(iter->internal.info);
strbuf_release(&iter->val);
strbuf_release(&iter->key);
}
+
+int amend_file_with_trailers(const char *path, const struct strvec *trailer_args)
+{
+ struct child_process run_trailer = CHILD_PROCESS_INIT;
+
+ run_trailer.git_cmd = 1;
+ strvec_pushl(&run_trailer.args, "interpret-trailers",
+ "--in-place", "--no-divider",
+ path, NULL);
+ strvec_pushv(&run_trailer.args, trailer_args->v);
+ return run_command(&run_trailer);
+}
diff --git a/trailer.h b/trailer.h
index 9f42aa7599..6eb53df155 100644
--- a/trailer.h
+++ b/trailer.h
@@ -4,6 +4,9 @@
#include "list.h"
#include "strbuf.h"
+struct trailer_info;
+struct strvec;
+
enum trailer_where {
WHERE_DEFAULT,
WHERE_END,
@@ -29,27 +32,6 @@ int trailer_set_where(enum trailer_where *item, const char *value);
int trailer_set_if_exists(enum trailer_if_exists *item, const char *value);
int trailer_set_if_missing(enum trailer_if_missing *item, const char *value);
-struct trailer_info {
- /*
- * True if there is a blank line before the location pointed to by
- * trailer_block_start.
- */
- int blank_line_before_trailer;
-
- /*
- * Offsets to the trailer block start and end positions in the input
- * string. If no trailer block is found, these are both set to the
- * "true" end of the input (find_end_of_log_message()).
- */
- size_t trailer_block_start, trailer_block_end;
-
- /*
- * Array of trailers found.
- */
- char **trailers;
- size_t trailer_nr;
-};
-
/*
* A list that represents newly-added trailers, such as those provided
* with the --trailer command line option of git-interpret-trailers.
@@ -89,15 +71,63 @@ void parse_trailers_from_command_line_args(struct list_head *arg_head,
void process_trailers_lists(struct list_head *head,
struct list_head *arg_head);
-void parse_trailers(const struct process_trailer_options *,
- struct trailer_info *,
- const char *str,
- struct list_head *head);
+/*
+ * Given some input string "str", return a pointer to an opaque trailer_info
+ * structure. Also populate the trailer_objects list with parsed trailer
+ * objects. Internally this calls trailer_info_get() to get the opaque pointer,
+ * but does some extra work to populate the trailer_objects linked list.
+ *
+ * The opaque trailer_info pointer can be used to check the position of the
+ * trailer block as offsets relative to the beginning of "str" in
+ * trailer_block_start() and trailer_block_end().
+ * blank_line_before_trailer_block() returns 1 if there is a blank line just
+ * before the trailer block. All of these functions are useful for preserving
+ * the input before and after the trailer block, if we were to write out the
+ * original input (but with the trailer block itself modified); see
+ * builtin/interpret-trailers.c for an example.
+ *
+ * For iterating through the parsed trailer block (if you don't care about the
+ * position of the trailer block itself in the context of the larger string text
+ * from which it was parsed), please see trailer_iterator_init() which uses the
+ * trailer_info struct internally.
+ *
+ * Lastly, callers should call trailer_info_release() when they are done using
+ * the opaque pointer.
+ *
+ * NOTE: Callers should treat both trailer_info and trailer_objects as
+ * read-only items, because there is some overlap between the two (trailer_info
+ * has "char **trailers" string array, and trailer_objects will have the same
+ * data but as a linked list of trailer_item objects). This API does not perform
+ * any synchronization between the two. In the future we should be able to
+ * reduce the duplication and use just the linked list.
+ */
+struct trailer_info *parse_trailers(const struct process_trailer_options *,
+ const char *str,
+ struct list_head *trailer_objects);
+
+/*
+ * Return the offset of the start of the trailer block. That is, 0 is the start
+ * of the input ("str" in parse_trailers()) and some other positive number
+ * indicates how many bytes we have to skip over before we get to the beginning
+ * of the trailer block.
+ */
+size_t trailer_block_start(struct trailer_info *);
+
+/*
+ * Return the end of the trailer block, again relative to the start of the
+ * input.
+ */
+size_t trailer_block_end(struct trailer_info *);
-void trailer_info_get(const struct process_trailer_options *,
- const char *str,
- struct trailer_info *);
+/*
+ * Return 1 if the trailer block had an extra newline (blank line) just before
+ * it.
+ */
+int blank_line_before_trailer_block(struct trailer_info *);
+/*
+ * Free trailer_info struct.
+ */
void trailer_info_release(struct trailer_info *info);
void trailer_config_init(void);
@@ -125,12 +155,19 @@ void format_trailers_from_commit(const struct process_trailer_options *,
* trailer_iterator_release(&iter);
*/
struct trailer_iterator {
+ /*
+ * Raw line (e.g., "foo: bar baz") before being parsed as a trailer
+ * key/val pair as part of a trailer block (as the "key" and "val"
+ * fields below). If a line fails to parse as a trailer, then the "key"
+ * will be the entire line and "val" will be the empty string.
+ */
+ const char *raw;
struct strbuf key;
struct strbuf val;
/* private */
struct {
- struct trailer_info info;
+ struct trailer_info *info;
size_t cur;
} internal;
};
@@ -158,4 +195,11 @@ int trailer_iterator_advance(struct trailer_iterator *iter);
*/
void trailer_iterator_release(struct trailer_iterator *iter);
+/*
+ * Augment a file to add trailers to it by running git-interpret-trailers.
+ * This calls run_command() and its return value is the same (i.e. 0 for
+ * success, various non-zero for other errors). See run-command.h.
+ */
+int amend_file_with_trailers(const char *path, const struct strvec *trailer_args);
+
#endif /* TRAILER_H */
diff --git a/transport-helper.c b/transport-helper.c
index 8d284b24d5..780fcaf529 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -551,7 +551,7 @@ static int fetch_with_import(struct transport *transport,
else
private = xstrdup(name);
if (private) {
- if (read_ref(private, &posn->old_oid) < 0)
+ if (refs_read_ref(get_main_ref_store(the_repository), private, &posn->old_oid) < 0)
die(_("could not read ref %s"), private);
free(private);
}
@@ -923,8 +923,10 @@ static int push_update_refs_status(struct helper_data *data,
private = apply_refspecs(&data->rs, ref->name);
if (!private)
continue;
- update_ref("update by helper", private, &(ref->new_oid),
- NULL, 0, 0);
+ refs_update_ref(get_main_ref_store(the_repository),
+ "update by helper", private,
+ &(ref->new_oid),
+ NULL, 0, 0);
free(private);
} else {
for (report = ref->report; report; report = report->next) {
@@ -934,11 +936,12 @@ static int push_update_refs_status(struct helper_data *data,
: ref->name);
if (!private)
continue;
- update_ref("update by helper", private,
- report->new_oid
- ? report->new_oid
- : &(ref->new_oid),
- NULL, 0, 0);
+ refs_update_ref(get_main_ref_store(the_repository),
+ "update by helper", private,
+ report->new_oid
+ ? report->new_oid
+ : &(ref->new_oid),
+ NULL, 0, 0);
free(private);
}
}
@@ -1105,9 +1108,11 @@ static int push_refs_with_export(struct transport *transport,
int flag;
/* Follow symbolic refs (mainly for HEAD). */
- name = resolve_ref_unsafe(ref->peer_ref->name,
- RESOLVE_REF_READING,
- &oid, &flag);
+ name = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ ref->peer_ref->name,
+ RESOLVE_REF_READING,
+ &oid,
+ &flag);
if (!name || !(flag & REF_ISSYMREF))
name = ref->peer_ref->name;
@@ -1252,7 +1257,7 @@ static struct ref *get_refs_list_using_list(struct transport *transport,
if (eon) {
if (has_attribute(eon + 1, "unchanged")) {
(*tail)->status |= REF_STATUS_UPTODATE;
- if (read_ref((*tail)->name, &(*tail)->old_oid) < 0)
+ if (refs_read_ref(get_main_ref_store(the_repository), (*tail)->name, &(*tail)->old_oid) < 0)
die(_("could not read ref %s"),
(*tail)->name);
}
diff --git a/transport.c b/transport.c
index df518ead70..0ad04b77fd 100644
--- a/transport.c
+++ b/transport.c
@@ -100,8 +100,9 @@ static void set_upstreams(struct transport *transport, struct ref *refs,
/* Follow symbolic refs (mainly for HEAD). */
localname = ref->peer_ref->name;
remotename = ref->name;
- tmp = resolve_ref_unsafe(localname, RESOLVE_REF_READING,
- NULL, &flag);
+ tmp = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ localname, RESOLVE_REF_READING,
+ NULL, &flag);
if (tmp && flag & REF_ISSYMREF &&
starts_with(tmp, "refs/heads/"))
localname = tmp;
@@ -543,10 +544,12 @@ static void update_one_tracking_ref(struct remote *remote, char *refname,
if (verbose)
fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
if (deletion)
- delete_ref(NULL, rs.dst, NULL, 0);
+ refs_delete_ref(get_main_ref_store(the_repository),
+ NULL, rs.dst, NULL, 0);
else
- update_ref("update by push", rs.dst, new_oid,
- NULL, 0, 0);
+ refs_update_ref(get_main_ref_store(the_repository),
+ "update by push", rs.dst, new_oid,
+ NULL, 0, 0);
free(rs.dst);
}
}
@@ -814,7 +817,8 @@ void transport_print_push_status(const char *dest, struct ref *refs,
if (transport_color_config() < 0)
warning(_("could not parse transport.color.* config"));
- head = resolve_refdup("HEAD", RESOLVE_REF_READING, NULL, NULL);
+ head = refs_resolve_refdup(get_main_ref_store(the_repository), "HEAD",
+ RESOLVE_REF_READING, NULL, NULL);
if (verbose) {
for (ref = refs; ref; ref = ref->next)
diff --git a/upload-pack.c b/upload-pack.c
index 902144b9d3..8fbd138515 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -618,7 +618,8 @@ static void for_each_namespaced_ref_1(each_ref_fn fn,
if (allow_hidden_refs(data->allow_uor))
excludes = hidden_refs_to_excludes(&data->hidden_refs);
- for_each_namespaced_ref(excludes, fn, data);
+ refs_for_each_namespaced_ref(get_main_ref_store(the_repository),
+ excludes, fn, data);
}
@@ -873,7 +874,8 @@ static void deepen(struct upload_pack_data *data, int depth)
* Checking for reachable shallows requires that our refs be
* marked with OUR_REF.
*/
- head_ref_namespaced(check_ref, data);
+ refs_head_ref_namespaced(get_main_ref_store(the_repository),
+ check_ref, data);
for_each_namespaced_ref_1(check_ref, data);
get_reachable_list(data, &reachable_shallows);
@@ -1288,7 +1290,8 @@ static int find_symref(const char *refname,
if ((flag & REF_ISSYMREF) == 0)
return 0;
- symref_target = resolve_ref_unsafe(refname, 0, NULL, &flag);
+ symref_target = refs_resolve_ref_unsafe(get_main_ref_store(the_repository),
+ refname, 0, NULL, &flag);
if (!symref_target || (flag & REF_ISSYMREF) == 0)
die("'%s' is a symref but it is not?", refname);
item = string_list_append(cb_data, strip_namespace(refname));
@@ -1413,13 +1416,15 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,
if (data.timeout)
data.daemon_mode = 1;
- head_ref_namespaced(find_symref, &data.symref);
+ refs_head_ref_namespaced(get_main_ref_store(the_repository),
+ find_symref, &data.symref);
if (advertise_refs || !data.stateless_rpc) {
reset_timeout(data.timeout);
if (advertise_refs)
data.no_done = 1;
- head_ref_namespaced(send_ref, &data);
+ refs_head_ref_namespaced(get_main_ref_store(the_repository),
+ send_ref, &data);
for_each_namespaced_ref_1(send_ref, &data);
if (!data.sent_capabilities) {
const char *refname = "capabilities^{}";
@@ -1433,7 +1438,8 @@ void upload_pack(const int advertise_refs, const int stateless_rpc,
advertise_shallow_grafts(1);
packet_flush(1);
} else {
- head_ref_namespaced(check_ref, &data);
+ refs_head_ref_namespaced(get_main_ref_store(the_repository),
+ check_ref, &data);
for_each_namespaced_ref_1(check_ref, &data);
}
@@ -1511,7 +1517,7 @@ static int parse_want_ref(struct packet_writer *writer, const char *line,
strbuf_addf(&refname, "%s%s", get_git_namespace(), refname_nons);
if (ref_is_hidden(refname_nons, refname.buf, hidden_refs) ||
- read_ref(refname.buf, &oid)) {
+ refs_read_ref(get_main_ref_store(the_repository), refname.buf, &oid)) {
packet_writer_error(writer, "unknown ref %s", refname_nons);
die("unknown ref %s", refname_nons);
}
diff --git a/walker.c b/walker.c
index c0fd632d92..946d86b04e 100644
--- a/walker.c
+++ b/walker.c
@@ -286,7 +286,8 @@ int walker_fetch(struct walker *walker, int targets, char **target,
ALLOC_ARRAY(oids, targets);
if (write_ref) {
- transaction = ref_transaction_begin(&err);
+ transaction = ref_store_transaction_begin(get_main_ref_store(the_repository),
+ &err);
if (!transaction) {
error("%s", err.buf);
goto done;
@@ -294,7 +295,8 @@ int walker_fetch(struct walker *walker, int targets, char **target,
}
if (!walker->get_recover) {
- for_each_ref(mark_complete, NULL);
+ refs_for_each_ref(get_main_ref_store(the_repository),
+ mark_complete, NULL);
commit_list_sort_by_date(&complete);
}
@@ -324,7 +326,7 @@ int walker_fetch(struct walker *walker, int targets, char **target,
strbuf_reset(&refname);
strbuf_addf(&refname, "refs/%s", write_ref[i]);
if (ref_transaction_update(transaction, refname.buf,
- oids + i, NULL, 0,
+ oids + i, NULL, NULL, NULL, 0,
msg ? msg : "fetch (unknown)",
&err)) {
error("%s", err.buf);
diff --git a/wrapper.c b/wrapper.c
index eeac3741cf..f87d90bf57 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -670,7 +670,7 @@ int xsnprintf(char *dst, size_t max, const char *fmt, ...)
va_end(ap);
if (len < 0)
- BUG("your snprintf is broken");
+ die(_("unable to format message: %s"), fmt);
if (len >= max)
BUG("attempt to snprintf into too-small buffer");
return len;
diff --git a/wt-status.c b/wt-status.c
index bdfc23e2ae..ff4be071ca 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -145,7 +145,8 @@ void wt_status_prepare(struct repository *r, struct wt_status *s)
s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
s->use_color = -1;
s->relative_paths = 1;
- s->branch = resolve_refdup("HEAD", 0, NULL, NULL);
+ s->branch = refs_resolve_refdup(get_main_ref_store(the_repository),
+ "HEAD", 0, NULL, NULL);
s->reference = "HEAD";
s->fp = stdout;
s->index_file = get_index_file();
@@ -976,7 +977,8 @@ static int stash_count_refs(struct object_id *ooid UNUSED,
static int count_stash_entries(void)
{
int n = 0;
- for_each_reflog_ent("refs/stash", stash_count_refs, &n);
+ refs_for_each_reflog_ent(get_main_ref_store(the_repository),
+ "refs/stash", stash_count_refs, &n);
return n;
}
@@ -1304,10 +1306,10 @@ static int split_commit_in_progress(struct wt_status *s)
!s->branch || strcmp(s->branch, "HEAD"))
return 0;
- if (read_ref_full("HEAD", RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
- &head_oid, &head_flags) ||
- read_ref_full("ORIG_HEAD", RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
- &orig_head_oid, &orig_head_flags))
+ if (refs_read_ref_full(get_main_ref_store(the_repository), "HEAD", RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+ &head_oid, &head_flags) ||
+ refs_read_ref_full(get_main_ref_store(the_repository), "ORIG_HEAD", RESOLVE_REF_READING | RESOLVE_REF_NO_RECURSE,
+ &orig_head_oid, &orig_head_flags))
return 0;
if (head_flags & REF_ISSYMREF || orig_head_flags & REF_ISSYMREF)
return 0;
@@ -1679,7 +1681,7 @@ static void wt_status_get_detached_from(struct repository *r,
char *ref = NULL;
strbuf_init(&cb.buf, 0);
- if (for_each_reflog_ent_reverse("HEAD", grab_1st_switch, &cb) <= 0) {
+ if (refs_for_each_reflog_ent_reverse(get_main_ref_store(the_repository), "HEAD", grab_1st_switch, &cb) <= 0) {
strbuf_release(&cb.buf);
return;
}
@@ -2087,7 +2089,8 @@ static void wt_shortstatus_print_tracking(struct wt_status *s)
upstream_is_gone = 1;
}
- short_base = shorten_unambiguous_ref(base, 0);
+ short_base = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+ base, 0);
color_fprintf(s->fp, header_color, "...");
color_fprintf(s->fp, branch_color_remote, "%s", short_base);
free(short_base);
@@ -2220,7 +2223,8 @@ static void wt_porcelain_v2_print_tracking(struct wt_status *s)
ab_info = stat_tracking_info(branch, &nr_ahead, &nr_behind,
&base, 0, s->ahead_behind_flags);
if (base) {
- base = shorten_unambiguous_ref(base, 0);
+ base = refs_shorten_unambiguous_ref(get_main_ref_store(the_repository),
+ base, 0);
fprintf(s->fp, "# branch.upstream %s%c", base, eol);
free((char *)base);